FR-048 Phase 2a — 授權守門盤點:grc-group(api/grc + api/flow_engine)

純事實盤點,NO 判斷軸。branch: fix/v1.8.0-bugs。 範圍:每個 WRITE method(post/put/delete/patch)+ 敏感 GET(export/download/report)。 只列「actively registered」(未被註解)的 route class;被 # api.add_resource(...) 註解掉的 DEAD-V1 route 不列。 URL prefix:api/grc/__init__.py blueprint prefix = /api/1.0/grcapi/flow_engine/__init__.py blueprint prefix = /api/1.0

「現況守門」判讀基準:route decorator + 追進 app-service method body 找 ForbiddenError / role / participant / is_admin 守門。 停用守門特別標注:common/authz/workflow.py:assert_workflow_project_participant() 函式第 51 行 body 開頭即 return(FR-038 v2 暫時停用),實際不守。app/flow_engine/service/workflow_execution_service.py:133 assert_project_participant() 是它的 wrapper。


§1

api/grc

Route path Method Route file:line @jwt_required? 呼叫的 service method 現況守門 備註
/api/1.0/grc/projects/list POST api/grc/routes/project_route.py:93 ProjectService.list_projects() (app/grc/service/project_service.py:114) 僅 JWT POST 實為分頁查詢(讀);service 硬帶 is_admin=False 只回使用者參與的專案(可見性過濾,非角色守門)
/api/1.0/grc/projects/batch-delete POST api/grc/routes/project_route.py:245 ProjectService.batch_delete_projects() (project_service.py:653) 已有: is_admin 或 owner/manager 參與者 @ project_service.py:679-685(否則 ForbiddenError(ErrorCode.PROJECT_NO_PERMISSION) @:644 for single;batch 同 pattern) POST 實為批次刪除(寫)
/api/1.0/grc/project/<uid> PUT api/grc/routes/project_route.py:168 ProjectService.update_project() (project_service.py:336) 僅 JWT _domain_service.get_project(uid,user_id,is_admin) 做可見性(非成員回 None→route 回 200 false);無角色守門。service 內註解明示「授權由 update_project 自身把關(另列 follow-up)」@:454 — 即尚未實作角色 gate
/api/1.0/grc/project/<uid> DELETE api/grc/routes/project_route.py:221 ProjectService.delete_project() (project_service.py:609) 已有: is_admin 或 owner/manager 參與者 @ project_service.py:632-644(否則 ForbiddenError(ErrorCode.PROJECT_NO_PERMISSION)
/api/1.0/grc/project/<project_uid>/ap/<ap_uid> PUT api/grc/routes/assessment_plan_route.py:55 ProjectService.update_assessment_plan() (project_service.py:550) 僅 JWT service body 為 FR-038 2A dark stub(return None, False)— 無守門且不做事
/api/1.0/grc/project/<project_uid>/ap/<ap_uid> DELETE api/grc/routes/assessment_plan_route.py:93 ProjectService.delete_assessment_plan() (project_service.py:567) 已有: manager 參與者 @ project_service.py:572-573(否則 ForbiddenError(GRC_NOT_MANAGER)
/api/1.0/grc/project/<project_uid>/ap/<ap_uid>/control-group/<group_uid>/control/<control_uid>/assessment-object/<ao_uid>/jobs/list POST api/grc/routes/job_route.py:50 JobService.list_jobs() (app/grc/service/job_service.py:105) 僅 JWT POST 實為分頁查詢(讀)
/api/1.0/grc/project/<project_uid>/job/<job_uid> PUT api/grc/routes/job_route.py:100 JobService.update_job() (job_service.py:126) 僅 JWT route 傳 user_id/is_admin 進 service,但 service body 從未用來守門(無 ForbiddenError)
/api/1.0/grc/project/<project_uid>/job/<job_uid> DELETE api/grc/routes/job_route.py:142 JobService.delete_job() (job_service.py:92) 僅 JWT 無 user_id 參數,無守門
/api/1.0/grc/project/<project_uid>/assessment-object/<ao_uid>/jobs POST api/grc/routes/job_route.py:177 JobService.create_job() (job_service.py:44) 僅 JWT 無 user_id 參數,無守門
/api/1.0/grc/jobs/my/list POST api/grc/routes/job_route.py:224 TaskAssigneeService.list_my_grc_jobs() 僅 JWT POST 實為分頁查詢(讀);query 以 user_id=user.id 自我 scope
/api/1.0/grc/job-executions/<job_execution_uid>/comments POST api/grc/routes/job_comment_route.py:40 JobCommentService.add_comment() (app/grc/service/job_comment_service.py:22) 僅 JWT 無角色/參與者守門
/api/1.0/grc/job/comment/<comment_uid> PUT api/grc/routes/job_comment_route.py:68 JobCommentService.update_comment() (job_comment_service.py:38) 已有: 作者本人 @ job_comment_service.py:48-49comment.author_id != user_idForbiddenError(GRC_JOB_COMMENT_FORBIDDEN) 僅 owner-of-record,非專案角色
/api/1.0/grc/job/comment/<comment_uid> DELETE api/grc/routes/job_comment_route.py:89 JobCommentService.delete_comment() (job_comment_service.py:54) 已有: 作者本人 @ job_comment_service.py:59-60(同上) 僅 owner-of-record
/api/1.0/grc/project/<project_uid>/ap/<ap_uid>/jobs/export GET api/grc/routes/job_import_route.py:35 JobImportService.export_excel() (app/grc/service/job_import_service.py:93) 僅 JWT 敏感 GET(匯出 Excel,send_file 附件);無角色守門
/api/1.0/grc/project/<project_uid>/ap/<ap_uid>/jobs/import POST api/grc/routes/job_import_route.py:59 JobImportService.validate_import() (job_import_service.py:180) 僅 JWT 上傳+驗證,無守門(未寫入)
/api/1.0/grc/project/<project_uid>/ap/<ap_uid>/jobs/import/validate POST api/grc/routes/job_import_route.py:83 JobImportService.revalidate_items() (job_import_service.py:293) 僅 JWT 重新驗證(讀),無守門
/api/1.0/grc/project/<project_uid>/ap/<ap_uid>/jobs/import/confirm POST api/grc/routes/job_import_route.py:105 JobImportService.confirm_import() (job_import_service.py:374) 已有: manager 參與者 @ job_import_service.py:379_check_manager_role() (:81-90, 否則 ForbiddenError(GRC_NOT_MANAGER)) 實際寫入路徑,有守門
/api/1.0/grc/project/<project_uid>/jobs/batch-complete POST api/grc/routes/job_batch_complete_route.py:27 JobBatchCompleteService.batch_complete() (app/grc/service/job_batch_complete_service.py:30) 僅 JWT user_id 僅作 actor 歸屬(留言/通知);無角色/參與者守門
/api/1.0/grc/project/<project_uid>/ap/<ap_uid>/control/<control_uid>/review POST api/grc/routes/review_route.py:18 ReviewService.mark_control() (app/grc/service/review_service.py:42) 僅 JWT 無角色/參與者守門
/api/1.0/grc/project/<project_uid>/ap/<ap_uid>/control/<control_uid>/review DELETE api/grc/routes/review_route.py:32 ReviewService.unmark_control() (review_service.py:54) 僅 JWT 無守門
/api/1.0/grc/project/<project_uid>/ap/<ap_uid>/control/<control_uid>/ao/<ao_uid>/review POST api/grc/routes/review_route.py:50 ReviewService.mark_ao() (review_service.py:66) 僅 JWT 無守門
/api/1.0/grc/project/<project_uid>/ap/<ap_uid>/control/<control_uid>/ao/<ao_uid>/review DELETE api/grc/routes/review_route.py:65 ReviewService.unmark_ao() (review_service.py:78) 僅 JWT 無守門
/api/1.0/grc/project/<project_uid>/start-task-execution POST api/grc/routes/task_execution_route.py:35 TaskExecutionService.start_task_execution() (app/grc/service/task_execution_service.py:60) 已有: manager 參與者 @ task_execution_service.py:61_check_manager() (:46-56, 否則 ForbiddenError(GRC_NOT_MANAGER))
/api/1.0/grc/audits/my/list POST api/grc/routes/auditor_dashboard_route.py:27 AuditorDashboardService.get_my_audit_list() (app/grc/service/auditor_dashboard_service.py:12) 僅 JWT POST 實為清單查詢(讀);以 user_id=user.id 自我 scope

grc — 未列入的 WRITE / 敏感 GET(DEAD-V1,route 已被註解不註冊,不可達)

  • ArVerdictResource.put / ArFindingCreateResource.post / ArFindingDetailResource.put/deleteapi/grc/routes/audit_route.py)— api/grc/__init__.py:137-160 整組註解。
  • PoamListResource.post / PoamDetailResource.putapi/grc/routes/poam_route.py)— __init__.py:163-170 註解。
  • ProjectControlListResource.post / ProjectAOListResource.post / control-group 系列 — __init__.py:90-113 註解。
  • (AR/POA&M/audit-round 的 live 端點在 api/project,非本盤點模組。)

