Move PRD, design specs, architecture docs, and TDD from .autoflow/ (personal/per-branch layer) to docs/autoflow/ (shared layer that goes into git) per the new Autoflow workspace layout. Files moved: - 02-prd/PRD.md - 03-design/design-review.md - 03-design/user-flow-cross-system.md - 04-architecture/TDD.md - 04-architecture/design-doc.md - 04-architecture/security.md The originals were never tracked, so git mv reduced to a filesystem rename with no history to preserve. .autoflow/ remains for personal notes (progress.md, review reports, testing logs). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
28 KiB
Design Review — API 對外開放 L 級功能
審查範圍:2026-04-25 的 L 級新功能「開放 Kneron Model Converter 轉檔能力為對外 REST API 供 VisionA 使用」。
審查者:Design Agent(Autoflow)
審查時機:三方聯合討論階段(與 PM Agent / Architect Agent 同步作業)
特別聲明:這次任務的直接產出物是 後端 API 介面,不是新 UI 畫面。本次 Review 的焦點為:
- 對既有 Web UI 使用者體驗的間接影響
- API 設計對下游消費者(visionA-backend)能做出什麼樣的終端 UX 的限制
- 從 UX 觀點給 PM / Architect 的建議
不在本次範圍:新 UI 畫面設計、Wireframe、Prototype、Design Tokens 調整。這些本次都不需要做。
變更歷程
| 日期 | 變更內容 |
|---|---|
| 2026-04-25 | 原始模型上傳路徑改為 visionA-backend → Converter multipart 直連(不經過 File Access Agent)。同步更新:(1)錯誤情境表移除「原始模型在 FAA 找不到 input_object_not_found」,改為 multipart 相關錯誤 invalid_multipart / file_too_large;(2)相依圖中 Converter 對 FAA 的依賴只保留 promote PUT,移除讀原始模型的箭頭;(3)衝突 response 範例保持不變(不受上傳路徑影響)。 |
1. 摘要
1.1 整體評估結論
Phase 1 對既有 Web UI 使用者體驗的影響:幾乎無感(✅ 優秀)
- 既有 Web UI 走的 API 路徑(
/jobs、/jobs/:id、/jobs/:id/events、/jobs/:id/download/:filename)不改動 - 對外 API 走全新路徑
/api/v1/*,兩套並存 - 既有 Web UI 使用者繼續以 multipart 上傳、SSE 追蹤、GET 下載,流程零改動
主要 UX 風險:集中在「我們給 visionA 前端團隊的操作彈性」上(⚠️ 要注意)
我們不實作 VisionA 的 UI,但 我們的 API 設計會限制他們能做出什麼樣的體驗。如果 API 設計得太死板,visionA 前端團隊就算想做更好的 UX 也做不到。本次 Review 會針對這點給 Architect 一份「API 設計的 UX 彈性需求」清單。
1.2 Phase 1 vs Phase 2 對使用者體驗的差異
| 情境 | Phase 1 體驗 | Phase 2 體驗 | UX 差距 |
|---|---|---|---|
| VisionA 使用者上傳模型並轉檔 | ✅ 在 VisionA 平台內完成 | ✅ 同 Phase 1 | 無差 |
| VisionA 使用者把轉檔結果加進模型庫 | ✅ 按一下按鈕即完成 | ✅ 同 Phase 1 | 無差 |
| VisionA 使用者下載已轉檔的模型 | ⚠️ 阻塞 / 折衷方案 — VisionA 前端目前能做的:(a) 顯示「下載功能即將上線」占位;(b) 從 VisionA backend proxy 下載(違反原架構);(c) 導向舊的 Kneron Converter Web UI 下載(會混亂) | ✅ 瀏覽器直連 File Access Agent,速度快、省流量 | 中等 — 這是 UX 上的明顯缺口,必須在 Phase 1 上線時和 VisionA 產品團隊協調 messaging |
Design Agent 的強烈建議:Phase 1 上線時必須有「使用者下載 messaging 策略」,不能讓使用者上傳完轉檔後發現東西下載不了(UX 上的死胡同)。這是需要使用者決策的議題 #1,詳見第 6 節。
2. 既有 Web UI 影響分析
2.1 既有 Web UI 使用者旅程是否改變?
結論:Phase 1 完全不改,Web UI 使用者無感。
| 旅程階段 | 既有行為(會繼續保留) | 是否受影響 |
|---|---|---|
| 進入 Web UI 主頁 | 直接打開網頁,不需登入([推測] 現況) | ❌ 不受影響 |
| 上傳模型(multipart) | 瀏覽器表單 → POST /jobs with FormData |
❌ 不受影響 |
| 追蹤進度(SSE) | 瀏覽器開 SSE 連線 GET /jobs/:id/events,自動 fallback 到每 3 秒 polling |
❌ 不受影響 |
| 下載結果 | 直接點 GET /jobs/:id/download/:filename |
❌ 不受影響 |
| 任務列表 | GET /jobs 列出全部 job |
❌ 不受影響(但查不到 VisionA 使用者透過新 API 建立的 job — 見 2.3) |
核心設計選擇(已由 PM 決策):
- 既有
/jobs路徑保留,不加 OAuth 驗證 - 對外 API 走新路徑
/api/v1/*,獨立加 OAuth middleware - 兩套 API 並存,互不影響
✅ Design Agent 同意此決策,理由:
- 避免破壞現有使用者(零 regression 風險)
- 讓 Web UI 和對外 API 的演進節奏脫鉤(Web UI 是內部工具,對外 API 需要穩定性承諾)
- 未來若要合併,可在 Phase 3 評估,不用現在壓時程決定
2.2 既有 Web UI 的 API 呼叫路徑是否受影響?
結論:不受影響。
既有 Web UI 呼叫的所有端點(在 apps/task-scheduler/server.js 中驗證過):
POST /jobs (multipart 上傳)
GET /jobs (列表)
GET /jobs/:jobId (查詢單一 job)
GET /jobs/:jobId/events (SSE)
GET /jobs/:jobId/download/:filename (下載)
GET /health
這些端點 Phase 1 保留原樣。對外 API 是新增,不是取代。
2.3 既有 Web UI 要不要也改走新 OAuth 流程?
Design Agent 建議:Phase 1 不改,維持現況。 但有一個 UX 面的警示要給使用者知道。
建議不改的理由(UX 觀點)
- 內部工具的 UX 定位:既有 Web UI 的 persona 是 Kneron 內部 AI 工程師,在可信網段內使用,不需要 OAuth 這層摩擦
- 加上 OAuth 等於要加登入流程:會多出「登入頁 → 選 tenant → 授權」等步驟,對內部工具體驗是倒退
- 風險可控:Web UI 目前應該是在內網 / VPN 後面運行,不直接暴露公網(這需要由 Architect 與 DevOps 確認,見下方警示)
⚠️ 警示 — 需要使用者與 Architect 釐清
如果 Web UI 和對外 API 部署在同一個 Task Scheduler instance 上(例如同一個 Express app 綁兩套 route),那麼:
- 對外 API 的 public endpoint(
/api/v1/*)會和 Web UI 用的/jobs共用同一個 TCP port / Nginx vhost - 若未來公開
/api/v1/*到公網,/jobs路徑也會曝光 - 有心人可以直接打
POST /jobs(不需 OAuth)繞過對外 API 的 rate limit / scope 檢查
緩解方案(建議交給 Architect 評估):
- 方案 A:部署層級隔離 — Web UI 的
/jobs只綁 internal network interface,/api/v1/*綁 public interface - 方案 B:Nginx 路由控制 — 同一個 Task Scheduler,但 public Nginx 只 proxy
/api/v1/*,internal Nginx 才 proxy/jobs - 方案 C:在
/jobs加基本 IP allowlist(內網 CIDR)
2.4 既有 SSE (/jobs/:id/events) 機制在新架構下是否保留?
結論:保留,但只給 Web UI 用。對外 API 走 polling,不對外開放 SSE。
Design Agent 的觀察
- Web UI 繼續用 SSE:既有 Web UI 的即時性體驗(看到 stage 切換、進度百分比即時跳動)是 UX 亮點,不能砍
- 對外 API 不做 SSE(PM 已決策):polling 已足夠,理由充分:
- 下游消費者是另一個 backend 服務(visionA-backend),polling 對它們而言是標準做法
- 不做 Webhook / SSE 能簡化 Phase 1 的 surface area
- visionA-backend 自己再決定要不要把進度以 SSE / WebSocket 推給 VisionA 前端
- 但要確保 SSE endpoint 不意外被對外 API 消費者呼叫(沒意義且資源浪費):
/jobs/:id/events保留在非 OAuth 路徑下,visionA-backend 沒有理由呼叫它- 若要防禦,可以在 Nginx 層封堵 public access 到
/jobs/*/events
UX 風險監測
visionA-backend 的 polling 策略會直接影響 VisionA 使用者看到的進度「順暢度」。建議 API 規格中明確給出指引(見第 4 節「給 Architect 的建議」):
- 建議的 polling 間隔(2-5 秒)
- 鼓勵
stage_changed時立即 poll(讓 VisionA 能快速反應階段切換) - 回應中的
etag/updated_at讓消費者知道何時真的有變
3. 新呼叫方(visionA-backend)間接影響分析
3.1 間接 UX 影響總覽
雖然我們不設計 VisionA 的 UI,但以下 API 設計決策會 直接限制 visionA 前端能做出的體驗:
| Converter API 設計點 | 對 VisionA 終端使用者 UX 的影響 | Design Agent 建議 |
|---|---|---|
| 同使用者同時一個轉檔限制(US-11) | 使用者想同時轉兩個不同模型會被擋 | 回 409 時附清晰的 active_job_id + 人類可讀的訊息,讓 VisionA 能做「你有一個轉檔進行中,要切過去看嗎?」的 UX |
| Polling 模式(不做 Webhook) | 進度更新延遲 = polling 間隔 | API 文件明示建議 polling 間隔;回應要快(p95 < 200ms)避免 VisionA 排隊等待 |
POST /api/v1/jobs 採 multipart/form-data(原始模型直接上傳) |
大檔上傳期間使用者需要「可取消 / 可重試」的體感 | API 文件建議 visionA-backend 在上傳到 Converter 時使用支援 progress event 的 HTTP client(原生 net/http + io.TeeReader 或等效),並在 visionA 前端以 progress bar 呈現上傳百分比;建議 Architect 在 TDD 中明確:收檔失敗 / 網路中斷時回 4xx/5xx 足以讓 visionA-backend 判斷是否重試(不要只 reset connection) |
| 原始模型檔案大小上限 500MB | 超過上限的使用者會被擋在建 job 前 | API 在 413 file_too_large 回應中附 details.limit_bytes / details.actual_bytes,讓 visionA 前端能顯示具體原因;VisionA 前端可在上傳前做 client-side 大小檢查提前攔截 |
| promote 需要另一個 API 呼叫 | 使用者要按兩次(轉完 + 加進模型庫) | 建議 visionA 前端把兩步驟做成一次操作(使用者按一次「轉檔並加進模型庫」,VisionA backend 內部自動 chain),但這是 VisionA 側的決定 |
| Converter Bucket 7 天 lifecycle | 使用者轉完沒 promote,7 天後檔案消失 | API 回應中要暴露 expires_at,讓 VisionA 能在 UI 顯示「檔案將於 X 天後自動清除」 |
| Recovery API 是 list 模式 | 使用者離開後回來 → VisionA 前端要決定是否自動跳轉到 job 頁 | API 要回足夠多資訊(job_id、stage、progress、created_at),讓 VisionA 前端做智慧決策 |
| Phase 1 沒有 delegated download | 使用者在 VisionA 模型庫看到模型,但不能下載 | 嚴重 UX 缺口,見第 6 節議題 #1 |
3.2 錯誤情境的 UX 投射
visionA 前端能把 Converter 回的錯誤轉成什麼樣的訊息,完全取決於我們回了什麼。以下是 Design Agent 建議 API 要清楚區分的錯誤類型:
| 情境 | HTTP 狀態 | 錯誤碼建議 | VisionA 能做出的 UX |
|---|---|---|---|
| token 無效 / 過期 | 401 | unauthorized |
背景 refresh token 重試 |
| token 有效但 scope 不足 | 403 | insufficient_scope + required_scope |
提示 admin 去 Member Center 補授權 |
| 已有 in-progress job | 409 | user_has_active_job + active_job_id |
「你有一個轉檔進行中,要切過去看嗎?」 |
| job 狀態不對(promote 時 job 還沒 completed) | 409 | job_not_ready_for_promote + current_status |
「轉檔還沒完成,請等進度條到 100% 再加進模型庫」 |
multipart body 格式錯 / model 檔案欄位缺失 / 必填 field 缺失(例如 user_id、model_id) |
400 | invalid_multipart + details.missing_field 或 details.reason |
「上傳失敗,請確認檔案格式與欄位」+ 具體指出缺哪個欄位 |
| 原始模型超過 500MB 上限 | 413 | file_too_large + details.limit_bytes + details.actual_bytes |
「檔案過大(限制 500MB),請確認上傳的模型大小」 |
| 轉檔失敗(模型本身的問題) | — | job.error.reason 要人類可讀 |
「在 BIE 量化階段失敗:[具體原因],建議檢查參考圖片是否足夠」 |
| File Access Agent 不可用(promote 時) | 502 | file_gateway_unavailable |
「模型庫服務暫時不可用,我們會自動重試」+ 顯示 retry 按鈕 |
| Member Center JWKS 取用失敗 | 503 | auth_service_unavailable |
系統層錯誤,顯示 maintenance banner |
備註:Phase 1 的原始模型改由 visionA-backend 以 multipart 直接上傳到 Converter,Converter 不再從 File Access Agent 拉原始模型,因此原本的
input_object_not_found(422)錯誤碼在 Phase 1 不會出現。取而代之的是上傳階段的invalid_multipart(400)與file_too_large(413)。File Access Agent 相關錯誤在 Phase 1 只會發生在 promote 階段。
3.3 API 設計上要給 visionA 留下哪些彈性?
為了讓 visionA 前端能做出更好的 UX,API 要預留以下能力(即使 Phase 1 可以先不實作,但 schema 要設計得可擴展):
必要(Phase 1)
- 狀態細節:不只
status,要有stage+progress(0-100) - 錯誤碼結構化:
error.code+error.message+error.details(可擴展) - 時間戳完整:
created_at、updated_at、各階段的stage_started_at/stage_completed_at(用於 VisionA 做階段耗時顯示) - 保留欄位:
metadata: {}(讓未來能加欄位不破壞 API 契約) - job_id 可識別:使用者若要截圖 / 反映問題,能清楚引用 job_id
建議(未必 Phase 1,但設計時要預留)
- ETA 欄位:
estimated_completion_at(Phase 1 可回 null,未來再實作) - 取消能力:即使 Phase 1 不實作,API 路徑
DELETE /api/v1/jobs/:id要預留(避免 Phase 2 需要時得改契約) - Webhook 註冊:同上,即使 Phase 1 不實作,資料模型要考量未來可擴展
- progress 的顆粒度:每個 stage 內部的 progress(例如「BIE 階段 45%」而不只是「整體 33%」)
4. 建議與風險
4.1 給 Architect 的 API 設計建議(UX 觀點)
以下建議從「下游消費者能做出什麼樣的 UX」角度出發,請 Architect 在 TDD 中採納或說明取捨。
4.1.1 Response Schema 建議
GET /api/v1/jobs/:id 回應範例(建議):
{
"job_id": "uuid-v4",
"user_id": "visionA-user-id",
"status": "running", // created / running / completed / failed
"stage": "bie", // onnx / bie / nef / null
"progress": 45, // 0-100(整體)
"stage_progress": 60, // 0-100(當前階段內)—— 建議有
"created_at": "2026-04-25T12:00:00Z",
"updated_at": "2026-04-25T12:05:30Z",
"stage_timings": { // 建議有,讓 VisionA 能顯示階段耗時
"onnx": {"started_at": "...", "completed_at": "..."},
"bie": {"started_at": "...", "completed_at": null},
"nef": null
},
"estimated_completion_at": null, // Phase 1 可為 null
"result_object_keys": null, // completed 時才有
"expires_at": "2026-05-02T12:00:00Z", // Converter Bucket 7 天後過期
"error": null, // 失敗時結構化錯誤
"metadata": {}
}
POST /api/v1/jobs 衝突回應(建議):
{
"error": {
"code": "user_has_active_job",
"message": "使用者目前已有進行中的轉檔任務",
"details": {
"active_job_id": "uuid-v4",
"active_job_status": "running",
"active_job_stage": "bie",
"active_job_progress": 45
}
}
}
這讓 visionA 前端能直接顯示「你有一個轉檔進行中(BIE 階段 45%),要切過去看嗎?」而不用再多打一次 API 查詳情。
4.1.2 Polling 效能考量
- p95 < 200ms(已在 PRD §9.2.1):visionA-backend 可能每 2-5 秒 polling 一次,如果 API 慢 visionA 的 UI 會跟著卡
- 建議加
ETag/If-None-Match支援:visionA-backend 可以在 304 時跳過資料傳輸,省流量 - 避免無必要的 DB 查詢:
GET /api/v1/jobs/:id應該只讀 Redis,不做任何外部 HTTP 呼叫(否則 polling × N 個使用者會變擴增 load)
4.1.3 promote API 的 UX 考量
建議 POST /api/v1/jobs/:id/promote 是同步呼叫並回等候 result:
- 好處:visionA 前端可以直接顯示 loading → 成功 / 失敗
- 風險:PUT 到 File Access Agent 若慢(大檔),API 會 block 幾秒(p95 < 3s 已在 SLA)
- 備案:若 PUT 超過某個 timeout(例如 10s),API 回 202 + 新的
promote_job_id,visionA polling 查 promote 進度 - Architect 決策:Phase 1 建議先做同步版本(簡單),失敗率觀察後再決定是否需要 async 模式
4.1.4 其他
- 版本化:
/api/v1/是對的,建議 OpenAPI spec 明確標注「breaking change 會走/api/v2/」 - error response 統一格式:所有 4xx/5xx 都用同一個
{error: {code, message, details}}結構,避免 visionA 要寫多套 parser - job_id 格式固定:建議用 UUID v4,不要用 snowflake 之類的自訂 ID(visionA 端的 log 比較好看)
4.2 給 PM 的需求補強建議
PM 的 PRD 已經相當完整,以下是 Design Agent 從 UX 觀點發現可以補強的地方:
4.2.1 建議新增:使用者下載 messaging 策略(§15.1 或 §12.2)
Phase 1 上線時 VisionA 使用者會遇到「我的模型在模型庫裡但下不下來」的情境。建議在 PRD 中增加一段:
Phase 1 使用者下載缺口的 UX 處理方案(待確認): Phase 1 上線時,delegated download 尚未可用。VisionA 需在其 UI 中明確告知使用者「下載功能於 Phase 2 上線」,或採 fallback proxy 方案。此取捨由 VisionA 產品團隊主導,Kneron Converter 不需額外做事,但雙方需在 Phase 1 上線 kickoff 前對齊 messaging。
4.2.2 建議新增:VisionA 前端 UX 對我們 API 的期望(§4.4 或新增 §4.5)
目前 PRD §4.4 的 User Story 是從「visionA-backend」視角寫的。建議補一組 從 VisionA 終端使用者視角 的 UX acceptance criteria,例如:
- 「轉檔成功後,使用者能在 5 秒內看到模型出現在自己的模型庫」
- 「同使用者同時轉檔限制觸發時,使用者能在 2 秒內看到『你有一個轉檔進行中』的提示,並能一鍵跳過去」
- 「轉檔失敗時,使用者能看到具體原因(不只是 generic error)」
這些是 UX 標準,不是技術標準,寫進 PRD 可以讓 Architect 在設計 API 時有依據。
4.2.3 建議補強:[推測] 標記的清理策略
PRD 中保留了既有的 [推測] 標記,但 §1.2 新增的 Persona C 和 §4.3~4.4 的 User Stories 沒有 [推測] 標記(因為是基於本次討論確認的)。建議使用者審閱時:
- 新增章節(§1.2 Persona C、§4.3~4.4、§14、§15):請使用者確認後正式定案
- 舊章節的
[推測]標記:獨立一個工作項,逐條請使用者確認或刪除
這不是本次 L 級範圍,但建議 PM 在下一版 PRD 中處理。
4.3 給 Architect 的一般性 UX 風險提醒
4.3.1 Polling 間隔太短可能讓 VisionA UI 卡頓?
風險等級:低
- visionA-backend 是 polling 方(不是 visionA 前端直接 polling Converter),所以 Converter 端壓力可控
- 但若有很多 VisionA 使用者同時轉檔,visionA-backend 可能每秒對 Converter 打幾十次
GET /jobs/:id - 建議:Architect 在 TDD 中明確給出 rate limit 策略(對 visionA-backend 的 client_credentials token 設 rate limit),並在 API 文件中建議 polling 間隔
4.3.2 同時一個轉檔的限制可能引起使用者困惑
風險等級:中
- 「我剛剛明明建立了一個 job,為什麼再按一次就 409」可能讓使用者以為系統壞了
- 建議:429 或 409 的 response body 要帶完整的 active job 資訊(見 4.1.1),讓 visionA 前端能做出「你有 X 在轉中,要看嗎?」的友善提示
- 護欄指標:PRD §9.2.2 已經設計了「同使用者 409 比率 < 5%」的指標追蹤,Design Agent 同意這個目標
4.3.3 Converter Bucket 7 天 lifecycle 和使用者期待不符
風險等級:中
- 使用者可能誤以為「轉完就在那裡了」,7 天後突然不見會很驚訝
- 建議:
- API 回應明確標注
expires_at(見 4.1.1) - visionA 前端在轉檔結果頁顯示「請於 X 天內加進模型庫,否則檔案將被自動清除」
POST /promote應該是非常顯眼的 primary action(但這是 VisionA 的 UI 決定)
- API 回應明確標注
4.3.4 使用者中途關掉頁面再回來(Recovery)是否會遺失 SSE?
風險等級:低(已由 PM 決策接受)
- PRD 已明確 Phase 1 對外 API 是 polling 模式,visionA-backend 重新進入頁面時會呼叫
GET /api/v1/jobs?user_id=...&status=in_progress - Converter 本身的 Redis 狀態在這段時間是持續更新的,所以 recovery 不會因為瀏覽器關掉而遺失資料
- 風險:若 Converter 在使用者離開期間 Crash(符合設計哲學),使用者回來會看不到任何 job
- PRD 已在 US-12 明示這個限制(「Crash 即 Reset」不保證跨 Crash recovery)
- Design Agent 接受這個設計取捨,但建議 API 回應中區分「沒有 in-progress job」vs「job 已不存在(可能因為 Crash / 過期)」讓 visionA 能給使用者不同提示
4.4 潛在 UX 風險清單(彙整)
| # | 風險 | 嚴重度 | 建議處理 |
|---|---|---|---|
| 1 | Phase 1 使用者下載功能缺口 | 高 | 需 VisionA 產品團隊協調 messaging 策略(見議題 #1) |
| 2 | Web UI /jobs 路徑在公網意外曝露 |
中 | 部署層或 Nginx 層隔離(見 2.3 警示) |
| 3 | 7 天 lifecycle 讓使用者驚訝 | 中 | API 要暴露 expires_at,visionA UI 要顯示 |
| 4 | 同使用者 409 的使用者困惑 | 中 | 回應要帶完整 active job 資訊 |
| 5 | 錯誤訊息不夠人類可讀 | 中 | 結構化 error code + 可讀 message |
| 6 | Polling 效能對 visionA 的影響 | 低 | API p95 < 200ms + 建議 ETag |
| 7 | Crash 後 job 消失 | 低(已接受) | API 能區分「無 job」vs「job 不存在」 |
| 8 | 轉檔階段耗時資訊不足,使用者無法預期 | 低 | 回應中帶 stage_timings,未來可做 ETA |
5. 其他觀察
5.1 既有 Web UI 的非本次議題(延伸觀察,不在本次範圍)
在審查過程中 Design Agent 觀察到既有 Web UI 有以下 UX 債,但 不屬於本次 L 級範圍,僅作記錄供未來討論:
- 前後端 API 契約不一致(已在 PRD §7.3 列出):Web UI 的單階段表單呼叫的
/api/onnx/upload等端點後端沒實作。UX 影響:使用者按了按鈕會失敗 - 無時間預估:使用者只能看到「BIE 階段 45%」,不知道總共還要多久
- 無批次上傳:一次只能轉一個模型
- 錯誤訊息品質:
job.error.reason欄位存在但文字品質未知 - 無登入系統:內部工具現況,但若未來要加 OAuth 要從頭設計登入 UX
5.2 Mermaid 相依圖(從 UX 視角)
flowchart LR
subgraph UsersWorld["使用者世界"]
KneronUser["Kneron 內部 AI 工程師<br/>(既有 Web UI 使用者)"]
VisionAUser["VisionA 終端使用者<br/>(新的 間接受益者)"]
end
subgraph InnovedusEcosystem["Innovedus 生態"]
WebUI["Kneron Converter Web UI<br/>(保留不動)"]
VisionAFrontend["VisionA 前端<br/>(另一個團隊實作)"]
VisionABackend["visionA-backend<br/>(Persona C)"]
MemberCenter["Member Center"]
FileAccessAgent["File Access Agent"]
end
subgraph Converter["Kneron Model Converter(本專案)"]
OldAPI["舊 API<br/>POST /jobs<br/>GET /jobs/:id<br/>GET /jobs/:id/events (SSE)<br/>不加 OAuth"]
NewAPI["新 API<br/>POST /api/v1/jobs<br/>GET /api/v1/jobs/:id<br/>POST /api/v1/jobs/:id/promote<br/>OAuth2 Bearer"]
end
KneronUser -->|multipart 上傳 / SSE 看進度| WebUI
WebUI -->|保持既有呼叫| OldAPI
VisionAUser -->|平台內操作| VisionAFrontend
VisionAFrontend -->|VisionA 自家協議| VisionABackend
VisionABackend -->|取 service token| MemberCenter
VisionABackend -->|Bearer token + multipart<br/>(含原始模型 + ref_images)| NewAPI
NewAPI -.->|promote PUT 結果檔| FileAccessAgent
NewAPI -.->|驗 token / 取 token| MemberCenter
classDef newPath fill:#e1f5ff,stroke:#0288d1,stroke-width:2px
classDef oldPath fill:#fff9c4,stroke:#fbc02d,stroke-width:2px
class NewAPI,VisionAUser,VisionAFrontend,VisionABackend,MemberCenter,FileAccessAgent newPath
class OldAPI,KneronUser,WebUI oldPath
圖例:黃色 = Phase 1 保留不動的既有路徑;藍色 = Phase 1 新增 / 整合的部分。
6. 需要使用者決策的 UX 議題
議題 #1(最重要):Phase 1 使用者下載的 messaging 策略
背景:Phase 1 上線後,VisionA 使用者能完成「上傳 → 轉檔 → 加進模型庫」,但 不能下載 已搬進模型庫的模型檔。這是因為 Phase 2 的 delegated download 阻塞於 Member Center 未實作 POST /file-access/download-tokens。
為什麼這是重要 UX 議題:
- 使用者的心智模型會是「我的模型在我的模型庫裡 → 我當然可以下載它」
- 上線時如果下載按鈕不能按、或按了沒反應,會是明顯的 UX 死胡同
- 使用者可能繞道去舊 Kneron Web UI 下載,但那邊資料和 VisionA 模型庫不同步(混亂)
可選方案:
| 方案 | 做法 | UX 優劣 | 工程成本 |
|---|---|---|---|
| A | 隱藏下載按鈕,標示「下載功能 Phase 2 上線」 | UX 誠實,但缺口明顯 | 低(VisionA 前端) |
| B | VisionA backend 做 proxy 下載(VisionA backend 從 File Access Agent 拉檔再回給瀏覽器) | 暫時堪用,但違反原架構(大檔過 VisionA backend) | 中(VisionA backend) |
| C | 使用者點下載 → 跳轉到舊 Kneron Converter Web UI 下載 | 技術最簡單,但資料不同步,使用者會混亂 | 低(導流) |
| D | 等 Member Center 實作完才上線 Phase 1 | UX 完整,但時程被別人卡住 | 阻塞 |
Design Agent 傾向方案 A(隱藏 + messaging),但這需要 使用者 + VisionA 產品團隊 一起決定,不是 Converter 單方能決定。
建議 Orchestrator 協調:Phase 1 kickoff 前召一次 VisionA 產品團隊 + Kneron Converter PM + Member Center owner 的跨團隊會議,明確 messaging 策略與時程。
議題 #2(次要):既有 Web UI 的公開曝光風險
背景:見第 2.3 節。若未來 /api/v1/* 對外公開而 /jobs 沒做任何隔離,可能被繞過。
需要使用者確認:
- 本專案部署目標是什麼?(純內網 / VPN 後面 / 公網)
- Web UI 是否會和對外 API 在同一個 public entry 後面?
這個議題交由 Architect Agent 在 TDD 中提出具體部署策略,使用者確認即可。Design Agent 只提出警示。
議題 #3(低優先):既有 PRD 的 [推測] 標記清理
見 4.2.3。建議在本次 L 級之後單獨開一個工作項處理。不阻塞 Phase 1。
7. 結論
7.1 對三方聯合討論的 Design 立場
- ✅ 同意 PM 的 Phase 1 / Phase 2 切分(§15)
- ✅ 同意 user_id 以 multipart form field 帶入(方式 A),而非放 token claim
- ✅ 同意 原始模型採 multipart 直連上傳(visionA-backend → Converter),不經過 File Access Agent(2026-04-25 更新)
- ✅ 同意 polling 模式不做 Webhook
- ✅ 同意 Web UI 不改(Phase 1 保留既有路徑和 UX)
- ✅ 同意 搬檔做法 2(Converter 自己 PUT 到 File Access Agent,僅限 promote 階段)
- ⚠️ 要求補強:Phase 1 使用者下載 messaging 策略(議題 #1)
- ⚠️ 要求補強:API response schema 要符合第 4.1 節的 UX 期望(錯誤結構化、stage_timings、expires_at 等)
- ⚠️ 新增 UX 關切:multipart 上傳的 progress bar 呈現與
invalid_multipart/file_too_large錯誤碼細節結構化(見 3.1、3.2)
7.2 Design Agent 對其他兩方文件的審閱(待三方產出後執行)
- 審閱 PRD 時的重點:Persona C 是否清楚描述服務對服務的互動?終端使用者的 UX 期望是否納入 acceptance criteria?
- 審閱 TDD 時的重點:API response schema 是否提供足夠彈性讓 visionA 做好 UX?錯誤碼是否結構化?polling 效能是否達 SLA?
7.3 本次 Design Review 的直接產出
- 本份
design-review.md user-flow-cross-system.md(跨系統使用者流程圖)- 不產出 Wireframe、Prototype、Design Tokens(本次無新 UI 需求)