本卡屬 FR-095(母卡見本 arc README front matter),第 4 棒 H2:任務 CRUD/匯入匯出/批次完成/執行查詢(BE repo)。只掃不修。
主專案這一側處理「任務」本身的服務:查任務清單與明細、Excel 匯入任務(驗證→重驗→確認三步)、匯出、一次把多個任務標成完成、查執行進度,以及把稽核計畫轉成任務。共 19 檔,但其中 job_service.py/job_import_service.py 是數千行的大檔。只找問題、不修問題。
「批次完成任務」這支服務預設把呼叫者當成管理者,只有在守門服務、專案服務、專案編號三者都齊的時候才真的檢查——這正是總表第 59 條(viewer 可完成別人任務)當時寫「未核對」的那個點。匯入那三步裡前兩步沒有守門,只有最後確認那步有。5,000 行大檔裡有多少條路能走到「不檢查就寫入」,要一次看完。
這些是首腦讀過程式碼後認為最容易出事的地方,是思考起點不是檢查清單。每條後面的「首腦核對」是首腦親自開檔的結果——✅ 屬實的不必重做核對,直接當錨點追下去;標「待 runner 核對」的才要你自己開檔確認。工具沒答的自己開檔查了再寫,標明「(工具未報,人工查證)」:
is_manager = True 預設、條件不齊就跳過檢查(疑點 #5):app/flow_control/service/job_batch_complete_service.py:50-56 註解自陳「沿用舊守門『context 不齊就跳過檢查』的行為」,if self._participant_role_service is not None and self._project_domain_service is not None and project_uid: 三者齊才 assert_project_participant。route api/flow_control/routes/job_batch_complete_route.py:37 有傳 project_uid,風險在內部呼叫者(不經 route 呼叫這支方法的地方)。為什麼可疑:任何一個內部呼叫沒傳 project_uid,呼叫者就被當 manager、可以完成任何任務。首腦核對:✅ 屬實。要追:grep 全 repo 誰呼叫 batch_complete、各自傳了什麼;DI 有沒有可能兩個服務其中一個是 None。app/flow_control/service/job_import_service.py:198 validate_import 與 :315 revalidate_items 沒有守門;:399 confirm_import 有 manager 檢查。為什麼可疑:前兩步會解析上傳的 Excel、預載該專案的驗證資料(控制項、成員、部門)並回給前端——只驗登入就能拿別家專案的資料當「驗證結果」讀走;另外上傳檔案的 _validate_file 有沒有限制大小與型別。首腦核對:讀碼助手報,首腦未開檔,待 runner 核對。project_uid 不用:api/flow_control/routes/job_route.py:75-92——這是總表第 45 條已登記,本棒看到只寫「同第 45 條」;但要追的是 job_service.py 裡其他方法(更新、刪除、清單)有沒有同款「收了不用」。infra/flow_control/repository/flow_control_job_repo_impl.py、job_export_query.py、job_import_lookup_query.py、task_execution_query.py、task_existence_query.py、infra/readmodel/tasks/job_batch_complete_query.py——逐支看 SQL 有沒有 project_id 條件、匯出查詢會不會跨專案。job_executions 表有租戶欄但隔離關、零規則(11,788 筆),資料庫層目前也不擋。(工具未報時人工查證)infra/readmodel/detection/detection_job_notify_query.py——凌晨排程靠無身分跑(總表第 46 條已登記);本棒只記這支查詢在無身分下會撈到哪些租戶的資料,不重報第 46 條。common/authz/workflow.py 與 common/authz/project.py:兩支守門政策檔,前者 FR-088 H2 已掃(第 51 條、:38 註解錯誤已知),後者與 H1 重疊——本棒只看「本棒 scope 內的 service 呼叫它們時有沒有每條路都呼叫到」,不重審守門函式本身。app/detection_tools/task_type_declaration.py:檢測工具型別向套件的型別登記簿申報啟動掛鉤——申報的 callable 若失敗會被套件 except Exception 吞掉(P3/P4 主題),本棒只看它申報時有沒有夾帶憑證或外部指令。授權判定怎麼流(首腦 2026-09-14 開檔核對,行號可直接打開):
common/authz/project.py(120 行):assert_project_manager :16-30/assert_project_role_fallback :33-57/assert_project_role :60-98/assert_project_participant :101-120。守門函式本身沒有 fail-open(fail-open 就是「查不到就放行」的壞習慣):查不到角色就 raise、沒有拿租戶代替專案、沒有 super_admin 短路。participant/app/service/participant_role_service.py:33-83,三層往上找:project_control_participants → control_group_participants → project_participants → 都沒有就回 None。core/plugins/participant.py:90-102 的 adapter → 套件 participant/common/guard.py:26-52 的 configure();沒接線時 :45-49 直接 raise、不放行(這一段是好的)。task 那一半的三道守門(license/project_role/identity)在 core/plugins/task.py:89-98,與 jedi-compliance-audit 共用同一組 adapter。