FR-060 中繼交接 — 討論稿已產出,等 D1–D18 拍板後落地 design.md

項目 內容
緣由 前一棒(本 session)走完 big-feature-workflow Step 1(五支平行探脈)+ Step 2(HTML 討論稿產出並發 Artifact)。接手棒次負責:協助決策者逐項拍板 D1–D18 → Step 3 落地 design.md → Step 4 Notion 母子 case 樹 → Step 5 交接 prompt
Branch feature/e2e-env-build不要切 branch,發現不對停下問決策者)
角色定位 分析決策 / 協調者 —— 實作與文件產出一律外包(派 subagent 或開 case),本體只做需求釐清、決策討論、拍板、派工、抽查
接手前必讀 本文件 §0 讀序(討論稿 Artifact 為主,一次讀完)
預估時間 拍板討論 1–2 小時(視決策者節奏);Step 3–5 各派一支 subagent
現況 Step 2 完成,等拍板。討論稿已發 Artifact,尚未 commit(docs/features/FR-060-.../ 整個資料夾是 untracked)

🧭 原始需求 / WHY(置頂,先懂這個再碰任何東西)

決策者原話(2026-08-03)

「目前只有項目,user 完全不知道這個東西會驗證什麼,我怎麼知道我要選什麼?哪些基準可以參考,我可以先請負責人去判斷、提前先處理,而不是等報告出來才去處理。」

這件事在解什麼

FR-059 做完了「掃描設定檔管理」(/plugin/detection-profile-manage)—— 把 profile 打包檔收進平台庫、agent 拉檔執行。但平台把 profile 當成 opaque binary,完全不理解內容:使用者在管理頁與任務下拉看到的只有一個名字(如「TWGCB-01-014 Ubuntu 22.04 LTS v1.2」),不知道它會驗什麼、驗幾項、哪些項目其實跑不出結果。

一個支撐急迫性的實測數字:TWGCB-01-014 共 234 條控制項,其中 199 條是人工待判項impact 0.0,跑起來是 skip),實際自動檢查只有 35 條。使用者現在完全看不到這件事 —— 他選了、掃了、拿到一份 85% 是 skip 的報告,才發現。

決策者要的是提前判斷:選之前就看得到內容,可以先請負責人評估、先處理,而不是等報告出來才補救。

本案範圍(三件事)

  1. 瀏覽 profile 的檢驗內容(核心需求)
  2. 修改基本資料含改名 —— 租戶只能改自己的,公版限 root(決策者原話:「打錯字就只能砍掉重建,很奇怪」)
  3. 分類體系 —— 決策者指出「CINC 連瀏覽器都有,我不知道還有什麼可以透過他去掃描」,profile 一多下拉會很長、會選錯

為什麼一個「瀏覽功能」要拆資料表

決策者在討論過程中明確要求:「你要拿出你專業設計師的模式,而不是每次都用最快達到要求的模式把功能做出來,底層設計很重要。

技術上的必然性:現在 config.detection_tool_profiles 是單表,版本鏈靠 (detection_tool_id, tenant_id, name) 三值推斷 —— 拿 name 當身分,這正是改名改不動的根因;而分類三軸(標的類型/產品/基準體系)是「這支 profile 是什麼」的屬性,不是「這一版是什麼」的屬性,存在單表會每版重複、版更漏帶就漂移。

而且現在是最便宜的時機:13 筆資料、FR-059 上線才兩天、沒有租戶真的在用。等 FR-061(選用範圍/豁免)把設定綁上去再拆,成本是現在的好幾倍。

本棒在大圖的位置

FR-060(本案)
 .1 資料模型重構    主從拆表 + controls 表 + 13 筆搬遷 + RLS 移位 + 派工鏈兩處破口修補
 .2 分類體系 + 基本資料編輯(含改名)
 .3 控制項抽取 + 瀏覽    BE 裝 CINC + 非同步抽取管線 + 詳細頁
 ──────  以上第一批:全在管理面,不碰 agent、不動派工參數
FR-061(下一案,本案只定模型契約不做實作)
 .4 選用範圍 + 豁免(--controls / --tags / --waiver-file)
 .5 人工判定那 199 條 / 自訂檢查項(wrapper profile)

