Skip to main content

Architecture Decisions

The ADRs are the canon for why the system is shaped the way it is. They live in the backend repo under docs/adr/ — this page is a map, not a replacement. Read the source ADR before making a structural decision it touches.

ADR-001 — Fork VLMIS into a Generic LMIS

Source: docs/adr/001-fork-vlmis-into-generic-lmis.md.

The founding decision. VLMIS was tightly coupled to Rwanda's DHIS2, TRVST, and HMIS. Rather than refactor in place (risky for the live deployment) or rewrite (throws away years of supply-chain logic), HLMIS is a fork with fresh git history, migrated incrementally. Every architectural rule on the Architecture page traces back here:

  • pluggable integrations behind interfaces, toggled at runtime
  • configuration table over environment variables
  • database-driven permissions, not hard-coded roles
  • TypeORM retained deliberately — not up for re-litigation

ADR-002 — Cross-Repo Version Tolerance & Rollout-Gating Flags

Source: docs/adr/002-cross-repo-version-tolerance.md.

Backend and frontend deploy independently. This ADR adds:

  • apiContractVersion — a small integer, bumped only on breaking API changes, compared bidirectionally by the frontend, rendered as a warn-only dismissible banner. Never blocks — a false lockout is worse than a missed warning. See API Contract & CI.
  • Feature flags reuse the configuration table under a features. key convention, global per backend instance (one instance = one deployment; there is no tenancy boundary in the codebase).
  • Both are exposed on GET /api/config/capabilities.

ADR-003 — OpenAPI Spec as a Versioned, CI-Enforced Contract

Source: docs/adr/003-openapi-spec-as-versioned-contract.md.

Makes openapi.json a real deliverable, not a side effect of the /docs page:

  • committed at the repo root, regenerated by a script that boots the real app
  • CI fails the build on any drift between code and the committed spec
  • the @nestjs/swagger CLI plugin is enabled so response types come from real TS return types
  • coverage is intentionally <100%, documented rather than faked

The full mechanics are on API Contract & CI.

Adding an ADR

New architecturally-significant decisions get a new numbered file in the backend's docs/adr/, following the existing format (Context / Decision / Consequences / Alternatives Considered). Add a matching summary section here so the docs site stays a complete index.