Merge pull request 'ADR 0283: a part waiting for the operator's secret or setting is said as waiting and passes the first-node gate (issue 386)' (#294) from feat/386-a-wait-for-the-operator into main
This commit was merged in pull request #294.
This commit is contained in:
+10
-1
@@ -265,6 +265,10 @@ 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 `-*`; 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)).
|
||||
- **grant** — what an identity may call or reach, bounded by the provisions it requires
|
||||
@@ -387,7 +391,7 @@ planner, the walk). **Downstream of** Module, Core, Health and repair and Data.
|
||||
**Purpose.** To notice what is wrong with the mesh, say it once, repair what may be repaired unattended,
|
||||
and record what was done by hand. **Recorded by** the controller's condition store.
|
||||
**Upstream of** Change and delivery (the first-node gate) and Operator and conversation (a condition
|
||||
becomes a message). **Decided by** ADR 0227, 0231, 0240, 0252.
|
||||
becomes a message). **Decided by** ADR 0227, 0231, 0240, 0252, 0283.
|
||||
**Uses:** node, module, node-engine (Core).
|
||||
|
||||
- **health** — a module's or a core component's statement of how it is alive and ready, which the
|
||||
@@ -395,6 +399,11 @@ becomes a message). **Decided by** ADR 0227, 0231, 0240, 0252.
|
||||
- **relogin needed** — an account's health when the group database lists it in an account group and its
|
||||
running session, started before, does not have that group yet. Said by the node-engine as the module's
|
||||
resource of kind `account`; it clears at the first look after a new login (ADR 0252).
|
||||
- **waiting** — a resource's health when its module's tool check says it waits for the operator: a named own
|
||||
secret or setting of the module, not given yet, without which a part cannot work. Not a fault: the
|
||||
controller checks it and says it as the condition `needs-operator`, naming the act, and the first-node gate
|
||||
reads it as *waits for a person*
|
||||
([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)).
|
||||
- **probe** — one look at one thing's health, run by whoever owns the verdict; what a probe returns is a
|
||||
**finding**, before it becomes a condition.
|
||||
- **signal** and **watchdog** — something that must keep happening (a heartbeat, a report after a send),
|
||||
|
||||
@@ -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
|
||||
|
||||
+6
@@ -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
|
||||
|
||||
+7
@@ -111,6 +111,13 @@ Rejected:
|
||||
vault and unsealed on the node as a file (ADR 0086). The module writes one credentials file per source
|
||||
from it, readable by root only, which the mount unit names. No password is written in a
|
||||
repository, a manifest or `/etc/fstab`.
|
||||
|
||||
> **The mechanism changed — 2026-10-10, by ADR 0283.** That a share's credential is an operator-delivered
|
||||
> secret, issued outside the mesh and unsealed on the node as a file, stands. The one secret
|
||||
> `smb-credentials` holding every login is replaced: the username is the setting `smb-users`, and each SMB
|
||||
> source's password is its own one-line secret `smb-password-<source>`, a member of a secret family the
|
||||
> mesh never makes a value for, so it can be typed at the desk prompt one source at a time
|
||||
> ([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)).
|
||||
8. **Health:** a share that should always be reachable and is not, for 5 minutes, raises one plain
|
||||
condition, naming the share, the node and since when. It is the `mounts` module's health (ADR 0240),
|
||||
judged by its tool `mounts_health`, whose finding is *share unreachable*; no new kind of condition is
|
||||
|
||||
+192
@@ -0,0 +1,192 @@
|
||||
---
|
||||
topic: what runs on it
|
||||
status: accepted
|
||||
date: 2026-10-10
|
||||
deciders: jochen
|
||||
reconstructed: false
|
||||
extends: 02-DECISIONS/0240-a-module-says-how-it-is-healthy-and-the-node-engine-judges-it.md
|
||||
---
|
||||
|
||||
# 283. A part that waits for the operator's secret or setting is said as waiting, passes the first-node gate, and names the act
|
||||
|
||||
## Context
|
||||
|
||||
On 2026-10-10 the mounts module ([ADR 0263](0263-a-share-is-a-provision-a-node-mounts-it-on-demand-and-only-nodes-that-ask-get-it.md))
|
||||
was given an occasional source on the workstation: the gaming device's SMB share, approved by the operator on
|
||||
their phone at 15:06 through a settings proposal ([ADR 0277](0277-a-trusted-setting-is-proposed-through-a-verb-and-set-on-the-operators-warrant-and-a-modules-own-secret-is-asked-for-and-typed-at-the-desk.md)).
|
||||
Its login was never given. What followed is issue 386, with issue 379 behind it:
|
||||
|
||||
- **The module said the wait, and the mesh read it as a fault.** Its health tool answered *not healthy*:
|
||||
"the source … cannot be mounted: its login is not given". The node-engine has two answers from a tool
|
||||
check, healthy or not (ADR 0240 rule 2), so it stated the resource `unhealthy`. The controller raised
|
||||
`module.mounts.<machine>.unhealthy`, urgent after four hours, whose plain words said "Nothing for you to
|
||||
do … It clears as soon as it runs again". Both halves were false: it waited for the operator, and nothing
|
||||
but the operator would clear it.
|
||||
- **The first-node gate failed a build for it.** A fix to mounts sat in its gate for ten minutes at 0 of 3
|
||||
passes and was put back (`build.mounts.<machine>.rolled-back`), because the gate reads a module's stated
|
||||
health and the resource was unhealthy. Every later walk waited behind it, since one walk runs at a time.
|
||||
The fault was not the build's: any build would have said the same until the login was given.
|
||||
- **The intended path could not give what the module wanted.** The module took one own secret,
|
||||
`smb-credentials`, holding a `[source]` section with `username=` and `password=`. The desk prompt that
|
||||
`secret-ask` opens (ADR 0277 §5) takes one hidden line. A later build of the module read a one-line form,
|
||||
but a login typed blind as `[name] username=… password=…` is a line the operator gets wrong without seeing
|
||||
it, and several sources would need several lines the prompt cannot take.
|
||||
- **The mesh puts a value of its own in a secret nobody gave.** For an own secret not given, the controller
|
||||
makes a random value and places it, even for one whose manifest says `"issued-by": "outside"`. That is how
|
||||
the module came to read "line 1 is not key=value inside a [section]": the file held forty random
|
||||
characters. ADR 0228 already says no value of the mesh's works in place of an outside party's; making one
|
||||
anyway hides "not given" behind "given and wrong".
|
||||
- **One precedent exists.** ADR 0254 made a wait for a person's new login a gate reading of its own,
|
||||
*waits for a person*, which passes and is carried in the verdict, and a condition of its own,
|
||||
`relogin-needed`, the operator's, never escalated by age. Issue 339 did the same for a directory used as
|
||||
found. Both are recognised by the controller from what the node-engine says of a kind of resource. Neither
|
||||
lets a module say it waits.
|
||||
|
||||
**Checked against GENESIS.** *Failure must be loud*, and a wait is not a failure: a gate that undoes a build
|
||||
for the operator's missing step says something false, loudly, and a condition that says "nothing for you to
|
||||
do" about the one thing only the operator can do is the quiet half of the same fault. *Evidence over
|
||||
assertion*: a module saying it waits is an assertion, so the controller checks it against what it holds
|
||||
before it excuses anything. *When something needs a decision, you are asked, with the context*: the act is
|
||||
named exactly, once. Nothing here conflicts with GENESIS.
|
||||
|
||||
## Considered Options
|
||||
|
||||
**How the wait is said.**
|
||||
|
||||
1. *Keep it unhealthy, and fix only the words of the condition.* The gate still fails every build sent
|
||||
while a secret is owed. Rejected.
|
||||
2. *A reason prefix on an unhealthy resource, as `relogin needed` and `used as found` are.* Works with no
|
||||
new state, but a module's tool says free text, and a prefix on free text is a word anyone can type.
|
||||
Rejected for a module's own check.
|
||||
3. **A third answer of a health tool, *waits*, carried as a state of its own, `waiting`, naming each thing
|
||||
it waits for: an own secret or a setting of the module, by name, and what the operator gives, in
|
||||
words.** Chosen. Structured, so the controller can check it; a state, so nothing that reads `unhealthy`
|
||||
counts it as a fault.
|
||||
|
||||
**What the gate does with it.**
|
||||
|
||||
4. *Read it as waiting*, as a provider down is read: no pass, no failure. The walk then waits for the
|
||||
operator, possibly for days, and every walk behind it with it. That is issue 386 without its rollback.
|
||||
Rejected.
|
||||
5. **The reading *waits for a person* of ADR 0254, carried in the verdict: a pass.** Chosen, under a check:
|
||||
the controller excuses a wait only when what it names is the module's and is not given (decision 3).
|
||||
|
||||
**Whether only the move that brought the wait is excused**, as ADR 0254 narrowed its own.
|
||||
|
||||
6. *Yes.* A new login is owed because one build added a group, so a later build cannot have brought it. A
|
||||
secret not given is owed by every build alike; excusing only the first would fail every fix sent while
|
||||
the operator is away, which is the stall this record removes. Rejected.
|
||||
7. **No: any build is excused while what it waits for is, on the record, not given.** Chosen. The cost is in
|
||||
the consequences.
|
||||
|
||||
**How a module with several sources takes one hidden line per password.**
|
||||
|
||||
8. *One secret holding every login, typed in a set form.* Issue 386's own path. Rejected above.
|
||||
9. *One fixed secret per module for the password, with the username as a setting.* One SMB source per
|
||||
machine, and a second needs a change to the manifest. Rejected.
|
||||
10. **An own secret may be declared as a family, `<prefix>-*`: one member per part the settings name, each
|
||||
one line, given by its full name.** Chosen. The username is an ordinary setting, since it is not a
|
||||
secret, and it travels through a settings proposal the operator approves on their phone.
|
||||
|
||||
## Decision
|
||||
|
||||
1. **A health tool answers one of three: healthy, unhealthy, or waits.** The answer keeps `healthy` and
|
||||
`why`, and gains `state` (`healthy`, `unhealthy`, `waits`) and `waits`: a list, each naming exactly one
|
||||
own secret (`secret`) or one setting (`setting`) of the module by name, the part that waits (`part`),
|
||||
and what the operator gives, in words with no path, address or value (`what`). `waits` means nothing
|
||||
else of the module is wrong. A module with a fault beside a wait answers `unhealthy` and says both.
|
||||
An answer that says `waits` with no wait, or a wait naming neither or both, is read as unhealthy with
|
||||
that reason. The type, its constructors and its reader are mesh-sdk's (`go/health`), so the module and
|
||||
the node-engine read one shape; an answer without `state` is read from `healthy` as before.
|
||||
|
||||
2. **The node-engine states such a resource `waiting`**, a fifth state beside healthy, unhealthy,
|
||||
starting, held and unknown (ADR 0240 §4), with its waits. One look that says it is enough, inside the
|
||||
grace too: it is a statement, not a flake that a second look might not repeat. The next look that says
|
||||
anything else replaces it.
|
||||
|
||||
3. **The controller checks a wait before it excuses it.** A wait for a secret is excused only when the
|
||||
module's manifest declares that own secret (or the family it belongs to, decision 6) as
|
||||
`"issued-by": "outside"`, and the store holds no value given for it on that machine. A wait for a
|
||||
setting is excused only when the manifest declares that setting. A wait that fails the check is judged
|
||||
as unhealthy, saying why ("says it waits for … , which was given at …").
|
||||
|
||||
4. **The first-node gate reads an excused wait as *waits for a person* (ADR 0254), a pass**, and the
|
||||
verdict carries it: "… and it waits for the operator: <what> on <machine>". Nothing is put back for it.
|
||||
Any build of the module is excused while the wait checks out; a module with anything else unhealthy is
|
||||
judged as before.
|
||||
|
||||
5. **The wait is said to the operator as the module's condition `module.<module>.<machine>.needs-operator`**,
|
||||
in place of `unhealthy`: a warning, the operator's, never escalated by age, raised on two statements in a
|
||||
row and cleared on the first that no longer says it, as every module condition is. Its plain words
|
||||
(ADR 0253) name the act and never say "nothing for you to do": for a secret, "Needs you: type <what> at
|
||||
<machine>'s desk prompt. An agent opens the prompt for you when asked"; for a setting, "Needs you: approve
|
||||
<setting> of <module> on <machine> when an agent proposes it". Its summary names the secret or setting and
|
||||
the line (`nox secret ask <machine> <module> <secret>`), for whoever looks closer. A wait that fails the
|
||||
check raises the module's `unhealthy` condition instead.
|
||||
|
||||
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 — 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 `*`.
|
||||
|
||||
7. **The mounts module takes a source's login as a setting and a secret.** The username is the setting
|
||||
`smb-users` (`name=username`, space-separated). The password is the family `smb-password-*`, one member
|
||||
per SMB source, one hidden line each. A source whose username or password is not given is not mounted
|
||||
and is said as waiting for that setting or secret, never as unhealthy. The `smb-credentials` secret and
|
||||
its form are dropped: nothing was ever given for it.
|
||||
|
||||
## Consequences
|
||||
|
||||
- **Issue 386's walk passes.** A build of mounts sent while the password is owed passes its gate with the
|
||||
wait carried, and later walks go on.
|
||||
- **The operator reads one sentence that names the act**, "Needs you: type the password of the source …
|
||||
at <machine>'s desk prompt", which clears once the password is given and the source is said healthy or
|
||||
absent.
|
||||
- **What the gate cannot tell.** While a wait checks out, a build that also breaks the waiting part itself
|
||||
(a source whose mount would fail for a reason of its own once the password came) passes. That fault is
|
||||
said after the password is given, as the module's own `unhealthy` condition, and a newer build or a
|
||||
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. 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. 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).
|
||||
|
||||
## How it is checked
|
||||
|
||||
| Rule | Checked by |
|
||||
|---|---|
|
||||
| 1 Three answers | mesh-sdk `go/health` tests: each constructor's JSON; the reader on an answer with no state (healthy and not), on `waits` with no wait, a wait naming neither or both, a `what` with a path or an address — each read as unhealthy with its reason |
|
||||
| 2 The state `waiting` | node-engine (mesh-host) `internal/liveness` tests: a tool check answering `waits` is stated `waiting` with its waits, in grace and after; the next healthy answer is `healthy`; an engine reading an answer without `state` judges as before |
|
||||
| 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, 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 |
|
||||
|
||||
## References
|
||||
|
||||
- Issue 386 (the gate), issue 379 (the workstation's two hand-written mounts).
|
||||
- [ADR 0240](0240-a-module-says-how-it-is-healthy-and-the-node-engine-judges-it.md) (the states, the tool
|
||||
check), [ADR 0254](0254-a-wait-for-a-persons-new-login-is-not-a-gates-failure-and-each-module-of-a-send-keeps-its-own-pass.md)
|
||||
(*waits for a person*), [ADR 0253](0253-a-condition-says-itself-to-the-operator-in-plain-words-beside-its-summary.md)
|
||||
(plain words), [ADR 0277](0277-a-trusted-setting-is-proposed-through-a-verb-and-set-on-the-operators-warrant-and-a-modules-own-secret-is-asked-for-and-typed-at-the-desk.md)
|
||||
(the proposal and the desk prompt), [ADR 0228](0228-a-value-given-by-hand-lives-only-until-its-modules-first-good-start.md)
|
||||
(issued outside), [ADR 0263](0263-a-share-is-a-provision-a-node-mounts-it-on-demand-and-only-nodes-that-ask-get-it.md)
|
||||
rule 7.
|
||||
- [To-be 48](../03-DESIGN/01-to-be/48-a-module-says-how-it-is-healthy.md) §4 and §5, and
|
||||
[to-be 52](../03-DESIGN/01-to-be/52-shares-and-mounts.md): the designs this amends.
|
||||
- mesh-sdk, mesh-controller, mesh-host and mesh-catalog: the branches `feat/386-a-wait-for-the-operator`.
|
||||
@@ -1,9 +1,10 @@
|
||||
---
|
||||
layer: to-be
|
||||
status: in-progress
|
||||
code: [mesh-host, mesh-controller, mesh-lab, mesh-catalog]
|
||||
updated: 2026-10-08
|
||||
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
|
||||
- 02-DECISIONS/0254-a-wait-for-a-persons-new-login-is-not-a-gates-failure-and-each-module-of-a-send-keeps-its-own-pass.md
|
||||
- 02-DECISIONS/0240-a-module-says-how-it-is-healthy-and-the-node-engine-judges-it.md
|
||||
- 02-DECISIONS/0241-a-machine-says-how-its-network-is-and-an-outside-writer-of-a-mesh-file-is-a-finding.md
|
||||
@@ -121,8 +122,16 @@ period do the timing, without an execution per look from outside.
|
||||
|
||||
**Per module and long-running resource, the node-engine keeps a state:** `healthy`, `unhealthy` (with the
|
||||
reason: down, restarting, or the check's failure in words), `starting` (inside grace), `held` (§1) or
|
||||
`unknown` (nothing could be read). With it: since when, the failing streak, and the restarts counted. Every
|
||||
start of a resource — a new build, a recreate, a restart — begins in `starting`.
|
||||
`unknown` (nothing could be read), or `waiting` (its tool check says it waits for the operator, below).
|
||||
With it: since when, the failing streak, and the restarts counted. Every start of a resource — a new build,
|
||||
a recreate, a restart — begins in `starting`.
|
||||
|
||||
**A tool check answers one of three: healthy, unhealthy, or waits**
|
||||
([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)).
|
||||
*Waits* says nothing of the module is wrong but a part that cannot work until the operator gives something:
|
||||
each wait names one own secret or one setting of the module, the part, and what the operator gives, in words
|
||||
with no path, address or value. The answer's shape is mesh-sdk's, read by the module and the node-engine
|
||||
alike. One look that says it states the resource `waiting`, inside the grace too, with its waits.
|
||||
|
||||
**Said three ways**, as the core already says its own state:
|
||||
|
||||
@@ -146,6 +155,14 @@ place of `unhealthy` ([ADR 0254](../../02-DECISIONS/0254-a-wait-for-a-persons-ne
|
||||
cleared as above, its summary one sentence that says to log out and in again. When the login has come and
|
||||
a unit still fails, it clears and `unhealthy` is raised.
|
||||
|
||||
**A wait for the operator's secret or setting is its own condition**, `module.<module>.<machine>.needs-operator`,
|
||||
in place of `unhealthy` (ADR 0283): a warning, the operator's, never escalated by age, raised and cleared as
|
||||
above. The controller first checks the wait: a secret it names must be the module's own, declared issued
|
||||
outside the mesh, and hold no value given on that machine; a setting must be one the module declares. Its
|
||||
plain words name the act — "Needs you: type the password of the source … at <machine>'s desk prompt", or
|
||||
approve the setting when an agent proposes it — and never say there is nothing to do. A wait that fails the
|
||||
check is said as `unhealthy`, with why.
|
||||
|
||||
**`status`** lists it with the other conditions; **`node show`** shows each module's resources with their
|
||||
state and since when, so "is it working" has an answer without opening a terminal on the machine.
|
||||
|
||||
@@ -174,6 +191,11 @@ fails at the bound until the operator logs in again.
|
||||
The node-engine names the account on every resource that runs in an account's own manager, which is how
|
||||
the controller tells such a unit from one that is broken.
|
||||
|
||||
**A wait for the operator's secret or setting is a wait for a person too** (ADR 0283, issue 386). A module
|
||||
whose only resources not healthy are `waiting`, each wait checked as in §4, reads **waits for a person**: a
|
||||
pass, carried in the verdict, nothing put back. Unlike a new login, a secret not given is owed by every
|
||||
build alike, so any build of the module is excused while the wait checks out.
|
||||
|
||||
**Each module of a send keeps its own pass** (ADR 0254). A send is still judged as one, with one verdict.
|
||||
The gate also counts, per module, the judgings in a row that found it healthy or waiting for a person;
|
||||
when the send fails, a module whose count reached the passes asked keeps a pass, said "on its own", and is
|
||||
|
||||
@@ -7,6 +7,7 @@ code:
|
||||
- mesh-catalog modules/mounts
|
||||
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
|
||||
- 02-DECISIONS/0277-a-trusted-setting-is-proposed-through-a-verb-and-set-on-the-operators-warrant-and-a-modules-own-secret-is-asked-for-and-typed-at-the-desk.md
|
||||
- 02-DECISIONS/0263-a-share-is-a-provision-a-node-mounts-it-on-demand-and-only-nodes-that-ask-get-it.md
|
||||
- 02-DECISIONS/0051-shared-data-is-the-operators.md
|
||||
@@ -55,7 +56,7 @@ The glossary holds the three words.
|
||||
| `nfs-server` | the catalogue | holds `node-nfs-server`, provides the provision, writes its export file, runs the service, opens 2049 to the private network |
|
||||
| `mounts` | the catalogue | holds `node-mounts`, writes a unit pair per share, keeps each share's state, serves the tools |
|
||||
| the binding | the controller | gives a consumer the server's name; the consumer asks the server's seat for each share's path and access over the bus |
|
||||
| the credential | the vault | the `mounts` module's own secret `smb-credentials`, issued outside the mesh and given with `secret accept`, unsealed on the node as a file |
|
||||
| the credential | the vault | per SMB source, the `mounts` module's own secret `smb-password-<source>` (a member of the family `smb-password-*`), issued outside the mesh and given with `secret accept` or typed at the desk prompt, unsealed on the node as a file; the username is the setting `smb-users` |
|
||||
|
||||
## 1. The server: `nfs-server`
|
||||
|
||||
@@ -102,12 +103,18 @@ The glossary holds the three words.
|
||||
this node mounts, by the server's name for them. `none` (the default) mounts none.
|
||||
- **Its setting `sources`.** Occasional sources: `name=smb://<host>/<share>@<mountpoint>` or
|
||||
`name=disk:<uuid>@<mountpoint>`, each optionally `:ro`. `none` (the default) is none.
|
||||
- **Its secret `smb-credentials`.** One section per SMB source, `[name]` with `username=` and
|
||||
`password=`, issued outside the mesh and given with `secret accept <node> mounts smb-credentials
|
||||
--from <file>` at the controller's terminal — or asked for by an agent with the controller's `secret-ask`
|
||||
verb, on which a hidden prompt opens at that machine's desk naming the module, the secret and who asked,
|
||||
and the operator types it there ([ADR 0277](../../02-DECISIONS/0277-a-trusted-setting-is-proposed-through-a-verb-and-set-on-the-operators-warrant-and-a-modules-own-secret-is-asked-for-and-typed-at-the-desk.md)). The process writes one credentials file per source, readable by root only. A source
|
||||
with no section is said with that remedy and is not mounted.
|
||||
- **Its setting `smb-users`.** The username of each SMB source, `name=username`, space-separated; `none` (the
|
||||
default) is none. Not a secret, so it is a setting.
|
||||
- **Its secret family `smb-password-*`.** One member per SMB source, `smb-password-<source>`, holding that
|
||||
source's password as one line, issued outside the mesh and asked for by an agent with the controller's
|
||||
`secret-ask` verb, on which a hidden prompt opens at that machine's desk naming the module, the secret and
|
||||
who asked, and the operator types it there ([ADR 0277](../../02-DECISIONS/0277-a-trusted-setting-is-proposed-through-a-verb-and-set-on-the-operators-warrant-and-a-modules-own-secret-is-asked-for-and-typed-at-the-desk.md));
|
||||
or given with `secret accept <node> mounts smb-password-<source> --from <file>` at the controller's
|
||||
terminal. The mesh never makes a member, so one not given is no file ([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)).
|
||||
The process writes one credentials file per source from the username and the password, readable by root
|
||||
only. A source whose username or password is not given is not mounted, and its health answers *waits*,
|
||||
naming the setting or the secret and what the operator gives: the controller says it as
|
||||
`needs-operator`, and the first-node gate does not fail a build for it (ADR 0283).
|
||||
- **Its settings are trusted settings** (a trusted file asks for them), so a verb may not set them outright:
|
||||
an agent proposes them (`settings propose mounts … --node <node>`) and the operator approves on their
|
||||
phone, where the ask shows each source in its shape ("recalbox=‹address›@‹path›") and the layer's
|
||||
@@ -213,9 +220,9 @@ folders, none refused for a reason not understood.
|
||||
export goes; the mesh's stays. *Undo:* `zfs set sharenfs=<the old value>` by a person, recorded as a
|
||||
hand-act.
|
||||
7. **The downloads**, the same way: read-only first, then read-write.
|
||||
8. **The gaming device**: an agent asks for `smb-credentials` with `secret-ask`, and the operator types it at
|
||||
that machine's desk (or gives it with `secret accept` at the terminal); the agent proposes the source in
|
||||
`sources`, and the operator approves it on their phone; `node-mounts.list` says it `absent` while the
|
||||
8. **The gaming device**: the agent proposes the source in `sources` and its username in `smb-users`, and the
|
||||
operator approves each on their phone; an agent asks for `smb-password-<source>` with `secret-ask`, and the
|
||||
operator types it at that machine's desk (or gives it with `secret accept` at the terminal); `node-mounts.list` says it `absent` while the
|
||||
device is off, and it mounts on access when it is on. Then its fstab line is adopted.
|
||||
9. **The laptop**, read-only, granted read-only on the home server.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user