A.1 盤點:grc 專案稽核模組端點 × 三段式能力點

卡片 CM-2511(FR-132 T-1.1)。唯讀盤點,不改程式、不改 DB。

§1

範圍與數量

  • 範圍:專案(project)、稽核輪次與其下的 AP/AR/POA&M、任務(job,含成員、指派、留言、佐證)、流程執行(api/flow_engine/ 的任務提交與稽核階段推進)、專案摘要報告、資訊系統(information-system)、workflow 能力點。
  • 主專案 route 檔 16 支、92 個 method:api/flow_control/routes/ 4 支、api/project/routes/ 4 支、api/project_summary_report/routes/ 2 支、api/flow_engine/routes/ 6 支(30 個)。另有 1 個已註解停用的 Resource(ProjectMenuResource,/projects/menu),不計入。
  • 外部套件 route 檔 10 支、33 個 method:jedi-compliance-audit 2 支(5)、jedi-task-platform task 5 支(12)、jedi-task-platform participant 2 支(10)、jedi-asset 1 支(6)。讀的是 .venv/lib/python3.11/site-packages/ 內實際執行的版本。
  • 合計 26 支檔、125 個 method。其中流程範本管理 11 個屬 T-1.2 範圍,只列不定名。jedi-flow-engine 套件本身沒有 route。
  • DEV 查詢時間:2026-10-06 16:18(本機 localhost:5432/guidant_ai_dev)。範圍內舊能力點 23 個。
§2

先看這幾點

  1. 125 個 method 裡,只有 25 個掛了能力點守門。 主專案 8 個(專案列表/明細/改/刪/批次刪、建專案)、流程範本 11 個(flow_template.*),jedi-asset 資訊系統 6 個。其餘 100 個只有 jwt_required(多數加授權模組軸 require_license),專案內的權限全靠 service 層的專案成員角色檢查。
  2. audit.* 四個能力點一支 route 都沒守。 它們只出現在三處:稽核管理頁的選單綁定(/project/audit-manage)、出貨角色範本、FE 儀表板的 hasCap('audit.read')。整個稽核輪次/AP/AR/POA&M 共 36 個 method 都沒有公司層守門。
  3. project.approve/project.assign/project.export 三個獨立動詞一支 route 都沒守。 只綁在專案列表頁選單與角色範本,FE ProjectListView 只讀 CREATE/UPDATE/DELETE。下面主表把「指派」接到專案成員端點、「匯出」接到任務匯出;approve 沒有任何對應功能(任務提交與審核關卡走 /flow-engine/task/complete 與 .../stage/advance,都不是它),名字移給 grc.audit.approve(審閱標記)。
  4. 兩層守門要分開看:主表「現有守門」欄先寫公司層(能力點),再寫「成員角色:」後的專案層檢查。成員角色守門是「你在這個專案裡是什麼身分」,能力點是「公司准不准你碰這類功能」,有前者不等於有後者。
  5. 個人視角端點(我的任務、我的稽核、儀表板摘要、我被指派的專案下拉)只回「自己參與的」資料,service 層不做角色檢查。新名照主資源 read 填,定案要掛守門;上線前要確認出貨角色範本都帶了對應 read。
§3

新名總覽(定案)

grc 模組 7 個資源,資訊系統歸 asset 模組:

新資源 read create update delete 獨立動詞 取代的舊名
grc.project ✓ ✓ ✓ ✓ assign(專案成員) project.read/create/update/delete/assign
grc.audit ✓ ✓ ✓ ✓ import(AP Word、AR Excel 匯入)、close(結束輪次)、approve(審閱標記,控制項與 AO 兩層同一個) audit.* 四個;project.approve(名字移過來)
grc.job ✓ ✓ ✓ ✓ assign(任務指派、啟動任務執行、強制開始)、import、export project.export(移過來)
grc.job-comment ✓ ✓ ✓ ✓ — 無
grc.job-evidence ✓ ✓ ✓ ✓ — 無
grc.summary-report ✓ ✓ ✓ ✓ export project-summary-report.*
asset.information-system ✓ ✓ ✓ ✓ — information-system.*
  • grc.audit 一組涵蓋稽核輪次、評估計畫(AP)、評估結果(AR,含風險)、矯正計畫(POA&M)。這四塊誰能寫,由專案層的成員角色分(AP/AR 給 auditor/manager,POA&M 給 manager),公司層只分「能不能看、能不能改」。
  • workflow.* 四個刪除,不給新名。
  • 「每個資源固定四個」照規則全開;某資源今天沒有 delete 或 create 端點的,仍要建出來。
