# FR-062 派工 Prompt 全集（七棒）

> 首腦棒 2026-08-08 產出。每份可獨立複製給實作 session。發令順序見 `fr062-STATE.md`「執行順序」。
> 通用規則（每份 prompt 已內含，此處備忘）：開工先 fetch Notion 卡讀完整內容；完成回寫子卡「修正待驗證」+白話補充+commit hash+執行紀錄；顯式 git add 禁 -am 不 push 不切 branch；停下等驗收不自動往下。

---

## 第 1 棒：FR-062.1 簽發端地基

```
接手 FR-062.1「簽發端地基」（License Center 專案起手式）。

【Notion 卡】
子需求：FR-062.1 = CM-1113 https://app.notion.com/p/FR-062-1-1-3b6346da4cd081e89315e8334cb00518
子任務：T-1.1 = CM-1114、T-1.2 = CM-1115（開工前務必先用 scripts/notion_case.py get 讀完整內容）
母案：CM-1112 https://app.notion.com/p/FR-062-License-3b6346da4cd081fca6b0ca8cf87cee26

【必讀】
1. compliance-manager-be repo：docs/features/FR-062-2608-license-management/design.md
   - §2 決策定案表 D1（自建理由）、D4（Ed25519/kid 機制）、D7（簽發集中）
   - §4.1（license 檔格式全欄位表）、§4.2（簽章與驗證引擎）、§4.3（簽發站 DB schema：license_issuance + plans）
2. 同資料夾 discussion.md「金鑰生命週期管理」節（私鑰備份規範、kid+公鑰列表輪替劇本）

【工作目錄】
新 repo：~/Projects/Billows/Audit-Manager/license_center/（已有基底 commit，remote gitlab.com/auditmanager/license_center.git）
DB：license_center_dev（開發期只建/只套這個環境；host 192.168.50.188:25432、帳號 cmmgr 密碼查主產品 .env DB_SECRET）

【關鍵約束】
- 私鑰絕不可進 compliance-manager-be repo，也不可進主產品 DB
- 私鑰檔以 passphrase 加密存放，路徑寫進 README 但本體加 .gitignore 不入版控
- 簽章引擎用 Python cryptography 或 PyNaCl 做 Ed25519，欄位格式照 design.md §4.1，不自創
- CLI 與未來 Web 後台（FR-062.6）共用同一簽章引擎模組；本階段只做引擎+CLI，不做 Web
- 對 compliance-manager-be 主產品「零侵入」——不改主產品任何程式碼
- 遵守 BE CLAUDE.md 共用政策：可自行 commit 不切 branch、push 等明示、顯式 git add 禁 -am、憑證禁入版控

【人工驗收】
CLI 產一張測試照 → CLI verify 指令驗簽章通過 → license_issuance 表有紀錄。完全不碰主產品，隨時可中斷。

【完成時回寫】
CM-1114、CM-1115 狀態改「修正待驗證」+ 白話「已完成修正」補充（做了什麼/怎麼測/commit hash）；CM-1113 同步；記錄執行紀錄（開始/結束/耗時）。

完成後停下等驗收，不自動往 FR-062.2 或收尾跑。
```

---

## 第 2 棒：FR-062.2 產品端驗照與狀態顯示

