# ADR-005: 導入 BFF (Backend-For-Frontend) API 閘道模式

> **狀態**: Accepted
> **日期**: 2026-03-19
> **決策者**: CTO + CIO

## 背景

AWOOOI 的底層是由 leWOOOgo Engine 驅動的微服務/Plugin 架構。如果讓 Next.js 前端直接呼叫：
- 多個分散的 Plugin API
- Ollama / Claude API
- PostgreSQL / Redis
- K8s API

會導致：
1. 前端邏輯過於肥大
2. 極高的資安外洩風險
3. 難以實施統一的身分驗證與權限控制

## 決策

**強制實施 BFF (Backend-For-Frontend) 架構**

```
┌─────────────────────────────────────────────────────────────────┐
│                        AWOOOI 架構                               │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│   ┌─────────┐         ┌─────────────────┐                       │
│   │ Next.js │ ──────→ │  FastAPI BFF    │                       │
│   │ 前端    │ HTTPS   │  Gateway        │                       │
│   └─────────┘         └────────┬────────┘                       │
│                                │                                │
│            ┌───────────────────┼───────────────────┐            │
│            ↓                   ↓                   ↓            │
│   ┌─────────────┐     ┌─────────────┐     ┌─────────────┐       │
│   │ leWOOOgo    │     │ OpenClaw     │     │ PostgreSQL  │       │
│   │ Plugins     │     │ (Ollama)    │     │ Redis       │       │
│   └─────────────┘     └─────────────┘     └─────────────┘       │
│                                                                 │
│   ════════════════════════════════════════════════════════════  │
│                    DMZ (前端無法直達)                            │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘
```

### 核心規則

| 規則 | 說明 |
|------|------|
| **單一入口** | 前端只能打 `https://api.awoooi.wooo.work/v1/*` |
| **禁止直連** | 前端禁止直連 PostgreSQL、Redis、K8s、Ollama |
| **身分驗證** | 所有請求經 BFF JWT 驗證 |
| **資料脫敏** | Privacy Shield 在 BFF 層攔截機敏資料 |

### BFF 層職責

```python
# apps/api/src/routes/agent.py

from fastapi import APIRouter, Depends
from src.auth import require_auth
from src.privacy import PrivacyShield
from src.services import openclaw_client, approval_service

router = APIRouter(prefix="/agent", tags=["Agent"])

@router.post("/chat")
async def chat_with_agent(
    request: ChatRequest,
    user: User = Depends(require_auth),  # 1. 身分驗證
):
    # 2. 資料脫敏
    sanitized = PrivacyShield.sanitize(request.message)

    # 3. 聚合多個後端服務
    response = await openclaw_client.chat(sanitized, user_id=user.id)

    # 4. 判斷是否需要 Approval
    if response.requires_action:
        approval = await approval_service.create(
            action=response.suggested_action,
            user_id=user.id,
        )
        response.approval_id = approval.id

    return response
```

### 禁止事項

```typescript
// ❌ 禁止：前端直連資料庫
const client = new Client({ connectionString: 'postgresql://...' })

// ❌ 禁止：前端直接呼叫 Ollama
const response = await fetch('http://192.168.0.188:11434/api/generate')

// ❌ 禁止：前端直接操作 K8s
const k8s = new KubeConfig()

// ✅ 正確：透過 BFF API
const response = await fetch('https://api.awoooi.wooo.work/v1/agent/chat', {
  method: 'POST',
  headers: { 'Authorization': `Bearer ${token}` },
  body: JSON.stringify({ message: '...' }),
})
```

## 理由

### 1. Zero Trust 網路隔離

| 元件 | 網路可達性 |
|------|-----------|
| Next.js (前端) | Public Internet |
| FastAPI BFF | DMZ (僅接受前端) |
| PostgreSQL | Internal Only |
| Redis | Internal Only |
| Ollama | Internal Only |
| K8s API | Internal Only |

### 2. 統一關注點

| 關注點 | 處理位置 |
|--------|---------|
| 身分驗證 | BFF Middleware |
| 權限檢查 | BFF Dependency |
| 請求限流 | BFF / Nginx |
| 資料脫敏 | BFF Privacy Shield |
| 審計日誌 | BFF Logger |

### 3. 資料聚合

```python
# 一個 API 呼叫 = 多個後端服務聚合
@router.get("/dashboard")
async def get_dashboard(user: User = Depends(require_auth)):
    # 平行取得多個資料源
    agent_status, pending_approvals, recent_alerts = await asyncio.gather(
        openclaw_client.get_status(),
        approval_service.list_pending(user.id),
        alert_service.list_recent(limit=10),
    )

    return DashboardResponse(
        agent=agent_status,
        approvals=pending_approvals,
        alerts=recent_alerts,
    )
```

## 後果

### 優點

- **Zero Trust** 真正的網路隔離
- **前端精簡** 只負責渲染 UI
- **統一治理** 所有安全策略集中管理
- **可觀測性** 單一入口易於監控

### 缺點

- **開發成本** 新功能需在 BFF 層多寫一層
- **延遲增加** 多一層網路跳躍 (~1-5ms)

### 風險

| 風險 | 緩解措施 |
|------|---------|
| BFF 成為瓶頸 | 水平擴展 + Redis 快取 |
| 開發速度下降 | OpenAPI 自動生成 Client SDK |

## 參考

- [BFF Pattern](https://samnewman.io/patterns/architectural/bff/)
- api-contract.yaml (BFF 對外契約)
- ADR-001: MCP Protocol (內部服務整合)