§4

主表

欄位:route 路徑 | HTTP | 程式位置 | 現有守門 | 新三段名 | 現有能力點 | 對應 UI | 可指派範圍層 | 備註。

守門縮寫:J=jwt_required;L(x)=require_license("x");C(x)=require_capability("x")。專案層守門寫「成員:」+放行角色(參與者=任何成員)。路徑前綴:主專案 grc 段=/api/1.0/grc,其餘=/api/1.0。

專案(grc.project)

route 路徑 HTTP 程式位置 現有守門 新三段名 現有能力點 對應 UI 範圍層 備註
/oscal-project/start POST api/project/routes/project_route.py:28 J+L(project)+C(project.create);成員:無(建立者此時尚非成員) grc.project.create project.create ProjectCreateView org_unit
/grc/projects/list POST api/flow_control/routes/project_route.py:99 J+L(project)+C(project.read);成員:可見性過濾(只列參與的) grc.project.read project.read ProjectListView、DashboardView、ProjectSummaryReportManage(下拉) org_unit
/grc/project/<uid> GET project_route.py:146 J+L(project)+C(project.read);成員:參與者(is_admin 一律傳 False) grc.project.read project.read ProjectPlanningView、ProjectSettingsView(GRC_PROJECT 前綴,未逐支核) org_unit
/grc/project/<uid> PUT project_route.py:177 J+L(project)+C(project.update);成員:manager grc.project.update project.update ProjectListView(編輯鈕)、ProjectSettingsView org_unit
/grc/project/<uid> DELETE project_route.py:232 J+L(project)+C(project.delete);成員:owner 或 manager(admin 可刪任意) grc.project.delete project.delete ProjectListView org_unit service 內有 is_admin 旁路,見「確認要補的守門缺口」
/grc/projects/batch-delete POST project_route.py:258 J+L(project)+C(project.delete);成員:同上,逐筆判 grc.project.delete project.delete ProjectListView org_unit
/grc/jobs/my/projects/menu GET project_route.py:74 J+L(project);成員:無(只回自己被指派的) grc.project.read 無 MyTasksView(篩選下拉) tenant 輔助端點;個人視角
/grc/dashboard/summary GET 套件 jedi_task_platform/task/api/routes/dashboard_route.py:28 J+L(project);成員:無(is_admin=False,只算自己參與的) grc.project.read 無 DashboardView tenant 個人視角;FE 自己用 hasCap('project.read') 決定顯示
/project-participants/menu GET 套件 jedi_task_platform/participant/api/routes/project_participant_route.py:20 J(宿主注入);成員:參與者 grc.project.read 無 ProjectPlanningView org_unit 輔助端點;無 license 軸
/project-participants POST project_participant_route.py:39 J;成員:參與者 grc.project.read 無 ProjectPlanningView、ProjectSettingsView org_unit 列表
/project-participant POST project_participant_route.py:55 J;成員:manager grc.project.assign 無 ProjectSettingsView(成員設定) org_unit 「指派」類獨立動詞,project.assign 的落點
/project-participant PUT project_participant_route.py:71 J;成員:manager grc.project.assign 無 同上 org_unit 改成員角色
/project-participant DELETE project_participant_route.py:84 J;成員:manager grc.project.assign 無 同上 org_unit
/grc/project/<pid>/start-task-execution POST 套件 task/api/routes/task_execution_route.py:34 J+L(project);成員:manager grc.job.assign 無 ProjectPlanningView、ProjectAuditorOverview org_unit 把已指派的任務一次派發並通知被指派人,屬派工
/grc/project/<pid>/task-execution/progress GET task_execution_route.py:57 J+L(project);成員:參與者 grc.project.read 無 ProjectPlanningView org_unit 輪詢進度

稽核:輪次(grc.audit)

