Files
awoooi/docs/adr/ADR-062-data-safety-guardrails.md
OG T 0af5c2e89c docs(sprint5.1): LOGBOOK + ADR-062 + Skill 02 更新(首席架構師審查記錄)
- docs/LOGBOOK.md: 當前狀態更新至 L1-L5+審查完成,里程碑補充審查修正記錄
- docs/adr/ADR-062: 新增實施記錄章節(執行清單+審查問題+修正方式)
- .agents/skills/02-lewooogo-backend-core.md v2.5→v2.6:
    加入 Sprint 5.1 Service Registry 模式
    加入 Guardrail 保守原則(失敗 block 不放行)
    加入新 Service 標準樣板(structlog/now_taipei/DI setter/try-except)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-08 16:38:31 +08:00

128 lines
5.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# ADR-062 — 資料安全護欄 (Data Safety Guardrails)
> **狀態**: 已批准 (首席架構師裁示 2026-04-08)
> **撰寫**: Claude Sonnet 4.6 / 2026-04-08 Asia/Taipei
> **相關**: ADR-061 (Alert Operation Log), ADR-058 (SSH Host Repair), ADR-039 (CI/CD)
---
## 背景
Sprint 5.1 啟動前AWOOOI 的自動修復機制已「移除所有 gate」2026-04-08 統帥指令),所有 APPROVED Playbook 均可直接執行。此設計在無狀態服務上運作良好,但對**有狀態服務Stateful Services**存在資料遺失風險:
- PostgreSQL 重啟 → WAL 截斷、事務回滾
- Redis 重啟 → in-memory 資料遺失、冪等鎖消失
- ClickHouse 重啟 → 列欄檔案損壞
同時系統缺乏「AI 動作可追查」機制OpenClaw 的 LLM 推理過程與 alert_operation_log 斷層。
---
## 決策
### D1 — 服務分級Q1
建立四級 Stateful 分類,儲存於 `ops/config/service-registry.yaml`IaC版控
| 等級 | 定義 | 服務 |
|------|------|------|
| `BLOCK` | 系統禁止,僅告警 | PostgreSQL (所有實例), ClickHouse |
| `CRITICAL_HITL` | MultiSig 2票才執行 | Redis, Gitea, Harbor, MinIO |
| `STANDARD_HITL` | 1票審核特殊 restart 命令 | Prometheus, Grafana, Alertmanager |
| `AUTO` | 自動執行 | Nginx, 所有 K3s Pod, Ollama 等 |
### D2 — Pre-flight 備份檢查Q2
針對 `CRITICAL_HITL``requires_pre_backup=True` 的服務,執行前檢查:
- Velero 最近 Completed 備份 < 4 小時 → 放行
- 過期 → **Abort + 觸發緊急備份(非同步)+ 通知人工**(非直接執行)
- CPU/IO 高負載類告警 → 禁止觸發備份Q4防止雪上加霜
### D3 — MultiSig 雙簽Q3
`CRITICAL_HITL` 服務需要 2 票 Telegram 授權才執行,延續 Sprint 3 的 MultiSig 基礎設施。Sprint 5.1 先以同一 user 兩次點擊驗證狀態機,後續 Sprint 擴充多帳號。
### D4 — Prometheus auto_repair flag 優先級Q9
- `auto_repair: "false"` → 強制 HITLAI 無法覆寫
- `auto_repair: "true"` → 進入 AI + Guardrail 評估Guardrail 有最終否決權
### D5 — Langfuse trace_id 寫入 alert_operation_logQ10
OpenClaw 分析完成後,`langfuse_trace_id` 必須寫入 `alert_operation_log.context`,實現 AI 動作全程可追查。
### D6 — AlertManager 不抑制Q11
Guardrail 阻擋時,不呼叫 AlertManager silence API。靠 AWOOOI Redis TTL 去重10 分鐘AlertManager 持續 firing 保持監控可見性。
---
## 新增 event_type共 8 個)
```
GUARDRAIL_BLOCKED # Stateful 服務被阻擋
PRE_FLIGHT_PASSED # Pre-flight 備份檢查通過
PRE_FLIGHT_FAILED # Pre-flight 失敗(備份過期)
BACKUP_TRIGGERED # 緊急備份已觸發
BACKUP_COMPLETED # 緊急備份完成
BACKUP_FAILED # 緊急備份失敗
APPROVAL_ESCALATED # 升級為 CRITICAL_APPROVAL需 2 票)
CHANGE_APPLIED # 手動變更已記錄
```
---
## 新增模組
| 模組 | 路徑 | 職責 |
|------|------|------|
| ServiceRegistryClient | `services/service_registry.py` | 讀取 YAML查詢服務分級 |
| VeleroClient | `services/velero_client.py` | kubectl 查詢備份狀態,觸發緊急備份 |
| PreflightService | `services/preflight_service.py` | Pre-flight 備份檢查邏輯 |
所有模組遵循 leWOOOgo 積木化規範Service 層,有 `get_xxx()` + `set_xxx()` singleton 模式。
---
## 後果
- 所有有狀態服務的自動修復操作,由「預設允許」改為「預設拒絕,明確授權才執行」
- AI 每一個修復決策都有 Langfuse trace_id 可追查
- Prometheus alert rule 的 `auto_repair` flag 成為有效的安全底線
- 系統複雜度增加,但「資料安全」優先於「修復速度」
---
## 實施計畫
`docs/superpowers/plans/2026-04-08-sprint5-data-safety-guardrails.md`Layer 0~7 完整步驟)
---
## 實施記錄Sprint 5.1 執行)
### L1-L5 完成2026-04-08 commit 88696db
- DB Migration M-002/M-003 已在 192.168.0.188 執行完畢
- `ops/config/service-registry.yaml` 建立21 個服務分級)
- 三個新 Service 建立:`service_registry.py` / `velero_client.py` / `preflight_service.py`
- Guardrail 注入 `auto_repair_service.py`BLOCK 等級保守拒絕)
- ALERT_RECEIVED 溯源 + `auto_repair` flag Q9 + Langfuse trace_id Q10 寫入 `webhooks.py`
- `db/models.py` 同步 MultiSig 欄位
- `docker-health-monitor.sh` 純感知層改造(移除所有 docker restart
- T1-T6 六個 Telegram 通知方法加入 `telegram_gateway.py`
### 首席架構師審查2026-04-08 commit 0f5fecf
評分70/100 → 修正後 90+/100
| 問題 | 級別 | 修正 |
|------|------|------|
| 三個新 service 使用 `logging` 而非 `structlog` | S1 | 改用 `structlog.get_logger()` |
| `velero_client` 使用 `datetime.now(UTC)` | S1 | 改用 `now_taipei()`(台北時區鐵律) |
| Guardrail 失敗時放行(保守原則方向錯誤) | S1 | 失敗時 block返回 `GUARDRAIL_ERROR` |
| `service_registry` import 在函數內部 | S1 | 移至模組頂部 |
| T1-T6 方法無 try/except | S2 | 全部補齊,失敗 log 不拋出 |
| Langfuse URL 硬寫內網 IP | S2 | 改用 `settings.LANGFUSE_URL` |
| `velero trigger_emergency_backup` kubectl 語法錯誤 | S3 | 改為 `kubectl apply Backup CRD` |