From a880c99857d174c5f8e38fc82865d2c0ee33a0e8 Mon Sep 17 00:00:00 2001 From: Chris Date: Sun, 29 Mar 2026 23:15:15 +0800 Subject: [PATCH] docs: add frontend handoff architecture and index --- docs/ARCHITECTURE_AND_CONFIG.md | 8 +- docs/FRONTEND_API_CONTRACT.md | 120 ++++++++++++++++++++++ docs/FRONTEND_ARCHITECTURE.md | 114 ++++++++++++-------- docs/FRONTEND_IMPLEMENTATION_CHECKLIST.md | 29 ++++++ docs/index.md | 17 +++ 5 files changed, 243 insertions(+), 45 deletions(-) create mode 100644 docs/FRONTEND_API_CONTRACT.md create mode 100644 docs/FRONTEND_IMPLEMENTATION_CHECKLIST.md create mode 100644 docs/index.md diff --git a/docs/ARCHITECTURE_AND_CONFIG.md b/docs/ARCHITECTURE_AND_CONFIG.md index 2043093..9126d33 100644 --- a/docs/ARCHITECTURE_AND_CONFIG.md +++ b/docs/ARCHITECTURE_AND_CONFIG.md @@ -7,12 +7,18 @@ 3. `docs/FRONTEND_ARCHITECTURE.md` ## 文件地圖 +- `docs/index.md` + - 前端開工入口(給前端 AI 的第一份) - `docs/BACKEND_BOOTSTRAP.md` - 後端啟動步驟(環境、安裝、建表、啟動) - `docs/BACKEND_ARCHITECTURE.md` - memberapi 後端模組、資料流、API、安全策略 - `docs/FRONTEND_ARCHITECTURE.md` - - member 前端架構(由前端 AI 接手) + - member 前端架構(可直接開工版) +- `docs/FRONTEND_API_CONTRACT.md` + - 前端 API request/response 契約 +- `docs/FRONTEND_IMPLEMENTATION_CHECKLIST.md` + - 前端實作與交付核對清單 - `docs/API_CLIENTS_SQL.sql` - `api_clients` 白名單表與初始資料 SQL diff --git a/docs/FRONTEND_API_CONTRACT.md b/docs/FRONTEND_API_CONTRACT.md new file mode 100644 index 0000000..0b257d9 --- /dev/null +++ b/docs/FRONTEND_API_CONTRACT.md @@ -0,0 +1,120 @@ +# Frontend API Contract(memberapi) + +Base URL:`https://memberapi.ose.tw` + +## 1. 使用者資訊 +### GET `/me` +Headers: +- `Authorization: Bearer ` + +200 Response: +```json +{ + "sub": "authentik-sub-123", + "email": "user@example.com", + "display_name": "User Name" +} +``` + +401 Error: +```json +{ "detail": "missing_bearer_token" } +``` +或 +```json +{ "detail": "invalid_bearer_token" } +``` + +## 2. 我的權限快照 +### GET `/me/permissions/snapshot` +Headers: +- `Authorization: Bearer ` + +200 Response: +```json +{ + "authentik_sub": "authentik-sub-123", + "permissions": [ + { + "scope_type": "site", + "scope_id": "tw-main", + "module": "campaign", + "action": "view" + } + ] +} +``` + +## 3. Grant 權限 +### POST `/admin/permissions/grant` +Headers: +- `X-Client-Key: ` +- `X-API-Key: ` + +Request: +```json +{ + "authentik_sub": "authentik-sub-123", + "email": "user@example.com", + "display_name": "User Name", + "scope_type": "site", + "scope_id": "tw-main", + "module": "campaign", + "action": "view" +} +``` + +200 Response: +```json +{ + "permission_id": "uuid", + "result": "granted" +} +``` + +## 4. Revoke 權限 +### POST `/admin/permissions/revoke` +Headers: +- `X-Client-Key: ` +- `X-API-Key: ` + +Request: +```json +{ + "authentik_sub": "authentik-sub-123", + "scope_type": "site", + "scope_id": "tw-main", + "module": "campaign", + "action": "view" +} +``` + +200 Response: +```json +{ + "deleted": 1, + "result": "revoked" +} +``` + +404 Response: +```json +{ "detail": "user_not_found" } +``` + +## 5. Health Check +### GET `/healthz` +200 Response: +```json +{ "status": "ok" } +``` + +## 6. 常見錯誤碼 +- `401 invalid_client` +- `401 invalid_api_key` +- `401 client_expired` +- `403 origin_not_allowed` +- `403 ip_not_allowed` +- `403 path_not_allowed` +- `503 internal_secret_not_configured` +- `503 authentik_admin_not_configured` diff --git a/docs/FRONTEND_ARCHITECTURE.md b/docs/FRONTEND_ARCHITECTURE.md index 408e0d7..93be8e9 100644 --- a/docs/FRONTEND_ARCHITECTURE.md +++ b/docs/FRONTEND_ARCHITECTURE.md @@ -1,55 +1,81 @@ -# member.ose.tw 前端架構(Vue) +# member.ose.tw 前端架構(可直接開工版) -## 1. 角色定位 -- 網域:`member.ose.tw` -- 功能:會員中心前台(管理 users/公司/站台/權限) -- 注意:密碼流程不在這裡做,自動導 Authentik flow +## 1. 前端責任邊界 +- 站點:`member.ose.tw` +- 主要責任: + - 顯示目前登入使用者資訊 + - 顯示目前使用者權限快照 + - 透過管理 API 執行 grant/revoke +- 不處理: + - Authentik 管理 API 直連 + - 密碼重設流程(導向 Authentik) -## 2. 技術棧 -- `Vue 3 + Vite` -- `Element Plus` -- `Tailwind CSS` -- `Vue Router` -- `Pinia`(建議) +## 2. 建議技術堆疊 +- Vue 3 + Vite + TypeScript +- Vue Router +- Pinia +- Axios +- Element Plus + Tailwind -## 3. 建議目錄 +## 3. 建議目錄結構 - `frontend/src/main.ts` -- `frontend/src/router/` +- `frontend/src/router/index.ts` - `frontend/src/stores/` -- `frontend/src/api/`(axios client + modules) + - `auth.ts`:token、me、登入狀態 + - `permission.ts`:snapshot 與快取 +- `frontend/src/api/` + - `http.ts`:axios instance + interceptor + - `me.ts` + - `permission-admin.ts` - `frontend/src/pages/` - - `users/` - - `companies/` - - `sites/` - - `permissions/` -- `frontend/src/components/` + - `profile/MePage.vue` + - `permissions/PermissionSnapshotPage.vue` + - `permissions/PermissionAdminPage.vue` +- `frontend/src/types/` + - `api.ts` -## 4. 第一版頁面 -- 使用者列表/搜尋 -- 公司列表 -- 站台列表 -- 權限指派(user x scope x module x action) +## 4. 路由規劃(第一版) +- `/me` + - 顯示 `GET /me` 資料 +- `/me/permissions` + - 顯示 `GET /me/permissions/snapshot` +- `/admin/permissions` + - grant/revoke 表單與結果顯示 -## 5. 權限與登入 -- 透過 Authentik OIDC 登入 -- 前端持有 backend session/token,不直接操作 Authentik admin API -- 「修改密碼 / 忘記密碼」按鈕導 Authentik 使用者流程頁 +## 5. Token 與 Header 策略 +- 使用者路由(`/me*`) + - header: `Authorization: Bearer ` +- 管理路由(`/admin*`) + - headers: + - `X-Client-Key` + - `X-API-Key` +- 建議: + - 使用 axios request interceptor 統一注入 header + - 401 時統一導向登入或刷新流程 -## 6. API 串接 -- `VITE_API_BASE_URL=https://memberapi.ose.tw` -- 所有請求帶上必要 auth header -- 管理操作走 `memberapi` 的 admin 路由 +## 6. 狀態管理最小模型 +- `auth store` + - `accessToken: string | null` + - `me: { sub, email, display_name } | null` + - actions: `setToken`, `fetchMe`, `logout` +- `permission store` + - `snapshot: { authentik_sub, permissions[] } | null` + - actions: `fetchMySnapshot`, `grantPermission`, `revokePermission` -## 7. UI/互動規則 -- Element Plus 做表單/表格/對話框 -- Tailwind 做 spacing/layout/快速樣式 -- 權限編輯畫面要清楚顯示: - - scope_type(company/site) - - scope_id - - module - - action(view/edit) +## 7. 錯誤處理規則 +- `401` + - 使用者 token 過期或無效,導回登入 +- `403` + - API client 白名單限制(origin/ip/path) +- `404` + - revoke 時 user 不存在 +- `503` + - 後端必要設定缺失(例如 internal secret / authentik admin) -## 8. 第一版不做項目 -- 不做密碼重設畫面 -- 不做複雜儀表板 -- 不做跨系統 SSO 管理 UI +## 8. 開工順序(建議) +1. 建立 axios client 與 interceptor +2. 完成 `/me` 與 `/me/permissions` 畫面 +3. 完成 grant/revoke 表單 +4. 補通知、loading、錯誤提示 + +詳細 request/response 契約請看 `docs/FRONTEND_API_CONTRACT.md`。 diff --git a/docs/FRONTEND_IMPLEMENTATION_CHECKLIST.md b/docs/FRONTEND_IMPLEMENTATION_CHECKLIST.md new file mode 100644 index 0000000..bbd6902 --- /dev/null +++ b/docs/FRONTEND_IMPLEMENTATION_CHECKLIST.md @@ -0,0 +1,29 @@ +# Frontend Implementation Checklist + +## A. 專案初始化 +- [ ] 建立 `src/api/http.ts` +- [ ] 建立 `src/stores/auth.ts` +- [ ] 建立 `src/stores/permission.ts` +- [ ] 配置 `VITE_API_BASE_URL` + +## B. API 對接 +- [ ] `GET /me` +- [ ] `GET /me/permissions/snapshot` +- [ ] `POST /admin/permissions/grant` +- [ ] `POST /admin/permissions/revoke` + +## C. 頁面 +- [ ] Me 頁面(顯示 sub/email/display_name) +- [ ] 我的權限頁(表格) +- [ ] 權限管理頁(grant/revoke) + +## D. 行為驗證 +- [ ] Bearer token 遺失時顯示重新登入 +- [ ] grant 成功後自動刷新 snapshot +- [ ] revoke 成功後自動刷新 snapshot +- [ ] 404 user_not_found 顯示可讀錯誤訊息 + +## E. 交付條件 +- [ ] 三個頁面都可獨立刷新 +- [ ] 所有 API 錯誤碼都有 UI 提示 +- [ ] 主要操作有 loading 與成功提示 diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 0000000..8e06ba7 --- /dev/null +++ b/docs/index.md @@ -0,0 +1,17 @@ +# member docs index + +## 先看這三份 +1. `docs/FRONTEND_ARCHITECTURE.md` +2. `docs/FRONTEND_API_CONTRACT.md` +3. `docs/FRONTEND_IMPLEMENTATION_CHECKLIST.md` + +## 系統架構與後端 +- `docs/ARCHITECTURE_AND_CONFIG.md` +- `docs/BACKEND_ARCHITECTURE.md` +- `docs/BACKEND_BOOTSTRAP.md` + +## SQL 與配置 +- `docs/API_CLIENTS_SQL.sql` + +## 給前端 AI 的一句話交接 +請先完成 `/me`、`/me/permissions/snapshot`、`/admin/permissions/grant|revoke` 三組 API 對接,並依 `FRONTEND_IMPLEMENTATION_CHECKLIST.md` 逐項完成。