本卡屬 FR-166(母卡 CM-3109),批 7。repo:agent。只改 evidence-agent。由 P2-7(CM-3138,FE 執行紀錄分頁)的小弟回報、首腦查證屬實:前端要畫的那張表,Agent 端沒有資料來源。P2-7 改到批 8,等本卡做完再派。
主控台的「執行紀錄」分頁要把這台 Agent 做過的事列成一張表:主系統派的任務和在主控台手動按的都在同一張表,每列看得到回傳狀態(已回傳附時間/待回傳/回傳失敗附原因),被拒絕的執行也要看得到。現在 Agent 只有「單筆查詢」和「立即重試」,沒有清單;主系統派的任務跑完沒在本機留紀錄;被拒絕的執行只寫在稽核紀錄。本卡補齊這三件。
repo:~/Projects/Billows/Audit-Manager/evidence-agent
改:core/local_db/migrations.py(尾巴加 v3)
改:core/local_runs.py(list_page、主系統任務寫入)
改:core/task_sinks.py(CloudSink 落本機紀錄)
改:core/console/runs_routes.py(GET 清單)
參考:core/console/audit.py(讀 local_scan_refused)、core/outbox.py(判斷是否還在待回傳)
🔴 不動 core/console/routes.py(runs_routes 已由 P3-1 掛上)
local_runs 加 source 欄(manual/cloud,舊列預設 manual)。不要另開一張表,兩種來源同一張表、同一套回傳狀態欄(synced_at/sync_error)。local_runs:CloudSink 在 ack 時寫一列(source=cloud、uid 用任務 uid、kind=scan、tool、targets,params 照 LocalSink 同樣濾掉帳密),result 時更新終態;回傳主系統成功就填 synced_at,失敗入 outbox 時照 P3-1 的方式記。不要複製 LocalSink,抽共用的寫入函式。主系統任務的終態寫入 local_runs 時,不可再入一次 local_run 類的 outbox(它回主系統走的是 task_result),在 finish 裡依 source 分開。GET /console/api/runs?source=&kind=&days=30&page=&size=:回每列 時間/來源/種類/工具/目標/執行者/狀態/摘要/回傳狀態(已回傳=synced_at 有值;待回傳=outbox 還有這筆;回傳失敗=sync_error 有值)/報告檔 uid。權限沿用 runs_routes._required_scope:scan 要 run-local-scan、diag 要 net-diag、cloud 要 configure,沒權限的種類不列(不是回 403)。size 上限 100。local_scan_refused 那幾筆(時間、執行者、工具、目標、原因),標成 status=refused、source=manual,和 local_runs 的列合併後依時間排序;只讀稽核,不改稽核格式。GET /console/api/scan/runs/<uid>、/netdiag/runs/<uid> 維持現狀,不要改;新的清單是另一支。GET /console/api/runs 看得到 source=cloud 那列;斷網時它的回傳狀態是待回傳,復線後變已回傳附時間。test_fr166_guards.py 綠;清單權限過濾、v3 升級、cloud 不重複入 outbox 各有測試,權限過濾要有突變。.claude/rules/security/ 八支。