# 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`

### 第二批：前作脈絡（按需查，不必全讀）

3. `docs/features/FR-059-2608-detection-profile-library/design.md` **§3 決策表**（P1–P7 + D1–D10）—— 本案疊在它上面，D2（`profile:<uid>` 前綴契約）、P4（版本模型）、D8（驗證深度界線）三項與本案直接相關
4. `docs/specs/current/system-admin/detection-profile-manage.md` **§12 邊界情況與已知坑**（13 條）—— 現況坑清單，其中坑 2「`detection-profile.update` capability 是預留孤兒」正是本案 D8 要消費的
5. `.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.frameworks` 的 `main_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`~`0084` 標 `check_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（接手必跑，全唯讀）

```bash
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 唯讀盤點（密碼取自 `.env` 的 `DB_SECRET`，**不要寫進任何檔案**）：

```bash
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-1049**（https://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 產出定義）。

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