50 lines
1.5 KiB
Markdown
50 lines
1.5 KiB
Markdown
# AwoooP RLS Access Path Audit
|
|
|
|
> Purpose: verify API runtime DB access paths are ready for fail-closed RLS.
|
|
|
|
Before enabling RLS policies, runtime database access must set
|
|
`app.project_id`. The approved paths are:
|
|
|
|
- FastAPI dependency `get_db()`.
|
|
- Background/service context `get_db_context()`.
|
|
- `UnitOfWork`, which now sets `app.project_id` on entry.
|
|
|
|
Both `get_db()` and `get_db_context()` derive `app.project_id` from
|
|
`src.core.context.get_current_project_id()` unless the caller passes an explicit
|
|
project id to `get_db_context()`.
|
|
|
|
Run:
|
|
|
|
```bash
|
|
python3 scripts/ops/awooop-rls-access-audit.py
|
|
```
|
|
|
|
To include accepted exceptions:
|
|
|
|
```bash
|
|
python3 scripts/ops/awooop-rls-access-audit.py --show-allowed
|
|
```
|
|
|
|
## 2026-05-12 Result
|
|
|
|
After fixing direct `get_session_factory()` runtime call sites:
|
|
|
|
```text
|
|
AwoooP RLS access audit: BLOCKED=0 ALLOW=10
|
|
```
|
|
|
|
Accepted exceptions:
|
|
|
|
- `apps/api/src/db/base.py`: owns the shared engine/session factory and sets
|
|
`app.project_id` in `get_db()` / `get_db_context()`.
|
|
- `apps/api/src/routes/health.py`: raw `asyncpg` health check only runs
|
|
`SELECT 1`, not tenant table queries.
|
|
- `apps/api/src/main.py` and `apps/api/src/workers/signal_worker.py`: only log a
|
|
sanitized DB host suffix.
|
|
- `apps/api/src/services/incident_approval_service.py`: injects
|
|
`UnitOfWork`; `UnitOfWork` now sets `app.project_id`.
|
|
|
|
Manual scripts under `apps/api/scripts/` and top-level `scripts/` are not API
|
|
runtime. They still need operator review before being used against production
|
|
after RLS policy enablement.
|