依 autoflow-agent workspace v2 設計把 PRD / 設計 / 架構 / 交付類 共享文件從個人層 .autoflow/(ignored)搬到 docs/autoflow/(進 git), 讓團隊可共享產品與架構文件,個人層只留 progress / review / testing 等 per-branch 筆記。 - 02-prd/ 21 個檔(PRD、features、market-analysis 等) - 03-design/ 18 個檔(design-spec、wireframes、flows 等) - 04-architecture/ 31 個檔(TDD、design-doc、ADR×14、API 規格等) - 07-delivery/ 3 個檔(project-summary、phase-0.6-handover、stage-deployment-setup) 合計 73 檔。原檔已從 .autoflow/ 移除(migration 工具執行 git mv, 但因 .autoflow/ 在 .gitignore 中、git 將此操作視為新增、無 rename history)。
25 KiB
Design Doc — visionA Cloud
Metadata
- 作者:Architect Agent
- 狀態:Draft(待三方交叉審閱)
- 最後更新:2026-04-21
- 範圍:visionA-frontend + visionA-backend 的雲端版架構;定位為「POC 升格為產品」的雛形骨架
- 相關文件:
- 健檢:
.autoflow/00-onboarding/health-check.md - PRD:
.autoflow/02-prd/PRD.md(PM 主導,平行產出中) - 設計規格:
.autoflow/03-design/(Design 主導,平行產出中) - TDD:
.autoflow/04-architecture/TDD.md(本文檔的姊妹檔,實作細節) - ADRs:
.autoflow/04-architecture/adr/adr-*.md
- 健檢:
1. 系統總覽(High-Level Overview)
visionA Cloud 把「使用者的 Kneron 裝置」透過雲端反向代理提供給瀏覽器操作。核心流向:
┌────────────────────────────────────────────────────────────────────────┐
│ 使用者瀏覽器 │
│ visionA-frontend (Next.js) │
└─────────────────┬────────────────────────────┬────────────────────────┘
│ HTTPS REST │ WSS (訂閱)
│ │
┌─────────────────▼────────────────┐ ┌─────────▼──────────────────────┐
│ visionA-backend / api-server │ │ visionA-backend / api-server │
│ (無狀態, 水平擴展) │ │ (WebSocket 訂閱, 同 binary) │
└─────────────────┬────────────────┘ └─────────┬──────────────────────┘
│ Session 查詢(in-mem 同進程 / Redis 跨進程) │
▼ ▼
┌────────────────────────────────────────────────────────────────────────┐
│ 共享 Session Store(routing table) │
│ 雛形:in-memory(單進程) / Phase 1:Redis │
└─────────────────────────────┬──────────────────────────────────────────┘
│ 查到該 token 的 tunnel 在哪個 proxy 節點
▼
┌────────────────────────────────────────────────────────────────────────┐
│ visionA-backend / remote-proxy (有狀態) │
│ 持有 yamux.Session map[token]→Session │
└────────────────────────────┬───────────────────────────────────────────┘
│ WebSocket + yamux(長連線)
▼
┌────────────────────────────────────────────────────────────────────────┐
│ 使用者電腦 local agent │
│ (local-tool 或 tunnel-only client;連 remote-proxy 出站) │
│ 本機 HTTP server :3721 │
└────────────────────────────┬───────────────────────────────────────────┘
│ USB
▼
┌──────────────────┐
│ Kneron 裝置 │
│ KL520 / KL720 │
└──────────────────┘
外部依賴(均透過介面,雛形 stub):
├─ kneron_model_converter (`/api/converter/*` stub, TODO)
├─ S3-compatible 物件儲存 (LocalFSStore for prototype)
└─ PostgreSQL + Auth provider (in-memory for prototype, ADR-005)
關鍵概念:
- Session key = pairing token,一個 token 對應一個 yamux tunnel。
- API Server 把收到的請求,查 session store 找到對應 token 的 tunnel,轉發到該 tunnel 上的 remote-proxy 節點,由 proxy 打 yamux stream 送進 local agent,拿到 response 再回傳瀏覽器。
- WebSocket 訂閱同理:api-server 升級 WS 後,在 session store 裡找到 tunnel,把 WS 幀透過 yamux stream 送給 local agent 的
/ws/*。
1.9 Non-Goals(雛形明確不做的事,2026-04-22 M-8)
以下項目在 Phase 0 雛形階段刻意不支援,列出以避免誤解:
| # | Non-Goal | 原因 | 對應 Phase |
|---|---|---|---|
| N1 | 多 instance 部署 — 雛形僅支援單一 api-server instance + 單一 remote-proxy instance |
無共享 state 機制(無 Redis、無 DB session metadata);開兩個 api-server 會因為 session lookup 散到不同節點而壞掉;開兩個 remote-proxy 會讓 tunnel 註冊到 A 節點、但 api-server 的 ProxyClientStore 配置只連 B,查無 session |
Phase 1 |
| N2 | 真實使用者註冊 / 登入 — StaticAuthProvider 無論帳密都回 demo-user |
Auth 不是 POC → 產品驗證的核心風險;整合 Clerk / 自建 OIDC 需 2-4 週,放 Phase 1 | Phase 1 |
| N3 | 真實 DB 持久化 — 所有 repository 走 in-memory map | ADR-005 明定;Phase 1 實作 Postgres*Repository |
Phase 1 |
| N4 | 真實 Converter 整合 — /api/converter/* 走 Stub |
Converter 團隊 API 規格未定;見 api/api-converter-contract.md |
Phase 1 |
| N5 | Pairing Token 兩階段升級 — 雛形 Pairing 與 Session 合併為單一 token | 單 token 比對流程足以驗證 tunnel;兩階段 DB transaction 需 Postgres | Phase 1(必須在公開 release 前完成) |
| N6 | HTTPS / WSS — 雛形走明文 HTTP / WS | TLS termination 由 Phase 1 LB / reverse proxy 處理 | Phase 1 |
| N7 | Rate limiting / Audit log — 雛形無 | 雛形只跑 dev / 內測 | Phase 1 |
| N8 | Observability(metrics / trace / alert) — 雛形只有 stdout log | 雛形不追求 SLO | Phase 1 |
| N9 | Local agent 自己的 binary(visionA/local-agent/) — 雛形用 POC edge-ai-server 當 tunnel client 暫代 |
讓雛形專注在 backend 協定正確性;Phase 1 從 local-tool 複製起步 | Phase 1 |
| N10 | cmd/dev-all-in-one 單進程合併模式 |
會讓部署拓撲與 Production 不一致,反而掩蓋 bug | 永不做 |
重要後果:
- 開第二個
api-server(例如為了測試無狀態性)會因ProxyClientStore只配一個VISIONA_PROXY_INTERNAL_URL,導致兩個 api-server 都指向同一個 remote-proxy,這可以運作(真實多 instance 場景)。但開兩個remote-proxy會壞 — tunnel 連上的是 A,但 api-server 可能查到 B(視 LB 分配),B 沒有 session 就回 404。 - 雛形的部署指引明確:恰好 1 個 api-server + 恰好 1 個 remote-proxy。
- Phase 1 解多
remote-proxy節點時會補 session metadata 共享機制(見tunnel.md§5.4 + 待產出的新 ADR)。
2. 系統邊界與組件
2.1 visionA-frontend(客戶端)
| 屬性 | 值 |
|---|---|
| 技術 | Next.js 16 App Router + React 19 + TypeScript + Tailwind 4 + Radix + Zustand 5 + Lucide + Recharts + driver.js |
| 部署 | 靜態打包 + CDN(雛形用 Next.js 本地 dev server;Phase 1 上 Vercel / Cloudflare Pages / S3+CloudFront) |
| 狀態 | 無(純前端,所有資料 via API) |
| Auth | JWT / session cookie(雛形 stub;Phase 1 真實) |
| 連線對象 | 只連 visionA-backend/api-server,不直連 remote-proxy 或 local agent |
從 local-tool 搬來的內容:所有頁面、components、stores、i18n、UI styling;改 API base URL,移除 localhost hardcode。
新增:
/login、/register(雛形骨架,Auth stub)/account(雛形骨架)/devices/pair(輸入 / 產生 pairing token)/clusters(從 POC 搬)
2.2 visionA-backend / api-server(cmd/api-server)
| 屬性 | 值 |
|---|---|
| Binary | cmd/api-server/main.go |
| 狀態 | 無狀態(所有狀態在 DB / session store / 物件儲存) |
| 水平擴展 | ✅ 多實例 + 前置 L7 load balancer |
| 對外 | HTTP :3001(雛形預設);正式上 443 |
| 職責 | REST API、WebSocket 升級、Auth、權限、把請求 proxy 到 remote-proxy、Storage presigned URL、Converter 呼叫 |
2.3 visionA-backend / remote-proxy(cmd/remote-proxy)
| 屬性 | 值 |
|---|---|
| Binary | cmd/remote-proxy/main.go |
| 狀態 | 有狀態(持有 yamux.Session) |
| 水平擴展 | 可多實例;session 路由交給 session store |
| 對外(local agent) | WS :3800(POC 預設) |
| 對內(api-server) | HTTP :3801(內部 API,不對外) |
| 職責 | 接受 local agent 的 tunnel 連線、維護 yamux session、轉發 api-server 送來的請求 |
2.4 共享狀態:Session Store(2026-04-22 Q1 裁決 C + ADR-006:雛形即雙 binary,無 Redis)
| 雛形實作 | Phase 1 實作 |
|---|---|
| Session state 完全由 remote-proxy 持有(in-memory);api-server 無狀態,透過 internal HTTP 向 remote-proxy 查詢 | 多 remote-proxy 節點間的 metadata 共享機制待 Phase 1 評估(Redis / gossip / sticky LB 等 — 不預設採用 Redis) |
雛形設計:
cmd/remote-proxy:唯一持有*yamux.Session的 process;以InMemoryStore儲存cmd/api-server:無狀態;internal/session載入ProxyClientStore(internal HTTP client)- 兩 binary 透過
internal/forward/*和internal/session/*endpoints 溝通(詳見api/api-internal.md)
Non-Goal(刻意不做):
- 不做
cmd/dev-all-in-one單進程合併模式 — 會讓部署拓撲與 Production 不一致,反而讓 bug 在雛形階段無法暴露 - 不引入 Redis — POC 從未用過(見 ADR-006)
詳細見 TDD §2 與 tunnel.md §5。
2.5 local agent(使用者電腦)
三種形態:
- local-tool(桌面版 Wails 應用):原本離線用,加一個 config 選項「啟用雲端模式」後,額外啟動 tunnel client 連 remote-proxy。local-tool 本身不動;雲端模式是新增 opt-in 模組,不影響離線使用。
- tunnel-only client(未來):專為「headless / server 使用者」提供的輕量 Go binary,只跑 tunnel client + 最小 HTTP server,不含 Wails / UI。雛形不做。
- 既有 edge-ai-platform:POC 的 tunnel client 可直接繼續用來做技術驗證。
2.6 外部依賴
| 依賴 | 雛形 | Phase 1 |
|---|---|---|
kneron_model_converter |
Stub:/api/converter/* 回假資料 |
真實打 converter API |
| 物件儲存 | LocalFSStore(本地檔案) |
S3Store(AWS S3 / Cloudflare R2 / MinIO) |
| 資料庫 | in-memory repositories | PostgreSQL |
| Auth | StaticAuthService(永遠 demo-user) |
真實 Auth |
| Observability | stdout log | Prometheus + Loki + OpenTelemetry |
3. 12-Factor 合規策略
| # | Factor | 雛形做法 | Phase 1 做法 |
|---|---|---|---|
| 1 | Codebase | ✅ Monorepo (visionA/visionA-frontend + visionA/visionA-backend) |
同 |
| 2 | Dependencies | ✅ go.mod + package.json 明確宣告;無系統隱式依賴 |
同 |
| 3 | Config | ✅ 全走 env vars(VISIONA_* prefix);internal/config 讀取 |
同 + 密鑰用 Secrets Manager |
| 4 | Backing services | ✅ Storage / DB / Auth 全走 interface | 同(實作 swap) |
| 5 | Build / Release / Run | ⚠️ 雛形只有 make build + docker-compose |
Build:CI 產出 image;Release:tag + manifest;Run:K8s / ECS deploy |
| 6 | Processes | ✅ api-server 無狀態;state 全走 Store interface | 同 |
| 7 | Port binding | ✅ api-server :3001,remote-proxy 對 agent :3800,對 api :3801 |
同(port 由 env 指定) |
| 8 | Concurrency | ✅ 單進程多 goroutine;跨進程靠 SessionStore | 多實例 + auto-scale |
| 9 | Disposability | ⚠️ 雛形 SIGTERM graceful shutdown;tunnel 斷線有重連 | 同 + drain period |
| 10 | Dev/Prod Parity | ✅ Docker 一致化 | 同 |
| 11 | Logs | ⚠️ 雛形 stdout(已有 broadcaster WebSocket 看 log) | 結構化 JSON log + 集中收集 |
| 12 | Admin processes | ⚠️ 雛形手動 | 後台 CLI / admin API |
雛形妥協:log 未結構化、缺 metrics、缺 trace。記錄為 TODO,不影響功能驗證。
4. 水平擴展策略
4.1 api-server(無狀態)
- 多實例,前置 L7 load balancer(ALB / nginx / Cloud Run 自動)
- Sticky session 不需要(無狀態)
- 擴展訊號:CPU > 60% 或 p95 延遲 > 300ms
4.2 remote-proxy(有狀態)
remote-proxy 的狀態是 map[token]*yamux.Session。擴展的挑戰:
- Local agent 連 proxy 時,會連到某一個具體節點(由 LB 分派,例:ALB + IP hash 或 DNS round-robin)
- 後續 api-server 要送請求到該 token 的 tunnel 時,需要知道這條 tunnel 在哪個 proxy 節點
解決方案:Session Store 記錄 routing table
Session Store 儲存(Redis Hash):
session:{token} = {
proxy_node_id: "proxy-2",
proxy_internal_url: "http://proxy-2.internal:3801",
connected_at: "...",
last_seen: "..."
}
api-server 送請求的流程:
1. 收到 API 請求(例:GET /api/devices + X-Pairing-Token: xxx)
2. 查 Session Store:token → proxy_internal_url
3. 呼叫該 proxy 的 internal endpoint:POST http://proxy-2.internal:3801/forward
- body = 原請求(method, path, headers, body)
4. proxy-2 收到後,從自己 in-memory map 取 yamux.Session
5. 開 stream,傳 HTTP request
6. 等 response → 回給 api-server → 回給瀏覽器
4.3 雛形簡化(單節點)
雛形期 api-server 與 remote-proxy 同進程,SessionStore 就是本機 map,跳過跨節點轉發:
1. 查 SessionStore(local map)取 yamux.Session
2. 直接開 stream 送請求
Phase 1 時把 SessionStore 換 Redis、引入「proxy internal HTTP API」,不改 API handler 程式碼。
4.4 擴展邊界
| 資源 | 估算 |
|---|---|
| remote-proxy 單節點 tunnel 數上限 | ~10K(受檔案描述符 / 記憶體限制,每個 tunnel ~100KB) |
| api-server 單節點 QPS | ~5K(Gin + Go 典型值) |
| Session Store(Redis)單節點 QPS | ~100K |
雛形單節點即可撐 demo / 早期內測。Phase 1 再引入多節點。
5. 資料流
5.1 前端呼叫 REST API(最常見情境)
[瀏覽器] GET /api/devices
↓ HTTPS + Cookie/JWT
[api-server] authMiddleware 驗 user
↓ 從 user 找對應 pairing token(雛形 env 寫死;Phase 1 查 DB)
[api-server] 查 SessionStore(token) 取 proxy location
↓
(單節點雛形:直接拿到 yamux.Session)
(多節點:轉發 http://proxy-X.internal:3801/forward)
↓
[remote-proxy] 從 session open yamux stream
↓ 把 HTTP request 寫進 stream(沿用 POC 方法)
[local agent] tunnel client accept stream
↓ 轉發到本機 127.0.0.1:3721
[local HTTP server] 處理 /api/devices → 回 response
↓ 經 yamux stream 回到 remote-proxy
↓ remote-proxy 回 api-server
↓ api-server 回瀏覽器
[瀏覽器] 得到裝置列表
5.2 前端開 WebSocket 訂閱(例:裝置事件串流)
[瀏覽器] WS /ws/devices/events (connect)
↓
[api-server] authMiddleware → 升級 WS
↓ 查 SessionStore → 取 yamux session
↓ 開 stream,把 HTTP upgrade request 寫進 stream(沿用 POC proxyWebSocket 邏輯)
[local agent] handleStream 偵測 upgrade → 連本機 raw TCP → 雙向 copy
[local HTTP server] /ws/devices/events 升級 → 開始推事件
↓ 事件 frame → yamux stream → api-server → 瀏覽器
POC 已完整實作此流程,visionA 直接沿用。
5.3 模型上傳(不走 tunnel)
[瀏覽器] 點「上傳模型」
↓
[api-server] POST /api/models/upload-url
↓ 呼叫 Storage.PresignedPutURL → 回給瀏覽器
[瀏覽器] 直接 PUT 檔案到 S3 / LocalFS(不走 tunnel,省 tunnel 頻寬)
↓ 上傳完成後
[瀏覽器] POST /api/models/register (告知 api-server 上傳完成 + metadata)
↓
[api-server] 寫入 model repository
為何不走 tunnel?
- 模型檔可達百 MB,走 tunnel = 占用使用者本地頻寬兩次(上傳 → 雲端 → 下載)
- S3 presigned URL 讓瀏覽器直連,scalable
- 需要時 api-server 再叫 local agent「下載這個 model 的 URL」,由 local agent 用自己網路下載
5.4 轉檔呼叫(Phase 1)
[瀏覽器] POST /api/converter/convert {source_url, target_chip: "kl520"}
↓
[api-server] 驗 user → 呼叫 kneron_model_converter API
↓ (非同步)取得 job_id
[api-server] 回 job_id
↓ 輪詢 /api/converter/jobs/{id} 或 WS 訂閱進度
雛形 api-server 提供端點,但回 stub(job_id 假的,狀態永遠 queued)。
6. 安全架構
6.1 通訊加密
- 瀏覽器 ↔ api-server:HTTPS(Phase 1);雛形開發用 HTTP
- api-server ↔ remote-proxy 內部:雛形同進程無需加密;多節點 Phase 1 考慮 mTLS 或 VPC-only
- local agent ↔ remote-proxy:WSS(Phase 1);雛形 WS。TLS 由前端反代(ALB / nginx)終止
6.2 認證 / 授權
| 物件 | 雛形 | Phase 1 |
|---|---|---|
| 使用者登入 | StaticAuthService 永遠過 |
OIDC / SAML / 自建 |
| 前端 call API | 無 token 也接受(stub) | JWT / session cookie |
| local agent 連 proxy | VISIONA_PAIRING_TOKEN env 寫死 |
DB-backed Pairing Token(見 ADR-003) |
| API handler 授權 | 一律通過 | RBAC:user 只能看自己的 device |
6.3 CORS / CSRF
- CORS:api-server 雛形設
Access-Control-Allow-Origin: *(dev);Phase 1 白名單 - CSRF:用 JWT in header(非 cookie)可天然免疫;若用 session cookie 則需 CSRF token
- WebSocket Origin:本 repo 的
local-tool/server/internal/api/ws/origin.go已有成熟 allowlist,搬過來用
6.4 Pairing Token 安全
詳見 ADR-003。重點:
- 雛形:env 寫死
- Phase 1:DB 存
sha256(token),不存明文;15min expiry;可 revoke;綁 user_id + device_id
6.5 輸入驗證
- 模型檔案格式驗證(雛形僅 extension;Phase 1 加 magic bytes + file size limit)
- API body schema 驗證(用 struct tags
binding:"required"或go-playground/validator)
6.6 STRIDE 分析(重點項目)
| 威脅 | 防護 | 雛形 / Phase 1 |
|---|---|---|
| 偽冒(Spoofing):他人冒用 token | sha256(token) 存 DB + rate limit;雛形 env 隔離 |
Phase 1 必做 |
| 竄改(Tampering):中間人改 request | TLS | Phase 1 |
| 否認(Repudiation) | Audit log | Phase 1 |
| 資訊洩露(Information Disclosure) | TLS + least privilege log | Phase 1 |
| DoS | rate limit on /tunnel/connect + API |
Phase 1 |
| 提權(EoP) | RBAC | Phase 1 |
雛形期驗證技術,不預期公開部署,以上多數 Phase 1 才補全。
7. 部署架構
7.1 雛形(開發 / 內測)
方案 A:本機一鍵啟動
docker-compose up
docker-compose.yml:
services:
api-server:
build: { context: ., dockerfile: docker/Dockerfile.api-server }
ports: ["3001:3001"]
environment:
VISIONA_SESSION_BACKEND: inmemory
VISIONA_STORAGE_BACKEND: localfs
VISIONA_AUTH_MODE: static
VISIONA_PAIRING_TOKEN: dev-token-abc123
volumes: ["./data:/data"]
remote-proxy:
build: { context: ., dockerfile: docker/Dockerfile.remote-proxy }
ports: ["3800:3800", "3801:3801"]
environment:
VISIONA_SESSION_BACKEND: inmemory
VISIONA_PAIRING_TOKEN: vAc_<32 hex> # 格式見 security.md §1.3
frontend:
build: { context: visionA-frontend }
ports: ["3000:3000"]
environment:
NEXT_PUBLIC_API_BASE: http://localhost:3001
雛形交付物(Phase 0):上述雙 binary + docker-compose 即完整雛形。不提供 cmd/dev-all-in-one(見 §2.4 Non-Goal)。
7.2 Phase 1(正式部署,草圖)
┌──────────┐
│ CDN │ (Cloudflare / CloudFront)
└────┬─────┘
│ static frontend
┌───────────────┴────────────────┐
│ │
┌────▼─────┐ ┌──────▼────┐
│ ALB │ │ NLB │ (for WebSocket, TCP pass-through)
└────┬─────┘ └──────┬────┘
│ HTTPS /api/*, /ws/* │ WSS /tunnel/connect
│ │
┌────▼───────────────┐ ┌────▼──────────────────┐
│ api-server cluster │◄──────────►│ remote-proxy cluster │
│ (K8s / ECS) │ Redis │ (K8s / ECS, StatefulSet│
│ stateless, N pods │ Session │ or DaemonSet) │
└────┬───────────────┘ Store └────┬──────────────────┘
│ │
├─► PostgreSQL (RDS) │
├─► S3 / R2 (object store) │
└─► Converter API │
│ WSS + yamux
▼
使用者電腦 local agent
Cloud-agnostic:所有組件(Redis、PG、S3)都有對應的 interface;可用 AWS / GCP / 自建。
7.3 CI/CD(雛形目標)
make build→ 兩個 binarymake docker-build→ 兩個 imagemake docker-compose-up→ 本機跑起來- GitHub Actions / GitLab CI(Phase 1)→ 自動 build + push registry + deploy
8. 觀測(Observability)
8.1 雛形
| 項目 | 做法 |
|---|---|
| Log | stdout;沿用 local-tool 的 log broadcaster(WS 看 log) |
| Metrics | 無;/api/system/health 回 ok 即可 |
| Trace | 無 |
| Alert | 無 |
8.2 Phase 1(TODO)
| 項目 | 做法 |
|---|---|
| Log | 結構化 JSON → Loki / CloudWatch Logs |
| Metrics | Prometheus export:qps, p95_latency, tunnel_count, session_active_count |
| Trace | OpenTelemetry SDK → Tempo / X-Ray |
| SLO | API 可用性 99.9%,p95 < 500ms;Tunnel 連線穩定度 99%(7 天滾動) |
| Alert | Grafana / PagerDuty |
9. ADR 索引
| 編號 | 標題 | 狀態 |
|---|---|---|
| ADR-001 | 單一 Go 專案 / 雙 binary 結構 | Accepted |
| ADR-002 | 沿用 POC 的 Tunnel 協定(WebSocket + yamux) | Accepted |
| ADR-003 | 以 Pairing Token 取代 SHA256(MAC) Token | Accepted |
| ADR-004 | 模型儲存採用 S3-Compatible 介面 | Accepted |
| ADR-005 | 雛形階段不接真實 DB 與 Auth | Accepted |
10. 三方交叉審閱檢核清單
給 PM 審閱
- 所有 PRD 中列出的 P0 功能,是否在本 Design Doc 都有對應的技術路徑?
- 「雲端能操作使用者本地裝置」的核心價值主張是否由架構支撐?
- 雛形 vs Phase 1 的差異,PM 能否向使用者解釋「現在能做什麼、未來會做什麼」?
給 Design 審閱
- 「pairing token 輸入」頁面是否技術可行(API 已定義)?
- 模型上傳流程的 presigned URL 對 UX 是否清楚?
- tunnel 斷線時瀏覽器要怎麼顯示?(已在 §5.2 指出走 POC 同機制;需 Design 規劃 UI)
給 Architect 自我檢查
- 每個 ADR 都有 Context / Decision / Consequences
- 所有雛形實作都有明確的 Phase 1 替換計畫
- 擴展策略說明完整(§4)
- 安全架構覆蓋 STRIDE(§6.6)
下一步:閱讀 TDD.md(實作細節),以及各 ADR。