# FR-059 檢測工具 Profile / Content 庫 — STG / POC 部署 Runbook

> **給部署執行者的自包含操作手冊**：照本文件由上到下依序執行即可，不需閱讀 design.md 或其他文件。
> 撰寫日期：2026-08-01｜對應 SUMMARY：[`handoff/2026-08-01-fr059-arc-SUMMARY.md`](./handoff/2026-08-01-fr059-arc-SUMMARY.md)

---

## 🔴 執行前必讀：環境鐵律

- **本 runbook 適用 STG / POC 上版。執行前必須取得決策者「當次」明確放行**——之前放行過別的版不算，這一次要有這一次的放行。
- **DEV（192.168.50.188 / guidant_ai_dev）已全部完成，勿在 DEV 重複執行本文件任何步驟。**
- STG 與 POC 是兩個獨立環境，**各自需要放行、各自完整走一遍本文件**。POC 等同 production（對外 demo / 客戶試玩），尤其謹慎。
- 執行中任何一步結果與本文件描述不符：**停下回報，不要自行補救或跳步**。

## 0. 前提（開始前逐項確認）

本功能跨三個 repo，部署前確認目標環境拿到的版本**包含以下 commit**（請開發者或版控管理者確認，不確定就問）：

| Repo | 版本要求 |
|------|---------|
| BE（compliance-manager-be） | 含 FR-059 全部 12 個 commit（`960abaec` 起至 `413ed121`；branch `feature/FR-058`） |
| FE（compliance-manager-fe） | 含 `7f06a3d`＋`78f8e07` 兩個 commit |
| agent（evidence-agent） | image 版本 **0.2.27** |

其他前置：

- 目標環境 DB 連線資訊（host / port / DB 名）見下表；**密碼一律查該環境部署文件或 BE 主機上的 `.env`（`DB_SECRET`），本文件不記載密碼**。
- BE migration 一律用 `cmmgr` 帳號執行（不是 `cm_app`）。
- 目標環境 DB 座標：

| 環境 | Host | Port | DB 名 |
|------|------|------|-------|
| STG | `192.168.50.188` | `25432` | `guidant_ai_stg` |
| POC | `192.168.50.189` | `25432` | `guidant_ai_poc` |

> ⚠️ port 是 `25432` 不是預設 5432，指令漏 `-p 25432` 會像連不上 / DB 不存在。

## 1. 執行順序總覽

```
① BE 程式碼更新（含 FR-059 commits，migration 檔與 seed script 都在裡面）
② migration fr059-1（表 + RLS + 權限）
③ migration fr059-2（capability + 角色授予）
④ migration fr059-3-detection-profile-menu-route（選單）
⑤ seed script（10 筆系統公版 profile）
⑥ migration fr059-3-param-schema-options-source（下拉切換到庫）★ 必須在 ⑤ 之後
⑦ agent 部署 0.2.27（cache 掛載點目錄要先建）
⑧ FE 部署新版
⑨ 部署後驗收 checklist
```

**⑤ 和 ⑥ 的順序不可對調**：⑥ 會把任務抽屜下拉的靜態選項整批拿掉、改成讀 Profile 庫；若庫裡還沒有 ⑤ 灌的資料，下拉會**直接空掉**，使用者立刻受影響。照「先 seed、後切換」的順序執行，切換瞬間庫裡已有完整資料，使用者完全無感。

## 2. BE migration（四支，依序執行）

四支檔案都在 BE repo 的 `scripts/sql/` 底下：

| 順序 | 檔名 | 內容 |
|------|------|------|
| 1 | `2026-08-01-fr059-1-detection-tool-profiles.sql` | 新表 `config.detection_tool_profiles`＋RLS＋GRANT |
| 2 | `2026-08-01-fr059-2-detection-profile-capability.sql` | 4 個 capability＋角色授予 |
| 3 | `2026-08-01-fr059-3-detection-profile-menu-route.sql` | 側邊選單「掃描設定檔管理」登記 |
| 4 | `2026-08-01-fr059-3-param-schema-options-source.sql` | param_schema 升版（下拉切到庫）——**留到第 5 步之後才執行** |

