Order the records the way the system is learned
Jochen asked whether the order made sense. It did not -- it followed when things happened to be decided, which after consolidation is fictional anyway since record 5 alone folds decisions taken across a week. Concretely wrong before: the domain statement sat at 8, after five engineering rules; the constitution was scattered across 5, 12 and 17; the tiers landed at 15, 16, 21 and 22 with process records in between. Now it walks: what the mesh is (1-3), its tiers from the bottom up (4-8), what runs on them and how it gets there (9-10), how it is built (11-16), how it is checked (17-18), how we work (19-23). Two things made this safe rather than free. It is a permutation, not a compaction, so the renames go through temporary names -- otherwise two files want one slot and one is lost. And the reference rewrite is a single simultaneous pass, because almost every number moved into a slot another number was vacating; replacing one at a time would have cascaded and pointed things at the wrong record while still resolving. Verified: 284 [ADR NNNN](path) links across the repository, all with matching text and target. The ordering principle is now stated in 19 rather than left implicit -- the repository already said "the numbering is the flow" about its folders, and there was no reason for the records to be the exception.
This commit is contained in:
@@ -0,0 +1,93 @@
|
||||
---
|
||||
status: accepted
|
||||
date: 2026-08-26
|
||||
deciders: jochen
|
||||
reconstructed: false
|
||||
extends: 0009-modules-and-the-graph.md
|
||||
---
|
||||
|
||||
# 8. A context owns its store, exclusively
|
||||
|
||||
## Context
|
||||
|
||||
[ADR 0009](0009-modules-and-the-graph.md) settles what a module
|
||||
declares. This settles what a grant may be, and it is the half that **removes** things.
|
||||
|
||||
`how-we-build` §4 already says *contexts integrate through the record, never through a shared
|
||||
schema*, and states the cost: several domains share one forty-five-table schema, which is why
|
||||
work belonging to one context keeps having to be implemented in another.
|
||||
|
||||
That was written as a principle. Counted, it is thirteen foreign tables belonging to three
|
||||
separate contexts, living in the mesh's own registry database.
|
||||
|
||||
## Considered options
|
||||
|
||||
1. **A schema per consumer inside a shared database.** Namespaced, revocable by dropping the
|
||||
schema, with a cross-context join possible but deliberate. Rejected: it keeps the letter of
|
||||
§4 and leaves the temptation in place, and a boundary that is merely inconvenient to cross
|
||||
gets crossed.
|
||||
2. **Read-only roles on another context's store.** Rejected for the same reason and one worse:
|
||||
reading another context's tables couples you to its layout exactly as firmly as writing them,
|
||||
and the coupling is invisible until the owner changes a column.
|
||||
3. **Exclusive ownership.** Chosen.
|
||||
|
||||
## Decision
|
||||
|
||||
> **A context is granted only what it exclusively owns.**
|
||||
|
||||
No shared writes. No read-only role on another context's store. If you need what another context
|
||||
holds, you ask it or you subscribe to it.
|
||||
|
||||
**The unit is the context, not the process.** Everything inside a context — its service, its
|
||||
surface, its tools — reads its own store freely. A board showing the mesh's own nodes and
|
||||
modules is the mesh showing its own data, not a boundary crossing. What is forbidden is a
|
||||
*different* context reading it.
|
||||
|
||||
### Asking or subscribing is derived, not chosen
|
||||
|
||||
[ADR 0004](0004-a-node-and-how-it-joins.md) makes disconnection an ordinary situation. So:
|
||||
|
||||
- **Anything that must keep working while disconnected cannot ask** — there is nobody to ask. It
|
||||
keeps a local copy, which means subscribing.
|
||||
- **Anything where a stale answer is worse than none cannot subscribe.** A display may lag; a
|
||||
decision about whether a grant is still valid may not.
|
||||
|
||||
Neither is a query against another store, whatever transport it travels over.
|
||||
|
||||
## What this removes
|
||||
|
||||
The first clear list of what the design deletes rather than adds:
|
||||
|
||||
- **Grant kinds.** There is one: an exclusive resource. No schema grants, no read roles, no
|
||||
rules about who may see what inside a shared thing.
|
||||
- **The question of who owns which table**, and the guessing at revocation time. Removing a
|
||||
consumer drops what it was granted, whole.
|
||||
- **Cross-context migration ordering.** Two contexts migrating one database must be ordered
|
||||
against each other. Exclusive ownership means a context's migrations are ordered only against
|
||||
itself.
|
||||
- **A class of permission modelling** a shared store would otherwise need.
|
||||
|
||||
## Consequences
|
||||
|
||||
- **Cross-context reporting is harder, and that is the point.** Anything wanting to see across
|
||||
contexts consumes their events or calls their interfaces. That is §4's argument, and the cost
|
||||
it names is the one already paid.
|
||||
- **A single surface over several contexts still works** — that is what a surface is. It reads
|
||||
interfaces, not stores. This holds while the contexts sit behind **one** interface; splitting
|
||||
a context into its own deployable costs that, and the composition would have nowhere to live
|
||||
that tier 3 permits. **A real constraint on how far the control plane may be split.**
|
||||
- **Three contexts must move out of the registry database**, taking thirteen tables with them.
|
||||
Their dependency on the registry then shrinks to almost nothing — one of them needs a single
|
||||
table.
|
||||
- **The node appliers were already handled.** [ADR 0005](0005-the-node-host.md)
|
||||
stopped the host querying the mesh database for tier reasons unrelated to this, and it removes
|
||||
most of the remaining direct readers as a side effect.
|
||||
- **What a consumer does about events missed while disconnected is not decided** — replay from a
|
||||
point, ask once and resume, or rebuild. The question every projection has.
|
||||
|
||||
## References
|
||||
|
||||
- [`how-we-build.md`](../00-META/how-we-build.md) §4 — the rule this makes enforceable.
|
||||
- [Research 011](../01-RESEARCH/011-the-module-graph/worked-provider.md) — the count, the worked
|
||||
provider, and the dashboard case.
|
||||
- [ADR 0004](0004-a-node-and-how-it-joins.md) — why asking or subscribing is derived.
|
||||
Reference in New Issue
Block a user