盤點 ②:專案成員角色制與流程綁定現況

2026-10-06 探脈產出,唯讀盤點,供討論稿引用。$S = .venv/lib/python3.11/site-packages。

1. 成員角色資料

  • 表與 ORM:表在 jedi_task_platform 套件內,主專案沒有 model。五張表的 role 欄位定義相同:String(20)、default viewer。
    • project_participants:主鍵 project_id + user_id。$S/jedi_task_platform/participant/infra/model/project_participant.py
    • control_group_participants:project_id + group_id + user_id
    • project_group_participants:同上
    • project_control_participants:project_id + group_id + control_id + user_id
    • process_participants:project_id + process_id + user_id
  • Enum 有兩份,內容相同:common/enum/participant_enum.py:12-18 和 $S/jedi_task_platform/participant/common/participant_enum.py:10-14。註解寫明角色是「決定系統行為(通知、待辦)」。
    • manager:收「待管理」,可管理參與人員
    • reviewer:收「待審核」通知
    • auditor:收「待稽核判定」
    • viewer:純瀏覽,沒有待辦
  • 角色字串也硬寫在:app/oscal/service/excel_parser/validators.py:9、$S/jedi_task_platform/participant/api/serializers/project_participant.py:13,18、process_participant.py:15,20、$S/jedi_compliance_audit/api/serializers/project.py:77、$S/jedi_task_platform/task/app/service/task_execution_service.py:30。建專案時建立者自動補為 manager:app/project/service/project_start_app_service.py:166-176。

2. 硬編角色判定清單

欄位說明:「fb」代表走 control→group→project 回退;「精確」代表只認專案層那一列。M=manager、R=reviewer、A=auditor、V=viewer、Any=任一參與者。

