Files
awoooi/docs/runbooks/AWOOOP-RLS-MANUAL-SCRIPTS.md
Your Name 8c4dc7a5a8
Some checks failed
Code Review / ai-code-review (push) Successful in 10s
CD Pipeline / tests (push) Successful in 1m5s
CD Pipeline / build-and-deploy (push) Failing after 10m6s
CD Pipeline / post-deploy-checks (push) Has been skipped
chore(rls): 新增 manual script gate 與 canary wave1
2026-05-12 20:23:27 +08:00

1.7 KiB

AwoooP RLS Manual Script Review

Manual scripts are not API runtime, but they can still break after fail-closed RLS if they connect directly with DATABASE_URL and do not set app.project_id.

Run:

python3 scripts/ops/awooop-rls-manual-script-audit.py --show-pass

Use strict mode for CI or pre-apply review:

python3 scripts/ops/awooop-rls-manual-script-audit.py --strict-review

2026-05-12 Result

AwoooP RLS manual script audit: BLOCKED=0 REVIEW=5 PASS=13

BLOCKED=0 means no hardcoded PostgreSQL URL with inline credentials was found in the scanned manual scripts.

REVIEW=5 are intentional operator paths:

  • apps/api/scripts/awooop_phase1_batch1_backfill.py: RLS/project_id bootstrap backfill; use migration/operator role.
  • apps/api/scripts/run_migration.py: DDL migration script; use migration/operator role.
  • scripts/ops/awooop-rls-role-bootstrap.sql: role bootstrap; requires postgres/CREATEROLE operator.
  • scripts/ops/awooop_rls_preflight.py: read-only preflight inside API pod.
  • scripts/sync_dev_db.py: dev schema sync; requires DEV_DATABASE_URL and must not target production.

The common tenant-data manual scripts now set app.project_id or use get_db_context().

Operator Rule

  • Direct tenant table access must set app.project_id on every connection, or use an approved migration/operator role with BYPASSRLS.
  • Direct asyncpg scripts should use session-level context:
await conn.execute("SELECT set_config('app.project_id', $1, FALSE)", project_id)
  • SQLAlchemy runtime/service code should use get_db_context() or get_db().
  • Do not add PostgreSQL URLs with inline credentials to scripts, comments, or examples.