# [InsuRo 개인정보 P0-1] Drive 프록시 Phase 1.5 — 백엔드 보완 (Codex 조율 반영)

## allowed_resources

```yaml
allowed_resources:
  paths:
    - "server/**"
    - "server/tests/**"
  forbidden_paths:
    - ".env"
    - ".env.*"
    - ".github/**"
  commands:
    - "pytest"
    - "python3 -m py_compile"
    - "python3 -c"
    - "curl"
  merge_policy: "tiered"
  ttl_hours: 48
```

## 배경
Phase 1(백엔드 코어)은 main에 머지·배포 완료(file-ticket/프록시 엔드포인트, drive_file_id 컬럼+과거백필, ES256 전용). **Codex 교차검증에서 프론트 배선(Phase 2) 전 반드시 고쳐야 할 백엔드 갭 3+1건**이 나옴. 본 Phase 1.5는 그 보완. 필독:
- `/home/jay/projects/InsuRo/docs/plans/drive-proxy/plan.md` (설계)
- Phase 1 구현: `server/main.py`(file-ticket ~5856, 프록시 file/{ticket}), `server/file_ticket_store.py`, `server/gdrive.py::extract_drive_file_id`

## 수정 범위 (4건)

### 1. ★신규 쓰기 경로에 `drive_file_id` 채우기 (필수 — 안 하면 새 파일 열람 불가)
- 마이그레이션은 **과거 데이터 백필만** 했음. **신규 업로드/분석이 `drive_file_id`(s)를 저장하지 않으면 새 레코드는 ticket 발급 IDOR 조회에서 누락**됨.
- Drive 업로드 후 `file_url`을 저장하는 **모든 신규 쓰기 경로**에서 `extract_drive_file_id()`로 id 추출해 컬럼도 함께 저장:
  - `newsletters`/`premium_data` 업로드(`upload-to-drive` ~`main.py:6070` 부근) → `drive_file_id`
  - `policy_analyses` 증권분석(`analyze-policy`, `main.py:6839,6848` 부근, result 배열) → `drive_file_ids text[]`
  - 기타 Drive 업로드→file_url 저장 경로 전수 점검(누락 없이)
- 검증: 신규 업로드/분석 후 해당 레코드 `drive_file_id(s)` 채워짐 확인.

### 2. ★미리보기 대응 — `view`(inline) 모드 + 짧은TTL 다회 토큰 (필수)
- 현재 `GET /file/{ticket}`는 **진입 즉시 1회 소비(pop) + 항상 `attachment`**. → `<img>`·PDF뷰어·Range 재요청이 2번째부터 **404**, "보기"가 다운로드로 귀결.
- 수정: file-ticket에 **`mode` 파라미터** 도입.
  - `mode="download"`(기본, 기존): **1회용** ticket + `Content-Disposition: attachment`.
  - `mode="view"`: **짧은 TTL(예: 120초) 다회 사용** 토큰(1회소비 안 함, TTL 만료로만 무효) + `Content-Disposition: inline` + **HTTP Range 지원**(PDF뷰어/이미지 재요청·부분요청 정상). 유출면은 짧은 TTL로 완화.
- 보안: view 토큰도 등급별 IDOR 인가는 발급 시 동일 적용. `nosniff`·`Referrer-Policy: no-referrer` 유지.
- 검증: 같은 view URL **2회+ 요청 모두 200**(1회소비 아님), Range 요청 206, attachment(download)는 1회용 유지.

### 3. `main.py:377` 다중계정 미들웨어 ES256 통일 (소소)
- `algorithms=["ES256","HS256"]` → `["ES256"]` (verify_jwt와 일관, 알고리즘 컨퓨전 방어). 이건 탐지용 미들웨어라 크리티컬 아니나 일관성.

### 4. ticket store 외부화 — 이번엔 **범위 밖(주석/TODO만)**
- 현재 인메모리(`file_ticket_store.py`)는 **단일 uvicorn 워커 전제**. 지금 배포가 단일 워커라 실위험 없음 → 이번엔 고치지 말고, **멀티워커 전환 시 외부화 필요**를 코드 주석/TODO로 명시만.

## 검증 기준
1. 유닛/통합: 신규경로 drive_file_id 배선 / view 모드 다회요청 200 / Range 206 / download 1회용 유지 / ES256 미들웨어.
2. 회귀 0 (기존 Phase 1 테스트 84 포함 통과).
3. 로컬 스모크: 신규 업로드→drive_file_id 채워짐, view 티켓 2회 GET 200.

## 배포
- **마이그레이션 없음**(컬럼 이미 존재) — 코드만. 머지=ANU, systemd insuro-api 재배포=ANU 조율. finalize-only.
- 프로덕션. finish-task 후 원격 head 확인.

## 완료 보고 8항목
수정 파일/함수 diff · 신규 drive_file_id 배선 지점 목록 · view 모드/다회토큰/Range 구현 · 미들웨어 ES256 · ticket store TODO · 회귀/스모크 결과 · PR/머지 상태 · callback.
