Reconcile: adopt initialization's consolidated HQ as canonical, re-home this session's new work #24
@@ -0,0 +1,99 @@
|
||||
---
|
||||
topic: the tiers
|
||||
status: accepted
|
||||
date: 2026-08-31
|
||||
deciders: jochen
|
||||
reconstructed: false
|
||||
extends: 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-substrate.md`](../03-DESIGN/01-to-be/07-the-substrate.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](0035-one-implementation-several-surfaces.md)), 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](0034-the-local-account-owns-the-mesh.md)). 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](0033-the-substrate-is-a-store-and-a-broker.md)). 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](0035-one-implementation-several-surfaces.md) — the surfaces, and why the command line
|
||||
must keep working
|
||||
- [ADR 0034](0034-the-local-account-owns-the-mesh.md) — the local account owns the mesh; this adds
|
||||
no user model
|
||||
- [ADR 0033](0033-the-substrate-is-a-store-and-a-broker.md) — what must exist before the control
|
||||
plane, which this does not change
|
||||
@@ -97,6 +97,7 @@ python3 00-META/checks/index.py fail if stale
|
||||
- **0030** — [Data outlives the mesh that declared it](0030-data-outlives-the-mesh-that-declared-it.md)
|
||||
- **0031** — [The control plane authenticates nobody, so identity is a module](0031-the-control-plane-authenticates-nobody.md)
|
||||
- **0033** — [The substrate is a store and a broker](0033-the-substrate-is-a-store-and-a-broker.md)
|
||||
- **0036** — [Bootstrap ends at a usable mesh, and the first credential comes from a person](0036-bootstrap-ends-at-a-usable-mesh.md)
|
||||
|
||||
### What runs on them, and how it gets there
|
||||
|
||||
|
||||
Reference in New Issue
Block a user