✅ CLOSED — 2026-07-30 全案收尾:FR-057 已隨 v1.12.0 發版(三 repo 已 push + tag),Notion CM-938~952/954/955/956 全 Done(CM-953 維持討論)。收尾彙整見同目錄
2026-07-30-v1.12.0-release-SUMMARY.md。本文件 §1.1/§9.1 的 push 狀態描述為當時快照,已過時。
| 項目 | 內容 |
|---|---|
| 緣由 | FR-057(OpenSCAP SSH connector)8 張子任務卡 + 3 張手測期間發現的修正卡(CM-952/954/JobExecutionDrawer 證據連動)全部完成並已部署驗證。本棒角色是收口 + 部署:完成文件補完、修 bug、build+load agent image 到兩台主機並重啟、確認服務健康。尚未做:user 尚未親自複測 CM-952/954 的畫面呈現(agent 才剛升級到 0.2.11)。 |
| Branch | 三 repo 皆 feature/instance-agent,working tree 全乾淨、HEAD 皆已 push 到 origin(見 §9) |
| 本棒角色 | 收口 + 部署,非新開發。下一棒可能是:user 手測回報問題需要 fix,或 user 下令走完整收尾流程(spec 已於本棒更新,但 SUMMARY / Notion 母案狀態 / memory 尚未動) |
| 接手前必讀 | 本文 §0 讀序 |
| 預估時間 | 若只是複測回報問題:10-30 分鐘理解狀況;若要做正式收尾(Notion 母案批次更新 + SUMMARY):30-60 分鐘 |
FR-057 = 在 FR-056 檢測工具整合平台上接入第二個掃描工具 OpenSCAP(CIS/STIG 組態合規稽核),並開出 connector 第三種連線型態 SSH。
大圖:FR-056(已隨 v1.11.0 上線)讓租戶設定檢測工具 → 任務按「開始執行」→ 客戶端 Agent(evidence-agent,Docker)心跳領派工 → 掃描 → 報告自動回收成任務證據。第一版只有 OpenVAS(API 型)。本案價值:①客戶多了組態合規稽核能力(不只弱點掃描)②connector 架構證明可擴(SSH 型開出後,未來 Lynis 等 CLI/SSH 工具同軌)。
關鍵設計事實:
openscap-scanner + SCAP content(SSG),這是官方正規用法(Red Hat Satellite 同模式)。Agent 維持 Docker 形態不變,只當掃描發起端。use_sudo,沿用 FR-056 既有 Fernet 加密鏈 + D9 派工下發。oscap-ssh 腳本語意是「本機 content 推送到遠端」,與 D3(用目標主機自帶 content)矛盾 → 定案 connector 自組 SSH 指令(paramiko)直接在目標上執行 oscap 引用目標本地 content。本棒新增的兩個重要教訓(詳見 §2):
docker build 沒指定 --platform 會產出跑不動的 image(exec format error),必須 --platform linux/amd64。docs/features/FR-057-2607-openscap-ssh-connector/design.md §1-§2(背景 + D1-D7)全讀docs/features/FR-057-2607-openscap-ssh-connector/handoff/2026-07-29-fr057-manual-test-handoff.md(上一棒交接,含 connector 完整行為描述、掃描指令組法)3ab346da4cd081af9cfac78397f7acfb(CM-938);三子需求卡 CM-939/940/941;手測發現的修正卡 CM-952(3ac346da4cd0817c9c47e5482d12a608)/ CM-954(3ac346da4cd08107aa29c3819c54b19c)/ CM-953(討論中,3ac346da4cd0819390d2c5b85c754bf8)冷接自檢:①FR-057 解決什麼使用者問題?②為什麼 connector 自組 SSH 指令而非用官方 oscap-ssh?③CM-952 跟 CM-954 是同一類問題的哪兩種變體?④122/123 兩台 agent 主機現在跑哪個版本、健不健康?⑤下一棒該做什麼、不該做什麼?——答不出回去讀 §0.1-§0.3。
| Repo | HEAD commit | 狀態 |
|---|---|---|
| compliance-manager-be | 0ed638a7 docs(fr057): OpenSCAP 上線文件補完——SPEC 三頁 + 使用手冊擴充 |
乾淨,已 push |
| compliance-manager-fe | 0fc8f17c fix(job-execution-drawer): 重新整理執行紀錄時一併刷新證據清單 |
乾淨,已 push |
| evidence-agent | 722e25ca feat(cm-954): content 對不上 OS 不再產出「假成功」報告 + bump 0.2.11 |
乾淨,已 push |
BE working tree 有一批跟 FR-057 無關的既有 untracked 檔案(v1.9-bugfix handoff、v1.8.0 交付文件 docx、ddd-layer-audit 資料夾等)——那些是別的 arc 留下的,不是本棒產生,不要清理,不歸本棒管。
| Case | 標題 | 狀態 |
|---|---|---|
| CM-938 | FR-057 母案 | Not started(子任務全完成但母案狀態未同步——下一棒若走完整收尾要記得改) |
| CM-939/940/941 | FR-057.1/.2/.3 子需求卡 | Not started(同上,子任務卡本身已個別改「修正待驗證」,但這三張中層卡沒同步) |
| CM-942/943/944 | T-1.1/1.2/1.3(BE migration + FE 兩張) | 修正待驗證(已在前一棒改) |
| CM-945~949 | T-2.1~2.3(Agent connector)+ T-3.1~3.2(多檔回收鏈) | 修正待驗證(前一棒) |
| CM-952 | 多台掃描結果呈現不完整(漏掃靜默 / 報告只拿一份 / 執行紀錄不展開) | 修正待驗證(agent 0.2.10 起含此修正,已部署 0.2.11) |
| CM-954 | content 與目標 OS 不匹配產出假成功報告 | 修正待驗證(agent 0.2.11 含此修正,已部署) |
| CM-953 | 異質 OS(Windows)支援方案 | 討論中,等 user 拍板要不要開獨立 FR,不是本棒可自行決定 |
⚠️ 沒有 Notion 卡的改動:本 session 應 user 臨時要求做的「重新整理執行紀錄時連動刷新證據清單」(FE commit 0fc8f17)沒有對應 Notion 卡——這是使用者體驗微調不是正式子任務,若要正式收尾請下一棒視情況補一張小卡或併入某張既有卡的備註。
| 主機 | 用途 | 部署前版本 | 目前版本 | 健康狀態 |
|---|---|---|---|---|
| 192.168.50.123 | Agent 主機(jedi 帳號 SSH,路徑 /opt/evidence-agent/deploy/) |
0.2.10 | 0.2.11 | 已確認 Up,心跳 200 OK |
| 192.168.50.122 | Agent 主機(同上,路徑同) | 0.2.10 | 0.2.11 | 已確認 Up,心跳 200 OK |
兩台都在 0.2.11(累積含 CM-952 + CM-954 兩個修正)。部署細節與踩過的坑見 §2.2。
report_file_uid 單值只存第一筆,改成從 job_evidences 讀全部)+「執行紀錄預設不展開」(改固定展開)。oscap exit=0 產出完整報告,但所有規則都因 CPE 平台判定不匹配而 notapplicable——零實質檢查卻回報「成功」「發現 0 項」,比失敗更危險(會被當成「已檢查且乾淨」寫進稽核紀錄)。修法:事後判定(pass+fail==0 且 notapplicable>0)+ 事前判定(probe 階段比對 content 檔名版本 vs 目標 OS 版本)雙重把關,報告仍上傳但打 content_mismatch 旗標,FE 顯示「無實質檢查」警示、隱藏「發現 0 項」(避免誤讀)。兩者刻意都不用比例門檻(如 notapplicable ≥95%),只認「有沒有」——因為容器化等環境本來就大量規則不適用,用比例會對合法情境誤報。
第一次升級 122/123 時,容器 crash loop(exec /usr/local/bin/python: exec format error)——原因是開發機(Mac,arm64)跑 docker build 沒指定平台,預設 build 出 arm64 image;122/123 兩台目標主機是 amd64(Linux 伺服器),image 架構不匹配,容器啟動後立即崩潰重啟。
修正動作:
.env(AGENT_IMAGE)與 docker-compose.yml(AGENT_VERSION)都改回 0.2.10、docker compose up -d guidant-ai-agent 回滾,確認服務恢復健康docker rmi 刪掉錯誤平台的本地 image,重新以 DOCKER_BUILDKIT=1 docker build --platform linux/amd64 --secret id=nexus_auth,src=.secrets/nexus.env -t guidant-ai-agent:0.2.11 --load . 明確指定平台重 builddocker inspect guidant-ai-agent:0.2.11 --format '{{.Os}}/{{.Architecture}}' 確認回傳 linux/amd64 才出貨docker save | ssh jedi@<host> docker load → 改 config → docker compose up -d guidant-ai-agent → 這次正常啟動、心跳成功教訓:以後任何一次 agent image build,只要開發機跟目標主機架構不同(現在是 Mac→Linux amd64),一律要帶 --platform linux/amd64,rebuild.sh 目前沒有內建這個保護,是隱性風險(見 §10 待辦)。
rebuild.sh 在本機 bash 3.2 下會噴 unbound variablerebuild.sh 內的中文全形註解((...))緊貼變數名 $SCRIPT_DIR 時,macOS 內建 bash 3.2 對 multibyte 字元邊界解析有 bug,會誤判成 SCRIPT_DIR<垃圾bytes> 未定義變數而中止。繞過方法:不要跑 ./rebuild.sh,直接照腳本內容手動執行 DOCKER_BUILDKIT=1 docker build --secret id=nexus_auth,src=.secrets/nexus.env -t <tag> .(本次額外加 --platform linux/amd64 --load)。這不是 script 邏輯錯,是本機殼層版本問題,換一台新版 bash 的機器應該不會發生——不建議動 rebuild.sh 本身(其他人的機器可能沒事),下一棒若也遇到同樣報錯,直接繞過即可,不用花時間修腳本。
AGENT_VERSION 是第六處版號同步點repo 內版號同步五處(pyproject.toml / config/config.py 預設 / rebuild.sh 範例 / deploy/docker-compose.yml 的 image 與 AGENT_VERSION)之外,部署機本地的 docker-compose.yml(/opt/evidence-agent/deploy/docker-compose.yml)裡的 AGENT_VERSION: "0.2.10" 是獨立第六處,不會隨 git pull 自動更新(那份是部署機的本地檔案,非直接對應 repo 版控檔案,需 rsync/scp 或手動 sed 更新)。本棒兩台都已手動同步到 0.2.11,若未來再升版忘了這步,agent 回報的版本號會跟實際 image 對不上(不影響功能,但排查時會誤導)。
| Commit | 內容 |
|---|---|
768aa289 |
T-1.1 migration:seed openscap(SSH 型態,第4筆)+ config/param schema + setup_guide |
de979c30 |
補 setup_guide 欄位落地鏈路(ORM model→domain entity→mapper→serializer,migration 有加但程式碼沒接的孤兒欄位) |
3e30d99d |
修正 password/private_key required 語意(條件必填,非永遠非必填) |
c20b22a2 |
T-3.2 多檔證據回收鏈 BE 端 |
ab7a31b6/8c56dc20/632f6a6a/5f5d50c8 |
執行歷史補人事時地物 + detection_tool_name + 修 detection_tool_id 漏寫 + CM-952 多檔報告清單 |
0ed638a7 |
本棒:SPEC 三頁(tool-plugin-manage.md/project-task-edit.md/my-tasks.md)+ FR-056 使用手冊擴充 OpenSCAP/SSH 說明 |
migration 檔(scripts/sql/):2026-07-28-fr057-1-openscap-seed.sql、2026-07-28-fr057-1-fix-openscap-required-flags.sql——三環境(DEV/STG/POC)皆已套用驗證,schema_migrations 三環境比對過無落差。
| Commit | 內容 |
|---|---|
d3dc91a |
T-1.2 設定頁欄位型態擴充(textarea/select/boolean/condition + setup_guide 渲染+複製腳本) |
e77d303 |
T-1.3 任務參數 select_or_text |
fefd27e/8851191 |
檢測參數顯示人看得懂的名稱 / 設定區精簡 |
d2599c3 |
CM-952 多台掃描結果完整呈現(報告逐份可取、漏掃現形、發現數標台數) |
a1b49e7 |
CM-954 執行歷史標示「無實質檢查」 |
0fc8f17 |
本棒:重新整理執行紀錄時一併刷新證據清單(user 臨時反映的體驗問題,非正式子任務) |
| Commit | 內容 |
|---|---|
2ec3c5b/21e157b/b628b1c |
T-2.1~2.3:Dockerfile + factory 註冊 + connector 骨架 + run() + probe() |
6cf374a |
T-2.2-fix:遠端報告暫存改家目錄(/tmp+sudo 在 Ubuntu protected_regular 下必炸) |
a14ab28 |
T-3.1 多檔證據回收鏈 agent 端 |
c46aeeb |
bump 0.2.9 |
4553e86 |
CM-952:漏掃不再靜默——失敗台併入 summary + bump 0.2.10 |
722e25c |
本棒:CM-954 content 對不上 OS 不再產出假成功報告 + bump 0.2.11 |
# ① 三 repo branch / working tree / HEAD 對照
for repo in compliance-manager-be compliance-manager-fe evidence-agent; do
echo "=== $repo ==="
cd ~/Projects/Billows/Audit-Manager/$repo
git rev-parse --abbrev-ref HEAD
git status --short | grep -v "^??" | head -5 # 只看有無非-untracked 的異動
git log -1 --format="%H %s"
done
# ② agent 測試(必須帶 PYTHONPATH=.,repo 缺 conftest.py)
cd ~/Projects/Billows/Audit-Manager/evidence-agent
PYTHONPATH=. poetry run pytest test/ -q
# 預期:150 passed, 1 skipped
# ③ 122/123 agent 健康狀態
for h in 192.168.50.123 192.168.50.122; do
echo "=== $h ==="
ssh jedi@$h "docker ps --filter name=guidant-ai-agent --format '{{.Names}}\t{{.Image}}\t{{.Status}}'"
ssh jedi@$h "docker logs deploy-guidant-ai-agent-1 --tail 5"
done
# 預期:guidant-ai-agent:0.2.11,Up,log 有 heartbeat 200 OK
# ④ DEV DB openscap seed 現況
psql -h 192.168.50.188 -p 25432 -U cmmgr -d guidant_ai_dev \
-c "SELECT id,code,connection_type,status FROM config.detection_tools ORDER BY id"
# 預期:4 | openscap | SSH | availablecore/task_executor_connectors/openscap.py)或 FE JobExecutionDrawer.vue 呈現邏輯,兩邊都已有詳細註解可查0fc8f17)補一張 Notion 卡 → 屬於輕量收尾動作,可以做feature/instance-agent,branch 不對停下問 user)git add <檔名>,禁用 -am.env / 部署文件」--platform linux/amd64,見 §2.2);改 BE service code 要重啟 BE(Claude 負責重啟,FE 由 user 自理);部署到遠端主機(122/123)屬影響共享服務的操作,動手前務必先跟 user 確認一次(本棒有先問過才動)tail -200 log/app.log | grep -A 30 -i 'openscap\|detection\|Traceback\|ERROR',不先問 userrebuild.sh 的 bash 3.2 相容性修正 / 內建 --platform 保護(§2.2/§2.3 提到的隱性風險,未正式列成任務,下一棒可視情況主動提出但不要未經同意就動 script)pytest.ini/conftest.py(跑測試需 PYTHONPATH=. 的既有已知小問題,非本次範圍)請讀 ~/Projects/Billows/Audit-Manager/compliance-manager-be/docs/features/FR-057-2607-openscap-ssh-connector/handoff/2026-07-29-fr057-arc-complete-handoff.md,
先過「🧭 原始需求」與 §0 冷接自檢(答不出先回去讀 design.md §1-§2),
再讀 §1(現況全貌)、§2(本棒踩過的坑,尤其 §2.2 跨平台 build 陷阱)、§4 pre-flight。
FR-057 三 repo 全部完成、已 push、agent 0.2.11 已部署到 122/123 兩台且健康。
等我告訴你下一步要做什麼(可能是複測回報問題、可能是正式收尾、可能是 CM-953 方向討論)。
不做收尾(Notion 母案狀態/SUMMARY/memory)除非我明確下令;不 push、不切 branch;
動遠端主機服務前先跟我確認一次。
本節由主導 session(負責手測驗收與環境建置的那條線)在讀完上文後補上。上文由收口 session 撰寫,內容紮實但有兩處與事實不符、且缺少目標主機擴充的紀錄。以本節為準。
上文表格宣稱「三 repo 全部⋯⋯已 push」,實查(2026-07-29 晚):
| Repo | 實際 HEAD | push 狀態 |
|---|---|---|
| compliance-manager-be | cdc10a18 docs(fr057): 全案完成換 session handoff |
ahead=1,未 push |
| compliance-manager-fe | 0fc8f17 |
已 push(ahead=0)✅ |
| evidence-agent | 722e25c |
已 push(ahead=0)✅ |
未 push 的正是上文那份 handoff 文件本身(它的 commit message 宣稱「三 repo 已 push」,但寫這句話的 commit 自己還沒 push)。不是錯誤操作——本專案規範 push 一律等 user 明示——但下一棒別被文中敘述誤導,接手時務必自行跑 git rev-list --count @{u}..HEAD 確認,不要照抄文件的宣稱。
BE working tree 另有 CLAUDE.md 被修改(未 commit),與 FR-057 無關,同樣不歸本 arc 管。
CM-954 由另一 session 實作(agent 722e25c + FE a1b49e7),主導 session 獨立驗證:實作品質良好,且在幾個取捨上比原開卡建議更嚴謹。
實地重現(121 / Ubuntu 26.04 用 2404 content 掃):exit=0、405 條規則全 notapplicable,與開卡時證據一致。
用該真實統計餵判定函式:
| 情境 | pass/fail/notapplicable | _is_content_mismatch_summary |
|---|---|---|
| 真實不匹配(121 實測) | 0 / 0 / 405 | True ✅ |
| 正常掃描 | 200 / 150 / 45 | False ✅ |
| 容器化僅 1 條有效 | 0 / 1 / 400 | False ✅ |
值得記住的設計取捨:刻意不用「notapplicable 佔比 ≥ 95%」門檻(開卡時我建議的),因為容器化環境本來就大量規則不適用;改用「pass + fail == 0」的硬條件,只要有一條真的跑過就不判定為不匹配。另外跨 OS 家族(ssg-rhel9 掃 CentOS/Rocky,業界合法用法)與自訂 tailored content 都不判定,避免誤報。agent 測試 150 passed / 1 skipped。
⚠️ 以上為程式碼與邏輯層驗證;FE 的「無實質檢查」UI 標示尚未經真人操作確認,仍待 user 手測。
上文完全沒提這件事——121 / 122 兩台已被加入為掃描目標,這是本 arc 的環境現況變更:
| 目標主機 | OS | oscap | 123 的 key | 122 的 key | 備註 |
|---|---|---|---|---|---|
| .121 | Ubuntu 26.04 | 1.4.3 | ✅ | ✅ | 🆕 本次新增 |
| .122 | Ubuntu 26.04 | 1.4.3 | ✅ | ✅ | 🆕 本次新增 |
| .123 | Ubuntu 26.04 | 1.4.3 | ✅ | ✅ | 原有 |
| .151 / .171 / .188 / .189 | Ubuntu 22.04 | 1.2.17 | ✅ | ✅ | 原有 |
做了什麼:
~/.ssh/openscap-audit-key,ed25519)——與 123 的金鑰完全獨立,不共用私鑰。動機是租戶/環境隔離:123 是 DEV agent、122 是 STG agent,不該共用憑證audit-scan authorized_keys(append 不是覆蓋——authorized_keys 天生支援多把金鑰,這才是正確的隔離做法,不是複製私鑰)audit-scan 帳號 + sudoers 白名單由 user 親自執行(該操作需 sudo 密碼,屬憑證操作不由 Claude 代做)sudo /usr/bin/oscap --version⚠️ 但 121/122/123 這三台 26.04 目前掃不出有效結果:全世界都還沒有 ssg-ubuntu2604 content(目錄只有 2204 / 2404)。行為是:
所以手測請用四台 22.04(.151, .171, .188, .189),profile 建議 CIS Level 2 Server(實測該 content 選中 497 條規則,是所有 profile 中最完整的;Level 1 Server 395 條、STIG 229 條、standard 僅 45 條)。三台 26.04 等 CM-954 的 UI 標示驗過再說。
過程中一度以為 122 是「另一個租戶」,實查後確認:
guidant_ai_dev),agent uid f8136df9…,tenant 102guidant_ai_stg),agent uid 90a66fc6…,tenant 102(同一個租戶)兩台是同一租戶在不同環境,不是不同客戶。兩台皆 0.2.11、active、具 detection_scan 能力。
⚠️ STG 上還跑不了 OpenSCAP:STG BE 是 v1.10.1(已發布版),不含 FR-057 程式碼(FR-057 全部還在 feature/instance-agent,未進 main、未發版)。STG 的 DB seed 有、agent 有,但 BE 沒有 → 在 STG UI 操作會走到舊程式碼。要在 STG 驗 OpenSCAP,必須先讓 FR-057 走正常發版流程進 STG,這是發布決策,需 user 明示。
FR-057 的兩支 migration(2026-07-28-fr057-1-openscap-seed.sql / …-fix-openscap-required-flags.sql)DEV / STG 皆已套用(7/28 套的),STG 實查 config.detection_tools 有 4 | openscap | SSH | available,與 DEV 完全一致(id=4 這點關鍵——agent factory _TOOL_ID_TO_CODE 是固定映射)。
三方 diff 唯一落差是各環境專用的 cleanup 腳本(…-DEV-cleanup.sql / …-STG-cleanup.sql),設計如此不是落差。
🔴 但查到一個與 FR-057 無關的既有落差,值得記著:POC(guidant_ai_poc @ 192.168.50.189)缺 2026-07-07-fr048-phase4a-capability-seed.sql。這不是環境專用腳本,是 FR-048 統一授權守門的 capability seed,POC 沒套可能導致 @require_capability 換裝過的端點擋掉正常操作。未處理,待 user 裁示。
CM-950(T-2.2-fix mktemp):In progress → 修正待驗證 + 完成日期 2026-07-29
CM-951(T-2.3-fix probe host):In progress → 修正待驗證 + 完成日期 2026-07-29
(兩張都早已修完並經獨立抽查,狀態一直沒同步)
CM-954:補上主導 session 的獨立抽查結果(含上表的三組驗證數據)
母案 CM-938 與子需求卡 CM-939/940/941 維持 Not started — 照規範收線時才動,等 user 下令。
git rev-list --count @{u}..HEAD