Consolidate: 65 decision records to 23

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.
This commit is contained in:
2026-08-28 20:03:24 +02:00
parent 5e83ac2c22
commit 77f3a4cea7
90 changed files with 1041 additions and 4187 deletions
@@ -64,4 +64,4 @@ Recorded so they are not mistaken for oversights. Each is open, and each comes o
| Catalogue destination — one repository or many. | Open. Phase 4. |
| What the shared library keeps after extraction. | Open. Phase 3. |
| Where human agent modality is recorded — which user, on which node, a human agent acts as. | Open. Required by the model; not yet stored. |
| Which domains the modules outside the platform core group into. | Open, from [ADR 0017](../../02-DECISIONS/0017-modules-outside-the-core-are-grouped-by-domain.md), which settles the principle and deliberately not the list. |
| Which domains the modules outside the platform core group into. | Open, from [ADR 0044](../../02-DECISIONS/0044-modules-and-the-graph.md), which settles the principle and deliberately not the list. |
@@ -3,8 +3,8 @@ status: graduated
initiated: 2026-08-22
touches: [03-DESIGN/00-as-is/05-runtime-and-installation.md]
became:
- 02-DECISIONS/0057-the-host-is-a-root-service-installed-as-a-package.md
- 02-DECISIONS/0061-the-host-asks-an-init-for-start-and-restart.md
- 02-DECISIONS/0037-the-node-host.md
- 02-DECISIONS/0037-the-node-host.md
- 03-DESIGN/01-to-be/05-the-node-host.md
---
@@ -57,14 +57,14 @@ which is why the effort sat `active` for five days after being answered. Recorde
finding that is the point of a sweep.
**The third option is what the mesh adopted.** `Docker is the supervisor for everything` is
[ADR 0057](../../02-DECISIONS/0057-the-host-is-a-root-service-installed-as-a-package.md): the
[ADR 0037](../../02-DECISIONS/0037-the-node-host.md): the
host is a plain process on the machine and everything above tier 0 is a container. The substrate
bootstrap declares no service at all — it is package, container, action, container — so the
44-of-44 restart policies this effort counted are the supervision, exactly as it argued.
**Fate-sharing was the hard part, and it is solved the way this effort predicted.** It said any
mesh-native supervisor inherits the problem *unless it sits outside the mesh's own process
tree*. [ADR 0061](../../02-DECISIONS/0061-the-host-asks-an-init-for-start-and-restart.md) puts
tree*. [ADR 0037](../../02-DECISIONS/0037-the-node-host.md) puts
the launcher there: it supervises the host as a child and shares no code with it, so a host that
cannot start is still recovered.
@@ -2,17 +2,17 @@
status: graduated
initiated: 2026-08-23
touches:
- 02-DECISIONS/0017-modules-outside-the-core-are-grouped-by-domain.md
- 02-DECISIONS/0044-modules-and-the-graph.md
- 03-DESIGN/00-as-is/10-module-catalogue.md
- 03-DESIGN/00-as-is/02-modules-and-manifests.md
became:
- 02-DECISIONS/0044-a-module-declares-presence-instantiation-and-exclusion.md
- 02-DECISIONS/0054-things-that-change-together-share-an-authority.md
- 02-DECISIONS/0044-modules-and-the-graph.md
- 02-DECISIONS/0044-modules-and-the-graph.md
---
# 005 — Which domains the catalogue groups into
[ADR 0017](../../02-DECISIONS/0017-modules-outside-the-core-are-grouped-by-domain.md) settles
[ADR 0044](../../02-DECISIONS/0044-modules-and-the-graph.md) settles
that modules outside the platform core are grouped by domain rather than by single function,
and deliberately does not settle the list. This effort settles the list — and, first, tests
whether the premise survives measurement.
@@ -59,12 +59,12 @@ open questions below.
this effort — which is why it stayed open after being resolved.
**Whether provider modules group at all** — *no.*
[ADR 0044](../../02-DECISIONS/0044-a-module-declares-presence-instantiation-and-exclusion.md):
[ADR 0044](../../02-DECISIONS/0044-modules-and-the-graph.md):
there is no `networking` thing to install, there are concrete modules named individually. Folders
assert relationships; edges record them. *Provider* stops being a category at the same time.
**Whether "group or leave" is even the right pair of options** — *it was not*, and that is the
useful finding. [ADR 0054](../../02-DECISIONS/0054-things-that-change-together-share-an-authority.md)
useful finding. [ADR 0044](../../02-DECISIONS/0044-modules-and-the-graph.md)
reframes it: things that change together share an **authority**, not a package. This effort's own
measurement is what that record rests on — reachability being the *only* place modules genuinely
co-change is why connectivity is a context and why nothing else needed one.
@@ -3,7 +3,7 @@ status: active
initiated: 2026-08-23
touches:
- 02-DECISIONS/0015-mesh-brokers-nodes-host-agents-think.md
- 02-DECISIONS/0017-modules-outside-the-core-are-grouped-by-domain.md
- 02-DECISIONS/0044-modules-and-the-graph.md
- 03-DESIGN/00-as-is/00-overview.md
- 03-DESIGN/01-to-be/00-work-breakdown.md
became: []
@@ -26,7 +26,7 @@ disk, and where today's catalogue lands.
Every structural decision so far has been a **correction**: eight contexts replacing thirty-three
modules ([ADR 0015](../../02-DECISIONS/0015-mesh-brokers-nodes-host-agents-think.md)), domains
replacing single-function modules
([ADR 0017](../../02-DECISIONS/0017-modules-outside-the-core-are-grouped-by-domain.md)). A
([ADR 0044](../../02-DECISIONS/0044-modules-and-the-graph.md)). A
correction inherits the frame of the thing it corrects, and two of the mesh's oldest problems
look unsolvable from inside that frame:
@@ -88,7 +88,7 @@ the catalogue where modules genuinely change together under one intent. The skel
|---|---|
| Does the record — the event log contexts integrate through — belong to the substrate or the control plane? | It is infrastructure by shape and domain by content. Placing it wrong reintroduces a circularity. |
| One repository per tier, or per context? | Already open from ADR 0015 as "catalogue destination — one repository or many". The skeleton assumes per tier and does not settle it. |
| ~~Does an unprivileged node earn a place in the inventory, or only a presence?~~ | **Answered 2026-08-25** by the operator: a node is a *managed machine inside the mesh*, not an unprivileged something — and a disconnected node is still a node, in a different situation. The question posed a class distinction; the answer is that there is none, and what varies is **state**. Recorded as [ADR 0036](../../02-DECISIONS/0036-a-node-is-a-managed-machine.md). |
| ~~Does absorbing overlay, filtering, packages, supervision and the container runtime make the host too large?~~ | **Answered 2026-08-25** — [`host-size.md`](host-size.md). Measured: the absorption is smaller than the machinery that already applies state, and eight of ten adapters already carry no dependency. The risk is not size but direction, and it is two modules wide. The claim survives with its scope corrected — the host carries one concern, *apply declared state on this machine*, of which the six are instances. Recorded as [ADR 0037](../../02-DECISIONS/0037-the-host-applies-it-does-not-decide.md), designed in [`05-the-node-host.md`](../../03-DESIGN/01-to-be/05-the-node-host.md). |
| ~~Does an unprivileged node earn a place in the inventory, or only a presence?~~ | **Answered 2026-08-25** by the operator: a node is a *managed machine inside the mesh*, not an unprivileged something — and a disconnected node is still a node, in a different situation. The question posed a class distinction; the answer is that there is none, and what varies is **state**. Recorded as [ADR 0036](../../02-DECISIONS/0036-a-node-and-how-it-joins.md). |
| ~~Does absorbing overlay, filtering, packages, supervision and the container runtime make the host too large?~~ | **Answered 2026-08-25** — [`host-size.md`](host-size.md). Measured: the absorption is smaller than the machinery that already applies state, and eight of ten adapters already carry no dependency. The risk is not size but direction, and it is two modules wide. The claim survives with its scope corrected — the host carries one concern, *apply declared state on this machine*, of which the six are instances. Recorded as [ADR 0037](../../02-DECISIONS/0037-the-node-host.md), designed in [`05-the-node-host.md`](../../03-DESIGN/01-to-be/05-the-node-host.md). |
| ~~Four substrate services or five?~~ | **Answered conditionally**, which is the honest form — [`07-the-substrate.md`](../../03-DESIGN/01-to-be/07-the-substrate.md). The substrate is *what the control plane consumes and cannot grant itself*. The identity provider qualifies only if the control plane delegates authentication; if it authenticates natively it is an ordinary hosted service. The count follows from a decision not yet taken, and asserting four was asserting that decision. |
| Does `feature` survive? | The skeleton splits it in two and argues the conflation is what makes the delivery pipeline hard to reason about. Unproven. |
@@ -160,7 +160,7 @@ neither option covers, and it is the most common one.
| **Absorbed into the host** | It is not a module at all. It is part of what "managing a machine" means, and belongs in tier 0. | overlay membership, packet filtering, package management, service supervision, container runtime, filesystem management |
| **Substrate** | The control plane cannot exist without it. Pinned, host-applied. | relational store, bus, object store, image registry |
| **Control-plane context** | It decides something across nodes. | connectivity policy, inventory, delivery, provisioning, observability |
| **Workload module** | The mesh hosts it. Grouped per [ADR 0017](../../02-DECISIONS/0017-modules-outside-the-core-are-grouped-by-domain.md). | media library, desktop session, collaboration tooling |
| **Workload module** | The mesh hosts it. Grouped per [ADR 0044](../../02-DECISIONS/0044-modules-and-the-graph.md). | media library, desktop session, collaboration tooling |
| **Leaves the repository** | A standalone application, per [ADR 0010](../../02-DECISIONS/0010-applications-live-in-their-own-repository.md). | the applications identified in research 005 |
**The first fate is the finding.** Research 005 measured the reachability cluster — proxy,
@@ -97,7 +97,7 @@ a second surface would have to reimplement.
This is the whole of the bootstrap answer, and per this repository's own rule it must say how
it is checked: a dependency-direction lint in the build, failing on an upward import. A tier
rule enforced by intention is the same as no tier rule — that is
[ADR 0008](../../02-DECISIONS/0008-a-failed-step-fails-the-job.md) applied to architecture.
[ADR 0058](../../02-DECISIONS/0058-delivery.md) applied to architecture.
## Move 1 — the substrate is applied, not delivered
@@ -163,7 +163,7 @@ So the evidence and the gap point the same way. `connectivity` owns:
This is an addition to an accepted record, so it is a decision, not a drafting choice. It
belongs in a new record that extends ADR 0015 the way
[ADR 0017](../../02-DECISIONS/0017-modules-outside-the-core-are-grouped-by-domain.md) does —
[ADR 0044](../../02-DECISIONS/0044-modules-and-the-graph.md) does —
not written here.
### Where the networking actually lives
@@ -195,7 +195,7 @@ The invitation was to check whether the concept survives. It does not, in one pi
Today a **feature** means both *a thing built once* and *a thing selected per node*, and the
delivery pipeline is hard to reason about precisely because those have different cardinality
and one word ([ADR 0014](../../02-DECISIONS/0014-build-publish-and-deploy-are-three-silos.md)
and one word ([ADR 0058](../../02-DECISIONS/0058-delivery.md)
is the pipeline half of the same confusion).
Split it:
@@ -3,7 +3,7 @@ status: active
initiated: 2026-08-23
touches:
- 03-DESIGN/00-as-is/03-provisioning.md
- 02-DECISIONS/0005-capabilities-are-provisioned-on-declaration.md
- 02-DECISIONS/0044-modules-and-the-graph.md
- 01-RESEARCH/006-mesh-from-scratch/code-skeleton.md
became: []
---
@@ -14,7 +14,7 @@ became: []
Provisioning is the mechanism the whole mesh rests on: a module declares what it needs, and the
mesh makes it exist, generates the credential, records the grant, and puts the values where the
module will read them. [ADR 0005](../../02-DECISIONS/0005-capabilities-are-provisioned-on-declaration.md)
module will read them. [ADR 0044](../../02-DECISIONS/0044-modules-and-the-graph.md)
calls it the mesh's core concern rather than its plumbing.
[Research 006](../006-mesh-from-scratch/code-skeleton.md) then asks it to carry **more**: the
@@ -3,12 +3,12 @@ status: graduated
initiated: 2026-08-23
touches:
- 03-DESIGN/00-as-is/04-delivery.md
- 02-DECISIONS/0014-build-publish-and-deploy-are-three-silos.md
- 02-DECISIONS/0013-an-artifact-is-build-output.md
- 02-DECISIONS/0058-delivery.md
- 02-DECISIONS/0058-delivery.md
- 01-RESEARCH/006-mesh-from-scratch/code-skeleton.md
became:
- 02-DECISIONS/0058-delivery-ends-in-a-declaration.md
- 02-DECISIONS/0063-delivery-is-reconciliation-not-a-pipeline.md
- 02-DECISIONS/0058-delivery.md
- 02-DECISIONS/0058-delivery.md
---
# 008 — The coordinator: a change checked in becomes a deployed state
@@ -49,14 +49,14 @@ working across the transition to self-hosted providers.
because the first was honest about what it did not fix.
**Does the coordinator dispatch stages, or converge nodes on a declaration?** — *Converge.*
[ADR 0058](../../02-DECISIONS/0058-delivery-ends-in-a-declaration.md): a pipeline ends when the
[ADR 0058](../../02-DECISIONS/0058-delivery.md): a pipeline ends when the
declaration is updated, and the host applies it and reads back — so the reporter is the applier.
**Does the three-silo split survive?** — *Yes, with the third redefined.* The cardinality
observation holds; the third silo is not a stage any more.
**How does a change become a pipeline, reliably?** — *It does not become a pipeline at all.*
[ADR 0063](../../02-DECISIONS/0063-delivery-is-reconciliation-not-a-pipeline.md) applies 0058's
[ADR 0058](../../02-DECISIONS/0058-delivery.md) applies 0058's
move one level up: the control plane holds what source exists and what has been built, and builds
the difference. **An event makes it fast; nothing makes it necessary.** The failures this effort
catalogued — a truncated commit list, a broken path match — become latency rather than silence.
@@ -83,7 +83,7 @@ load-bearing question first.
## What is NOT closed by this
[ADR 0063](../../02-DECISIONS/0063-delivery-is-reconciliation-not-a-pipeline.md) names four costs
[ADR 0058](../../02-DECISIONS/0058-delivery.md) names four costs
and one of them is a real risk rather than a trade: **a reconciler that cannot reach its target
retries forever, and without something that notices, the failure is silence** — which is the
fault this effort exists to catalogue, reintroduced in a new place. That belongs to observability
@@ -98,4 +98,4 @@ and it is not designed.
| How does a change **become** a pipeline, reliably? | Detection has failed for reasons unrelated to the change, silently. |
| What produces a **verdict**, and what is it a verdict about? | Ties to the lab ([ADR 0016](../../02-DECISIONS/0016-the-lab.md)) and to a module carrying its own assertions. |
| How does delivery work **before self-hosting**, and across the transition? | From research 006: source and artifacts start external and are re-bound to internal providers. The coordinator has to be indifferent to which. |
| Does the **three-silo** split survive the artifact/part split? | [ADR 0014](../../02-DECISIONS/0014-build-publish-and-deploy-are-three-silos.md) is cardinality-driven, and research 006 renames the thing the cardinality is about. |
| Does the **three-silo** split survive the artifact/part split? | [ADR 0058](../../02-DECISIONS/0058-delivery.md) is cardinality-driven, and research 006 renames the thing the cardinality is about. |
+11 -11
View File
@@ -2,14 +2,14 @@
status: graduated
initiated: 2026-08-25
became:
- 02-DECISIONS/0044-a-module-declares-presence-instantiation-and-exclusion.md
- 02-DECISIONS/0044-modules-and-the-graph.md
- 02-DECISIONS/0045-a-context-owns-its-store.md
- 03-DESIGN/01-to-be/06-the-control-plane.md
- 03-DESIGN/01-to-be/07-the-substrate.md
touches:
- 02-DECISIONS/0002-everything-is-a-module.md
- 02-DECISIONS/0017-modules-outside-the-core-are-grouped-by-domain.md
- 02-DECISIONS/0036-a-node-is-a-managed-machine.md
- 02-DECISIONS/0044-modules-and-the-graph.md
- 02-DECISIONS/0044-modules-and-the-graph.md
- 02-DECISIONS/0036-a-node-and-how-it-joins.md
- 03-DESIGN/00-as-is/02-modules-and-manifests.md
- 03-DESIGN/00-as-is/10-module-catalogue.md
- 04-ISSUES/007-an-installed-package-is-not-a-capability/00-report.md
@@ -21,9 +21,9 @@ touches:
> *instantiation*, and both are **runtime** edges — they answer *what does this need in order to
> run*. Delivery needs a different question answered — *what has to be rebuilt when this changes*
> — and that is a **build** edge, fixed inside an artifact rather than negotiated when it runs.
> Recorded by [ADR 0064](../../02-DECISIONS/0064-a-build-edge-is-a-third-kind.md), which also
> Recorded by [ADR 0044](../../02-DECISIONS/0044-modules-and-the-graph.md), which also
> notes what this effort's three entities turn out to be good for
> ([ADR 0065](../../02-DECISIONS/0065-the-core-library-is-the-meshs-domain.md)).
> ([ADR 0044](../../02-DECISIONS/0044-modules-and-the-graph.md)).
## What is being investigated
@@ -76,10 +76,10 @@ concluded — `provider:` is a dependency edge that is not read as one, which ma
for a working mesh come out without a database; and the resolver continues past a cycle and
past a missing dependency, contrary to ADR 0008.
[ADR 0017](../../02-DECISIONS/0017-modules-outside-the-core-are-grouped-by-domain.md) proposes
[ADR 0044](../../02-DECISIONS/0044-modules-and-the-graph.md) proposes
grouping modules by domain. [Research 005](../005-domain-grouping/analysis.md) measured that
proposal and found its evidence holds in exactly one place — reachability — which
[ADR 0037](../../02-DECISIONS/0037-the-host-applies-it-does-not-decide.md) has since absorbed
[ADR 0037](../../02-DECISIONS/0037-the-node-host.md) has since absorbed
into the host. The measured case for domain grouping has therefore been consumed by a decision
taken for unrelated reasons, and what remains is fifty modules that co-change with nothing.
@@ -102,7 +102,7 @@ and abandoned in favour of one concept with facets, for a reason worth keeping:
Filing decisions that follow from nothing are the disease research 005 measured. A second
taxonomy would reproduce it.
So [ADR 0002](../../02-DECISIONS/0002-everything-is-a-module.md) survives, and the question
So [ADR 0044](../../02-DECISIONS/0044-modules-and-the-graph.md) survives, and the question
becomes what a module must be able to **declare**.
## The shape being investigated
@@ -111,7 +111,7 @@ Five declarations, of which two exist today.
| Declaration | Today | Notes |
|---|---|---|
| **requires a resource** — a database, a bucket | yes | provisioning, [ADR 0005](../../02-DECISIONS/0005-capabilities-are-provisioned-on-declaration.md) |
| **requires a resource** — a database, a bucket | yes | provisioning, [ADR 0044](../../02-DECISIONS/0044-modules-and-the-graph.md) |
| **provides a resource** | yes | as above |
| **requires another module** | **no** | the dependency edge — the graph's substance |
| **excludes another module** | **no** | installing A makes B unavailable |
@@ -174,7 +174,7 @@ Struck-through rows are answered, with where. The rest are live.
| ~~What does the graph **delete**?~~ | For the existing system: nothing, it is already there ([`analysis.md`](analysis.md)). For the design: the module/resource distinction, the interface as a kind of thing, capability checking as a separate mechanism, domain grouping, and — the first clear deletion — **grant kinds**, once a module may only be granted what it exclusively owns ([`worked-provider.md`](worked-provider.md)). |
| ~~Is an interface a module, or a name?~~ | A **name**, and only where providers are genuinely substitutable. The adapter is what creates one; without an adapter there is a **tag**, which describes and does not bind ([`proposal.md`](proposal.md)). |
| ~~Where do domain modules fit?~~ | They do not. There is core infrastructure — concrete modules named individually, not flavourable, nothing standing in front of them. |
| ~~What happens to domain grouping?~~ | Superseded. Folders assert relationships; edges record them. What grouping was for is a tag and a query. [ADR 0017](../../02-DECISIONS/0017-modules-outside-the-core-are-grouped-by-domain.md) is `proposed` and should be superseded rather than narrowed. |
| ~~What happens to domain grouping?~~ | Superseded. Folders assert relationships; edges record them. What grouping was for is a tag and a query. [ADR 0044](../../02-DECISIONS/0044-modules-and-the-graph.md) is `proposed` and should be superseded rather than narrowed. |
| ~~Is there one kind of edge?~~ | **No — two.** *Presence*, where a thing must exist, and *instantiation*, where a provider makes something for a consumer and hands back credentials. Instantiation implies presence, not the reverse. |
| ~~When two modules provide one name, who chooses?~~ | Neither the consumer naming a node nor the consumer not caring. The consumer declares the **scope of its own need** — shared across its instances, or one each — the mesh binds, and the binding is written down and sticky. Where it is written follows the scope. |
| ~~Can several modules share one database?~~ | **No.** A module is granted only what it exclusively owns — no shared writes and no read role on another's store, because reading couples you to its layout just as firmly. |
+3 -3
View File
@@ -36,7 +36,7 @@ another module's provision is treated as an implicit edge to that module**, so a
not have to declare the same relationship twice.
So *ordering by the graph* — which
[ADR 0043](../../02-DECISIONS/0043-a-declaration-is-an-ordered-list-of-owned-resources.md) says
[ADR 0037](../../02-DECISIONS/0037-the-node-host.md) says
the control plane will do — is not a thing to build. It is a thing to call.
## Finding 3 — the most important edges in the mesh are invisible
@@ -82,7 +82,7 @@ means.
## Finding 4 — the resolver continues past faults it should stop on
Two behaviours, both contrary to
[ADR 0008](../../02-DECISIONS/0008-a-failed-step-fails-the-job.md):
[ADR 0058](../../02-DECISIONS/0058-delivery.md):
- **A cycle warns and falls back to input order.** A cycle means no correct order exists; the
resolver proceeds with an arbitrary one and logs a line.
@@ -91,7 +91,7 @@ Two behaviours, both contrary to
Neither has fired in the current catalogue — there are no cycles and nothing dangling — which
is why nobody has noticed. They are latent, and they are in the component that
[ADR 0043](../../02-DECISIONS/0043-a-declaration-is-an-ordered-list-of-owned-resources.md) makes
[ADR 0037](../../02-DECISIONS/0037-the-node-host.md) makes
responsible for the ordering a host will apply without question.
## Finding 5 — placement is decided in the catalogue
+1 -1
View File
@@ -13,7 +13,7 @@ it is simply up. *A relational store, a message broker, an object store, a dashb
**2 — A system package with configuration.** Not a container. Installed into the machine,
configured through files, run by the service manager. *A firewall, a resolver, an overlay.*
Note: [ADR 0037](../../02-DECISIONS/0037-the-host-applies-it-does-not-decide.md) says applying
Note: [ADR 0037](../../02-DECISIONS/0037-the-node-host.md) says applying
these is the host's job — so what the module contributes is the *deciding*, not the doing.
**3 — An application a person launches.** Installed on a node, started by a human, running only
+1 -1
View File
@@ -55,7 +55,7 @@ registry. **Tier 2, delivery.**
**Resources — desired state on a machine.** `configs`, `service`, `systemd`, `vhost`, `tools`.
Applied, converged, idempotent — which is exactly what
[ADR 0043](../../02-DECISIONS/0043-a-declaration-is-an-ordered-list-of-owned-resources.md)
[ADR 0037](../../02-DECISIONS/0037-the-node-host.md)
already describes and what the host already does. **Tier 0.**
**Actions — run once, against something that is not this machine.** `migrations`, `seeds`,
+1 -1
View File
@@ -132,7 +132,7 @@ The question the effort opened with, answered for the design rather than for wha
to install. There is **core infrastructure**, which is a set of concrete modules named
individually — a firewall, a store, a resolver — with no flavour and no grouping module
standing in front of them.
- **Domain grouping as structure** ([ADR 0017](../../02-DECISIONS/0017-modules-outside-the-core-are-grouped-by-domain.md)).
- **Domain grouping as structure** ([ADR 0044](../../02-DECISIONS/0044-modules-and-the-graph.md)).
Folders assert relationships; edges record them. What grouping was for — finding things,
seeing what belongs together — is a **tag** and a *query* over the graph, neither of which
anybody has to keep true by hand.
@@ -149,7 +149,7 @@ Steps 2 and 3 happen **before there is a mesh to do them**. So provisioning is n
control-plane service that consumers use; it is part of the bootstrap, and part of what the
carried bundle has to be able to express.
**Which strains what a declaration is.** [ADR 0043](../../02-DECISIONS/0043-a-declaration-is-an-ordered-list-of-owned-resources.md)
**Which strains what a declaration is.** [ADR 0037](../../02-DECISIONS/0037-the-node-host.md)
has the host applying *declared state on this machine*. A database inside a running store is not
a file or a unit — and at bootstrap it is, at least, local: the store is on the same machine as
the host applying the bundle.
@@ -158,7 +158,7 @@ Later it is not. A consumer on one node provisioned from a store on another is t
case, and reaching it is not the host's job.
**Resolved as two mechanisms, which is the answer rather than a compromise**
([ADR 0047](../../02-DECISIONS/0047-the-bundle-may-carry-actions-the-link-may-not.md)). The host
([ADR 0037](../../02-DECISIONS/0037-the-node-host.md)). The host
runs bootstrap actions locally from the bundle; the control plane provisions across the mesh
afterwards. Different actors, different scopes, different trust paths — so there is no single
operation with a tier boundary running through it.
@@ -279,7 +279,7 @@ of them is work.
| Group | What happens under the rule |
|---|---|
| **The owner and its machinery** — the mesh module, the SDK, the environment and configuration synchronisers, secrets | Nothing. It owns the database. |
| **Node appliers** — the overlay, the shell daemon, the resolver | **Already resolved.** [ADR 0037](../../02-DECISIONS/0037-the-host-applies-it-does-not-decide.md) stops the host querying the mesh database, decided for tier reasons with nothing to do with this. |
| **Node appliers** — the overlay, the shell daemon, the resolver | **Already resolved.** [ADR 0037](../../02-DECISIONS/0037-the-node-host.md) stops the host querying the mesh database, decided for tier reasons with nothing to do with this. |
| **Foreign tenants** — the work engine (10 tables), the knowledge base (2), pipeline logs (1) | They need **their own database**. They are not reading the registry; they are storing their own data in it. |
| **Genuine cross-context reads** — the work engine reads `nodes`; two others read a handful | The only ones needing an interface or events. |
@@ -312,7 +312,7 @@ not the distinction.
| when the other side is down | you cannot answer | you answer from your copy |
| what you must handle | a round trip that can fail | events you missed while you were down |
**What decides is not taste.** [ADR 0036](../../02-DECISIONS/0036-a-node-is-a-managed-machine.md)
**What decides is not taste.** [ADR 0036](../../02-DECISIONS/0036-a-node-and-how-it-joins.md)
makes disconnection an ordinary situation rather than an exception. So:
> **Anything that must keep working while disconnected cannot use a request** — there is nobody
@@ -354,14 +354,14 @@ proves it cannot be a global rule.
**What happens to a grant when the consumer is removed?** The game is uninstalled. Its database
still exists, holding its data. Dropping it silently is data loss; keeping it forever is a leak.
[ADR 0043](../../02-DECISIONS/0043-a-declaration-is-an-ordered-list-of-owned-resources.md) says
[ADR 0037](../../02-DECISIONS/0037-the-node-host.md) says
the host removes what it applied and no longer declares — but this is not on the host, it is
inside another module's state, and the same reasoning does not obviously carry.
**Where does node-derived configuration come from?** (3) The control plane composes a
declaration, and cannot know this machine's memory. Either the host fills in a blank the
declaration leaves — which makes the host decide something, against
[ADR 0037](../../02-DECISIONS/0037-the-host-applies-it-does-not-decide.md) — or the control
[ADR 0037](../../02-DECISIONS/0037-the-node-host.md) — or the control
plane reads the node's inventory first and composes with it. The second is consistent and means
a declaration is composed *per node from what the node reported*, which is a stronger claim than
anything recorded so far.
@@ -421,7 +421,7 @@ But two things differ *between* them, and both matter more than the similarity.
[ADR 0001](../../02-DECISIONS/0001-nodes-communicate-over-a-broker.md) makes the broker the
channel every node takes work from, and
[ADR 0039](../../02-DECISIONS/0039-the-link-is-the-security-boundary.md) makes it the security
[ADR 0036](../../02-DECISIONS/0036-a-node-and-how-it-joins.md) makes it the security
boundary — everything a node applies arrives through it.
So the module providing the broker is also **the way modules are managed**. A declaration cannot
@@ -430,7 +430,7 @@ reconfigured. Nothing else in the catalogue has that property; the store is cons
control plane but is not how the control plane *reaches* anything.
This is exactly what the carried bundle exists for
([ADR 0038](../../02-DECISIONS/0038-a-node-joins-by-linking-first.md)): the broker is raised from
([ADR 0036](../../02-DECISIONS/0036-a-node-and-how-it-joins.md)): the broker is raised from
what the host carries, before there is a channel, because there is no other way to raise it.
Recorded here because it is a constraint on *one module*, not a general rule, and a schema with
no way to say so hides it.
@@ -439,7 +439,7 @@ no way to say so hides it.
The broker is one per mesh — a single point of failure and a single point of trust, by decision
rather than by accident. The store cannot be: a node that must keep working while disconnected
([ADR 0036](../../02-DECISIONS/0036-a-node-is-a-managed-machine.md)) cannot depend on a database
([ADR 0036](../../02-DECISIONS/0036-a-node-and-how-it-joins.md)) cannot depend on a database
somewhere else.
Same nine properties, opposite answers. Which settles something the cases file left open: **how
@@ -2,7 +2,7 @@
status: active
initiated: 2026-08-26
touches:
- 02-DECISIONS/0043-a-declaration-is-an-ordered-list-of-owned-resources.md
- 02-DECISIONS/0037-the-node-host.md
- 02-DECISIONS/0004-managed-files-are-generated-never-edited.md
- 03-DESIGN/01-to-be/05-the-node-host.md
- 03-DESIGN/00-as-is/05-runtime-and-installation.md
@@ -34,7 +34,7 @@ carry everything in the bundle, download at apply time, or have something push t
first. Downloading fails on the first node, which cannot fetch the image registry from the image
registry it is trying to start.
> **Qualified by [ADR 0046](../../02-DECISIONS/0046-the-installer-fetches-what-it-pins.md).** The
> **Qualified by [ADR 0048](../../02-DECISIONS/0048-the-substrate-and-the-control-plane.md).** The
> reframing below still holds for what a *tailored installer* contains — the missing pieces for a
> given machine. It does **not** have to hold for container images: the installer fetches those
> by digest, because a real machine has a network and the sealed case is the lab.
@@ -77,7 +77,7 @@ starts applying. Three states, and the middle one is new:
> unmanaged → **adopted once** → generated
**And it crosses a boundary just drawn.** [ADR 0043](../../02-DECISIONS/0043-a-declaration-is-an-ordered-list-of-owned-resources.md)
**And it crosses a boundary just drawn.** [ADR 0037](../../02-DECISIONS/0037-the-node-host.md)
says the host never touches what it did not create — the rule that stops a converger deleting
what the mesh never put there. Adoption is the deliberate act of taking ownership of exactly
that. The rule needs a companion rather than an exception: *never, unless adoption made it the