route 路徑 HTTP 程式位置 現有守門 新三段名 現有能力點 對應 UI 範圍層 備註
/projects/<pid>/audit-rounds POST api/project/routes/audit_round_route.py:58 J+L(audit);成員:manager grc.audit.create 無 ProjectPlanningView、ProjectAuditorOverview org_unit J 組
/projects/<pid>/audit-rounds/list POST audit_round_route.py:74 J+L(audit);成員:參與者 grc.audit.read 無 同上、MyTasksView org_unit J 組
/audit-round/<rid> GET audit_round_route.py:86 J+L(audit);成員:參與者 grc.audit.read 無 輪次各頁 org_unit J 組
/audit-round/<rid>/close-round POST audit_round_route.py:97 J+L(audit);成員:manager grc.audit.close 無 ProjectAuditorOverview org_unit J 組;狀態轉換
/audit-round/<rid>/launch-reverify POST audit_round_route.py:110 J+L(audit);成員:auditor/manager grc.audit.create 無 ProjectApListView org_unit J 組;產生一輪新的覆核輪
/audits/my/list POST 套件 jedi_compliance_audit/api/routes/auditor_dashboard_route.py:26 J+L(audit);成員:無(只回自己是 auditor 的) grc.audit.read 無 MyAuditsView(/project/audit-manage)、DashboardView tenant 個人視角;回的是 AP 清單

稽核:評估計畫 AP(grc.audit)

route 路徑 HTTP 程式位置 現有守門 新三段名 現有能力點 對應 UI 範圍層 備註
/grc/project/<pid>/assessment-plans/menu GET api/flow_control/routes/assessment_plan_route.py:32 J+L(project);成員:參與者 grc.audit.read 無 ProjectAuditorOverview、ImportDocxPage org_unit J 組;輔助端點
/grc/project/<pid>/ap/<ap>/dashboard GET assessment_plan_route.py:54 J+L(project);成員:參與者 grc.audit.read 無 ProjectAuditorOverview org_unit J 組
/audit-round/<rid>/ap GET audit_round_route.py:139 J+L(audit);成員:參與者 grc.audit.read 無 RoundApAuthoringView org_unit
/ap/<ap>/reviewed-controls PUT audit_round_route.py:152 J+L(audit);成員:auditor/manager grc.audit.update 無 RoundApAuthoringView org_unit
/ap/<ap>/assessment-subjects PUT audit_round_route.py:167 J+L(audit);成員:auditor/manager grc.audit.update 無 RoundApAuthoringView org_unit
/ap/<ap>/tasks PUT audit_round_route.py:182 J+L(audit);成員:auditor/manager grc.audit.update 無 RoundApAuthoringView org_unit
/ap/<ap>/parties GET audit_round_route.py:198 J+L(audit);成員:參與者 grc.audit.read 無 RoundApAuthoringView org_unit
/ap/<ap>/parties POST audit_round_route.py:208 J+L(audit);成員:auditor/manager grc.audit.update 無 RoundApAuthoringView org_unit
/ap/<ap>/docx-imports/parse POST api/project/routes/ap_docx_import_route.py:42 J+L(audit);成員:auditor/manager grc.audit.import 無 ImportDocxPage(ApDocxImportService) org_unit J 組
/ap-docx-import/<parse> GET ap_docx_import_route.py:66 J+L(audit);成員:參與者(預覽較寬) grc.audit.import 無 同上 org_unit J 組;匯入流程內的預覽,跟匯入同一個能力點
/ap-docx-import/<parse> DELETE ap_docx_import_route.py:82 J+L(audit);成員:auditor/manager grc.audit.import 無 同上 org_unit J 組;放棄本次解析
/ap-docx-import/<parse>/confirm POST ap_docx_import_route.py:103 J+L(audit);成員:auditor/manager grc.audit.import 無 同上 org_unit J 組
/grc/project/<pid>/ap/<ap>/control/<c>/review POST 套件 jedi_compliance_audit/api/routes/review_route.py:18 J+L(project);成員:manager/reviewer grc.audit.approve 無 JobExecutionDrawer、ProjectAuditorOverview org_unit 審閱標記(控制項層)
同上 DELETE review_route.py:27 同上 grc.audit.approve 無 同上 org_unit 取消標記(控制項層)
/grc/project/<pid>/ap/<ap>/control/<c>/ao/<ao>/review POST review_route.py:40 同上 grc.audit.approve 無 同上 org_unit AO 層
同上 DELETE review_route.py:49 同上 grc.audit.approve 無 同上 org_unit AO 層

稽核:評估結果 AR,含風險(grc.audit)

