Communication Data Model
Communication manages three primary entities: Channels, Registrations, and Deliveries. IDs use prefixed formats for quick identification.
CommunicationChannel
A configured messaging endpoint backed by a provider.
interface CommunicationChannel {
id: string; // "ch_" + nanoid(12)
name: string; // Unique channel name
provider: CommunicationProvider; // Provider type
description?: string;
status: ChannelStatus; // "active" | "disabled"
config: Record<string, unknown>; // Provider-specific configuration
createdAt: string; // ISO 8601
updatedAt: string; // ISO 8601
}
type CommunicationProvider =
| "resend" | "slack" | "telegram"
| "whatsapp" | "webhook" | "custom";
type ChannelStatus = "active" | "disabled";
Config Examples
// Resend (email)
{ "apiKey": "env:RESEND_API_KEY", "fromAddress": "noreply@example.com" }
// Slack
{ "webhookUrl": "env:SLACK_WEBHOOK_URL" }
// Telegram
{ "botToken": "env:TELEGRAM_BOT_TOKEN", "chatId": "-100123456789" }
// Webhook
{ "url": "https://example.com/hook", "headers": { "X-Auth": "env:WEBHOOK_SECRET" } }
ChannelRegistration
An application's connection to a channel.
interface ChannelRegistration {
id: string; // "reg_" + nanoid(12)
appId: string; // Application identifier
channelId: string; // Channel ID
target: string; // Default recipient (email, channel name, etc.)
metadata?: Record<string, string>; // Additional context
enabled: boolean; // Whether the registration is active
createdAt: string; // ISO 8601
updatedAt: string; // ISO 8601
}
CommunicationDelivery
A record of a sent (or attempted) message.
interface CommunicationDelivery {
id: string; // "dl_" + nanoid(12)
appId: string; // Application that sent the message
channelId: string; // Channel used
registrationId?: string; // Registration used for routing
provider: string; // Provider that handled delivery
target: string; // Recipient address
status: DeliveryStatus; // "accepted" | "failed"
subject?: string; // Message subject (email)
text?: string; // Plain text body
html?: string; // HTML body (email)
providerMessageId: string; // ID from the provider
live: boolean; // Whether actually sent (false = dry-run)
details?: unknown; // Provider-specific response details
metadata?: Record<string, string>;
createdAt: string; // ISO 8601
errorMessage?: string; // Error details on failure
}
type DeliveryStatus = "accepted" | "failed";
SendPayload
The request body for sending a message.
interface SendPayload {
channelId: string; // Required: which channel to use
registrationId?: string; // Optional: specific registration (auto-resolved if omitted)
to?: string; // Optional: override target from registration
subject?: string; // Message subject
text?: string; // Plain text body (at least text or html required)
html?: string; // HTML body
metadata?: Record<string, string>;
}
Storage
File-Based (SHIFT_STORAGE=file)
.communication/
store.json # All channels, registrations, and deliveries in a single file
Gateway-Backed (SHIFT_STORAGE=gateway)
CLI routes all operations through the gateway REST API. No local storage.