jim800121chen fb7da5d180 chore(autoflow): migrate .autoflow/ 共享層文件至 docs/autoflow/
依 autoflow-agent workspace v2 設計把 PRD / 設計 / 架構 / 交付類
共享文件從個人層 .autoflow/(ignored)搬到 docs/autoflow/(進 git),
讓團隊可共享產品與架構文件,個人層只留 progress / review / testing 等
per-branch 筆記。

- 02-prd/        21 個檔(PRD、features、market-analysis 等)
- 03-design/     18 個檔(design-spec、wireframes、flows 等)
- 04-architecture/ 31 個檔(TDD、design-doc、ADR×14、API 規格等)
- 07-delivery/   3 個檔(project-summary、phase-0.6-handover、stage-deployment-setup)

合計 73 檔。原檔已從 .autoflow/ 移除(migration 工具執行 git mv,
但因 .autoflow/ 在 .gitignore 中、git 將此操作視為新增、無 rename history)。
2026-05-04 16:55:55 +08:00

336 lines
8.7 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.

# API Spec — 對前端的 REST + WebSocket 端點
> **base URL**`https://api.visiona.cloud`Phase 1/ `http://localhost:3001`(雛形)
> **認證**`Authorization: Bearer <JWT>`(雛形可省略,走 `StaticAuthService`
> **通用回應格式**
> ```json
> { "success": true, "data": {...} }
> { "success": false, "error": { "code": "ERR_CODE", "message": "..." } }
> ```
---
## 1. Auth雛形 stub
### POST `/api/auth/login`
- 雛形:回 `501 { code: "NOT_IMPLEMENTED" }`
- Phase 1`{ email, password }``{ user, access_token, refresh_token }`
### POST `/api/auth/register`
- 同上
### POST `/api/auth/logout`
- Phase 1清 refresh token
### GET `/api/auth/me`
- 雛形:回 `demo-user` hard-coded
- Phase 1從 JWT 取
---
## 2. Pairing
### POST `/api/pairing/token`
- Auth required雛形靜默通過
- 雛形 Response
```json
{ "success": false, "error": { "code": "NOT_IMPLEMENTED", "message": "Dev uses env VISIONA_PAIRING_TOKEN" } }
```
- Phase 1 Response
```json
{
"success": true,
"data": {
"token": "pk_AbCd1234...",
"expires_at": "2026-04-21T13:00:00Z"
}
}
```
### GET `/api/pairing/status`
- 查詢當前 user 的 tunnel 連線狀態
- Response:
```json
{
"success": true,
"data": {
"connected": true,
"connected_at": "2026-04-21T12:00:00Z",
"last_seen_at": "2026-04-21T12:34:56Z",
"device_id": "dev-xxx",
"agent_version": "local-tool 1.2.3"
}
}
```
### GET `/api/pairing/tokens`
- List 當前 user 的所有 tokens
- Phase 1回 array of `{ id, device_id, kind, created_at, last_seen_at }`
### DELETE `/api/pairing/tokens/:id`
- 撤銷指定 token
- Phase 1 實作;雛形 501
---
## 3. Devices
以下大部分端點**會被轉發到 local agent**。api-server 行為:
1. 檢查 user 有 tunnel 連線
2. 若 device_id 有傳,檢查 ownership
3. 透過 tunnel forward 請求到 local agent沿用 POC `handleProxy`
4. 回傳 local agent 的 response
路徑與回應格式**與 local-tool 相同**,前端改 base URL 即可。
### GET `/api/devices` — 列出當前本地掃到的裝置
### POST `/api/devices/scan` — 觸發重掃
### GET `/api/devices/:id` — 單一裝置
### POST `/api/devices/:id/connect`
### POST `/api/devices/:id/disconnect`
### POST `/api/devices/:id/flash` — 燒韌體(透過 tunnel
### POST `/api/devices/:id/inference/start`
### POST `/api/devices/:id/inference/stop`
**雲端特有(非 tunnel forward**
### GET `/api/cloud/devices` — 列出「我在雲端綁過的 Device records」
- 與 `GET /api/devices` 不同:這個是查雲端 DB不問 local agent
- 雛形:從 `InMemoryDeviceRepository` 回
- Response`[{ id, name, device_type, serial_number, status, last_seen_at }]`
### POST `/api/cloud/devices/:id/rename`
- 改雲端上的 device name
---
## 4. Models
### GET `/api/models` — 列出 user 的 model
- 雲端模型(存 storage+ preset models硬編碼
- Response
```json
{
"success": true,
"data": [
{
"id": "abc-123",
"name": "YOLOv5 Face",
"target_chip": "kl520",
"file_size": 12345678,
"source": "uploaded",
"created_at": "..."
}
]
}
```
### GET `/api/models/:id`
- Model 詳情
### POST `/api/models/init` — 初始化上傳
- Request: `{ name, file_size, checksum, target_chip, description? }`
- Response:
```json
{
"success": true,
"data": {
"model_id": "new-id",
"upload_url": "https://...presigned-put-url...",
"upload_expires_at": "..."
}
}
```
### POST `/api/models/:id/finalize`
- 在 presigned PUT 成功後呼叫
- api-server 驗證檔案已存在、size / checksum 對 → status 改 "ready"
### DELETE `/api/models/:id`
### POST `/api/models/:id/load-to-device`
- Body`{ device_id }`
- api-server 產 presigned GET URL → 透過 tunnel 送 local agent 「下載並載入」
- 回傳 job status
---
## 5. Clusters從 POC 搬)
### GET `/api/clusters`
### POST `/api/clusters`
- Body: `{ name, device_ids: [...] }`
### GET `/api/clusters/:id`
### DELETE `/api/clusters/:id`
### POST `/api/clusters/:id/devices`
### DELETE `/api/clusters/:id/devices/:deviceId`
### PUT `/api/clusters/:id/devices/:deviceId/weight`
### POST `/api/clusters/:id/flash`
### POST `/api/clusters/:id/inference/start`
### POST `/api/clusters/:id/inference/stop`
---
## 6. Camera / Media
與 local-tool 相同,全部透過 tunnel forward
### GET `/api/camera/list`
### POST `/api/camera/start`
### POST `/api/camera/stop`
### GET `/api/camera/stream` — MJPEG透過 tunnel streaming
### POST `/api/media/upload/image`
### POST `/api/media/upload/video`
### POST `/api/media/upload/batch-images`
### GET `/api/media/batch-images/:index`
### POST `/api/media/seek`
---
## 7. System
### GET `/api/system/health`
- 雲端側:回 api-server 自己的健康 + tunnel 連線狀態
```json
{
"success": true,
"data": {
"api_server": "ok",
"tunnel_connected": true,
"agent_last_seen_at": "..."
}
}
```
### GET `/api/system/info`
- 版本資訊
---
## 8. Converter
### 8.1 Phase 1 stub既有保留
> 雛形 stub 路由Phase 0.8 的真實整合改走 §8.2 `/api/conversion/*`,下列路由保留為 placeholder 待 Phase 1 視需要 supersede。
#### POST `/api/converter/jobs`
- Body`{ source_model_key, target_chip, params? }`
- Response`{ job_id, status: "queued" }`
#### GET `/api/converter/jobs`
- List user 的 jobs
#### GET `/api/converter/jobs/:id`
- Job 狀態
#### GET `/api/converter/jobs/:id/download`
- 下載產物presigned URL redirect
**詳細契約** → [`api-converter-contract.md`](api-converter-contract.md)
### 8.2 Phase 0.8 — `/api/conversion/*`(轉檔功能整合)
正式對接 kneron_model_converter scheduler + FAA delegated download
- `POST /api/conversion/init` — multipart streaming proxy 到 converter建 job
- `GET /api/conversion/{job_id}` — 查狀態HTTP pollingfrontend 間隔 2s
- `POST /api/conversion/{job_id}/promote-to-models` — 「加到模型庫」
- `POST /api/conversion/{job_id}/download-token` — 換 browser 直連 FAA 的 delegated URL
- `GET /api/conversion/active` — 查當前 user 是否有 active job
**詳細契約** → [`api-conversion.md`](api-conversion.md)
**內部設計** → [`../conversion.md`](../conversion.md)
**ADR** → [`../adr/adr-014-conversion-integration.md`](../adr/adr-014-conversion-integration.md)
---
## 9. WebSocket
### WS `/ws/devices/events`
- 訂閱「裝置上下線」事件
- Server push
```json
{ "type": "device.connected", "device_id": "xxx", "at": "..." }
{ "type": "device.disconnected", "device_id": "xxx", "at": "..." }
```
### WS `/ws/devices/:id/flash-progress`
- 燒錄進度(透過 tunnel 從 local agent 取)
### WS `/ws/devices/:id/inference`
- 推論結果串流
### WS `/ws/server-logs`
- log broadcast沿用 local-tool 的 broadcaster
### WS `/ws/system`
- 系統事件server:shutdown-imminent 等)
### WS `/ws/clusters/:id/inference`
### WS `/ws/clusters/:id/flash-progress`
### WS `/ws/pairing/status`(新)
- 訂閱 tunnel 連線狀態變化
- Server push
```json
{ "type": "tunnel.connected", "connected_at": "..." }
{ "type": "tunnel.disconnected", "reason": "network_error", "at": "..." }
```
---
## 10. Storage雛形 LocalFS 代理)
### GET `/storage/*filepath?expires=...&signature=...`
- LocalFS 的假 presigned GET
- 驗簽後讀檔回傳
### PUT `/storage/*filepath?expires=...&signature=...`
- LocalFS 的假 presigned PUT
- 驗簽後收 body 寫檔
**Phase 1**:直接由 S3 提供,不走 api-server。
---
## 11. 錯誤碼清單
| Code | HTTP | 說明 |
|------|------|------|
| `UNAUTHORIZED` | 401 | 未認證或 token 無效 |
| `FORBIDDEN` | 403 | 權限不足 |
| `NOT_FOUND` | 404 | 資源不存在 |
| `VALIDATION_FAILED` | 400 | 輸入驗證失敗 |
| `TUNNEL_DISCONNECTED` | 502 | Local agent 未連線 |
| `TUNNEL_ERROR` | 502 | Tunnel 傳輸錯誤 |
| `NOT_IMPLEMENTED` | 501 | 雛形尚未實作 |
| `RATE_LIMITED` | 429 | 請求過快Phase 1|
| `INTERNAL_ERROR` | 500 | 未預期錯誤 |
---
## 12. Pagination
對會變大的 listmodels、devices、jobs用 cursor-based
```
GET /api/models?limit=50&cursor=...
Response:
{ "data": [...], "next_cursor": "..." | null }
```
雛形可先簡單回全部in-memoryPhase 1 接 DB 時實作 cursor。
---
**雛形 MVP 清單**(必須有):
- `GET /api/system/health`
- `GET /api/pairing/status`
- `GET /api/devices` + 透過 tunnel forward
- `GET /api/models` + `POST /api/models/init` + `/finalize`LocalFS
- `/storage/*` 代理
- WS `/ws/devices/events`
- WS `/ws/pairing/status`
其他可以先 501 或 stub。