# task-3010 — 증권 이미지 파일 업로드 지원 (고객이 사진으로 보내는 경우)

**레벨**: Lv.2 · **팀**: dev5-team (마르둑) · **회장 승인 완료** (2026-08-25)

## 배경 — 회장 실사용 요구

> **"고객 증권 요청을 하면 가끔 사진 찍어서 주시는 분들이 계셔서 이미지 파일도 읽어서 분석할 수 있어야 함"**

현재는 **PDF 만 받는다.** 고객이 증권을 촬영해 보내면 설계사가 업로드할 방법이 없다.

## ★ ANU 실측 — 엔진은 이미 이미지를 읽는다. 입구만 막혀 있다

```
server/policy_extract/vision.py
  "이미지를 임시 디렉터리에 스테이징하고 cwd=그 디렉터리로 실행한다"
  → vision 어댑터는 원래 이미지 파일을 입력으로 받는다.

현재 흐름:
  PDF 업로드 → suffix=".pdf" 강제 → 텍스트레이어 검사 → 없으면 PDF를 이미지로 렌더 → vision

막혀 있는 곳:
  src/pages/PolicyAnalysis.tsx:28   file.type === "application/pdf" || 파일명.endsWith(".pdf")
  src/pages/PolicyAnalysis.tsx:225  toast.error("PDF 파일만 업로드 가능합니다")
  src/pages/PolicyAnalysis.tsx:536,573  accept=".pdf"
  server/main.py (analyze_policy)   "분석할 PDF 파일이 없습니다" · suffix = ".pdf" 하드코딩
```

**즉 새 엔진을 만드는 것이 아니라, 이미지를 받아 기존 vision 경로로 태우는 배선이다.**
PDF→이미지 렌더 단계를 **건너뛰면** 된다.

★ 위는 ANU 가 grep 으로 확인한 사실이나 **네가 다시 확인하라.** 다르면 ANU 에 보고하라.

---

## 고칠 것

### ① 프론트 — 이미지 파일 허용
- `accept` 에 이미지 형식 추가, 검증 함수도 함께 수정 (두 곳 모두 — 놓치면 한쪽만 열린다)
- 최소 지원: **JPEG · PNG**
- ★ **HEIC/HEIF 주의**: 아이폰 기본 촬영 형식이다. 브라우저·서버가 그대로 처리 못 할 수 있다.
  **먼저 실측**하고, 불가하면 **사용자에게 명확히 알려라**(조용히 실패시키지 마라).
  변환이 필요하면 어떤 방법이 있는지 **조사해 보고**하고 임의 구현하지 마라
- 오류 문구를 형식에 맞게 고쳐라 ("PDF 파일만..." → 실제 허용 목록)

### ② 백엔드 — 이미지 입력을 vision 경로로
- `suffix` 하드코딩(`.pdf`)을 **업로드된 파일의 실제 형식**에 맞춘다
- 이미지면 **PDF→이미지 렌더 단계를 건너뛰고** 바로 vision 으로 보낸다
- ★ **형식 판정은 확장자만 믿지 마라.** 매직바이트로 확인하라
  (기존 사례: task-2908 이 `_render_source_page_images` 에서 확장자 의존을 제거하고 매직바이트 감지로 바꿨다)

### ③ 여러 장 대응
증권이 여러 페이지면 고객이 **사진 여러 장**을 보낸다.
- 현재 업로드 UI 가 다중 선택을 지원하는지 확인하고, 여러 이미지가 **한 증권으로** 묶여 분석되는지 확인하라
- 안 되면 그 사실을 보고하라. **이 태스크에서 UX 를 새로 설계하지는 마라**

### ④ 실패를 조용히 넘기지 마라 ★
- 지원하지 않는 형식·손상 파일·과대 용량은 **사용자에게 이유를 알린다**
- 분석이 실패했는데 성공처럼 보이는 응답을 만들지 마라
  (2026-08-25 복합설계 사고가 정확히 그 유형이었다 — `ok:true` 인데 실제로는 전송 안 됨)

---

## 검증 (실측 강제)
1. **현재 거부 재현** — 이미지 파일 업로드가 지금 막히는 것을 확인해 기록하라
2. **JPEG/PNG 실제 분석 성공** — 증권을 촬영한 형태의 이미지로 **실호출**해
   담보가 추출되는지 확인하라. 결과를 표로 제시하라
   ★ 검증 샘플: `/home/jay/workspace/memory/fixtures/silson/jonghap-sample-260824.pdf`
     (회장 제공 KB 증권 5p 스캔). 이걸 **이미지로 변환**해 업로드 경로로 넣으면 실제 시나리오가 된다
     ☠ **실명·주민번호 앞자리·주소 포함. git 커밋 금지. 보고서·로그에 PII 기록 금지.**