切線在管理面/執行面之間:.1–.3 最壞情況是詳細頁少一塊,既有掃描零影響;.4 起動掃描參數,改錯會讓結果不對(GRC 系統裡使用者以為自己合規是嚴重問題)。


§0 接手讀序

🔒 第一批:先懂需求(硬 gate,讀完才准往下)

  1. 本文件的「🧭 原始需求 / WHY」段(上面那節,全讀)
  2. 討論稿 Artifact:https://claude.ai/code/artifact/223cf4dd-72c7-43a7-8215-6067b02e601e (1,003 行、18 項 D、4 張 mermaid、五支探脈實測結果。這是本棒的主要工作對象,必須全讀) 本機檔:docs/features/FR-060-2608-detection-profile-content-management/discussion.html

第二批:前作脈絡(按需查,不必全讀)

  1. docs/features/FR-059-2608-detection-profile-library/design.md §3 決策表(P1–P7 + D1–D10)—— 本案疊在它上面,D2(profile:<uid> 前綴契約)、P4(版本模型)、D8(驗證深度界線)三項與本案直接相關
  2. docs/specs/current/system-admin/detection-profile-manage.md §12 邊界情況與已知坑(13 條)—— 現況坑清單,其中坑 2「detection-profile.update capability 是預留孤兒」正是本案 D8 要消費的
  3. .claude/skills/big-feature-workflow/SKILL.md —— 本棒要接著跑 Step 3–5

冷接自檢 4 問(答不出來回去讀,別開始派工)

  1. 決策者要「提前判斷」是什麼意思?他現在看不到什麼?
  2. 為什麼一個「瀏覽功能」需要拆資料表?(要能講出 name 當身分、分類屬性歸屬兩個理由)
  3. FR-060 與 FR-061 的界線在哪?為什麼這樣切?
  4. profile:<uid> 這個契約為什麼不能動?動了會壞什麼?

§1 現況:已完成什麼

Step 1 平行探脈(五支全完成,全唯讀)

# 範圍 關鍵產出
1 BE 拆表影響面 全部讀寫點盤點、四個自訂查詢改寫方向、fork/copy 語意重想、派工鏈兩處破口
2 frameworks 主從前例 完整實作模式;發現該前例的 main_version_id FK 已被官方認錯廢棄
3 inspec json 實跑 真實輸出形狀、體積與耗時、錯誤形狀、推翻「必須解壓成目錄」的假設
4 FE 現況 管理頁改動量、PrimeVue 分組能力實查、控制項清單可複用元件
5 migration / RLS 13 筆資料、RLS 四段全文、遷移三段式路徑、發現 STG 已服役

Step 2 討論稿(完成並發布)

  • 檔案:docs/features/FR-060-2608-detection-profile-content-management/discussion.html(1,003 行)
  • Artifact:https://claude.ai/code/artifact/223cf4dd-72c7-43a7-8215-6067b02e601e
  • 內容:18 項 D(每項含「我的建議」+ 利弊 + 被排除方案)、2 項已拍板 callout、4 張 mermaid 圖
  • 抽查已過:4 張圖各自帶完整 %%{init:...}%% 單行、D1–D18 齊全、無憑證洩漏

§2 探脈推翻的四個假設(前一棒講錯過,接手不要重蹈)

這四項都是前一棒先講了、探脈才發現講錯的。接手時若看到舊說法(例如在對話摘要裡),以這裡為準:

