# FR-171 交接現況（STATE）

> **這份是 living 檔**：每棒就地 Edit，只描述「此刻」。歷史脈絡看同資料夾的 `FR-171-LOG.md`。

| 項目 | 值 |
|------|-----|
| 最後更新 | 2026-11-01（第 1 棒，首腦，討論稿 v1 交出、等決策者裁 D1～D12） |
| branch | BE `feature/FR-139`；Agent／jedi 主線（本棒未動） |
| 母案卡 | 未開（討論階段不開卡） |
| 本棒角色 | 首腦（分析決策人員），走 `big-feature-workflow`，不開 subagent |
| 階段 | Step 2 討論稿已交，**未拍板**；design.md 未寫、Notion 未開卡 |
| 接手前必讀 | §0 讀序 |

## 🧭 原始需求 / WHY

> **這節寫一次，之後各棒不動。**

**決策者原話（2026-10-31）**：
> 之前都是只能等心跳由 agent 發訊息給本體，後來才有了臨時 token 的模式讓本體可以主動跟 agent 溝通，所以現在應該算是可以雙向溝通？我想要把等待心跳的功能都改掉，除了原本的心跳功能，因為我覺得這太偷懶了而且越塞越多，不可能都只依靠心跳來處理事情。

**討論中追加的三個要求（2026-10-31）**：
1. 「反正都要重構了，我希望是好的設計，而不是像之前一樣都沒想過硬塞。」
2. 「mTLS 10 年過了要怎麼更新？客戶是沒有 IT 的一般人，叫他打指令是要他的命；原廠出差到冰島、俄羅斯怎麼處理。」→ 換證要全自動。
3. 「很多機制沒錯，但都做一半或是沒有統一。要嘛就是機制統一幾個，不然兩個月後沒人記得，除錯要花兩三天。」→ 不只做指令直推，連守門、client、簽章規則一起收斂。
4. 「要真的分析過，不合理要反駁我，我會自己判斷。」→ 首腦據此撤回兩項自己先前的說法（見 §2）。

**2026-11-01 另一 session 的決策者裁示（memory `feedback_no_heartbeat_piggyback_messaging`）**：「之後不要再用心跳帶訊息了，這機制真的雷到一個不行。」心跳只表存活；Agent→主系統的結果／進度走專用端點當下送、送不到進 outbox；主系統→Agent 走資料面。**這條比討論稿 v1 更激進**（v1 的主題 B 仍讓心跳帶設定同步，只是加版本號），接手首腦要把這條併進去重審主題 B，見 §3。

**目標長什麼樣**：一條指令通道（主系統→Agent 8443，派工／重啟／升級／換證／取消，打不通退回主系統 DB 的單子由心跳或下次直推補）；心跳只表存活（設定同步改專用端點或帶版本號，依 11-01 裁示重審）；兩個方向同一套「60 秒、綁方法路徑、綁 jti、自己私鑰簽」的簽章規則；憑證一年自動換、CA 與簽章公鑰走信任錨清單可輪換；主系統四份 client 收一份、Agent 守門一條規則。

**本棒在大圖的位置**：第 1 棒，探脈＋討論稿 v1。前作 FR-170 第 4 棒「P4 分析」是起點，FR-170 P0～P3 已於 10-31 合回主線。

## §0 接手讀序

### 0.1 🔒 先懂需求 gate
1. 本檔 🧭 WHY 節
2. `docs/features/FR-171-2610-agent-command-channel/discussion.md` **全讀**（或開 `discussion.html`）——§2 現況地圖、§4 九個洞、§5 六主題、§7 D1～D12
3. memory `feedback_no_heartbeat_piggyback_messaging`（`docs/claude/memory/`）——11-01 裁示，討論稿 v1 寫在它之前

### 0.2 現況與待辦
4. 本檔 §2 已定裁示、§3 下一步
5. `FR-171-LOG.md` 第 1 棒 block

### 0.3 需要細節才開
- FR-170 LOG 第 4 棒「P4 分析」段、FR-170 design §3.x
- Agent：`guidant_agent/sync/api/data_plane_auth.py`、`sync/app/enroll.py`、`sync/adapters/cert_files.py`（`prior_key_proof`）、`sync/domain/agent_auth.py`
- jedi-remote-agent（`.venv/lib/python3.11/site-packages/jedi_remote_agent/`）：`common/agent_auth/jwt_util.py`、`possession.py`、`app/service/agent_enrollment_service.py`、`agent_enroll_token_service.py`
- 主系統：`infra/remote_agent/agent_credential_client.py`、`agent_update_notify_client.py`、`core/plugins/remote_agent.py`（`build_adapters`）

### 0.4 ✅ 冷接自檢
1. 現在主系統與 Agent 有哪四條路？每條怎麼證明身分？（答不出來回去讀 discussion §2）
2. 九個洞哪一個是「真正的洞」、哪些只是縱深不足？（§4）
3. 為什麼心跳改持有證明選 DPoP 式而不是 mTLS？（§5.6）
4. 為什麼撤回「CA 縮到 3 年」？（§7 D5）
5. 11-01 的「心跳不帶訊息」裁示跟討論稿主題 B 哪裡衝突？

## §1 當前狀態

| 項目 | 狀態 |
|---|---|
| 登記 | `docs/features/README.md` FR-171 列已加（commit `03feb84ae`） |
| 討論稿 | `discussion.md` v1，6 張 mermaid、D1～D12；已 build 站；**未經決策者拍板** |
| design.md | 未寫 |
| Notion | 未開母卡與子卡 |
| 雛形 | 未畫（D11 建議不畫整頁，管理頁多一欄即可） |
| 程式 | 本棒零改動 |
| Agent 主線 | `3ab1253`（FR-170 合回）；1.4.8 已於 11-01 推 189（另一 session） |

