Busflow Docs

Internal documentation portal

Skip to content
Reviewed 02 May 2026

Channel Provisioning Protocol ​

Domain: Communications (Shared Core Domain) Trigger: Operator-initiated channel registration (post-provisioning) Output: Configured channel_accounts with active CPaaS provider connections Sources: communications.md, ADR-003L3 DoD: βœ… Schema | βœ… API | βœ… Edge States β€” Ready to Code


Β§1 Overview ​

Channel provisioning is an explicit post-provisioning operator action β€” ProvisionTenant (ADR-003) seeds notification_templates but does NOT create channel_accounts. Channel registration requires operator action (Meta Business Verification, SES domain verification) that the system cannot automate at signup.

The Workspace UI shows a "Complete your communications setup" onboarding checklist. Seeded notification_templates reference channels that do not yet exist β€” the notification pipeline defers template activation until the matching ChannelAccount reaches ACTIVE.


Β§2 ChannelAccount Lifecycle State Machine ​

100%
FromToTriggerSide Effects
β€”PENDING_VERIFICATIONregisterChannel Hasura ActionCreates channel_accounts + operator_integrations (PENDING). Initiates provider verification.
PENDING_VERIFICATIONACTIVEProvider verification completesoperator_integrations.status β†’ CONNECTED. Pipeline can dispatch. change_event (CONFIG).
PENDING_VERIFICATIONSUSPENDEDVerification failed/timed outoperator_integrations.status β†’ FAILED + error_message.
ACTIVESUSPENDEDManager action or provider revocation detectedoperator_integrations.status β†’ DISCONNECTED. Pipeline skips channel β†’ fallback chain.
SUSPENDEDACTIVERe-verification or manager reactivatesoperator_integrations.status β†’ CONNECTED.
ACTIVEREVOKEDProvider permanently bans accountTerminal. operator_integrations.status β†’ DISCONNECTED. Must register new account.

Suspension detection:

  • WhatsApp: channel_health_check Hasura Cron Trigger (daily, 03:00 UTC) polls Meta WABA status.
  • Email: SES accountSendingPaused SNS notification β†’ auto-suspend.

Β§3 WhatsApp Registration Flow (Meta Embedded Signup) ​

Phase 1 uses Meta's Embedded Signup β€” a JavaScript SDK handling Facebook Login, business verification, and WABA creation in an iframe.

100%

Steps:

  1. Operator opens Workspace Settings β†’ Communications β†’ Add Channel β†’ WhatsApp.
  2. Meta Embedded Signup launches (FB.login() with whatsapp_business_management permissions).
  3. Operator completes flow β†’ Meta returns waba_id, phone_number_id, short-lived token.
  4. Frontend calls registerChannel with the credentials.
  5. Handler: exchange token β†’ generate webhook_verify_token β†’ subscribe to Meta webhooks via POST /<WABA_ID>/subscribed_apps (WABA-level override, not app-level /{app_id}/subscriptions) β†’ encrypt secrets β†’ INSERT both tables β†’ poll Meta Business Verification status.

NOTE

Busflow Meta App: All tenants share one Busflow-owned Meta App (BSP model). app_id and app_secret are platform-level constants stored in provider_config for worker convenience.

WARNING

Blocking prerequisite: The Busflow Meta App must pass Meta App Review for whatsapp_business_management and whatsapp_business_messaging before any tenant can provision WhatsApp.


Β§4 Email Registration Flow (SES Domain Verification) ​

Operator adds DNS records (DKIM, SPF/DMARC) to prove domain ownership.

Steps:

  1. Operator opens Add Channel β†’ Email, enters domain (e.g., reisen-mueller.de).
  2. Frontend calls registerChannel with domain and sender email.
  3. Handler: create SES domain identity β†’ enable DKIM β†’ create Configuration Set β†’ create SNS topics + subscription β†’ return DNS records.
  4. Operator adds DNS records at domain registrar.
  5. ses_verification_check Cron Trigger (every 15 min) polls SES verification status.
  6. On success β†’ ACTIVE. On 30-day timeout β†’ SUSPENDED.

DNS Record Display UI: Panel with copy-to-clipboard buttons, per-record status indicators (⏳/βœ…/❌), and "Verify Now" button.

NOTE

SES Sandbox: Busflow's AWS account must promote out of SES Sandbox before any tenant sends production emails.


Β§5 SMS Registration (Platform-Managed) ​

Phase 1: Platform-managed, not operator-provisioned. DACH Sender ID registration requires per-country carrier pre-registration β€” unsuitable for self-service.

  • Busflow registers a platform-wide Sender ID ("Busflow") with DACH carriers via SNS.
  • All tenants share this Sender ID.
  • registerChannel for SMS creates the row with status = ACTIVE immediately.
  • provider_config stores platform-level SNS config.

