warrenchen e77fdec76b feat: add FileAccessDownloadToken entity and migration
- Introduced the FileAccessDownloadToken entity with properties for managing file access tokens.
- Created a migration to add the file_access_download_tokens table to the database with appropriate constraints and indexes.
2026-04-24 16:27:31 +09:00

148 lines
7.9 KiB
Markdown
Raw Permalink 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.

# Flows
流程以「API 自建 UI」與「會員中心統一 UI」兩種模式描述。
## F-01 註冊會員
- [API] 站點送出 `POST /auth/register`
- [API] 會員中心建立 user、寄送驗證信
- [UI] 導向會員中心註冊頁完成註冊
- [UI] 會員中心寄送驗證信
## F-02 登入OAuth2 + OIDC
- [API] 站點送出 `POST /auth/login` 取得 access_token + id_token
- [API] 站點建立自身 session
- [UI] 使用 `usage=web_login` OAuth client導向 `/oauth/authorize` 完成 Authorization Code + PKCE
- [UI] 若未登入,會員中心會導向 Web login登入後回到原 authorize request
- [UI] 站點用 code + code_verifier 換 token
- [UI] `web_login` 可使用 public client不要求 client secret必須設定 redirect URI
- [UI] 若 Web 與 API 不同 origin需設定 `Auth:WebLoginUrl`,且 Web 端需允許導回 `Auth:Issuer``Auth:AllowedLoginReturnUrlPrefixes`
- [UI] 若 Web 與 API 位於不同子網域,需設定 `Auth:CookieDomain`,讓 authorize endpoint 可讀取 Web login cookie
## F-02a 登出(外站 direct logout
- [UI] 外站將瀏覽器導向 Member Center Web `/account/logout`
- [UI] Member Center 清除 Web login cookie / session
- [UI] 若帶 `returnUrl`Member Center 僅允許導回本站 local URL 或 allowlist 內的外站 URL
- [UI] 登出完成後導回外站 callback
- [UI] 外站 callback 清除本站 session / token
## F-02b 內容站台呼叫 Send EngineClient Credentials + JWT 驗簽)
- [API] 內容站台以 `client_credentials` 呼叫 `POST /oauth/token` 取得 access_token`usage=send_api`
- [API] 內容站台帶 Bearer token 呼叫 Send Engine 建立發送任務
- [API] Send Engine 以 Member Center JWKS 驗簽 token
- [API] 驗證 `scope/tenant_id/exp` 通過後才受理任務
## F-02c 檔案上傳A service -> File Space
- [API] `A service``client_credentials` 向 Member Center 取得 access token
- [API] token 需包含 `files:upload.write`
- [API] token 應包含 `tenant_id`,並以 `aud=file_access_api` 為目標資源
- [API] `A service` 帶 token 呼叫 access agent / file space 上傳檔案
- [API] access agent 以 JWKS 驗簽 JWT並驗 `iss/aud/exp/scope/tenant_id`
## F-02d 檔案下載A service -> client -> File Space
- [API] client 向 `A service` 請求下載檔案
- [API] `A service` 以自己的商業邏輯驗證該 user 是否可讀取指定檔案
- [API] `A service``files:download.delegate` 呼叫 Member Center `POST /file-access/download-tokens` 取得短效 download token
- [API] download token 由 Member Center 簽發,至少綁定 `tenant_id + user_id + file_id/object_key + method=GET + exp`
- [UI/API] `A service` 將帶短效 token 的下載 URL 回給 client
- [UI/API] client 直接向 access agent / file space 請求檔案
- [API] access agent 以 `files:download.read` 呼叫 Member Center `POST /file-access/download-tokens/validate`,確認 token 與實際 GET request 邊界一致後放行
註記:下載流程不直接暴露一般 S2S token 給 client。
## F-03 忘記密碼 / 重設密碼
- [API] 站點送出 `POST /auth/password/forgot`
- [UI] 會員中心頁提交 email 並發送重設信
- [API/UI] 使用 token 進入重設密碼頁
註記:目前 Web UI 已實作 forgot/reset 流程,但尚未串接 email 發送;開發階段會直接顯示 reset token 與 reset 連結。
## F-03b 已登入修改密碼
- [UI] 使用者登入後進入 `/account/changepassword`
- [UI] 輸入目前密碼與新密碼
- [UI] 會員中心驗證目前密碼後更新密碼
- [UI] 更新成功後刷新登入狀態
## F-04 訂閱電子報(未登入)
- [API] 站點送出 `POST /newsletter/subscribe`
- [API] 會員中心建立 pending 訂閱並發送驗證信
- [UI] 使用者點擊驗證信連結 `/newsletter/confirm?token=...`
- [UI] 訂閱改為 active發出 event `subscription.activated`
## F-05 取消訂閱(單一清單)
- [API] 站點以 `list_id + email` 呼叫 `POST /newsletter/unsubscribe-token` 取得 token
- [UI] 使用者點擊退訂連結 `/newsletter/unsubscribe?token=...`
- [UI] 訂閱狀態改為 unsubscribed
- [API] 發出 event `subscription.unsubscribed`
## F-05b One-Click 退訂 TokenSend Engine 發信前)
- [API] Send Engine 以 `tenant_id + list_id + subscriber_id` 呼叫 `POST /newsletter/one-click-unsubscribe-token`
- [API] 或以 `tenant_id + list_id + subscriber_ids[]` 呼叫 `POST /newsletter/one-click-unsubscribe-tokens` 批次取得
- [API] Member Center 回傳 one-click `unsubscribe_token`
- [API] Send Engine 將 token 置入信件 `List-Unsubscribe` URL
## F-06 訂閱偏好管理(登入後)
- [API] 站點以 `list_id + email` 讀取 `/newsletter/preferences`
- [API] 站點以 `list_id + email` 更新 `/newsletter/preferences`
- [UI] 會員中心提供偏好頁(可選)
## F-06b 我的電子報訂閱管理(登入後)
- [UI] 使用者登入後進入 `/profile/subscriptions`
- [API/UI] 會員中心依目前登入 user 查出其已綁定的訂閱清單
- [UI] 顯示各租戶 / 清單 / 狀態 / 訂閱時間
- [UI] 使用者可直接按下取消訂閱
- [API/UI] 系統驗證該訂閱屬於目前登入 user 後直接退訂
- [API/UI] 不需再次 email token 驗證
- [API] 發出 event `subscription.unsubscribed`
## F-10 Send Engine 事件同步Member Center → Send Engine
- [API] Member Center 以 webhook 推送 `subscription.activated/unsubscribed/preferences.updated`scope: `newsletter:events.write`
- [API] Header 使用 `X-Signature` / `X-Timestamp` / `X-Nonce` / `X-Client-Id`
- [API] `X-Client-Id` 對應 Send Engine `auth_clients.id`UUID
- [API] Member Center 從 DB 的 tenant 設定讀取對應 webhook client id
- [API] Send Engine 驗證簽章 + timestamp + nonce重放防護後入庫
- [API] Send Engine 更新名單快照
## F-11 黑名單回寫Send Engine → Member Center
- [API] Send Engine 依事件規則處理:
- [API] `hard_bounce` / `soft_bounce_threshold` / `suppression`:回寫後由 Member Center 取消該 email 的所有訂閱(跨租戶)並加入黑名單
- [API] `complaint`:回寫後由 Member Center 僅取消該筆訂閱,不加入黑名單
- [API] 呼叫 `POST /subscriptions/disable`
- [API] tenant client 用 `newsletter:events.write`
- [API] 平台 clientSES 聚合事件)用 `newsletter:events.write.global`
- [API] body 需含 `tenant_id + subscriber_id + list_id + reason + disabled_by + occurred_at`
- [API] `hard_bounce` / `soft_bounce_threshold` / `suppression` 才會寫入 `email_blacklist``complaint` 不寫黑名單
## F-12 Webhook Client Mapping 回填Send Engine → Member Center
- [API] Send Engine 建立/更新 tenant 對應的 webhook client`auth_clients.id`
- [API] 呼叫 `POST /integrations/send-engine/webhook-clients/upsert`scope: `newsletter:events.write.global`
- [API] Member Center 更新 tenant 設定DB
## F-07 會員資料查看
- [API] 站點讀取 `/user/profile`
- [UI] 會員中心提供個人資料頁
## F-07b 會員資料維護
- [UI] 使用者登入後進入 `/profile`
- [UI] 維護電話、公司、統編等基本資料
- [API/UI] 儲存會員基本資料
## F-07c 地址簿管理
- [UI] 使用者登入後進入 `/profile/addresses`
- [UI] 新增、編輯、刪除收貨地址
- [UI] 可設定預設地址
- [API/UI] 地址簿資料綁定目前登入 user
- [API/UI] 若只剩最後一筆地址,不允許刪除
## F-07d 其他服務讀取會員資料
- [API] 其他服務以 access token 呼叫會員中心 profile API
- [API] token 需帶對應 profile scopes
- [API] 會員中心依 scope 決定可讀取基本資料、地址簿或訂閱資料
- [API] service API 為主要模式,只要 client 具對應 scope 即可存取對應資料
## F-08 管理者管理租戶/清單/Client
- [UI] 會員中心管理後台進行 CRUD
## F-09 訂閱與會員綁定
- [API] 使用者完成註冊後,會員中心將訂閱資料與 user_id 綁定
- [API] 發送事件 `subscription.linked_to_user`