feat(Phase 6): AI SLO REST API — GET /api/v1/ai/slo 收官
Some checks failed
CD Pipeline / build-and-deploy (push) Has been cancelled

ADR-087 Phase 6 自我治理閉環最後一塊拼圖:

1. api/v1/ai_slo.py — GET /api/v1/ai/slo
   - Service 層快取優先(TTL 5min,AiSloCalculator.get_cached_report)
   - force_refresh=true 強制重算(AiSloCalculator.run)
   - Router 層零 Redis 直接存取(leWOOOgo 積木化鐵律)

2. main.py — 路由掛載 ai_slo_v1.router(prefix=/api/v1)

3. MASTER §8 Living Changelog 追加:
   - P0 告警靜默 3 根因 RCA 完整紀錄
   - P2 飛輪斷鏈修復摘要
   - Phase 6 全元件完成清單

Phase 6 退出條件 5/6 已達(生產驗證待 image 上線)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
OG T
2026-04-15 19:57:26 +08:00
parent 14579ce149
commit 05b774386b
3 changed files with 105 additions and 0 deletions

View File

@@ -0,0 +1,58 @@
"""
AI SLO REST API
===============
ADR-087 Phase 6 自我治理閉環 — AI 決策品質 SLO 查詢端點
Endpoints:
GET /api/v1/ai/slo — 取得最新 SLO 計算結果(含 Redis 快取)
設計原則:
- 優先讀 Service 層快取TTL 5min快取失效才重算
- 計算失敗 → 保守回傳 any_violated=True由 AiSloCalculator 處理)
- 強制重算:?force_refresh=true
- Router 層不直接存取 RedisleWOOOgo 積木化鐵律)
2026-04-15 ogt + Claude Sonnet 4.6(亞太): Phase 6 初始建立
"""
from __future__ import annotations
import structlog
from fastapi import APIRouter, Query
from src.services.ai_slo_calculator import AiSloCalculator
logger = structlog.get_logger(__name__)
router = APIRouter()
@router.get("/ai/slo")
async def get_ai_slo(
force_refresh: bool = Query(False, description="忽略快取,強制重算"),
) -> dict:
"""
取得 AI 決策品質 SLO 最新結果。
優先讀 Redis 快取TTL 5minforce_refresh=true 則強制重算並更新快取。
Response:
calculated_at ISO 時間戳
window_days 計算視窗(天)
any_violated 是否有任何 SLO 違反
cache_hit 是否命中快取
metrics[] 三大 SLO 指標明細
"""
calc = AiSloCalculator()
if not force_refresh:
cached = await calc.get_cached_report()
if cached:
data = cached.to_dict()
data["cache_hit"] = True
return data
report = await calc.run()
data = report.to_dict()
data["cache_hit"] = False
return data

View File

@@ -34,6 +34,7 @@ from sentry_sdk.integrations.starlette import StarletteIntegration
from src.api.v1 import agents as agents_v1 # Phase 9.5: Agent Teams API
from src.api.v1 import ai as ai_v1
from src.api.v1 import ai_slo as ai_slo_v1 # Phase 6 ADR-087: AI SLO 自我治理
from src.api.v1 import approvals as approvals_v1
from src.api.v1 import alert_operation_logs as alert_operation_logs_v1
from src.api.v1 import audit_logs as audit_logs_v1
@@ -514,6 +515,7 @@ app.include_router(csrf_v1.router, prefix="/api/v1", tags=["Security"]) # Phase
app.include_router(dashboard_v1.router, prefix="/api/v1", tags=["Dashboard"])
app.include_router(approvals_v1.router, prefix="/api/v1", tags=["HITL Approvals"])
app.include_router(ai_v1.router, prefix="/api/v1", tags=["AI Decision"])
app.include_router(ai_slo_v1.router, prefix="/api/v1", tags=["AI SLO"]) # Phase 6 ADR-087
app.include_router(webhooks_v1.router, prefix="/api/v1", tags=["Webhooks"])
app.include_router(timeline_v1.router, prefix="/api/v1", tags=["Timeline"])
app.include_router(audit_logs_v1.router, prefix="/api/v1", tags=["Audit Logs"])