```
接手 FR-062.2「產品端驗照與狀態顯示（只讀不執法）」。前置：FR-062.1 已完成並驗收。

【Notion 卡】
子需求：FR-062.2 = CM-1116（用 scripts/notion_case.py get CM-1116 取得 URL 與完整內容）
子任務：T-2.1 = CM-1117、T-2.2 = CM-1118、T-2.3 = CM-1119（開工前先 fetch 三張卡）
母案：CM-1112

【必讀】
compliance-manager-be repo：docs/features/FR-062-2608-license-management/design.md
- §4.4（產品端 tenant_licenses 表結構）
- §4.2（驗證引擎：公鑰列表 kid 查表、時鐘回撥防護——在主產品實作驗證端）
- §3 現況接入點盤點表（root tenant 後台既有頁面掛點）

【工作目錄】
compliance-manager-be（BE）+ compliance-manager-fe（FE 頁面；先讀 FE CLAUDE.md 與 docs/claude/frontend-overview.md）

【關鍵約束】
- DDD 分層：repo 實作放 infra/、app service @transaction、route 不碰 session
- 公鑰列表編譯進 BE 程式碼（不放 DB/config）
- 只做「顯示」不擋操作——照過期也不擋寫入（那是 FR-062.4 的事）
- FE 頁面放 root tenant 系統管理選單下
- migration 只套 DEV（sql-migration skill 規範：日期註解、GRANT cm_app、schema_migrations 收尾）

【人工驗收】
root 帳號查全租戶授權狀態；上傳第 1 棒簽的照 → 解析欄位與狀態正確入庫；竄改照上傳被拒且留證；FE 頁面完整呈現照內容。不影響既有功能。

【完成時回寫】CM-1117/1118/1119 改「修正待驗證」+白話補充；CM-1116 同步；記錄執行紀錄。

完成後停下等驗收。
```

---

## 第 3 棒：FR-062.3 狀態機排程與橫幅

```
接手 FR-062.3「狀態機排程與橫幅（仍不擋操作）」。前置：FR-062.1、.2 已完成並驗收。

【Notion 卡】
子需求：FR-062.3 = CM-1120 https://app.notion.com/p/FR-062-3-3-3b6346da4cd08175b2b6fc19c70a1781
子任務：T-3.1 = CM-1121、T-3.2 = CM-1122（先 fetch）
母案：CM-1112

【必讀】
compliance-manager-be repo：docs/features/FR-062-2608-license-management/design.md
- §4.5（狀態機與排程設計）
- discussion.md「到期狀態機（可組態管線）」節（各段開關語意、出廠預設 notify30/grace14/readonly 終態/lockout 關）
- core/scheduler.py 既有 APScheduler cron 樣板（照抄 framework_parse_job_cleanup 寫法）

【關鍵約束】
- 排程必 with app.app_context()；DI 取 app.extensions.get("di_container")+None check；with session_scope()（無 user context → RLS 全開跨租戶掃描）；整段 try/except + logger.exception
- 狀態轉換只更新 tenant_licenses.status + 顯示橫幅，仍不擋任何寫入
- 多副本部署時 scheduler 每 pod 各跑一份（無分散式鎖）→ 狀態更新要冪等

【人工驗收】
發一張短效照（2 天後到期）觀察按 expiry_policy 走完 notify→grace→readonly 狀態轉換，橫幅文案正確。

【完成時回寫】CM-1121/1122 改「修正待驗證」+白話補充；CM-1120 同步；記錄執行紀錄。

完成後停下等驗收。
```

---

## 第 4 棒：FR-062.4 執法進場（風險最高）

