kneron_model_converter/docs/autoflow/03-design/user-flow-cross-system.md
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

354 lines
18 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 跨系統使用者流程圖 — VisionA 終端使用者視角
> **視角**VisionA 終端使用者Edge AI 應用開發者)在 VisionA 平台內完成模型轉檔的完整體驗。
>
> **重點**從使用者能「感知到什麼」切入而非技術細節。Token 種類、錯誤情境等只標示關鍵分支,詳細 API 規格見 `04-architecture/TDD.md`。
>
> **涵蓋情境**
> - 情境 A首次上傳模型並轉檔主要 Happy Path
> - 情境 B離開頁面後回來看未完成的 jobRecovery
> - 情境 CPhase 2 使用者下載模型(阻塞中 — 僅供未來參考)
>
> **服務標記慣例**
> - 🧑 = VisionA 終端使用者(人類)
> - 🖥️ = VisionA 前端(瀏覽器)
> - ⚙️ = visionA-backendGo 服務)
> - 🔐 = Member CenterAuth 中心)
> - 📦 = File Access Agent檔案閘道
> - 🏭 = Kneron Converter API本專案
> - 🗄️ = Converter BucketMinIO 暫存)
> - 💾 = NAS Bucket模型庫長期儲存
## 變更歷程
| 日期 | 變更內容 |
|------|---------|
| 2026-04-25 | 原始模型上傳路徑改為 visionA-backend → Converter multipart 直連(不經過 File Access Agent`POST /api/v1/jobs` 改為 multipart/form-data移除 `input_object_key` 欄位,`user_id` 改以 multipart field 帶入。Phase 1 Converter 不再從 File Access Agent 讀取原始模型,只在 promote 階段 PUT 結果檔。階段編號:原「階段 2上傳 FAA+ 階段 3建 job」合併為新「階段 2建 job + 上傳)」,後續階段編號往前挪一格。|
---
## 情境 A使用者上傳新模型並轉檔Happy Path
### A.1 使用者視角的流程摘要(非技術)
```
🧑 使用者在 VisionA 平台
├─ 1. 在「模型庫」按「新增模型」→ 選本機 ONNX 檔
├─ 2. 填寫 model_id / version / 選擇 Kneron 晶片平台520/720/...
├─ 3. 按「上傳並轉檔」
│ ↓
│ [系統顯示進度條ONNX 優化 0% → 33% → BIE 量化 33% → 66% → NEF 編譯 66% → 100%]
├─ 4. 轉檔完成!顯示成功訊息 + 「加進我的模型庫」按鈕
└─ 5. 按「加進我的模型庫」→ 短暫 loading → 顯示「已加入模型庫」
使用者在模型庫看到新的已轉檔模型
```
**使用者感知到的總體體驗**:從選檔到加進模型庫,一條流水線,使用者不需要知道背後有多個服務在協作(建 job 時涉及 visionA-backend / Member Center / Converterpromote 時才會再呼叫 File Access Agent
---
### A.2 完整跨系統流程圖Mermaid Sequence
```mermaid
sequenceDiagram
autonumber
participant U as 🧑 使用者
participant FE as 🖥️ VisionA 前端
participant BE as ⚙️ visionA-backend
participant MC as 🔐 Member Center
participant FA as 📦 File Access Agent
participant CV as 🏭 Converter API
participant CB as 🗄️ Converter Bucket
participant NB as 💾 NAS Bucket
Note over U,FE: 階段 1選檔 + 填表
U->>FE: 選本機 ONNX 檔
U->>FE: 填 model_id / version / platform
U->>FE: 按「上傳並轉檔」
FE->>BE: 送出 (multipart: 檔案 + 參數)
Note over BE,CB: 階段 2visionA-backend 呼叫 Converter 建 jobmultipart 同時帶原始模型)
BE->>MC: POST /oauth/token (client_credentials, scope=converter:job.write)
MC-->>BE: service token (aud=kneron_converter_api)
BE->>CV: POST /api/v1/jobs<br/>Authorization: Bearer token<br/>Content-Type: multipart/form-data<br/>files: model (必填, ≤500MB), ref_images[] (optional, maxCount 100)<br/>fields: user_id, model_id, version, platform, enable_evaluate, enable_sim_fp, enable_sim_fixed, enable_sim_hw
CV->>MC: 驗 token (JWKS)
MC-->>CV: 驗證通過
CV->>CV: 檢查user_id 是否有 in-progress job?<br/>US-11 同使用者一個轉檔限制)
alt 有 in-progress job
CV-->>BE: 409 Conflict + {code: user_has_active_job, active_job_id, active_job_status, active_job_stage}
BE-->>FE: 409 + active job 詳情
FE-->>U: 顯示「你有一個轉檔進行中,要切過去看嗎?」
Note over U: 走情境 BRecovery
else 沒有 in-progress job
CV->>CB: 寫入原始模型 (jobs/{job_id}/input/{filename})<br/>(含 ref_images[] 如有)
CV->>CV: 建 job 記錄,塞進 Redis<br/>Enqueue 到 onnx-worker
CV-->>BE: 201 Created + {job_id, status: created}
BE-->>FE: 201 + job_id
end
Note over FE,CV: 階段 3Polling 進度(每 2-5 秒一次)
loop 直到 status=completed 或 failed
FE->>BE: GET /api/jobs/{job_id}/status
BE->>CV: GET /api/v1/jobs/{job_id}<br/>Authorization: Bearer token
CV-->>BE: {status, stage, progress, stage_timings, expires_at, ...}
BE-->>FE: 轉譯後的進度 JSON
FE->>U: 更新進度條 + 階段顯示
end
Note over CV: Worker 背景處理ONNX → BIE → NEF<br/>Crash 即 Reset 設計,不保證跨 Crash 存活)
CV->>CB: 儲存各階段結果out.onnx / out.bie / out.nef
Note over FE,U: 階段 4轉檔完成顯示「加進模型庫」按鈕
CV-->>BE: {status: completed, result_object_keys: [...], expires_at: "2026-05-02"}
BE-->>FE: 已完成 + result 資訊
FE->>U: 顯示「轉檔完成!」<br/>+「加進我的模型庫」按鈕<br/>+「檔案將於 7 天後自動清除」提示
Note over U,NB: 階段 5使用者按「加進模型庫」→ promote
U->>FE: 按「加進我的模型庫」
FE->>BE: POST /api/models/{job_id}/add-to-library
BE->>CV: POST /api/v1/jobs/{job_id}/promote<br/>Authorization: Bearer token<br/>Body: {target_object_key: "visionA/models/{user_id}/{model_id}/v{version}/out.nef", ...}
CV->>MC: 取 files:upload.write token若 cache 過期)
MC-->>CV: service token
CV->>CB: 讀結果檔
CV->>FA: PUT /files/{target_object_key}<br/>Authorization: Bearer token<br/>Body: out.nef
FA->>MC: 驗 token
MC-->>FA: 驗證通過
FA->>NB: 儲存到 NAS使用者的模型庫區
FA-->>CV: 200 OK
CV-->>BE: 200 OK + promoted_object_keys
BE-->>FE: 成功
FE->>U: 顯示「已加入模型庫」
Note over U: 使用者在模型庫看到新模型
```
### A.3 使用者感知到什麼 vs 背後發生什麼
| 使用者看到 / 做的事 | 背後發生的事(簡述)|
|------------------|------------------|
| 選檔並按「上傳並轉檔」 | visionA-backend 以 multipart/form-data 直接把原始模型上傳到 Converter經 Member Center auth 取 `converter:job.write` service tokenConverter 收檔後暫存在自己的 Bucket |
| 進度條跳動 | visionA-backend 每 2-5 秒 polling Converter拿到新進度就更新 UI |
| 「ONNX 優化 → BIE 量化 → NEF 編譯」階段切換 | Converter 的 Task Scheduler 在 Redis 中推進 job stageWorker 消耗 stage queue |
| 「檔案將於 7 天後自動清除」 | Converter Bucket 有 7 天 lifecycle促使使用者做 promote |
| 按「加進我的模型庫」 | visionA-backend 呼叫 Converter `/promote`Converter 自己把檔案 PUT 到 File Access Agent不經 visionA-backend省流量|
| 模型出現在使用者的模型庫 | NAS Bucket 已經收到檔案(在 VisionA 使用者模型庫的 objectKey path 下)|
### A.4 關鍵時間點與可能的等待體驗
| 時間點 | 使用者感受 | 影響 UX 的因素 |
|-------|---------|--------------|
| 按「上傳並轉檔」後 | Loading / 上傳進度條 | 單一 multipart 上傳從 visionA-backend 到 Converter 的時間,**與檔案尺寸相關**(上限 500MB。**建議 UI 顯示 upload progress bar**multipart 上傳可追蹤 byte 進度XHR upload progress event 或等效機制),不再像舊設計有「上傳 FAA + 拉檔入 Bucket」兩段式等待 |
| 進度條階段切換 | 期待每階段的時間均等,但實際上 NEF 通常最久 | 建議 UI 顯示各階段預估時間(可從 `stage_timings` 歷史推算)|
| 轉檔完成 → 按「加進模型庫」 | 短暫 loading | API p95 < 3s使用者體感應該 OK |
| 轉檔失敗 | 希望看到具體原因 | 錯誤碼要結構化`error.details.stage` + 人類可讀的 `error.details.reason` |
---
## 情境 B使用者離開頁面後回來Recovery
### B.1 使用者視角
```
🧑 使用者在轉檔進行中...
├─ 按上一頁 / 關閉瀏覽器 / 切到其他 app
│ [Converter 背景繼續轉檔,不受影響]
├─ 15 分鐘後回來 VisionA進入「模型庫」或「轉檔中心」
├─ 系統自動偵測到「你有一個轉檔進行中」
│ └─ 顯示:「模型 XYZ 正在轉檔BIE 階段 60%),要繼續追蹤嗎?」
└─ 使用者按「繼續追蹤」→ 回到進度頁,正常 polling 進度
```
### B.2 跨系統流程Mermaid Sequence
```mermaid
sequenceDiagram
autonumber
participant U as 🧑 使用者
participant FE as 🖥️ VisionA 前端
participant BE as ⚙️ visionA-backend
participant MC as 🔐 Member Center
participant CV as 🏭 Converter API
Note over U,FE: 使用者重新打開 VisionA 模型庫頁
U->>FE: 進入頁面
FE->>BE: GET /api/models/in-progress?user_id=...
BE->>MC: 取 service token若 cache 過期)<br/>scope=converter:job.read
MC-->>BE: service token
BE->>CV: GET /api/v1/jobs?user_id=...&status=in_progress<br/>Authorization: Bearer token
CV->>MC: 驗 token
MC-->>CV: 驗證通過
CV->>CV: 從 Redis 查 user_id 對應的所有 in-progress job
CV-->>BE: [{job_id, status, stage, progress, created_at}, ...]
alt 有 in-progress job
BE-->>FE: job 列表
FE->>U: 顯示「你有一個轉檔進行中<br/>模型 XYZ - BIE 階段 60%<br/>[繼續追蹤] [放著不管]」
U->>FE: 按「繼續追蹤」
FE->>U: 進入進度頁,開始 polling<br/>(同情境 A 階段 4
else 沒有 in-progress job
BE-->>FE: 空陣列
FE->>U: 正常顯示模型庫頁,不打擾使用者
end
Note over CV: ⚠️ 特別情境Converter 在使用者離開期間 Crash
Note over CV: Redis 被重置 → in-progress job 消失<br/>符合「Crash 即 Reset」設計
Note over U: 使用者回來看不到 job<br/>需要重新上傳US-12 已明示此限制)
```
### B.3 Recovery 的 UX 考量
| 考量點 | 處理建議 |
|-------|---------|
| 使用者不記得自己有 job 在跑 | 進入頁面時主動查詢並顯示提示 |
| 使用者有多個裝置手機+電腦都登入 | 每個裝置都會看到相同的 in-progress job因為是 server-side 查詢|
| Converter Crash 導致 job 消失 | VisionA 前端顯示上次的轉檔記錄已遺失建議重新上傳」( visionA-backend 決定是否保留本地 cache|
| 回來時 job 已完成 | 可查 `GET /api/v1/jobs?user_id=...&status=completed` 看最近完成的 job可選功能|
---
## 情境 CPhase 2 — 使用者直接下載模型庫檔案(阻塞中)
> ⚠️ **重要提示**:本情境的 `POST /file-access/download-tokens` endpoint 在 Member Center **尚未實作**Phase 1 **不做此情境**。
>
> 以下流程圖僅供未來 Phase 2 啟動時參考。Phase 1 上線時使用者如何處理下載需求,見 `design-review.md` 第 6 節「議題 #1」。
### C.1 Phase 2 目標使用者體驗
```
🧑 使用者在 VisionA 模型庫
├─ 看到已轉檔的模型
├─ 按「下載 .nef 檔」
└─ 瀏覽器直接下載(快速,因為直連 File Access Agent不經 visionA-backend
```
### C.2 Phase 2 跨系統流程Mermaid Sequence尚未實作
```mermaid
sequenceDiagram
autonumber
participant U as 🧑 使用者
participant FE as 🖥️ VisionA 前端
participant BE as ⚙️ visionA-backend
participant MC as 🔐 Member Center
participant FA as 📦 File Access Agent
participant NB as 💾 NAS Bucket
Note over U,FE: 使用者按下載按鈕
U->>FE: 按「下載 .nef」
FE->>BE: POST /api/models/{model_id}/download-token
Note over BE,MC: ⚠️ Phase 2 阻塞中Member Center 尚未實作此 endpoint
BE->>MC: POST /file-access/download-tokens<br/>Body: {tenant_id, user_id, object_key, scope: "files:download.delegate"}
MC-->>BE: {delegated_token (opaque, exp <= 5min), expires_at}
BE-->>FE: delegated_token + File Access Agent 的 download URL
Note over FE,FA: 瀏覽器直接下載(不經 visionA-backend省流量
FE->>FA: GET /files/{object_key}?token=<delegated_token>
FA->>MC: POST /validate-delegated-token<br/>Body: {token}
MC-->>FA: {valid: true, user_id, object_key, tenant_id}
FA->>NB: 讀檔
FA-->>FE: 檔案stream 下載)
FE->>U: 瀏覽器儲存檔案
```
### C.3 Phase 2 體驗 vs Phase 1 折衷方案的 UX 落差
| 項目 | Phase 1 折衷方案任一| Phase 2 完整方案 |
|------|----------------------|----------------|
| 下載速度 | 大檔走 visionA-backend proxy或無法下載隱藏按鈕| 瀏覽器直連 File Access Agent|
| visionA-backend 的負擔 | proxy| |
| 檔案流量路徑 | 使用者 visionA-backend File Access Agent 使用者 | 使用者 File Access Agent直連|
| 使用者 UX | spinner可能 timeout | 瀏覽器原生下載體驗 |
| 安全性 | Phase 2都走 Member Center auth| |
---
## 綜合:三個情境的狀態機
```mermaid
stateDiagram-v2
[*] --> 選擇模型: 使用者進入 VisionA
選擇模型 --> 上傳中: 選檔 + 填表 + 提交
上傳中 --> 建 job: multipart 直接上傳到 Converter含原始模型 + ref_images
建 job --> 有衝突: 檢查 user_id 已有 in-progress
有衝突 --> 繼續追蹤舊 job: 使用者選擇查看既有 job
建 job --> 轉檔中: 無衝突Converter 收檔並建立 job
轉檔中 --> ONNX 階段
ONNX 階段 --> BIE 階段: 完成
BIE 階段 --> NEF 階段: 完成
NEF 階段 --> 轉檔完成: 完成
ONNX 階段 --> 轉檔失敗: 失敗
BIE 階段 --> 轉檔失敗: 失敗
NEF 階段 --> 轉檔失敗: 失敗
轉檔中 --> 使用者離開: 使用者關頁面
使用者離開 --> 繼續追蹤舊 job: 使用者回來(走情境 B Recovery
使用者離開 --> Job 消失: Converter Crash符合設計哲學
Job 消失 --> [*]
轉檔完成 --> 已 promote: 使用者按「加進模型庫」Converter PUT 到 File Access Agent
已 promote --> 下載: 使用者要用模型
下載 --> Phase 1 折衷: Phase 1下載功能缺口
下載 --> Phase 2 直連: Phase 2等 Member Center 補完)
轉檔失敗 --> [*]: 使用者看錯誤訊息
Phase 1 折衷 --> [*]
Phase 2 直連 --> [*]
繼續追蹤舊 job --> 轉檔中
```
---
## 附錄Token 類型快速對照
| Token | 誰持有 | 誰簽發 | 誰驗 | 用途 |
|-------|-------|-------|------|------|
| visionA-backend service tokenaud=kneron_converter_api, scope=converter:job.write / converter:job.read| visionA-backend | Member Centerclient_credentials grant| Converter APIJWKS 驗簽| visionA-backend 呼叫 Converter API job / 查詢 / promote|
| Converter service tokenaud=file_access_api, scope=files:upload.write| Converter API | Member Centerclient_credentials grant| File Access Agent | Converter promote 階段 PUT 結果檔到 NAS。**Phase 1 不再需要 `files:download.read` / `files:metadata.read`**因為原始模型已改由 visionA-backend multipart 直接上傳到 ConverterConverter 不再從 FAA 拉檔 |
| Delegated download tokenPhase 2| 瀏覽器 | Member Center user | File Access Agent線上驗| 使用者瀏覽器直連 File Access Agent 下載 |
---
## 附錄:錯誤情境快速對照
| 使用者看到的訊息 | 技術原因 | 對應 HTTP 狀態 + error code |
|---------------|---------|--------------------------|
| 你有一個轉檔進行中要切過去看嗎?」| 同使用者同時一個轉檔限制觸發 | `POST /api/v1/jobs` 409 `user_has_active_job` |
| 轉檔失敗BIE 量化階段 [具體原因]」| Worker 內部失敗 | Job `status=failed`, `error.details.stage=bie`, `error.details.reason=...` |
| 上傳失敗請確認檔案格式與欄位」| multipart body 格式錯 / `model` 欄位缺失 / 必填 field 缺失例如 `user_id``model_id`| `POST /api/v1/jobs` 400 `invalid_multipart` |
| 檔案過大請確認模型不超過 500MB」| 上傳檔案超過 Converter 的大小上限 | `POST /api/v1/jobs` 413 `file_too_large` |
| 模型庫服務暫時不可用請稍後再試」| promote File Access Agent 不可用 | `POST /promote` 502 `file_gateway_unavailable` |
| 轉檔還沒完成請等進度條到 100% 再加進模型庫」| promote job 還沒 `completed` | `POST /promote` 409 `job_not_ready_for_promote` |
| 你的登入已過期請重新登入」| visionA-backend user session 過期visionA 自己的 auth不是 Converter 的問題| visionA-backend 自己處理 |
| 系統錯誤請聯絡客服」| Member Center File Access Agent 完全無法連線 | `POST /api/v1/jobs` 503 `auth_service_unavailable` 或類似Phase 1 job 本身不依賴 FAAFAA 錯誤集中在 promote|
---
## 結語
這份跨系統流程圖揭露的關鍵 UX 訊息
1. **使用者只看到「在 VisionA 平台內按幾下就轉完」**背後有多個服務協作visionA-backend / Member Center / Converter / File Access Agent)— 這是架構要盡力維持的體驗值得注意的是 Phase 1 **建 job 階段只涉及 3 方**visionA-backend / Member Center / ConverterFile Access Agent 僅在 promote 階段參與簡化了上傳時的故障面
2. **Phase 1 的 UX 閉環卡在「下載」**需要 VisionA 產品團隊協調 messaging `design-review.md` 議題 #1
3. **Recovery 體驗是 VisionA 的 UX 優勢**但受限於Crash Reset設計不保證跨 Crash 存活 要誠實告知使用者
4. **錯誤訊息的人類可讀性直接決定使用者對系統的信任**Architect TDD 中要重視 error code 的結構化設計
5. **multipart 直連上傳的 UX 優勢**相較於舊設計visionA-backend FAA Converter 拉檔兩段式新設計從使用者按下上傳並轉檔 Converter job 成功只有一次網路傳輸上傳時間可用 progress bar 精準呈現不再有中間看不見的 Converter 拉檔等待