# FR-166 Agent 獨立作業主控台 — 收尾總結（2026-10-28）

> 從 `FR-166-LOG.md` 七棒濃縮。決策者 2026-10-28 在 123 手測五項全過、29 張追加卡按 Done、裁示收尾並重產出貨基線。
> 規格看 `docs/spec-site/current/evidence/agent-console.md`、`remote-agent-manage.md`、`system-admin/ldap-config.md`；操作看 `docs/user-manual/agent/13-standalone-operation.md`；設計取捨看 `docs/analysis/2026-10-26-fr166-*.md` 與 `2026-10-28-fr166-*.md`。

## 一、做了什麼（白話）

Agent 跟主系統斷線時，現場的人可以直接打 Agent 網址登入主控台，照主系統事先授權的範圍手動跑八支檢測工具、做網路除錯、重啟 Agent；結果先收在 Agent，連回主系統自動補傳。Agent 不會因此變成跳板：能掃哪些主機永遠照主系統下發的清冊，Agent 端不能新增使用者、沒有命令列。

三天內從立案到收尾：2026-10-26 討論稿五版、十二幕雛形兩輪、design 定案、41 張卡一次開完；10-27 工作坊整晚自動跑 59 張；10-28 決策者手測追加 29 張（延伸 10 張工作坊派、追加 19 張多數由首腦直接做）。

## 二、關鍵決策（終局）

| 決策 | 結論 |
|---|---|
| 登入三層（D1） | 安裝時強制設的本機管理員 `local-admin`（永不過期）／主系統授權的離線操作者（本人在線時設離線密碼、有到期日）／主系統入場券跳轉。救援碼保留。Agent 端沒有「新增使用者」 |
| 誰能登入 vs 能掃誰 | 兩道門。掃描範圍一律照主系統下發的清冊，不看身分；從未同步的 Agent 只准 local-admin 登、只准查主系統連線 |
| 離線權限來源（D23，手測改判） | 跟主系統同一份：名單只管能不能離線登入與到期日，範圍每次心跳依當下能力點算；`restart` 不下放；沒有任何 Agent 能力點的人不可加入 |
| 八支工具（D3） | 全部可在 Agent 手動執行；ZAP 網址解析成 IP 過清冊；Nmap 的執行主機也過清冊 |
| 網路除錯（D5／D10／D20） | 儀表板九卡＋十項診斷；噪音以「這次總連線數」計，超 10 或含 traceroute／mtr 要確認；埠一次上限 5；不包 tcpdump／iperf／埠範圍／ARP |
| 續傳（D7／D15） | Agent outbox 永不丟主系統派工結果；心跳後 drain；主系統 `receive_result` 任何終態冪等；派工 Agent 離線 7 天 reaper |
| 本機狀態（D11／D16） | 不起 Postgres，收進 SQLite，最小 `schema_version` 表 |
| LDAP（D17／D18／D19） | Agent 三選一（同步／自設／不接）；憑證首次信任釘住、預設 STARTTLS（推翻 CM-2239，主系統設定頁一併改）；抽零相依套件 jedi-ldap |
| 儲存位置（D22，手測改判） | 主控台只能選內建 SeaweedFS，其餘走 CLI |
| 離線天數（手測追加） | 租戶設定，預設 7、1～30，心跳下發；AD 登入不受此限 |
| 報告預覽（手測追加） | JSON／文字／PDF／HTML 都可線上看；HTML 走 Agent 預覽端點帶 CSP sandbox，前端只在回應帶 sandbox 才畫、iframe 自帶 sandbox，不轉 blob |
| 主控台用字 | 畫面一律不印 CLI 指令（看到的人多半沒主機權限），改「請聯絡負責這台 Agent 主機的系統管理員」；來源一律「Agent 手動」 |

## 三、改動範圍與 commits

四個 repo 都在 `feature/FR-139`、已推 origin。

| repo | 2026-10-26 起 FR-166 commits | 主要落點 |
|---|---|---|
| BE | 79 | `plugins/remote_agent/` 接線、離線操作者授權、local-runs 端點、7 天 reaper、排程去重、LDAP 釘住寫回、`agent-local-runs` 頁併入第三方元件手動掃描；主線 migration 5 支（能力點、路由、選單搬移、檢測工具頁隱藏） |
| FE | 79 | `console/` 主控台殼、登入頁、六個分頁、history 路由、報告預覽、閒置登出 composable；主站 Agent 管理頁改版、離線操作者對話框、LDAP 設定頁、角色矩陣補翻譯 |
| Agent | 83 | `core/console/`（inline_policy、netdiag、local_runs、outbox、ldap）、安裝與升級腳本強制設密碼、CIDR 白名單、NET_RAW 守衛、HTML 預覽 |
| jedi 套件 | 2 批發版 | jedi-ldap 新套件；jedi-iam 1.8.0→1.9.0（`provider_login`）；jedi-remote-agent 1.7.0→1.8.0（兩張新表、心跳契約、D23）；jedi-source-scan 0.4.0→0.5.0（Agent 手動掃描清單）；jedi-system-core 1.3.0；jedi-detection 1.6 |

