visionA/docs/autoflow/02-prd/features/feature-pairing.md
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

182 lines
7.0 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.

# FeaturePairing 流程P0雛形必做
> 父文件:[PRD.md](../PRD.md) | 對應 User StoriesUS-04、US-05、US-06、US-18、US-19
---
## 概述
Pairing 是 visionA Cloud 獨有的流程local-tool 沒有):把使用者筆電上的 local agent 連到 visionA Cloud 的 remote-proxy讓雲端能代管該裝置。
這個流程替代了 POC 中「Token = SHA256(MAC)[:16]」的硬編碼方式,改為**雲端發 token、綁 user + device、有 expiry、可撤銷**的產品化版本。
---
## 使用者行為
### 正向流程Happy Path
1. 使用者在瀏覽器登入 visionA Cloud
2. 在「裝置」頁面點「配對新裝置」
3. 彈出對話框,顯示:
- 一組 Pairing Token例如 `vAc_7f3c8e2a9b1d0f5e...`
- QR code方便手機掃或直接貼
- 說明文字:「在你的 local agent 貼上這個 token」
- 倒數計時「15 分鐘內要完成配對」
4. 使用者打開筆電上的 local-tool
5. Phase 0 妥協)手動編輯 local-tool 的設定檔,填入:
- `VISIONA_RELAY_URL=wss://relay.visiona.cloud`
- `VISIONA_PAIRING_TOKEN=vAc_7f3c8e2a9b1d0f5e...`
- 重啟 local-tool
6. local-tool 的 tunnel client 啟動,連到 remote-proxy
7. remote-proxy 驗證 token → 找到對應 user → 記錄 device 已配對
8. 雲端前端透過 WebSocket 收到「裝置上線」事件 → 即時更新裝置列表
9. 使用者看到新裝置出現,完成配對
### 異常流程
**A. Token 過期**
- 超過 15 分鐘未完成配對 → local-tool 連線時 remote-proxy 回 403
- local-tool 顯示「Pairing Token 已過期,請重新取得」
- 使用者回雲端重新產生
**B. Token 已被使用**
- Token 預設為一次性。配對成功後不能再用
- 再次用同一 token → 回 409 Conflict
- 雲端 UI 提示「此 token 已使用」
**C. Token 無效**
- 亂打 token → 401 Unauthorized
**D. 網路中斷後重連**
- local-tool 已配對的裝置tunnel 斷線後自動重連
- 重連時用的是 **Session Token長期**,不是 Pairing Token一次性
- Session Token 在首次配對成功後由 remote-proxy 發給 local-toollocal-tool 存到本機 config
---
## Token 設計
### Pairing Token一次性、短期
| 屬性 | 值 |
|------|---|
| 格式 | `vAc_` + 32 字元 hex範例`vAc_7f3c8e2a9b1d0f5e...`|
| 產生者 | api-server |
| 儲存 | Phase 0in-memory mapPhase 1DB |
| TTL | 預設 15 分鐘(可調整)|
| 使用次數 | 1 次 |
| 綁定 | user_id產生者|
### Session Token長期、可撤銷
| 屬性 | 值 |
|------|---|
| 格式 | `vAs_` + 64 字元 hex |
| 產生者 | remote-proxy首次 pairing 成功後發)|
| 儲存 | Phase 0in-memory mapPhase 1DB<br>local-tool 端:寫入 config 檔 |
| TTL | **90 天**(到期或使用者主動撤銷時失效)|
| 使用次數 | 無限TTL 內每次重連共用)|
| 綁定 | user_id + device_id |
> **兩階段 TTL 設計**
> - **Pairing Token 階段**:使用者在雲端產 token、貼到 local agent15 分鐘內要完成首次連線,一次性使用
> - **Session Token 階段**local agent 首次連上 remote-proxy 後,由 remote-proxy 發 Session Token 寫入 local config之後 tunnel 斷線重連、跨 session 維持長連線都用這把 token90 天內有效
>
> Phase 0 先做固定 90 天 TTLPhase 1 加 rotation到期前一段時間自動換新 token避免使用者介入
### 為什麼分兩種 Token
- Pairing Token 一次性、短期 → 防止 token 洩漏的危害被放大(最壞情況只影響 15 分鐘)
- Session Token 長期 → 避免每次重連都要使用者介入,但 90 天 TTL 限制洩漏風險
- 兩階段模式類似 OAuth 的 authorization code + refresh token
---
## 介面契約API 層面)
完整 API spec 由 Architect Agent 寫入 TDD本文件只列出關鍵端點
### POST `/api/pairing/generate`
**Request** (需登入)
```json
{}
```
**Response 200**
```json
{
"pairing_token": "vAc_7f3c8e2a9b1d0f5e...",
"expires_at": "2026-04-21T10:30:00Z",
"relay_url": "wss://relay.visiona.cloud/tunnel/connect"
}
```
### WebSocket `wss://relay.visiona.cloud/tunnel/connect?token={token}`
**流程**
1. local-tool 發起 WebSocket 連線,帶 token可能是 Pairing Token 或 Session Token
2. remote-proxy 驗證:
- 若是 Pairing Token檢查未過期、未使用 → 發 Session Token透過 WebSocket 首個 message 傳給 local-tool→ 標記 Pairing Token 已使用
- 若是 Session Token檢查未撤銷 → 接受連線
3. 建立 yamux session沿用 POC 的設計)
4. 後續所有 HTTP/WebSocket 請求透過 yamux stream 轉發到 local agent
### POST `/api/devices/{device_id}/revoke` Phase 1
**功能**:撤銷某 Session Token強制該裝置斷線。
---
## 驗收條件Phase 0
- [ ] 登入後,裝置頁面的「配對新裝置」按鈕可點
- [ ] 點擊後彈出對話框,顯示 Pairing Token明文 + QR code
- [ ] Pairing Token 格式符合規範(`vAc_` + 32 hex
- [ ] Pairing Token TTL = 15 分鐘,過期後 local-tool 連不上
- [ ] local-tool 用正確 token 連線 → 成功建立 tunnel
- [ ] local-tool 用錯誤 / 過期 / 已使用的 token 連線 → 收到明確錯誤
- [ ] 配對成功後,雲端裝置列表 5 秒內顯示新裝置
- [ ] local-tool 收到 Session Token 並寫入本機 config
- [ ] Session Token 格式符合規範(`vAs_` + 64 hex
- [ ] Session Token TTL = 90 天,到期後 local-tool 連線被拒,需重新 pairing
- [ ] tunnel 斷線後local-tool 用 Session Token 自動重連TTL 內)
- [ ] 全流程繁體中文 UI
- [ ] TODOPhase 0 不實作「撤銷」功能,但要在 UI 留按鈕disabled
---
## Phase 0 的 TODO
- **TODO 1**local-tool 端的整合 — Phase 0 先讓使用者手動編輯 config 檔Phase 1 要在 local-tool 內建 UI「配對到 visionA Cloud」
- **TODO 2**QR code 產生 — 可用前端套件(例如 `qrcode.react`),但優先級低,可先只顯示明文 token
- **TODO 3**Token 撤銷 — 介面留著,實作留到 Phase 1
- **TODO 4**:多 local agent 同時配對 — Phase 0 每個 user 最多 1 台 agent 同時連線Phase 1 支援多台
- **TODO 5**Session Token rotation — Phase 0 採固定 90 天 TTL到期需重新 pairingPhase 1 做到期前自動 rotation無需使用者介入
- **TODO 6**Pairing 流程的使用者引導tutorial — Phase 0 不做Phase 1 加 onboarding
---
## 安全考量
**Phase 0 最小要求**
- Token 必須透過 TLS`wss://`)傳輸,不能走明文
- Token 儲存在記憶體不要 log 出來
- Pairing Token 產生後不要再可讀取(只有產生當下顯示給使用者)
**Phase 1 要加的**
- Token 在 DB 以 hash 儲存(不存明文)
- Rate limiting防暴力破解
- IP 地址記錄(配對時、連線時)
- 異常偵測(同一 token 從不同 IP 嘗試連線)
---
## 連結
- 回:[PRD 索引](../PRD.md)
- 相關:[介面契約](../interface-contracts.md)、[非功能性需求](../nonfunctional.md)