錯誤說法 實測真相 影響
「當前版本用 FK 指標,不是布林旗標」 oscal.frameworksmain_version_id FK 已被官方認錯並事實廢棄(2026-06-16 改字串欄、列入待 DROP)。三個傷害:循環 FK 逼拆兩段 DDL/刪除流程被綁死/DB 保證不了唯一 應保留 FR-059 現行的 is_current 布林 + partial unique index
「拆表對派工鏈零影響」 兩處會壞_load_profile()is_active 守門(拆表後在主檔)→ AttributeError 或靜默失效(已停用 profile 照樣派得出去,無聲授權漏洞);_humanize_profile_param()getattr(profile,"name",None) → 通知信 profile 名稱靜默退化成 uuid,且現在沒有任何測試會抓到 需新增 get_version_with_profile(uid) 回主+從合成 entity
「CINC 吃目錄,必須解壓,與不落地驗收條件衝突」 CINC 直接吃 .tar.gz / .zip(實測 exit 0、234 條、輸出與讀目錄一致)。衝突根本不存在 —— T-1.3 禁的是「解壓成目錄樹」,不禁「把壓縮檔本身寫成臨時檔」 抽取管線設計大幅簡化
「FR-059 只在 DEV」 STG 已服役:STG(188 的 guidant_ai_stg)與 DEV 同為 125 筆 migration,config.detection_tool_profiles 存在且有 10 筆(全 SYSTEM 無 TENANT),RLS 四段齊全 拆表是要 rename 一張 STG 正在服役的表;且 STG 無 TENANT 資料 → 「STG 跑得順」不能當驗收

§3 已定案兩項(不要再拿出來討論)

① 抽取落點 = BE 裝 CINC

決策者 2026-08-03 明確選擇(看過實測數據後仍維持)。

  • 安裝:curl -fsSL https://omnitruck.cinc.sh/install.sh | bash -s -- -P cinc-auditor -v 7
  • 體積 275MB(其中 200MB 是用不到的 AWS/Azure/GCP SDK 與遠端 transport)
  • 三台部署機 + 每台開發機都要裝;收尾要在 docs/claude/host-dependencies.md 加第三項
  • ⚖️ 授權紅線:必須是 CINC Auditor(Apache 2.0),絕不可換官方 InSpec 6+ 商業 binary(需 Chef EULA);inspec-core gem 是 Chef 官方發布受 EULA 影響,同樣不可用
  • macOS binary 解析比照 LibreOffice 慣例(env var CINC_AUDITOR_CMD → PATH → 絕對路徑 fallback),不要硬編 /usr/bin/cinc-auditor
  • 被排除:派 agent 抽(BE 零主機依賴但要新增 agent 指令型別、依賴 agent 在線)

② 版本鎖定 = 鎖版 + 提示

任務綁版本 uid(現行行為,D2 契約零變動、10 筆既有綁定零轉換)。

但純鎖版有合規漏洞:TWGCB 發新版、排程任務無聲繼續掃舊版,使用者以為合規實際不是 —— 在 GRC 系統裡這是正確性問題不是 UX 瑕疵。故要配「此基準已有新版 vN,目前使用 v1」徽章 + 一鍵換版,換不換是使用者決定,但必須知情

拆表後「是不是現行版」就是主檔 current_version_id 一次比對,menu API 順手帶回,成本極低。BE 側留 FR-060;FE 徽章與一鍵換版若範圍太肥可移 FR-061(BE 先備好)。

被排除:跟隨現行版(同任務前後跑出不同結果、稽核無法回溯、破壞凍結契約 + 要轉換既有資料)。


§4 待辦:D1–D18 拍板(本棒主要工作)

18 項全在討論稿 §3,每項已含「我的建議」+ 利弊 + 被排除方案。接手要做的是陪決策者逐項確認,不是重新分析。

建議的拍板順序(前三項會牽動其他多項)

優先 D 項 為什麼先問
1 D1 主從欄位歸屬 定了之後 D2(當前版指標)、D3(從檔 RLS)、D15(is_active 放哪)大半跟著定
2 D5 分類三軸定義 決策者最核心的需求;enum 值域、「標的產品/基準體系」要不要合併都在這
3 D14 主列表 vs 版本歷史 決定 FE 重構範圍,也影響 D10(extraction_status 落點)
其餘 D2–D4、D6–D13、D15–D18 多為技術取捨,決策者沒異議就照建議走