出貨基線：188 基線庫補套 12 支主線 migration（含 FR-157／161／162／165 累積的 9 支），02／04／99 重產，BE `4c927ece4`。

DEV `schema_migrations` 補登記套件 011／012（物件早已存在，登記列漏補）。

## 四、行為差異（使用者看得到的）

- 主系統 Agent 管理頁：按鈕改「連線至 Agent」；頂端四格儀表板；每列 ⋮ 開離線操作者對話框（只選人與到期日，「主系統權限」唯讀）；可設離線登入天數、看本機管理員最近登入與 180 天密碼提醒；Agent 名稱可改。
- 新頁「合規與稽核 → Agent 掃描執行紀錄」：主系統派工與 Agent 手動同一表，可依 Agent／種類／工具／人篩，報告在 Agent 上。
- 主系統「檢測工具」頁隱藏（enable=0），帳密改在 Agent 主控台管。
- 主控台：登入頁三態四種登入；總覽＝儀表板；掃描工具、網路除錯、執行紀錄、LDAP 設定、服務與重啟六分頁；網址一般路徑 `/console/runs`；閒置 15 分提醒 30 分登出。
- 安裝與升級：新裝強制設 local-admin 密碼；主系統位址只收 https（開發模式明確開啟才允許 http）；容器版補 ping／traceroute。

## 五、未做與待裁示

**未做**
- STG／POC 未上：本案所有改動只在 DEV 與 123。前提是主系統先有 https（CM-3178）。
- e2e（CM-3148）：部署測試站後另開一棒到 test repo。
- 網路除錯 Linux 真機實跑。
- 多因子登入：明列太龐大不做。
- 123 的 `dist-console.bak-*` 備份累積 13 份未清。

**待決策者**
1. 主系統「檢測工具」頁：連端點一起拆（開卡）還是翻回 enable=1（等 PM）。
2. 守衛測試 4 支紅不是本案的（`evidence-reuse-*` 三頁沒登記 `ui_routes`、`scan-tool-resources` 沒進入門檻）要不要開卡。
3. 本機管理員登入通知只寄信，Telegram／Discord 要不要。
4. jedi-iam 4 支 FR-155 留下的紅燈要不要修。
5. 刪除 Agent 是硬刪、不清關聯、開著的機器會自動重註冊，要不要改成「在線擋下」或「一併清理」。
6. 123 掃描帳號 sudo 過寬，正式環境只留 nmap 那條（細節在 123 主機上查，不寫進文件）。
7. http＋IP 下「複製」按鈕失效，已裁「測試機先不管」。

## 六、教訓（濃縮自 LOG，已進 memory 的標 ★）

- ★ 離線權限不另存一份：權限類設計先問「真相有幾份」（D23）。
- ★ HTML 預覽不轉 blob：blob 網址會丟掉伺服器端 CSP；安全防線要能說出「這道壞了還有哪道」。
- ★ http＋IP 開主系統登入停在登入頁：`crypto.randomUUID` 只在安全環境存在，被 `.catch` 吞掉；UUID 一律用 uuid 套件。
- ★ 新增資料出口先查同一份資料在既有端點的守門，新門不可較寬（總覽吐內網拓撲）。
- ★ 起服務別包在會被停掉的背景指令裡，停掉會連帶殺子程序。
- Nmap 跟其他工具不同，要登「執行主機」；設成 Agent 本機時本機的掃描帳號也要收那把私鑰。
- SSH 金鑰先比指紋再動手；檔名相近的金鑰可能毫無關係。
- 切 path dependency 後 `pip show` 三支都要 Editable；重裝一支會把別支換回 wheel。
- 123 curl Agent TLS 要 `--http1.1`；8443 是 mTLS，主控台在 8444。
- headless 下 PrimeVue popup 選單點不開，改元件單元測試＋頁面內直接嵌目標網址。
- Stage 號接在同母卡最大值後；「順手改另一個 repo 一兩行」也違反一卡一 repo。
- i18n 缺漏拿 DB 當清單比，不靠肉眼。
- 清冊「名稱」常就是 IP，顯示名前要排除。
- zsh 的 `for f in $VAR` 不按行拆，多檔名會被當一個路徑；逐支套 migration 用 `while read`。
