# task-2788 (A-0) — background 직접 API 조회 실증 스파이크 (인터셉터 제거 가능성 판정)

## 레벨
Lv.3 (아키텍처 결정 스파이크). **신규 브랜치 `task/task-2788-dev5` 를 최신 `origin/main`(cc7476b)에서 분기.** 진단 브랜치(`task/task-2787+2-dev5`)는 **참조만**, 절대 병합·체리픽 금지. PR·merge·배포·운영활성화 금지.

## 단일 소스 (먼저 읽을 것)
`memory/specs/ohmy_product_premium_data_contract_v1_260718.md` (**V1 동결 계약** — GPT+Codex+ANU 합의)

## 목적 (기능 구현 아님 — 결정용 증거 수집)
현재 확장은 MAIN world 에서 fetch/XHR 을 가로채 응답을 관찰한다. 이 구조 때문에 **relay 무결성(first-PORT race)이 미해결**로 남아있다.
구 수집기가 `requests.get(url, headers={"Authorization": f"Bearer <token>"})` **순수 HTTP GET + Bearer JWT** 로 성공했고(쿠키·브라우저세션 불필요), 그 JWT 는 페이지 URL `?token=` 에 있다.
→ **background 가 API 를 직접 조회할 수 있다면 MAIN world·인터셉터·MessageChannel·first-PORT race 를 전부 삭제**할 수 있다. 그 가능 여부를 **실증**하는 것이 이번 유일한 목표.

## ★ 불변식 (절대)
- **서버 전송 0** (insuro.biz/localhost 로 어떤 POST 도 금지). **토큰 저장·로깅·전송 절대 금지** — 메모리에서 1회 사용 후 폐기.
- **자동 실행 금지** — 반드시 **사용자 명시 클릭**으로만 동작.
- MAIN world inject / 인터셉터 **신규 추가 금지**(이번 스파이크는 그것 없이 되는지 보는 것).
- 실고객 데이터 저장·전송 0. 진단 로그는 로컬 콘솔만.

## allowed_resources
```yaml
allowed_resources:
  paths:
    - "extension/content.js"
    - "extension/background.js"
    - "extension/manifest.json"
    - "extension/__tests__/direct_fetch_spike.test.ts"
    - "memory/reports/task-2788.md"
  forbidden_paths: ["src/**","server/**","supabase/**","**/migrations/**",".github/**",".env*","extension/inject.js"]
  new_file_limit: 1
  commands: ["git","npm","node","npx"]
  merge_policy: "none"
  ttl_hours: 8
```

## 구현 요구 (최소)
### D1. 사용자 클릭 트리거
ohmymanager 페이지에 **명시적 버튼 1개**(또는 기존 확장 팝업 버튼 재사용). 클릭 전에는 **아무 동작 없음**.

### D2. 토큰 1회 취득 (ISOLATED content script)
클릭 시에만 `location.search` 에서 `token` 파라미터를 읽어 background 로 1회 전달. **저장 금지·로깅 금지**(콘솔에 토큰 원문 출력 금지, 길이/존재여부만).

### D3. background 직접 조회
`fetch(<ProductPremiums URL>, {headers:{Authorization:'Bearer '+token}})` 실행. **응답 본문은 서버로 보내지 않음.**
URL·쿼리 구성은 진단 브랜치의 `request_fingerprint`(age·gender·insurance_type·plan_id) 형식을 참조하되, **현재 페이지가 실제로 호출하는 URL 을 클릭 시점에 어떻게 알아낼지**도 이번 스파이크의 판정 대상(아래 R2).

### D4. 판정 결과 출력 (콘솔, PII·토큰 없이)
```
{ transport_ok, http_status, has_coverage_premiums, company_count,
  cors_error|null, origin_referer_rejected|null, token_expired|null,
  url_construction: "SOLVED"|"NEEDS_INTERCEPT", notes }
```

## ★ 반드시 판정할 3가지 (Codex 지정)
- **R1. 권한/전송**: background cross-origin fetch 가 실제로 나가는가. (manifest `host_permissions` 에 `*://*.ohmymanager.com/*` 이미 존재 — 확인만)
- **R2. 서버측 검사**: 서버가 `Origin`/`Referer` 등 브라우저 컨텍스트를 검사해 확장 요청을 거부하는가. 거부 시 상태코드·응답 기록.
- **R3. 토큰 수명**: URL 토큰이 클릭 시점에 아직 유효한가(만료·회전 여부).
- (추가) **URL 구성 가능성**: 조회 파라미터를 가로채기 없이 DOM/URL 만으로 구성 가능한가. 불가하면 `NEEDS_INTERCEPT` 로 정직 기록.

## 검증
- 단위테스트 `direct_fetch_spike.test.ts`: 토큰 미로깅 · 클릭 전 무동작 · 서버전송 경로 0 · 응답 파싱.
- **라이브 판정은 회장 1회 실행**(인증 세션 필요). 코드로 단정 금지.
- ANU 재실행: `npx vitest run` 전체.

## goal_assertions
- `npx vitest run`

## STOP_REPORT 조건
URL 구성이 가로채기 없이 불가 · 서버가 확장 요청 거부 · 토큰이 클릭 시점 무효 · MAIN world 없이는 구조적으로 불가 → **각각 증거와 함께 STOP 보고**(우회 시도 금지).

## 금지
서버 전송 · 토큰 저장/로깅 · 자동 실행 · MAIN world 인터셉터 추가 · inject.js 수정 · PR·merge·배포 · 실고객 데이터 · 진단브랜치 병합/체리픽.

## 산출물 & 보고
1. 신규 브랜치 커밋. PR 금지.
2. 보고: diff / R1·R2·R3 + URL구성 판정 / 회장 실행 절차(1페이지, 토큰·PII 노출 없는 캡처 방법 포함) / vitest 카운트 / MATCH·GAP·UNKNOWN.
3. 봇 종료 전 ANU callback(envelope만·UTF-8 ≤3900B, collector=ANU key c119085addb0f8b7).