Phase 2: operators can register their own Sender ID (1–3 week carrier approval).


Β§6 Hasura Action Contracts ​

registerChannel ​

PropertyTypeRequiredDescription
Input
channel_typeStringβœ…WHATSAPP, EMAIL, SMS
display_nameStringβœ…Operator-editable label
sender_identityStringβœ…Canonical sender identifier
whatsapp_configObject❌Required if WHATSAPP (§3)
email_configObject❌Required if EMAIL (§4)
Output
channel_account_idUUIDβœ…Created ChannelAccount ID
statusStringβœ…PENDING_VERIFICATION or ACTIVE
dns_recordsObject[]❌EMAIL only: DNS records to add
Errors
CHANNEL_ALREADY_EXISTSTenant has existing account for this channel type
PROVIDER_ERRORMeta/SES API call failed
VALIDATION_ERRORInvalid input

Authorization: MANAGER role only.

updateChannelConfig ​

Updates operator-editable fields. Does NOT allow changing channel_type or secrets (re-registration required).

PropertyTypeRequiredDescription
channel_account_idUUIDβœ…Target account
display_nameString❌Updated label
sender_identityString❌Updated sender (re-verification for Email)
reply_to_emailString❌Email only

Authorization: MANAGER role only.

testChannel ​

Sends a test message to verify end-to-end connectivity.

PropertyTypeRequiredDescription
channel_account_idUUIDβœ…Channel to test
test_recipientStringβœ…Phone (E.164) or email

Authorization: MANAGER or DISPATCHER.

suspendChannel / reactivateChannel ​

PropertyTypeRequiredDescription
channel_account_idUUIDβœ…Target account
reasonStringβœ…Logged in change_events

Side effects (suspend): Pipeline skips channel. Queued messages β†’ FAILED with failed_reason = 'channel_suspended'. Fallback chain activates.

Authorization: MANAGER role only.


Β§7 Meta Webhook Setup & Verification ​

NOTE

WABA-level override: This section covers webhook setup via POST /<WABA_ID>/subscribed_apps. The per-tenant callback URL (/api/webhooks/meta/{tenant_id}) receives both inbound messages and delivery status callbacks. See notification-pipeline-protocol.md Β§8 for the delivery webhook handler spec.

During registration (automatic):

  1. Handler calls POST /<WABA_ID>/subscribed_apps with tenant-specific override_callback_url and verify_token. This is a WABA-level override β€” it does NOT overwrite the app-level subscription. Each tenant's WABA independently routes to its own callback URL.
  2. Meta sends GET /api/webhooks/meta/{tenant_id}?hub.mode=subscribe&hub.verify_token={token}&hub.challenge={challenge}.
  3. Controller: extract tenant_id β†’ load channel_accounts β†’ compare webhook_verify_token β†’ respond with hub.challenge or HTTP 403.

Runtime signature verification (every delivery):

  1. Meta sends POST /api/webhooks/meta/{tenant_id} with X-Hub-Signature-256.
  2. Handler computes HMAC-SHA256(app_secret, body) β†’ compare.
  3. Match β†’ process. Mismatch β†’ HTTP 401, log security alert.

IMPORTANT

Shared Meta App Secret: All tenants share one app_secret. Tenant isolation relies on WABA-level scoping (each WABA receives webhooks for its own phone number only).


Β§8 operator_integrations ↔ channel_accounts Sync Contract ​

Two tables, two schemas, one business concept. Writes happen atomically within a single transaction.

Eventchannel_accountsoperator_integrations
RegisteredINSERT PENDING_VERIFICATIONINSERT PENDING
Verification succeeds→ ACTIVE→ CONNECTED
Verification fails→ SUSPENDED→ FAILED + error_message
Manager suspends→ SUSPENDED→ DISCONNECTED
Manager reactivates→ ACTIVE→ CONNECTED
Provider revokes→ REVOKED→ DISCONNECTED
Manager deletesDELETE→ DISCONNECTED

NOTE

Cross-schema write justification: Controlled exception to "contexts communicate via events." Channel provisioning is an administrative configuration action (infrequent, operator-initiated) that must be atomic. Async sync would create consistency gaps in the Workspace UI.


Β§9 operator_integrations β€” CPaaS Types ​

integration_typeDescriptionProvisioned By
META_WHATSAPPWhatsApp via Meta Cloud APIregisterChannel (operator)
AWS_SESEmail via Amazon SESregisterChannel (operator)
AWS_SNSSMS via Amazon SNSregisterChannel (platform-managed Phase 1)

Config shapes live in schema-backoffice.md Β§operator_integrations.

Internal documentation β€” Busflow