Files
awoooi/docs/adr/ADR-021-playbook-update-validation.md
OG T 2f5986df5c docs: ADR 整理與新增 (021-029)
ADR 編號修正:
- ADR-023 failure-auto-repair → ADR-028
- ADR-025 cicd-ai-integration → ADR-029

新增 ADR:
- ADR-021: Playbook 更新驗證
- ADR-022: Sentry 整合架構
- ADR-027: Incident-Approval 同步
- ADR-028: 失敗自動修復閉環
- ADR-029: CI/CD AI 整合 (原 ADR-025)

更新:
- ADR-018: LLM 測試策略狀態更新

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-26 19:09:08 +08:00

2.1 KiB

ADR-021: Playbook 更新驗證策略

屬性
狀態 Accepted
建立日期 2026-03-26
決策者 首席架構師
關聯 Phase 8 P1 修復, leWOOOgo 積木化原則

背景

Router 層 (playbooks.py) 使用 setattr() 動態更新 Playbook 欄位,繞過 Pydantic 驗證:

# ❌ 問題代碼 (Router 層)
update_data = request.model_dump(exclude_unset=True)
for field, value in update_data.items():
    setattr(playbook, field, value)  # 無驗證!

問題:

  1. 資料完整性 - 非法狀態值可直接寫入
  2. 違反分層 - Router 層執行業務邏輯
  3. 安全風險 - 可修改 playbook_id, success_count 等欄位

決策

將更新邏輯移至 Service 層,實作 update_with_validation() 方法。

驗證規則

規則 說明
禁止修改欄位 playbook_id, created_at, success_count, failure_count, last_used_at
狀態轉換 DRAFT → APPROVED (允許), APPROVED → DEPRECATED (允許), 反向 (禁止)
DEPRECATED 狀態 不可修改任何欄位

實作

# ✅ Service 層 (playbook_service.py)
async def update_with_validation(
    self,
    playbook_id: str,
    update_data: dict,
) -> Playbook | None:
    # 1. 過濾禁止修改的欄位
    # 2. 驗證狀態轉換
    # 3. 應用更新
    # 4. 儲存
# ✅ Router 層 (playbooks.py)
updated = await service.update_with_validation(
    playbook_id=playbook_id,
    update_data=request.model_dump(exclude_unset=True),
)

影響

檔案 變更
src/services/playbook_service.py 新增 update_with_validation()
src/api/v1/playbooks.py 改用 Service 方法

替代方案

方案 優點 缺點 決定
維持現狀 (setattr) 無需改動 繞過驗證
Pydantic validator 自動驗證 無法檢查狀態轉換
Service 層驗證 完整控制 需新增方法

相關

  • ADR-003: leWOOOgo 積木化架構
  • Skill 02: leWOOOgo Backend Core