Skip to content

Channels

A channel is a concrete integration — channel equals provider. palumb publishes a flat catalog of channels; you enable the ones you want and attach your credentials. Today the catalog ships one entry, email-smtp (kind email), a generic SMTP relay you can point at any SMTP endpoint.

Two distinct things:

  • The catalog is what palumb makes availableGET /v1/channels/catalog. Each entry declares its key, kind, a human label, and a list of config fields (name, type, required, secret, description). It is the schema your config is validated against.
  • Your enabled channels are what you turned on — POST /v1/channels with your credentials. GET /v1/channels lists them as a safe view (no secrets).

A channel has a kind (email today; slack, telegram, whatsapp later) that fixes the recipient shape and the content shape. The distinction is what keeps workflows portable:

  • A workflow sends by kindstep.send('welcome', 'email', …). It never names a provider.
  • At send time palumb resolves your enabled channel of that kind. If you have more than one, the lowest priority wins (0 before 1; ties broken by oldest first). Disabled channels are skipped.

So you can swap or fail over the underlying provider without touching workflow code.

  • Validated against the catalog schema. On enable/update, the config is checked field-by-field against the catalog entry — unknown fields, missing required fields, and type mismatches are rejected (422).
  • Encrypted at rest. The whole config blob is stored encrypted with AES-256-GCM, with owner-binding AAD (channel:{tenantId}:{channelKey}) so a blob can’t be relocated to another channel or tenant. Decryption happens only inside palumb-core at send time.
  • Never returned. GET responses are a safe view — they confirm a channel is configured: true but never echo a secret back. A PATCH to config is a full replacement, precisely because secrets can’t be read back to merge.

The catalog entry for email-smtp declares:

FieldTypeRequiredSecret
hoststring
portnumber
secureboolean
usernamestring
passwordstring
fromEmailstring
fromNamestring

The secret: true flag is what marks password as never-echoed. New channel kinds ship as new catalog entries with their own field list — the enable / resolve / encrypt path is identical.