route 路徑 HTTP 程式位置 現有守門 新三段名 現有能力點 對應 UI 範圍層 備註
/audit-round/<rid>/ar/findings GET audit_round_route.py:223 J+L(audit);成員:參與者 grc.audit.read 無 RoundAuditReviewView org_unit
/audit-round/<rid>/ar/finding/<f> PUT audit_round_route.py:235 J+L(audit);成員:auditor/manager grc.audit.update 無 RoundAuditReviewView org_unit 判定符合/不符合
/audit-round/<rid>/ar/observations POST audit_round_route.py:252 J+L(audit);成員:auditor/manager grc.audit.create 無 RoundAuditReviewView org_unit
/audit-round/<rid>/ar/observation/<o> PUT audit_round_route.py:270 同上 grc.audit.update 無 同上 org_unit
同上 DELETE audit_round_route.py:285 同上 grc.audit.delete 無 同上 org_unit
/audit-round/<rid>/ar/risks GET audit_round_route.py:299 J+L(audit);成員:參與者 grc.audit.read 無 RoundAuditReviewView、RoundPoamView org_unit
同上 POST audit_round_route.py:309 J+L(audit);成員:auditor/manager grc.audit.create 無 RoundAuditReviewView org_unit 風險不另開資源
/audit-round/<rid>/ar/risk/<r> PUT audit_round_route.py:327 同上 grc.audit.update 無 同上 org_unit
同上 DELETE audit_round_route.py:342 同上 grc.audit.delete 無 同上 org_unit
/audit-round/<rid>/ar/risk/<r>/findings PUT audit_round_route.py:357 同上 grc.audit.update 無 同上 org_unit 風險連結發現
/audit-round/<rid>/ar-imports/parse POST api/project/routes/ar_import_route.py:42 J+L(audit);成員:auditor/manager grc.audit.import 無 ArImportDialog(ArImportService) org_unit J 組
/ar-import/<parse> GET ar_import_route.py:66 同上 grc.audit.import 無 同上 org_unit J 組
/ar-import/<parse> DELETE ar_import_route.py:82 同上 grc.audit.import 無 同上 org_unit J 組
/ar-import/<parse>/confirm POST ar_import_route.py:103 同上 grc.audit.import 無 同上 org_unit J 組

稽核:矯正計畫 POA&M(grc.audit)

route 路徑 HTTP 程式位置 現有守門 新三段名 現有能力點 對應 UI 範圍層 備註
/audit-round/<rid>/poam-items GET audit_round_route.py:373 J+L(audit);成員:參與者 grc.audit.read 無 RoundPoamView org_unit
/audit-round/<rid>/poam-item/<i> GET audit_round_route.py:384 同上 grc.audit.read 無 同上 org_unit
/audit-round/<rid>/ar/risk/<r>/remediations POST audit_round_route.py:396 J+L(audit);成員:manager grc.audit.create 無 同上 org_unit
/audit-round/<rid>/remediation/<m>/milestones POST audit_round_route.py:412 同上 grc.audit.create 無 同上 org_unit
/audit-round/<rid>/poam-milestone/<ms> PUT audit_round_route.py:432 同上 grc.audit.update 無 同上 org_unit
同上 DELETE audit_round_route.py:444 同上 grc.audit.delete 無 同上 org_unit
/audit-round/<rid>/remediation/<m> DELETE audit_round_route.py:458 同上 grc.audit.delete 無 同上 org_unit

任務(grc.job)

