docs(ops): 記錄 RLS role bootstrap 套用

This commit is contained in:
Your Name
2026-05-12 19:35:28 +08:00
parent f0255e0300
commit 33c0577e93
2 changed files with 82 additions and 15 deletions

View File

@@ -1,3 +1,40 @@
## 2026-05-12 | RLS Role Bootstrap 已套用
**背景**:上一輪已新增 `scripts/ops/awooop-rls-role-bootstrap.sql`,但尚未執行;使用者批准後,本輪只執行 role bootstrap不啟用 RLS policy。
**執行方式**
- 沒有使用 `sudo`,也沒有走 K8s app `DATABASE_URL`
- 188 `ollama` 使用者可用 Docker使用 host PostgreSQL socket 與 host `postgres` UID `115:121` 連線。
- 驗證連線為 `current_user=postgres``rolsuper=true` 後,透過 stdin 執行 `scripts/ops/awooop-rls-role-bootstrap.sql`
- SQL 成功 `COMMIT`,未建立任何密碼、未修改 K8s Secret、未啟用任何 RLS policy。
**role 結果**
- `awooop_app``NOLOGIN`,非 superuser`BYPASSRLS`
- `awooop_platform_admin``NOLOGIN``BYPASSRLS=true`
- `awooop_migration``NOLOGIN``BYPASSRLS=true`
- `awoooi` 仍是 production API DB user並已成為 `awooop_app` member。
- `awoooi_migrator` 存在,並已授權 `awooop_migration` group未變更其 password / login secret。
**post-bootstrap RLS preflight**
- `bash scripts/ops/awooop-rls-preflight.sh --exact-counts` → exit `2`,符合預期,因 policy 尚未啟用。
- `PASS=7 WARN=0 BLOCKED=1`
- 新增轉綠:
- `required_roles` → PASS。
- `app_role_membership` → PASS。
- 唯一 BLOCKED
- `rls_enabled_forced_policy`target tables 尚未 RLS enabled / forced / policied。
- exact counts 仍顯示 target tables `NULL project_id = 0`
**production smoke**
- `https://awoooi.wooo.work/api/v1/health` → 200PostgreSQL / Redis / Ollama / OpenClaw / SignOz 均 up。
- `/api/v1/platform/runs/list?per_page=1` → 200`total=126`
- `awoooi-api` pods 2/2 running近 10 分鐘 log 未見 DB permission / RLS / SQLAlchemy / asyncpg error。
**下一步**
- 不要直接全表熱開 RLS。
- 先做 DB access path audit確認所有 production read/write 入口皆會設定 `app.project_id`
- 再產出 staged policy enablement先 staging / canary再 production batch。
## 2026-05-12 | 188 Ollama Gate 綠燈與 RLS Role Bootstrap 設計
**背景**Wave 1 尚有兩個可收斂點188 local Ollama 是否仍有 direct caller以及 RLS roles 缺失如何安全補上。原則維持:只驗證與準備,不直接 uninstall 188 Ollama不直接 production 熱開 RLS。

View File

@@ -28,7 +28,7 @@ AWOOOP_RLS_SSH_TARGET=wooo@192.168.0.120 bash scripts/ops/awooop-rls-preflight.s
Exit code `2` means the gate is blocked and RLS must not be enabled yet.
## 2026-05-12 Production Result
## 2026-05-12 Initial Production Result
`--exact-counts` returned:
@@ -61,28 +61,58 @@ Important exact counts from the same run:
| `knowledge_entries` | 2102 | 0 |
| `playbooks` | 220 | 0 |
## 2026-05-12 Role Bootstrap Applied
At `19:33 CST`, the manual role bootstrap was applied through the host
PostgreSQL socket as `postgres`. It did not enable RLS policies.
Post-bootstrap `--exact-counts` returned:
- `PASS current_role_rls_enforced`: current DB user is still `awoooi`, not
superuser and not `BYPASSRLS`.
- `PASS project_context_set_config`: `set_config('app.project_id', 'awoooi', TRUE)` works.
- `PASS required_roles`: `awooop_app`, `awooop_platform_admin`, and
`awooop_migration` now exist.
- `PASS app_role_membership`: current API DB user is a member of `awooop_app`.
- `PASS project_id_columns`: every existing target table has `project_id`.
- `BLOCKED rls_enabled_forced_policy`: target tables are still not RLS enabled,
forced, or policied.
- `PASS fail_open_policies`: no fail-open policy expressions detected.
- `PASS project_id_backfill`: exact counts found zero `NULL project_id` rows in
counted target tables.
Current blocker summary:
```text
PASS=7 WARN=0 BLOCKED=1
```
Updated exact counts:
| Table | Rows | NULL project_id |
| --- | ---: | ---: |
| `audit_logs` | 686 | 0 |
| `awooop_mcp_tool_registry` | 4 | 0 |
| `awooop_outbound_message` | 248 | 0 |
| `awooop_projects` | 2 | 0 |
| `awooop_run_state` | 126 | 0 |
| `incidents` | 1524 | 0 |
| `knowledge_entries` | 2103 | 0 |
| `playbooks` | 220 | 0 |
## Remediation Order
1. Create or reconcile RLS roles.
- Current production app user is `awoooi`; policy design must either grant it
membership in `awooop_app` or update the application connection role before
policies are enforced.
- Do not create passworded LOGIN roles in a migration unless the K8s Secret
rotation path is ready.
- Use `scripts/ops/awooop-rls-role-bootstrap.sql` only after review, and run
it manually as `postgres` or a `CREATEROLE` operator. It is intentionally
outside `apps/api/migrations/` so Gitea auto-migration will not run it.
2. Verify all DB access paths use `get_db()` / `get_db_context()` or otherwise set
1. Verify all DB access paths use `get_db()` / `get_db_context()` or otherwise set
`app.project_id` before queries.
3. Apply policies first in staging or a canary DB.
4. In production, enable one batch at a time.
5. After each batch, run:
2. Apply policies first in staging or a canary DB.
3. In production, enable one batch at a time.
4. After each batch, run:
```bash
bash scripts/ops/awooop-rls-preflight.sh --exact-counts
```
6. Validate AwoooP Runs, Approvals, Monitoring, Tickets, Cost, alert ingestion,
5. Validate AwoooP Runs, Approvals, Monitoring, Tickets, Cost, alert ingestion,
background workers, and TelegramGateway mirror paths.
## Do Not