# task-2787 — InsuRo 복합설계 A1 캡처·어댑터 스파이크 (개발자 검증용, flag OFF) [rev1]

## 레벨
Lv.3 (확장 read-only interceptor + tab-scoped 버퍼 + 어댑터 정규화 골격 + fixture/테스트). **코드+테스트+worktree 커밋+ANU 보고까지. PR 생성은 ANU 독립검증 후 별도 승인. merge·운영 활성화 금지.**

## 단일 소스 (반드시 먼저 읽을 것)
`memory/plans/insuro-composite-design/plan-v2.2-implementation-ready-draft-260716.md` (§2·§3·§4·§17 + A1 스파이크 절) + `phase0.5-evidence-260716.md`(응답 스키마 실증).

## 목표 (한 줄)
ohmymanager `/api/ProductPremiums` 응답을 **탭별로 안전하게 복제-읽기** 하고 **허용 필드만 정규화**하여, **명시 버튼 클릭 시 개발자 검증용 matrix**(기존 계산엔진 입력 스키마)를 생성한다. **계산 정답 확정이 아니라 어댑터 계약을 실측·고정**하는 스파이크.

## allowed_resources
```yaml
allowed_resources:
  paths:
    - "extension/inject.js"                                  # 수정: read-only interceptor 신규 구현
    - "extension/content.js"                                 # 수정: MAIN→ISOLATED relay + 명시 버튼서 dev matrix
    - "extension/background.js"                               # 수정: sender.tab.id 기준 tab-scoped 버퍼(A안)
    - "extension/manifest.json"                              # 수정: world:MAIN content_script 별도 엔트리
    - "extension/lib/ohmy_premium_adapter.js"                # 신규(1)
    - "extension/lib/ohmy_active_plan_resolver.js"           # 신규(2)
    - "extension/__tests__/ohmy_premium_adapter.test.ts"     # 신규(3) — 다중 describe
    - "extension/__tests__/fixtures/productpremiums.min.json"# 신규(4) — _fixture_meta 포함
    - "memory/reports/task-2787.md"                          # 보고서(신규 상한서 제외)
  forbidden_paths: ["src/**","server/**","supabase/**","**/migrations/**",".github/**",".env*"]
  new_file_limit: 4          # ★ extension 신규 코드/test/fixture 4개만(adapter·resolver·test·fixture). memory/reports/task-2787.md는 상한서 제외. inject/content/background/manifest는 기존 파일 수정(신규 아님). 4 초과 필요 시 STOP_REPORT
  commands: ["git","npm","node","npx"]
  merge_policy: "none"
  ttl_hours: 8
```

## 구현 요구 (GPT rev1 고정)

### 1. ProductPremiums 전용 read-only interceptor 신규 구현 (표현: "부활" 금지)
- `inject.js`: no-op → **`/api/ProductPremiums` 응답만 복제해서 읽는 read-only interceptor 신규 구현**.
- **실행 방식 고정**: manifest에 **별도 `world:"MAIN"` content_script 엔트리 + `run_at:"document_start"`**, **ProductPremiums 대상 호스트(mmlfcp.ohmymanager.com)에만 적용**. 기존 ISOLATED content script와 **별도 엔트리로 분리**(같은 엔트리에 섞지 말 것). 이 방식 실패 시 **STOP_REPORT**(대체 주입 방식 임의 선택 금지).
- **절대 불변**: 원래 fetch/XHR **반환값·헤더·예외 동작 변경 0**, 요청 차단 0, 요청 헤더 변경 0. **`/api/ProductPremiums` 외 응답 캡처 0.** 자동 서버 전송·자동 push·응답 원본 외부 저장·실고객 저장 **0**.
- **transport**: 실환경에서 ProductPremiums를 발생시키는 **실제 transport(fetch 또는 XHR)를 우선** 지원. 다른 transport는 동일 fixture·contract로 추가하되 **불필요한 monkeypatch 확장 금지**.

### 2. 탭별 버퍼 = background sender.tab.id 기준 (A안 — 전역 latest 금지)
- **[P0 실현가능 확인됨]** background.js는 MV3 service worker이며 **이미 `chrome.runtime.onMessage.addListener` 타입 라우터**(background.js:112, OHMY_MATRIX_CAPTURED 등·sendResponse·sender 파라미터)를 가짐. → **기존 라우터에 신규 메시지 타입 2개 추가**(①capture 버퍼 저장: `sender.tab.id` 사용 / ②버튼이 자기 탭 버퍼 요청)로 구현. 기존 핸들러 분기 동작 무변경.
- 흐름: inject.js(MAIN) 응답 복제 → `window.postMessage`(nonce·origin 검증) → content.js(ISOLATED) → `chrome.runtime.sendMessage` → **background.js가 `sender.tab.id` 기준 tab-scoped 버퍼에 저장**.
- 버퍼 키 = `sender.tab.id` + `page_session_id` + `request_fingerprint`. **전역 단일 latest 금지.**
- navigation(페이지 이동/SPA 라우팅) 시 이전 버퍼 무효화 · TTL 만료 · **중복 응답 hash 제거**.
- **명시적 요청(해당 탭 버튼)에만 그 탭의 버퍼 반환.**

### 3. 활성 플랜 식별 = 후보 판정까지만
- 우선순위: ①내부 명시 연결키 탐색 ②요청 직전 화면 `user_plan_name` **최소** 읽기 ③후보 details hash 비교. **전체 담보 DOM 스크래핑=마지막 진단수단(운영 경로 강제 금지)**.
- **`UNIQUE_MATCH`일 때만 matrix 생성.** 복수 후보·무매칭·정보부족 → **fail-closed**(matrix 미생성). **임의 첫 항목 선택 금지.**

