docs(rls): 記錄 canary wave1 production apply

This commit is contained in:
Your Name
2026-05-12 20:55:40 +08:00
parent 8c4dc7a5a8
commit 1617b73a9d
2 changed files with 75 additions and 2 deletions

View File

@@ -1,3 +1,51 @@
## 2026-05-12 | RLS Canary Wave1 已套用
**背景**:上一輪已產出 `scripts/ops/awooop-rls-canary-wave1-empty-tables.sql` 與 rollback SQL使用者批准後本輪只套用六張 live preflight 顯示為空表的 Wave1 canary policy不碰 `incidents` / `knowledge_entries` / `playbooks` / `audit_logs` 等高流量或非空表。
**套用前 gate**
- `python3 scripts/ops/awooop-rls-access-audit.py``BLOCKED=0 ALLOW=10`
- `python3 scripts/ops/awooop-rls-manual-script-audit.py``BLOCKED=0 REVIEW=5 PASS=13`
- `scripts/ops/awooop-rls-preflight.sh --exact-counts``PASS=7 WARN=0 BLOCKED=1`;唯一 blocker 為尚未啟用 policy。
- 六張 Wave1 target 仍為 `total_rows=0 null_project_id_rows=0`
- `awooop_contract_revisions`
- `awooop_conversation_event`
- `awooop_mcp_credential_refs`
- `awooop_mcp_gateway_audit`
- `awooop_mcp_grants`
- `budget_ledger`
**production apply**
- 已同步到 188
- `/home/ollama/awoooi-ops/awooop-rls-canary-wave1-empty-tables.sql`
- `/home/ollama/awoooi-ops/awooop-rls-canary-wave1-empty-tables-rollback.sql`
- 以 postgres/operator socket path 執行:
- Docker image`pgvector/pgvector:pg14`
- UID/GID`115:121` (`postgres:postgres`)
- DB`awoooi_prod`
- Apply result`COMMIT`,六張 target table 均 `ENABLE ROW LEVEL SECURITY` + `FORCE ROW LEVEL SECURITY` + fail-closed `FOR ALL TO awooop_app` policy。
**套用後驗證**
- `scripts/ops/awooop-rls-preflight.sh --exact-counts`
- Wave1 六張表皆為 `rls=True force=True policies=1 fail_open_null=False fail_open_empty=False`
- 全域 preflight 仍為 `PASS=7 WARN=0 BLOCKED=1`,剩餘 blocker 只列未套用的非空/後續 wave 表:`audit_logs``awooop_mcp_tool_registry``awooop_outbound_message``awooop_projects``awooop_run_state``incidents``knowledge_entries``playbooks`
- production health `/api/v1/health` → 200 healthy。
- runtime/manual audits 仍為:
- runtime access audit`BLOCKED=0 ALLOW=10`
- manual script audit`BLOCKED=0 REVIEW=5 PASS=13`
- RLS 行為 rollback-only 測試API pod / current app DB user
- 未設 `app.project_id``budget_ledger``InsufficientPrivilegeError`,符合 fail-closed。
-`app.project_id='awoooi'` 後寫 `budget_ledger` → allowed隨即 rollback。
- `budget_ledger_count_after=0`,未留下測試資料。
**整體進度**
- Wave 0MOMO PostgreSQL backup → AwoooP 失敗通知接線完成並已推 Gitea。
- Wave 1Claude P0 紅燈驗證已完成多項GitHub production deploy disabled、RLS production 0 policy 已證實、RLS role bootstrap 已套用、API runtime access path 已收斂、manual script gate 已建立、Wave1 空表 canary RLS 已套用。
- 尚未完成token rotation需外部輪換、188 certbot 正式修復、剩餘 RLS waves、高流量表 canary/rollout、188 local Ollama stop window。
**下一步**
- Wave1.1:選擇下一批低行數但非空表 canary候選`awooop_projects` 2 rows、`awooop_mcp_tool_registry` 4 rows先做 explicit read/write rollback tests再產出 apply/rollback SQL。
- 高流量表 (`incidents` / `knowledge_entries` / `playbooks` / `audit_logs`) 暫不熱開,需另做 query-path 與 rollback rehearsal。
## 2026-05-12 | RLS Manual Script Gate 與 Canary Wave1 套件
**背景**API runtime DB access path 已收斂後,下一個風險是人工腳本在 RLS fail-closed 後直接用 `DATABASE_URL` 讀寫 tenant tables同時需要第一批低風險 RLS policy 套件,但不可直接熱開高流量表。

View File

@@ -1,7 +1,9 @@
# AwoooP RLS Canary Wave 1
This wave is a staged apply package only. It enables fail-closed RLS on tables
that were empty in the latest production preflight.
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:
@@ -67,6 +69,29 @@ 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