# FR-039 Agent 認證 — 實作計畫（mTLS + JWT + 指紋 + 撤銷）

> ⚠️ **本檔(v1)已被 v2 取代,勿用**。改用:`handoff/2026-06-19-agent-auth-v2-TRACKER.md`(進度中樞)
> + `handoff/2026-06-19-agent-auth-v2-plan-{backend,agent,frontend}.md`(三 track 詳盡計劃)。
> v2 改:自我註冊 + 心跳 + 憑證雲端簽發(取代本檔的 ops 預發/雲端抓指紋)。

> 對應設計：`design-agent-auth.md`。範圍：cloud↔agent 認證機制；連線方向不動（決策 7）。
> 原則：用 `AGENT_AUTH_MODE`（`none|full`）feature flag 包覆，**過程不破壞現有 demo**；全綠才把 dev 切 `full`。

## 階段

### Phase 0 — Dev PKI / 金鑰（dev-only，不 commit）
- 腳本 `scripts/agent-auth/gen-dev-pki.sh`：產 ① 內部 CA ② 雲端 client cert+key ③ agent server cert+key ④ JWT RS256 keypair。
- 產物放 dev 本機 / `.secrets/agent-auth/`（gitignored），不入版控。

### Phase 1 — DB + 雲端設定 scaffolding（非破壞）
- migration `2026-06-19-fr039-remote-agents-auth-columns.sql`：`remote_agents` 加 `device_fingerprint`、`status`。
- config：`AGENT_AUTH_MODE`（預設 `none`）、CA/client cert/key 路徑、JWT 私鑰路徑（走 env/secret）。
- `RemoteAgentEntity` / mapper / serializer 補 `device_fingerprint`、`status`。

### Phase 2 — 雲端認證（gated by mode）
- JWT util（PyJWT RS256，mint per-request：iss/aud/exp/op/tenant/bound_fp）。
- `RemoteAgentAdapter`：mode=full 時 httpx 帶 client cert + `verify=CA` + `Authorization: Bearer` + 檢查回應 `X-Agent-Fingerprint`；mode=none 維持現狀。
- 所有呼叫前檢查 `status != revoked`。

### Phase 3 — agent 端
- fingerprint 模組：讀 `/host/product_uuid` + `/host/machine-id` + `/host/mac` → sha256 快取。
- `GET /agent-info`（回 fingerprint/version）。
- before_request：驗 JWT（公鑰/exp/aud）+ `live_fp == bound_fp`（gated by env）。
- 回應加 `X-Agent-Fingerprint`。
- compose：nginx sidecar 收 mTLS（proxy→Flask）+ 掛 certs/JWT 公鑰/host 識別碼 + `deploy/collect-host-id.sh`。

### Phase 4 — enrollment / bind / 撤銷（雲端）
- service + endpoint：`bind`（建立時抓 fingerprint 存）、`rebind`（重新綁定，manager）、`revoke`/`unrevoke`（status，manager）。
- 測試連線維持唯讀（不寫 fingerprint）。

### Phase 5 — FE
- 建立存檔即綁定（顯示指紋）；「重新綁定設備」「撤銷/復用」鈕（manager）。
- 狀態欄：已綁定 / 指紋相符 or 不符警示 / active|revoked。

### Phase 6 — dev 端到端驗證
- 跑 Phase 0 PKI → agent 重 build（nginx + 新 code）+ 掛 certs → 雲端切 `AGENT_AUTH_MODE=full` → 驗：正常連線通、改指紋擋、撤銷即時擋、JWT 過期擋。

## 安全 / 紀律
- 憑證/金鑰**一律不入版控**（gitignored；連線資訊文件只寫路徑）。
- 過程 `AGENT_AUTH_MODE=none` 不影響現有 121 demo；最後才切 full。
- 套件不動（agent 認證在 evidence-agent app + nginx，不碰 jedi-file-upload）。
