diff --git a/01-RESEARCH/026-the-graphical-session-as-modules/00-overview.md b/01-RESEARCH/026-the-graphical-session-as-modules/00-overview.md index 1790df5..410fc0f 100644 --- a/01-RESEARCH/026-the-graphical-session-as-modules/00-overview.md +++ b/01-RESEARCH/026-the-graphical-session-as-modules/00-overview.md @@ -60,3 +60,4 @@ desktops. Measured in [01](01-what-the-workstations-run.md): - [01 — What the workstations run](01-what-the-workstations-run.md): evidence. - [02 — The questions and the options](02-the-questions-and-the-options.md) +- [03 — What the predecessor taught](03-what-the-predecessor-taught.md): its 128 modules and 3,395 commits, as patterns to keep and failures not to repeat; shared with research 027. diff --git a/01-RESEARCH/026-the-graphical-session-as-modules/03-what-the-predecessor-taught.md b/01-RESEARCH/026-the-graphical-session-as-modules/03-what-the-predecessor-taught.md new file mode 100644 index 0000000..d4e41be --- /dev/null +++ b/01-RESEARCH/026-the-graphical-session-as-modules/03-what-the-predecessor-taught.md @@ -0,0 +1,51 @@ +# 03 — What the predecessor taught + +A study on 2026-10-04 of the retired predecessor: + +- its 128 module manifests, their hooks, its installer and its sync engine; +- 3,395 commits of history; +- what it left on four machines. + +This document holds what bears on the graphical session and on the system layer +([research 027](../027-the-system-layer-as-modules/00-overview.md)). The evidence is in the +predecessor's history. A commit is cited here by what it fixed, not by its hash, because the +repository is private. + +## Keep: what worked + +| pattern | where it shows | in the mesh | +|---|---|---| +| ownership marked inside the file: inside the markers is reconciled, outside is kept verbatim | a block marker in a shared file, after an engine that rewrote whole files | kept regions (ADR 0174, ADR 0204) | +| two writers get two files and an `include`, the include first | the ssh client's configuration, after two writers fought over one file | ADR 0203's two files; research 026 C1 | +| one writer per file, one authority per action | only the reload watcher restarts the window manager, after three mechanisms each did | ADR 0182 | +| refuse to write when the source of truth is unreadable; never empty a block because a query found nothing | a block of names was emptied by a failed query | — keep | +| an unresolved template variable fails the install | a literal unfilled path was installed green | [issue 231](../../04-ISSUES/231-a-misspelled-placeholder-is-written-out-as-text/00-report.md): the mesh still has this gap | +| prune only what you can prove you placed | stale files from earlier deliveries | ADR 0189 | +| ensuring never rotates a credential | a silent rotation caused a retry storm, a ban of the shared address and a lost registry | ADR 0114 | +| vendor only the files you use; never clone and link | three files instead of 77 MB | ADR 0205 | +| copy, never symlink | a recursive delete followed a link, and every reinstall failed | ADR 0012 | +| verification says what it did not check | a verifier said *clean* while the secret was still on disk | — keep | +| alert once per condition | 411 alerts hid a 28-hour outage | ADR 0090 | + +## Do not repeat + +| failure | what it did | the mesh instead | where the mesh is still exposed | +|---|---|---|---| +| **Flavors** | variant files and packages per machine type: a gate dropped, the first-seen variant won, packages never installed, the verifier ignored the gate. On the day of the study a desktop carried a laptop model's fragments | one module per piece, assignment per machine (ADR 0174, research 026 §1) | a setting that switches which whole file is rendered is a flavor under another name | +| **The freeze** | existing values outranked new defaults; templated files were rendered once (*copy if absent*) | files are generated (ADR 0011) | a created-once file (ADR 0087) is a deliberate freeze, and a push must say *kept* | +| **Adopting drift** | a *merge* strategy made a local edit the record forever; switching strategies clobbered a person's model choice | nothing is read back (ADR 0174) | an edit outside a kept region is overwritten **silently**. The predecessor's *why is this back* loop: the push should name what it overwrote | +| **Environment templating** | `${VAR}` matched any name; unresolved names stayed literal; comments and destination paths were interpolated | namespaced placeholders; `$` forbidden in contributed values (ADR 0203) | issue 231 | +| **Hooks with privilege** | install hooks ran `sudo`, `chsh`, `systemctl`, `git clone` and `curl`, and swallowed failures into a warning | the `user` shape, the service shape, archives (ADR 0176, 0177, 0205) | the agent module writes under `/etc` from its own tool through `sudo` (no keep-original, no give-back); the prompt's helper downloads itself unpinned; that the operator escalates without a prompt is assumed by three modules and declared by none (research 027) | +| **Secrets in environment files** | `.env` files left world-readable; the decryption key beside what it decrypts; a deleted secret stayed in the file, so rotation was a no-op | the vault (ADR 0113, 0114) | a predecessor file of secrets is still sourced into the graphical session on two machines (research 027 Q2) | +| **Symlinks into a home** | a system file linked into a person's home | ADR 0012 | on the control machine, a fail2ban action file is still a predecessor link into its home tree. Deleting that tree would silently break the repeat-offender jail. The mesh's fail2ban module must own it as a file first | +| **Green while broken** | a recorded version frozen for four months; a verifier passing what it skipped | ADR 0134, 0145, 0184 | issue 230: a plan waiting for ever reads as healthy | + +## What it means here + +- **Research 026:** the desktop's 88 flavor-gated files and 92 theme variables are the flavor and + templating failures in one module. Question 1 (one module per piece) and question 6 (hardware + modules, settings later) are the answer, and nothing in the new modules may switch whole files on a + setting. +- **Research 027:** the hooks that installed the AUR helper, enabled the login manager and changed + shells are what the `package`, `service` and `user` shapes replace. Every remaining `sudo` in a module's + own code is a debt to be named, starting with the agent module. diff --git a/01-RESEARCH/027-the-system-layer-as-modules/00-overview.md b/01-RESEARCH/027-the-system-layer-as-modules/00-overview.md index 60742e2..aa64f27 100644 --- a/01-RESEARCH/027-the-system-layer-as-modules/00-overview.md +++ b/01-RESEARCH/027-the-system-layer-as-modules/00-overview.md @@ -51,3 +51,4 @@ matters on their own. - [01 — What the machines run](01-what-the-machines-run.md): evidence. - [02 — Candidates and questions](02-candidates-and-questions.md) +- The predecessor's lessons, shared with research 026: [026/03](../026-the-graphical-session-as-modules/03-what-the-predecessor-taught.md) diff --git a/04-ISSUES/231-a-misspelled-placeholder-is-written-out-as-text/00-report.md b/04-ISSUES/231-a-misspelled-placeholder-is-written-out-as-text/00-report.md new file mode 100644 index 0000000..45181bd --- /dev/null +++ b/04-ISSUES/231-a-misspelled-placeholder-is-written-out-as-text/00-report.md @@ -0,0 +1,41 @@ +--- +status: open +opened: 2026-10-04 +located-in: + - mesh-controller +fixed-by: +amended-design: +--- + +# 231 — A misspelled placeholder is written out as text + +## What was observed + +2026-10-04, while studying the predecessor's failures. A manifest was checked whose one file holds four +placeholders: `${shel:zsh:first}` (a misspelled namespace), `${setting:Undeclared}` (a setting the module +does not declare), `${machnie:address}` (a misspelled namespace) and `${XDG_CACHE_HOME:-x}` (shell +syntax, which must pass through). The catalogue check, which runs the same functions registration does, +answered `ok`. + +The controller fills each namespace it knows with its own pattern (`machine`, `setting`, `bound`, `dir`, +`port`, `secret`, `environment`, `shell`, …). A word in that shape that no pass consumes is left in the +file as it was written. A misspelling therefore reaches a machine as literal text, in a configuration +file that then reads it as a value. + +## Why it matters beyond this instance + +This is exactly the predecessor's failure: an unresolved template variable in a destination path +installed green, and a literal `${...}` path stood under `/etc/ssl` until somebody looked. The mesh's +namespaced placeholders were meant to end it ([ADR 0164](../../02-DECISIONS/0164-a-setting-is-declared-with-its-default-its-meaning-and-what-changing-it-costs.md)), +and they do for every name spelled right. + +## What a fix has to settle + +After every pass, a final sweep refuses any remaining `${:` whose word is a lower-case +namespace-shaped token, naming the module, the field and the token, at the catalogue check and at +composition. Shell syntax (`${NAME:-…}`, `${(%):-…}`, `${1:-.}`) is not namespace-shaped and passes. So +does contributed shell code, which no pass reads (ADR 0204). A setting a module uses but does not +declare is refused the same way. + +How it is checked: the controller's test with the four placeholders above, three refused by name and +one passed through.