# AwoooP RLS Canary Wave 1 This wave is a staged apply package only. It enables fail-closed RLS on tables that were empty in the latest production preflight. Apply script: ```bash scripts/ops/awooop-rls-canary-wave1-empty-tables.sql ``` Rollback script: ```bash scripts/ops/awooop-rls-canary-wave1-empty-tables-rollback.sql ``` ## Scope Wave 1 targets only tables that had `total_rows=0` and `null_project_id_rows=0` on 2026-05-12: - `awooop_contract_revisions` - `awooop_conversation_event` - `awooop_mcp_credential_refs` - `awooop_mcp_gateway_audit` - `awooop_mcp_grants` - `budget_ledger` The SQL aborts if any target now has rows, is missing, lacks `project_id`, or contains NULL `project_id`. ## Pre-Apply Gate Run these before any production apply: ```bash python3 scripts/ops/awooop-rls-access-audit.py python3 scripts/ops/awooop-rls-manual-script-audit.py bash scripts/ops/awooop-rls-preflight.sh --exact-counts ``` Expected before wave1 apply: - Runtime access audit: `BLOCKED=0`. - Manual script audit: `BLOCKED=0`; review items acknowledged. - RLS preflight: still blocked only because policies are not enabled. - Exact counts for the six wave1 target tables remain `total_rows=0`. ## Apply Run with a migration/operator role in a reviewed maintenance window: ```bash psql "$DATABASE_URL" -v ON_ERROR_STOP=1 \ -f scripts/ops/awooop-rls-canary-wave1-empty-tables.sql ``` Then rerun: ```bash bash scripts/ops/awooop-rls-preflight.sh --exact-counts curl -fsS https://awoooi.wooo.work/api/v1/health ``` The global preflight will still be blocked until later waves cover the remaining tables. The six wave1 tables should show `rls=true`, `force=true`, and `policies=1`, with no fail-open policy expression. ## Rollback ```bash psql "$DATABASE_URL" -v ON_ERROR_STOP=1 \ -f scripts/ops/awooop-rls-canary-wave1-empty-tables-rollback.sql ``` Rollback disables RLS and removes only the wave1 policies on the six canary tables. It does not modify data.