diff --git a/03-DESIGN/01-to-be/42-milestones/zfs-owns-zfs-lead-answers.md b/03-DESIGN/01-to-be/42-milestones/zfs-owns-zfs-lead-answers.md new file mode 100644 index 00000000..5dcf27f8 --- /dev/null +++ b/03-DESIGN/01-to-be/42-milestones/zfs-owns-zfs-lead-answers.md @@ -0,0 +1,86 @@ +--- +layer: to-be +status: in-progress +design: 42 +milestone: zfs-owns-zfs +updated: 2026-11-13 +decisions: + - "ADR 0679" +--- +# 42, milestone zfs-owns-zfs — the lead's answers to the prepare's questions + +The lead's answers to the prepare's design questions (Q-n) and to the places where a design line and the code +disagree (C-n), for the milestone part [zfs-owns-zfs](zfs-owns-zfs.md): each one line, naming the principle that +settles it (`00-META/principles.md`), cited as "design 42 zfs-owns-zfs A-n". The code read is the prepare's, at the +`origin/main` commits its milestone file names. + +- **A-1** (Q-1, §8; principles 2 and 7) The pool's name is not held by mesh-config: it is the zfs module's + `values` in the home server's assignment (seat `mesh-module-assigner`), a layer mesh-config's rename does not move. + So the module keeps `renamed-from: scrub-pool` for the values mesh-config holds, and at the delivery the lead moves + the assignment's value: `pool` set to that name through mesh-config for the home server, and the assignment + proposed without `scrub-pool` through `mesh-module-assigner.propose`, both before the new version is placed. +- **A-2** (Q-2, §14; principle 7) The module's ZED folder also holds the package's `zed-functions.sh`, from the + module's files archive, root's, mode 0644, under `if-config: [zed=on]` beside `zed.rc`; the handlers find it where + ZED points them, and nothing else changes. +- **A-3** (Q-3, §13; principles 2 and 7) `trim-schedule: none` is a set value meaning "no trim by the mesh": the + distribution's trim timers are held stopped for `none`, `weekly` and `monthly` alike; only an unset value leaves + them as found. +- **A-4** (Q-4, §3; principle 3) The validator refuses a `:` in a `config-lines` prefix, beside `}`, `$` and a + newline, naming the key. +- **A-5** (Q-5, §3; principle 3) The validator refuses `mib-bytes` on a value whose type is not a number, and a + `config-lines` key the module does not declare, as it refuses `${config:}` of an undeclared key today. +- **A-6** (Q-6, §18, §24; principles 1 and 6) The follower's process bus declares + `invokes: ["seat:node-service-manager.start"]`, and the module's `invokes` carries the same for its tools bundle. +- **A-7** (Q-7, §14, §18; principle 7) `/etc/zfs/mesh-zed.d` is a directory resource under `if-config: [zed=on]` + with `unknown: module`; `/run/zfs-tools` is a directory resource with `unknown: program`, as `/run/zfs-events` is. +- **A-8** (Q-8, §18; principle 3) `zfs-tools apply` exits 0 on a refusal and on a wait, which it says by event and + in its state `applied` and which make the module unhealthy by §29; it exits non-zero only when a command it ran + failed, so the node-engine gates the module on a real failure. +- **A-9** (Q-9, §30; principle 7) When the module leaves a node, its kept data (the states `applied`, `schedule` and + `findings`, the ledger `snapshots`, the events stream) is kept as every module's kept data is on leaving; a return + finds its scheduled ZFS snapshots' records. +- **A-10** (Q-10, §27; principle 7) The findings stream is the one design 47 G §383 defines for every observer: + `zfs-findings`, its events `finding-written.*`, `finding-cleared.*` and `findings-stated.*`, kept 7 days and + 16 MiB, said by the writer generated from the seat `mesh-conditions`' definition; the module declares it as §383 + says and builds nothing of its own for it. +- **A-11** (Q-11, acceptance test 8; principles 5 and 7) Test 8 runs in the test lab, on a pool built on a + file-backed device, never on the home server's pool. +- **A-12** (Q-12, §24; principles 3 and 4) A hand act's tool waits at most 30 seconds for the act's event; past it, + it answers "started", naming the act and that `zfs_module_events` reads its outcome, and never answers "done" + for what it did not see end. +- **A-13** (C-1, §4; principle 7) The node-engine states the new reading as `word:resources.if-config` and + `form:config-lines` (and `form:config-json`, A-15), computed by `ManifestReads` and marked by `ManifestNeeds`; + stopping at the first failure is stated by no capability, since the node-engine build that reads those words is + the build that stops. +- **A-14** (C-2, §11; ADR 0679 §3; principle 7) The validator accepts a config value with neither a default nor + `required` as "not managed until set"; built in the validator's subtasks of this milestone. +- **A-15** (C-3, §9; principles 2 and 7) The config file's content is one new node-engine placeholder + `${config-json}`: the module's set config values as one JSON object, an unset value absent, lists and objects as + JSON; no unset value refuses the module. It is built with §2 and §3 in the node-engine, the validator and + mesh-sdk's form list, and stated as `form:config-json`; no existing form writes an unset value as absent. +- **A-16** (C-4, §18; principle 7) The follower, which runs from boot, starts the apply unit once at its own start + and on the events §27 names; the apply's own wait for an unimported pool (§18) stands for the order after + `zfs-import.target`. No new process field. +- **A-17** (C-5, §24; principle 7) A hand act writes its act into the state `schedule` under its own key and starts + `zfs-mesh-run.service`; the run reads the key, acts under the same lock and guards, and deletes it. No instance + units. +- **A-18** (C-6, §24; principle 7) `node-service-manager.start` is called with `{scope, unit}`; the tool keeps + `why` in its own event. The seat is not changed. +- **A-19** (C-7, §26; principle 7) The ledger `snapshots` declares a fixed `max-mib` sized from the bound of 168 per + kind (§11); a full ledger takes §21's "ledger full" path. +- **A-20** (C-8, §21, §22, §26; principles 1 and 7) A process cannot write a ledger: the ledger is served to a tools + bundle alone, through the tool runner (mesh-sdk `buscalls`, `ProcessBus` has no ledger). The scheduled run records + `taken` and `removed` by calling its own module's tool `zfs_snapshots_record` (declared in the run's process bus + `invokes`), whose bundle applies the operation to the ledger; the tool refuses a snapshot not named `mesh-`. No new + field in mesh-sdk. +- **A-21** (C-9, §13; principle 2) When one record of a unit goes while another still declares it, the found state + passes to the record that stays, as a file is handed to the resource still declaring its path (ADR 0223); built in + the node-engine's §2 subtask. +- **A-22** (C-10, the test budget; the test-budget instruction) The node-engine's repository is over its budget (about 1,742 unit tests + against 500): each new table test merges or replaces at least as many tests in the file it touches, named in the + build map, so the count does not rise. +- **A-23** (C-11, §9, §11; principle 6) The config file carries `"trusted": false`; each value's own `trusted` (§11) + decides who sets it. +- **A-24** (C-12, §2, §3; principle 3) `config-lines` and `config-json` are added to the validator's and the + composer's placeholder tables, and the validator counts `if-config`, `config-lines` and `config-json` as placing + their keys.