# T703 — compatibility fixtures not-ready guards

> Status: `done`  
> Milestone: `M0` · Phase A  
> Kind: `test` · Est. change: `~150 lines`

## Goal

以跨層 fixture 鎖定舊 watch／opportunity 相容讀法，並證明所有新增 API 在尚未完成時誠實失敗。

## Depends on

- T700、T701、T702

## Inputs

- `../spec.md` §4.6、§5.3、驗收 #10、#13
- 舊 RadarWatchPublic／OpportunityPublic JSON shape

## Outputs

| 路徑 | 動作 | 說明 |
|------|------|------|
| `apps/backend/internal/logic/radar/product_contract_test.go` | add | JWT、not-ready、成對 ID、跨 owner 契約測試 |
| `apps/web/src/data/fixtures/radarLegacy.ts` | add | 缺新欄位的舊 response fixture |
| `apps/web/src/data/live/radarRepos.test.ts` | edit | 舊 watch→generic、舊商機→未指定產品 |

## Behavior

- 缺 `context_mode` 不報錯、不猜產品。
- 只帶一個 ID 或跨 owner ID 明確失敗且不洩漏名稱。
- 新 endpoint 不得回 `code=102000`＋空 data。

## Out of scope

- 真正 product CRUD 與 persistence
- UX fixture（T720）

## Acceptance

- [x] spec #10、#13 有具名測試。

```bash
cd apps/backend && go test ./internal/logic/radar/ -count=1
cd apps/web && npm run test -- radarRepos
```

Implementation result (2026-08-10): added legacy watch/opportunity fixtures,
mapper compatibility assertions, and kept the generated product routes on the
explicit 501010/not-ready path. Backend and frontend contract tests pass.
