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_versionimport_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_mappingao_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_framestemplate_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_queuescripts/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。