- Introduced SqsSesPollerWorker to poll messages from SQS and process SES events. - Implemented SesEventProcessingService to handle SES event payloads and store them in the database. - Updated DevMockSenderWorker to support new SES sending methods and improved logging for unsubscribe headers. - Added AWS SDK for SQS to project dependencies.
3.4 KiB
3.4 KiB
Design
本文件描述 Send Engine 的核心模組、資料流、模組邊界與 Auth/Scope 設計。 本引擎只負責事件控制與執行,不提供 UI。 ESP 介接暫定為 Amazon SES。
核心模組
- Event Ingest
- List Store(多租戶)
- Campaign / Send Job
- Sender Adapter
- Delivery & Bounce Handling
Sending Proxy 規格整合
目標與邊界
- 接收內容網站或會員平台送來的發送工作
- 呼叫 Amazon SES API(優先 SES v2)
- 必帶 Configuration Set + Message Tags
- 消費 SES 回流事件(Bounce / Complaint / Delivery)
- 必要時回寫 Member Center
不負責:
- List-Unsubscribe one-click endpoint 本身的服務實作
- 會員最終名單權威資料庫
狀態機
Job 狀態(目前實作):
- pending
- running
- completed
- failed
- cancelled
Job 狀態(規劃擴充):
- queued
- sending
- sent
- partially_failed
Recipient 狀態:
- pending
- sent
- delivered
- soft_bounced
- hard_bounced
- complained
- suppressed
SES 事件回流架構(建議)
SES Configuration Set -> SNS Topic -> SQS Queue -> ECS Worker- Worker 職責:
- Poll SQS
- 解析 SNS envelope 與 SES payload
- 更新 DB 狀態
- 必要時呼叫 Member Center 停用/註記 API
目前實作:
- 已提供
SqsSesPollerWorker(SQS 輪詢) - worker 直接呼叫內部 SES processing service(不走 HTTP self-call)
- 仍保留
POST /webhooks/ses直接接收模式(相容/測試)
信任邊界與 Auth 模型
外部角色
- Member Center:事件來源與名單權威來源(authority)
- 各租戶網站:內容來源(campaign/content producer)
- Send Engine:執行與狀態記錄(executor)
信任邊界
- Send Engine 不自行發放 tenant 身分;一律以 Member Center 代表的 tenant scope 為準
- 所有 API 必須攜帶 tenant_id,且在驗證後固定於 request context
驗證方式(建議)
- Member Center → Send Engine
- 使用簽名 Webhook(HMAC,已實作)
- header 內含
X-Client-Id,對應auth_clients.id並受 tenant 綁定與 scope 驗證
- 租戶網站 → Send Engine
- 使用 OAuth2 Client Credentials 或 JWT(由 Member Center 簽發)
- token 內含
tenant_id與 scopes(例如newsletter:send.write)
- Send Engine → Member Center
- 使用 OAuth2 Client Credentials(Send Engine 作為 client)
- scopes 只允許
newsletter:list.read/newsletter:events.read/newsletter:events.write
Tenant Scope 取得與約束
- 事件 ingest:以 token 中的
tenant_id為唯一來源,不接受 body 覆寫 - Send Job 建立:tenant_id 從 token 取得;list_id 必須屬於該 tenant
- 名單同步:由 Member Center 主動推送(全量/增量),Send Engine 不主動拉取名單
- 回寫事件:回寫時攜帶同一 tenant_id,Member Center 做二次驗證
防護與審計
- 所有跨服務呼叫需記錄
tenant_id、client_id、scope、request_id - API 層進行 scope 檢查與 tenant 一致性檢查
- Event Ingest 與 Webhook 需具備重放防護(timestamp + nonce)
名單外流風險控制
- Send Engine 不提供「名單查詢 API」
- 全量同步由 Member Center 發動並推送
- 如需測試/診斷,僅回傳計數與版本資訊,不回傳名單內容
資料模型原則
- 事件為 append-only,快照表僅反映最新狀態
- 任何狀態變更必須可追溯(含來源與租戶)