三處最需要決策者注意的紅框(討論稿內已標)

  1. 人工待判項判準是 impact == 0.0 —— 用 tags.check_type == 'pending' 會漏 6 條(twgcb_01_014_0079~0084check_type: 'service' 但實為 impact 0.0 + 只有 skip)。impact 是 InSpec 原生語意,外來 profile 也一定有
  2. 派工鏈兩處破口(見 §2)—— 尤其 is_active 守門靜默失效屬無聲授權漏洞
  3. STG 已服役(見 §2)—— 且無 TENANT 資料,搬遷 SQL 在 STG 測不到租戶路徑、測不到 32/33 三欄 JOIN 陷阱

§5 拍板後的後續步驟(Step 3–5)

big-feature-workflow skill:

Step 3 落地 design.md(派 subagent)

  • 落點:docs/features/FR-060-2608-detection-profile-content-management/design.md
  • 結構照 FR-057(docs/features/FR-057-2607-openscap-ssh-connector/design.md):檔頭狀態列 → 變更紀錄表 → 需求背景與端到端流程 → 決策定案表 D1–D18(每項含定案理由與被排除方案)→ 現況接入點盤點 → 詳細設計 → 拆分表 → 端到端驗收
  • 必須包含 FR-061 模型契約段(討論稿 §4 已寫):豁免要能綁單條控制項、選用範圍綁主檔不綁版本、抽取欄位必須一次抽完整
  • docs/features/README.md FR 登記表加一列
  • commit(顯式 add),不 push

Step 4 Notion 母子 case 樹(派 subagent)

  • data source:collection://23c346da-4cd0-8041-955e-000bb6976dd2
  • 順序:母案 → 子需求 → 子任務(Case No 是 auto_increment,靠建立順序保證連號)
  • Properties:專案 CM/來源 雷門/作業人員 小弟/狀態 Not started/需求編號 FR-060(母案)或 FR-060.x(子卡)
  • 子任務卡內容要自足到新 session 不讀其他文件能開工
  • 格式範本:FR-057 母案 https://app.notion.com/p/3ab346da4cd081af9cfac78397f7acfb
  • 抽查:主 session 實際 fetch 母案 + 至少一張子任務卡,驗連號/關聯/properties/內容自足度

Step 5 交接 prompt(主 session 親自寫,不外包)

per 子需求一份可複製 code block,含實際 Case No + 必讀清單 + 關鍵約束 + 回寫規則 + 「停下等驗收」結尾。


§6 Pre-flight(接手必跑,全唯讀)

cd ~/Projects/Billows/Audit-Manager/compliance-manager-be

# ① branch 必須是 feature/e2e-env-build(不對就停下問決策者,不要自己切)
git branch --show-current

# ② FR-060 資料夾狀態(預期:整個資料夾 untracked,尚未 commit)
git status --short docs/features/FR-060-2608-detection-profile-content-management/

# ③ 討論稿存在且完整(預期 1003 行、4 張 mermaid、D1-D18)
wc -l docs/features/FR-060-2608-detection-profile-content-management/discussion.html
grep -c 'class="mermaid"' docs/features/FR-060-2608-detection-profile-content-management/discussion.html
grep -o 'D1[0-8]\|D[1-9][^0-9]' docs/features/FR-060-2608-detection-profile-content-management/discussion.html | grep -o 'D[0-9]*' | sort -u -V | tr '\n' ' '

# ④ FR 編號未被佔用(預期:README 最大整數號仍是 059)
grep -c "FR-060" docs/features/README.md

DB 唯讀盤點(密碼取自 .envDB_SECRET不要寫進任何檔案):