route 路徑 HTTP 程式位置 現有守門 新三段名 現有能力點 對應 UI 範圍層 備註
/grc/project/<pid>/ap/<ap>/control-group/<g>/control/<c>/assessment-object/<ao>/jobs/list POST api/flow_control/routes/job_route.py:52 J+L(project);成員:參與者 grc.job.read 無 ProjectPlanningView org_unit J 組
/grc/project/<pid>/job/<job> GET job_route.py:82 J+L(project);成員:參與者 grc.job.read 無 ProjectPlanningView、JobExecutionDrawer org_unit J 組
同上 PUT job_route.py:104 J+L(project);成員:manager grc.job.update 無 AoTaskForm org_unit J 組
同上 DELETE job_route.py:147 J+L(project);成員:manager grc.job.delete 無 AoTaskSection org_unit J 組
/grc/project/<pid>/assessment-object/<ao>/jobs POST job_route.py:183 J+L(project);成員:manager grc.job.create 無 ProjectPlanningView、AoTaskForm org_unit J 組
/grc/jobs/my/list POST job_route.py:231 J+L(project);成員:無(只回自己的) grc.job.read 無 MyTasksView、DashboardView tenant J 組;個人視角
/grc/project/<pid>/job/<job>/blocked-status GET api/flow_control/routes/job_force_start_route.py:41 J+L(project);成員:參與者 grc.job.read 無 JobBlockedNotice、AoTaskSection org_unit J 組
/grc/project/<pid>/job/<job>/force-start POST job_force_start_route.py:66 J+L(project);成員:manager grc.job.assign 無 AoTaskSection、AoTaskForm(useJobForceStart) org_unit J 組;任務卡在前一關時由經理放行,屬派工
/grc/project/<pid>/jobs/batch-complete POST 套件 task/api/routes/job_batch_complete_route.py:26 J+L(project);成員:參與者 grc.job.update 無 MyTasksView org_unit 執行人把自己的任務批次完成
/grc/project/<pid>/ap/<ap>/jobs/export GET 套件 task/api/routes/job_import_route.py:34 J+L(project);成員:參與者 grc.job.export project.export(建議移過來) ProjectPlanningView org_unit
/grc/project/<pid>/ap/<ap>/jobs/import POST job_import_route.py:52 J+L(project);成員:參與者(只驗不寫) grc.job.import 無 JobImportDialog org_unit 上傳+驗證
/grc/project/<pid>/ap/<ap>/jobs/import/validate POST job_import_route.py:70 同上 grc.job.import 無 同上 org_unit 重新驗證
/grc/project/<pid>/ap/<ap>/jobs/import/confirm POST job_import_route.py:86 J+L(project);成員:manager grc.job.import 無 同上 org_unit 寫入
/task-assignees POST 套件 participant/api/routes/task_assignee_route.py:44 J(宿主注入);成員:參與者 grc.job.read 無 JobExecutionDrawer org_unit 列表;無 license 軸
/task-assignees/batch POST task_assignee_route.py:20 J;成員:manager grc.job.assign 無 JobExecutionDrawer org_unit
/task-assignee POST task_assignee_route.py:59 J;成員:manager grc.job.assign 無 同上 org_unit
/task-assignee PUT task_assignee_route.py:73 J;成員:manager grc.job.assign 無 同上 org_unit
/task-assignee DELETE task_assignee_route.py:95 J;成員:manager grc.job.assign 無 同上 org_unit

任務留言(grc.job-comment)

route 路徑 HTTP 程式位置 現有守門 新三段名 現有能力點 對應 UI 範圍層 備註
/grc/job-executions/<je>/comments GET 套件 task/api/routes/job_comment_route.py:25 J+L(project);成員:無 grc.job-comment.read 無 JobExecutionDrawer org_unit service list_comments 不驗成員,見「確認要補的守門缺口」
同上 POST job_comment_route.py:35 J+L(project);成員:參與者 grc.job-comment.create 無 同上 org_unit
/grc/job/comment/<c> PUT job_comment_route.py:58 J+L(project);只有作者本人 grc.job-comment.update 無 同上 org_unit
同上 DELETE job_comment_route.py:74 同上 grc.job-comment.delete 無 同上 org_unit

流程執行(api/flow_engine,歸 grc)

任務提交、審核關卡的通過/退回、稽核階段推進都在這一段,project.approve 跟它們無關。流程執行的 19 個 method 全部只有 jwt_required,沒有 license 軸。

