從 edge-ai-platform POC 轉為正式產品的雲端後端,含以下整合階段:
- Phase 0:雛形骨架 — `cmd/api-server` (REST :3721) + `cmd/remote-proxy`
(tunnel :3800 / internal :3801) 雙 binary 共用 internal/,沿用 POC 的
WebSocket+yamux tunnel 協定但解耦 relay 與 API
- Phase 0.6:OIDC BFF 接 Innovedus Member Center
- internal/oidc package(coreos/go-oidc + PKCE S256 + state + nonce)
- internal/usersession package(HMAC-SHA256 cookie + RotateSessionID
防 session fixation, OWASP ASVS V3.2.1)
- 4 個 OIDC handler(/api/auth/login|callback|me|logout)+ AuthMiddleware
- 完全拔除 StaticAuthProvider,OIDC 是唯一認證路徑
- 9 個 ADR(含 ADR-010 BFF / ADR-011 取代 static auth /
ADR-012 pending session shared cookie / ADR-013 PKCE-only public client)
- Phase 0.7:A1 改造 + security audit 修復
- OIDC ClientSecret 變選填,支援 stage MC 的 public PKCE-only client
(AuthStyleInParams 強制 token endpoint 不送 client_secret)
- 預留 ServiceClient* 欄位給未來 client_credentials grant
- 移除 13+ 處 resolveUserID(uc, StaticUserID) fallback 改 strict mode
(Audit C1:multi-tenant 隔離破口)
- Pairing exchange MarkUsed 失敗 abort + revoke session token(Audit M3)
- 新增 all_endpoints_require_auth_test 整合測試(51 endpoint × 401)
驗證:go test -race -count=3 ./... 17 packages 全綠 / go vet 0 warning
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
93 lines
3.2 KiB
YAML
93 lines
3.2 KiB
YAML
# visionA-backend docker-compose
|
||
#
|
||
# 對應:.autoflow/04-architecture/build-deploy.md §4
|
||
#
|
||
# 服務拓撲(Phase 0 雛形):
|
||
#
|
||
# browser ──(3721)──▶ api-server ──(internal:3801)──▶ remote-proxy
|
||
# ▲
|
||
# │
|
||
# local agent ──(WS:3800)──┘
|
||
#
|
||
# - api-server 無狀態;session state 全在 remote-proxy in-memory
|
||
# - 兩個 service 用 compose 的 default bridge network(service 名稱互通)
|
||
# 因此 api-server 用 `http://remote-proxy:3801` 打 internal API
|
||
#
|
||
# 使用:
|
||
# cd visionA-backend
|
||
# cp .env.example .env # 首次
|
||
# docker compose -f docker/docker-compose.yml up -d
|
||
# docker compose -f docker/docker-compose.yml logs -f
|
||
# docker compose -f docker/docker-compose.yml down
|
||
|
||
services:
|
||
api-server:
|
||
build:
|
||
context: ..
|
||
dockerfile: docker/Dockerfile.api-server
|
||
image: visiona/api-server:dev
|
||
container_name: visiona-api-server
|
||
restart: unless-stopped
|
||
ports:
|
||
# 對外暴露給瀏覽器 / curl
|
||
- "${VISIONA_API_PORT:-3721}:3721"
|
||
env_file:
|
||
- ../.env
|
||
environment:
|
||
# 容器內固定值(不要讓 .env 的 host-specific URL 汙染到容器)
|
||
# .env 裡的 VISIONA_PROXY_INTERNAL_URL 可被這裡覆蓋,改指向 compose service name
|
||
VISIONA_HOST: "0.0.0.0"
|
||
VISIONA_API_PORT: "3721"
|
||
VISIONA_PROXY_INTERNAL_URL: "http://remote-proxy:3801"
|
||
# api-server 的 storage BaseURL — 注意:生產會是 https://api.example.com/storage,
|
||
# 雛形 demo 直接用 host 的 API port(LocalFS presigned URL 從瀏覽器打回來)
|
||
VISIONA_STORAGE_LOCALFS_BASE_URL: "${VISIONA_STORAGE_BASE_URL:-http://localhost:3721/storage}"
|
||
volumes:
|
||
# 模型檔持久化 — 避免 container 重建時上傳過的模型消失
|
||
- ./data/storage:/app/data/storage
|
||
depends_on:
|
||
remote-proxy:
|
||
condition: service_healthy
|
||
networks:
|
||
- visiona-net
|
||
healthcheck:
|
||
# 覆蓋 Dockerfile 裡的預設(放寬 start_period 給冷啟動用)
|
||
test: ["CMD", "curl", "-fsS", "http://localhost:3721/healthz"]
|
||
interval: 30s
|
||
timeout: 3s
|
||
start_period: 10s
|
||
retries: 3
|
||
|
||
remote-proxy:
|
||
build:
|
||
context: ..
|
||
dockerfile: docker/Dockerfile.remote-proxy
|
||
image: visiona/remote-proxy:dev
|
||
container_name: visiona-remote-proxy
|
||
restart: unless-stopped
|
||
ports:
|
||
# 3800:tunnel WS,對外(local agent 要能從 host 或外部連進來)
|
||
- "${VISIONA_TUNNEL_PORT:-3800}:3800"
|
||
# 3801 internal 不對外 — 只有同 compose network 的 api-server 會打
|
||
# 若本機要 debug internal API,可臨時 uncomment 下行:
|
||
# - "${VISIONA_PROXY_INTERNAL_PORT:-3801}:3801"
|
||
env_file:
|
||
- ../.env
|
||
environment:
|
||
VISIONA_HOST: "0.0.0.0"
|
||
VISIONA_TUNNEL_PORT: "3800"
|
||
VISIONA_PROXY_INTERNAL_PORT: "3801"
|
||
networks:
|
||
- visiona-net
|
||
healthcheck:
|
||
test: ["CMD", "curl", "-fsS", "http://localhost:3800/healthz"]
|
||
interval: 30s
|
||
timeout: 3s
|
||
start_period: 10s
|
||
retries: 3
|
||
|
||
networks:
|
||
visiona-net:
|
||
driver: bridge
|
||
name: visiona-net
|