1. Core Entities
ProviderConfig ( The Gateway )
Configuration for an external service. Encrypted at rest.
- id (
string): Unique ID (nanoid). - tenantId (
string | null): Owner workspace.NULL= System Default. - type (
ProviderType):twilio,aws-ses,resend,smtp,webhook. - name (
string): User-friendly label ("Marketing SES"). - encryptedConfig (
string): AES-256 encrypted JSON blob (apiKey,secret,host). - mask (
string): Partial display for UI ("...a1b2"). - enabled (
boolean): Active switch. - priority (
int): 0=Primary, 1=Fallback. - metadata (
json): Custom provider settings (e.g., "TPS Limit"). - createdAt (
timestamp). - updatedAt (
timestamp).
Message ( The Immutable Log )
A specific request to send content. Once created, it is IMMUTABLE except for status.
- id (
string): Unique ID (nanoid). - tenantId (
string): Context. - channel (
ChannelType):email,sms,push,webhook. - direction (
Direction):outbound(default) orinbound(reply). - recipient (
string): E.164 Phone or Email. - subject (
string | null): Email subject. - content (
json): The full message body.- Structure:
{ html?: string, text?: string, templateId?: string, variables?: json }
- Structure:
- status (
MessageStatus):queued,sending,sent,delivered,failed,canceled. - providerId (
string): The built-in or tenant provider used. - providerMessageId (
string | null): The external ID (e.g.,MessageSid). - cost (
decimal | null): Estimated cost (0.0075). - idempotencyKey (
string | null): Client-provided key for de-duplication. - scheduledAt (
timestamp | null): Future delivery time. - sentAt (
timestamp | null): When it left our system. - metadata (
json): Traceability tags (campaignId, userId, source IP).
MessageEvent ( The Audit Trail )
History of every state change or feedback.
- id (
string): PK. - messageId (
string): FK to Message. - status (
MessageStatus): The state reported. - reason (
string | null): "Bounced: Mailbox full". - source (
string):internal(API) orprovider(Webhook). - rawPayload (
json): The full webhook body for debugging. - occurredAt (
timestamp).
2. Enums & Types
enum ChannelType {
EMAIL = 'email',
SMS = 'sms',
PUSH = 'push',
WEBHOOK = 'webhook'
}
enum MessageStatus {
QUEUED = 'queued', // In Cloudflare Queue
SENDING = 'sending', // Picked up by Worker
SENT = 'sent', // 200 OK from Provider
DELIVERED = 'delivered', // Webhook confirmed receipt
FAILED = 'failed', // Provider rejected (4xx/5xx)
CANCELED = 'canceled' // Recalled by user
}3. Storage Strategy
- Hot Data (Last 30 days): D1 (Hyper-fast SQL).
- Cold Data (Archive): R2 (JSON/Parquet logs for analytics).
- Secrets:
encryptedConfigcolumn using Web Crypto API.
4. Failover Logic
If Provider A fails:
- Log
MessageEvent(Failed). - Check for
Provider B(Next Priority) for same Tenant + Channel. - If found, clone
Messagewith newproviderId(Retry). - If not found, mark
Messageas Final Failure.