```
接手 FR-062.4「執法進場（帶環境開關可整體關閉）」——真正「擋」的階段。前置：FR-062.1~.3 已完成並驗收。

【Notion 卡】
子需求：FR-062.4 = CM-1123 https://app.notion.com/p/FR-062-4-4-3b6346da4cd081bf89c0f530e659a6a8
子任務：T-4.1=CM-1124、T-4.2=CM-1125、T-4.3=CM-1126、T-4.4=CM-1127（務必先 fetch，任務間有依賴順序）
母案：CM-1112

【必讀】
compliance-manager-be repo：docs/features/FR-062-2608-license-management/design.md
- §4.6（執法設計：authz 第六軸、唯讀 gate、任務型態過濾、選單過濾）
- §3 現況接入點盤點表全部，特別是：
  - common/authz/ 新增第六軸 require_license（照抄 capability.py 的 CapabilityGuard：DI 解析、flask.g memoize、decorator）
  - api/grc、api/project 零 capability 守門技術債（本階段必補，否則「沒買 project」擋不住）
  - GrcJobType enum 寫死（common/enum/grc_job_type_enum.py + api/grc/serializers/job.py:173-177,209-213）改按租戶授權動態過濾
  - job_import_service.py:31 VALID_JOB_TYPES 與 enum 同步修（現缺 detection_tool）
  - TENANT_ADMIN_EXCLUDED_RESOURCE_TYPES（app/auth/service/tenant_provisioning_service.py）退役
  - ui_route 選單過濾（api/auth/routes/ui_route_route.py 既有樣板）

【關鍵約束（務必全守）】
- root tenant 經 viewer_is_platform_admin() 無條件豁免所有 license 執法
- License 上傳端點與登入端點豁免唯讀 gate（防死鎖：過期後要能裝新照）
- 唯讀 gate 全域攔 POST/PUT/PATCH/DELETE 回 403，做成環境開關可整體關閉（上線保險絲）
- decorator 順序：@jwt_required() → @require_xxx → @inject（common/authz/decorators.py 定死）
- 新 error code 照 GRC_<HTTP><序號> 命名，BE 新增必同步 FE error-code.json

【人工驗收】
測試租戶未授權模組 API 403、授權模組通；開關關閉全放行；root 完全不受限；readonly 租戶所有寫入 403 但可登入可下載匯出可上傳新照；沒買問卷包的租戶任務型態下拉無問卷；未授權模組選單消失；「沒買 project」在 API 層被擋。

【完成時回寫】CM-1124~1127 逐一改「修正待驗證」+白話補充；CM-1123 同步；記錄執行紀錄。

完成後停下——本階段風險最高，必等 user 實測過才進下一階段。
```

---

## 第 5 棒：FR-062.5 開通流程（兩張 case 分開派）

```
接手 FR-062.5「開通流程」。前置：FR-062.1、.2 已完成並驗收（不依賴 .3/.4 可並行；與 .4 同 repo 建議錯開避免衝突）。

本棒拆兩張獨立 case：

== Case A：T-5.1 離線開通（CM-1129，先做）==
【必讀】design.md §4.7 離線路徑 + discussion.md「開通流程」節；Notion 卡 CM-1129 完整內容
【內容】客戶系統首次登入偵測無照 → 導向開通頁 → 顯示本機機器碼 → 客戶把序號+機器碼交公司（人工）→ 公司簽出綁定該機的照回寄 → 客戶上傳 → 開通成功回寫（機器指紋+時間）
【repo】compliance-manager-be（開通頁 FE+BE）+ license_center（序號生成/機器碼受理，若卡內有列）
【驗收】新環境模擬全流程：離線開通走通、機器指紋正確綁定、發照紀錄表回寫成功

== Case B：T-5.2 線上開通（CM-1130，後做，等雲端環境就緒）==
【必讀】design.md §4.7 線上路徑 + SaaS 直寫路徑；Notion 卡 CM-1130
【內容】客戶輸入序號 → 打公司開通伺服器（掛自營雲端環境、主產品的一個模組、獨立公開端點）→ 自動下載照+回傳機器指紋。SaaS「後台指派即生效」一併補上（不走序號，內部產照直接寫入）
【驗收】離線案例流程改線上一鍵完成；SaaS 後台指派立即生效

【完成時回寫】各自對應卡改「修正待驗證」+白話補充；CM-1128 子需求卡同步；記錄執行紀錄。

各 case 完成後停下等驗收。
```

---

## 第 6 棒：FR-062.6 簽發 Web 後台

