Architecture¶
banlieue describes its own architecture as code, in the
FINOS Common Architecture Language Model (CALM).
The model lives at
docs/architecture/calm/architecture.json
and the diagrams under this section are rendered from it by the CALM CLI —
they are never hand-edited.
Why CALM¶
A README that says "the controller talks to the K8s API" is unverifiable.
A CALM document encodes the same claim as structured data: there is a
relationship of type connects from service-banlieue-controller to
service-kubernetes-api, and the protocol is HTTPS. The renderer turns
that into a Mermaid diagram; the validator turns it into a build failure
when the model and the reality diverge.
The model also encodes our non-negotiables as controls (see below),
so a reviewer can confirm at a glance that the architecture-as-code still
matches the project's stated principles.
What's in the model¶
| Section | Count | Examples |
|---|---|---|
| Nodes | 16 | actors, the management cluster, the controller, planned providers, every CRD |
| Relationships | 13 | every wire (connects), every container (composed-of), every consumer (interacts) |
| Flows | 3 | Create, Swap, Delete a VirtualMachine |
| Controls | 3 | CRD-only contract, code-first CRDs, supply-chain scanning |
Each provider node carries its development phase in its display name
((planned, Phase 1B), etc.) so the picture is honest about what's
implemented today vs the target architecture.
Rendered artefacts¶
- System Diagram — every node and the wires between
them, in a single Mermaid
flowchart LR. - Architecture Flows — one Mermaid
flowchart TDper business flow (Create, Swap, Delete), with each step labelled.
Both pages are regenerated by:
make docs runs calm-diagrams first, so the published site is always
in sync with the CALM model on disk.
Controls modelled in CALM¶
The CALM controls block is where banlieue's invariants are encoded as
machine-readable requirements with links to evidence files and NIST
references. Today:
| Control | What it asserts | Evidence |
|---|---|---|
crd-only-contract |
The controller MUST NOT speak RPC, REST, or gRPC to providers — only CRDs via the K8s API. | CLAUDE.md, reasoning/crd-only-contract.md — NIST SP 800-53 SC-7, AC-4 |
code-first-crds |
All CRD YAML is generated from the Rust type system in banlieue-api via the crdgen binary; no hand-edited YAML. |
crates/banlieue-api/src/bin/crdgen.rs — NIST SP 800-218 SSDF PW.4, PS.1 |
capi-v1beta2-infra-machine-contract |
Every provider's infrastructure CRD satisfies the upstream Cluster API v1beta2 InfraMachine contract. | crates/banlieue-api/src/infrastructure/vsphere_machine.rs, concepts/infra-crds-capi.md — CAPI v1beta2 InfraMachine |
supply-chain-scanning |
CodeQL, cargo-deny, OpenSSF Scorecard, and SPDX headers on every source file. | .github/workflows/, deny.toml — NIST SP 800-218 SSDF PO.5, PS.1, PW.4 |
Working with the model¶
Validate¶
Validates architecture.json against the CALM 1.2 meta-schema. The CI
workflow calm-test.yaml
runs this on every push.
Re-render diagrams¶
Re-runs the Handlebars templates in
docs/architecture/calm/templates/mermaid/ and writes the output back
into this directory.
Generate a richer doc site¶
Uses calm docify (instead of calm template) and accepts the same
template directory. The two commands produce equivalent output today;
the docify form is reserved for future template bundles that emit
multi-page documentation sites.
Add a new node, relationship, or flow¶
When you ship a new provider, subsystem, or backend:
- Add a node to
architecture.jsonwith a stableunique-id. - Wire it into the right
deployed-in/composed-ofrelationship (almost alwaysrel-mgmt-cluster-contains-controllersorrel-kube-api-stores-crs). - Add a
connectsrelationship to the K8s API (every provider has one) and a secondconnectsrelationship to its backend. - If a flow now traverses the new edge, add a transition to the relevant flow.
- Run
make calm-validate && make calm-diagrams.
The full editor's guide lives at
docs/architecture/calm/README.md.