建議 model:Sonnet 5,effort:low——規則現成、純開開關+補一條 OR 分支,難點只在「造一個跨租戶樣本」。本卡屬 FR-094(母卡見兄弟卡段),.2 開隔離的第 1 棒(整案第 3 棒)。無前置棒,可立即派。吸收 CM-1453。
兩張表的隔離規則早就寫好,只是開關被關了:客戶雲端硬碟串接設定(tenant_drive_integrations)與專案清單(projects)。projects 是 2026-06-25 做 POC 對齊 STG 時「以 STG 為主」順手關的(commit e7709295),不是產品決策,而且它的 4 條規則沒有平台管理員分支——直接打開,平台管理員(blsadmin)會看不到不屬於自己路徑的專案。所以要先補分支再開。
首腦核對(2026-09-13 DEV localhost 實查):
public.tenant_drive_integrations:RLS 關、4 policy、1 筆。policy 本身已含 is_super_admin OR(scripts/sql/2026-04-23-google-drive-oauth-integration.sql:48-79)。⚠️ 盤點報告寫 public.,2026-04-23 migration 寫 compliance.——DEV 實查在 public,動手前 \dt *.tenant_drive_integrations 確認 schema。compliance.projects:RLS 關、4 policy、221 筆、全屬 tenant 102(select tenant_id,count(*) group by 1 → 102|221)。policy 現況(02-schema.sql:24061-24085)四條都只有 app_tenant_allowed_for_session(tenant_id),無 is_super_admin 分支。scripts/sql/2026-06-25-align-poc-to-stg-view-eventtrigger-projects-rls.sql:124 ALTER TABLE compliance.projects DISABLE ROW LEVEL SECURITY;,manifest 標 envs=poc;基線 02-schema.sql 也沒有 ENABLE 行 → 四環境全關。infra/flow_control/repository/flow_control_project_repo_impl.py);儀表板先算「我參與的專案」再查,開了不會弄斷(FR-087 §6.3)。webhook_channel_renewer 排程讀 tenant_drive_integrations(CM-1559 盤點 B 表)——它現在靠 fail-open 跑,開 RLS 後在 1559 收緊前仍能跑;1559 收緊後由該棒接系統身分,本卡回寫時提醒 1559。~/Projects/Billows/Audit-Manager/compliance-manager-be/scripts/sql/2026-09-XX-fr094-cm<本卡號>-enable-rls-projects-drive-integrations.sql (新)本棒 migration
~/Projects/Billows/Audit-Manager/compliance-manager-be/scripts/sql/manifest.tsv 加一列 active / *
~/Projects/Billows/Audit-Manager/compliance-manager-be/scripts/init/02-schema.sql:24061-24085 projects 四條 policy 現況(重產後應多 is_super_admin 分支+ENABLE)
~/Projects/Billows/Audit-Manager/compliance-manager-be/scripts/sql/2026-06-25-align-poc-to-stg-view-eventtrigger-projects-rls.sql:124 當初關掉的那行(不改歷史檔)
~/Projects/Billows/Audit-Manager/compliance-manager-be/docs/system-design/database/RLS_DESIGN.md 若有列 projects 為停用,改成現況
-- Date: 2026-09-XX
-- 1. projects 四條 policy 補 super_admin 分支 (2026-09-XX)
ALTER POLICY projects_select ON compliance.projects USING (COALESCE(current_setting('app.is_super_admin', true),'f')='t' OR public.app_tenant_allowed_for_session(tenant_id));
ALTER POLICY projects_update ON compliance.projects USING (...同上...) WITH CHECK (...同上...);
ALTER POLICY projects_delete ON compliance.projects USING (...同上...);
-- insert 維持 WITH CHECK (app_tenant_allowed_for_session(tenant_id)),比照 tenant_drive_integrations 亦可放寬為 true——先查同族表慣例(surveys_insert 是 tenant AND org)再定
-- 2. 開開關 (2026-09-XX)
ALTER TABLE compliance.projects ENABLE ROW LEVEL SECURITY;
ALTER TABLE public.tenant_drive_integrations ENABLE ROW LEVEL SECURITY; -- schema 以實查為準
INSERT INTO public.schema_migrations(filename, note) VALUES ('<本檔名>', 'FR-094 .2a ...') ON CONFLICT (filename) DO NOTHING;
先查再寫:ALTER POLICY 語法對 USING/WITH CHECK 要分開寫;若 DEV 與基線的 policy 名不同(\d+ compliance.projects 看),用 DROP POLICY IF EXISTS + CREATE POLICY 重建更穩。
cmmgr 在 DEV INSERT 一筆專案到另一個已存在的租戶(select id,path from public.tenants where id<>102 limit 3,挑一個非 root 的子租戶,例如 131/158/162 之一——user_roles.tenant_id 有這幾個值,代表有帳號隸屬),name 帶 [FR-094 樣本] 前綴。不套 STG/POC、不進基線庫(基線庫只套 migration、不進樣本)。cm_app 連線 SET LOCAL 模擬 blsit(allowed_tenant_paths 用 select path from public.tenants where id=102 實查值),開前 select count(*) from compliance.projects 應 222(含樣本),開後應 221;app.is_super_admin='t' 開後仍 222。tenant_drive_integrations 同法(1 筆,屬哪個租戶先查)。guidant_ai(188:25432)→ scripts/init/gen_schema_sql.sh 重產 02 → git diff scripts/init/02-schema.sql 只該多出 projects 的 policy 變更+兩行 ENABLE。projects_select 的 is_super_admin OR 分支拿掉(ALTER POLICY)→ 以 blsadmin(allowed_tenant_paths='/1/'、is_super_admin='t')模擬查 projects 應仍 222(因為 /1/ 前綴涵蓋所有子租戶)——這個突變的意義是確認 root 路徑分支與 super_admin 分支是兩條獨立的路;還原後再驗一次。