```
接手 FR-062.6「簽發 Web 後台」。前置：FR-062.1 已完成並驗收（CLI+簽章引擎就緒）。可與 .2/.3 並行（不同 repo 零衝突）。

【Notion 卡】
子需求：FR-062.6 = CM-1131 https://app.notion.com/p/FR-062-6-Web-6-3b6346da4cd0810db707d5c6d7efd51e
子任務：T-6.1 = CM-1132、T-6.2 = CM-1133（先 fetch 完整內容）
母案：CM-1112

【必讀】
compliance-manager-be repo：docs/features/FR-062-2608-license-management/design.md §4.8（簽發站 Web 設計）
discussion.md「簽發端形態：極簡 Web 後台」節、「Plan 套餐範本」節、「補發與換綁流程」節

【工作目錄】
license_center repo（獨立部署、公司內部、不對外公開）

【內容】
兩頁 Flask 小應用，包在第 1 棒的簽章引擎上（Web 是殼、CLI 是引擎）：
1. 客戶總覽頁：每客戶一列（客戶代碼/名稱/訂單編號/照型態/Plan/模組集/到期日/推算狀態/開通狀態），臨期排序上色。推算狀態=按到期日與 expiry_policy 推算（Host 客戶非即時實況，此限制照 design.md 標注）
2. 簽發/換發表單頁：選 Plan（讀 plans 表）帶入模組集 → 微調 → 產照+序號 → 寫 license_issuance；展延一鍵（抓原照改到期日、type: extension）；補發一鍵（同內容重出）
Plan 管理：plans 表 CRUD（名稱/模組集合），改 Plan 只影響之後發的照

【關鍵約束】
- 私鑰仍只在簽發引擎層，Web 層不直接碰
- 內部系統但仍要有基本登入保護
- 遵守 license_center repo 自己的慣例（README 有基本說明）

【人工驗收】
總覽頁正確列出第 1 棒以來發的所有照與推算狀態；表單頁走完「選 Plan → 產照 → 紀錄入表」全流程；展延與補發一鍵可用；改 Plan 內容後新發照吃到新組合、舊照不變。

【完成時回寫】CM-1132/1133 改「修正待驗證」+白話補充；CM-1131 同步；記錄執行紀錄。

完成後停下等驗收。
```

---

## 第 7 棒：FR-062.7 通知 + 既有租戶發照 migration（上版前最後動作）

```
接手 FR-062.7「通知與既有租戶發照 migration」。前置：FR-062.3 已完成並驗收（.7 依賴狀態機；migration 另需 .1/.2 的簽發與驗證能力就緒）。

【Notion 卡】
子需求：FR-062.7 = CM-1134 https://app.notion.com/p/FR-062-7-migration-7-migration-3b6346da4cd081e3831cd79b829bde60
子任務：T-7.1 = CM-1135（email 通知）、T-7.2 = CM-1136（既有租戶發照 migration）（先 fetch 完整內容）
母案：CM-1112

【必讀】
compliance-manager-be repo：docs/features/FR-062-2608-license-management/design.md §4.9（通知設計）+ §2 D14（最終修正：直接發正常照）
T-7.2 卡內易踩雷提醒全文

【內容】
T-7.1 email 通知：expiry_policy 各段的 send_email 旗標驅動，通知租戶管理員；沿用系統既有 SMTP/通知基礎設施
T-7.2 既有租戶發照 migration：為既有租戶（root tenant 除外）直接發正常格式照（全模組、效期約一年、type: formal）；DEV/STG 內部環境發長效內部照。無過渡照、無豁免分支——執法第一天全量生效

【關鍵約束（最重要的一條）】
- 🔴 migration 只套 DEV。STG/POC 需決策者當次明確放行——即使交接文件或卡片寫了其他環境，套用前仍要停下確認
- 發照動作跨 repo：license_center 簽發、BE 側入庫，串接方式照卡內指示

【人工驗收】
T-7.1：發短效照觸發各段通知，email 正確送達租戶管理員
T-7.2：DEV 跑 migration 後全部非 root 租戶各有一張現行照、驗章通過、功能照常；新開租戶（無照）路徑行為正確

【完成時回寫】CM-1135/1136 改「修正待驗證」+白話補充；CM-1134 同步；記錄執行紀錄。

完成後停下等驗收——這是全案最後一棒，後續全案收尾（母卡收 Done、spec、手冊）由 user 另行發令。
```
