本卡屬 FR-181(母卡 FR-181 母案(同清單上一張)),卡 B-1,批 6。只改 主 repo。依賴:A-1、A-3。
證據存在 Agent 那台的租戶,主系統只有一筆「參照」(檔案在哪台、Agent 那邊的檔案 uid),bytes 全在 Agent。現況上傳/下載/轉 PDF/刪除都是主系統主動連 Agent /blob。改成(決策者裁 A 案「經主系統中轉」):上傳=主系統收檔先暫存 → ask(fetch_file) → Agent 來拿、驗 sha、存好回覆檔案 uid → 主系統寫參照、刪暫存;下載/預覽=ask(send_file) → Agent 把檔 multipart 送上來落暫存 → 主系統串給瀏覽器 → 刪暫存;轉 PDF 同下載、Agent 側先轉;刪除=fire(delete_file) 不等。使用者感受:多 1~2 秒;大檔等待約翻倍(Agent 整檔傳完主系統才開始回瀏覽器)——100 MB 要實測記時間。錯誤碼不變(FE 依碼顯示)。adapter 選擇邏輯不動。
extend:infra/upload_file/remote_agent_adapter.py——save_file:收檔→spool.save→ask(fetch_file, {request_id, name, sha256})→result 的 file_uid 寫參照 row;get_file/fetch_agent_blob:ask(send_file, {file_uid})→spool.open(request_id) 串給呼叫端→讀完刪;convert_to_pdf:ask(send_pdf);delete_file:fire(delete_file)。_via_data_plane/_data_plane/_lookup_agent 刪(直推開關關閉時這條本來就不通;主系統側直推留在 AgentCommandService 已足夠 D6)。錯誤碼不變(FE 依碼顯示):504→FILE_AGENT_UNREACHABLE、Agent failed→FILE_AGENT_BAD_RESPONSE。禁:managed_file_upload_service.py 的 adapter 選擇邏輯不動
repo:~/Projects/Billows/Audit-Manager/compliance-manager-be
改既有:infra/upload_file/remote_agent_adapter.py
改既有:test/test_remote_agent_adapter.py
infra/upload_file/remote_agent_adapter.py:建構子多收 agent_request_service(DI 注入;managed_file_upload_service.py:85 那行建 adapter 的呼叫處加參數——那是唯一允許碰該檔的一行)。save_file:收檔 → spool.save(request_id_pre, stream)(先產 uid 當 request_id)→ ask(agent, KIND_FETCH_FILE, {"request_id": …, "name": …, "sha256": …}) → result file_uid 寫參照 row(save_file_name)、path 記 agent 位址照舊 → spool.discard。get_file/fetch_agent_blob:ask(KIND_SEND_FILE, {"file_uid": entity.save_file_name}) → result 含 spool 的 request_id → spool.open 回給呼叫端(既有呼叫端吃 httpx.Response?看 _verify_integrity 與上層怎麼用,改成吃 file-like,上層不動就包一層)。convert_to_pdf:KIND_SEND_PDF。delete_file/delete_files_by_uids:fire(KIND_DELETE_FILE, …)。_via_data_plane/_data_plane/_lookup_agent/_Route 裡只給直推用的欄位刪;_route_for_entity 的「用檔案自己記的 agent」邏輯保留(改成回 agent entity 給 ask)。mode=none 的裸 http demo 路徑保留不動。FILE_AGENT_UNREACHABLE、503→FILE_AGENT_UNREACHABLE(FE 沒有 busy 的碼,沿用)、Agent failed→FILE_AGENT_BAD_RESPONSE、result 缺 file_uid→FILE_AGENT_BAD_RESPONSE。test_remote_agent_adapter.py 改成假 service。STORAGE_CONFIG 設 remote_agent 指 123 Agent(🔴 只改 DEV 的 system_configs);design §8 第 9 條逐項;100 MB 檔上傳與下載各量一次時間寫進回寫;Agent 停掉 → 上傳 30 秒後 FILE_AGENT_UNREACHABLE。DEV 一個租戶 STORAGE_CONFIG 設 remote_agent 指 123 Agent:上傳 1 MB → upload_files 參照 row 有 save_file_name、/tmp/agent-outbound 空、Agent 側檔存在;預覽/下載拿到同 sha;docx 轉 PDF 可開;刪除 → Agent 側檔消失;100 MB 檔上傳與下載各量一次時間寫進回寫;Agent 停掉 → 上傳 30 秒後回 FILE_AGENT_UNREACHABLE 不 500
~/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