Skip to content
chalupa
How it worksSecurityDocumentation
Open console
Menu
How it worksSecurityDocumentationOpen console
chalupa

Operational signal for ephemeral environments. Compute can be torn down while persistent data follows its own lifecycle.

Product

How it worksSecurityConsole

Learn

QuickstartConceptsAPI and schemaEmail

Built for ephemeral operations, not forgotten resources.

All displayed costs are estimates.

Documentation/Email delivery
/

Start here

QuickstartLocal CLI and operator UISecrets with tvault

Operating model

Conceptschalupa.yml referenceLifecycleTunnels and securityData and seeds

Control plane

Control plane and agentPerformance telemetryPrivate log artifactsSuites and artifactsCosts and idle observation

Reference

Private operationsEmail deliveryTroubleshootingAPI and schema
Browse documentation
/

Start here

QuickstartLocal CLI and operator UISecrets with tvault

Operating model

Conceptschalupa.yml referenceLifecycleTunnels and securityData and seeds

Control plane

Control plane and agentPerformance telemetryPrivate log artifactsSuites and artifactsCosts and idle observation

Reference

Private operationsEmail deliveryTroubleshootingAPI and schema

Reference

Email delivery

Operate domain-scoped sending and signed inbound forwarding without turning Chalupa into a public mail relay.

Reviewed 2026-07-25

Chalupa can send mail from its verified domain and receive mail at hello@chalupa.run. Incoming messages are forwarded to one private, operator-controlled destination. The destination exists only in encrypted runtime configuration; it is never committed, returned by an API, or written to application logs.

Email is an operational channel, not part of the fleet control protocol. Launching, observing, or sinking an environment never depends on Resend.

Security boundary

POST /api/webhooks/resend is a provider callback, not a public send API. It:

  • accepts only application/json bodies up to 64 KiB;
  • verifies the unmodified body with the endpoint-specific Svix secret;
  • handles only signed email.received events;
  • forwards only the exact hello@chalupa.run envelope recipient;
  • ignores other recipients captured by the domain-wide receiving rule;
  • blocks messages that would loop through the inbound, forwarding, or private destination addresses;
  • makes one authenticated Receiving API request for the matching event only, with a 10-second timeout, no redirects, no cache, and a 4 MiB streamed JSON limit;
  • forwards bounded HTML/text with inbox@chalupa.run as the fixed sender and the validated original Reply-To (falling back to From); it deliberately omits attachment bytes and adds a neutral notice when attachments exist; and
  • keeps 90 days of SHA-256 pseudonymized digests of the Svix and Resend identifiers for replay suppression. The digests remain joinable provider identifiers, so they are not anonymous data; Chalupa stores neither message content, plaintext provider IDs, sender, nor destination. A lease and provider idempotency key reduce duplicates, but email delivery is not an absolute exactly-once protocol.

Resend stores received mail and treats a receiving domain as a catch-all. An ignored local part can therefore still consume provider quota and remain visible in the Resend account. Monitor that quota and use the provider dashboard to recover a message when webhook delivery is unavailable.

Email content is untrusted input. It must never be interpreted as a Chalupa command, passed to an agent, or used to authorize an infrastructure action.

Credential separation

Secret Permission Runtime
RESEND_SEND_API_KEY Resend sending_access, restricted to chalupa.run Trusted operator or a future fixed-template sender only; not required by the web app.
RESEND_RECEIVE_API_KEY Resend full_access Vercel Production server runtime; only the current webhook code reads it.
RESEND_WEBHOOK_SECRET One Resend webhook endpoint Vercel Production server runtime; only the current webhook code reads it.
RESEND_FORWARD_TO One private email address Vercel Production server runtime; only the current webhook code reads it.

Use separate named keys for sending and receiving. Never give a browser, Preview deployment, Compose workload, or droplet either key. A generic route that accepts request-controlled recipients, senders, subjects, or HTML is deliberately absent.

Resend full-access keys cannot be restricted to one domain and can see events for every receiving domain in the team. The route filters signed events for the exact Chalupa address before touching Neon or the Receiving API. A compromise of the Production webhook runtime nevertheless crosses a wider provider boundary than the domain-scoped send key. Vercel environment variables are project-runtime scoped, so any server-side code in the same deployment could read them even though Chalupa currently reads them only in the webhook path. True route-level isolation requires a separate deployment or secret broker. Keep these values out of Preview, use a separate receiving key per product, and audit or revoke each key independently.

Provision the domain

Create the domain with sending and receiving enabled and enforced TLS. Publish the exact SPF, DKIM, MX, and optional tracking records returned for that domain; do not copy example record values from documentation. Add a DMARC policy after SPF and DKIM verify.

The root MX routes every address at chalupa.run through Resend. If the root domain later gains a normal mailbox provider, move Resend reception to a dedicated subdomain before changing MX records.

After the application route is deployed:

  1. create a webhook for https://chalupa.run/api/webhooks/resend;
  2. subscribe it only to email.received;
  3. save the one-time signing secret directly into TinyVault and the Vercel Sensitive Production environment;
  4. create a separate full-access receiving key and store it the same way;
  5. store the private forwarding address as RESEND_FORWARD_TO;
  6. keep the domain-scoped send key in TinyVault unless a reviewed server-side template needs it; and
  7. redeploy, then inspect one signed inbound delivery and one outbound test.

Do not enable these secrets for Preview. The public landing page, documentation, health route, and local demo remain independent from email configuration.

Verify and recover

Run the local contract before release:

cd cloud
bun test tests/email-config.test.ts tests/inbound-email.test.ts tests/resend-webhook-route.test.ts
bun run typecheck

For an outbound smoke test, send a short plain-text message with the domain-scoped send key and a unique idempotency key. For inbound verification, send one message to hello@chalupa.run and confirm that:

  1. Resend records one received message;
  2. the webhook returns 200;
  3. the private destination receives the bounded body copy (without attachments); and
  4. the application logs contain no sender, recipient, subject, body, attachment name, or provider response.

A 401 means the webhook secret or signed bytes do not match. A 413 means the event envelope exceeded the route limit. A 502 means forwarding failed after signature and policy validation, so Resend may retry. A 503 means the Production email configuration is incomplete or another delivery currently holds the replay lease; retry after the response's Retry-After interval.

PreviousPrivate operationsNextTroubleshooting

On this page

Security boundaryCredential separationProvision the domainVerify and recover