diff --git a/apps/web/content/docs/modules/communications.mdx b/apps/web/content/docs/modules/communications.mdx index 6877b0f..afe46f6 100644 --- a/apps/web/content/docs/modules/communications.mdx +++ b/apps/web/content/docs/modules/communications.mdx @@ -1,10 +1,14 @@ --- title: Communications -description: Unified email, SMS, and push notifications (replaces legacy modules). -agent_summary: "v0.17 unified communications; email/SMS/push via Admin API and grpcSdk; MCP ?modules=communications; Handlebars templates." +description: Unified email, SMS, and push — one module, three channels, orchestrated delivery. +agent_summary: "v0.17 unified communications; Admin /email /push /sms; EmailTemplate + CommunicationTemplate; orchestrator multi-channel/fallback; grpcSdk legacy aliases; MCP ?modules=communications." --- -In **v0.17**, separate **email**, **sms**, and **push-notifications** modules are consolidated into **communications** — one module, one config namespace, three channels. +import CommunicationsDeepDive from "@/mdx/deep-dives/communications-deep-dive.mdx"; + +Your app needs to reach users on email, push, and SMS — without operating three separate modules, credential sets, and send paths. The **communications** module is the unified messaging layer: one config namespace, channel-specific Admin API routes under `/email`, `/push`, and `/sms` (not `/pushNotifications`), plus orchestration for multi-channel and fallback delivery. + +In **v0.17**, legacy **email**, **sms**, and **push-notifications** modules consolidate here. Existing `grpcSdk.email`, `grpcSdk.pushNotifications`, and `grpcSdk.sms` calls continue to work; new integrations can use `grpcSdk.communications` for orchestrated sends. Sending from application runtime stays server-side — never admin credentials in the browser. ## Use cases @@ -12,19 +16,23 @@ In **v0.17**, separate **email**, **sms**, and **push-notifications** modules ar items={[ { title: "Transactional email", - outcome: "Welcome emails, receipts, password resets via Handlebars templates", + outcome: "Welcome emails, receipts, password resets via Handlebars EmailTemplate", }, { title: "Push notifications", - outcome: "FCM device tokens registered from apps; send via Admin API or workers", + outcome: "FCM/OneSignal device tokens registered from apps; send via Admin API or workers", }, { title: "SMS & 2FA", - outcome: "Twilio or AWS SNS for verification codes and alerts", + outcome: "Twilio Verify, AWS SNS, or MessageBird for verification codes and alerts", }, { title: "Multi-channel orchestration", - outcome: "Fallback chains (email then push) configured admin-side", + outcome: "Broadcast to email + push + SMS, or fallback chains when a channel fails", + }, + { + title: "Unified templates", + outcome: "CommunicationTemplate documents coordinate copy across channels for GitOps export", }, ]} /> @@ -33,26 +41,36 @@ In **v0.17**, separate **email**, **sms**, and **push-notifications** modules ar -## Example: Transactional email + push token +## Example: Template, email send, and fallback + Hi {{name}}, welcome aboard.

