本卡屬 FR-108(母卡見建卡後補號),第 3 棒:2,498 行的編排服務、任務綁定處理、結果回收、執行群組狀態機、逾時收斂排程、執行紀錄 domain/infra。34 檔(行數最重的一棒),只掃不修。
客戶按「執行掃描」後:系統挑一台代理程式、把工具帳密解密放進派工單、代理程式做完把報告傳回來存成證據、狀態機收口。這棒看:誰能按執行/取消/刪除(是不是那個專案的人)、帳密解密後放進哪裡、有沒有落 log、報告收回時信不信代理程式說的檔名與內容、背景排程用什麼身分寫資料庫。
這是 CM-1595 明文帳密鏈的「出」端,也是整支套件唯一的背景排程。編排服務一支 2,498 行,工具一定會咬它,但卡片重點大半在它咬不到的接縫。
api/routes/detection_tool_route.py:165-345 屬 D1 檔但這棒要讀它的呼叫端;detection_orchestration_service.py:171/:851/:893/:996/:1019/:1072/:1114)。route 只掛 require_license("plugin")+登入,tenant_id 從 get_user_context() 來。要驗:start_execution(job_uid, …, tenant_id) 有沒有驗「這個 job 屬本租戶」以外的「呼叫者是這個專案的成員/管理者」(與跨 arc 總表第 59 項 viewer 完成任務同款);delete_execution :1090 有 execution.tenant_id != tenant_id 檢查——其他六支有沒有同樣一致;force=True 誰能用。_resolve_credentials :1397、_dispatch_one :438-518)。解密後 params["_credentials"] = creds 存進 agent_tasks.params JSONB——明文落資料庫了嗎(create_task(params=…) 那張表 compliance.agent_tasks RLS 開不強制);_expand_scan_target_fields/_ssh_iterated_fields 把 SSH 帳密展開到每一列;有沒有任何 logger.* 印 params/creds(grep 34 檔);_resolve_credentials docstring 自陳「綁定寫入端從未寫過 tenant_config_id、一律 NULL、靠 (tenant_id, tool_id) 反查自癒」——這個 fallback 會不會在跨租戶情境挑錯設定。detection_result_handler.py:69-146/:181-223)。_fetch_blob 在 settings.enabled=False 時裸 httpx.get(base_url)(同 R2b ⑤ 型態,標交接);檔名優先信 agent 回的 Content-Disposition——檔名可控→存進 JOB_EVIDENCES/{job.uid} 時有沒有洗(路徑穿越交給 upload_files_for_tenant,追它);content_type 信 agent;result_ref.upload_uids 由 agent 自報——能不能讓雲端去抓別台 agent 的 blob;handle_result 用 agent.tenant_id 寫證據——agent 是誰查出來的(_resolve_agent(agent_id))。domain/detection_execution/service/*、detection_group_status.py、_close_group_if_terminal :1562)。cancel 與 agent 回報交錯、rerun 時 _cancel_running_execution :1300、_guard_no_running_group :261 用 force 繞過;group 狀態重算是否可被重複觸發 listener(通知寄兩次/證據建兩份)。converge_timed_out_executions :1151)。無 HTTP、無 user context 進來,寫 detection_executions(RLS 1 條 FOR ALL policy、超管旁路)——用什麼身分:主專案排程怎麼呼叫它(宿主側,讀可以標越界)、若走 system_context 或超管則是跨全租戶寫入;_is_timed_out 閾值從哪來;收斂後觸發 _close_group_if_terminal→通知→以誰的名義。與 FR-094 排程具名身分那批同題,撞到標。detection_job_binding_handler.py)。_encrypt_tool_secret_params :124/_encrypt_assignment_secret_params :391:加密發生在寫入前的哪一層,前端送來的 tool_params 若已是信封會不會被二次加密或原樣存明文;_validate_transport_overrides/_validate_scan_target_specs:scan target(主機/IP/網址清單)是使用者填的,agent 拿到後會去掃——這是「用我們的 agent 掃任意目標」的面,有沒有限制只能掃本租戶登記的設備(job_execution_devices 那張表零隔離、屬 flow-control)。list_executions 回傳(:1648)。agent_uid/agent_name/scan_targets/_display_target_spec :1722——回給前端的欄位有沒有夾帶帳密或內網拓樸。_resolve_credentials 解密租戶工具憑證明文交給 agent(主專案 detection_task_payload_provider.py+本套件 detection_orchestration_service.py:1397)。那條是 agent 控制面不驗身分的問題,撞到標「重複 CM-1595」,但本套件這側「憑證解密後的流向與落點」是新的觀察面。detection_executions/_groups/job_execution_detection_tools/_agents/tenant_detection_tool_configs 各 1 條 FOR ALL policy;detection_profiles/_versions 各 4 條)、9 張零隔離:detection_tools/detection_tool_param_schemas/detection_profile_taxonomies/detection_profile_controls(四張是碼表或公版內容,依「有沒有主人」判準可能正確)與 job_execution_comments/_devices/_org_units/_surveys(屬 flow-control 不在本套件)。8 顆能力點 is_platform 全 f。detection_tools 8 筆、tenant_detection_tool_configs 7 筆(1 租戶)、detection_profiles 11 筆(2 租戶)、detection_executions 76 筆。common/guard.py 與 api/guards.py 是「未接線 fail loudly」設計(_guard() 缺 adapter 直接 RuntimeError)——與 FR-098 A1 ⑤ 同款正面案例,驗證它真的做到即可,不要當漏洞報。