# task-1073.1: InsuWiki Firestore 보안 규칙 배포 (임시저장 실패 수정)

**팀**: dev4-team (비슈누)
**일시**: 2026-03-26

---

## SCQA

**S**: InsuWiki 에디터에서 `autoSaveDrafts` 컬렉션에 대한 Firestore 보안 규칙이 `firestore.rules` L297-307에 작성되어 있으나, Firebase에 실제 배포되지 않은 상태이다.

**C**: 사용자가 에디터에서 임시저장 시 `FirebaseError: Missing or insufficient permissions` 에러가 발생하여 임시저장 기능이 완전히 작동하지 않는다. 추가로 브라우저 콘솔에 Service Worker 관련 TypeError가 2건 발생 중이다.

**Q**: Firestore 규칙 배포로 임시저장 실패를 해결하고, Service Worker 에러의 원인을 분석하여 수정할 수 있는가?

**A**: Firestore 규칙을 `firebase deploy --only firestore:rules --project insuwiki-j2h`로 성공 배포하여 임시저장 권한 문제를 해결했다. Service Worker의 fetch 핸들러에서 캐시 미스 시 `undefined`가 `respondWith()`에 전달되는 버그를 발견하여 수정 커밋했다.

---

## 작업 내용

### 1. Firestore 보안 규칙 배포

**배포 전 상태**: `firestore.rules`에 `autoSaveDrafts` 규칙 존재 (L297-307), Firebase에 미배포

**배포 명령**:
```
firebase deploy --only firestore:rules --project insuwiki-j2h --token $(gcloud auth print-access-token)
```

**배포 결과**:
```
✔ cloud.firestore: rules file firestore.rules compiled successfully
✔ firestore: released rules firestore.rules to cloud.firestore
✔ Deploy complete!
```

**배포된 `autoSaveDrafts` 규칙 요약**:
- `read`: 인증 + member/admin + (resource null 또는 본인 소유)
- `create`: 인증 + member/admin + 본인 userId
- `update/delete`: 인증 + member/admin + 본인 소유
- guest 역할은 `isMemberOrAdmin()` 조건에 의해 차단됨

### 2. Service Worker 에러 분석 및 수정

**에러 2건**:
1. `FetchEvent for "https://insuwiki.vercel.app/docs/..." resulted in a network error response`
2. `TypeError: Failed to convert value to 'Response'` (sw.js:1)

**원인 분석**:
- `nextapp/public/sw.js` L34-36의 fetch 핸들러
- `fetch(event.request).catch(() => caches.match(event.request))` 구조
- 네트워크 실패 시 `caches.match()`가 캐시에 없는 URL에 대해 `undefined` 반환
- `event.respondWith(undefined)` → TypeError 발생

**수정 내용** (커밋 `f2d682c`):
- 캐시 미스 시 `Promise.reject()`로 네트워크 에러를 자연스럽게 전파
- `chrome-extension://` 등 non-http 스킴 요청 필터링 추가

---

## 생성/수정 파일

- `nextapp/public/sw.js` — fetch 핸들러 수정 (캐시 미스 처리 + non-http 필터링)
- Firestore 규칙은 기존 `firestore.rules` 파일을 그대로 배포 (파일 변경 없음)

## 발견 이슈 및 해결

### 자체 해결 (3건)
1. **Firestore 규칙 미배포** — `firebase deploy --only firestore:rules` 실행으로 배포 완료
2. **SW 캐시 미스 TypeError** — `caches.match()` 결과 undefined 처리 추가 (`cached || Promise.reject()`)
3. **SW non-http 스킴 에러** — `url.protocol.startsWith('http')` 필터링 추가

### 범위 외 미해결 (1건)
1. **guest 역할 사용자의 임시저장 차단** — `isMemberOrAdmin()` 조건에 의해 guest는 임시저장 불가. 이는 의도된 보안 설계이므로, 변경 필요 시 제품 결정 필요. (범위 외: 비즈니스 요구사항 결정 사안)

## 추가 확인 사항

- SW 수정은 `nextapp/public/sw.js`에 커밋됨. Vercel 배포 시 반영됨 (기존 SW는 사용자 브라우저에 캐시되어 있으므로 `CACHE_NAME` 변경 없이도 `skipWaiting()` + `clients.claim()`으로 자동 업데이트됨)
- Firebase Console에서 규칙 반영 확인 가능: https://console.firebase.google.com/project/insuwiki-j2h/firestore/rules

## QC 검증

```json
{
  "task_id": "task-1073.1",
  "verified_at": "2026-03-26T15:31:16",
  "overall": "PASS",
  "summary": "5 PASS, 7 SKIP",
  "checks": {
    "file_check": "PASS (sw.js 1420 bytes, report 3916 bytes)",
    "data_integrity": "PASS",
    "critical_gap": "PASS",
    "spec_compliance": "PASS",
    "duplicate_check": "PASS (최대 유사도 7.6%)",
    "api_health": "SKIP (서버 작업 아님)",
    "test_runner": "SKIP (관련 테스트 파일 0개)",
    "tdd_check": "SKIP (Lv.1 운영 작업)",
    "pyright_check": "SKIP (Python 파일 없음)",
    "style_check": "SKIP (Python 파일 없음)",
    "schema_contract": "SKIP (workers 없음)",
    "scope_check": "SKIP"
  }
}
```
