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

80 lines
2.1 KiB
Markdown

# ADR-021: Playbook 更新驗證策略
| 屬性 | 值 |
|------|-----|
| **狀態** | Accepted |
| **建立日期** | 2026-03-26 |
| **決策者** | 首席架構師 |
| **關聯** | Phase 8 P1 修復, leWOOOgo 積木化原則 |
## 背景
Router 層 (`playbooks.py`) 使用 `setattr()` 動態更新 Playbook 欄位,繞過 Pydantic 驗證:
```python
# ❌ 問題代碼 (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 狀態** | 不可修改任何欄位 |
### 實作
```python
# ✅ Service 層 (playbook_service.py)
async def update_with_validation(
self,
playbook_id: str,
update_data: dict,
) -> Playbook | None:
# 1. 過濾禁止修改的欄位
# 2. 驗證狀態轉換
# 3. 應用更新
# 4. 儲存
```
```python
# ✅ 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