3. **PDF 경로 무회귀** — 기존 PDF 업로드가 그대로 동작하는지 확인 (텍스트레이어 PDF · 스캔 PDF 둘 다)
4. **HEIC 실측** — 되는지 안 되는지 확인하고, 안 되면 사용자에게 알려지는지 확인
5. **매직바이트 판정** — 확장자를 속인 파일(`.jpg` 인데 내용은 다른 것)이 올바로 처리/거부되는지
6. **봉인** — 이미지 형식이 다시 막히면 FAIL 하는 테스트. **변이로 실증**하라
7. `pytest` · `npx vitest run` 회귀 유지 (**base 재측정 기준선**. 명세 수치 아님)

## 범위 · 금지
**수정 허용**: `src/pages/PolicyAnalysis.tsx` · `server/main.py`(analyze_policy 입력 처리부) ·
`server/policy_extract/**`(형식 분기 필요 시) · 관련 테스트

**금지**:
- **LLM 프롬프트 변경**(`build_policy_prompt` · `DEFAULT_COVERAGES`) — 파급이 크다. 보고만 하라
- **타임아웃 상수 변경** — task-3007 결과물(`POLICY_ANALYSIS_TIMEOUT_SEC = 420`). 건드리지 마라
- `server/silson/**` · `src/pages/NewDesignComparison.tsx`
- `server/scripts/**` · `ops/**` (task-3008 결과물)
- 샘플 PDF/이미지를 git 에 추가하거나 PII 기록
- 조용한 실패 경로 신설

## allowed_resources

```yaml
allowed_resources:
  paths:
    - "src/pages/PolicyAnalysis.tsx"
    - "src/pages/__tests__/**"
    - "server/main.py"
    - "server/policy_extract/**"
    - "server/tests/**"
    - "tests/**"
    - "memory/reports/task-3010.md"
  forbidden_paths:
    - "server/policy_analyzer.py"
    - "server/silson/**"
    - "server/scripts/**"
    - "ops/**"
    - "src/pages/NewDesignComparison.tsx"
    - "extension/**"
    - ".github/**"
  commands:
    - "pytest"
    - "npx vitest run"
    - "npm run build"
    - "python3"
  merge_policy: "tiered"
  ttl_hours: 48
```

## 운영 계약
- `origin/main`(=`997fa5d`) 기준 `git pull --ff-only` 후 시작
- ★ `gh` 호출 시 `GH_TOKEN="$BOT_GITHUB_TOKEN"` 주입 필수 (회장 개인 PAT 금지 — 감사기록 오염)
- 워크플로우 `/home/jay/workspace/prompts/DIRECT-WORKFLOW.md` · QC `/home/jay/workspace/teams/shared/QC-RULES.md`
- `WORKSPACE_ROOT=/home/jay/workspace` · `CHAT_ID=6937032012` · 수집자 key `ANU_KEY=c119085addb0f8b7`
- 완료 경로는 `finish-task.sh` 실행이 유일하다. 수동 `.done` 금지.
- **명세와 실측이 다르면 임의 판단하지 말고 ANU 에 보고하라.**

★ 백엔드는 2026-08-25 14:40 KST 에 `997fa5d` 로 배포됐다. 이 변경도 머지 후 **배포해야 반영**된다.

## 보고
**★★★ PR 생성까지가 범위다. 머지는 ANU 가 한다. 절대 직접 머지하지 마라.**
★ CI 워처가 `MERGE_READY` 를 내더라도 **자동 머지하지 마라.** 2026-08-25 에 워처 경로
자동 머지가 **3회**(t3006·t3007·t3008) 발생했고 현재 그 통제를 복구하는 중이다.
`memory/reports/task-3010.md` 작성 후 표준 완료 콜백 등록. 콜백 프롬프트 **UTF-8 3900 bytes 이하**.
★ 봉투 첫 줄에 **"이미지(JPEG/PNG) 실제 분석 성공 여부 + HEIC 지원 여부"** 를 담아라.

## goal_assertions (auto-generated)
- `npx vitest run`
