本卡屬 FR-181(母卡 FR-181 母案(同清單上一張)),卡 A-4,批 5。只改 jedi-python-package。依賴:A-1、F-1。
檢測功能在 jedi-detection 套件裡,它有三支自己打 Agent 8443 的小 client:測試連線(probe)、存工具帳密、取消檢測。本案這三支不再自己發 HTTP,改成呼叫主系統注入進來的 ask/fire(A-1 的插槽)——套件不認識 Redis,只認識一個「有 ask 和 fire 兩個方法」的介面。測試連線與存帳密要等答案用 ask,取消用 fire 不等。既有 HTTP 路徑在套件裡刪掉(主系統側直推留著已夠 D6,套件不留兩套)。錯誤碼對映:逾時→既有 AGENT_UNREACHABLE、插槽滿→新 AGENT_BUSY。做完發版。
extend:agent_probe_client.py→probe(agent, target) 改 self._channel.ask(agent, KIND_PROBE, {target}) 回 result;agent_credential_client.py→ask(KIND_CREDENTIALS_SET, …)(存好才算,要等);agent_cancel_client.py→fire(KIND_DETECTION_CANCEL, {job_uid})。三支的建構子改收 channel port(ask/fire 兩個方法的 Protocol,放 jedi_detection/app/ports/agent_channel.py);主系統 DI 注入 A-1 的 service。既有 HTTP 路徑刪(套件不留開關——主系統開關關閉時這三條本來就打不到,留兩套在套件裡沒意義;主系統側 AgentCommandService 留著已足夠 D6)。錯誤碼對映:ask 504→既有 AGENT_UNREACHABLE、503→新 AGENT_BUSY。發版
repo:~/Projects/Jedicogy/module/jedi-python-package
改既有:jedi-detection/jedi_detection/infra/detection_tools/connector/agent_probe_client.py
改既有:jedi-detection/jedi_detection/infra/detection_tools/connector/agent_credential_client.py
改既有:jedi-detection/jedi_detection/infra/detection_tools/connector/agent_cancel_client.py
改既有:jedi-detection/jedi_detection/app/service/detection_dispatch_guard.py(probe 呼叫點)
改既有:jedi-detection/pyproject.toml
新開:jedi-detection/jedi_detection/app/ports/agent_channel.py
新開:jedi-detection/tests/test_agent_channel_clients.py
jedi_detection/app/ports/agent_channel.py:class AgentChannel(Protocol): def ask(self, agent, kind: str, payload: dict, timeout: float = 30) -> dict; def fire(self, agent, kind: str, payload: dict) -> None。channel: AgentChannel(DI 由主系統注入 A-1 的 service;套件自己的 container 若有預設實作,改成必填、沒注入就 raise 明確訊息)。agent_probe_client.probe(agent, target) → self._channel.ask(agent, KIND_PROBE, {"target": target}),回傳形狀不變;agent_credential_client.set(agent, payload) → ask(KIND_CREDENTIALS_SET, payload);agent_cancel_client.cancel(agent, job_uid) → fire(KIND_DETECTION_CANCEL, {"job_uid": job_uid})。AgentDataPlaneClient 呼叫刪;detection_dispatch_guard 的 probe 呼叫點簽名不變就不動。錯誤對映:ask 拋的逾時例外(主系統那邊的 GRC_504_AGENT_NO_REPLY,套件透過例外型別或 error_code 字串判)→ 既有 AGENT_UNREACHABLE;503 → 新 AGENT_BUSY(jedi_detection/common/error_code.py 加一個)。tests/test_agent_channel_clients.py:假 channel 回 {reachable: true} → probe 回 True;ask 拋 timeout → AGENT_UNREACHABLE;cancel 只叫 fire;grep -rn 'httpx\|requests\|AgentDataPlaneClient' connector/agent_*_client.py 為 0。pytest:假 channel 回 {reachable: true} → probe 回 True;ask 拋 timeout → 既有 AGENT_UNREACHABLE;cancel 只叫 fire 不叫 ask;grep -rn 'httpx\|requests' connector/agent_*_client.py 為 0。發版推 Nexus 回寫版號
~/Projects/Billows/Audit-Manager/compliance-manager-be/docs/features/FR-181-2611-agent-outbound-only-channel/design.md §3 決策定案(D1~D8)、§4 端到端流程兩張圖、§5 詳細設計本卡那節、§7 拆分表本卡那列;為什麼這樣定看 discussion.mdcore/plugins/_agent_commands.py(檔頭說明三個觸發點)、app/remote_agent/service/agent_command_service.py、core/plugins/_agent_config_notify.py、core/plugins/_agent_keys.py、infra/upload_file/remote_agent_adapter.py、core/plugins/remote_agent.py(plugin mount 與 handle)jedi-remote-agent/jedi_remote_agent/api/routing.py(端點表與 AUTH_AGENT)、api/routes/(心跳 route 範本)、app/service/agent_data_plane_client.py(直推出口,留著)、app/service/heartbeat_vulndb.py(_CORE_KEYS 心跳守衛);契約 jedi-agent-protocol/jedi_agent_protocol/commands.py、heartbeat.py、events.pyguidant_agent/sync/app/config_pull.py(WorkerComponent 拉取範本)、enroll.py(心跳 client 與通行證)、event_sender.py+outbox.py(送不到補送)、task_queue.py、sync/api/data_plane_server.py(8443 與 blueprint 掛點)、sync/api/cmd_*.py(直推 handler,本案改薄)、files/api/blob_route.py、scan/api/routes/、docs/ARCHITECTURE.md