Files
awoooi/docs/runbooks/AWOOOP-RLS-CANARY-WAVE1.md
2026-05-12 20:55:40 +08:00

2.7 KiB

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:

scripts/ops/awooop-rls-canary-wave1-empty-tables.sql

Rollback script:

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:

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:

psql "$DATABASE_URL" -v ON_ERROR_STOP=1 \
  -f scripts/ops/awooop-rls-canary-wave1-empty-tables.sql

Then rerun:

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:

budget_ledger_no_context=InsufficientPrivilegeError
budget_ledger_with_context=allowed_and_rolled_back
budget_ledger_count_after=0

Rollback

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.