cMail docs

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:

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

  1. Work from an up-to-date, reviewed branch with no unrelated changes.
  2. Review git diff, dependency changes, documentation, and the full commit list. Run pnpm db:migrate:verify to apply and inspect migrations in a throwaway local D1 (Cloudflare's database, emulated by Wrangler on this machine; nothing remote is touched).
  3. Update CHANGELOG.md with user-visible, operational, migration, security, and compatibility notes. Rename [Unreleased] to [X.Y.Z] - YYYY-MM-DD and leave a new empty [Unreleased] above it. Set the same version in the root package.json, apps/web, apps/email-worker, apps/backup-worker and packages/shared, and set version and date-released in CITATION.cff. .zenodo.json carries no version, so only check that its description is still accurate.
  4. Run pnpm release:check. A source or reachable-history secret finding is a release blocker.
  5. Complete affected manual scenarios from deployment verification in an isolated staging environment.
  6. Confirm rollback, backup, restore, and credential-rotation owners.
  7. 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:

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.

← Documentation home