@constal/agent-email
v0.2.0
Published
`@constal/agent-email` is the tenant Channel and AuthProvider for Cloudflare Email Service deliveries. It leaves Constal's internal Resend-backed account and meeting mail Worker unchanged.
Readme
Agent email Channel for Constal
@constal/agent-email is the tenant Channel and AuthProvider for Cloudflare Email Service deliveries. It leaves
Constal's internal Resend-backed account and meeting mail Worker unchanged.
The Cloudflare email() bridge stores the complete raw MIME and attachments through Constal's tenant-scoped artifact
writer before posting a small signed delivery envelope to the platform-owned source Channel. The source Channel uses
the existing subscription directory to forward it to exactly the authorized tenant Channel. The envelope contains a
content reference for the full message and any attachment, with inline text or a separate text reference. No content
is silently truncated. The source AuthProvider checks the bridge signature with a platform Credential. Tenant
AuthProviders check host-authenticated source provenance. The sender address is an external subject, not tenant authority.
Create one constal-email-mailbox Credential for each hosted mailbox. Its Provider generates a stable, unique
@constal.dev address from that Credential's Resource identity and returns the address in verified Credential claims.
Creating another Credential generates another address. Bind the Credential to the email Service and Channel, using
its verified address for the Service's pinned sender, the Channel's config.address, and emailSource(address).
The binding chooses the receiving Agent; changing the binding keeps the address. The Driver requires the hosted
Credential's signed exact-address grant, so one tenant cannot send from another mailbox on the shared domain.
The Channel keys a Session by the
earliest RFC References message ID, or In-Reply-To/Message-ID for a new thread. It pins the sender and thread
headers as the reply address. send() and an Agent's explicit proactive send call the same send operation on the
bound Cloudflare Email Service Driver; the Driver pins the verified sender address and declares non-idempotent recovery.
Outbound messages can include CC, BCC, and attachment artifact references. The Driver loads attachments through the
same tenant-scoped artifact capability used by other Resource invocations.
The package manifests are templates. Install the source Channel and its AuthProvider in platform/ingress. Its
credentialProviders config pins the trusted constal-email-mailbox Provider revision and, when tenant-owned domains
are enabled, the cloudflare-email-domain Provider revision. Set hostedDomain to constal.dev. Publish and install
those Providers in platform/default with management.kind=platform; a tenant-private Provider is not a shared issuer.
The hosted Provider checks Cloudflare's current mail configuration and signs an exact-address grant. The optional
tenant-domain Provider checks the zone ownership marker and signs a tenant/domain grant. Their platform-operator
grantTtlMs configuration sets the renewal interval. Keep their Cloudflare API token and shared grant key behind
bootstrap Credentials; do not offer either to Agent code.
Import the bridge signing key through platform/ingress's built-in static Credential Provider for the source
AuthProvider. The Email Driver uses the shared grant key as a Worker secret named EMAIL_DOMAIN_GRANT_KEY; its
domain-grant Credential must come from a trusted Provider. The inbound Worker uses EMAIL_BRIDGE_SIGNING_KEY and PLATFORM_AUTH_TOKEN
Worker secrets. The bridge key is bound as a platform Credential to the source AuthProvider. The internal artifact token
is used only after the platform rechecks the current subscription Credential and resolves exactly one authorized tenant
owner for the recipient.
Agent deployments opt in with the channels.constal.ai/email=enabled label.
For the platform-owned domain, prepare the existing apex zone with
npm run provision:domain -- prepare-hosted platform constal.dev ZONE_ID. This enables Email Sending without routing
mail yet. Create a hosted mailbox Credential, Service, and Channel for each address, then run
npm run provision:domain -- activate-hosted platform constal.dev ZONE_ID to route the catch-all to the inbound
Worker. Neither hosted step creates a tenant ownership marker. Cloudflare requires Enterprise for separately delegated
child zones.
For an Enterprise tenant-owned child zone, an operator can create and activate it with
npm run provision:domain -- prepare TENANT DOMAIN and, after the tenant adds the returned NS records,
npm run provision:domain -- activate TENANT DOMAIN ZONE_ID. The script sets a zone ownership TXT marker,
enables Email Routing and Sending, and routes the zone catch-all to the one inbound Worker. The Credential Provider
checks the marker and each provider readiness state before minting a domain grant. Run the script with the Cloudflare
account ID and a scoped API token in CLOUDFLARE_ACCOUNT_ID and CLOUDFLARE_EMAIL_API_TOKEN.
The driver and inbound Worker live at apps/driver-email and apps/email-ingress. Cloudflare Email Sending's Worker
binding acknowledges acceptance, not final delivery. send is declared non-idempotent; an uncertain result is never
retried blindly. The original inbound message.reply() cannot be used after an Agent Run, so replies use the sending
binding and the pinned RFC thread headers.