§2

api/flow_engine

Route path Method Route file:line @jwt_required? 呼叫的 service method 現況守門 備註
/api/1.0/flow-engine/process/comments/<id> PUT api/flow_engine/routes/flow_engine_route.py:182 ElementVariableService.update_element_variable()(jedi_flow_engine 套件,route 直接呼叫;WorkflowExecutionCommentRoute 僅 JWT 新增流程留言(寫);route 直接操作 element_variable,無專案守門
/api/1.0/flow-engine/task/complete/<id> POST api/flow_engine/routes/flow_engine_route.py:317 WorkflowExecutionService.complete_job() (app/flow_engine/service/workflow_execution_service.py:640) 已有(停用): assert_project_participant → assert_workflow_project_participant @ workflow_execution_service.py:649 / common/authz/workflow.py:51 — 函式開頭 return,實際不守 停用期間僅靠 RLS 租戶隔離
/api/1.0/flow-engine/task/revert/<id> POST api/flow_engine/routes/flow_engine_route.py:342 WorkflowExecutionService.revert_job() (workflow_execution_service.py:813) 已有(停用): assert_project_participant @ workflow_execution_service.py:822 / common/authz/workflow.py:51 — 函式開頭 return,實際不守;另有 _assert_round_not_frozen_for_workflow @:825(狀態前置條件守門,非角色/參與者) 停用期間僅靠 RLS
/api/1.0/flow-engine/process-definition/<uid> GET api/flow_engine/routes/flow_engine_route.py:146 WorkflowTemplateService.get_workflow_template_by_uid()(套件) 僅 JWT 讀取(非 export/download/report),非敏感 GET;列此供上下文,WorkflowExecutionRoute 僅 GET
/api/1.0/job-execution/task/link PUT api/flow_engine/routes/flow_engine_route.py:413 WorkflowExecutionService.update_assessment_plan_task_job_link() (workflow_execution_service.py:1582) 僅 JWT 更新任務連結(寫);無角色/參與者守門
/api/1.0/job-evidences POST api/flow_engine/routes/job_evidence_route.py:36 JobEvidenceService.add_job_evidence() (app/flow_engine/service/job_evidence_service.py:73) 僅 JWT 批次新增證明(寫);add_job_evidence body 無 participant 守門(僅 NotFound 檢查)
/api/1.0/job-evidence / /api/1.0/job-evidence/<uid> POST api/flow_engine/routes/job_evidence_route.py:77 JobEvidenceService.add_job_evidence() (job_evidence_service.py:73) 僅 JWT 單筆新增證明(寫);同上,無 participant 守門
/api/1.0/job-evidence/<uid> PUT api/flow_engine/routes/job_evidence_route.py:100 JobEvidenceService.update_job_evidence() (job_evidence_service.py:134) 已有(停用): _workflow_execution_service.assert_project_participant() @ job_evidence_service.py:141common/authz/workflow.py:51 — 函式開頭 return,實際不守 停用期間僅靠 RLS
/api/1.0/job-evidence/<uid> DELETE api/flow_engine/routes/job_evidence_route.py:119 JobEvidenceService.delete_job_evidence() (job_evidence_service.py:151) 已有(停用): _workflow_execution_service.assert_project_participant() @ job_evidence_service.py:164common/authz/workflow.py:51 — 函式開頭 return,實際不守 停用期間僅靠 RLS
/api/1.0/flow-engine/flow-templates POST api/flow_engine/routes/flow_template_route.py:36 是 (method_decorators) FlowTemplateAppService.create() (app/flow_engine/service/flow_template_app_service.py:67) 僅 JWT 建立範本(寫);無角色守門
/api/1.0/flow-engine/flow-templates/validate POST api/flow_engine/routes/flow_template_route.py:121 FlowTemplateAppService.validate() (flow_template_app_service.py:138) 僅 JWT POST 實為純驗證(讀,不寫入)
/api/1.0/flow-engine/flow-templates/<uid> PUT api/flow_engine/routes/flow_template_route.py:56 FlowTemplateAppService.update() (flow_template_app_service.py:85) 僅 JWT(授權層);另有資源守門 _guard_not_builtin @:88 / :182-184(builtin 唯讀,非使用者角色/參與者) 更新範本(寫);無角色/參與者守門
/api/1.0/flow-engine/flow-templates/<uid> DELETE api/flow_engine/routes/flow_template_route.py:65 FlowTemplateAppService.soft_delete() (flow_template_app_service.py:131) 僅 JWT;資源守門 _guard_not_builtin @:133(builtin 唯讀) 軟刪範本(寫)
/api/1.0/flow-engine/flow-templates/<uid>/duplicate POST api/flow_engine/routes/flow_template_route.py:76 FlowTemplateAppService.duplicate() (flow_template_app_service.py:154) 僅 JWT 複製範本(寫);無角色守門
/api/1.0/flow-engine/flow-templates/<uid>/publish PUT api/flow_engine/routes/flow_template_route.py:93 FlowTemplateAppService.publish() (flow_template_app_service.py:105) 僅 JWT;資源守門 _guard_not_builtin @:107 發布範本(寫)
/api/1.0/flow-engine/flow-templates/<uid>/unpublish PUT api/flow_engine/routes/flow_template_route.py:105 FlowTemplateAppService.unpublish() (flow_template_app_service.py:119) 僅 JWT;資源守門 _guard_not_builtin @:121 退回草稿(寫)
/api/1.0/project/<project_uid>/audit-round/<round_uid>/stage/advance POST api/flow_engine/routes/stage_advance_route.py:48 是 (method_decorators) StageAdvanceService.advance_stage() (app/flow_engine/service/stage_advance_service.py) 已有: role gate @ stage_advance_service.py:286-293user_role not in main_roles and != MANAGERForbiddenError(GRC_STAGE_ROLE_FORBIDDEN));force 需 MANAGER @:297-304(否則 GRC_NOT_MANAGER 推進階段(寫);有實際角色守門

flow_engine — 未列入的 WRITE(DEAD-V1,route 已被註解不註冊,不可達)

  • MainWorkflowExecutionsRoute.post(分頁查詢)/ MainWorkflowExecutionRoute.put/deleteflow_engine_route.py)— api/flow_engine/__init__.py:39-40 註解。
  • JobCommentsRoute.put(task/comments)— __init__.py:43 註解(process/comments 才 live)。
  • ElementVariableRoute.put(element-variable)— __init__.py:47 註解。
  • WorkflowExecutionsRoute.get(process-definitions 複數)— __init__.py:50 註解。
  • WorkflowExecutionControlMappingsRoute.get__init__.py:55 註解(且 service __init__ 缺參數會 500)。

flow_engine — 純讀取 GET(非 export/download/report,非敏感,未列主表)

  • WorkflowExecutionCommentRoute.get(process/comments 讀)、JobEvidencesRoute.getJobEvidenceRoute.getUserJobQueueRoute.getStageObjectsRoute.getFlowTemplatesRoute.getFlowTemplateRoute.getStageInfoResource.get — 皆 @jwt_required,僅 JWT,無敏感匯出語意。