17 — Extending the Project & Contribution Guide
You have read the step-by-step tour. Now you want to change something.
First Principles
- The TDD documents (
docs/TDD/) are the design source of truth. If you are adding a significant feature, start by updating (or creating) the relevant TDD section. - The implementation plans (
docs/plans/) show the historical granularity. New work can be proposed as a similar set of small, reviewable.mdsteps if the change is large. - Behavior compatibility with the Go Madmail (in
context/madmail/) is usually required for federation and client interop. When in doubt, make the Rust version do what the Go version does (or document the intentional difference). - Single-binary + simple ops is a core constraint. Avoid adding new mandatory external processes or complex deployment steps.
Where to Make Common Changes
| Change Type | Primary Locations |
|---|---|
| New CLI command (madmail parity) | chatmail-config/src/cli.rs, chatmail/src/ctl/<new>.rs, ctl/dispatch.rs |
| New admin API method / resource | chatmail-admin/src/resources/<new>.rs, handler.rs |
| New setting / dynamic toggle | chatmail-db/src/settings_keys.rs, chatmail-db/src/settings.rs, relevant cache |
| SMTP extension or verb | chatmail-smtp/src/session.rs + protocol bits |
| IMAP extension or METADATA entry | chatmail-imap/src/session.rs + config passed from supervisor |
| New federation policy or routing rule | chatmail-fed/src/mxdeliv.rs, chatmail-delivery/src/router.rs, chatmail-state caches |
| New background maintenance job | chatmail-tasks/src/jobs.rs, scheduler |
| Change to quota / storage accounting | chatmail-state/src/quota.rs, chatmail-storage |
| Change to PGP enforcement | chatmail-pgp/src/lib.rs (very careful — tests are mandatory) |
| TURN / Iroh discovery change | chatmail-turn, chatmail-iroh, turn_boot.rs / iroh_boot.rs, IMAP METADATA path |
| Admin web UI change | external/madmail-admin-web/ (then make build-with-admin-web) |
| New public web page or API | chatmail-www/src/handlers.rs, router.rs, webimap* |
| Config / effective_* logic | chatmail-config (the effective_* functions are the contract) |
| New migration or schema change | chatmail-db/migrations/sqlite/ (and postgres/), schema.rs |
Adding Tests
- Every new hot-path or security-sensitive function should have a unit test next to it.
- Protocol changes should have both unit parsing tests and an E2E exercise in
tests/. - If the change affects registration, delivery, or federation, add or extend a Delta Chat client E2E scenario if possible.
- Update the relevant row in
docs/TDD/16-testing.mdif you are expanding coverage.
Documentation Obligations
When you land a change that affects humans or other developers:
- Update the matching
docs/project/NN-*.md(especially the crate tour and the flow documents). - If it's a design-level change, update the TDD section.
- If it changes operator-visible behavior, consider updating
docs/install-*.mdor adding a note in the admin docs. - Cross-link from the implementation plan (if you created one) back to the code.
Commit & PR Hygiene
- Small, reviewable commits are preferred (the original b1–b9 plans were literally one small
.md+ implementation per step). - Run
make fmt,make lint, and the relevant test subset before opening a PR. - For large features, consider opening a design / plan document first (similar to the existing
plans/entries). - Never commit
target/,node_modules/, or your personal.env/data/.
Working with the Submodules
external/madmail-admin-web— treat it like a normal repo for UI work. The parent repo just records the commit pointer.context/*trees — you almost never commit changes to them. They are reference material. If you find a bug in one of them while studying, open an issue or PR against the upstream project, not here.
Security & Privacy Changes
- Anything touching the PGP gate, auth, admin token handling, or logging (No-Log) is high risk.
- Such changes require:
- Unit + E2E tests that specifically exercise the security property.
- Careful review of error messages (they must not leak information).
- Usually an update to
docs/TDD/12-security.md.
When to Add a New Crate
Only when the concern is clearly separable and likely to be used by multiple other crates or external tools.
Examples of good new crates: a new sidecar supervisor, a new storage backend abstraction, a metrics collector.
Do not create a new crate just to split a 400-line file.
Getting Help / Asking Questions
- The existing TDD and plan documents are the primary written record.
- The Go Madmail source + its docs are the behavioral spec.
- The integration tests in
tests/are executable documentation of "what good looks like." - For real-time discussion, the project uses whatever chat channels the team has (often Delta Chat itself on a madmail server).
Final Encouragement
This project was built by following a very detailed, step-by-step plan across many phases. The same approach works for new work:
- Write a small plan (or a TDD update).
- Implement the smallest possible vertical slice.
- Add tests that would have caught the thing you just built.
- Document it in the human-facing
docs/project/series. - Ship.
Welcome to the codebase. You now know where everything is and how it fits together.
— The madmail-v2 documentation team