Files
awoooi/docs/adr/ADR-UI-01-operator-console-architecture.md
Your Name 13e51802fe feat(awooop): Phase 0 全 ADR + Phase 1 control plane schema(含 critic 四項修正)
## Phase 0(文件層,全部 Accepted)
- ADR-106/107:AwoooP 平台架構 + 儲存策略
- ADR-111~118:Bootstrap → RLS 七項核心 ADR
- ADR-119~124:SAGA → Singleton Decomposition 六項 ADR
- ADR-UI-01~04:Operator Console 四個 UI ADR

## Phase 1(DB schema + migration)
- awooop_phase1_control_plane_2026-05-04.sql:7 張新表 + trigger + RLS
  - Step 1:三角色(platform_admin/migration BYPASSRLS,awooop_app 受 RLS)
  - Step 13:GRANT awooop_app 最小權限(7 條)
  - Step 14:RLS fail-closed,移除 __platform__ 後門
- awooop_phase1_batch1_rls_2026-05-04.sql:高流量四表三步式 ADD COLUMN
- awooop_phase1_batch1_backfill.py:SKIP LOCKED 分批回填腳本
- awooop_models.py:7 個 SQLAlchemy 2.x models

## Critic 修正(4 Critical + 3 Major)
- C-1:ADD CONSTRAINT IF NOT EXISTS → DO 塊 + pg_constraint 查詢
- C-2:__mapper_args__ 字串 list → primary_key=True on mapped_column
- C-3:__platform__ RLS 後門 → 全移除,改用 BYPASSRLS role
- C-4:awooop_app role 從未建立 → Step 1 + 7 條 GRANT
- M-1:active_pointer_guard SECURITY DEFINER(FORCE RLS 跨租戶保護)
- M-2:pg_partman create_parent 加冪等防護
- M-3:immutability trigger 新增身份欄位保護(project_id/family/contract_id)

## Task 1.2 修補
- agent_loader.py:硬編碼 Mac 路徑 → AGENTS_DIR 環境變數
- Dockerfile:補 COPY .claude/agents/

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-04 13:37:11 +08:00

