jim800121chen cff9236699 docs: migrate Autoflow shared documents to docs/autoflow/
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>
2026-05-01 10:59:21 +08:00

28 KiB
Raw Blame History

Design Review — API 對外開放 L 級功能

審查範圍2026-04-25 的 L 級新功能「開放 Kneron Model Converter 轉檔能力為對外 REST API 供 VisionA 使用」。

審查者Design AgentAutoflow

審查時機:三方聯合討論階段(與 PM Agent / Architect Agent 同步作業)

特別聲明:這次任務的直接產出物是 後端 API 介面,不是新 UI 畫面。本次 Review 的焦點為:

  1. 對既有 Web UI 使用者體驗的間接影響
  2. API 設計對下游消費者visionA-backend能做出什麼樣的終端 UX 的限制
  3. 從 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_large2相依圖中 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 同意此決策,理由:

  1. 避免破壞現有使用者(零 regression 風險)
  2. 讓 Web UI 和對外 API 的演進節奏脫鉤Web UI 是內部工具,對外 API 需要穩定性承諾)
  3. 未來若要合併,可在 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 觀點)

  1. 內部工具的 UX 定位:既有 Web UI 的 persona 是 Kneron 內部 AI 工程師,在可信網段內使用,不需要 OAuth 這層摩擦
  2. 加上 OAuth 等於要加登入流程:會多出「登入頁 → 選 tenant → 授權」等步驟,對內部工具體驗是倒退
  3. 風險可控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
  • 方案 BNginx 路由控制 — 同一個 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 的觀察

  1. Web UI 繼續用 SSE:既有 Web UI 的即時性體驗(看到 stage 切換、進度百分比即時跳動)是 UX 亮點,不能砍
  2. 對外 API 不做 SSEPM 已決策polling 已足夠,理由充分:
    • 下游消費者是另一個 backend 服務visionA-backendpolling 對它們而言是標準做法
    • 不做 Webhook / SSE 能簡化 Phase 1 的 surface area
    • visionA-backend 自己再決定要不要把進度以 SSE / WebSocket 推給 VisionA 前端
  3. 但要確保 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 使用者轉完沒 promote7 天後檔案消失 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_idmodel_id 400 invalid_multipart + details.missing_fielddetails.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 直接上傳到 ConverterConverter 不再從 File Access Agent 拉原始模型,因此原本的 input_object_not_found422錯誤碼在 Phase 1 不會出現。取而代之的是上傳階段的 invalid_multipart400file_too_large413。File Access Agent 相關錯誤在 Phase 1 只會發生在 promote 階段。

3.3 API 設計上要給 visionA 留下哪些彈性?

為了讓 visionA 前端能做出更好的 UXAPI 要預留以下能力(即使 Phase 1 可以先不實作,但 schema 要設計得可擴展):

必要Phase 1

  1. 狀態細節:不只 status,要有 stage + progress0-100
  2. 錯誤碼結構化error.code + error.message + error.details(可擴展)
  3. 時間戳完整created_atupdated_at、各階段的 stage_started_at / stage_completed_at(用於 VisionA 做階段耗時顯示)
  4. 保留欄位metadata: {}(讓未來能加欄位不破壞 API 契約)
  5. job_id 可識別:使用者若要截圖 / 反映問題,能清楚引用 job_id

建議(未必 Phase 1但設計時要預留

  1. ETA 欄位estimated_completion_atPhase 1 可回 null未來再實作
  2. 取消能力:即使 Phase 1 不實作API 路徑 DELETE /api/v1/jobs/:id 要預留(避免 Phase 2 需要時得改契約)
  3. Webhook 註冊:同上,即使 Phase 1 不實作,資料模型要考量未來可擴展
  4. 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.1visionA-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例如 10sAPI 回 202 + 新的 promote_job_idvisionA 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 之類的自訂 IDvisionA 端的 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 天後突然不見會很驚訝
  • 建議
    1. API 回應明確標注 expires_at(見 4.1.1
    2. visionA 前端在轉檔結果頁顯示「請於 X 天內加進模型庫,否則檔案將被自動清除」
    3. POST /promote 應該是非常顯眼的 primary action但這是 VisionA 的 UI 決定)

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_atvisionA 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 級範圍,僅作記錄供未來討論:

  1. 前後端 API 契約不一致(已在 PRD §7.3 列出Web UI 的單階段表單呼叫的 /api/onnx/upload 等端點後端沒實作。UX 影響:使用者按了按鈕會失敗
  2. 無時間預估使用者只能看到「BIE 階段 45%」,不知道總共還要多久
  3. 無批次上傳:一次只能轉一個模型
  4. 錯誤訊息品質job.error.reason 欄位存在但文字品質未知
  5. 無登入系統:內部工具現況,但若未來要加 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 沒做任何隔離,可能被繞過。

需要使用者確認

  1. 本專案部署目標是什麼?(純內網 / VPN 後面 / 公網)
  2. 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 Agent2026-04-25 更新)
  • 同意 polling 模式不做 Webhook
  • 同意 Web UI 不改Phase 1 保留既有路徑和 UX
  • 同意 搬檔做法 2Converter 自己 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 的直接產出

  1. 本份 design-review.md
  2. user-flow-cross-system.md(跨系統使用者流程圖)
  3. 不產出 Wireframe、Prototype、Design Tokens本次無新 UI 需求)