檔:行 守的動作 允許角色 查法
定義 common/authz/project.py:28,43 assert_project_manager 本體 M fb
common/authz/project.py:47,72 assert_project_role_fallback 本體 allowed_roles fb
common/authz/project.py:75,110 assert_project_role 本體 allowed_roles(預設 M) 精確
common/authz/project.py:118 assert_project_participant 本體 Any fb
common/authz/workflow.py:32 workflow 參與者守門(沒有登入情境就放行) Any 專案層
common/authz/workflow.py:50,71 完成/退回任務 M 或該任務被指派人 專案層
common/authz/ssp.py:91-132 SspPermissionChecker 的 require_participant / require_manager(寫入還要求 AP 可編輯) Any / M 精確
flow_control app/flow_control/service/project_service.py:383 更新專案 M fb
project_service.py:578-582 刪除專案:非成員回 404;是否 manager 決定能否刪 owner 或 M fb+精確
project_service.py:629 批次刪除專案 owner 或 M 精確
project_service.py:676-679 專案啟動通知裡的角色標籤(不是守門) — —
job_service.py:150(呼叫點 212/261/337) 新增/刪除/更新任務 M fb
job_service.py:159(呼叫點 300) 列任務 Any fb
job_service.py:185 取單一任務 Any fb
job_batch_complete_service.py:60-61 批次完成任務:manager 可略過被指派人檢查 Any 可進,M 不限指派 fb
assessment_plan_app_service.py:236(呼叫點 209/549/561/592/706) AP 編輯:審查控制項、受評對象、tasks、parties A、M 精確
job_import_service.py:120(呼叫點 477) 確認匯入任務 M 精確
job_import_service.py:135 匯入前檢查計畫屬於本專案 Any fb
project_read_guard.py:22 專案讀取守門 Any fb
workflow_xml_sync_service.py:142-157(呼叫點 96) 流程編輯器存檔(會增刪任務) M fb
project_summary_report project_summary_report_history_service.py:33(呼叫點 41/78) 報告歷史讀取、還原 Any fb
project_summary_report_service.py:45(呼叫點 53/115) 建立/讀取摘要報告 Any fb
cloud_integration drive_sync_admin_service.py:150(呼叫點 136) 初始化專案雲端資料夾 M 精確
drive_project_verify_service.py:160 驗證雲端硬碟 M 精確
oscal(SSP) ssp_document_pool_service.py:59,149,187 讀文件池 Any 精確
ssp_document_pool_service.py:65,119,157,164,195,202 寫文件池 M+AP 可編輯 精確
ssp_inventory_items_app_service.py:66 / 75,102,128 inventory 讀 / 寫 Any / M 精確
ssp_resources_app_service.py:33 / 38,45,51 resources 讀 / 寫 Any / M 精確
ssp_system_characteristic_app_service.py:46 / 54 系統特性讀 / 寫 Any / M 精確
ssp_leveraged_app_service.py:67 / 75,102,132 leveraged 讀 / 寫 Any / M 精確
ssp_components_app_service.py:60 / 71,103,133 components 讀 / 寫 Any / M 精確
ssp_party_app_service.py:69 / 78,99,115 parties 讀 / 寫 Any / M 精確
ssp_control_implementation_service.py:71,96,157,911 / 79,846,866,883,889,924 控制實作讀 / 寫 Any / M 精確
ssp_control_impl_import_service.py:104,220,336 / 379 控制實作匯出、驗證、預覽 / 寫入 Any / M 精確
ssp_excel_import_app_service.py:798 / 788 Excel 匯入預覽 / 寫入 Any / M 精確
ssp_docx_import_app_service.py:604 / 594 docx 匯入預覽 / 寫入 Any / M 精確
export/ssp_export_app_service.py:80 SSP 匯出 Any 精確
module_frame/service/ssp_import_template_app_service.py:283 為 SSP 產生匯入範本 Any 精確
flow_engine stage_advance_service.py:93 讀階段 banner Any(四值全列) 精確
stage_advance_service.py:130 banner 上的「可推進」旗標 main_roles 或 M 精確
stage_advance_service.py:307 推進階段 main_roles 或 M 精確
stage_advance_service.py:318 強制推進(force,略過前置條件) M 精確
stage_rollback_service.py:96 階段回退 M 精確
job_force_start_service.py:115(呼叫點 60) 強制開始任務:預檢 Any fb
job_force_start_service.py:127(呼叫點 67) 強制開始任務:執行 M fb
workflow_execution_service.py:132-140 依流程實例反查專案後驗參與者 Any 專案層
workflow_execution_service.py:142-146 → job_operator_guard.py:39,46 任務完成/退回 M 或被指派人 專案層
job_evidence_service.py:61,82 列佐證 Any 專案層
job_evidence_service.py:97,163,188 新增/修改/刪除佐證 Any 專案層
core/plugins _file_ownership.py:175 輪次檔案存取 A、M 精確
_file_ownership.py:277 / 279 任務檔案寫 / 讀 M 或被指派人 / Any 專案層
_file_ownership.py:310-312 證據分類批次檔案寫 / 讀 M / Any 精確
file_upload.py:124 / 132 佐證檔案讀 / 刪 Any / M 或被指派人 專案層
evidence_classification.py:79-88 is_project_manager M 精確
evidence_classification.py:90-97 is_any_project_manager(任一專案是 manager) M 精確
evidence_classification.py:101-113 is_project_participant Any fb
compliance_audit.py:80-93、participant.py:91-107、infra/survey/adapters.py:46-65 套件守門 adapter,轉發給上面的 canonical — —
$S/jedi_compliance_audit review_service.py:14,50(呼叫點 89/102/116/130) 標記/取消已審閱(控制項、AO) M、R fb
audit_service.py:42(呼叫點 97/108/130/144) 判定、新增/修改/刪除 finding A、M 精確
audit_round_app_service.py:132(呼叫點 240/411/567/823/855/880) 建輪次、發動稽核、結案、三種回退 M 精確
audit_round_app_service.py:132(呼叫點 472/504/613) 開始稽核、定案、發動複驗 A、M 精確
audit_round_app_service.py:139 輪次讀取 Any 精確
assessment_result_app_service.py:113 / 120 AR 寫 / 讀 A、M / Any 精確
poam_app_service.py:92 / 98 POA&M 寫 / 讀 M / Any 精確
$S/jedi_task_platform project_participant_service.py:96,118,137 新增/修改/刪除參與者 M fb
project_participant_service.py:49,161 列參與者、選單 Any fb
project_control_participant_service.py:44,66 控制項參與者選單、繼承清單 Any fb
task_assignee_service.py:102,188,224 新增/修改/刪除任務指派 M fb(含 control_id)
task_assignee_service.py:88,93 讀指派 Any fb / 專案層
task_execution_service.py:57(呼叫點 72) 開始任務執行 M 精確
task_execution_service.py:147 準備階段任務進度讀取 Any 精確
job_comment_service.py:45 任務留言 Any 專案層
$S/jedi_survey task_survey_guard.py:58(writer:question_answer_service.py:120,255,407、question_answer_history_service.py:82) 填答、存檔、修改答案、還原歷史 被指派人或 M 專案層
task_survey_guard.py:77 問卷讀取 Any 專案層
task_survey_guard.py:87(task_survey_service.py:112,296) 更新問卷、批次匯入題目 M fb
$S/jedi_evidence_classification evidence_batch_service.py:1476(呼叫點 412/513/542/552/577/669/732/839/996) 建批次、上傳、刪檔、封存、歸檔、清除、刪批次、寫 run 狀態、分類 M 精確
$S/jedi_detection detection_orchestration_service.py:209,913,969,1061,1090,1159,1189,1532 / 1736 偵測任務操作 / 讀 M 或被指派人 / Any 專案層

