本卡屬 FR-181(母卡 FR-181 母案(同清單上一張)),卡 A-3,批 5。只改 evidence-agent。依賴:F-2。

這張卡做什麼(白話)

Agent 這邊把 F-2 留空的九種指令接上:換證、取消檢測、測試連線、存帳密、查日誌、證據檔四種(來拿、送上去、送 PDF、刪)。每一種都接既有的處理函式——但這些函式現在多數寫在 route 檔裡(8443 直推端點的 handler),要先抽到 app 層(scan/app/cancel.py、scan/app/probe.py、files/app/blob_ops.py),route 殼改成一行呼叫,長輪詢分派表呼叫同一支,不複製。「要回答的」七種(測試連線、存帳密、取檔、送檔、送 PDF、查日誌)流程固定:拿到先回 taken(讓主系統知道「在做了」不是「沒拿到」)→ 做 → 回 done 帶結果,或 failed 帶原因(主系統立刻讓瀏覽器收到錯誤,不等到逾時)。證據檔「來拿」要驗 sha256,不符就 failed 不落檔;「送上去」用 multipart 帶檔。

reuse/extend/new

extend:command_pull.py 分派表填九個 no-op——credentials_renew→cert_renew.request_now();detection_cancel→scan 既有 cancel 的 app 層函式(從 detection_route.DetectionCancelRoute 抽到 scan/app/cancel.py,route 改呼叫);probe→既有 probe app 函式(同法抽 scan/app/probe.py);credentials_set→scan/app/credential_store 既有存法;query_logs→platform/audit_log.list_logs(cmd_logs 已是薄殼);fetch_file→GET /agents/files/<id> 下載→jedi_file_upload FileUploadService.save→reply done 帶 {file_uid, sha256};send_file/send_pdf→讀本機(pdf 先走既有轉檔)→reply_sender.reply(file=) multipart;delete_file→既有刪除、reply done。要回答的七個 kind 先 taken 再做,做失敗 failed reason=;證據檔四種的 app 層從 files/api/blob_route.py 抽到 files/app/blob_ops.py,route 改薄殼。禁:不碰 registry.py/data_plane_server.py(F-2 已留槽)

在哪裡

repo:~/Projects/Billows/Audit-Manager/evidence-agent
改既有:guidant_agent/sync/app/command_pull.py(填分派表)
改既有:guidant_agent/scan/api/routes/detection_route.py(抽 app 層)
改既有:guidant_agent/scan/api/routes/credential_route.py
改既有:guidant_agent/files/api/blob_route.py(抽 app 層)
新開:guidant_agent/scan/app/cancel.py
新開:guidant_agent/scan/app/probe.py
新開:guidant_agent/files/app/blob_ops.py
新開:tests/sync/test_command_reply_kinds.py

怎麼做

驗收(首腦照這個驗)

pytest:每個 kind 一支:收到→taken reply→handler 被叫→done reply 帶 result;handler 拋 → failed 帶 reason;fetch_file 下載 sha 不符 → failed 不落檔;route 殼(POST /detection/cancel 等)在開關開時仍能呼叫同一支 app 函式(抽層沒抽壞)。grep -n 'def ' files/api/blob_route.py 每支 ≤ 10 行

必讀