本卡屬 FR-114 資安修正(母卡 CM-2019),189 升級 1.21.0 後 agent 心跳每 2 分鐘 500 撞到,收集卡 CM-2231 #43。任何從 1.19.0 以前直升的客戶都會踩,b5 必修。本卡改 BE 主線一支 migration+盤缺欄清單+產補套 SQL;189 實際補套由首腦拿放行後做。
FR-093 把 21 支套件各自的建表 SQL 攤進升級流程時,為了不讓「表早就由主線 migration 建過」的既有機器重跑那些 SQL,加了一支回填 migration:直接在 schema_migrations 登記 23 支套件 migration 為已套,不執行。前提是「這些表在 1.19.0 基線就有了」。但 189 是 1.19.0 直升 1.21.0,那 23 支裡有的 DDL(例如 jedi_remote_agent/003 加 agent_tasks.payload_ref 欄)在 1.19.0 基線根本沒有,被假登記後永遠不會再套。結果 189 升級後 POST /agents/heartbeat 每兩分鐘 500 column agent_tasks.payload_ref does not exist,agent 全壞。
首腦已核的證據:189 schema_migrations 這 23 支 applied_at 全是同一毫秒 2026-09-28 11:17:16.662621(回填一次 INSERT);information_schema.columns 查 agent_tasks 沒有 payload_ref;upgrade log /srv/guidant-ai/log/upgrade-20260928-111401.log:179 列了 003 但實際是登記。同批 23 支裡可能不只這一欄缺,要逐支盤。
/Users/chouraymond/Projects/Billows/Audit-Manager/compliance-manager-be/.claude/worktrees/wt-fix-security/scripts/sql/2026-09-13-fr093-1-backfill-package-migrations.sql 23 支 INSERT ... ON CONFLICT DO NOTHING,無任何存在性檢查
/Users/chouraymond/Projects/Billows/Audit-Manager/compliance-manager-be/.claude/worktrees/wt-fix-security/scripts/sql/packages/manifest.tsv 套件 migration 攤平清單(build 期產)
套件 migration 本體:~/Projects/Jedicogy/module/jedi-python-package/.claude/worktrees/jedi-wt-fix-security/jedi-*/jedi_*/migrations/*.sql(23 支對照回填檔名)
/Users/chouraymond/Projects/Billows/Audit-Manager/compliance-manager-be/.claude/worktrees/wt-fix-security/scripts/init/migrate.sh 兩輪+第三輪執行順序
scripts/sql/checks/fr093-backfill-objects-exist.sql(對每個物件 SELECT ... FROM information_schema/pg_policies/pg_indexes,缺的印一行)。在 DEV 跑一次確認 0 缺;用 ssh 對 189 唯讀跑一次(docker exec guidant-db psql -U cmmgr -d guidant_ai -f -)列出實際缺的清單,貼回本卡。2026-09-13-fr093-1-...sql 已在既有機器套過不能改語意,新開一支 scripts/sql/2026-09-28-fr114-fr093-backfill-verify-and-unmark.sql(active/*):對 23 支各自的關鍵物件做存在檢查,不存在的就從 schema_migrations DELETE 那筆登記,讓 migrate.sh 下一輪正常套它。冪等(重跑無事)。登記到 manifest。IF NOT EXISTS/DO 區塊包覆;不是的列回寫(不在本卡改套件)。test/test_fr093_backfill_objects_exist.py:連 DEV 跑 ① 的檢查 SQL 斷言 0 缺(DEV 是完整 migration 路徑,理應全有);突變:手動 DROP 一個欄再跑要紅(用 transaction rollback)。DELETE FROM schema_migrations WHERE filename='packages/jedi_remote_agent/003-agent-task-generic-payload.sql' 並 ALTER TABLE compliance.agent_tasks DROP COLUMN payload_ref(模擬 189)→ 套 ②(應無事,因登記已不在)→ 跑 scripts/init/migrate.sh 的 packages 輪(或手動套 003)→ 欄位回來。再反向:欄位在、登記在 → 套 ② → 登記仍在(冪等)。git add <檔名>,禁 -am。不發版、不 push、不切 branch。