011: correct the rule — contexts, not processes

An earlier version argued a dashboard reading a dozen stores was caught by
exclusive ownership, because a dashboard is a surface and surfaces speak to an
interface. Wrong, and it drew the line in the wrong place.

The mesh's own board showing nodes, modules and deployments is not a separate
context reaching across a boundary — it is the mesh showing its own data.
Requiring it to go through an interface to reach facts its own context owns is
ceremony.

The rule is that a CONTEXT is granted what it exclusively owns. Everything
inside it — service, surface, tools — reads that store freely. What is forbidden
is a different context reading it.

Which is what the consumer count already showed: the problem was never surfaces,
it was three other contexts keeping their tables in the mesh's database.
This commit is contained in:
2026-08-26 23:25:46 +02:00
parent e71d532c2e
commit fa62c7f0e4
2 changed files with 14 additions and 20 deletions
@@ -208,29 +208,23 @@ first clear instance:
against itself.
- **A whole class of permission modelling** that a shared store would otherwise need.
### The hardest case for it: a dashboard reading everything
### The rule is about contexts, not processes
Raised immediately, and it is the right test — a board showing nodes, modules, pipelines, agents
and tasks wants to read a dozen stores. Under this rule it cannot read any of them.
An earlier version of this file argued that a dashboard reading a dozen stores was caught by the
rule, because a dashboard is a surface and surfaces speak to an interface. **That was wrong, and
it drew the line in the wrong place.**
**It survives, and not by luck: the board is a surface, and surfaces already may not do this.**
The skeleton puts `api/` in the control plane as *the one interface every surface speaks to*, and
tier 3 as *thin; no logic lives here*. A board reading stores directly is a surface reaching past
the context that owns the data — which the tier rule forbids for reasons that have nothing to do
with databases.
The mesh's own board showing nodes, modules and deployments is not a separate context reaching
across a boundary. It is the mesh showing its own data. Reading that store is not a violation
however it is done, and requiring it to go through an interface to reach facts its own context
owns would be ceremony.
So the dashboard is not a counter-example. It is an instance the rule catches, and the two rules
turn out to be one rule seen from two sides: **exclusive ownership is the tier rule, expressed in
terms of storage.**
**The rule is: a context is granted what it exclusively owns.** Everything inside that context —
its service, its surface, its tools — reads it freely. What is forbidden is a *different*
context reading it.
**The general shape, for anything that needs to see across many things:** consume the record and
own your own view. A reporting context builds a projection from events and reads its own store.
It does not read anybody else's.
**And the cost is not small, so it should be said plainly.** A projection is more work than a
join, and it lags. Today a board queries the mesh's own database directly — that is ordinary,
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.
Which is exactly what the count below shows: the problem was never surfaces. It was three other
contexts keeping their tables in the mesh's database.
### Checked against the real consumers