011: checked the registry's real consumers, and the question was the wrong shape

The exclusive-ownership rule turned on whether every reader of the mesh registry
could be served another way. Eighteen consumers open a direct connection. Four
groups, and only one is work.

The owner and its machinery keep reading, because they own it. The node appliers
are already resolved — ADR 0037 stops the host querying the mesh database,
decided for tier reasons with nothing to do with this.

The bulk are FOREIGN TENANTS. The work engine holds ten of its own tables in the
registry's database, the knowledge base two, pipeline logs one. Thirteen foreign
tables across three contexts, which is how-we-build §4's shared schema counted.

So the question was the wrong shape: the problem is not readers needing a new
route to data, it is tenants needing to move out. Tasks, agents and teams have
nothing to do with nodes and modules and are co-located by history. Give that
context its own database and its dependency on the registry shrinks to one
table.

A handful of genuine cross-context reads remain, small enough to enumerate
rather than estimate. The rule holds.

Left open: whether those reads want an interface or events. Asking which nodes
exist at the moment you need to know is a request; reacting when a node appears
is a subscription, and some consumers want both.
This commit is contained in:
2026-08-26 23:16:13 +02:00
parent 6b1aab6a1e
commit afcc355744
@@ -232,17 +232,35 @@ join, and it lags. Today a board queries the mesh's own database directly — th
it works, and this rule makes it a migration rather than a preference. The reason to pay it is
[`how-we-build`](../../00-META/how-we-build.md) §4's already-measured cost, not elegance.
### What it does not answer
### Checked against the real consumers
**The mesh's own registry is read by many things.** Under this rule they cannot read its tables,
so they consume its events or call its tools. That is achievable and it is a real change from
how the mesh works today, where reading the registry directly is ordinary — and it is the same
change [ADR 0037](../../02-DECISIONS/0037-the-host-applies-it-does-not-decide.md) already forces
on the host for unrelated reasons.
The rule's survival turned on whether every reader of the mesh's own registry could be served
some other way. **Eighteen consumers open a direct connection to it.** Four groups, and only one
of them is work.
Whether *every* consumer of the registry can be served by events and an interface is not
established here. It is the one thing that could make this rule unworkable, and it should be
checked against real consumers before the rule is recorded as a decision.
| 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. |
| **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. |
**Thirteen foreign tables live in the mesh's registry database**, belonging to three separate
contexts. That is [`how-we-build`](../../00-META/how-we-build.md) §4's shared schema, counted.
**So the question was the wrong shape.** The bulk of the problem is not readers needing a new
route to data — it is **tenants needing to move out**. Tasks, agents and teams have nothing to do
with nodes and modules; they are co-located by history. Give that context its own database and
its dependency on the registry shrinks to a single table.
What remains is a handful of genuine cross-context reads, small enough to enumerate rather than
estimate. **The rule holds.**
### What it still does not answer
Whether those remaining reads want an **interface** or **events**. A consumer asking *which
nodes exist* at the moment it needs to know is a request; one that must react *when a node
appears* is a subscription. Some will want both, and nothing here says which.
## A migration belongs to the consumer and runs on the provider