本卡屬 FR-089,來源 FR-087 T1 盤點第 6 項(
compliance.information_systems連規則都沒寫、開關關掉)+ jedi-asset README 已知落差「tenant_id 可空性不一致」。決策者 2026-09-12 說「能修就修」;但這張動的是 DB 行為,套 migration 屬環境異動,runner 只寫腳本+DEV 驗證,STG/POC 等決策者放行。
資訊系統清單這張表沒有租戶隔離:RLS 關、零條規則。現在 DEV 只有一個租戶所以看不出來,但一旦第二個客戶上來,A 客戶登入就能看到 B 客戶登記的所有資訊系統(83 筆)。設備表反過來 RLS 是開的,但 tenant_id 允許 NULL,NULL 列會被 policy 擋掉變成「誰都看不到」。同一支套件的兩張表,隔離做法不一樣。
首腦 DEV 實查(2026-09-12,唯讀):
compliance.information_systems:relrowsecurity=false、policy 0 條、tenant_id NOT NULL、83 筆、1 個 distinct tenant、0 筆 NULLpublic.devices:relrowsecurity=true、policy 4 條(select/insert/update/delete)、tenant_id nullable、3 筆、1 個 tenant、0 筆 NULLscan-T1-isolation-gap-audit.md:51 對第 6 項的判斷:「開了不會弄斷——沒有查到背景程式或跨租戶統計會用到它」。首腦複核:grep -rn information_system core/scheduler.py 零命中,屬實。information_systems 的外鍵 0 條,開 RLS 不影響其他表的 join。jedi-asset/jedi_asset/migrations/002-asset-rls-grants.sql 現有:只有 devices 的 4 條 policy+GRANT;本卡補 information_systems 那半
jedi-asset/README.md 「已知落差」表 修完把那兩列刪掉或改「已修(CM-xxxx)」
主專案 scripts/sql/ 主專案側是否也要一支同步 migration,見「怎麼修」③
對照(devices 現有 policy 長什麼樣):
DEV 唯讀:SELECT policyname, cmd, qual, with_check FROM pg_policies WHERE tablename='devices';
qual/with_check 逐字抄(先在 DEV 用上面那句 SQL 看實際內容,不要憑記憶寫),改表名,加 ALTER TABLE compliance.information_systems ENABLE ROW LEVEL SECURITY。DDL 全部冪等(DO $$ IF NOT EXISTS ... $$),符合 SOP §4.2。ALTER COLUMN tenant_id SET NOT NULL。但要包成「先 count NULL,非 0 就 RAISE」的防呆,避免在別的環境炸一半。scripts/sql/ 要不要也放一支同內容的 migration 進 schema_migrations?兩種做法:(A) 只改套件的 002,主專案靠 init image migrate 模式撿;(B) 主專案另開一支 2026-09-xx-fr089-information-systems-rls.sql,兩邊都有。首腦傾向 A(套件的表歸套件的 migration 管,兩邊都放會漂移),但 STG/POC 的套法目前是 init image 讀哪裡首腦沒查,runner 查 scripts/init/README.md 後回寫問。psql --single-transaction -v ON_ERROR_STOP=1 -f 002-asset-rls-grants.sql 用 cmmgr 對 guidant_ai_dev(port 25432)。STG/POC 一律不碰。--migrate 加一個 --with-rls 旗標套 002(建 cm_app 角色樁與判定函式樁),確認 002 在乾淨庫上套得起來且冪等(套兩次不炸)。這條選做,做了寫進回寫。SELECT relrowsecurity, (SELECT count(*) FROM pg_policies WHERE tablename='information_systems') FROM pg_class WHERE relname='information_systems' → t | 4。cm_app 角色+設 app.allowed_tenant_paths 為現有租戶 → SELECT count(*) FROM compliance.information_systems 仍是 83;設成不存在的租戶路徑 → 0。