- 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>
5.2 KiB
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"→ 強制 HITL,AI 無法覆寫auto_repair: "true"→ 進入 AI + Guardrail 評估,Guardrail 有最終否決權
D5 — Langfuse trace_id 寫入 alert_operation_log(Q10)
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_repairflag 成為有效的安全底線 - 系統複雜度增加,但「資料安全」優先於「修復速度」
實施計畫
見 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_repairflag 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 |