# task-71.1 작업 보고서

**작업명**: InsuWiki 긴급 보안 패치 Phase 1 (2/2)
**작업일**: 2026-03-02
**팀**: dev2-team (오딘 팀장, 토르/헤임달/마아트)
**상태**: 완료

---

## 작업 내용

### 패치 1: [CRITICAL-5] 공개 문서 무제한 수정 권한 제한

**파일**: `/home/jay/projects/insuwiki/firestore.rules`
**위치**: 63-68줄 (documents 컬렉션 update 규칙)

**변경 전**:
```
// Update: Allow if author OR public (Team Shared editing) OR own Daily Note
allow update: if isAuthenticated() && (
    isAuthor() ||
    isPublic() ||
    docId.matches('daily-.*-' + request.auth.uid)
);
```

**변경 후**:
```
// Update: Allow if author OR admin OR own Daily Note
allow update: if isAuthenticated() && (
    isAuthor() ||
    isAdmin() ||
    docId.matches('daily-.*-' + request.auth.uid)
);
```

**보안 영향**: `isPublic()` 조건 제거로 인해 인증된 모든 사용자가 공개 문서를 임의로 수정하는 취약점 해소. 수정 권한은 작성자(owner) 또는 admin으로 제한됨. 읽기 권한은 기존 유지.

---

### 패치 2: [CRITICAL-4] pdfIndexing Batch 재사용 버그 수정

**파일**: `/home/jay/projects/insuwiki/functions/src/pdfIndexing.ts`
**위치**: 190-231줄 (청크 임베딩 배치 처리 로직)

**핵심 변경사항**:
- `const chunkBatch` → `let chunkBatch` (재할당 가능하도록)
- `let batchCount = 0` 추가 (배치 내 누적 수 추적)
- commit() 후 `chunkBatch = db.batch()` + `batchCount = 0` (새 배치 생성 및 초기화)
- 마지막 commit은 `if (batchCount > 0)` 조건부 실행 (빈 배치 commit 방지)

**버그 원인**: Firestore WriteBatch는 commit() 후 재사용 불가. 기존 코드는 commit() 후 동일 객체에 계속 set()을 호출 → 400개 초과 시 오류 발생.

---

## 생성/수정 파일 목록

| 파일 | 작업 | 내용 |
|------|------|------|
| `/home/jay/projects/insuwiki/firestore.rules` | 수정 | update 규칙 isPublic() → isAdmin() 교체 |
| `/home/jay/projects/insuwiki/functions/src/pdfIndexing.ts` | 수정 | WriteBatch 재사용 버그 수정 |

---

## 테스트 결과

### 헤임달(테스터) 검증

| 항목 | 결과 |
|------|------|
| firestore.rules update 규칙 - isPublic() 제거 확인 | PASS |
| firestore.rules update 규칙 - isAdmin()/isAuthor() 존재 확인 | PASS |
| firestore.rules read 규칙 - isPublic() 유지 확인 | PASS |
| pdfIndexing.ts - let chunkBatch 선언 | PASS |
| pdfIndexing.ts - batchCount 변수 추가 | PASS |
| pdfIndexing.ts - commit 후 새 배치 생성 | PASS |
| pdfIndexing.ts - 조건부 마지막 commit | PASS |
| TypeScript 빌드 (pdfIndexing.ts 오류) | PASS (0건) |

### 마아트(QC 매니저) 독립 재검증

| 검증 항목 | 결과 |
|-----------|------|
| firestore.rules update 규칙 (isPublic 제거, isAdmin/isAuthor 존재, 주석) | PASS |
| firestore.rules read 규칙 (isPublic 유지) | PASS |
| 타 컬렉션 불변 (users, dailyNotes, links, tags, jobs, gemini_file_cache, insurance_metadata) | PASS |
| WriteBatch 버그 수정 (A~E 전 항목) | PASS |
| TypeScript 빌드 (패치 범위 오류 없음) | PASS |
| 배치 처리 논리 - 100개 시나리오 | PASS |
| 배치 처리 논리 - 400개 시나리오 | PASS |
| 배치 처리 논리 - 450개 시나리오 | PASS |

**마아트 최종 판정: APPROVED**

---

## 셀프 QC (System 2 Forcing)

1. **다른 파일에 영향**: firestore.rules 수정은 공개 문서를 작성자가 아닌 사용자가 수정하는 기능에 영향. 의도된 보안 강화. pdfIndexing.ts는 독립적 함수로 타 파일 영향 없음.

2. **엣지 케이스**: 청크 수가 정확히 400의 배수일 때 batchCount=0으로 루프 후 commit 건너뜀(빈 배치 방지 정상 동작). 레거시 문서(visibility 필드 없음)의 타인 수정은 의도적으로 거부됨.

3. **작업 지시 일치**: isPublic()→isAdmin() 교체로 작성자/admin만 수정 가능 ✓. commit() 후 새 WriteBatch 생성 ✓.

4. **에러 처리/보안**: isAdmin()은 기존 delete 규칙에서도 사용 중(일관성). pdfIndexing.ts는 기존 try/catch로 커버됨.

5. **테스트 커버리지**: 헤임달·마아트 이중 검증 완료. TypeScript 컴파일 오류 0건.

---

## 비고

- `seed-drive-dummy-files.ts`에서 `dotenv` 모듈 타입 선언 누락 오류 발생하나, 이번 패치 대상 외 기존 이슈임. 별도 추적 필요 (`npm install --save-dev @types/dotenv` 또는 tsconfig exclude 처리).
- 배포(firebase deploy --only firestore:rules)는 별도 진행 예정.
- functions 빌드는 패치 범위 내 오류 없음 확인됨.