## §2 已定裁示（不要重新討論）

| 裁示 | 何時 | 誰 |
|---|---|---|
| WebSocket／長連線不做；SaaS 不開 8443 時才再議 | 2026-10-29 FR-170 §3.x；10-31 本案前置重申 | 決策者 |
| 心跳不再帶訊息（指令、結果、進度、清單）；心跳只表存活；事件走專用端點 | 2026-11-01 | 決策者（另一 session） |
| 換證必須全自動，客戶與原廠零人工 | 2026-10-31 | 決策者 |
| 機制要統一，不接受做一半 | 2026-10-31 | 決策者 |
| 「三種票共用一把私鑰是洞」**撤回**：RFC 8725 現況合規，分鑰是縱深（D10 仍建議順手做） | 2026-10-31 | 首腦自撤 |
| 「CA 縮到 3 年定期換」**撤回**：NIST 要求能換不是排程換 | 2026-10-31 | 首腦自撤 |
| 私鑰永遠在 Agent 產生、不經網路；主系統「發動換證」只能是叫 Agent 自己換 | 2026-10-31 | 首腦提、決策者未反對 |

## §3 下一步

**🔴 下一個動作**：接手首腦等決策者裁 D1～D12。裁之前**先做一件事**：把 11-01「心跳不帶訊息」裁示對照討論稿主題 B 重審。v1 主題 B 是「心跳帶 `config_versions`、主系統只回有變的」，仍是心跳帶設定；11-01 裁示下應改成「主系統設定有變→直推 `POST /config` 通知（或走指令通道）；Agent 啟動與重連時主動 `GET /agents/config?versions=…` 拉」。改完出 v2 再請決策者裁。

**決策者 10-31 討論中提出、v1 尚未落地的修正**（接手要併進 v2）：
- D9 要擴大：註冊 token 改成「多把並存、每把有標籤／到期日／可用次數（預設 1）、撤銷針對單把」（Kubernetes bootstrap token 做法）。決策者的疑問「重新產生跟撤銷差在哪」查證結果：現況 token 一租戶一組永久有效、產生＝換掉舊的、撤銷＝關掉註冊不產新的，兩者對舊 token 動作相同；名字騙人。約兩張卡（表加三欄、兩支 API、FE token 頁）。
- 已註冊的 Agent 不受 token 產生／撤銷影響（已向決策者確認）；要讓一台斷線是在 Agent 管理頁撤銷那一台。

之後順序：拍板 → design.md（含 `handoff/cards.py` 驗批）→ Notion 母卡＋子卡（四欄齊全）→ 停，工作坊派。釘版套件（jedi-agent-protocol、jedi-remote-agent）有改動，批 1 前要開環境卡。

> ⚠️ 這節是建議清單，不是執行授權。接手方讀完盤點完即停，等決策者發令。

## §4 待辦與風險

- **推測，待 verify**：主系統四份 client 簽 JWT 前都沒查 `remote_agents.status`。grep 過 cancel client 與 credential client 確實沒看到；`remote_agent_adapter.py` 與 probe client 沒細讀。verify：`grep -n "status\|enabled\|assert_agent_can_call" infra/upload_file/remote_agent_adapter.py .venv/lib/python3.11/site-packages/jedi_detection/infra/detection_tools/connector/agent_probe_client.py`。
- **已查證**：`proves_prior_key` 不看舊證到期日（只驗 CA 簽發、CN、簽章），所以過期後仍可換證，寬限在程式層已成立。
- **已查證**：取消掃描已經是直推（`agent_cancel_client` 打 `/detection/cancel`），不在心跳。
- mermaid 六張圖只靜態檢查（首行 init、語法形狀），**未開瀏覽器看渲染**（規範不開瀏覽器）。決策者若回報某張糊掉，看 `discussion.md` 對應 sequenceDiagram 的 Note 內有無特殊字元。
- CA 憑證本身效期：installer `openssl -days 3650`，已確認 10 年。

## §5 Pre-flight（唯讀）

```bash
cd ~/Projects/Billows/Audit-Manager/compliance-manager-be
git status --short | grep -v "^??" ; git log --oneline -3
ls docs/features/FR-171-2610-agent-command-channel/
grep -n "FR-171" docs/features/README.md | cut -c1-60
cat docs/claude/memory/feedback_no_heartbeat_piggyback_messaging.md | head -5
git -C ~/Projects/Billows/Audit-Manager/evidence-agent log --oneline -1
```

## §6 環境座標

- 本機 Agent：`~/guidant-agent-local/start-agent.sh`（venv `evidence-agent-knWYPLiu-py3.13`）連 DEV BE 8000。
- 不碰 STG／POC。189 POC 的 Agent 11-01 由另一 session 推 1.4.8，本案與它無關。
- 已裝套件版本：jedi-remote-agent 1.11.0、jedi-agent-protocol 0.1.0（主系統 `.venv/lib/python3.11/site-packages/`）。

## §7 行為規範提醒

- 首腦不開 subagent（決策者 10-16 改判）；探脈自己 grep。
- 討論稿拍板前不寫 design、不開卡；開卡照 `notion-card-templates`，一張卡一個 repo，登記型檔不同批。
- 回報一律白話、繁中；問裁決用「問題→建議→理由」。
- 決策者要求「不合理要反駁」——提方案要附規範依據（RFC／NIST／業界實作），不順著他講。