export PGPASSWORD=$(python3 -c "
import json
for line in open('.env'):
    line=line.strip()
    if line.startswith('DB_SECRET='):
        print(json.loads(line.split('=',1)[1])['rds_master_password']); break
")
# 預期 13 筆(10 SYSTEM / 3 TENANT),全部 version=1
psql -h 192.168.50.188 -p 25432 -U cmmgr -d guidant_ai_dev -c \
  "SELECT scope, count(*) FROM config.detection_tool_profiles GROUP BY scope;"

§7 行為規範重要提醒

  • 🔴 接手側紀律:讀完 §0 + 跑完 §6 pre-flight 後完全停下,回報「①自檢 4 問答案 ②現況盤點 ③待辦已就緒等發令」即止。本文件的「待辦」與「後續步驟」都只是建議清單,不是執行授權 —— 派 subagent、跑測試、改檔、commit 全都要決策者當次明確下令
  • 🔴 角色定位:本棒是分析決策/協調者 —— 實作與文件產出一律外包(派 subagent 或開 case),本體只做需求釐清、決策討論、拍板、派工、抽查。判準是「這是決策,還是產出/執行?」
  • 🔴 環境異動鐵律:開發期只套 DEV。STG(已服役 + 10 筆真資料)與 POC(未查、等同 production)都必須等決策者明示放行。拆表 migration 比加欄位危險一個量級 —— 它會 rename 掉一張 STG 正在服役的表
  • 派 subagent 一律用 1M context model(不帶 model override)
  • 顯式 git add 檔名,禁用 -am不 push(永遠等決策者明示);不切 branch
  • 憑證禁入版控(密碼一律寫「請查 .env」)
  • 不要晶晶體(中英夾雜);不用「速贏」這個詞
  • 收尾動作等命令:SPEC / SUMMARY / memory / Notion 回寫一律等決策者明確下令

§8 不在本期 scope(不要順手做)

項目 為什麼不做
HTML 轉換機制/討論稿改 md 🔴 已切成獨立案 CM-1049https://app.notion.com/p/3b1346da4cd081b48d09e80c3f5389fb),決策者會另開專門 session 處理。本棒完全不碰 —— 不要自己去改 render_html.py、不要研究 pandoc、不要動 big-feature-workflow skill 的產出定義。若需要產 HTML 文件,照現行方式(手刻 + 分段寫入)即可
FR-061 的實作(選用範圍/豁免/人工判定/自訂項) 本案只寫模型契約,不做實作。形狀應由 .1–.3 上線後的實際使用決定
既有手刻 html 回頭轉 屬 CM-1049 範圍
profile 內容線上編輯 與 InSpec 設計哲學逆行(上游不可變、疊加物獨立),已在討論過程排除
順手修 FR-059 的其他坑 spec §12 有 13 條坑,只處理與本案直接相關的(坑 2 update capability 孤兒、坑 4 停用降 is_current)

§9 前一棒的產出與 commit 狀態

本 session 沒有為 FR-060 做任何 commit —— docs/features/FR-060-2608-detection-profile-content-management/ 整個資料夾是 untracked。

產出 狀態
discussion.html(1,003 行) 已寫入、已發 Artifact、未 commit
本交接文件 已寫入、未 commit
CM-1049(HTML 轉換另案) 已建卡,內容自足

工作 branch 最近三個 commit(與 FR-060 無關,是前面別條線的):

1d8d8b6c fix(detection-profile): 停用後無法以同名再建(CM-1047)
13a3720b docs(handoff): 首腦中繼交接——E2E 測案 arc 現況與三張待派 case
6feaa0ab docs(e2e): 190 部署真 agent 方案(CM-1048)+ 凌晨驗收巡檢報告

注意 1d8d8b6c 是 FR-059 的 bug 修復(停用後同名無法再建),與本案 D15(is_active 歸屬)相關 —— 拆表後那個 bug 的修法可能要重新檢視。


§10 給 fresh session 的超短 prompt

接手 FR-060(檢測 Profile 內容管理)。

先讀交接文件:
docs/features/FR-060-2608-detection-profile-content-management/handoff/2026-08-03-fr060-discussion-to-design-handoff.md

照它的 §0 讀序走:先讀「🧭 原始需求/WHY」段,再全讀討論稿 Artifact
https://claude.ai/code/artifact/223cf4dd-72c7-43a7-8215-6067b02e601e
(1,003 行、18 項待決策、4 張圖),然後答 §0 末的冷接自檢 4 問。

答完跑 §6 pre-flight(全唯讀)。

⚠️ HTML 轉換機制已切成獨立案 CM-1049 由別的 session 處理,你不要碰
(不改 render_html.py、不研究 pandoc、不動 skill 產出定義)。

讀取與盤點完成後不做任何事——不派工、不跑測試、不改檔,
回報「自檢答案 + 現況盤點 + 待辦已就緒」後等我下指令才開始作業。