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

430 lines
17 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 Cloud
> **Phase 0 雛形範圍**:僅做低保真 stub表單 + 按鈕 + 路由),**不接後端認證**。使用者送出登入 / 註冊表單後直接跳轉到目標頁即可。
>
> 完整 auth 流程OAuth、2FA、密碼重設、Email 驗證、ToS / Privacy Policy、rate limit 等)**Phase 1+ 再設計**。
>
> 本檔記錄 Phase 0 雛形規格 + Phase 1+ TODO。
---
## 1. 雛形範圍決策
| 項目 | Phase 0 | Phase 1 TODO |
|------|---------|-------------|
| 登入表單 UI | ✅ 做 | 完整化 |
| 註冊表單 UI | ✅ 做 | 完整化 |
| 登入 API 串接 | ❌ 不做(直接跳轉)| 做 |
| 註冊 API 串接 | ❌ 不做 | 做 |
| OAuthGoogle / GitHub| ❌ 不做 | 做 |
| 密碼強度驗證 | ❌ 不做 | 做 |
| Email 驗證 | ❌ 不做 | 做 |
| 密碼重設 | ❌ 不做 | 做 |
| 2FA | ❌ 不做 | 做Phase 2 |
| ToS / Privacy Policy 勾選 | ❌ 不做 | 做 |
| 社群登入 | ❌ 不做 | 做Phase 2 |
| Rate Limit 提示 | ❌ 不做 | 做 |
| 帳號鎖定機制 | ❌ 不做 | 做 |
---
## 1.1 雛形 Auth 行為(三方一致)
Phase 0 **不接後端認證**,三方已對齊行為如下(對應 Reviewer C3
| 項目 | Phase 0 行為 |
|------|-------------|
| 登入表單送出 | HTML5 驗證通過後 → `router.push('/')`**不**打 API**不**做身分驗證 |
| 註冊表單送出 | 同上 → `router.push('/')` |
| Session / Token | 不存(前端不發、不讀);重新整理依然可進任何頁面 |
| 登出按鈕 | 點擊 → `router.push('/login')`,不清 session本來就沒存 |
| 受保護路由 | 雛形期所有 `/*` 路由對匿名使用者開放,**不做**導向 /login |
### 1.2 雛形 Banner全域
為了避免 demo 被誤認為正式版本,所有已登入的主畫面(`(main)/layout.tsx`)頂部顯示常駐 Banner
```
┌─────────────────────────────────────────────────────────────┐
│ 🚧 雛形版本 · 登入僅為 UI 示意,未實作身分驗證;資料皆為假資料 │
└─────────────────────────────────────────────────────────────┘
```
**規格:**
- 位置:`Header` 正下方,`sticky top-14 z-30`(在 `NetworkErrorBanner z-40` 之下,以利網路錯誤優先)
- 樣式:`bg-amber-100 dark:bg-amber-900/40 text-amber-900 dark:text-amber-100 border-b border-amber-300`
- 文字:`text-xs font-medium text-center py-1.5`
- 圖示:`Construction` / `Wrench`Lucide`h-3.5 w-3.5`
- 可關閉?**不可關閉**(雛形階段要讓使用者持續意識到)
- `role="status"` + `aria-label="雛形版本提示"`
- 響應式Mobile 文字改為「🚧 雛形版本demo」縮短版
### 1.3 i18n key雛形 Banner
```
prototype.banner.label → 雛形版本 · 登入僅為 UI 示意,未實作身分驗證;資料皆為假資料
prototype.banner.short → 雛形版本demo
prototype.banner.ariaLabel → 雛形版本提示
```
---
## 2. 路由與 Layout
```
app/
├── (auth)/
│ ├── layout.tsx ← 無 Sidebar / Header 的獨立 layout
│ ├── login/page.tsx ← /login
│ └── register/page.tsx ← /register
├── (main)/
│ ├── layout.tsx ← 有 Sidebar / Header 的主 layout既有
│ ├── page.tsx ← /
│ ├── devices/...
│ └── ...
└── layout.tsx ← root layoutThemeSync / LangSync / Toaster
```
**`(auth)/layout.tsx` 規格:**
- 無 Sidebar、無 Header
- 全螢幕 `min-h-screen``bg-background`
- 內容置中:`flex items-center justify-center`
- 無 padding wrapper頁面自己處理
---
## 3. `/login` — 登入頁
### 3.1 視覺Phase 0
```
┌────────────────────────────────────────────────────────┐
│ │
│ │
│ [Logo] visionA Cloud │
│ Edge AI Platform │
│ │
│ ┌──────────────────────────────────────┐ │
│ │ Email │ │
│ │ ┌──────────────────────────────────┐ │ │
│ │ │ you@example.com │ │ │
│ │ └──────────────────────────────────┘ │ │
│ │ │ │
│ │ 密碼 │ │
│ │ ┌──────────────────────────────────┐ │ │
│ │ │ •••••••• │ │ │
│ │ └──────────────────────────────────┘ │ │
│ │ │ │
│ │ [ 登入 ] │ │
│ │ │ │
│ │ ──────── 還沒有帳號? ───────── │ │
│ │ │ │
│ │ [ 建立新帳號 ] │ │
│ └──────────────────────────────────────┘ │
│ │
│ 忘記密碼? | 語言:繁中 ▾ │
│ │
└────────────────────────────────────────────────────────┘
```
### 3.2 規格
- **容器**`max-w-md w-full mx-auto px-4`
- **品牌區**
- Logo`h-12 w-12 rounded-lg`
- 產品名:`text-2xl font-bold`
- 副標題:`text-sm text-muted-foreground`
- 區塊間距:`space-y-2 mb-8`
- **Card**:既有 `Card` + `CardContent``py-8 px-6`
- **表單區塊**`space-y-4`
- **Input**:既有 shadcn`type="email"` / `type="password"` 搭配 `autoComplete`
- **登入按鈕**`w-full` + `variant=default` + `size=default`
- **分隔線 + 建立帳號**
- `Separator` + 中間文字(使用 Tailwind 的 flex center hack
- 建立帳號 `Button variant=outline w-full`
- **底部**
- 「忘記密碼?」:`Button variant=link size=sm`disabled
- 語言切換:輕量化 Select僅 2 選項)
### 3.3 行為Phase 0 簡化)
```tsx
async function handleLogin(e: FormEvent) {
e.preventDefault();
// Phase 0: 不接 API直接跳 dashboard
// Phase 1: const res = await api.post('/auth/login', { email, password })
router.push('/');
}
```
- 表單用 HTML5 `required`Phase 0
- 無 loading statePhase 1+
- 無 error statePhase 1+
- 送出直接跳 `/`
### 3.4 鍵盤行為
- Tab 順序Email → Password → 登入 → 建立新帳號 → 忘記密碼 → 語言
- Email 或 Password focused 時 Enter → 提交表單
- 「建立新帳號」Enter / Space 導航到 `/register`
- 語言切換Space 開啟 SelectArrow 選擇Enter 確認
### 3.5 響應式
- Mobile`px-4` 確保左右留白;其他結構不變
- Tablet / Desktop置中`max-w-md` 限寬
### 3.6 i18n key
```
auth.login.title → 登入
auth.login.subtitle → 歡迎回到 visionA Cloud
auth.login.email → Email
auth.login.emailPlaceholder → you@example.com
auth.login.password → 密碼
auth.login.submit → 登入
auth.login.submitting → 登入中...
auth.login.forgotPassword → 忘記密碼?
auth.login.noAccount → 還沒有帳號?
auth.login.createAccount → 建立新帳號
```
---
## 4. `/register` — 註冊頁
### 4.1 視覺Phase 0
```
┌────────────────────────────────────────────────────────┐
│ │
│ [Logo] visionA Cloud │
│ Edge AI Platform │
│ │
│ ┌──────────────────────────────────────┐ │
│ │ 建立帳號 │ │
│ │ │ │
│ │ Email │ │
│ │ [____________________________________] │ │
│ │ │ │
│ │ 密碼 │ │
│ │ [____________________________________] │ │
│ │ │ │
│ │ 確認密碼 │ │
│ │ [____________________________________] │ │
│ │ │ │
│ │ [ 建立帳號 ] │ │
│ │ │ │
│ │ ──────── 已經有帳號? ────────── │ │
│ │ │ │
│ │ [ 登入 ] │ │
│ └──────────────────────────────────────┘ │
│ │
│ 語言:繁中 ▾ │
│ │
└────────────────────────────────────────────────────────┘
```
### 4.2 規格差異(相對 /login
- 新增「確認密碼」欄位
- 「建立帳號」按鈕取代「登入」
- 底部連結改為「已經有帳號? → 登入」
### 4.3 驗證規則Phase 0 最小化)
- EmailHTML5 `type="email" required`
- 密碼:`required`**不驗證強度**
- 確認密碼失去焦點時比對client-side不符則顯示紅框 + 下方文字
**簡單驗證範例:**
```tsx
const [confirmError, setConfirmError] = useState('');
function handleConfirmBlur() {
if (password && confirm && password !== confirm) {
setConfirmError(t('auth.register.passwordMismatch'));
} else {
setConfirmError('');
}
}
```
顯示:`<Input aria-invalid={!!confirmError}>` + `<p className="text-xs text-destructive">{confirmError}</p>`
### 4.4 行為Phase 0 簡化)
```tsx
async function handleRegister(e: FormEvent) {
e.preventDefault();
if (password !== confirm) {
setConfirmError(t('auth.register.passwordMismatch'));
return;
}
// Phase 0: 不接 API直接引導到 pairing
router.push('/devices/pair');
}
```
**註冊成功後的導航**:跳 `/devices/pair` 引導第一次配對(避免使用者看到空白 Dashboard
### 4.5 i18n key
```
auth.register.title → 建立帳號
auth.register.subtitle → 開始使用 visionA Cloud
auth.register.email → Email
auth.register.password → 密碼
auth.register.confirmPassword → 確認密碼
auth.register.passwordMismatch → 兩次輸入的密碼不一致
auth.register.submit → 建立帳號
auth.register.submitting → 建立中...
auth.register.hasAccount → 已經有帳號?
auth.register.signIn → 登入
```
---
## 5. 登入狀態管理Phase 0 雛形)
### 5.1 `useAuthStore`Zustand
**目的**Phase 0 讓前端能在「未登入 / 已登入」兩個狀態間切換,即使後端沒接。
```typescript
interface AuthStore {
user: { email: string; displayName?: string } | null;
isAuthenticated: boolean;
login: (email: string) => void; // Phase 0: 只存 localStorage
logout: () => void;
}
```
**Phase 0 簡化實作**
- `login(email)`:設 `user = { email }``isAuthenticated = true`、存 `localStorage`
- `logout()`:清空、跳 `/login`
- Hydration頁面載入從 `localStorage` 恢復狀態
**Phase 1 升級**:改為真正的 JWT / Session cookie`login` 會呼叫 API、存 token`logout` 會呼叫 API 使 token 失效。
### 5.2 路由保護Phase 0 Middleware
**最簡版**:在 `(main)/layout.tsx` 或 Root 層加 hook
```tsx
'use client';
function MainLayout({ children }) {
const { isAuthenticated } = useAuthStore();
const router = useRouter();
useEffect(() => {
if (!isAuthenticated) router.replace('/login');
}, [isAuthenticated]);
// ... 顯示 Sidebar + Header + children
}
```
**注意**Phase 0 保護邏輯很弱(只是 client-side redirect**不是真正的安全機制**。任何直接 API 請求都應該由後端驗證。
---
## 6. 登出流程
**觸發點**
- Sidebar 底部 `UserMenu` → 「登出」
- `/account` 頁面(未來)
- Session 過期自動觸發Phase 1+
**行為Phase 0**
1. `useAuthStore.logout()`
2. 清空 localStorage 的 `user`
3. 顯示 toast「已登出」
4. `router.push('/login')`
**Phase 1+**
- 呼叫 `POST /api/auth/logout` 讓 token 失效
- 清除所有 cookies
- 若有未儲存的資料,顯示確認 Dialog
---
## 7. 首次登入的引導
**使用者第一次登入完成後**(有個好方法:**從註冊頁進來的**
- 註冊後跳 `/devices/pair`(引導第一次配對)
- Dashboard 的 `OnboardingDialog`local-tool 既有版本假設 USB Dongle**Phase 0 雲端版暫時 disable**
- Phase 1 做新的雲端版 Onboarding「歡迎來到 visionA Cloud — 讓我們先配對你的第一台裝置」→ 跳 `/devices/pair`
---
## 8. 錯誤情境Phase 1 再實作)
雛形不做,但在這裡列出 Phase 1 要處理的情境:
| 情境 | UI 回饋 |
|------|---------|
| 密碼錯誤 | Input 下方紅字「Email 或密碼不正確」(不明說哪個錯,避免 enumeration attack |
| Email 不存在 | 同上 |
| 帳號被鎖(短時間內失敗太多次)| 顯示「此帳號暫時被鎖定,請 15 分鐘後再試」 |
| Email 已被註冊(註冊時)| Input 下方紅字「此 Email 已被使用」 |
| 密碼強度不足 | 密碼下方即時顯示強度指示器 |
| 網路錯誤 | Toast「連線失敗請稍後再試」 |
| ToS 未勾選 | Button disabled + 紅字提示 |
---
## 9. 安全考量(給 Architect
雛形不做,但 Phase 1 必須:
- 密碼 hashbcrypt / argon2
- TokenJWTshort-lived access + refresh或 session cookiehttpOnly + secure + SameSite
- CSRF 保護
- XSS 防護Content-Security-Policy header
- Rate Limit失敗登入 N 次鎖定 X 分鐘)
- 密碼政策(最少長度、需字母 + 數字等,視法規要求)
- 記錄登入來源 IP / User-Agent/account/sessions 頁面顯示)
---
## 10. 無障礙
- 所有表單 `<label htmlFor>``<input id>` 對應
- `autoComplete` 正確設定(`email` / `current-password` / `new-password`
- 錯誤訊息用 `aria-describedby` 指向 input
- Tab 順序符合視覺順序
- Enter 可提交表單
- Focus ring 清晰可見shadcn 預設達標)
- 密碼欄不使用 `aria-live`(避免 SR 念密碼)
---
## 11. 設計示意(給 Frontend Agent 參考既有 Shadcn Auth 模板)
Shadcn 官方有 `auth-01` / `auth-02` 等區塊範例。可參考:
- https://ui.shadcn.com/blocksAuthentication 分類)
**選擇 `auth-01` 或 `auth-04` 風格**(左側表單 + 右側品牌區或全螢幕置中)。雛形建議**全螢幕置中**(更簡潔)。
Phase 1 可升級為左右分欄 + 右側行銷訊息 / 圖片。
---
## 12. Phase 1+ TODO完整清單
| 項目 | 重要性 |
|------|-------|
| OAuthGoogle、GitHub、Microsoft | 高 |
| Email 驗證流程 | 高 |
| 密碼重設Email 連結 → 重設頁)| 高 |
| 密碼強度指示器 | 高 |
| ToS / Privacy Policy 勾選 | 高(法規) |
| Remember me 選項 | 中 |
| 防機器人reCAPTCHA / Turnstile | 中 |
| Rate limit 提示 UI | 中 |
| 2FATOTP / WebAuthn / SMS| 中Phase 2|
| SSO for 企業SAML| 低Phase 2+|
| Magic linkpasswordless| 低Phase 2|
| 登入行為分析 / 異常偵測 | 低Phase 2+|