174 lines
6.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# ADR-UI-01: Operator Console Architecture
**狀態**Accepted
**日期**2026-05-03台北
**決策者**:統帥
**範圍**AwoooP Operator Console 前端整體架構、與現有 apps/web/ 的整合方式
**關聯**ADR-106六合約、ADR-112contract governance、ADR-115principal mapping
---
## 背景
AwoooP 需要一個 Operator Console管理員後台讓平台管理員可以
1. 管理 tenantproject和 principal 角色
2. 查看和管理 contract revisions六合約的 draft/publish/activate
3. 監控 runsrun state, saga steps, budget usage
4. 執行 approval decisionshuman approval for WAITING_APPROVAL runs
現有 `apps/web/` 是 Next.js 14 前端,已有 AI 監控 dashboard。Operator Console 需要在不破壞現有功能的情況下整合。
---
## 決策
### D1 — 整合方式:子路由擴展(不建新應用)
Operator Console 作為 `apps/web/` 的新路由段:
```
apps/web/src/app/
├── (existing)/ ← 現有頁面(不動)
│ ├── dashboard/
│ ├── incidents/
│ └── ...
└── awooop/ ← 新增 Operator Console
├── layout.tsx ← Console layoutsidebar + auth gate
├── tenants/ ← Tenant 管理
│ ├── page.tsx
│ └── [project_id]/
│ ├── page.tsx
│ └── principals/
├── contracts/ ← Contract governance
│ ├── page.tsx
│ └── [contract_id]/
│ ├── page.tsx
│ └── revisions/
├── runs/ ← Run 監控
│ ├── page.tsx
│ └── [run_id]/
│ └── page.tsx
└── approvals/ ← Approval decisions
├── page.tsx
└── [run_id]/
└── page.tsx
```
### D2 — Auth GateOperator Console 專屬)
Operator Console 需要 `platform_subject.roles` 中包含 `admin``approver`
```typescript
// apps/web/src/app/awooop/layout.tsx
import { redirect } from "next/navigation"
import { getServerSession } from "@/lib/auth"
import { hasOperatorRole } from "@/lib/awooop-auth"
export default async function AwoooPLayout({ children }) {
const session = await getServerSession()
if (!session || !hasOperatorRole(session.user)) {
redirect("/unauthorized")
}
return (
<div className="awooop-operator-layout">
<AwoooPSidebar />
<main>{children}</main>
</div>
)
}
```
### D3 — API Client 分層
```
apps/web/src/lib/
├── awooop/
│ ├── client.ts ← AwoooP Platform API client/v1/platform/...
│ ├── types.ts ← TypeScript types從 API spec 生成)
│ ├── runs.ts ← Run 相關 API calls
│ ├── contracts.ts ← Contract 相關 API calls
│ ├── tenants.ts ← Tenant 相關 API calls
│ └── approvals.ts ← Approval 相關 API calls
```
**API base URL**
```typescript
// 從環境變數讀取(禁止 hardcode 內網 IPfeedback_frontend_internal_ip_ban
const AWOOOP_API_BASE = process.env.NEXT_PUBLIC_AWOOOP_API_URL
// K8s ConfigMap 設置NEXT_PUBLIC_AWOOOP_API_URL=https://api.awoooi.com
```
### D4 — 8 個 UI 模組Phase 5 實作)
| 模組 | 路由 | 功能 | ADR 關聯 |
|------|------|------|---------|
| M1 Tenant List | `/awooop/tenants` | 列出所有 project建立/停用 | ADR-115 |
| M2 Principal Manager | `/awooop/tenants/[id]/principals` | 角色管理auto-provision 確認 | ADR-115 |
| M3 Contract Dashboard | `/awooop/contracts` | 六合約總覽active revision 狀態 | ADR-106 |
| M4 Contract Editor | `/awooop/contracts/[id]/revisions` | draft/publish/activate 操作 | ADR-112 |
| M5 Run Monitor | `/awooop/runs` | 所有 run 的即時狀態 | ADR-114 |
| M6 Run Detail | `/awooop/runs/[run_id]` | saga_steps, budget, trace_id | ADR-119 |
| M7 Approval Queue | `/awooop/approvals` | WAITING_APPROVAL run 列表 | ADR-114 |
| M8 Approval Decision | `/awooop/approvals/[run_id]` | approve/reject + token 生成 | ADR-116 |
**各模組的詳細設計在 ADR-UI-02 / ADR-UI-03 / ADR-UI-04。**
### D5 — 設計原則
1. **禁止 emoji使用 Lucide icon**feedback_no_emoji_use_icons
2. **全站統一字體/顏色**feedback_design_system_consistency
3. **100% next-intl i18n**feedback_i18n_zero_hardcode— 所有文字走翻譯 key
4. **禁止內網 IP**feedback_frontend_internal_ip_ban— NEXT_PUBLIC_* 只用公網域名
5. **Logo SVG 與正式環境一致**feedback_brand_logo_consistency
### D6 — 即時更新WebSocket / SSE
Run MonitorM5和 Approval QueueM7需要即時更新
```typescript
// Server-Sent Events比 WebSocket 更簡單,適合單向推送)
// GET /v1/platform/runs/stream?project_id=awoooi&status=RUNNING,WAITING_APPROVAL
const eventSource = new EventSource(
`/v1/platform/runs/stream?project_id=${projectId}`
)
eventSource.onmessage = (event) => {
const update = JSON.parse(event.data) as RunStateUpdate
updateRunInCache(update)
}
```
---
## 後果
### Benefits
- 複用現有 apps/web/ 的 auth、i18n、設計系統不重造輪子
- 子路由設計:現有功能不受影響,可獨立部署 Operator Console 路由
- Phase 5 前,`/awooop/*` 路由可以用 feature flag 隱藏9 個 feature flag 中的 `ENABLE_OPERATOR_CONSOLE`
### Costs
- 需要在 apps/web/ 建立 `awooop/` 目錄結構(~15 個新檔案)
- API client 需要 TypeScript type generation從 OpenAPI spec
### Risks
- Operator Console 的 auth gate 若有漏洞 → 非管理員可存取敏感操作
- 緩解auth gate 在 layout.tsx 實作server-side不依賴 client-side 隱藏
---
## 驗收標準
- [ ] `/awooop` 路由在 `apps/web/src/app/` 建立Phase 5
- [ ] auth gate非 admin/approver → redirect `/unauthorized`(整合測試)
- [ ] `NEXT_PUBLIC_AWOOOP_API_URL` 不含內網 IPCI lint check
- [ ] 8 個模組全部有對應路由Phase 5 完成)
## 關聯
- ADR-106六合約Contract Dashboard M3/M4 的資料來源)
- ADR-112contract governance APIM4 的操作路徑)
- ADR-114run stateM5 M6 的資料來源)
- ADR-115principal mappingM1 M2
- ADR-116approval tokenM8 核心功能)