The identity provider is settled as not-substrate: the mesh does not require one, tier 2 authenticates natively, and it is a hosted service like any other. Four substrate services, not five. The tier test's second step gains the verb that matters — can the control plane START without it, not function fully without it. That verb answers the forge and the registries. They are not substrate and they are not duplicated: the control plane starts and manages nodes without a forge, it just cannot change itself. One gitea module, tier 4, and the mesh's own instance is distinguished by what it is bound to rather than by being a different module — the same answer as postgres, from the same test. It also buys a property worth having: if the forge dies the mesh keeps running. Delivery needing them is not an upward dependency, resolved the way the constitution already says to: tier 2 declares requirements, tier 4 provides implementations, the binding is data. The mechanism is provisioning, and the new idea is that the control plane is itself a consumer. Self-hosting therefore becomes a state the mesh REACHES, not a precondition. A first node comes up from pinned external artifacts and re-binds to internal providers once they exist. Today's mesh assumes the second state from the first moment, which is why the first-node path needs a script that papers over an impossibility and is the least-exercised code in the system. Made explicit, the transition is also reversible. Research 007 and 008 opened for the two areas flagged as important and complex, scoped from the weaknesses the as-is layer already documents rather than started blank. And the origin: this began as a dotfiles repository. The first two days adopt dotfiles, add per-node overrides, and introduce service symlinking with an ignore file. The flat one-directory-per-tool catalogue, linking over copying, adoption of already-configured machines, per-node overrides and the desktop modules are all inherited rather than chosen for a mesh. That is the single most useful fact for anyone changing the catalogue, it strengthens ADR 0018 — the case for links was never made for a mesh — and it explains research 005's silent fifty: dotfiles-era entries for one tool never shared a domain because they never had one.
52 lines
3.2 KiB
Markdown
52 lines
3.2 KiB
Markdown
---
|
|
status: active
|
|
initiated: 2026-08-23
|
|
touches:
|
|
- 03-DESIGN/00-as-is/03-provisioning.md
|
|
- 02-DECISIONS/0005-capabilities-are-provisioned-on-declaration.md
|
|
- 01-RESEARCH/006-mesh-from-scratch/code-skeleton.md
|
|
became: []
|
|
---
|
|
|
|
# 007 — Provisioning as the mesh's core mechanism
|
|
|
|
## What is being investigated
|
|
|
|
Provisioning is the mechanism the whole mesh rests on: a module declares what it needs, and the
|
|
mesh makes it exist, generates the credential, records the grant, and puts the values where the
|
|
module will read them. [ADR 0005](../../02-DECISIONS/0005-capabilities-are-provisioned-on-declaration.md)
|
|
calls it the mesh's core concern rather than its plumbing.
|
|
|
|
[Research 006](../006-mesh-from-scratch/code-skeleton.md) then asks it to carry **more**: the
|
|
control plane becomes a consumer with its own requirements — a source of record, an image
|
|
registry, a package registry — satisfied by the same mechanism. That generalisation is only
|
|
safe if the mechanism is sound, and the as-is record says it is not, in named ways.
|
|
|
|
## Why now
|
|
|
|
Four weaknesses are already documented in
|
|
[`03-DESIGN/00-as-is/03-provisioning.md`](../../03-DESIGN/00-as-is/03-provisioning.md), each
|
|
observed rather than theorised:
|
|
|
|
- **Rotation has no fan-out.** A shared credential can be rotated without telling the peers
|
|
holding the old one. This has locked the mesh out of its own broker.
|
|
- **A grant is not a check.** The record says a resource was provisioned. Nothing verifies it
|
|
still exists, still has that credential, or is reachable from where the consumer runs.
|
|
- **A frozen password outlives its generation.** A generated secret written once diverges from a
|
|
persistent data directory initialised earlier, and presents as an authentication error.
|
|
- **No requirements is indistinguishable from provisioning that did not run.** A module that
|
|
declares nothing skips the stage, which is correct, and looks identical to failure.
|
|
|
|
Generalising a mechanism with these properties to the control plane's own dependencies would
|
|
make each of them fatal rather than annoying.
|
|
|
|
## The questions
|
|
|
|
| Question | Why it matters |
|
|
|---|---|
|
|
| What does a **grant** mean, exactly — a record that a resource was created, or a claim about the world that is continuously reconciled? | The difference between the current model and one where "provisioned" is checkable. Almost every weakness above is a symptom of the first answer. |
|
|
| How is a credential **rotated** with fan-out to every holder? | The mechanism grants easily and regrants not at all. This is the most damaging gap and it has taken the mesh down. |
|
|
| Can the **control plane** hold requirements, and what satisfies them before anything is installed? | The generalisation research 006 needs. Ties directly to the self-hosting transition. |
|
|
| What happens when a requirement **cannot** be satisfied — no provider, provider on an unreachable node, provider not yet installed? | Today this is silent or a stall. It should be a stated, visible state. |
|
|
| Does a requirement belong to a **module** or to one of its **parts**? | Research 006 splits `feature` into artifact and part. A part-scoped requirement means a database is not provisioned where the part that needs it is not installed. |
|