Maintainer release guide
This guide covers public-repository and release hygiene. It does not replace the deployment or operations checklists used by each cmail operator.
Repository settings
After creating or transferring the public GitHub repository:
- set
mainas the default branch; - set a concise repository description and add discoverability topics such as
email,self-hosted,cloudflare,sveltekit,oauth, andemail-routing; - upload a PNG, JPG, or GIF social preview derived from
apps/web/static/og-image.svgunder Settings → Social preview; - enable private vulnerability reporting and review the contact path in SECURITY.md;
- enable dependency graph, Dependabot alerts, secret scanning, and push protection where available;
- protect
mainwith pull requests, successful CI checks, resolved review conversations, and protection from force pushes and deletion; - grant write, administration, Pages, DNS, and provider access only to people who need it;
- create the labels referenced by issue forms and
.github/release.yml, or adjust that metadata to the repository's chosen labels.
Repository security features complement the local release gates; they do not make committed credentials safe. Revoke any exposed value before addressing its Git history.
GitHub's current social-preview requirements are documented in Customizing your repository's social media preview.
Prepare a release
- Work from an up-to-date, reviewed branch with no unrelated changes.
- Review
git diff, dependency changes, documentation, and the full commit list. Runpnpm db:migrate:verifyto apply and inspect migrations in a throwaway local D1 (Cloudflare's database, emulated by Wrangler on this machine; nothing remote is touched). - Update CHANGELOG.md with user-visible, operational,
migration, security, and compatibility notes. Rename
[Unreleased]to[X.Y.Z] - YYYY-MM-DDand leave a new empty[Unreleased]above it. Set the sameversionin the rootpackage.json,apps/web,apps/email-worker,apps/backup-workerandpackages/shared, and setversionanddate-releasedinCITATION.cff..zenodo.jsoncarries no version, so only check that its description is still accurate. - Run
pnpm release:check. A source or reachable-history secret finding is a release blocker. - Complete affected manual scenarios from deployment verification in an isolated staging environment.
- Confirm rollback, backup, restore, and credential-rotation owners.
- Create the version tag (
vX.Y.Z) only after the release commit is approved, then push it.
CI runs pnpm release:check on Node 22, 24 and 26 for every pull request, so
a green run on the release commit is the same gate you ran locally.
For identity changes, inspect the complete authorization-code and enrolment
flow, not just the sign-in button. Confirm both providers obtain identity from
access-token UserInfo, returning accounts resolve solely by provider plus
sub, invitation hashes remain single-use and expiring, resend revokes older
links, and raw invitation/bootstrap credentials never enter provider callbacks
or logs. A release must not reintroduce Microsoft /me, email/UPN lookup, or
ID-token claims as an account selector. A release touching email one-time-code
sign-in must keep codes hashed and single-use, keep the Manager role refusing
an email-only identity, and keep Turnstile scoped to the request form only. A
release touching sign-in countries must keep the first-manager bootstrap
exemption and the manager-notification throttle intact.
Release notes
GitHub's generated release notes use .github/release.yml for categories.
Review generated notes rather than publishing them verbatim. Call out:
- required configuration or secret changes;
- D1 migrations and upgrade order;
- changes to OAuth callbacks, UserInfo endpoints, identity audiences, scopes, immutable subject binding, enrolment, bootstrap, or sessions;
- data exposure, retention, mail-flow, or DNS implications;
- known limitations and staging evidence.
Do not include private issue details, deployment identifiers, production URLs, message content, personal data, or secret values in commits, tags, artifacts, screenshots, or release notes.