Files
hq/02-DECISIONS/0036-bootstrap-ends-at-a-usable-mesh.md
T
jschoubben 1111bd84d7 Establish the repo for the completed Phase 0-3 build
Settles the design repository now that the self-upgrade build is on main:
- Records the two decisions that shipped without a record — ADR 0077 (the
  controller/foundation/node vocabulary) and ADR 0078 (the store and broker are
  ordinary modules); accepts ADR 0075 and 0076, which shipped work rests on.
- Fills issue 051's amended-design and wires ADR 0078 into 07-the-foundation.
- Sweeps the repo rename (mesh-control -> mesh-controller) into the mutable docs
  now that the forge repo is renamed; updates the glossary note and repos.md.
- Fixes the six broken links from the design-doc renames, indexes the glossary,
  regenerates the decisions reading order.

Both checks (records.py, index.py) are green. Statuses stay honest: the build is
on main and lab-proven but not deployed as the production mesh, so the to-be docs
remain in-progress and the as-is layer (the hal mesh) is unchanged — graduation
to implemented + as-is belongs to deployment, not merge.

https://claude.ai/code/session_01D6qtiYU3P9jk3pnAXyAFyx
2026-09-17 00:04:58 +02:00

4.9 KiB

topic, status, date, deciders, reconstructed, extends
topic status date deciders reconstructed extends
the tiers accepted 2026-08-31 jochen false 02-DECISIONS/0035-one-implementation-several-surfaces.md

36. Bootstrap ends at a usable mesh, and the first credential comes from a person

Context

Bootstrap currently ends when the control plane starts (07-the-foundation.md). That is a mesh that runs and cannot yet be used by anybody who is not standing at the machine: the networked surfaces need an OAuth2 identity provider (ADR 0035), the provider is a module, and no module has been assigned.

So bootstrap should go further — through the identity provider and the first login — and stop at a mesh somebody can actually use.

One thing in the way, and it is not incidental. The mesh has never held a readable secret. The sealing code says what it does and why:

Make generates a secret and seals it to both ends, keeping no readable copy.

An initial administrator's credential is the first value a person must read. Everything else the mesh generates is something no human ever sees, and everything a human provides is something the mesh immediately stops being able to read.

Considered Options

  1. The mesh generates it and prints it once, to the terminal of whoever ran the bootstrap. Convenient, and needs no prompt. Rejected. It would give the control plane a plaintext secret for the first time — briefly, and only to one terminal, but the capability would then exist. An exception made for one case does not stay one: the next credential that is awkward to supply gets printed too, and the property that a copy of the mesh's database is a copy of nothing stops being checkable by reading the code.

  2. No password: a one-time link that lets the operator set their own. The nicest to use. Rejected for now — it needs a mechanism that does not exist, and the thing it improves is one prompt, once, on a new mesh.

  3. The operator supplies it. Adopted.

Decision

Bootstrap runs to a usable mesh: the substrate, the control plane, the identity provider as an ordinary module, its realm and client provisioned, an administrator able to log in, and the networked surfaces available.

The administrator's credential is supplied by the person doing the bootstrap, on standard input and not echoed — the path that already exists for a model-access key. The mesh seals it and cannot read it afterwards.

What is created is an account in the identity provider, not a user of the mesh. The mesh still has no user model and gains none here (ADR 0034). What this produces is the first login for the applications that have one.

The provisioning is ordinary. A realm, a client and a first account are what an identity module's provisioner makes from what the mesh granted it — the same shape as a database and a bucket, which are built and proven.

The surfaces arrive when their dependency does. The command API is not started with the control plane and then broken until identity exists; it becomes available once it can authenticate, the way anything else waits for a provider.

Consequences

The mesh still never holds a readable secret, and that sentence needs no exception clause. That is the whole reason for the prompt.

An unattended bootstrap is still possible, and the value still comes from outside. Automation supplying the credential is the operator supplying it. What is refused is the mesh inventing one — so an unattended bootstrap with no credential provided produces a mesh with no administrator, which is correct rather than broken.

Bootstrap gains an interactive step, and it is the only one. Worth stating because a bootstrap that cannot run without a person is a real constraint on how a node is stood up, and this is deliberate rather than an oversight.

The identity provider is still not substrate. It is assigned by the control plane, so it comes after it, and a thing that comes after cannot be a thing that must exist before (ADR 0033). Bootstrap running through it does not move it: bootstrap is a sequence, the substrate is a dependency.

And the recovery path is unchanged. When the identity provider is broken later — which is the failure that matters, not the one at first start — the command line still works, because it authenticates through nothing (ADR 0035).

References

  • ADR 0035 — the surfaces, and why the command line must keep working
  • ADR 0034 — the local account owns the mesh; this adds no user model
  • ADR 0033 — what must exist before the control plane, which this does not change