對齊 ADR-015:visionA backend 從 OAuth client_credentials 改 pre-shared API key 服務間認證。Phase 0.8 stage e2e 撞 4 個 blocker(MC scope 沒註冊 / converter image 舊版 / converter 缺 env / FAA 不確定)後,使用者拍板 1:1 internal trust 用 OAuth 過度設計,改 API key。
實作(5 個增量 task,T1-T5 全綠 + Reviewer 5 輪 + final cross-task review):
T1 config + env:
- ConversionConfig 新增 ConverterAPIKey / FAAAPIKey 欄位
- Enabled() 改判定 4 欄位齊全(含兩個 API key)
- .env*.example 移除 OIDC service client / OIDC tenant / FAA delegated TTL env、新增 API key env
- TenantID / DelegatedTTLSeconds T1 暫留、T5 整批清
T2 client 改造:
- converter_client / faa_client 移除 MCTokenClient 依賴
- 直接讀 cfg.Conversion.{Converter,FAA}APIKey、set Authorization: Bearer <key>
- NewConverterClient / NewFAAClient APIKey 為空時 panic(fail-fast,對齊 ADR-015 §3.5.3 #1)
- 新增 ErrConverterAuthFailed / ErrFAAAuthFailed sentinel
- 對外 mask 成 converter_unavailable / faa_unavailable(不洩漏 401 細節,對齊 ADR-015 §3.5.3 #3)
T3 砍 mc_token_client:
- mc_token_client.go (624 行) + mc_token_client_test.go (864 行) 整檔砍
- 砍 5 個僅 mc_token_client 用的 sentinel(ErrServiceClientUnauthorized / ErrMCTokenUnavailable / ErrIDPMisconfigured / ErrIDPUnavailable / ErrDownloadTokenFailed)
- helper(truncate / silentLogger)搬到 util.go / testing_helpers_test.go
T4 flow + handler stream proxy:
- Service interface DownloadRedirectURL → DownloadStream(ctx) (io.ReadCloser, *DownloadMetadata, error)
- flow.DownloadStream 用 faa.GetFile 直接 stream NEF binary(取代 MC delegated token + 302)
- handler conversionDownloadHandler 改 io.Copy + Content-Type/Disposition/Cache-Control header
- 新增 sanitizeDownloadFilename helper 防 HTTP header injection
- 跨 package handler test (conversion_test.go) 改測 ErrFAAUnavailable + 補 *_AuthFailed 對稱 test
T5 wire 切換 + cleanup:
- main.go 砍 mcTokenClient wire、改 APIKey 注入、startup log 用 *_api_key_set boolean(不印 key)
- ConverterClient/FAAClient struct Tokens 欄位移除
- mc_token_stub.go (T4 過渡期) 整檔砍
- ConversionConfig TenantID / DelegatedTTLSeconds 欄位移除
- e2e_test.go TestConversionE2E_Download302Redirect 改寫為 TestConversionE2E_DownloadStream
- 補 MaxDownloadStreamBytes = 1 GiB size cap(io.CopyN,T4 reviewer Minor M-1)
- escapeObjectKeyPath Phase 1+ 預留 godoc + //nolint:unused(T4 reviewer Minor M-2)
- conversion.md §4.1 line 502 filename 來源描述歧義修訂(T4 reviewer Minor M-3,由 architect 處理)
- conversion_e2e_test.go 檔頭 docstring 更新(final reviewer Minor #1)
驗證:
- go build ./... exit 0
- go test -race -count=3 ./... 17 packages 全綠
- ADR-015 §6 砍除清單 100% cover(reviewer 獨立 grep 確認 MC chain / TenantID / DelegatedTTLSeconds 全清)
- ADR-015 §3.5.3 部署檢查清單 visionA 範圍 4/4 達成(fail-fast / mask / 不印 token / placeholder env)
不動:
- OIDCConfig.ServiceClientID/Secret 欄位保留(使用者拍板 backward compat)
- user login OIDC 完全不動
下一步:
- 步驟 4 — converter scheduler middleware 改 API key(jimchen 跨 repo,ADR-015 §3.5.1 Go snippet)
- 步驟 5 — FAA middleware 改 API key(warrenchen 跨 repo,ADR-015 §3.5.2 C# snippet)
- 步驟 6 — stage redeploy + e2e 完整測試
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
98 lines
4.1 KiB
Plaintext
98 lines
4.1 KiB
Plaintext
# visionA dev 環境變數範本
|
||
#
|
||
# 使用方式:
|
||
# cp .env.dev.example .env.dev
|
||
# # 編輯 .env.dev,填入 OAuth client_id / client_secret(手動 seed 後產生)
|
||
# docker compose -f docker-compose.dev.yml --env-file .env.dev up -d
|
||
#
|
||
# 詳細步驟:見 docs/DEV-SETUP.md
|
||
#
|
||
# ⚠️ 不要 commit .env.dev(已在 .gitignore 中排除)
|
||
|
||
# ============================================================
|
||
# Member Center
|
||
# ============================================================
|
||
# 預設用 ../member_center 路徑 build。如果你的 member_center 在別處,改這個。
|
||
# 例:MEMBER_CENTER_PATH=/Users/me/code/member_center
|
||
MEMBER_CENTER_PATH=../member_center
|
||
|
||
# Member Center admin 帳號(installer init 會建立)
|
||
# 之後可用這組帳密登入 MC admin UI / 拿 admin API token
|
||
MC_ADMIN_EMAIL=admin@visiona.local
|
||
MC_ADMIN_PASSWORD=Admin12345!
|
||
|
||
|
||
# ============================================================
|
||
# visionA OIDC client(必須先在 MC 註冊,詳見 docs/DEV-SETUP.md)
|
||
# ============================================================
|
||
# 第一次起來時這兩個值還沒有 → 先用 static auth 跑(VISIONA_AUTH_TYPE=static)
|
||
# OAuth client 註冊完後填入這兩個值 + 改 VISIONA_AUTH_TYPE=oidc → docker compose up -d 重啟
|
||
VISIONA_OIDC_CLIENT_ID=CHANGE_ME
|
||
VISIONA_OIDC_CLIENT_SECRET=CHANGE_ME
|
||
|
||
# Phase 0.8b 移除:VISIONA_OIDC_SERVICE_CLIENT_ID / _SECRET
|
||
# 服務間認證(visionA → converter / FAA)改 pre-shared API key(ADR-015);
|
||
# 不再走 OAuth client_credentials grant,所以 dev 也不需要 service client。
|
||
# 取代設定見下方 Phase 0.8 / 0.8b conversion 區塊。
|
||
|
||
# auth mode 切換:static(雛形預設)/ oidc(接 MC)
|
||
VISIONA_AUTH_TYPE=static
|
||
|
||
# OIDC issuer / redirect — 預設值已對齊 MC 的 dev port
|
||
# ⚠️ trailing slash 不可省(MC discovery 回的 issuer 帶 slash,否則 client init 會 reject)
|
||
VISIONA_OIDC_ISSUER_URL=http://localhost:5050/
|
||
VISIONA_OIDC_REDIRECT_URL=http://localhost:3721/api/auth/callback
|
||
|
||
|
||
# ============================================================
|
||
# Cookie / session
|
||
# ============================================================
|
||
# 至少 32 byte 隨機字串(建議:openssl rand -hex 32)
|
||
VISIONA_SESSION_SECRET=please-change-me-32-bytes-random-dev-secret
|
||
|
||
# Frontend URL(OIDC callback 完成後 redirect 回的目標)
|
||
VISIONA_FRONTEND_URL=http://localhost:3000
|
||
|
||
|
||
# ============================================================
|
||
# 既有 visionA-backend 環境變數(與 visionA-backend/.env.example 一致)
|
||
# ============================================================
|
||
VISIONA_LOG_LEVEL=info
|
||
VISIONA_API_PORT=3721
|
||
VISIONA_TUNNEL_PORT=3800
|
||
# Phase 0.7 security audit (2026-05-01) 後僅供 dev seed (VISIONA_SEED_DEMO_DATA=true) 與 unit test fixture 用;
|
||
# 已從 api.Deps 移除(見 .autoflow/05-implementation/review/phase-0.7-security-audit.md C1);
|
||
# stage / prod 不需設定。
|
||
VISIONA_STATIC_USER_ID=demo-user
|
||
|
||
VISIONA_CORS_ALLOWED_ORIGINS=http://localhost:3000
|
||
VISIONA_SEED_DEMO_DATA=true
|
||
|
||
VISIONA_STORAGE_BASE_URL=http://localhost:3721/storage
|
||
# ⚠️ 生產必改:openssl rand -hex 32
|
||
VISIONA_STORAGE_SIGNING_SECRET=dev-signing-secret-change-me-32-bytes
|
||
|
||
# Pairing token(雛形仍用 static;留空則動態配發)
|
||
VISIONA_PAIRING_TOKEN=
|
||
|
||
|
||
# ============================================================
|
||
# Phase 0.8 / 0.8b — 轉檔功能整合(dev 通常不啟用,留空即可)
|
||
# ============================================================
|
||
# 對齊 .autoflow/04-architecture/conversion.md §3 + ADR-015。
|
||
#
|
||
# 4 個欄位全部非空才會啟用 conversion 模組;dev 全空 = sidebar tab 顯示但 endpoint 不註冊。
|
||
# 若要在 dev 連 stage 的 converter / FAA 測整合,依 .env.stage.example 模板填入。
|
||
#
|
||
# 產生 API key:openssl rand -hex 32
|
||
# VISIONA_CONVERTER_BASE_URL=http://192.168.0.130:9501
|
||
# VISIONA_FAA_BASE_URL=http://192.168.0.130:5081
|
||
# VISIONA_CONVERTER_API_KEY=
|
||
# VISIONA_FAA_API_KEY=
|
||
|
||
# ============================================================
|
||
# 進階:port 衝突時可改
|
||
# ============================================================
|
||
# POSTGRES_PORT=5432
|
||
# MEMBER_CENTER_PORT=5050
|