diff --git a/02-DECISIONS/0009-modules-and-the-graph.md b/02-DECISIONS/0009-modules-and-the-graph.md index aca46f5..08fe2ab 100644 --- a/02-DECISIONS/0009-modules-and-the-graph.md +++ b/02-DECISIONS/0009-modules-and-the-graph.md @@ -219,9 +219,46 @@ mesh holds a dead credential, the failure [recorded in ADR 0001](0001-mesh-brokers-nodes-host-agents-think.md) as consumers on three nodes holding one for two days. -**What remains is a provisioner** — something that creates the database user the credential is -for. The mesh now generates the secret, tells the provider to create it and the consumer to use -it; nothing yet acts on the telling. +### The provisioner, which is where the mesh stops + +*Written 2026-08-30, from building one and running it against a real database.* + +**A password nothing was told to create authenticates nowhere.** The mesh generates one, seals it +to both ends and cannot read it — so it cannot tell the software to start accepting it either. +Something on the providing machine reads what arrived and makes it true. That is a provisioner. + +**It belongs to the module, not to the mesh**, and the boundary is the same one that keeps +third-party software running *on* the mesh rather than being *of* it +([ADR 0001](0001-mesh-brokers-nodes-host-agents-think.md)). The control plane decides and never +touches a machine. **What the mesh owns is the contract**, which is two files the host writes from +an ordinary declaration: + +| | | +|---|---| +| the manifest | every consumer, what it asked for, and **where** its credential is | +| one file per consumer | that credential, alone in it | + +Two files because the mesh discarded the value and cannot compose a document containing it. As +before, the constraint produces the better shape: the readable half stays readable and auditable +in the declaration, and the secret half changes only when the secret does. + +**It reconciles; it is never told what changed.** It runs after every declaration and must reach +the same state from wherever it starts. Three consequences, and each of them is a fault that has +been shipped somewhere: + +- **the password is set every time, not only on creation** — otherwise the role already exists, + nothing happens, and a rotation reports success while changing nothing +- **what it made and nobody asks for any more is removed** — otherwise a consumer that left keeps + a working login for ever and nothing ever says so. This is the same rule the host follows about + [removing what it declared and no longer declares](../04-ISSUES/010-the-first-declaration-destroys-the-substrate/00-report.md) +- **what it did not make is left alone** — otherwise it cannot be run on a system that predates + it, which is every system anybody would want to adopt + +**A missing credential is refused rather than worked around.** A role created without one is a +login nothing can use, and nothing would report it until something tried to connect. + +**This is where the mesh stops**, and saying so is the point of the section. It decides, delivers +and can prove what it delivered; the last inch belongs to whoever knows what `create role` means. **One check that only became possible now.** Two machines wired together across no private network is a mesh that reports itself configured and does not work, and the failure surfaces as a