104 lines
2.7 KiB
Markdown
104 lines
2.7 KiB
Markdown
# 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.
|