route 路徑 HTTP 程式位置 現有守門 新三段名 現有能力點 對應 UI 範圍層 備註
/flow-engine/task/complete/<id> POST api/flow_engine/routes/flow_engine_route.py:38 J;成員:該任務被指派人或 manager(assert_job_operator) grc.job.update 無 JobExecutionDrawer(TASK_COMPLETE) org_unit 任務提交;審核關卡的通過/退回也走這支
/flow-engine/task/revert/<id> POST flow_engine_route.py:63 同上 grc.job.update 無 JobExecutionDrawer(TASK_REVERT) org_unit 退回上一關
/flow-engine/task/queue GET flow_engine_route.py:88 J;成員:無(只回自己的待辦) grc.job.read 無 userUtil.js(TASK_QUEUE,待辦數字) tenant 個人視角
/flow-engine/process-definition/<uid> GET flow_engine_route.py:27 J;無任何檢查 待 T-1.2 定 無 WorkflowSetupForm(/workflow/workflow-setup) tenant 讀流程圖 XML。呼叫它的頁面是舊入口,見「確認要補的守門缺口」
/job-evidences GET api/flow_engine/routes/job_evidence_route.py:27 J;成員:參與者 grc.job-evidence.read 無 JobExecutionDrawer、RoundAuditReviewView org_unit 一個任務執行的佐證列表
/job-evidences POST job_evidence_route.py:36 J;成員:參與者 grc.job-evidence.create 無 JobExecutionDrawer org_unit 上傳佐證(多檔)
/job-evidence POST job_evidence_route.py:131 J;成員:參與者 grc.job-evidence.create 無 JobExecutionDrawer org_unit 單筆新增
/job-evidence/<uid> GET job_evidence_route.py:64 J;成員:參與者 grc.job-evidence.read 無 JobExecutionDrawer org_unit
同上 PUT job_evidence_route.py:78 J;成員:參與者 grc.job-evidence.update 無 同上 org_unit
同上 DELETE job_evidence_route.py:97 J;成員:參與者 grc.job-evidence.delete 無 同上 org_unit
/project/<pid>/audit-round/<rid>/stage/info GET api/flow_engine/routes/stage_advance_route.py:28 J;成員:參與者(先核輪次歸屬) grc.audit.read 無 FlowPhaseBanner(StageService) org_unit
/project/<pid>/audit-round/<rid>/stage/advance POST stage_advance_route.py:49 J;成員:該階段指定角色或 manager;force 只限 manager grc.audit.update 無 FlowPhaseBanner org_unit 推進稽核階段;審核階段的通過/退回也在這裡
/project/<pid>/audit-round/<rid>/stage/rollback POST api/flow_engine/routes/stage_rollback_route.py:29 J;成員:manager grc.audit.update 無 FlowPhaseBanner org_unit 退回上一個稽核階段
/project/<pid>/audit-round/<rid>/stage/transitions GET stage_rollback_route.py:59 J;成員:參與者 grc.audit.read 無 StageTransitionTimeline org_unit 階段異動紀錄
/flow-engine/stage-objects GET api/flow_engine/routes/stage_object_route.py:16 J;無成員檢查 待 T-1.2 定 無 FlowTemplateService(範本編輯器下拉) tenant 輔助端點,跟流程範本的 read

佐證開獨立資源 grc.job-evidence 的理由跟留言相同:「只能看任務、但要上傳佐證」的執行人,不必拿到改任務本身的權限。

流程範本管理(T-1.2 範圍,只列不定名)

api/flow_engine/routes/flow_template_route.py,11 個 method 已掛 flow_template.*(:37-147),綁 /flow/template-manage 頁。讀取用 require_capability("flow_template.read", "project.create", mode="any")(:23-25),因為建專案第一步要選流程範本。改 project.create 名字時這一處要跟著改。

route 路徑 HTTP 現有守門
/flow-engine/flow-templates GET/POST read(或 project.create)/create
/flow-engine/flow-templates/<uid> GET/PUT/DELETE read(或 project.create)/update/delete
/flow-engine/flow-templates/<uid>/duplicate POST create
/flow-engine/flow-templates/<uid>/publish PUT update
/flow-engine/flow-templates/<uid>/unpublish PUT update
/flow-engine/flow-templates/validate POST update

專案摘要報告(grc.summary-report)

route 路徑 HTTP 程式位置 現有守門 新三段名 現有能力點 對應 UI 範圍層 備註
/project-summary-reports POST api/project_summary_report/routes/project_summary_report_route.py:83 J(無 license 軸);成員:只列自己參與專案的報告 grc.summary-report.read project-summary-report.read 只綁選單 ProjectSummaryReportManage org_unit J 組;列表
/project-summary-report POST project_summary_report_route.py:103 J;成員:參與者 grc.summary-report.create 同上 .create ProjectSummaryReportForm org_unit J 組
/project-summary-report/<uid> GET project_summary_report_route.py:120 J;成員:參與者 grc.summary-report.read .read 同上 org_unit J 組
同上 PUT project_summary_report_route.py:129 J;成員:參與者 grc.summary-report.update .update 同上 org_unit J 組
同上 DELETE project_summary_report_route.py:149 J;成員:參與者 grc.summary-report.delete .delete ProjectSummaryReportManage org_unit J 組
/project-summary-report/export/<uid> GET project_summary_report_route.py:160 J;成員:參與者 grc.summary-report.export 無 ProjectSummaryReportManage org_unit J 組;PDF 匯出
/project-summary-report/histories POST project_summary_report_history_route.py:28 J;成員:參與者(有帶報告 uid 時) grc.summary-report.read .read ProjectSummaryReportHistory org_unit J 組
/project-summary-report/history/<uid> GET project_summary_report_history_route.py:47 J;成員:參與者 grc.summary-report.read .read 同上 org_unit J 組
/project-summary-report/history-revert POST project_summary_report_history_route.py:61 J;成員:參與者 grc.summary-report.update .update 同上 org_unit J 組;還原成舊版=改內容

