ADR 0262: say what a left-out module loses, and how far an entry's unknown key is read
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

The record claimed a left-out module kept what the machine holds for it and that an entry's unknown key
was read like a top-level one; neither is true of the merged controller.
This commit is contained in:
jochen
2026-10-08 17:55:38 +02:00
parent f09c9befdf
commit 6a9bc3f4b3
@@ -112,15 +112,26 @@ So the controller reads the rest of the catalogue as before, and for that module
- it is left out of every machine's declaration, by name, with the key as the reason, the way a module
whose stored settings no longer compose is left out
([ADR 0163](0163-taking-a-module-over-is-a-comparison.md), rule 6); what the machine holds for it is kept and its
containers are untouched;
([ADR 0163](0163-taking-a-module-over-is-a-comparison.md), rule 6). Its files and data on the
machine stay where they are and its containers are not removed, but everything the declaration
carries for it stops while it is left out: the backup holder's lines for its data, its contributions
to a seat's holder, and the ports the filter opens for it;
- the controller raises a condition naming the module, saying it uses a field this controller does not
know and is left out until the controller is updated, and clears it once the module reads again;
- the controller's log says it once.
This holds at any depth: a key inside a block (a state, a provided name, an offer's identity, a data
item's backup, an own secret, a seat's verb) is treated the same as one at the top. It holds for every
field a later record adds, not only `settings`.
A key at the top of the manifest is set aside and the rest of the manifest is read. A key inside an
entry (a state, a provided name, an offer's identity, a data item's backup, an own secret, a seat's verb)
is found as well, and the module is left out and raised the same way, but the controller that merged
this record then keeps only the module's name and version: it no longer provides what it provides, so a
module that requires it is refused on every machine, by name. The rule holds for every field a later
record adds, not only `settings`.
**What a left-out module keeps is to be widened.** A follow-up to the controller reads an entry with an
unknown key in a second pass, so a left-out module still provides what it provides and no consumer is
refused for it, and keeps its backup lines, so its data is still copied while it is left out; the
condition then says exactly what stopped. Until that follow-up is live, the condition and this record
say what stops as above.
## Consequences
@@ -151,7 +162,7 @@ field a later record adds, not only `settings`.
| Rule | Checked by |
|---|---|
| A default is declared only for a preference, with why | The controller's manifest parser, run on every catalogue pull request as the module check: a `settings` entry is refused without `kind: preference`, without a default, with an empty or non-scalar default, or without `why` (`TestTheParserTakesAPreferenceAndRefusesTheRest`) |
| The operator's own value has no default | The same parser refuses a default for a key about the operator's own value: its last word, read as singular, is one such name (among them domain, host, hostname, zone, site, timezone, url, ip, ipv4, ipv6, mail, address, user, owner, uid, password, secret, token, key, apikey, bearer, cert), or its last two are a compound such as client-id, site-name, server-name, public-name or smtp-relay. A key that starts with max, min, show, hide, enable or use is a number or a switch, not an identity, and the installation check of ADR 0155 already refuses a default naming a domain or a public address. `TestAnOperatorsValueWithoutADefaultIsStillRefused`: an unset key with no default is still refused by name |
| The operator's own value has no default | The same parser refuses a default for a key about the operator's own value: its last word, read as singular, is one such name (among them domain, host, hostname, zone, site, timezone, url, ip, ipv4, ipv6, mail, address, user, owner, uid, password, secret, token, key, apikey, bearer, cert), or its last two are a compound such as client-id, site-name, server-name, public-name or smtp-relay. A key that starts with max, min, num, count, show, hide, enable, disable, use or allow is a number or a switch, not an identity; the controller follow-up narrows that to the first eight, since `allow-from` or `use-host` names whom, and adds host-name, user-name, domain-name, nameserver, dns-server, gateway, subnet, sender, recipient, contact and certificate; and the installation check of ADR 0155 already refuses a default naming a domain or a public address. `TestAnOperatorsValueWithoutADefaultIsStillRefused`: an unset key with no default is still refused by name |
| The node over the mesh over the default | `TestTheNodeOverTheMeshOverTheDefault`, and `TestAComposedMachineGetsTheDefaultAndTheNodesValue` through a machine's whole composition |
| A default never becomes a key of a mergeable file | `TestADefaultIsNotMergedIntoAJSONFile` |
| A key with a default is accepted by `settings` | `TestAKeyWithADefaultIsNotStray` |