# FR-038 Q1 — 準備期 per-AO My Jobs（workflow 設定 + per-AO job 生成）設計

> 狀態：設計定稿（2026-06-15，與 user 互動拍板）。本檔為 brainstorm 收斂結果；依 user 指示
> **跳過 writing-plans，直接開發**。
> 上游：requirement-analysis §4.3b（Q1）/ design §4.4 / 本 arc handoff §2 trap 3（Q1 卡點）。

---

## 1. 問題

「任務執行 / My Jobs」= 受評公司在**稽核前（Phase 1-2）準備 SSP / 收證據**的工作。舊模型把
workflow 綁在 AO（`profile_assessment_workflow_mapping` → catalog_control_assessment），
專案成立 per AP task 起 workflow；v2 重建時該設定 DROP、依賴 v1 entity 故 dark。新資源庫
`module_frames.template_uid` 全 NULL、`vw_user_job_queue` 的 control_* 留 NULL 佔位。

**要補**：新模型「workflow 設定掛哪 + 如何在專案成立時為每個 AO 生成準備 job」。

## 2. 已驗證的地基（2026-06-15 真資料）

- 框架匯入（`framework_app_service.import_framework_version` → `import_catalog_from_pdf`）
  正確產出 catalog 樹含 `catalog_control_parts`：實測 CMMC L1 = 17 控制 / **59 assessment-objective**
  / 273 assessment-method / 17 statement。
- **AO = 只算 `assessment-objective` part**（part_id 含控制前綴，如 `AC.L1-3.1.1_obj.2`）。
  assessment-method/objects 不是判定/準備單位。B5 AR 矩陣已修成只取 assessment-objective
  （commit `a971e81b`，否則超量 5.6x）。
- 專案 catalog clone（B2 邊界②）**保留 AO parts**（已驗）。
- AO 是「專案自有」資料（clone 來的），可掛 job。

## 3. 決策（locked）

| # | 決策 | 值 |
|---|------|----|
| D-Q1-1 | 綁定粒度 | **per-AO**（每個 assessment-objective part 一個準備 job）|
| D-Q1-2 | AO 定義 | 只算 `assessment-objective` part（與 B5 共用）|
| D-Q1-3 | 設定粒度 | **A1：單一預設 template / 資源庫**（用現成 `module_frames.template_uid`）|
| D-Q1-4 | template | 先 seed 一個**最簡「收證據」BPMN template**（單一 user task）|
| D-Q1-5 | 生成時機 | **同步**：專案成立 @transaction 內，per-AO 當場建 job（非背景）|
| D-Q1-6 | 執行綁定 | `workflow_execution_control_mapping` 加 `ao_part_id`（job ↔ AO 精準對上）|
| D-Q1-7 | 指派 | `task_assignees`：建立時**不指派**，PM 之後指派（user+role）|

## 4. 資料模型

- **設定**：`module_frames.template_uid`（已存在，NULL）→ 存「收證據」master workflow template uid。
- **「收證據」master template**：落 `compliance.workflow_templates`（單一 user task BPMN）。
  因 FE 設定 UI 屬 Wave 3 → 本期用 **seed**（建 template + 把現有 resource-library `module_frames`
  的 `template_uid` 指過去）。
- **執行綁定**：`compliance.workflow_execution_control_mapping` 加欄 `ao_part_id varchar`（nullable
  soft-ref → 專案 catalog 的 `catalog_control_parts.part_id`）。原 (workflow_execution_id,
  version_id, control_id) 保留；ao_part_id 讓 per-AO 精準。migration（主專案表）+ entity/model/mapper。
- **指派**：`task_assignees`（既有）綁 job ↔ user+role；建立時不寫（unassigned）。

## 5. 流程（專案成立時，sync）

`project_start_app_service.start_project`，在 `_init_ssp_control_implementations` 之後：
1. 解析資源庫 `module_frames.template_uid`（無 → 跳過，記 log，不擋專案成立）。
2. clone「收證據」master template → snapshot（per 專案一份）。
3. 對每個 in-scope 控制的每個 **assessment-objective part**（專案 catalog clone）→ 建一個準備 job：
   - 起 / 共用 workflow_execution（**輕量建法**：避免每 AO 重 parse BPMN；prep 階段共用少量
     workflow_execution + per-AO `job_executions` 批次 insert）。
   - 寫 `workflow_execution_control_mapping(workflow_execution_id, version_id, control_id, ao_part_id)`。
4. 與 AP / 稽核輪次無關（純準備期）。

> **量考量**：per-AO L2 ~320。同步建，實作走輕量批次 insert，並以真 L2 量測專案成立耗時；
> 若 >數秒過慢，follow-up 改背景（本期 YAGNI，不預先做）。

## 6. My Jobs view

`vw_user_job_queue`（`scripts/sql/participant_role_migration.sql`）的 control_* rebind：
從舊 `oscal.assessment_plan_controls` join 改接**專案 catalog 的 control + AO（part_id）**
（經 `workflow_execution_control_mapping.ao_part_id` / `control_id`）。FE 畫面不動。

## 7. Scope / 非目標

- **本期做（BE）**：seed 收證據 template、`ao_part_id` 欄 + 綁定、project_start per-AO job 生成、
  vw_user_job_queue rebind、真資料 smoke。
- **非目標**：FE 資源庫 workflow 設定畫面（Wave 3）；job 自動指派（PM 手動）；背景建（follow-up）；
  per-control / per-AO 差異化 template（A2/A3，未來 override）；ISO/NIST。

## 8. 驗收

專案成立（用 catalog 729 真 L1 資源庫）→ 每個 assessment-objective part 各一準備 job →
`vw_user_job_queue` 能查到該 project 的 job（含 control + AO）→ 指派後 My Jobs 顯示。
BOOT OK + pytest 持平 baseline。