### 4. 정규화 = provenance 우선 (정답 확정 아님)
- 각 담보 결과 필드: `raw_premium, base_amount, selected_amount, normalized_premium, normalization_method(EXACT|SCALED_LINEAR|API_FINAL_FIELD), normalization_rule_version, validation_flags`.
- detailList 최종 보험료 필드 우선 / base==selected면 그대로 / 다르면 검증 선형 스케일 / **반올림 UNKNOWN이므로 SCALED_LINEAR는 계산값+정밀도 보존**. 불명확 시 계산 차단. **키 부재=미제공은 절대 0원 변환 금지.**

### 5. fixture = 비식별 최소 (JSON 주석 불가 → _fixture_meta)
- 실응답 기반, `consultant_id·ga_id·user_plan_id` 등 내부 식별정보 **가명화** · 토큰·쿠키·헤더·고객 PII **포함 금지** · 필요 필드만(구조·금액 관계 유지).
- **`.json` 주석 금지 → 최상위 `_fixture_meta` 객체에 `{"kind":"SANITIZED_FIXTURE","pii":"NO_CUSTOMER_PII","auth":"NO_AUTH_DATA"}` 기록.**
- 커버: 정상 / 누락(미제공) / premium 0·null / **복수 user_coverages** / 비선형 가능성 + **synthetic 미제공(보험사1 담보A 존재/보험사2 A 부재)**.

### 6. diagnostic flag = 기본 OFF + flag OFF 회귀 필수
- 기본 false. 원격·운영 자동 활성화 금지. 기존 flag 체계 재사용 또는 테스트 전용 constant/개발 빌드 한정.
- **flag OFF에서 기존 경로·기존 테스트 무변경(회귀 PASS 필수).**

### 7. 기존 버튼·DOM 경로 = 기존 동작 변경 0 + 자동 fallback 금지
- **기존 handler의 기존 동작 변경 0**(문구 정정: "handler 수정 0"이 아님 — flag-gated 분기 `if(diagnosticFlag){…}` 추가는 허용, flag OFF 시 기존 동작 완전 동일). 기존 DOM 스크래핑(`scrapeMmlfcpMatrix` 등) **수정·삭제·호출 0**.
- 명시 버튼에서 flag ON일 때만 **API buffer 기반 개발자 matrix 생성**(DOM scraper 호출 금지·서버 POST 금지). flag OFF면 기존 경로만.
- interceptor 실패 시 **기존 DOM 경로로 자동 전환 금지**(검증 오염 방지). 실패 시 명시적 실패 상태 반환 후 종료.

### 8. 진단 출력 위치 (src/ 수정 금지 → UI 불가)
- 후보 목록·matrix 검증 결과는 **구조화된 diagnostic result 객체 또는 개발 콘솔로만**. **원본 응답·내부 식별자·PII 콘솔 출력 금지.**
- 권장 반환 객체: `{status(UNIQUE_MATCH|MULTIPLE_CANDIDATES|NO_MATCH|INSUFFICIENT), candidates:[user_plan_name...], matrix?:{...}, validation_flags:[...], unknowns:[...]}`.

## 완료 수용 기준 (전부 PASS)
- `/api/ProductPremiums` 외 캡처 0 · 원본 fetch/XHR 반환·예외·헤더 변경 0 · 자동 외부 전송 0.
- 다중탭 fixture 버퍼 교차 0 · 동일 응답 중복 버퍼 0.
- 복수 user_coverages 자동 임의선택 0 · 불명확 후보 matrix 생성 0.
- 허용 필드 외 민감필드 출력 0 · **키 부재가 premium 0원으로 변환되는 사례 0**.
- 생성 matrix가 **기존 계산엔진 입력 schema 검증 PASS**.
- 기존 버튼·DOM 스크래핑 경로 수정·삭제 0 · **flag OFF 전체 회귀 PASS**.

## goal_assertions
- `npx vitest run extension/__tests__/ohmy_premium_adapter.test.ts` (다중 describe: interceptor 원본불변 / 복수후보 fail-closed / 다중탭 버퍼교차0 / 중복제거 / 자동전송0 / 키부재≠0원 / matrix schema)
- `npx vitest run` (기존 전체 확장 테스트 무변경 회귀 PASS)

## STOP_REPORT 조건
new_file_limit 4 초과 · src/·server/·migrations 수정 필요 · world:MAIN 엔트리 방식 실패 · 원본 네트워크 동작 변경 필요 · 자동 fallback/push 필요 · UNIQUE_MATCH 외 matrix 필요 · 실고객 저장 필요 · **★ 실제 ProductPremiums 응답 구조가 `phase0.5-evidence-260716.md` 계약(coverage_premiums/detailList/user_coverages/is_selected/coverage_amount 등)과 다를 경우 — 억지 구현 말고 STOP_REPORT(fixture 계약 ≠ 실응답이면 중단·보고).**

## 산출물 & 보고 (PR 없음 — ANU 보고까지)
1. worktree 커밋. PR 생성 금지(ANU 독립검증 후 별도 승인).
2. 보고: 코드·테스트 결과 / fixture 목록 / **MATCH·GAP·UNKNOWN** / 실환경 검증 필요항목(반올림 계약·활성플랜 직접 연결키·비선형 담보·선택담보 미제공 실사례·운영 JWT 상태) / **A2 저장계층 계약 제안**.
3. 봇 종료 전 ANU callback(envelope만·UTF-8 ≤3900B).

## 금지 (전부)
PR merge · 운영 활성화 · flag 자동 ON · 자동 push/서버전송 · 실고객 저장 · 고객 자동매칭 변경 · 고객 대면 그래프·표 · 기존 버튼/DOM 경로 수정·삭제·자동 fallback · src/·server/·DB 수정 · "부활" 표현.