Point ADRs 0240 and 0254 at ADR 0283, bound a family member's name, and say the cost of a setting wait
mesh/merge-gate pass: the change touches no module of the mesh's graph
mesh/repo-check pass: its merge-check.sh passed
mesh/delivery delivered
mesh/delivery-group group feat/386-a-wait-for-the-operator delivered: every member is delivered

From the review of hq#294.
This commit is contained in:
jochen
2026-10-10 21:08:40 +02:00
parent 242a6c548b
commit 2648d571b3
5 changed files with 25 additions and 11 deletions
+3 -2
View File
@@ -265,8 +265,9 @@ and the operator act. **Recorded by** the controller's `identity` and `licences`
is the two ends of one credential, the consumer's and the provider's.
- **secret** — a credential or other value the vault keeps sealed and the node-engine unseals into a
file at apply ([ADR 0085](../02-DECISIONS/0085-a-secret-is-a-provision.md)).
- **secret family** — a module's own secrets declared as one name ending in `-*`, one member per part its
settings name (`smb-password-<source>`), each given by its full name and never made by the mesh
- **secret family** — a module's own secrets declared as one name ending in `-*`; each member is the prefix
and a name (`smb-password-<source>`, one per source the module's settings name), given by its full name
and never made by the mesh
([ADR 0283](../02-DECISIONS/0283-a-part-that-waits-for-the-operators-secret-or-setting-is-said-as-waiting-passes-the-first-node-gate-and-names-the-act.md)).
- **vault** — the module that owns every secret (`mesh-vault`,
[24 — The secrets vault](../03-DESIGN/01-to-be/24-the-secrets-vault.md)).
@@ -172,6 +172,13 @@ send* holds the module on this condition. Every start begins in `starting`, so a
send clears at the new build's start and anything after it is the new build's. At the gate's bound the
build is put back, as ADR 0236 §3 says.
> **The mechanism changed — 2026-10-10, by [ADR 0283](0283-a-part-that-waits-for-the-operators-secret-or-setting-is-said-as-waiting-passes-the-first-node-gate-and-names-the-act.md).** The four states, the
> condition and the gate's reading stand. A fifth state, `waiting`, now sits beside them: a tool check
> (rule 2) may answer *waits* as well as healthy or not, naming an own secret or a setting the operator has
> yet to give, and one look that says so is enough, inside the grace too. The controller checks the wait,
> says it as `needs-operator` rather than `unhealthy`, and the gate reads it as ADR 0254's *waits for a
> person*: a pass.
**5. A provider down is said once, at the provider.** A check names the provision it exercises. While
that provision's provider for this consumer is unhealthy on the record, the consumer's finding is held under
the provider's condition — listed there as waiting on it, raised as nothing of its own — and the consumer's
@@ -101,6 +101,12 @@ anyway, since the unit that cannot run is what the gate names first.
> **Narrowed — 2026-10-08.** Read with the dated correction under "What the gate cannot tell" in the
> consequences: only a move whose build puts an account in a group its previous build did not is
> excused, and what that costs while a login stays owed.
> **The mechanism changed — 2026-10-10, by [ADR 0283](0283-a-part-that-waits-for-the-operators-secret-or-setting-is-said-as-waiting-passes-the-first-node-gate-and-names-the-act.md).** The reading
> *waits for a person* now has a second source: a resource whose tool check says it waits for an own
> secret or a setting the operator has yet to give, checked by the controller. Unlike a new login, such a
> wait is excused for any build of the module, since every build owes it alike; the narrowing above still
> holds for the login.
2. **The gate passes a module that waits for a person, and carries the wait.** The reading counts as a
pass. The verdict says the wait ("… and it waits for a person: relogin needed on the laptop: …"), in the
plan, in the gate's record and in each carried build's verdict. Nothing is put back for it, so the group
@@ -126,7 +126,8 @@ named exactly, once. Nothing here conflicts with GENESIS.
6. **An own secret may be a family.** A name ending in `-*` in `own-secrets` declares one: its path holds
exactly one `*`, and it must say `"issued-by": "outside"`. A member is the prefix followed by a name's
characters (`smb-password-games`), given by that full name through `secret accept` or `secret-ask`, and
characters — a lower-case letter or digit, then lower-case letters, digits and hyphens, so never a `/`, a
`.` or anything else a path could be steered by (`smb-password-games`); any other name is refused, given by that full name through `secret accept` or `secret-ask`, and
placed at the path with `*` replaced by what follows the prefix. **The mesh never makes a member**: one
not given is no file, and the module reads its absence as not given. `module check` refuses a family
without `issued-by: outside`, or whose path does not hold exactly one `*`.
@@ -150,20 +151,19 @@ named exactly, once. Nothing here conflicts with GENESIS.
person's push is the way, as ADR 0254 already accepts for its wait.
- **A setting's wait is checked by name only.** The controller cannot read whether a free-form setting
covers a part. A module that says it waits for a setting it declares is believed; the needs-operator
condition says it in front of the operator, which is where a false one shows.
condition says it in front of the operator, which is where a false one shows. Since that condition is
never escalated by age, a module that wrongly says it waits passes its gates for as long as the operator
leaves the condition standing; that is accepted, because the operator sees it every time the conditions
are read.
- **The state is new on the wire.** A controller older than this reads `waiting` as not healthy and raises
nothing, so the gate fails at the bound as before. A node-engine older than this reads `waits` as not
healthy, as before. Rollout order: mesh-sdk, then the controller, then the node-engine, then the module.
healthy, as before. Order of delivery: mesh-sdk, then the controller, then the node-engine, then the module.
- **An outside secret not given stops being made only for a family.** A plain own secret marked
`issued-by: outside` is still made when not given; changing that touches every module that declares one,
and is tracked by issue 401.
- **The workstation's fstab line for the device** is adopted only once the source is mounted by the module
(issue 379).
> **The mechanism changed — 2026-10-10, by this record.** ADR 0263 rule 7 named one own secret,
> `smb-credentials`, holding every SMB login. Decision 7 above replaces it with the setting `smb-users` and
> the secret family `smb-password-*`. That a credential for a share is an operator-delivered secret stands.
## How it is checked
| Rule | Checked by |
@@ -173,7 +173,7 @@ named exactly, once. Nothing here conflicts with GENESIS.
| 3 The check | controller tests: a wait for an outside secret not given is excused; for one given, for one not declared, for one not `issued-by: outside`, and for a setting not declared, it is not, each with its reason |
| 4 The gate | controller tests: a module whose only resource not healthy is an excused wait passes with the wait in the verdict; the same with a second resource unhealthy is not yet; a later build is excused too |
| 5 The condition | controller tests: two statements of an excused wait raise `needs-operator`, a warning, resolver operator, its needs naming the desk prompt for a secret and the approval for a setting, never "nothing for you to do"; a statement without it clears it; a wait that fails the check raises `unhealthy` |
| 6 Families | controller tests: `module check` refuses each malformed family; a member is accepted and asked for at the desk by its full name, a name outside the family is refused; a member given is placed at its path; a member not given places nothing and composes |
| 6 Families | controller tests: `module check` refuses each malformed family; a member is accepted and asked for at the desk by its full name, a name outside the family is refused, and so is a member whose suffix holds a `/`, a `.` or an upper-case letter; a member given is placed at its path; a member not given places nothing and composes |
| 7 mounts | the module's tests: a source without username waits for `smb-users`, without password waits for `smb-password-<source>`, with both is written; a password file is read as one line; health answers `waits` and not `unhealthy`; nothing logs or answers a password |
| live | on the workstation, before the password: `conditions` shows `module.mounts.<machine>.needs-operator` naming the desk prompt, no `unhealthy`, and the next mounts walk passes its gate. After `secret-ask` and the operator's typing: the condition clears, and the source mounts when the device is on |
@@ -1,7 +1,7 @@
---
layer: to-be
status: in-progress
code: [mesh-host, mesh-controller, mesh-lab, mesh-catalog]
code: [mesh-host, mesh-controller, mesh-lab, mesh-catalog, mesh-sdk]
updated: 2026-10-10
decisions:
- 02-DECISIONS/0283-a-part-that-waits-for-the-operators-secret-or-setting-is-said-as-waiting-passes-the-first-node-gate-and-names-the-act.md