project-summary-report.* 四個舊名在 DEV 有綁 /project-summary-report 頁選單,但後端沒有任何 route 守它們。

資訊系統(asset.information-system)

route 路徑 HTTP 程式位置 現有守門 新三段名 現有能力點 對應 UI 範圍層 備註
/information-systems/menu GET 套件 jedi_asset/api/routes/information_system_route.py:44 套件 auth_required+capability_required(read) asset.information-system.read information-system.read ModuleFrameSspInfoSystemsPanel、EntityPickerDialog org_unit 輔助端點
/information-systems/list POST information_system_route.py:62 同上(read) asset.information-system.read .read InformationSystemManage(/information-system/manage) org_unit
/information-systems POST information_system_route.py:85 同上(create) asset.information-system.create .create 同上 org_unit
/information-system/<uid> GET information_system_route.py:106 同上(read) asset.information-system.read .read 同上 org_unit
同上 PUT information_system_route.py:118 同上(update) asset.information-system.update .update 同上 org_unit
同上 DELETE information_system_route.py:139 同上(delete) asset.information-system.delete .delete 同上 org_unit

能力點名不是寫死的:route 讀 rt.config.information_system_*_capability,預設值在套件 jedi_asset/plugin/contract.py:81-84。改名時改這四個預設值(或宿主注入),route 不用動。

§5

現有能力點反查(DEV 23 個)

舊名 主表有 route 守它? 新名 其他引用處
project.create 有:/oscal-project/start grc.project.create 範圍外另有兩處拿它當放行條件:api/module_frame/routes/module_frame_route.py:26、api/flow_engine/routes/flow_template_route.py:24(mode="any")。角色範本 core/role_templates.py:37
project.read 有:列表、明細 grc.project.read FE DashboardView(7 處)、userUtil.js;角色範本 :13;已停用的 ProjectMenuResource 也掛它
project.update 有:PUT 專案 grc.project.update 角色範本 :25
project.delete 有:DELETE、批次刪 grc.project.delete 角色範本無(只有管理員角色帶得到)
project.approve 無,全系統找不到對應功能 grc.audit.approve(名字移去給審閱標記) 只綁 /project/projects 選單、角色範本 :39
project.assign 無 grc.project.assign(接專案成員端點) 只綁選單、角色範本 :38
project.export 無 grc.job.export(接任務匯出) 只綁選單、角色範本 :40
audit.create/read/update/delete 無 grc.audit.* 宣告在套件 jedi_compliance_audit/plugin/contract.py;綁 /project/audit-manage(我的稽核頁)選單;FE DashboardView 用 hasCap('audit.read');角色範本 :33-36、:46
project-summary-report.create/read/update/delete 無 grc.summary-report.* 宣告在 core/host_capabilities.py:45;綁 /project-summary-report 選單;角色範本 :41、:47
information-system.create/read/update/delete 有:jedi-asset 六支 asset.information-system.* 角色範本 :15(read)
workflow.create/read/update/delete 無 刪除 宣告在套件 jedi_flow_engine/plugin/contract.py:29-32;不綁任何選單;在新租戶排除清單 core/plugins/identity.py:89-95;DEV 只有 Administrator 角色掛著這四個

沒有任何 route 用到的能力點(孤兒)

project.approve、project.assign、project.export、audit.*(4)、project-summary-report.*(4)、workflow.*(4),共 15 個。前 11 個有綁選單、出貨角色範本也有給,孤兒不等於沒用:它們目前決定「選單看不看得到」,只是端點沒跟著守。改名後由主表對應的 route 掛上守門。workflow.* 才是真正什麼都沒用到。

§6

