Skip to content

feat(mail): send through Cloudflare Email Service on the managed cloud - #81

Merged
kodiakhq[bot] merged 3 commits into
mainfrom
feat/cloudflare-mail-service
Nov 8, 2026
Merged

kodiakhq[bot] merged 3 commits into
mainfrom
feat/cloudflare-mail-service

Conversation

@RedStar071

@RedStar071 RedStar071 commented Nov 8, 2026 •

Copy link
Copy Markdown
Member

Summary

The managed cloud now sends transactional mail (verification, password reset, invitations) through Cloudflare Email Service. A new cloudflare mail provider, chosen with MAIL_PROVIDER=cloudflare, sends through the Worker's send_email binding. apps/web/wrangler.jsonc declares the EMAIL binding and sets MAIL_PROVIDER and MAIL_FROM=noreply@code-zero.dev. Self-hosted installs are unchanged: console, resend, and smtp behave as before.

Why

On Cloudflare the binding is the credential, so the cloud needs no SMTP password or Resend key to rotate. A Worker receives its bindings with each request, so apps/web reads EMAIL per request (server/utils/mail-binding.ts) and hands it to packages/mail as a callback. packages/mail stays free of Nitro and Cloudflare runtime imports, and selecting cloudflare without the binding fails with a message that names the missing piece.

Verification

  • aube run check:repo
  • aube run lint:ci
  • aube run typecheck
  • aube test
  • aube run build

Safety and compatibility

  • I added or updated deterministic tests for changed behavior.
  • I preserved observe mode as read-only, or explained the policy change above.
  • Runtime commands and target-repository writes remain inside the runner boundary.
  • I did not expose secrets, tokens, personal data, or untrusted output in logs.
  • I updated documentation and Agent Skills when workflows or boundaries changed.

Agent context

  • Agent/tools used: Claude Code with the Wolfstar Agent Kit and Cloudflare tooling.
  • What the agent did, and what you changed or verified yourself: The agent split this change out of the earlier feat/cloudflare-email branch, which still carried the pre-squash commits of feat(dashboard): run the dashboard as a Cloudflare Worker #80. It dropped the inbound forwarding that branch had added and then reverted, and it checked that code-zero.dev is enabled for Email Sending in the Cloudflare account.

Reviewer notes

  • The Worker already running on app.code-zero.dev was deployed from main and has no EMAIL binding. The next dashboard deploy adds it. Sending is enabled for code-zero.dev, but the first real verification or reset mail is worth watching.
  • Inbound mail is not handled here. Cloudflare Email Routing forwards custom addresses on its own, so no Worker email() handler is needed.

🤖 AI disclosure: Wolfstar Agent Kit modified this description. AI open source policy.


Read this PR faster    Follow each request

RetriggerView in GreptileConfidence Score: 5/5

The PR appears safe to merge; no actionable defects were established.

Reviews (3) · Last reviewed commit: "Merge branch 'main' into feat/cloudflare..." · Reviewed by Greptile

The managed cloud sends transactional mail through the Worker's send_email binding instead of an SMTP or Resend credential. Nothing changes for self-hosted installs: the provider is chosen only when the binding exists or MAIL_PROVIDER names it.
@coldtea-pr-lens

coldtea-pr-lens Bot commented Nov 8, 2026 •

Copy link
Copy Markdown
  • Redraw · drawn at 5a7ce11, the branch has moved on

Architecture

Walkthrough of Cloudflare Email Service mail transport, in five steps

Read this PR faster

Inside the changed components — 1 view

Component view — Cloudflare Mail Delivery

Internal components handling Cloudflare Worker email binding resolution and delivery

Architecture view of Component view — Cloudflare Mail Delivery in wolfstar-project/code-zero

Data flow

Data flow diagram for wolfstar-project/code-zero at 5a7ce11

Follow each request


Tip

Add .github/workflows/pr-lens.yml with coldteadotai/pr-lens/packages/action@v0 and your model provider's key as its api-key to run PR Lens from your own CI. Any /chat/completions endpoint works

🪧 More tips
  • Run npx skills add coldteadotai/pr-lens, then tell your coding agent: "Diagram the change you just made with PR Lens and attach it to the pull request."
  • Run npx @coldtea/pr-lens-cli analyze --base origin/main on a branch, then npx @coldtea/pr-lens-cli render .pr-lens/graph.json. Same lenses, your own model key, before the pull request exists
  • Click the link under each diagram to open it on a canvas you can zoom, pan and step through
  • The diagrams are links. Click one to open it on the canvas, then press W or click play to walk through the change
  • Open a diagram on the canvas, then press W or click play to walk through the change one step at a time
  • The CLI's render reads .github/pr-lens.yml and applies your renames, exclusions and lane pins at draw time
  • Set github.comment.collapsed: true in .github/pr-lens.yml to fold the comment behind one View architecture… row. Drawing still runs as before
  • Set github.draw: on-demand in .github/pr-lens.yml and PR Lens stops drawing pull requests on its own. Comment @pr-lens draw on a pull request when you want that one drawn
  • After a push, tick Redraw to draw the latest commit
  • Switch GitHub to dark mode and the diagrams follow. The moving dots are this pull request's data in motion
  • Set github.description: false in .github/pr-lens.yml to stop PR Lens adding buttons to your PR descriptions

Thanks for using PR Lens! It's free for OSS. If it helped, a star helps other teams find it.  Star PR Lens on GitHub

The thrown message already carried only the refusal code, but the original error rode
along as `cause`, and its text can quote the recipient. Loggers print a nested cause, so the
address came back. Drop the cause, as the Resend provider does, and cover it with a test.
@kodiakhq
kodiakhq Bot merged commit 55406be into main Nov 8, 2026
15 of 18 checks passed
@kodiakhq
kodiakhq Bot deleted the feat/cloudflare-mail-service branch November 8, 2026 17:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant