Contributing to Ilavrita
Thank you for helping build open healthcare infrastructure. This document covers how to get a working tree, what we expect from a change, and how a change gets merged.
Everyone taking part agrees to the Code of Conduct.
Before you start
Open an issue before writing a large change. Ilavrita has a deliberately narrow v0.1 scope (see ROADMAP.md), and a pull request that expands it will be hard to accept no matter how good the code is.
Small fixes — a typo, a broken link, a clearly wrong error message — need no issue. Just send the pull request.
Setting up
Requires Go 1.27+, and Node 22+ with pnpm 10+ for the workspace tooling.
git clone https://github.com/Ilavrita/Ilavrita.git
cd Ilavrita
make bootstrap
Ilavrita compiles against the Ilavrita embedded-runtime fork,
pinned as a submodule at third_party/embedded-runtime. Without it the build cannot
resolve the replace directive in go.mod, so a clone without submodules will
not compile. make bootstrap handles this.
make build # compile the server
make run # run it
make test # Go tests
make lint # golangci-lint
pnpm build # everything, through Turborepo
Architectural rules
These are enforced in review and, where possible, by golangci-lint:
- The FHIR boundary is ours. Routes, error shapes, search semantics and
versioning are defined by Ilavrita. A embedded-runtime collection name, admin route
or error format must never be visible through
/fhir/R4. - Only the storage backend imports embedded-runtime. Everything else depends on
the interfaces in
packages/storage. This is what keeps a second backend possible. - No SQL outside the storage backend. Higher layers reason in FHIR terms.
- Never advertise what is not implemented. If the CapabilityStatement says a resource is supported, there is a test proving it.
- Never log resource bodies. They can contain patient data. Log a request id and correlate.
Code style
Follow the conventions already in the file you are editing. Beyond that:
- Small functions that do one thing, with names that say what that is.
- Prefer a named type over a bare
stringwhen the value has meaning. - Comments explain why. If a comment restates the code, delete one of them.
- Do not comment out code — delete it; the history keeps it.
- Leave the area cleaner than you found it, without turning a fix into a rewrite.
Run make fmt before committing.
Tests
New behaviour ships with tests. A test should assert one thing, read clearly, run fast, and pass regardless of what ran before it.
Core FHIR behaviour must be testable without driving a browser.
Commits
One line. Conventional Commits format:
feat(search): add token parameter indexing
fix(fhir): return not-found rather than deleted for missing resources
docs: correct the backup restore order
Types in use: feat, fix, perf, refactor, docs, test, build, ci,
chore. A ! after the type, as in feat(fhir)!:, marks a breaking change.
Keep commits small and atomic — one logical change each. CHANGELOG.md and the
release notes are generated from these subjects by
git-cliff, so a vague subject line becomes a vague
changelog. Never hand-edit CHANGELOG.md; run make changelog.
Pull requests
- Sign off your commits (
git commit -s) to certify the Developer Certificate of Origin. - Fill in the pull request template. The interesting part is why.
- Keep the branch rebased on
dev. - CI must be green.
- A maintainer reviews and merges. See GOVERNANCE.md.
Ilavrita intends to offer a commercial licence alongside the AGPL. The contributor agreement that makes that possible is still under legal review, so until it lands we cannot accept large external contributions to the core. Small fixes are welcome now, and issues, testing and review always are.
Security
Do not open a public issue for a vulnerability. Follow SECURITY.md.
Running CI locally
act runs the GitHub Actions workflows on your
machine, which is faster than pushing to find out something is broken.
brew install act # or see the act README
make ci-local # build the runner image and run the CI workflow
act -l # list jobs
act push -j go # run a single job
Settings live in .actrc, and make ci-image builds the runner image
act uses. The stock act image loses node from PATH once actions/setup-go
runs, which breaks every JavaScript action after it; the image in
build/docker/act-runner.Dockerfile fixes
that so local runs match CI.
CodeQL and dependency review cannot run locally — both need GitHub's own services.
Source revision 9462213 · dev
