Contributing
Spindle is a Matrix homeserver whose rooms are append-only logs with materialized state, written in Rust. The README says what it is and where it stands; ROADMAP.md says what is next; SPEC.md is the design. This page is how to work on it.
Build and test
rust-toolchain.toml pins the compiler and rustup fetches it on its own.
Storage is embedded, so there is nothing to provision.
cargo test --workspace --all-features
cargo clippy --workspace --all-targets --all-features -- -D warnings
cargo fmt --all --check
just lint and just test run the same commands, and just --list names
the rest: the generated pages (just docs) and the competitive benchmark
sitting from a bare checkout (just bench <group>, or its three steps
bench-field, bench-build, bench-sitting; docs/benchmarks.md says what
each does and what the field is pinned to).
Those three are the pull-request gate, with a few checks that keep generated and hand-copied things honest:
python3 scripts/coverage-dashboard.py --check # docs/dashboard.md matches the router
python3 scripts/readme-numbers.py --check # the README's headline numbers are the gated ones
python3 scripts/actions-pinned.py # every action is pinned to a commit
The slower suites run on pushes to main and nightly, not on pull requests:
the Complement ratchet (scripts/complement.sh, needs Docker), Element
Web and Element Call end to end, the full-mesh peer-to-peer call, the
Neutrino mesh seam, a real bridge through the appservice API, release-mode
performance budgets, and weekly fuzzing and coverage. .github/workflows/
is the list; each job's comment says why it runs where it runs.
What a change is expected to carry
- A test that would have failed before it. For a bug, the test reproduces the bug; for a feature, the test is the claim. Performance work arrives with a counting assertion (allocations, bytes, comparisons) rather than a timing, because timings do not fail deterministically.
- No stubs. An endpoint that is routed works; one that is not answers
404.
tests/surface.rsenforces that/versionsadvertises only what is built. A placeholder that returns{}is worse than a 404, because a client cannot tell it from success. - Honest numbers. The dashboard, the README's counts and the Complement allowlist are generated or gated. A claim about performance links the benchmark that made it; a retracted claim stays retracted in the text.
- Comments that say why. The code says what; a comment earns its place by recording the reason, the alternative that was rejected, or the failure that motivated it.
Adding an endpoint or an MSC
Both have a generated page CI holds to the code. A new route must
appear in docs/dashboard.md and leave docs/spec-gaps.md (run just regen); a new MSC surface needs an entry in contrib/msc/ledger.toml
naming the test that proves it, and the flag it advertises. The whole
procedure, with the spec-release and pin-bump cases, is in
docs/maintenance.md.
Finding something to do
Issues labelled good first issue are self-contained with a design in the
issue; help wanted marks work that needs something this repository does
not have (a client, a bridge, a second homeserver). The milestone table in
the README is the roadmap in prose, and ROADMAP.md has the entry points
for each track.
Pull requests
One change per pull request, with the commit message saying what changed and why in plain prose. Pushes to your branch re-run the gate; the Complement ratchet runs its protected subset on pull requests and the whole suite on main. A red check is yours to read before a reviewer does.
Security
Not an issue. SECURITY.md has the route.