3. 流程引擎綁定

  • main_role 存在哪:不是獨立欄位,是 BPMN XML 裡 UserTask 的 camunda extension property name="main_role"。值可以是單一角色,也可以逗號分隔多個。

    • 設計器範本:compliance.flow_templates.bpmn_xml(text)。DEV 現有 manager 35、auditor 12、reviewer 11。
    • 實例範本:compliance.workflow_templates.xml(text)。DEV 現有 manager 2250、auditor 2165、reviewer 7。
    • 值域只有 manager / reviewer / auditor,沒看到 viewer。
  • stage_objects.default_main_roles:compliance.stage_objects,JSONB,ORM 在 infra/flow_engine/models/stage_object.py:26。DEV 現值:

    code default_main_roles
    ap_authoring ["auditor"]
    audit ["auditor"]
    planning ["manager"]
    poam ["manager"]
    review ["reviewer"]
    task_execution ["manager"]
  • _resolve_main_roles(app/flow_engine/service/stage_advance_service.py:584-591):先讀當前 UserTask properties 的 main_role,有值就逗號切分;沒值才退回 stage_object.default_main_roles。比對對象是 _get_user_role(:593-601),只查專案層 participant 那一列,不做 fb。manager 一律可以覆寫(:130、:307)。

  • FE 選角色的地方:compliance-manager-fe/src/views/flow-template/FlowTemplateEditorView.vue :125-130 roleOptions 寫死四值(含 viewer);:277 讀 main_role;:371-377 未設定時自動帶入 stage 的 default_main_roles[0];:384 寫回 XML;:589-602 存檔驗證每個 UserTask 必有 main_role;:1111-1119 選單 UI。FlowTemplatePreviewDialog.vue:64-77,168 預覽顯示角色。service/StageService.js:24 API 回傳 main_roles。

4. 通知/待辦依角色決定對象

檔:行 用途 角色
infra/readmodel/tasks/job_batch_complete_query.py:232(get_batch_notification_data) 批次完成後寄「請審閱」 M、R
infra/readmodel/detection/detection_job_notify_query.py:150(_resolve_targets) 偵測任務完成通知 M、R
infra/readmodel/audit/auditor_dashboard_query.py:58(get_auditor_ap_list) 我的稽核待辦清單 A、M
app/flow_control/service/project_service.py:659-700(_notify_project_started) 專案啟動通知:發給所有參與者,角色只當信中標籤 全部
$S/jedi_task_platform/participant/app/service/participant_role_service.py:86-140(get_reviewers_for_task) 找控制項審核人,順序 control→group→project R

get_reviewers_for_task 在主專案沒有找到呼叫點。

5. 進行中的流程實例

  • 會快照,而且是整份 XML 快照。每個 workflow_execution 透過 template_id 指向一列自己專屬的 workflow_templates(帶 source_template_uid,從設計器範本複製出來),main_role 就在那列的 xml 裡。
  • 實例上的 workflow_template_xml 是指向 workflow_template.xml 的 association_proxy($S/jedi_flow_engine/infra/models/workflow_execution.py:57),stage 推進時從這裡讀(stage_advance_service.py:562)。
  • DEV 數量:PROCESSING 1150 筆,對應 1150 份各自獨立的範本;TODO 59427 筆;COMPLETED 67 筆。
  • default_main_roles 不會快照,每次即時讀 stage_objects。
  • 結論:翻譯 main_role 時必須連 workflow_templates.xml(實例那一份)一起改,或者在 _resolve_main_roles 做讀取時轉換。只改 flow_templates.bpmn_xml 不會影響已建立的實例。

6. control→group→project 回退

一句話:判斷某人在某個控制項或群組上的角色時,先找控制項層的指派,沒有就找群組層,再沒有才用專案層;回傳找到的第一個角色,所以下層指派會蓋過上層。

  • 實作:$S/jedi_task_platform/participant/app/service/participant_role_service.py:34-85(get_user_role)。
  • assert_project_manager、assert_project_role_fallback、assert_project_participant 都走這一套;只有傳了 group_id / control_id 才會往下查(common/authz/project.py:28-44)。
  • assert_project_role 只認專案層那一列,不回退(common/authz/project.py:75-90 有註明兩者不可互相冒充)。
  • 守門裡實際有傳 control_id 的,只看到 task_assignee_service。