# [Lv.2 URGENT regression] 소식지 업로드 타임아웃 수정 — 검증 파이프라인(codex) 백그라운드화 + 소비 게이트 필터

## allowed_resources
```yaml
allowed_resources:
  paths:
    - "server/main.py"
    - "server/tests/**"
  forbidden_paths:
    - ".github/**"
    - "extension/**"
    - "src/**"
    - "server/migrations/**"
    - "server/newsletter_review.py"
    - "server/newsletter_cross_verify.py"
    - "server/newsletter_validation.py"
  commands: ["pytest","python3","git"]
  merge_policy: "none"
  ttl_hours: 12
```
> ★ base=현 origin/main(0e601ad). **라이브 회귀 — 업로드가 "Failed to fetch"로 실패**. 우선순위 높음.

## 배경 (ANU 실증 — 회귀 원인 확정)
소식지 업로드(`@app.post("/api/insuro/upload-to-drive")` 5856, 그리고 다른 run_review_pipeline 호출 지점 ~5825)가 **vision추출(Opus) + `_render_source_page_images` + `run_review_pipeline`(내부 codex 교차검증)을 전부 동기 `await`**한다. 이전엔 codex 가 이미지 부재로 즉시 스킵돼 빨랐으나, 최근 렌더 수정(#187)으로 **codex 가 실제 실행 → 총 2분+ 소요 → cloudflared 터널 origin 타임아웃(~100s) → 프론트 "Failed to fetch"**. (로그 실증: 13:10:25~13:12:47 처리 중 프론트 중단.)

## 작업
### 1) [URGENT] 검증 파이프라인 백그라운드화 (업로드 즉시 응답)
- **vision 추출은 동기 유지**(응답에 title/company 필요, 기존에 타임아웃 안 났음). **느린 부분(`_render_source_page_images` + `run_review_pipeline` = 렌더+검증+AI자기검증+codex)만 백그라운드로**.
- FastAPI **`BackgroundTasks`** 사용: 두 호출 지점(upload-to-drive 경로 ~5949/5996, 직접 경로 ~5824/5825) 모두 — 
  1. 추출 결과로 **newsletters 레코드를 먼저 저장/업서트**(extracted_text + review_status 명시: 'uploaded' 유지, fail-OPEN 방지).
  2. `background_tasks.add_task(<async 래퍼>, ...)` 로 render+run_review_pipeline 예약(응답 후 실행). **응답은 추출 완료 즉시 반환**(job/record id + 추출값).
  - run_review_pipeline 은 async 이므로 add_task 에 async 함수로 넘기거나 얇은 async 래퍼로 감싼다. 예외는 백그라운드에서 삼켜 로깅(응답엔 영향 0).
- ★ 결과: 업로드 HTTP 응답은 추출 시간 내(수십초)로 끝나 타임아웃 회피. 소식지는 검토 대기 큐에 **잠시 뒤**(백그라운드 완료 후) 플래그와 함께 나타남. 상태기계·published fail-closed·flag-only·codex 로직 자체는 불변(호출 위치만 이동).
- 프론트 계약 최소 변경: 응답 스키마(추출 title/company)는 유지. (검토 플래그는 원래도 즉시 아니었음.)

### 2) 소비 게이트 필터 (승인된 것만 분석에 사용)
- `@app.post("/api/insuro/newsletter-chat")`(6142)의 newsletters 조회에 **`.eq("review_status", "published")`** 추가 — 사람 승인된 소식지만 AI분석에 사용. 기존 건은 backfill='published'라 유지, 신규는 승인 전 제외.
- ★ 관리 목록(`select *`)·검토 대기 큐 조회는 **불변**(전체/대기건 봐야 함). 이 필터는 소비(분석) 경로만.

## 제약
- server/main.py + 테스트만. review/cross_verify/validation 모듈·migration·src 불변. 기존 업로드 응답 스키마 유지. 회귀 0.

## 검증
- `pytest server/tests/` 회귀 0. 신규: 업로드 핸들러가 run_review_pipeline 을 **background_tasks.add_task 로 예약**(동기 await 아님) — mock 으로 확인 / 레코드가 응답 전 저장됨 / newsletter-chat 조회에 review_status='published' eq 포함 / 미승인 제외.
- ★ **L1 필수**: 실제 서버 재시작 후 소식지 PDF 업로드가 **타임아웃 없이 빠르게 응답**하고, 잠시 뒤 검토 대기에 codex 플래그와 함께 뜨는지 확인(가능하면). 보고서에 응답 소요시간 기록.

## 완료 (★ 순서 B)
- server/main.py + 테스트만. **dev6 금지** — dev1(헤르메스). 커밋 → push → **★ push 확인** → finish-task foreground 1회 → .done. ANU 독립검증·머지·재배포는 ANU.

## goal_assertions (auto-generated)
- `pytest server/tests/`
