Phase 6.4 - Modular Architecture: - Add lewooogo-brain adapters for LLM providers - Add lewooogo-data dual memory (Redis + PostgreSQL) - Implement consensus engine for multi-agent decisions - Add incident memory service for historical context Phase 9 - Agent Teams (Claude Agent SDK): - Add base agent class with Claude Sonnet 4 integration - Implement action planner, blast radius, and security agents - Add agent API endpoints and proposal workflow - Integrate ADR-009 OpenClaw Agent Teams architecture DevOps & CI/CD: - Add GitHub Actions CI/CD workflows (ci.yaml, cd.yaml) - Add pre-commit hooks and secrets baseline - Add docker-compose for local development - Update Kubernetes network policies Frontend Improvements: - Add auto-healing error boundary component - Update i18n messages for agent features - Enhance dual-state incident card with execution feedback Documentation: - Add 7 ADRs covering MCP, design system, architecture decisions - Update ARCHITECTURE_MEMORY.md with modular design - Add GLOBAL_RULES.md and SOUL.md for project identity Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
11 KiB
11 KiB
AWOOOI API 開發 SOP
版本: v1.0 建立日期: 2026-03-20 負責人: CTO 狀態: Phase 0 草稿
概述
此文件定義 AWOOOI 所有 API 端點的開發標準流程,確保 Contract-First 原則與 CI 強制檢查能夠有效執行。
API 開發流程
1. 設計階段 (Design)
┌─────────────────────────────────────────────────────────────┐
│ Step 1: OpenAPI 定義 │
├─────────────────────────────────────────────────────────────┤
│ 位置: docs/api/openapi.yaml │
│ 工具: Stoplight Studio / VS Code OpenAPI Editor │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ Step 2: 端點文檔 (Markdown) │
├─────────────────────────────────────────────────────────────┤
│ 位置: docs/api/endpoints/{module}/{endpoint}.md │
│ 內容: 用途說明、請求範例、回應範例、錯誤碼 │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ Step 3: PR Review + Approval │
├─────────────────────────────────────────────────────────────┤
│ 審核者: CTO / CISO (安全相關 API) │
│ 檢查項: 命名規範、版本策略、錯誤處理、安全考量 │
└─────────────────────────────────────────────────────────────┘
2. 實作階段 (Implementation)
# apps/api/app/routers/{module}.py
from fastapi import APIRouter, Depends, HTTPException, status
from app.schemas.{module} import {RequestModel}, {ResponseModel}
from app.services.{module} import {ServiceClass}
from app.core.deps import get_current_user, rate_limit
from app.core.cache import cache_response
router = APIRouter(prefix="/v1/{module}", tags=["{module}"])
@router.get(
"/{endpoint}",
response_model={ResponseModel},
summary="端點摘要",
description="詳細說明",
responses={
200: {"description": "成功"},
400: {"description": "請求格式錯誤"},
401: {"description": "未授權"},
403: {"description": "權限不足"},
404: {"description": "資源不存在"},
429: {"description": "請求過於頻繁"},
500: {"description": "伺服器錯誤"},
}
)
@cache_response(ttl=60) # 快取策略
@rate_limit(requests=100, window=60) # 限流策略
async def endpoint_name(
request: {RequestModel},
current_user: User = Depends(get_current_user),
service: {ServiceClass} = Depends()
):
"""
端點實作邏輯
"""
pass
3. 測試階段 (Testing)
# apps/api/tests/test_{module}.py
import pytest
from httpx import AsyncClient
from app.main import app
class Test{Module}API:
"""
測試命名規範: test_{method}_{endpoint}_{scenario}
"""
@pytest.mark.asyncio
async def test_get_endpoint_success(self, client: AsyncClient, auth_headers: dict):
response = await client.get("/v1/{module}/{endpoint}", headers=auth_headers)
assert response.status_code == 200
assert "data" in response.json()
@pytest.mark.asyncio
async def test_get_endpoint_unauthorized(self, client: AsyncClient):
response = await client.get("/v1/{module}/{endpoint}")
assert response.status_code == 401
@pytest.mark.asyncio
async def test_get_endpoint_not_found(self, client: AsyncClient, auth_headers: dict):
response = await client.get("/v1/{module}/nonexistent", headers=auth_headers)
assert response.status_code == 404
API 版本策略
URL 版本控制
https://api.awoooi.wooo.work/v1/... # 目前版本
https://api.awoooi.wooo.work/v2/... # 未來版本 (重大變更時)
版本升級規則
| 變更類型 | 版本影響 | 範例 |
|---|---|---|
| 新增端點 | 不變 | 新增 GET /v1/metrics/custom |
| 新增可選欄位 | 不變 | Response 新增 metadata 欄位 |
| 移除/重命名欄位 | 升版 | user_id → userId |
| 變更回應結構 | 升版 | 陣列 → 分頁物件 |
| 變更認證方式 | 升版 | Bearer → OAuth2 |
棄用流程
- 通知 (v1.x): 在回應 Header 加入
Deprecation: true+Sunset: 2026-06-01 - 文檔標記: OpenAPI 加入
deprecated: true - 過渡期: 至少 3 個月
- 移除: 完全移除舊端點
命名規範
URL 路徑
# ✅ 正確
GET /v1/hosts # 列表
GET /v1/hosts/{id} # 單一資源
POST /v1/hosts # 建立
PUT /v1/hosts/{id} # 完整更新
PATCH /v1/hosts/{id} # 部分更新
DELETE /v1/hosts/{id} # 刪除
# ✅ 子資源
GET /v1/hosts/{id}/metrics # 主機的指標
POST /v1/hosts/{id}/actions/scan # 動作 (非 CRUD)
# ❌ 錯誤
GET /v1/getHosts # 動詞命名
GET /v1/host_list # 底線 + 複數不一致
POST /v1/hosts/create # 冗餘動詞
查詢參數
# 分頁
?page=1&limit=20
# 排序
?sort=created_at&order=desc
# 篩選
?status=active&host_id=h-001
# 搜尋
?q=keyword
# 時間範圍
?start_time=2026-03-01T00:00:00Z&end_time=2026-03-20T23:59:59Z
請求/回應欄位
// ✅ 正確: camelCase (JSON 標準)
{
"hostId": "h-001",
"hostName": "web-server-01",
"createdAt": "2026-03-20T10:00:00Z",
"isActive": true
}
// ❌ 錯誤: snake_case (Python 內部使用)
{
"host_id": "h-001",
"host_name": "web-server-01"
}
回應格式
成功回應
// 單一資源
{
"data": {
"id": "h-001",
"name": "web-server-01",
"status": "healthy"
},
"meta": {
"requestId": "req-abc123",
"timestamp": "2026-03-20T10:00:00Z"
}
}
// 列表 (分頁)
{
"data": [
{"id": "h-001", "name": "web-server-01"},
{"id": "h-002", "name": "web-server-02"}
],
"pagination": {
"page": 1,
"limit": 20,
"total": 45,
"totalPages": 3
},
"meta": {
"requestId": "req-abc123",
"timestamp": "2026-03-20T10:00:00Z"
}
}
錯誤回應
{
"error": {
"code": "VALIDATION_ERROR",
"message": "請求參數驗證失敗",
"details": [
{
"field": "email",
"message": "必須為有效的電子郵件格式"
}
]
},
"meta": {
"requestId": "req-abc123",
"timestamp": "2026-03-20T10:00:00Z"
}
}
錯誤碼對照表
| HTTP Status | Error Code | 說明 |
|---|---|---|
| 400 | VALIDATION_ERROR |
請求參數驗證失敗 |
| 400 | INVALID_FORMAT |
請求格式錯誤 |
| 401 | UNAUTHORIZED |
未提供認證資訊 |
| 401 | TOKEN_EXPIRED |
Token 已過期 |
| 403 | FORBIDDEN |
權限不足 |
| 404 | NOT_FOUND |
資源不存在 |
| 409 | CONFLICT |
資源衝突 |
| 422 | UNPROCESSABLE_ENTITY |
語意錯誤 |
| 429 | RATE_LIMITED |
請求過於頻繁 |
| 500 | INTERNAL_ERROR |
伺服器內部錯誤 |
| 503 | SERVICE_UNAVAILABLE |
服務暫時不可用 |
安全規範
認證
Authorization: Bearer <jwt_token>
必要 Headers
Content-Type: application/json
Accept: application/json
X-Request-ID: <uuid> # 用於追蹤
X-Source: awoooi # 識別來源 (Kali Scanner 需要)
敏感資料處理
# ❌ 禁止: 回應中包含密碼、Token
{
"user": {
"password": "hashed_value", # 禁止
"apiKey": "sk-xxx" # 禁止
}
}
# ✅ 正確: 脫敏處理
{
"user": {
"hasPassword": true,
"apiKeyPrefix": "sk-***xxx"
}
}
日誌脫敏
# 自動脫敏欄位
SENSITIVE_FIELDS = [
"password", "token", "api_key", "secret",
"authorization", "cookie", "credit_card"
]
# 日誌輸出
# ✅ {"user": "admin", "password": "[REDACTED]"}
# ❌ {"user": "admin", "password": "actual_password"}
快取策略
TTL 分層
| 資料類型 | TTL | 說明 |
|---|---|---|
| 靜態配置 | 1 小時 | 系統設定、選單 |
| 聚合數據 | 5 分鐘 | Dashboard 統計 |
| 即時數據 | 30 秒 | 主機狀態、指標 |
| 無快取 | 0 | 審計日誌、敏感操作 |
快取 Key 規範
awoooi:{version}:{module}:{resource}:{id}:{params_hash}
# 範例
awoooi:v1:hosts:list:abc123
awoooi:v1:hosts:detail:h-001
awoooi:v1:metrics:dashboard:user-001:7d
CI 檢查項目
自動化檢查
| 檢查項 | 工具 | 失敗處理 |
|---|---|---|
| OpenAPI Schema 驗證 | spectral | 阻擋合併 |
| OpenAPI ↔ 程式碼一致性 | openapi-diff | 阻擋合併 |
| 端點文檔存在性 | 自訂腳本 | 阻擋合併 |
| 測試覆蓋率 > 80% | pytest-cov | 阻擋合併 |
| 安全掃描 | bandit | 警告 |
PR Checklist
## API 變更 Checklist
- [ ] OpenAPI 規格已更新 (`docs/api/openapi.yaml`)
- [ ] 端點文檔已更新 (`docs/api/endpoints/...`)
- [ ] 單元測試已撰寫 (覆蓋率 > 80%)
- [ ] 錯誤處理已實作
- [ ] 快取策略已定義
- [ ] 限流規則已設定
- [ ] 日誌已加入 (不含敏感資料)
- [ ] CISO 已審核 (安全相關 API)
文檔工具
內部開發
- Swagger UI:
http://localhost:8000/docs - 用途: 開發階段測試、除錯
對外文檔
- Scalar:
https://api.awoooi.wooo.work/scalar - 風格: Nothing.tech 純白主題
- 用途: 外部開發者文檔
變更記錄
| 日期 | 版本 | 變更 | 作者 |
|---|---|---|---|
| 2026-03-20 | v1.0 | 初版建立 | CTO |
此文件由 CTO 維護,API 開發者必須遵守此 SOP。