# AwoooP RLS Canary Wave 1 This wave enables fail-closed RLS on tables that were empty in the production preflight. Status: applied to production on 2026-05-12. 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. ## 2026-05-12 Production Evidence Apply completed with `COMMIT` through the 188 postgres/operator socket path. Post-apply preflight: - `awooop_contract_revisions`: `rls=true`, `force=true`, `policies=1` - `awooop_conversation_event`: `rls=true`, `force=true`, `policies=1` - `awooop_mcp_credential_refs`: `rls=true`, `force=true`, `policies=1` - `awooop_mcp_gateway_audit`: `rls=true`, `force=true`, `policies=1` - `awooop_mcp_grants`: `rls=true`, `force=true`, `policies=1` - `budget_ledger`: `rls=true`, `force=true`, `policies=1` All six showed `fail_open_null=false` and `fail_open_empty=false`. Rollback-only behavior test from the API pod: ```text budget_ledger_no_context=InsufficientPrivilegeError budget_ledger_with_context=allowed_and_rolled_back budget_ledger_count_after=0 ``` ## 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.