"}'`} + /> +
## How it works -### API surfaces + + -| Layer | Role | -|-------|------| -| **Client API** | Device token registration, in-app notification inbox | -| **Admin API** | Send email/push/SMS, template CRUD, delivery history | -| **gRPC / grpc-sdk** | Server-side sending from custom modules (`grpcSdk.email`, etc.) | +## Configure -Legacy grpc-sdk client names (`grpcSdk.email`, `grpcSdk.pushNotifications`, `grpcSdk.sms`) route to communications automatically. +Patch via MCP `patch_config_communications` (`?modules=communications` or aliases `email`, `push`, `sms`): + +| Key | Default | Meaning | +|-----|---------|---------| +| `email.active` | `false` | Enable email channel | +| `email.transport` | `smtp` | Provider: `smtp`, `sendgrid`, `mailgun`, `amazonSes`, `mandrill`, `mailersend` | +| `email.sendingDomain` | `conduit.com` | Appended to bare sender names | +| `email.storeEmails.enabled` | — | Persist sent email records for resend/history | +| `pushNotifications.active` | `false` | Enable push channel | +| `pushNotifications.providerName` | — | `firebase`, `onesignal`, `amazonSns` | +| `sms.active` | `false` | Enable SMS channel | +| `sms.providerName` | `twilio` | `twilio`, `awsSns`, `messageBird` | +| `sms.twilio.verify.active` | `false` | Twilio Verify for OTP flows | +| `orchestration.retryAttempts` | `3` | Retries per channel send | +| `orchestration.fallbackTimeout` | `5000` | Default fallback step timeout (ms) | -### Templates +## Client API -Email templates use Handlebars (`{{variableName}}`) in subject and body. Variables are extracted on create. Reference `templateName` when sending — provision templates at deploy time, not from app runtime. +Push and in-app notification routes (authenticated). Served at the router root (no module prefix): -### Migration from v0.16 +| Method | Path | Purpose | +|--------|------|---------| +| POST | `/token` | Register device token `{ token, platform }` | +| DELETE | `/token` | Clear tokens; optional `?platform=` | +| GET | `/notifications` | In-app inbox (`read`, `skip`, `limit`, `platform`) | +| PATCH | `/notifications` | Mark read `{ id }` or `{ before }` | -Standalone email, sms, and push-notifications modules are replaced. MCP aliases `?modules=email,push,sms` still work. See [Migration guide](/docs/resources/migration-v0.16-to-v0.17). - +**Sending** email, SMS, or push is Admin API or grpc-sdk only — not from browser-exposed app code. -## Configure +## Admin API -MCP: `?modules=communications` (aliases: `email`, `push`, `sms`). +All routes require Admin API authentication. Default Admin port: `3030`. Paths use `/email`, `/push`, `/sms` — never `/pushNotifications`. -| Tool | Purpose | -|------|---------| -| `get_config_communications` | Read email, push, SMS, orchestration | -| `patch_config_communications` | Provider credentials and channel settings | -| `post_email_templates` | Create Handlebars template | +### `/email` -Config nests `email`, `pushNotifications`, `sms`, and `orchestration` under the communications key. +| Method | Path | Purpose | +|--------|------|---------| +| POST | `/email/send` | Send — `templateName` or inline `subject` + `body` | +| GET | `/email/templates` | List EmailTemplates (`skip`, `limit`, `sort`, `search`) | +| POST | `/email/templates` | Create EmailTemplate | +| PATCH | `/email/templates/:id` | Update EmailTemplate | +| DELETE | `/email/templates/:id` | Delete EmailTemplate | +| GET | `/email/templates/external` | List provider-managed templates | +| POST | `/email/templates/external/sync` | Sync external templates into Conduit | +| POST | `/email/resend` | Resend by email record `{ id }` | +| GET | `/email/emails` | Sent email history | +| GET | `/email/emails/:id` | Single email record | + +### `/push` -## Client API +| Method | Path | Purpose | +|--------|------|---------| +| POST | `/push/send` | Send — `userId`, `title`, `body`, optional `data`, `platform`, `isSilent`, `doNotStore` | +| GET | `/push/tokens` | List device tokens | +| GET | `/push/tokens/:id` | Single token | +| DELETE | `/push/tokens/:id` | Remove token | -Push and in-app notification routes (authenticated). v0.17 unified communications serves these at the router root (no module prefix): +### `/sms` | Method | Path | Purpose | |--------|------|---------| -| POST | `/token` | Register FCM/device token `{ token, platform }` | -| DELETE | `/token` | Clear tokens; optional `?platform=` | -| GET | `/notifications` | In-app inbox (`read`, `skip`, `limit`, `platform`) | -| PATCH | `/notifications` | Mark read `{ id }` or `{ before }` | +| POST | `/sms/send` | Send SMS — `to`, `message` | +| GET | `/sms/messages` | Sent SMS history | +| GET | `/sms/messages/:id` | Single SMS record | -**Sending** email/SMS/push is Admin API or grpc-sdk — not from browser-exposed app code with admin credentials. +### Orchestrator (`/send`) + +| Method | Path | Purpose | +|--------|------|---------| +| POST | `/send/multiple` | Multi-channel broadcast — `channels`, `strategy`, `recipient`, `subject?`, `body?`, `variables?` | +| POST | `/send/fallback` | Fallback chain — `fallbackChain[{ channel, timeout }]`, `recipient`, `subject?`, `body?`, `variables?` | + +### CommunicationTemplate (GitOps) + +Multi-channel **CommunicationTemplate** documents have no dedicated Admin REST CRUD yet. Manage via [state export/import](/docs/guides/gitops-state-export) (`communicationTemplates`), direct database provisioning, or gRPC `RegisterCommunicationTemplate` from server-side workers (placeholder until unified template CRUD is complete). + +## grpc-sdk + +| Client | Use when | +|--------|----------| +| `grpcSdk.email` | Legacy email send, template register, status — routes to communications | +| `grpcSdk.pushNotifications` | Legacy push send, token management | +| `grpcSdk.sms` | Legacy SMS send, Twilio Verify | +| `grpcSdk.communications` | Unified API: `sendMessage`, `sendToMultipleChannels`, `sendWithFallback`, `getMessageStatus` | + +Never import grpc-sdk in client components or browser bundles. ## MCP -- `?modules=communications` -- Aliases: `?modules=email,push,sms` -- Note: `push-notifications` is not a valid MCP alias — use `push` or `communications` +- `?modules=communications` — full module tools and config +- Aliases: `?modules=email`, `?modules=push`, `?modules=sms`, or `?modules=email,push,sms` +- **Invalid:** `push-notifications` — use `push` or `communications` + +| Tool | Purpose | +|------|---------| +| `get_config_communications` | Read email, push, SMS, orchestration settings | +| `patch_config_communications` | Provider credentials and channel toggles | +| `post_email_templates` | Create Handlebars EmailTemplate | diff --git a/apps/web/src/mdx/deep-dives/communications-deep-dive.mdx b/apps/web/src/mdx/deep-dives/communications-deep-dive.mdx new file mode 100644 index 0000000..2572e73 --- /dev/null +++ b/apps/web/src/mdx/deep-dives/communications-deep-dive.mdx @@ -0,0 +1,131 @@ +### Unified module, channel-scoped Admin paths + +One **communications** module owns all three channels. Admin routes register at the **router root** — there is no `/communications` prefix: + +| Prefix | Purpose | +|--------|---------| +| `/email/*` | Send, templates, delivery history, resend | +| `/push/*` | Send notifications, manage device tokens — **not** `/pushNotifications` | +| `/sms/*` | Send SMS, delivery history | +| `/send/*` | Orchestrator — multi-channel broadcast and fallback | + +Config nests push settings under `pushNotifications` (legacy key name); Admin API paths use `/push`. + +### API surfaces + +| Layer | Role | +|-------|------| +| **Client API** | Device token registration, in-app notification inbox (router root, no prefix) | +| **Admin API** | Send email/push/SMS, template CRUD, delivery history, orchestration | +| **gRPC / grpc-sdk** | Server-side sending from custom modules (`grpcSdk.email`, `grpcSdk.communications`, …) | + +Legacy grpc-sdk clients (`grpcSdk.email`, `grpcSdk.pushNotifications`, `grpcSdk.sms`) route to communications automatically. + +### Templates: EmailTemplate vs CommunicationTemplate + +**EmailTemplate** — email-only Handlebars templates. Full Admin CRUD at `/email/templates`. Variables are auto-extracted from `{{placeholders}}` in subject and body on create. Reference by **`templateName`** when calling `POST /email/send` or `grpcSdk.email.sendEmail`. + +| Field | Purpose | +|-------|---------| +| `name` | Unique identifier — used as `templateName` when sending | +| `subject`, `body` | Handlebars strings | +| `variables` | Auto-derived from `{{…}}` placeholders | +| `sender` | Optional override sender | +| `externalManaged` | Sync with SendGrid/Mailgun provider templates | + +**CommunicationTemplate** — unified multi-channel template stored in the database. One document covers every channel the message uses: + +| Field | Purpose | +|-------|---------| +| `name` | Unique template identifier | +| `channels` | `['email', 'push', 'sms']` — which channels this template serves | +| `email` | `{ subject, body, sender? }` — Handlebars in subject/body | +| `push` | `{ title, body }` — `{{variable}}` interpolation | +| `sms` | `{ message }` — `{{variable}}` interpolation | +| `variables` | Declared variable names shared across channels | + +CommunicationTemplate documents are **exportable/importable** via [state export](/docs/guides/gitops-state-export) (`communicationTemplates` resource type). Provision at deploy time alongside EmailTemplates. + +For **EmailTemplate**, use Admin REST (`POST /email/templates`) or MCP `post_email_templates`. For **CommunicationTemplate**, prefer GitOps state import or direct database provisioning today. gRPC `RegisterCommunicationTemplate` is the orchestrator registration hook (server-side grpc-sdk only); it currently returns a minimal placeholder response — full unified Admin REST CRUD for CommunicationTemplate is not exposed yet. + +### Sending with `templateName` + +| Path | `templateName` behavior | +|------|-------------------------| +| `POST /email/send` | Resolves **EmailTemplate** by name; compiles Handlebars with `variables`. Omit only when providing inline `subject` + `body`. | +| `grpcSdk.email.sendEmail(templateName, …)` | Same resolution as Admin API | +| `POST /send/multiple`, `POST /send/fallback` | Inline `subject`, `body`, `variables` per channel — **no** `templateName` lookup on REST | +| gRPC `SendToMultipleChannels`, `SendWithFallback` | Accept `templateName` in the proto for CommunicationTemplate resolution | +| `POST /push/send`, `POST /sms/send` | Inline `title`/`body` or `message` — no template lookup | + +```typescript +// Email — template by name (server-side only) +await grpcSdk.email!.sendEmail("WelcomeEmail", { + email: "user@example.com", + variables: { name: "Alex" }, +}); + +// Orchestrator — multi-channel broadcast +await grpcSdk.communications!.sendToMultipleChannels( + ["email", "push"], + "BEST_EFFORT", + { + recipient: "user@example.com", + subject: "Order shipped", + body: "Your order {{orderId}} is on the way", + variables: { orderId: "ORD-42" }, + } +); +``` + +### Orchestration + +The orchestrator coordinates delivery across channels through two Admin API entry points: + +| Admin route | Strategy | Behavior | +|-------------|----------|----------| +| `POST /send/multiple` | `BEST_EFFORT` or `ALL_OR_NOTHING` | Parallel send to listed channels; `ALL_OR_NOTHING` fails if any channel fails | +| `POST /send/fallback` | Ordered chain | Try each channel in sequence with per-step `timeout` (ms) until one succeeds | + +`POST /send/multiple` returns `{ successCount, failureCount, results[] }`. `POST /send/fallback` returns `{ successfulChannel, messageId, attempts[] }`. + +Orchestration config (`retryAttempts`, `retryDelay`, `timeout`, `fallbackTimeout`) lives under `communications.orchestration`. + +### Migration from v0.16 + +Standalone **email**, **sms**, and **push-notifications** modules are deprecated. Communications is a drop-in replacement: + +1. **Deploy** — register `Communications` instead of three separate modules. +2. **Config** — nest legacy keys under `communications` (example below). +3. **Code** — existing `grpcSdk.email`, `grpcSdk.pushNotifications`, `grpcSdk.sms` calls continue unchanged. +4. **MCP** — use `?modules=communications` or aliases `?modules=email,push,sms`. `push-notifications` is **not** a valid alias. + +```yaml +communications: + active: true + email: + active: true + transport: sendgrid + sendingDomain: example.com + transportSettings: + sendgrid: + apiKey: "…" + pushNotifications: # config key — Admin paths use /push + active: true + providerName: firebase + firebase: + projectId: "…" + sms: + active: true + providerName: twilio + twilio: + accountSID: "…" + authToken: "…" + orchestration: + retryAttempts: 3 + fallbackTimeout: 5000 +``` + +On first boot, communications can auto-merge legacy top-level `email`, `pushNotifications`, and `sms` config into the unified namespace when channel values still match defaults. Legacy gRPC service names are preserved on the unified `Communications` gRPC service. + +See [Migration guide](/docs/resources/migration-v0.16-to-v0.17).