> ⚠️ 第 3、4 支檔名編號同為 `fr059-3`（歷史命名，不影響執行）；**執行順序一律照本清單**，第 4 支必須排在 seed（第 3 節）之後——原因見上方第 1 節。
> 兩支的內容不同：`-menu-route` 是選單、`-param-schema-options-source` 是下拉切換，看檔名主體區分。

指令模板（在能連到目標 DB 的機器上、BE repo 根目錄執行；`<host>` / `<db>` 依第 0 節的表帶入）：

```bash
psql -h <host> -p 25432 -U cmmgr -d <db> --single-transaction -v ON_ERROR_STOP=1 \
  -f scripts/sql/2026-08-01-fr059-1-detection-tool-profiles.sql
```

依序換檔名執行第 1〜3 支（第 4 支先跳過，等第 3 節 seed 完成後再回來跑）。

**每支跑完確認 migration 有落帳**：

```bash
psql -h <host> -p 25432 -U cmmgr -d <db> \
  -c "SELECT filename FROM public.schema_migrations WHERE filename LIKE '2026-08-01-fr059%' ORDER BY filename;"
```

跑完第 1〜3 支應看到 3 列；第 4 支跑完後共 4 列。少列＝該支沒成功，停下回報。

## 3. Seed script（10 筆系統公版 profile）

**在目標環境的 BE 主機上、以該環境的 `.env` 執行**（腳本讀 `.env` 的 `DB_HOST` / `DB_NAME` 決定寫進哪個 DB——務必確認 `.env` 指向的是你要部署的環境）。

### 3.1 環境防呆（必看）

腳本內建 D10 護欄：預設**只允許在 DEV 執行**。要在 STG / POC 執行，必須加 `--db-name <目標 DB 名>` 顯式確認——這個參數**不改變連線目標**（連線一律由 `.env` 決定），它的作用是要求執行者「逐字說出」自己要動哪個 DB，名稱與 `.env` 的 `DB_NAME` 不一致就拒絕執行。不需要修改腳本。

### 3.2 執行

先 dry-run 確認（只檢查不寫入；STG / POC 連 dry-run 也要帶 `--db-name`）：

```bash
# STG 為例（POC 用 guidant_ai_poc）
poetry run python scripts/seed_2026-08-01_fr059_detection_profiles.py --db-name guidant_ai_stg
```

輸出開頭會印 `DB : <db 名> @ <host>`——**核對這一行就是目標環境**，再實際執行：

```bash
poetry run python scripts/seed_2026-08-01_fr059_detection_profiles.py --apply --db-name guidant_ai_stg
```

行為說明：

- 走**與使用者相同的上傳管線**（真 HTTP 端點）建 10 筆 SYSTEM 公版：8 支 TWGCB（file 型，綁 GCB 工具）＋2 條 dev-sec（url 型，綁 CINC 工具）。
- **可重跑**：已存在的同名 profile 會印 `[skip]` 跳過，不會疊加、不會報錯。
- 腳本以平台管理員帳號登入（預設帳號 `admin`，密碼預設值寫在腳本內；若目標環境的管理員帳密不同，用環境變數 `FR059_SEED_USER` / `FR059_SEED_PASS` 覆寫，**不要把密碼改寫進腳本**）。
- 結尾自帶零回歸驗證：印出 `[gcb] menu 8 筆…` / `[inspec] menu 2 筆…` 即成功。

期望結果：`結果：建立 10｜跳過 0｜失敗 0`（重跑時建立與跳過數互補）。**有任何 `[fail]`：停下回報，不要接著跑第 4 支 migration。**

### 3.3 回頭跑第 4 支 migration

seed 成功後，回到第 2 節的指令模板執行：

```bash
psql -h <host> -p 25432 -U cmmgr -d <db> --single-transaction -v ON_ERROR_STOP=1 \
  -f scripts/sql/2026-08-01-fr059-3-param-schema-options-source.sql
```

