diff --git a/02-DECISIONS/0009-modules-and-the-graph.md b/02-DECISIONS/0009-modules-and-the-graph.md index a7b8db8..c5f0753 100644 --- a/02-DECISIONS/0009-modules-and-the-graph.md +++ b/02-DECISIONS/0009-modules-and-the-graph.md @@ -96,6 +96,47 @@ grants clients, a mail server grants mailboxes. It is a facet, not a kind. **A module may also declare what it claims**, because some things cannot coexist and that is a fact about the module rather than about a particular node. What that means precisely is below. +### Where the answer to a requirement is allowed to live + +*Written 2026-08-29, from building it. The table above distinguishes **presence** from +**instantiation** and this is the half of that distinction nobody had noticed was missing: not +what the edge hands over, but **where the thing on the other end is.*** + +Two different things were both being written as a requirement: + +| | *a shell*, *a display server*, *a private network* | *a database*, *an object store*, *an identity provider* | +|---|---|---| +| where the answer lives | **this machine** | **somewhere in the mesh** | +| how it is answered | install another module here | find the node already running it | +| what is missing if absent | a module to assign here | **a decision about where**, which is nobody's to make silently | + +Answering the second like the first installs a database on every machine that uses one, which is +what it did. + +**So a provided name carries a scope**, the same idea a claim already has, and written short in +the ordinary case so the few that are not node-scoped stand out rather than drowning. Scope is a +property of **the name, not of each provider**: two modules disagreeing about whether a database +is local would make one requirement mean two things depending on which happened to answer it, so +that is refused. + +**A requirement answered from the mesh is never satisfied by installing it here.** Nothing, and +the mesh refuses and says which module to assign somewhere. Two, and it refuses and says how to +choose — the same rule as everywhere else, for the same reason: picking is guessing, and the wrong +guess puts somebody's data on a machine they did not choose. + +**Choosing is recorded per node**, because that is the granularity the choice actually has — two +machines may reasonably use two different databases and a mesh-wide answer could not say so. A +choice pointing at a machine that does not provide the thing is refused rather than quietly +replaced by one that does, and a single available provider does not override a choice either. +**Both are the same rule: the mesh does not overrule a person, and it does not move data without +being told to.** + +**What this is a prerequisite for.** Knowing *which node* answers is the first half of handing a +credential back — you cannot be given a database's password before it is settled whose database it +is. So a node's resolution now records what it takes from elsewhere, which is both the only part +of its set that stops working when a *different* machine goes away, and the place a credential +will hang. + ### An edge has two directions, and only one of them is built *Written 2026-08-29, from building it. The row above already says a consumer **supplies a target