任務內容

標記審閱在 FR-038 2B 重建後又壞(接續已 Done 的 AO/控制項審閱在 v2 全壞):任一專案在控制項/AO 按「標記為已審閱」都失敗,且控制項即使進度 100% 也按不下去。

使用者回報:188 上控制項/AO 標記審閱都出錯;localhost 控制項一直跳「控制項完成後才可標記」按不了。

現況/需求釐清

三層根因(逐層揭開):

  1. stg 500GrcReviewRepoImpl._resolve_control_idsLEFT JOIN compliance.project_assessment_plan_mapping 反查 project_id。該表是 v1 遺留、v2 已無寫入點(全 grep ..._mapping_service.add( 零呼叫)。stg 該表 0 筆 → project_id 解出 NULL → insert ReviewMarkproject_id NOT NULL)→ IntegrityError 500。dev 因留 191 筆 v1 遺產才偶然能用。
  2. **localhost 404「稽核計畫不存在」**:改用 AP 鏈後仍 404 —— FR-040 規劃階段 round 根本沒有 AP(assessment_plan_id/ssp_id 皆 NULL,AP 要 launch_audit 才生),且 FE round 模式把 round uid 放進 URL /ap/<ap_uid> 段。以 AP 解析必查無。
  3. 控制項按不下去(FE)ctrlStatusFromAos summary 分支讀 total_tasks/completed_tasks 忽略 jobs,只有 jobs 無 task counts 時算出 total=0 → not_started;但進度條 ctrlProgress 讀 jobs → 100%。同一控制項「100%/未開始」,審閱 gate 看徽章 → 鎖死。AO 沒踩到(aoStatusFromAo 優先讀 jobs)。

方案規劃

BE:review resolve 改與 dashboard/control-tree 同源,從專案 living SSP 解控制集,不再依賴 AP 也不依賴 v1 mapping —— review 在任何階段皆可用:

projects(uid=project_uid) → project_extensions.living_ssp_id
  → ssp.import_profile_id → profile_imports.source_catalog_id → catalog_controls

project_uid 一路從 route 串到 repo(route 本就有此 path param)。ap_uid(=round uid)保留在 signature 但暫不參與解析。

FE:ctrlStatusFromAos 拿掉忽略 jobs 的 summary fallback,統一走 jobs(原 detail 分支邏輯一律套用),狀態與進度同源(100% ⇔ completed)。未引進新語意。

(被排除:只回填 stg mapping 資料 = 治標,新專案仍會壞,不採。)

實作狀態與紀錄

檔案 改動
BE api/grc/routes/review_route.py 4 endpoint 傳 project_uid
BE app/grc/service/review_service.py mark_/unmark_control/aoproject_uid
BE domain/grc/service/grc_review_domain_service.py add_review/remove_reviewproject_uid
BE domain/grc/repository/i_grc_review_repo.py interface 對齊 project_uid, ap_uid
BE infra/grc/repository/grc_review_repo_impl.py _resolve_control_ids 改 living SSP;移除 2 個未用 import
FE src/views/project/ProjectAuditorOverview.vue ctrlStatusFromAos 一致化(統一走 jobs)