盤點日期 2026-09-23|盤點卡 CM-2089|這份文件只盤點、不掃描——切好棒等首腦開卡派工。 行數全部是
wc -l逐檔實算。基準:BEfeature/reviewcommit2b595c976;jedi monorepofeature/reviewcommiteafc7ae5(jedi-compliance-audit/工作區乾淨)。每棒段落附兩側各自的驗證指令。
名詞先講清楚(讀者是 PM 與新手工程師):
jedi-compliance-audit,放在另一個 repo(~/Projects/Jedicogy/module/jedi-python-package/jedi-compliance-audit/)的一包程式,管「一輪稽核從開始到結案」。round_stage_transitions(階段歷程)、round_rollback_supersessions(回退標記)、ssp_reference_documents(程序書)、ssp_reference_document_mappings(程序書掛在哪個控制項)四張表:沒有客戶欄位、資料庫隔離沒開、一條規則都沒有(出貨版與 DEV 都一樣)。程式層只要漏一處歸屬檢查,資料就一路通到底。另外,稽核結果與改善計畫實際存在 oscal.assessment_*/oscal.poam* 八張表,也全部沒開隔離(DEV 實查)。audit_round_app_service.py 12 支對外方法中,9 支寫入都有「你在這個專案是什麼角色」的檢查,但 list_rounds、get_round、list_stage_transitions 三支讀取一行都沒有。第三支已是總表第 52 項(FR-088 H1 報過),前兩支沒有任何報告提過,而且外面只掛了「有登入」「客戶有買這個功能」兩道門。這是 C2a 的頭號問題。get_findings(整張判定矩陣)、list_risks、list_items(改善計畫清單)、get_item 四支,寫入同類都有角色檢查,讀取只有 _require_round… 這種「輪次查得到就放行」的檢查。沒有任何報告提過。這是 C3 的頭號問題。為什麼這幾件要先看:總表第 118/119/129 項已經證實這支套件的程式形狀是「只認編號、不問歸屬」,而上面四件是同一個形狀在別的功能上又出現——而且底下的資料表沒有隔離可以兜底。
⚠️ 以上是盤點時開檔看到的「疑點」,不是掃描結論。有沒有別的機制擋住(例如前端拿不到編號、別的中介層),要等掃描棒追完呼叫鏈才能下定論。
cd ~/Projects/Jedicogy/module/jedi-python-package/jedi-compliance-audit
git ls-files -- '*.py' | grep -v '^tests/' | xargs wc -l | tail -1 # 169 支、13,045 行正式程式 169 支/13,045 行(另有 tests 7 支/820 行不掃)。
⚠️ 卡片寫的「176 支/13,865 行」是誤植:把 tests 7 支 820 行也算進去了。以本文件為準。
169 支的去向:
| 分類 | 檔數 | 行數 | 說明 |
|---|---|---|---|
| 排進掃描棒 | 110 | 9,577 | 見第 2 節(去重後) |
| 死碼區,不派工 | 39 | 2,781 | 見 1.4 |
錯誤碼常數表 common/error_code.py |
1 | 483 | 純常數,不派工 |
harness/dev_app.py |
1 | 203 | 套件獨立測試用的假掛載(註解自陳「service 全是假的、不連 DB」),pyproject.toml 只打包 jedi_compliance_audit/,不進出貨包,不派工 |
空檔(0~1 行 __init__.py) |
18 | 1 | 不派工 |
| 合計 | 169 | 13,045 |
另有兩支不是 .py、但必須一起看的檔,已併入 C2a 與 C5 的重點: jedi_compliance_audit/migrations/001-compliance-audit-ui-routes.sql(19 行)、002-compliance-audit-rls.sql(92 行,稽核輪次與複核註記兩張表的隔離規則就在這支)。
三種方法交叉比對(前一棒做過,本棒在 HEAD 2b595c976 重跑確認數字不變):
# ① import grep
grep -rlE "(from|import) jedi_compliance_audit" --include='*.py' api app core di_containers infra domain config common | xargs wc -l | tail -1
# → 28 檔、11,557 行
# ② 從 core/plugins/compliance_audit.py 與 DI 容器反查(套件的 service 被哪些 provider 建、被誰注入)
# ③ 全文字串 grep(例如 "audit_service"、"flow_control_container" 這類用字串指名的接法)28 檔/11,557 行,三種方法結果一致。
另外用 ②③ 反查多抓到 3 支 import 抓不到的檔:前兩支納入 C1b,第三支納入 C2a。
| 檔 | 行數 | 為什麼 import 抓不到 | 為什麼要納入 |
|---|---|---|---|
app/readmodel/service/auditor_dashboard_service.py |
14 | 套件路由用字串 runtime().service("auditor_dashboard_service") 取服務,實際物件是主專案 DI 建的 |
套件的「稽核人員待辦清單」路由背後真正做事的是主專案這兩支,不看它們等於沒看這條路 |
infra/readmodel/audit/auditor_dashboard_query.py |
118 | 同上 | 同上;查詢條件是 pp.user_id = :uid,要確認沒有別的路徑能換人查 |
api/project/serializers/audit_round.py |
239 | 只在註解提到套件的服務名,沒有 import | 是 audit_round_route.py 32 個端點的請求/回應格式,路由少了它就看不到收什麼欄位 |
每一支都回頭對過該棒的卡片或報告裡的檔案清單。
| 檔 | 行數 | 哪一棒掃過 |
|---|---|---|
app/oscal/service/ssp_control_implementation_service.py |
1,037 | FR-113 O1 |
app/oscal/service/ssp_document_pool_service.py |
313 | FR-113 O6(第 118/119/129 項就在這支) |
app/oscal/service/ssp_control_impl_import_service.py |
416 | FR-113 O4 |
app/module_frame/service/module_frame_reference_document_service.py |
257 | FR-113 B2 |
app/module_frame/service/ssp_import_template_app_service.py |
1,500 | FR-113 B4 |
di_containers/module_frame/module_frame_containers.py |
260 | FR-113 B1 |
app/project/service/project_start_app_service.py |
481 | FR-095 H1 |
app/flow_control/service/project_service.py |
789 | FR-095 H1(並排在 FR-095 H2 CM-1783,尚未派) |
infra/flow_control/repository/flow_control_project_repo_impl.py |
716 | FR-095 H1 |
di_containers/flow_control/flow_control_containers.py |
753 | FR-095 H1 |
di_containers/project/project_containers.py |
70 | FR-095 H1 |
di_containers/flow_engine/workflow_excution_containers.py |
155 | FR-095 H1(FR-088 H4 也掃過) |
api/flow_engine/routes/stage_rollback_route.py |
67 | FR-088 H1 |
app/flow_engine/service/stage_advance_service.py |
702 | FR-088 H1 |
infra/readmodel/audit/flow_control_dashboard_repo_impl.py |
254 | FR-095 H2(CM-1783,已開卡、尚未派) |
infra/flow_control/repository/flow_control_job_repo_impl.py |
1,216 | FR-115 W4(CM-2093,已開卡、尚未派) |
infra/readmodel/tasks/job_export_query.py |
264 | FR-115 W4(CM-2093,已開卡、尚未派) |
| 合計 | 9,000 | 17 檔 |
⚠️ 交接說明裡寫「已掃過」的 api/flow_control/routes/project_route.py,查證後不成立:它只在 FR-088 H3 報告裡被引用當範例(「同 repo 讀取端點掛能力點的做法可抄這支」),不在任何一棒的掃描範圍內。本盤點改判「沒查過」,排進 C1c。
⚠️ api/flow_control/__init__.py 在 FR-095 H2 卡片範圍內,但那張卡還沒派。它是本套件掛上網址的唯一入口(attach() 在這裡被呼叫),放進 C1 當接縫檔;H2 若先派,C1 可以只讀不報。
⚠️ 交接說明提到的兩支懸案(infra/oscal/repository/ssp_catalog_title_query.py、di_containers/oscal/oscal_containers.py)維持前一棒判斷:只在 FR-113 O9 清單上出現過、O9 本體沒派、拆出的 O9a/O9b 也不含它們,當作沒查過,排進 C5。
這一區是舊版資料模型留下來、現在已經打不到的程式。盤點時逐條確認過「打不打得到」:
| 群組 | 檔數 | 行數 | 為什麼打不到 |
|---|---|---|---|
audit_service.py+其 domain/repo/mapper/DTO |
7 | 836 | DI 有建這個服務、core/plugins/compliance_audit.py:118 也登記給套件,但套件五條路由只取 review/task_setup/current-ssp/auditor_dashboard 四個服務(routing.py 逐條對過),全 codebase(兩個 repo)沒有任何呼叫者。底下 repo 的 13 個方法全部寫死回空值(flow_control_audit_repo_impl.py:34-77) |
poam_service.py+其 domain/repo/mapper/model/DTO |
8 | 522 | 同上:DI 有、登記有、沒有任何呼叫者。repo 的 list_poams/get_poam 寫死回空(poam_repo_impl.py:36-52),所以 update_poam 的第一步 get_poam 永遠回 None → 404,打不到後面那句「只用編號更新」(poam_repo_impl.py:55-56) |
| 控制項/控制群組/評估物件三組 repo+DTO+entity | 22 | 1,355 | DI 有建 domain service(flow_control_containers.py:385-406),但沒有任何服務注入它們;三支 repo 全部方法寫死回空(檔頭自陳「依附舊 OSCAL 資料模型,v2 切換後停用待重建」) |
oscal_audit_query.py |
1 | 68 | DI 注入給 AllTasksAssignedCheck,但那個檢查的 check() 直接 return ok(),從不呼叫它;本身 7 個方法也全部寫死回空 |
round_stage_transition_query_entity.py |
1 | 8 | 零引用 |
判斷:死碼不掃。但有兩點要首腦知道:
poam_service.py/audit_service.py「零守門」確認打不到,不成立為發現;poam_repo_impl.update_poam 那句「只用編號」的查詢也是死碼,列在第 4 節對照表但標「死碼」。core/plugins/compliance_audit.py:118,120 與 flow_control_containers.py:523-556)。哪天有人把它接回路由,零守門的服務會直接上線。建議併入 FR-092(死碼清理)的後續,把這 39 支連同 DI 登記一起刪——這是清理建議,不是資安發現。| 檔數 | 行數 | |
|---|---|---|
| 套件側 | 110 | 9,577 |
| 主專案側(28 − 排除 17 + 反查補入 3) | 14 | 2,678 |
| 合計(去重) | 124 | 12,255 |
# 套件側:預期 110 檔、9,577 行(把第 2 節各棒套件清單合併去重)
# 主專案側:預期 14 檔、2,678 行
cd ~/Projects/Billows/Audit-Manager/compliance-manager-be && git ls-files -- \
core/plugins/compliance_audit.py api/flow_control/__init__.py \
app/readmodel/service/auditor_dashboard_service.py infra/readmodel/audit/auditor_dashboard_query.py \
api/flow_control/routes/project_route.py api/flow_control/routes/assessment_plan_route.py \
api/project/routes/audit_round_route.py api/project/serializers/audit_round.py \
app/flow_control/service/prep_job_generation_service.py \
api/project/routes/ap_docx_import_route.py api/project/routes/ar_import_route.py \
app/oscal/dto/ssp/ssp_reference_document_dto.py di_containers/oscal/oscal_containers.py \
infra/oscal/repository/ssp_catalog_title_query.py | xargs wc -l | tail -1切法原則:按業務功能縱切——同一個功能的「主專案網址入口 → 套件服務 → 套件 domain → 套件 repo → 資料表 model」放同一棒。權限漏洞活在「兩側接縫」上:只給套件或只給主專案,兩邊都看不出來。
接縫檔(刻意在兩棒重複列):audit_round_app_service.py(C2a/C2b)、audit_round_route.py(C2a/C3)、api/guards.py(C1/C1b)、common/guard.py(C1/C3)、import_adapter/ 兩支(C4a/C4b)。
| 棒 | 做什麼 | 檔數 | 行數 | 套件/主專案 |
|---|---|---|---|---|
| C1 | 接線總裝+審閱簽核 | 22 | 1,739 | 20/2 |
| C1b | 任務設定樹、目前 SSP、稽核人員待辦清單 | 21 | 1,404 | 19/2 |
| C1c | 專案清單/詳細與稽核計畫選單的主專案路由 | 11 | 1,255 | 9/2 |
| C2a | 🔴 稽核輪次主體(開輪、啟動、結案、讀取) | 10 | 1,939 | 8/2 |
| C2b | 階段歷程、回退標記、規劃完成度檢查 | 15 | 1,612 | 14/1 |
| C3 | 🔴 稽核結果(判定、觀察、風險)與改善計畫 | 6 | 1,934 | 5/1 |
| C4a | 稽核計畫 Word 匯入 | 14 | 1,271 | 13/1 |
| C4b | 稽核結果 Excel 匯入 | 19 | 1,585 | 18/1 |
| C5 | 程序書文件池的資料層+兩支懸案檔 | 12 | 1,213 | 9/3 |
| 逐棒加總(含接縫重複) | 130 | 13,952 |
逐棒加總扣掉接縫重複(audit_round_app_service.py 925、audit_round_route.py 508、api/guards.py 125、common/guard.py 76、method_keywords.py 35、registry_base.py 28,共 6 支次、1,697 行)= 124 檔、12,255 行,與 1.5 一致。
前一棒把「稽核輪次主體+階段歷程+回退標記+規劃檢查+路由」放在同一棒,2,454 行超標。本棒先實算 audit_round_app_service.py 裡碰「歷程/回退」的比例:只有 7 行呼叫(:804、:806、:857 寫回退標記,:813、:836、:863 寫歷程,:877 讀歷程),全部集中在三支 rollback_to_* 與 list_stage_transitions。歷程與回退不是主體邏輯,是附掛的紀錄表。
所以拆法是:
另外兩個調整讓 C2a 壓進 2,000 行:
common/guard.py 在 C1、C3 都有,C2a 不再重複(研究員追呼叫可越界讀)。⚠️ 不用擔心兩棒各自膨脹:接縫檔只有 audit_round_app_service.py 一支(925 行),C2a 1,939、C2b 1,612 都在門檻內。
這一棒要回答:套件拿到的三道守門是不是主專案真的那三道;審閱簽核的角色檢查「零件沒裝就跳過」這個寫法,現在是不是每一處都有裝。
套件側(cd ~/Projects/Jedicogy/module/jedi-python-package/jedi-compliance-audit)
24 jedi_compliance_audit/__init__.py
37 jedi_compliance_audit/api/__init__.py
125 jedi_compliance_audit/api/guards.py ← 路由層守門(接縫,C1b 也帶)
56 jedi_compliance_audit/api/routing.py ← 套件自帶的 5 條網址
124 jedi_compliance_audit/plugin/__init__.py
92 jedi_compliance_audit/plugin/assembly.py ← 「守門沒接好就拒絕掛載」在這
124 jedi_compliance_audit/plugin/contract.py
41 jedi_compliance_audit/plugin/runtime.py
64 jedi_compliance_audit/plugin/wiring.py ← 把守門綁進服務層
39 jedi_compliance_audit/domain/ports.py
76 jedi_compliance_audit/common/guard.py ← 服務層守門(接縫,C3 也帶)
53 jedi_compliance_audit/api/routes/review_route.py
12 jedi_compliance_audit/api/serializers/review.py
129 jedi_compliance_audit/app/service/review_service.py ← 🔴「零件沒裝就跳過」寫法
32 jedi_compliance_audit/app/dto/review_dto.py
52 jedi_compliance_audit/domain/entities/flow_control_review_entity.py
44 jedi_compliance_audit/domain/repository/i_flow_control_review_repo.py
40 jedi_compliance_audit/domain/service/flow_control_review_domain_service.py
238 jedi_compliance_audit/infra/repository/flow_control_review_repo_impl.py
17 jedi_compliance_audit/infra/model/review_mark.py
主專案側(cd ~/Projects/Billows/Audit-Manager/compliance-manager-be)
185 core/plugins/compliance_audit.py ← 三道守門實際給什麼
135 api/flow_control/__init__.py ← attach() 呼叫點
共 22 檔/1,739 行(套件 20/1,419+主專案 2/320)。
驗證:
cd ~/Projects/Jedicogy/module/jedi-python-package/jedi-compliance-audit && git ls-files -- jedi_compliance_audit/__init__.py jedi_compliance_audit/api/__init__.py jedi_compliance_audit/api/guards.py jedi_compliance_audit/api/routing.py jedi_compliance_audit/plugin/__init__.py jedi_compliance_audit/plugin/assembly.py jedi_compliance_audit/plugin/contract.py jedi_compliance_audit/plugin/runtime.py jedi_compliance_audit/plugin/wiring.py jedi_compliance_audit/domain/ports.py jedi_compliance_audit/common/guard.py jedi_compliance_audit/api/routes/review_route.py jedi_compliance_audit/api/serializers/review.py jedi_compliance_audit/app/service/review_service.py jedi_compliance_audit/app/dto/review_dto.py jedi_compliance_audit/domain/entities/flow_control_review_entity.py jedi_compliance_audit/domain/repository/i_flow_control_review_repo.py jedi_compliance_audit/domain/service/flow_control_review_domain_service.py jedi_compliance_audit/infra/repository/flow_control_review_repo_impl.py jedi_compliance_audit/infra/model/review_mark.py | xargs wc -l | tail -1 # 20 檔、1419
cd ~/Projects/Billows/Audit-Manager/compliance-manager-be && git ls-files -- core/plugins/compliance_audit.py api/flow_control/__init__.py | xargs wc -l | tail -1 # 2 檔、320這一棒要回答:套件自帶的三條「只讀」網址背後,有沒有任何一道「你是不是這個專案的人」的檢查。
套件側
125 jedi_compliance_audit/api/guards.py ← 接縫(C1 也帶)
32 jedi_compliance_audit/api/routes/task_setup_route.py ← 只掛登入+商務授權
57 jedi_compliance_audit/api/serializers/task_setup.py
29 jedi_compliance_audit/app/service/task_setup_service.py ← 🔴 0 守門
97 jedi_compliance_audit/app/dto/task_setup_dto.py
64 jedi_compliance_audit/domain/entities/flow_control_task_setup_entity.py
11 jedi_compliance_audit/domain/repository/i_flow_control_task_setup_repo.py
10 jedi_compliance_audit/domain/service/flow_control_task_setup_domain_service.py
397 jedi_compliance_audit/infra/repository/flow_control_task_setup_repo_impl.py ← 🔴 編號三猜
35 jedi_compliance_audit/api/routes/project_current_ssp_route.py
69 jedi_compliance_audit/app/service/project_current_ssp_service.py ← 🔴 0 守門
37 jedi_compliance_audit/api/routes/auditor_dashboard_route.py
50 jedi_compliance_audit/api/serializers/auditor_dashboard.py
19 jedi_compliance_audit/domain/entities/project_extension_entity.py
12 jedi_compliance_audit/domain/entities/project_extension_query_entity.py
26 jedi_compliance_audit/domain/repository/i_project_extension_repo.py
46 jedi_compliance_audit/domain/service/project_extension_domain_service.py
127 jedi_compliance_audit/infra/repository/project_extension_repo_impl.py
29 jedi_compliance_audit/infra/mapper/project_extension_mapper.py
主專案側
14 app/readmodel/service/auditor_dashboard_service.py ← 反查補入
118 infra/readmodel/audit/auditor_dashboard_query.py ← 反查補入
共 21 檔/1,404 行(套件 19/1,272+主專案 2/132)。
驗證:
cd ~/Projects/Jedicogy/module/jedi-python-package/jedi-compliance-audit && git ls-files -- jedi_compliance_audit/api/guards.py jedi_compliance_audit/api/routes/task_setup_route.py jedi_compliance_audit/api/serializers/task_setup.py jedi_compliance_audit/app/service/task_setup_service.py jedi_compliance_audit/app/dto/task_setup_dto.py jedi_compliance_audit/domain/entities/flow_control_task_setup_entity.py jedi_compliance_audit/domain/repository/i_flow_control_task_setup_repo.py jedi_compliance_audit/domain/service/flow_control_task_setup_domain_service.py jedi_compliance_audit/infra/repository/flow_control_task_setup_repo_impl.py jedi_compliance_audit/api/routes/project_current_ssp_route.py jedi_compliance_audit/app/service/project_current_ssp_service.py jedi_compliance_audit/api/routes/auditor_dashboard_route.py jedi_compliance_audit/api/serializers/auditor_dashboard.py jedi_compliance_audit/domain/entities/project_extension_entity.py jedi_compliance_audit/domain/entities/project_extension_query_entity.py jedi_compliance_audit/domain/repository/i_project_extension_repo.py jedi_compliance_audit/domain/service/project_extension_domain_service.py jedi_compliance_audit/infra/repository/project_extension_repo_impl.py jedi_compliance_audit/infra/mapper/project_extension_mapper.py | xargs wc -l | tail -1 # 19 檔、1272
cd ~/Projects/Billows/Audit-Manager/compliance-manager-be && git ls-files -- app/readmodel/service/auditor_dashboard_service.py infra/readmodel/audit/auditor_dashboard_query.py | xargs wc -l | tail -1 # 2 檔、132這一棒要回答:主專案這兩支路由檔從沒被掃過(project_route.py 只被引用當範例、assessment_plan_route.py 只被 FR-095 H1 順帶查了一支選單)。背後的服務 project_service.py 已掃過,本棒只看路由層有沒有漏掛能力點、有沒有把網址上的編號不經比對就往下傳。
套件側
248 jedi_compliance_audit/api/serializers/project.py
54 jedi_compliance_audit/api/serializers/assessment_plan.py
157 jedi_compliance_audit/app/dto/project_dto.py
50 jedi_compliance_audit/app/dto/assessment_plan_dto.py
58 jedi_compliance_audit/domain/entities/flow_control_project_entity.py
15 jedi_compliance_audit/domain/entities/flow_control_project_query_entity.py
109 jedi_compliance_audit/domain/repository/i_flow_control_project_repo.py
59 jedi_compliance_audit/domain/service/flow_control_project_domain_service.py
115 jedi_compliance_audit/infra/mapper/flow_control_project_mapper.py
主專案側
273 api/flow_control/routes/project_route.py
117 api/flow_control/routes/assessment_plan_route.py
共 11 檔/1,255 行(套件 9/865+主專案 2/390)。
驗證:
cd ~/Projects/Jedicogy/module/jedi-python-package/jedi-compliance-audit && git ls-files -- jedi_compliance_audit/api/serializers/project.py jedi_compliance_audit/api/serializers/assessment_plan.py jedi_compliance_audit/app/dto/project_dto.py jedi_compliance_audit/app/dto/assessment_plan_dto.py jedi_compliance_audit/domain/entities/flow_control_project_entity.py jedi_compliance_audit/domain/entities/flow_control_project_query_entity.py jedi_compliance_audit/domain/repository/i_flow_control_project_repo.py jedi_compliance_audit/domain/service/flow_control_project_domain_service.py jedi_compliance_audit/infra/mapper/flow_control_project_mapper.py | xargs wc -l | tail -1 # 9 檔、865
cd ~/Projects/Billows/Audit-Manager/compliance-manager-be && git ls-files -- api/flow_control/routes/project_route.py api/flow_control/routes/assessment_plan_route.py | xargs wc -l | tail -1 # 2 檔、390這一棒要回答:開輪、啟動稽核、開始稽核、結案、覆核輪、三種回退,每一支的角色檢查對不對;兩支讀取(輪次清單、單筆輪次)為什麼沒有角色檢查。
套件側
925 jedi_compliance_audit/app/service/audit_round_app_service.py ← 接縫(C2b 也帶);12 支對外方法
29 jedi_compliance_audit/domain/entities/project_audit_round_entity.py
17 jedi_compliance_audit/domain/entities/project_audit_round_query_entity.py
30 jedi_compliance_audit/domain/repository/i_project_audit_round_repo.py
37 jedi_compliance_audit/domain/service/project_audit_round_domain_service.py
77 jedi_compliance_audit/infra/repository/project_audit_round_repo_impl.py ← get_by_uid 只用編號
34 jedi_compliance_audit/infra/mapper/project_audit_round_mapper.py
43 jedi_compliance_audit/infra/model/project_audit_round.py
主專案側
508 api/project/routes/audit_round_route.py ← 接縫(C3 也帶);32 個端點
239 api/project/serializers/audit_round.py
共 10 檔/1,939 行(套件 8/1,192+主專案 2/747)。 附帶讀:jedi_compliance_audit/migrations/002-compliance-audit-rls.sql(92 行,輪次表的隔離規則)。
驗證:
cd ~/Projects/Jedicogy/module/jedi-python-package/jedi-compliance-audit && git ls-files -- jedi_compliance_audit/app/service/audit_round_app_service.py jedi_compliance_audit/domain/entities/project_audit_round_entity.py jedi_compliance_audit/domain/entities/project_audit_round_query_entity.py jedi_compliance_audit/domain/repository/i_project_audit_round_repo.py jedi_compliance_audit/domain/service/project_audit_round_domain_service.py jedi_compliance_audit/infra/repository/project_audit_round_repo_impl.py jedi_compliance_audit/infra/mapper/project_audit_round_mapper.py jedi_compliance_audit/infra/model/project_audit_round.py | xargs wc -l | tail -1 # 8 檔、1192
cd ~/Projects/Billows/Audit-Manager/compliance-manager-be && git ls-files -- api/project/routes/audit_round_route.py api/project/serializers/audit_round.py | xargs wc -l | tail -1 # 2 檔、747這一棒要回答:歷程與回退兩張表(隔離全關)的讀寫,呼叫端有沒有先確認「這個輪次是你的」;規劃完成度檢查在查詢失敗時「放行」的寫法會不會被利用。
套件側
925 jedi_compliance_audit/app/service/audit_round_app_service.py ← 接縫(C2a 也帶)
19 jedi_compliance_audit/domain/entities/round_stage_transition_entity.py
12 jedi_compliance_audit/domain/repository/i_round_stage_transition_repo.py
17 jedi_compliance_audit/domain/service/round_stage_transition_domain_service.py
36 jedi_compliance_audit/infra/repository/round_stage_transition_repo_impl.py
35 jedi_compliance_audit/infra/mapper/round_stage_transition_mapper.py
25 jedi_compliance_audit/infra/model/round_stage_transition.py
20 jedi_compliance_audit/domain/entities/round_rollback_supersession_entity.py
21 jedi_compliance_audit/domain/repository/i_round_rollback_supersession_repo.py
37 jedi_compliance_audit/domain/service/round_rollback_supersession_domain_service.py
55 jedi_compliance_audit/infra/repository/round_rollback_supersession_repo_impl.py
33 jedi_compliance_audit/infra/mapper/round_rollback_supersession_mapper.py
23 jedi_compliance_audit/infra/model/round_rollback_supersession.py
128 jedi_compliance_audit/app/service/planning_readiness_checker.py ← 兩處查詢失敗就放行
主專案側
226 app/flow_control/service/prep_job_generation_service.py ← 覆核輪產生證據蒐集任務
共 15 檔/1,612 行(套件 14/1,386+主專案 1/226)。
驗證:
cd ~/Projects/Jedicogy/module/jedi-python-package/jedi-compliance-audit && git ls-files -- jedi_compliance_audit/app/service/audit_round_app_service.py jedi_compliance_audit/domain/entities/round_stage_transition_entity.py jedi_compliance_audit/domain/repository/i_round_stage_transition_repo.py jedi_compliance_audit/domain/service/round_stage_transition_domain_service.py jedi_compliance_audit/infra/repository/round_stage_transition_repo_impl.py jedi_compliance_audit/infra/mapper/round_stage_transition_mapper.py jedi_compliance_audit/infra/model/round_stage_transition.py jedi_compliance_audit/domain/entities/round_rollback_supersession_entity.py jedi_compliance_audit/domain/repository/i_round_rollback_supersession_repo.py jedi_compliance_audit/domain/service/round_rollback_supersession_domain_service.py jedi_compliance_audit/infra/repository/round_rollback_supersession_repo_impl.py jedi_compliance_audit/infra/mapper/round_rollback_supersession_mapper.py jedi_compliance_audit/infra/model/round_rollback_supersession.py jedi_compliance_audit/app/service/planning_readiness_checker.py | xargs wc -l | tail -1 # 14 檔、1386
cd ~/Projects/Billows/Audit-Manager/compliance-manager-be && git ls-files -- app/flow_control/service/prep_job_generation_service.py | xargs wc -l | tail -1 # 1 檔、226這一棒要回答:判定矩陣、風險清單、改善計畫清單與單筆這四支讀取為什麼只查「輪次存不存在」;寫入類刪除時,被刪的那筆有沒有確實屬於網址上那一輪。
套件側
828 jedi_compliance_audit/app/service/assessment_result_app_service.py ← 16 支對外方法
434 jedi_compliance_audit/app/service/poam_app_service.py ← 8 支對外方法
42 jedi_compliance_audit/app/service/ao_derivation.py
76 jedi_compliance_audit/common/guard.py ← 接縫(C1 也帶)
46 jedi_compliance_audit/common/round_guard.py
主專案側
508 api/project/routes/audit_round_route.py ← 接縫(C2a 也帶)
共 6 檔/1,934 行(套件 5/1,426+主專案 1/508)。
刻意做成大檔少數棒:兩支服務合計 1,262 行、24 支對外方法,而且直接呼叫 jedi-oscal-v2 套件十幾支 repo(稽核結果、改善計畫的資料實際存在 oscal.* 表)。研究員要越界讀 oscal-v2 的 repo 看查詢條件——那是必要的,但不報 oscal-v2 本身的問題(歸 FR-113/M11)。
驗證:
cd ~/Projects/Jedicogy/module/jedi-python-package/jedi-compliance-audit && git ls-files -- jedi_compliance_audit/app/service/assessment_result_app_service.py jedi_compliance_audit/app/service/poam_app_service.py jedi_compliance_audit/app/service/ao_derivation.py jedi_compliance_audit/common/guard.py jedi_compliance_audit/common/round_guard.py | xargs wc -l | tail -1 # 5 檔、1426
cd ~/Projects/Billows/Audit-Manager/compliance-manager-be && git ls-files -- api/project/routes/audit_round_route.py | xargs wc -l | tail -1 # 1 檔、508這一棒要回答:上傳 → 解析 → 預覽 → 確認四步,每一步是不是都有「專案角色」+「這份解析工作屬於你們公司」兩道檢查;上傳的 Word 檔解析時有沒有吃檔案的風險。
套件側
375 jedi_compliance_audit/app/service/ap_docx_import_app_service.py
23 jedi_compliance_audit/app/service/ap_report_parser/__init__.py
382 jedi_compliance_audit/app/service/ap_report_parser/airasia_cmmc_l1_v1.py ← Word 解析器
43 jedi_compliance_audit/app/service/ap_report_parser/base.py
26 jedi_compliance_audit/app/service/ap_report_parser/registry.py
35 jedi_compliance_audit/app/service/import_adapter/method_keywords.py ← 接縫(C4b 也帶)
28 jedi_compliance_audit/app/service/import_adapter/registry_base.py ← 接縫(C4b 也帶)
39 jedi_compliance_audit/domain/entities/ap_docx_parse_job_entity.py
25 jedi_compliance_audit/domain/repository/i_ap_docx_parse_job_repo.py
64 jedi_compliance_audit/domain/service/ap_docx_parse_job_domain_service.py
54 jedi_compliance_audit/infra/repository/ap_docx_parse_job_repo_impl.py
33 jedi_compliance_audit/infra/mapper/ap_docx_parse_job_mapper.py
28 jedi_compliance_audit/infra/model/ap_docx_parse_job.py
主專案側
116 api/project/routes/ap_docx_import_route.py
共 14 檔/1,271 行(套件 13/1,155+主專案 1/116)。
驗證:
cd ~/Projects/Jedicogy/module/jedi-python-package/jedi-compliance-audit && git ls-files -- jedi_compliance_audit/app/service/ap_docx_import_app_service.py jedi_compliance_audit/app/service/ap_report_parser/__init__.py jedi_compliance_audit/app/service/ap_report_parser/airasia_cmmc_l1_v1.py jedi_compliance_audit/app/service/ap_report_parser/base.py jedi_compliance_audit/app/service/ap_report_parser/registry.py jedi_compliance_audit/app/service/import_adapter/method_keywords.py jedi_compliance_audit/app/service/import_adapter/registry_base.py jedi_compliance_audit/domain/entities/ap_docx_parse_job_entity.py jedi_compliance_audit/domain/repository/i_ap_docx_parse_job_repo.py jedi_compliance_audit/domain/service/ap_docx_parse_job_domain_service.py jedi_compliance_audit/infra/repository/ap_docx_parse_job_repo_impl.py jedi_compliance_audit/infra/mapper/ap_docx_parse_job_mapper.py jedi_compliance_audit/infra/model/ap_docx_parse_job.py | xargs wc -l | tail -1 # 13 檔、1155
cd ~/Projects/Billows/Audit-Manager/compliance-manager-be && git ls-files -- api/project/routes/ap_docx_import_route.py | xargs wc -l | tail -1 # 1 檔、116這一棒要回答:同 C4a 四步;另外 Excel 匯入會「自動配對證據」——配對時撈的證據範圍有沒有可能撈到別的輪次、別的客戶。
套件側
610 jedi_compliance_audit/app/service/ar_import_app_service.py
23 jedi_compliance_audit/app/service/ar_report_parser/__init__.py
195 jedi_compliance_audit/app/service/ar_report_parser/airasia_cmmc_l1_ar_v1.py ← Excel 解析器
43 jedi_compliance_audit/app/service/ar_report_parser/base.py
22 jedi_compliance_audit/app/service/ar_report_parser/registry.py
37 jedi_compliance_audit/app/service/ar_framework_profile/cmmc_l1.py
17 jedi_compliance_audit/app/service/ar_import/aggregation.py
33 jedi_compliance_audit/app/service/ar_import/ao_alignment.py
107 jedi_compliance_audit/app/service/ar_import/evidence_matcher.py
35 jedi_compliance_audit/app/service/import_adapter/method_keywords.py ← 接縫
28 jedi_compliance_audit/app/service/import_adapter/registry_base.py ← 接縫
40 jedi_compliance_audit/domain/entities/ar_xlsx_parse_job_entity.py
29 jedi_compliance_audit/domain/repository/i_ar_xlsx_parse_job_repo.py
70 jedi_compliance_audit/domain/service/ar_xlsx_parse_job_domain_service.py
65 jedi_compliance_audit/infra/repository/ar_xlsx_parse_job_repo_impl.py
34 jedi_compliance_audit/infra/mapper/ar_xlsx_parse_job_mapper.py
28 jedi_compliance_audit/infra/model/ar_xlsx_parse_job.py
53 jedi_compliance_audit/infra/repository/wf_control_mapping_lookup_query.py ← 🔴 輪次可不帶
主專案側
116 api/project/routes/ar_import_route.py
共 19 檔/1,585 行(套件 18/1,469+主專案 1/116)。
驗證:
cd ~/Projects/Jedicogy/module/jedi-python-package/jedi-compliance-audit && git ls-files -- jedi_compliance_audit/app/service/ar_import_app_service.py jedi_compliance_audit/app/service/ar_report_parser/__init__.py jedi_compliance_audit/app/service/ar_report_parser/airasia_cmmc_l1_ar_v1.py jedi_compliance_audit/app/service/ar_report_parser/base.py jedi_compliance_audit/app/service/ar_report_parser/registry.py jedi_compliance_audit/app/service/ar_framework_profile/cmmc_l1.py jedi_compliance_audit/app/service/ar_import/aggregation.py jedi_compliance_audit/app/service/ar_import/ao_alignment.py jedi_compliance_audit/app/service/ar_import/evidence_matcher.py jedi_compliance_audit/app/service/import_adapter/method_keywords.py jedi_compliance_audit/app/service/import_adapter/registry_base.py jedi_compliance_audit/domain/entities/ar_xlsx_parse_job_entity.py jedi_compliance_audit/domain/repository/i_ar_xlsx_parse_job_repo.py jedi_compliance_audit/domain/service/ar_xlsx_parse_job_domain_service.py jedi_compliance_audit/infra/repository/ar_xlsx_parse_job_repo_impl.py jedi_compliance_audit/infra/mapper/ar_xlsx_parse_job_mapper.py jedi_compliance_audit/infra/model/ar_xlsx_parse_job.py jedi_compliance_audit/infra/repository/wf_control_mapping_lookup_query.py | xargs wc -l | tail -1 # 18 檔、1469
cd ~/Projects/Billows/Audit-Manager/compliance-manager-be && git ls-files -- api/project/routes/ar_import_route.py | xargs wc -l | tail -1 # 1 檔、116這一棒要回答:第 118/119/129 項的根因在這一層(已知,不重報);本棒要找的是同一個 repo 裡還沒被報過的其他方法有沒有同樣「只認編號」的形狀,以及 DI 組裝有沒有把文件池接到不該接的地方。
套件側
22 jedi_compliance_audit/domain/entities/ssp_reference_document_entity.py
31 jedi_compliance_audit/domain/repository/i_ssp_reference_document_repo.py
46 jedi_compliance_audit/domain/repository/i_ssp_document_pool_query.py
27 jedi_compliance_audit/domain/service/ssp_reference_document_domain_service.py
83 jedi_compliance_audit/infra/repository/ssp_reference_document_repo_impl.py ← 第 118/119 根因
263 jedi_compliance_audit/infra/repository/ssp_document_pool_query.py ← 第 129 根因
27 jedi_compliance_audit/infra/mapper/ssp_reference_document_mapper.py
43 jedi_compliance_audit/infra/model/ssp_reference_document.py
40 jedi_compliance_audit/infra/model/ssp_reference_document_mapping.py
主專案側
29 app/oscal/dto/ssp/ssp_reference_document_dto.py
509 di_containers/oscal/oscal_containers.py ← 懸案檔(O9 只列不掃)
93 infra/oscal/repository/ssp_catalog_title_query.py ← 懸案檔(O9 只列不掃)
共 12 檔/1,213 行(套件 9/582+主專案 3/631)。 附帶讀:兩張程序書表在 scripts/init/02-schema.sql 的建表段(沒有隔離規則,確認用)。
驗證:
cd ~/Projects/Jedicogy/module/jedi-python-package/jedi-compliance-audit && git ls-files -- jedi_compliance_audit/domain/entities/ssp_reference_document_entity.py jedi_compliance_audit/domain/repository/i_ssp_reference_document_repo.py jedi_compliance_audit/domain/repository/i_ssp_document_pool_query.py jedi_compliance_audit/domain/service/ssp_reference_document_domain_service.py jedi_compliance_audit/infra/repository/ssp_reference_document_repo_impl.py jedi_compliance_audit/infra/repository/ssp_document_pool_query.py jedi_compliance_audit/infra/mapper/ssp_reference_document_mapper.py jedi_compliance_audit/infra/model/ssp_reference_document.py jedi_compliance_audit/infra/model/ssp_reference_document_mapping.py | xargs wc -l | tail -1 # 9 檔、582
cd ~/Projects/Billows/Audit-Manager/compliance-manager-be && git ls-files -- app/oscal/dto/ssp/ssp_reference_document_dto.py di_containers/oscal/oscal_containers.py infra/oscal/repository/ssp_catalog_title_query.py | xargs wc -l | tail -1 # 3 檔、631① 算「守門次數」對「對外方法數」:
grep -c "require_\|authz\|permission\|Forbidden\|Permission\|assert_project\|_check_role\|_check_auditor\|_check_manager\|_check_participant" <檔>
grep -c "^ def [a-zA-Z]" <檔>守門 0 次不一定有洞(repo 層本來就不該有守門),但要說得出「守門在哪一層」。盤點時先跑了一輪,服務層與路由層 0 命中的:
| 檔 | 守門 | 對外方法 | 在哪棒 | 盤點時看到的 |
|---|---|---|---|---|
app/service/task_setup_service.py |
🔴 0 | 1 | C1b | 路由只掛登入+商務授權,往下到 repo 也沒看到角色檢查 |
app/service/project_current_ssp_service.py |
🔴 0 | 1 | C1b | 同上;回傳專案目前 SSP 的編號,那個編號是其他 SSP 端點的鑰匙 |
app/readmodel/service/auditor_dashboard_service.py(主專案) |
0 | 1 | C1b | 查詢條件是「呼叫者本人」(pp.user_id = :uid,uid 由伺服器端取),預期不是洞,確認即可 |
app/service/planning_readiness_checker.py |
2(都是註解字樣) | 1 | C2b | 不是網址入口,是推進前的軟提醒;兩處「查詢失敗就放行」(:70、:85) |
app/flow_control/service/prep_job_generation_service.py(主專案) |
0 | 1 | C2b | 被 audit_round_app_service.launch_reverify 呼叫,上游有角色檢查;確認沒有別的呼叫端 |
逐方法看(盤點時用腳本逐支對過,列出「對外方法裡一行守門都沒有」的):
| 檔 | 沒守門的對外方法 | 備註 |
|---|---|---|
audit_round_app_service.py |
🔴 list_rounds、get_round、list_stage_transitions |
第三支=總表第 52 項,前兩支沒人報過 |
assessment_result_app_service.py |
init_ar_matrix_for_round、narrowed_control_ids_for、narrowed_control_ids_from_parent、finalize_assessment |
四支都是「被別的服務在交易中呼叫」的內部方法(docstring 自陳),確認沒有網址直接打到即可 |
assessment_result_app_service.py |
🔴 get_findings、list_risks |
只有 _require_round_ar_result(..., writable=False)=只查輪次存不存在 |
assessment_result_app_service.py |
get_ao_counts_by_control |
同上形狀,但唯一呼叫端是 ar_import_app_service.py:167(上游已驗角色),不是網址入口 |
poam_app_service.py |
🔴 list_items、get_item |
只有 _require_round_poam(..., writable=False)=只查輪次存不存在 |
poam_app_service.py |
all_items_closed |
內部方法(結案時呼叫) |
ar_import_app_service.py |
upload_and_parse 本身 0 行 |
但它第一行呼叫 self._ar.resolve_round_for_import(),那一支有完整角色檢查,不是洞 |
② 找「檢查甲、動乙」的形狀(第 118/119 項那種):守門檢查的是網址上的輪次,被改/被刪的卻是另外傳進來的一個編號。看每一支 delete_*/update_* 裡「拿編號找東西」那一步,有沒有限定在「網址上那一輪」底下找。盤點抽看了 delete_observation、delete_milestone、delete_remediation:都是先用輪次的 ar_result_id/poam_id 限定範圍再找(例如 _resolve_observation(r.ar_result_id, obs_uid)),形狀是對的;其餘方法要掃描棒逐支確認。
③ 每一支讀取類也要問「憑什麼給你看」:總表第 52 項已經證實「讀取漏守門、寫入有守門」是這一塊的慣性。
C1(接線總裝+審閱)
review_service.py:43 _require_manager 開頭寫著「participant_role_service 或 project_domain_service 任一沒注入就直接 return」——零件沒裝就跳過檢查。現在主專案 DI 有裝(flow_control_containers.py:500-507 兩個都有傳),但這個寫法與總表 M10 第 8 條「漏裝一條、整支靜默全開」完全同形。要答:①現在是不是每個建 ReviewService 的地方都有傳;②plugin/assembly.py:_assert_wiring 的「沒接好就拒絕掛載」只檢查三道路由守門,管不管得到服務層這兩個零件。flow_control_review_repo_impl.py:25-78 _resolve_control_ids 用網址上的專案編號查,ap_uid 參數完全沒用到(docstring 自陳)。確認審閱標記寫進去的 project_id 就是剛剛檢查過角色的那個專案。core/plugins/compliance_audit.py 三支守門 adapter 有沒有吞例外、有沒有把「查不到角色」轉成放行(FR-095 H1 對 participant.py 做過同樣的查核,可參照)。C1b(三條只讀網址)
task_setup_route.py:27-31:網址是 /project/<project_uid>/ap/<ap_uid>/task-setup/tree,project_uid 收了沒用,只把 ap_uid 往下傳;flow_control_task_setup_repo_impl.py:247-290 _resolve_ssp 依序把這個編號當「專案編號→輪次編號→稽核計畫編號」三種去猜。整條路沒看到「你是不是這個專案的人」的檢查。回傳整棵控制項樹+每項任務的指派人 uid 與暱稱(:125-141)。跨客戶靠 compliance.projects 的隔離擋(專案表有開),同客戶跨專案要掃描確認。project_current_ssp_service.py:34-60:拿網址上的專案編號就回該專案 living SSP 的編號,沒有角色檢查。SSP 編號是其他 SSP 端點的輸入——要確認那些端點各自有守門(FR-113 O1 的 SspPermissionChecker),有的話這支只是洩漏編號、嚴重度低。project_extension_repo_impl.py:58-88 get_one_by_fields 用 living_ssp_id/owner_id 查專案——查主表 compliance.projects(有隔離),確認即可。C1c(主專案兩支路由)
assessment_plan_route.py:三個端點(選單、詳細更新、儀表板)都只掛登入+商務授權、沒有能力點。選單那支已是 FR-095 H1-3(總表第 66 項),不重報;要看的是另外兩支——AssessmentPlanDetailResource.put(:55-75,會改資料)與 ApDashboardResource.get(:105-116,FR-095 H1 報告順帶提到「也不驗 ap_uid 屬不屬於 project_uid」,但沒列成獨立發現)。project_route.py:MyAssignedProjectsResource(:71-81)沒掛能力點,但查的是「呼叫者本人被指派的專案」,預期不是洞,確認即可;其餘端點都掛了 project.read/update/delete。api/serializers/project.py:41-67 清單查詢的篩選條件全部選填(見第 6 節),送空條件會回什麼範圍要確認。C2a(輪次主體)🔴
audit_round_app_service.py:211-223 list_rounds、get_round:0 行守門。路由 audit_round_route.py:69-87 只掛 @jwt_required()+@require_license("audit")。project_audit_rounds 表 DEV 已開隔離(EXISTS 繞專案表),跨客戶應該被擋、同客戶跨專案不會——掃描要實證這個判斷。總表沒有這兩支。_check_role,但角色檢查用的是「從輪次查出來的專案」(e.project_id),不是網址上的專案——這是對的做法,確認每支都是。create_round 用網址上的 project_uid 解析專案再查角色(:226-230),對的;確認 name/round_type 沒有別的注入面。002-compliance-audit-rls.sql:輪次表的隔離規則是「看得到專案才看得到輪次」。確認出貨版有套上(scripts/sql/packages/manifest.tsv:16 有登記,但 02-schema.sql 靜態快照顯示輪次表沒開隔離——見第 5 節差異說明)。C2b(歷程、回退、規劃檢查)
round_stage_transition_repo_impl.py:29-33、round_rollback_supersession_repo_impl.py:48-52 的 list_by_round(round_id) 只用數字輪次編號過濾,兩張表隔離全關。唯一讀歷程的呼叫端是 list_stage_transitions(=第 52 項,已知);回退標記目前只有寫入呼叫端(:901 _mark_superseded),讀取的 list_by_round/list_by_entity_ids/is_superseded 盤點時沒找到呼叫者——確認是否死碼。planning_readiness_checker.py:67-78、:82-90:兩處查詢失敗就「不警告、放行」(註解自陳 fail-open)。它只是軟提醒、使用者本來就可以按確認放行,預期不是安全問題,但要確認不會被當成「權限檢查」用。prep_job_generation_service.py:覆核輪批次建立證據蒐集任務,確認建出來的任務歸屬(專案、輪次)是由伺服器端決定。C3(稽核結果與改善計畫)🔴
assessment_result_app_service.py:392(get_findings)、:695(list_risks)與 poam_app_service.py:246(list_items)、:271(get_item):讀取只查輪次存不存在。回傳的是整張稽核判定矩陣(每個控制項合不合格、理由)、系統風險、改善計畫與負責人——這一塊最敏感的內容。底下的 oscal.assessment_*/oscal.poam* 八張表 DEV 隔離全關,跨客戶沒有資料庫這層擋。總表沒有這幾支。_check_auditor/_check_manager)用的專案是「從輪次查出來的」,對的;再逐支確認「拿 uid 找東西」都有限定在該輪底下(第 3 節②)。judge_finding、link_risk_findings 收的是 finding/risk 編號清單——確認每一個編號都驗證屬於本輪。common/round_guard.py 只管「過了階段就唯讀」,不是權限檢查;確認沒有地方把它當成權限檢查用。C4a/C4b(兩條匯入)
_require_job(ap_docx_import_app_service.py:251、ar_import_app_service.py:569)有檢查「解析工作是不是你們公司的」(job.tenant_id != user_context.tenant_id),而且每一步都再用解析工作上記的輪次/計畫編號重查角色——形狀是對的。確認 user_context.is_admin 放行的是平台管理員、不是租戶管理員。wf_control_mapping_lookup_query.py:30-53 get_wf_ids_by_control_ids 的 round_id 可以不帶,不帶就只用控制項代號查全表;那張表 隔離關、沒有客戶欄位,控制項代號(如 AC-2)又是所有客戶共用的字串。盤點時追到唯一呼叫端 ar_import_app_service.py:175-177 有帶 round_id(從已驗證過的輪次取),round_id 只有在輪次物件本身是 None 時才會是 None——掃描要確認這條路徑到不到得了。_build_evidence_pool(:341)、_get_allowed_wf_ids_by_control(:424)兩處「查詢失敗就回空、不擋解析」(註解自陳 best-effort)。確認失敗時是「少給證據」而不是「給全部證據」。generator.py 公式注入的先例)。C5(文件池資料層)
ssp_reference_document_repo_impl.py:43-75(get_by_uid/update/delete_by_uid 只用編號)、ssp_document_pool_query.py:199-209(resolve_doc_uids_to_ids 只用編號)。add_mappings(:144-183)直接用呼叫端給的 doc_ids 建關聯、不驗文件屬於哪份 SSP——它的輸入正是第 129 項那支 resolve_doc_uids_to_ids 的輸出,是同一個洞的後半段、不另計;list_mappings/remove_mapping/get_mapping_doc_names 只用 context_type + context_id 查,確認 context_id 都由伺服器端解析。di_containers/oscal/oscal_containers.py:文件池的 DI 組裝(:102-106 import、與 module_frame_containers.py 各建一份)。確認兩邊建出來的是同一套、沒有一邊少注入守門零件(FR-113 O9b 證實過「DI 漏接讓守門靜默失效」)。ssp_catalog_title_query.py:控制項標題查詢,唯讀、被 SSP 匯入匯出用。確認查詢有帶 SSP/catalog 範圍,不是全庫撈。「範圍條件」=除了編號之外,查詢有沒有再加上「而且要屬於某份計畫/某個專案/某家客戶」。只列會讀或改單筆、多筆資料的方法;寫死回空值的 stub 另列。
| 方法 | 位置 | 查詢條件 | 表的隔離 | 狀態 |
|---|---|---|---|---|
SspReferenceDocumentRepoImpl.delete_by_uid |
ssp_reference_document_repo_impl.py:66-76 |
只有 uid |
🔴 關 | 第 118/119 項根因,重現、不另計 |
SspReferenceDocumentRepoImpl.update |
同檔 :51-64 |
只有 uid |
🔴 關 | 同上形狀;呼叫端在已掃的 O6/B2 範圍,重現、不另計(C5 確認有沒有第三個呼叫端) |
SspReferenceDocumentRepoImpl.get_by_uid |
同檔 :43-49 |
只有 uid |
🔴 關 | 同上 |
SspDocumentPoolQuery.resolve_doc_uids_to_ids |
ssp_document_pool_query.py:199-209 |
只有 uid IN (...) |
🔴 關 | 第 129 項根因,重現、不另計 |
SspDocumentPoolQuery.add_mappings |
同檔 :144-183 |
不驗 doc_ids 屬於誰 |
🔴 關 | 第 129 項後半段,不另計 |
ProjectAuditRoundRepoImpl.get_by_uid |
project_audit_round_repo_impl.py:29-31 |
只有 uid |
開(繞專案表) | 🟡 C2a/C3:多支讀取只靠它=「輪次查得到就放行」。跨客戶有隔離擋,同客戶跨專案沒擋 |
RoundStageTransitionRepoImpl.list_by_round |
round_stage_transition_repo_impl.py:29-33 |
只有 round_id(數字) |
🔴 關 | 呼叫端=第 52 項,已知 |
RoundRollbackSupersessionRepoImpl.list_by_round/list_by_entity_ids |
round_rollback_supersession_repo_impl.py:35-52 |
只有 round_id/entity_type+ids |
🔴 關 | 🟡 盤點時沒找到讀取呼叫端,C2b 確認是否死碼 |
WfControlMappingLookupQuery.get_wf_ids_by_control_ids |
wf_control_mapping_lookup_query.py:30-53 |
控制項代號;round_id 可不帶 |
🔴 關 | 🟡 唯一呼叫端有帶 round_id,C4b 確認不帶的路徑到不到得了 |
ArXlsxParseJobRepoImpl.get_completed_by_source |
ar_xlsx_parse_job_repo_impl.py:56-65 |
只有 source_uid(輪次編號) |
開(有客戶欄) | 跨客戶被隔離擋;呼叫端先驗過角色,預期不是洞 |
Ap/ArParseJobRepoImpl.update/deactivate |
ap_docx_parse_job_repo_impl.py:31-54、ar_…:31-54 |
只有 id/uid |
開(有客戶欄) | 呼叫端 _require_job 先驗客戶,預期不是洞 |
PoamRepoImpl.update_poam |
poam_repo_impl.py:55-66 |
只有 uid |
開 | ⚪ 死碼(見 1.4),不成立 |
| 方法 | 位置 | 範圍 |
|---|---|---|
FlowControlReviewRepoImpl.add_review/remove_review/_get_reviewers |
flow_control_review_repo_impl.py:104-200 |
project_id(由網址專案編號解析)+控制項+使用者 |
FlowControlReviewRepoImpl.clear_marks_for_controls |
同檔 :202-238 |
project_id+catalog_id |
ProjectAuditRoundRepoImpl.list_by_project/max_round_no |
project_audit_round_repo_impl.py:63-77 |
project_id |
ProjectAuditRoundRepoImpl.get_by_assessment_plan_id/get_by_ssp_id |
同檔 :33-61 |
只有計畫/SSP 數字編號(內部呼叫,數字由伺服器端取得) |
ProjectExtensionRepoImpl.* |
project_extension_repo_impl.py:58-127 |
查專案主表(有隔離) |
SspDocumentPoolQuery.list_pool/clone_pool_docs/get_pool_name_to_uid_map |
ssp_document_pool_query.py:25-110、:211-233 |
ssp_id |
SspDocumentPoolQuery.list_mappings/remove_mapping/get_mapping_doc_names |
同檔 :112-142、:185-197、:235-253 |
context_type+context_id(C5 確認 context_id 來源) |
FlowControlTaskSetupRepoImpl._resolve_ssp |
flow_control_task_setup_repo_impl.py:247-290 |
用編號猜三種身分;查專案表(有隔離)+輪次表(有隔離)+oscal.assessment_plans |
flow_control_audit_repo_impl.py(13 個方法)、flow_control_control_repo_impl.py(3)、flow_control_control_group_repo_impl.py(2)、flow_control_assessment_object_repo_impl.py(1)、oscal_audit_query.py(7)、poam_repo_impl.py 的 list_poams/get_poam、ssp_document_pool_query.py 的 get_ap_task_id_by_uid/get_ap_control_id_by_identifier。全部在死碼區或沒有呼叫者。
標紅統計:4.1 表 12 列中,真正「只有編號、底下表又沒隔離、呼叫端也沒補」而且還活著的,都是第 118/119/129 項已知的那 5 支;新懷疑點 4 支(輪次 get_by_uid 被讀取類依賴、回退標記讀取、round_id 可不帶、parse job 兩支)待掃描確認;死碼 1 支不成立。
對照來源:①出貨版 scripts/init/02-schema.sql(靜態快照);②DEV 實查(唯讀 SELECT,2026-09-23 21:06,cm_app 帳號,本棒重查、與前一棒 20:15 的結果一致);③套件自帶 migration 002-compliance-audit-rls.sql。
| 表 | 客戶欄位 | 出貨 02-schema | DEV | 誰的 | 白話 |
|---|---|---|---|---|---|
compliance.project_audit_rounds(稽核輪次) |
無 | ⚠️ 關(0 條) | 開(4 條,繞專案表) | 套件 002 | 看得到專案才看得到輪次 |
compliance.review_marks(審閱標記) |
無 | ⚠️ 關(0 條) | 開(4 條,繞專案表) | 套件 002 | 同上 |
compliance.poams(舊改善計畫表) |
有 | 開(4 條) | 開(4 條) | 死碼區在用的舊表 | |
oscal.ap_docx_parse_jobs(Word 解析工作) |
有 | 開(1 條) | 開(1 條) | ||
oscal.ar_xlsx_parse_jobs(Excel 解析工作) |
有 | 開(1 條) | 開(1 條) | ||
🔴 compliance.round_stage_transitions(階段歷程) |
無 | 關 | 關 | 操作者帳號、退回理由全文 | |
🔴 compliance.round_rollback_supersessions(回退標記) |
無 | 關 | 關 | ||
🔴 oscal.ssp_reference_documents(程序書) |
無 | 關 | 關 | 第 118/119 項的表 | |
🔴 oscal.ssp_reference_document_mappings(程序書掛在哪) |
無 | 關 | 關 | 第 129 項的表 |
| 表 | 客戶欄位 | DEV 隔離 | 誰在用 |
|---|---|---|---|
compliance.projects |
有 | 開(4 條) | 幾乎所有路徑的歸屬根源 |
🔴 public.workflow_execution_control_mapping |
無(有 round_id,可為 NULL) |
關 | C4b 證據配對 |
🔴 oscal.assessment_results/assessment_findings/assessment_observations/assessment_risks/assessment_remediations |
— | 關(DEV 21:21 實查) | C3 稽核結果的實際存放處 |
🔴 oscal.poams/poam_items/poam_milestones |
— | 關(DEV 21:21 實查) | C3 改善計畫的實際存放處 |
(oscal.* 那批表屬 jedi-oscal-v2,總表已登記「整個 oscal 區只有五張工作紀錄表開了隔離」,不重報;列在這裡是為了讓 C3 研究員知道讀取漏守門時沒有第二道防線。)
oscal.assessment_*/oscal.poam*)也全部沒開隔離。所以 C3 那四支「只查輪次存不存在」的讀取,如果成立,跨客戶也擋不住(只要拿得到輪次編號)。02-schema.sql 靜態快照裡是關的。原因是隔離規則在套件 migration 002(CM-1800,2026-09-14),出貨時由 flatten_pkg_migrations.sh 攤平進安裝包、登記在 scripts/sql/packages/manifest.tsv:16,02-schema.sql 本身沒重產。新客戶裝機會不會套到 002,取決於安裝腳本有沒有跑那份攤平清單——這是出貨基線的問題、不是本次掃描的範圍,列給首腦知道(見第 7 節)。| 請求格式 | 位置 | 選填欄位 | 對應網址 | 盤點判斷 |
|---|---|---|---|---|
AuditorDashboardRequestSchema+FiltersSchema |
套件 api/serializers/auditor_dashboard.py:5-18 |
status、keyword 全選填 |
POST /grc/audits/my/list |
查詢一律帶「呼叫者本人」(伺服器端取),空條件=回自己的全部,預期不是洞 |
ProjectListRequestSchema+FiltersSchema |
套件 api/serializers/project.py:41-67 |
全部篩選選填 | POST /grc/projects/list(C1c) |
背後 project_service.list_projects 已在 FR-095 H1 掃過;C1c 只確認路由層有掛 project.read |
主專案 api/project/serializers/audit_round.py 的請求格式都是寫入用、關鍵欄位都有 required=True,沒有查詢型的全選填格式。
api/flow_control/__init__.py 與 FR-095 H2(CM-1783,尚未派)重疊:本盤點放進 C1 當接縫檔。若 H2 先派,C1 的研究員讀但不報;若 C1 先派,H2 那邊比照。要不要乾脆從其中一邊拿掉,由首腦決定。02-schema.sql 與 DEV 的隔離狀態不一致(5.3 最後一點):這是出貨基線問題,不歸本批掃描。要不要另外查「新裝客戶到底有沒有套到套件 migration 002」,由首腦決定。api/flow_control/routes/project_route.py:交接列為「FR-088 H3 已掃」→ 查證只是被引用當範例,改判沒查過,排進 C1c。poam_service.py/audit_service.py:交接列為「待確認可達性」→ 確認打不到(1.4),不成立為發現。task_setup_service.py:交接說「只讀了一半」→ 本棒讀完 _resolve_ssp 與完整呼叫鏈,沒看到任何角色比對,列為 C1b 頭號疑點。get_wf_ids_by_control_ids 的 round_id 可不帶:交接列為「要查哪些呼叫端會傳 None」→ 唯一呼叫端有帶,只有輪次物件本身是 None 時才會不帶,列 C4b 確認。project_route.py)。