並照 2 節末的查詢確認 `schema_migrations` 共 4 列。

## 4. Agent 部署（image 0.2.27）

在目標環境的 agent 主機（evidence-agent 的 `deploy/` 目錄）操作。image 取得方式二擇一：依既有流程重建 0.2.27，或從 DEV 主機 `docker save` / `docker load` 搬運（版本以 `0.2.27` 為準）。

### 4.1 ⚠️ 啟動前必做：建 cache 掛載點目錄

```bash
cd /opt/evidence-agent/deploy
mkdir -p content/cache
```

**少這一步容器起不來**，且錯誤訊息（`read-only file system`、指向 `/var/lib/docker/rootfs/...`）**完全看不出跟這個目錄有關**——這是 2026-08-01 首次部署實際踩到的坑。原因與完整說明見 evidence-agent repo `deploy/README.md` §6.1。若容器起不來且錯誤長那樣，先檢查這個目錄存不存在。

### 4.2 更新與啟動

compose 操作**必須指定 service 名**（不帶名的 `docker compose up -d` 會把同一 compose 檔裡的其他 service 一起 recreate）：

```bash
docker compose up -d guidant-ai-agent
```

### 4.3 部署後驗證

- 平台管理頁（檢測工具 / agent 管理處）該 agent **版號顯示 0.2.27**。
- agent **心跳正常**（管理頁上線狀態，或等一個心跳週期約 5 分鐘後確認最後心跳時間有更新）。

## 5. FE 部署

照 FE 既有部署流程出新版即可（版本需含第 0 節列的兩個 commit）。本功能無 FE 端額外設定。

## 6. 部署後驗收 checklist（非開發者可執行）

以該環境的系統管理員帳號登入平台，逐項打勾：

- [ ] 側邊選單「系統管理」群組下出現新頁「**掃描設定檔管理**」（位置在檢測工具管理附近）
- [ ] 進入該頁，列表看到 **10 筆**系統公版：8 筆 TWGCB（名稱如「TWGCB-01-007 Windows Server 2016 v1.3（540 項自動檢查）」）＋2 筆 dev-sec 基準
- [ ] 開任一專案的 **GCB** 檢測任務抽屜，profile 下拉有 **8 個選項**，名稱與改版前完全一致（TWGCB 系列）
- [ ] 開 **CINC Auditor** 檢測任務抽屜，profile 下拉有 **2 個選項**（dev-sec Linux / Windows 基準）
- [ ] 下拉欄位仍可自行手動輸入文字（手填能力保留）
- [ ] （若該環境有可掃目標主機）從下拉選一支 TWGCB profile 派一次 GCB 掃描 → 執行成功、產出報告

任何一項不符：停下回報，附上該項的畫面截圖。

## 7. 回滾要點

| 對象 | 回滾方式 | 說明 |
|------|---------|------|
| 下拉切換（第 4 支 migration） | param_schema 有版本化：舊版（v1，靜態 options）以 `is_current=FALSE` 完整保留在 DB。把 inspec / gcb 兩工具的 param_schema **v2 設 `is_current=FALSE`、v1 設回 `TRUE`** 即恢復改版前的靜態下拉 | 這是最主要的回滾開關——切回後使用者看到的下拉與改版前一模一樣 |
| agent | 退回前一版 image（compose 指定舊版 tag 後 `docker compose up -d guidant-ai-agent`） | 舊機制的 `/data/content` 掛載仍在（過渡期兩路並存），舊行為不受影響 |
| FE | 照 FE 既有流程退回前一版 | — |
| 新表與 seed 資料 | **留著無害，不需回滾**——`config.detection_tool_profiles` 表與 10 筆公版資料在下拉切回靜態後不會被任何頁面誤用（管理頁選單可視需要停用） | 資料留存也讓下次重新上版免重跑 seed |

回滾操作若涉及直接改 DB（第一列），請由開發者執行或在開發者指導下執行，執行前先備份該兩列資料。