定案結論

  1. 資訊系統歸 asset 模組,名字 asset.information-system.*。它跟設備同屬資產:程式同一支套件(jedi-asset)、各自有獨立管理頁,專案與 SSP 只是挑選它來用,只需要 read。設備那份盤點要採用同一個模組名 asset。能力點名由套件 jedi_asset/plugin/contract.py:81-84 的預設值決定,改那四個值即可,route 不用動。
  2. workflow.* 刪除。 AO 流程執行走專案成員角色,流程範本走 flow_template.*,兩者都沒用到它。要動三處:套件 jedi_flow_engine/plugin/contract.py 的 CAPABILITIES 清空;core/plugins/identity.py 排除清單的 "workflow" 拿掉;migration 刪除四個能力點與 Administrator 角色的綁定。
  3. 稽核保留一組 grc.audit.*,不拆成輪次/AP/AR/POA&M 四組。
    • 誰能寫哪一塊,專案層成員角色已經分好(AP/AR:auditor、manager;POA&M:manager),公司層再拆一次是同一件事管兩遍,且兩層可能互相矛盾。
    • 拆開後,「專案裡是稽核員、但公司角色少勾一格」會變成按鈕 403 且沒有錯誤訊息,正是本 FR 要避免的失敗形狀。
    • 公司層真正要分的是「能看/能改」,read 與 update 已足夠。
    • 反悔條件:客戶要求「矯正計畫交給被稽核單位的人寫、但不能碰稽核結果」時,把 POA&M 拆成 grc.poam.*,其他三塊不受影響。
  4. project.approve 沒有對應功能。 任務提交與審核關卡走 /flow-engine/task/complete,稽核階段審核走 .../stage/advance,問卷審核屬問卷模組,都不是它。名字移給第 5 項。
  5. 審閱標記用 grc.audit.approve,控制項層與 AO 層打勾、取消共用一個。用 approve 不另創 review,是為了守住獨立動詞只有四類的規則;跟 update 分開,客戶才能做到「外部顧問可寫判定,最後審閱確認留給內部人員」。
  6. 風險不另開資源,跟評估結果一起,屬 grc.audit。
  7. 啟動任務執行、強制開始任務都歸 grc.job.assign。 兩者本質是派工,有權指派任務的人就要能派發。
  8. 任務留言獨立成 grc.job-comment;佐證比照獨立成 grc.job-evidence。
  9. 個人視角端點掛 read 守門(我的任務、我的稽核、儀表板摘要、我被指派的專案下拉、待辦數字)。上線前要確認出貨角色範本都帶了 grc.project.read、grc.job.read、grc.audit.read,否則只有成員身分的使用者會突然 403。
§7

確認要補的守門缺口

決策者已裁「要補」。本卡只讀,修正另開卡(由首腦排入 A.2 或獨立一棒)。

  1. 任務留言列表不驗專案成員:GET /grc/job-executions/<je>/comments 的 service(jedi_task_platform/task/app/service/job_comment_service.py:27)直接查,知道 job_execution uid 的登入者就能讀。要補成員檢查,比照同檔 add_comment 的 assert_project_participant。
  2. 專案摘要報告整組沒有授權模組檢查:api/project_summary_report/routes/ 9 個 method 都沒有 require_license。成員檢查有(列表以參與專案過濾,單筆走 _require_participant)。
  3. 刪除專案有管理員旁路:app/flow_control/service/project_service.py:547 起,is_admin 可刪任意專案,跟「明細讀取一律不給 admin 旁路」不一致。
  4. 流程圖定義端點沒有任何檢查:GET /flow-engine/process-definition/<uid>(api/flow_engine/routes/flow_engine_route.py:27),任何登入者給 uid 就能讀流程範本 XML。呼叫它的 WorkflowSetupForm 是舊入口,先確認還有沒有在用,沒用就退役,有用就補守門。歸屬由 T-1.2 一併處理。
§8

改名時要一起動的地方(給下一棒)

  • core/host_capabilities.py(PROJECT、PROJECT_SUMMARY_REPORT)
  • core/role_templates.py(:13、:15、:25、:33-41、:46-47)
  • 套件 contract:jedi_compliance_audit/plugin/contract.py(audit.*)、jedi_asset/plugin/contract.py:81-84(information-system 預設名)、jedi_flow_engine/plugin/contract.py:29-32(workflow 刪除)
  • 範圍外放行條件:api/module_frame/routes/module_frame_route.py:26、api/flow_engine/routes/flow_template_route.py:24
  • DEV route_capabilities:/project/projects、/project/audit-manage、/project-summary-report、/information-system/manage 四頁的綁定
  • FE:DashboardView.vue 的 hasCap('project.read')/hasCap('audit.read')、userUtil.js;ProjectListView 讀的是頁面動作字(CREATE/UPDATE/DELETE),三段式動詞不變就不用改

沿革見 FR-132-LOG.md 與 git log。