# [fix] PR-D2 isAllowedCrmUrl — prod 호스트 포트 검증 (egress allowlist exact-origin)

## allowed_resources
```yaml
allowed_resources:
  paths:
    - "extension/**"
  forbidden_paths:
    - "src/**"
    - "server/**"
    - ".github/**"
    - "docs/**"
  commands:
    - "npx vitest"
    - "git"
  merge_policy: "none"
  ttl_hours: 6
```
> ★ merge_policy=none. 브랜치 **`task/task-2836-dev1`**(PR #120)에 이어서 커밋(새 PR 금지).

## 문제 (Codex + 봇 자체 발견)
`extension/background/crm.js` `isAllowedCrmUrl()`(~line 69)이 **prod https 호스트 포트를 검증 안 함**:
```
const isProdHost = url.protocol === "https:" && url.hostname === "insuro.biz";   // ← 포트 무검증
const isLocalHost = url.protocol === "http:" && url.hostname === "localhost" && url.port === "8000";  // ← 엄격
```
→ `https://insuro.biz:444/...` 가 allowlist 통과. SSRF는 아니나 **egress-scope 갭**(insuro.biz 에 비-443 리스너 존재 시 PII 유출). single-egress choke 의 exact-origin 원칙 위반.

## 수정 (surgical — exact-origin)
prod 호스트도 **표준 https 포트만** 허용:
```
const isProdHost = url.protocol === "https:" && url.hostname === "insuro.biz"
                   && (url.port === "" || url.port === "443");
```
- localhost(`:8000`) 로직은 그대로. prod 도 포트 검증 추가로 대칭.
- `isAllowedCrmUrl` **외 로직·다른 함수 건드리지 마라.**

## 검증
- 신규 테스트(`prd2-crm-core.test.ts` 또는 single-egress 에): `https://insuro.biz:444/crm/customer-candidates/search` → **거부**(allowlist false·fetch 0). `https://insuro.biz/...`(443 기본) → 허용. `https://insuro.biz:443/...` → 허용.
- 기존 crm 테스트(single-egress·core·canary) 회귀 0. 확장 전체(369) 회귀 0.
- `npx vitest run extension/__tests__/`.

## 완료
- `extension/background/crm.js` + 테스트 외 변경 0 (`git diff --stat`)
- **dev6 금지** — dev1. worktree finish → push(PR #120 반영·새 PR 금지) → ANU 독립검증. **머지 금지**.
- **ANU callback**(UTF-8 ≤3900 bytes, envelope). ⚠️ 세션 사망 대비: 완료 후 즉시 finish-task(push) 우선.
