Every remaining cluster merged. Each was one design that had been split across
several records because it was worked out over days rather than at once.
the node host 8 -> 1 applies not decides, depends on nothing,
per operating system, root service, the
launcher, episodic, what a declaration is,
actions from the bundle only
a node and how it joins 4 -> 1 what a node is, joining, the link as
security boundary, the enrolment token
modules and the graph 7 -> 1 everything is a module, no domain modules,
three edges, provisioning, the core library
substrate and control 6 -> 1 the test, seven contexts, one control plane,
plane the authority is not a database, the named
products, the pinned bundle
connectivity 3 -> 1 a route is a grant, reachability declared,
filter rules
delivery 5 -> 1 reconciliation not a pipeline, artifacts,
the three silos, a failed step, the verdict
the lab 5 -> 1 (earlier)
how this repository 10 -> 1 (earlier)
works
Nothing was dropped. Each consolidated record carries the reasoning of the ones
it absorbs -- the measurements, the incidents, the alternatives rejected --
because that reasoning is the only reason to keep a record at all. What is gone
is the fragmentation: eight files to read to understand tier 0, when tier 0 is
one component.
The four superseded records went too. They existed to point at their
successors, and the successors now contain what they said.
The checker made this safe. Each merge left dangling links -- 38 files after
the host merge alone -- and it named every one. Nothing was found by reading,
and a manual pass would certainly have missed some, including references inside
AGENTS.md which every session loads.
3.9 KiB
layer, status, code, updated, decisions
| layer | status | code | updated | decisions | |||
|---|---|---|---|---|---|---|---|
| as-is | implemented |
|
2026-08-23 |
|
Provisioning
A module states what it needs. The mesh makes it exist, generates the credential, records the grant, and puts the values where the module will read them. Nobody writes a credential and nobody writes a topology.
This is the mesh's core concern rather than its plumbing — the property everything else is built on.
The declaration
A provider declares the resource type it can create and the network on which that resource is reachable from a container.
A consumer declares, per requirement: the provider module, the resource type, optionally a name and a target node, and a mapping from the resource's connection fields onto its own environment variables.
The consumer must also declare those variables as empty in its environment section. A mapped field with no declared variable is dropped — the value is produced and then discarded, because the generator only emits variables the manifest knows about.
What happens
Inside the pipeline the sequence is orchestrated by the coordinator and is not optional:
- The provisioner creates the resource and its credential, records the grant, and writes the mapped values as database overrides.
- The synchroniser regenerates the module's environment from those overrides.
- Only then is the service started.
Each step waits for the previous one's event. A module that declares no requirements skips the first step entirely — which is correct, and means the absence of provisioning is indistinguishable from provisioning that did not run.
Outside the pipeline the same two steps exist as direct operations, for debugging. They are not the normal path.
What can be provisioned
Providers exist for relational databases of two kinds, an object store, a cache, message-broker virtual hosts and access, an identity provider's clients, and a download category. Each returns the connection fields a consumer maps from — host, port, user, password, and whatever else the resource type implies.
A provider with no registered provisioner still records a grant, with an empty connection. This is deliberate and easy to misread: the grant exists, so the requirement looks satisfied, and nothing was created.
Cross-node grants
A requirement may name the node whose provider should satisfy it. The grant records consumer node and provider node separately, so a module on one node holding a database on another is the ordinary case rather than a special one.
For a containerised consumer, the provisioner returns the provider's routable name rather than a loopback address — the value has to be correct from inside a container on another machine.
Where this hurts
Rotation has no fan-out. A resource whose credential is shared by several consumers can be rotated by provisioning a new one, and the peers holding the old credential are not told. This has locked the mesh out of its own broker, and has caused a node's adoption to rotate a live shared password without informing anything that held it. Granting is easy; regranting is not modelled.
A frozen password outlives its generation. A generated password is written once. If the resource's persistent data directory already exists from an earlier initialisation, the stored credential and the generated one diverge, and the symptom is an authentication failure that looks like a configuration error.
Migrations against a provisioned resource run on the consumer's node, not the build node, and read the deployed artifact rather than the source tree. Both facts were wrong in the implementation for a period during which new provisioning migrations silently never ran.
A grant is not a check. The record says a resource was provisioned. Nothing verifies it still exists, still has the recorded credential, or is reachable from where the consumer runs.