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>
415 lines
11 KiB
Markdown
415 lines
11 KiB
Markdown
# 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)
|
||
|
||
```python
|
||
# 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)
|
||
|
||
```python
|
||
# 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 |
|
||
|
||
### 棄用流程
|
||
|
||
1. **通知** (v1.x): 在回應 Header 加入 `Deprecation: true` + `Sunset: 2026-06-01`
|
||
2. **文檔標記**: OpenAPI 加入 `deprecated: true`
|
||
3. **過渡期**: 至少 3 個月
|
||
4. **移除**: 完全移除舊端點
|
||
|
||
---
|
||
|
||
## 命名規範
|
||
|
||
### 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
|
||
```
|
||
|
||
### 請求/回應欄位
|
||
|
||
```json
|
||
// ✅ 正確: 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"
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 回應格式
|
||
|
||
### 成功回應
|
||
|
||
```json
|
||
// 單一資源
|
||
{
|
||
"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"
|
||
}
|
||
}
|
||
```
|
||
|
||
### 錯誤回應
|
||
|
||
```json
|
||
{
|
||
"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` | 服務暫時不可用 |
|
||
|
||
---
|
||
|
||
## 安全規範
|
||
|
||
### 認證
|
||
|
||
```http
|
||
Authorization: Bearer <jwt_token>
|
||
```
|
||
|
||
### 必要 Headers
|
||
|
||
```http
|
||
Content-Type: application/json
|
||
Accept: application/json
|
||
X-Request-ID: <uuid> # 用於追蹤
|
||
X-Source: awoooi # 識別來源 (Kali Scanner 需要)
|
||
```
|
||
|
||
### 敏感資料處理
|
||
|
||
```python
|
||
# ❌ 禁止: 回應中包含密碼、Token
|
||
{
|
||
"user": {
|
||
"password": "hashed_value", # 禁止
|
||
"apiKey": "sk-xxx" # 禁止
|
||
}
|
||
}
|
||
|
||
# ✅ 正確: 脫敏處理
|
||
{
|
||
"user": {
|
||
"hasPassword": true,
|
||
"apiKeyPrefix": "sk-***xxx"
|
||
}
|
||
}
|
||
```
|
||
|
||
### 日誌脫敏
|
||
|
||
```python
|
||
# 自動脫敏欄位
|
||
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
|
||
|
||
```markdown
|
||
## 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。*
|