Email delivery
Transactional email (verification, invitations, resets) flows through a provider-neutral adapter with a database outbox + retry worker — an email is recorded before it is sent, and failures retry with backoff instead of silently dropping (ADR-022, ADR-023).
- Local dev: Mailpit (in the compose stack) catches all mail at
http://localhost:8025— nothing leaves your machine. - Staging: Resend, configured purely via environment variables on the deployment host. API keys live only in the staging environment — never in the repo, and never in these docs. Rotate keys via the Resend dashboard and update the host env.
- Delivery state is inspectable in the
email_outboxtable; the worker logs retries.
Webhook-driven bounce handling and per-user email preferences are deferred (R-44 in the research backlog).