From de032e704c2cda46eed7b805c0b0d5922e58180f Mon Sep 17 00:00:00 2001 From: jochen Date: Sun, 4 Oct 2026 11:17:34 +0200 Subject: [PATCH] Research 026 (the graphical session) and 027 (the system layer) Evidence from both workstations and all four machines, read-only, and the questions each must answer: seats and gating for the display stack, who starts the session with which environment, contributions beyond shells, sway as a sibling session; the container runtime with docker-compose on workstations only, software outside the official repositories, secrets in the account's environment, and three security findings. --- .../00-overview.md | 62 ++++++++ .../01-what-the-workstations-run.md | 141 ++++++++++++++++++ .../02-the-questions-and-the-options.md | 123 +++++++++++++++ .../00-overview.md | 53 +++++++ .../01-what-the-machines-run.md | 103 +++++++++++++ .../02-candidates-and-questions.md | 87 +++++++++++ 6 files changed, 569 insertions(+) create mode 100644 01-RESEARCH/026-the-graphical-session-as-modules/00-overview.md create mode 100644 01-RESEARCH/026-the-graphical-session-as-modules/01-what-the-workstations-run.md create mode 100644 01-RESEARCH/026-the-graphical-session-as-modules/02-the-questions-and-the-options.md create mode 100644 01-RESEARCH/027-the-system-layer-as-modules/00-overview.md create mode 100644 01-RESEARCH/027-the-system-layer-as-modules/01-what-the-machines-run.md create mode 100644 01-RESEARCH/027-the-system-layer-as-modules/02-candidates-and-questions.md 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 new file mode 100644 index 0000000..1790df5 --- /dev/null +++ b/01-RESEARCH/026-the-graphical-session-as-modules/00-overview.md @@ -0,0 +1,62 @@ +--- +status: active +initiated: 2026-10-04 +touches: + - 02-DECISIONS/0176-the-login-shell-is-a-node-seat-and-execute-is-its-contract.md + - 02-DECISIONS/0177-a-unit-may-be-user-scoped-and-the-service-manager-is-a-node-seat.md + - 02-DECISIONS/0182-inside-a-home-the-mesh-owns-what-it-places-and-holds-the-rest-as-found.md + - 02-DECISIONS/0203-the-accounts-environment-is-one-modules-and-every-module-contributes-to-it.md + - 02-DECISIONS/0204-a-module-contributes-shell-code-to-the-login-shell-in-named-slots.md + - 02-DECISIONS/0205-software-the-distribution-does-not-package-ships-as-a-pinned-archive-of-the-module.md + - 03-DESIGN/01-to-be/37-the-operators-machine.md + - 03-DESIGN/01-to-be/38-building-the-operators-machine.md + - 04-ISSUES/168-a-setting-reaches-every-file-and-contribution/00-report.md +became: [] +--- + +# 026 — The graphical session as modules + +## What is investigated + +The workstations' graphical session as modules of the mesh, at the same level as the shell +([to-be 41](../../03-DESIGN/01-to-be/41-the-shell-and-the-accounts-environment.md)): a package, files +under the account's home, a seat, and nothing that names a machine. The pieces are: + +- the login manager; +- how a session starts and what environment it gets; +- the display server (X today, Wayland as a sibling); +- the window manager (i3, and sway as its Wayland sibling); +- the terminal emulator (xterm); +- the session's companions: bar, compositor, launcher, notifier, lock and idle, clipboard, + wallpaper, theming, fonts. + +[To-be 38](../../03-DESIGN/01-to-be/38-building-the-operators-machine.md) names this WP7, and says +each seat begins with a record naming its holders and verbs. [To-be 37](../../03-DESIGN/01-to-be/37-the-operators-machine.md) +§4 leaves one question for the resolver: whether a held seat can gate another's assignment. + +## Why + +The operator asked for the graphical modules next, at the shell's level, and for one consistent +experience across machines. Since the predecessor retired, nothing manages the workstations' +desktops. Measured in [01](01-what-the-workstations-run.md): + +- Two workstations carry one 983-line predecessor module's output, still byte-identical in its core. +- One workstation also carries another machine's hardware fragments. +- One runs a session that predates two fixes, with two notification daemons and two portals. +- The session's environment is a hand-kept second copy of the account's, beside the one the mesh + now writes. + +## What it touches + +- **The seat table:** up to ten node seats. +- **The resolver:** a seat held on a node gating another module's assignment. +- **The contribution mechanism of ADR 0204:** whether it generalises beyond shells, or whether + tools' own drop-in directories serve. +- **The host's user-scoped units** (mesh-host #72, still open). +- **Settings** for per-machine values (issue 168). +- **ADR 0205's archive** for the two pieces the distribution does not package. + +## Documents + +- [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) diff --git a/01-RESEARCH/026-the-graphical-session-as-modules/01-what-the-workstations-run.md b/01-RESEARCH/026-the-graphical-session-as-modules/01-what-the-workstations-run.md new file mode 100644 index 0000000..c9317c8 --- /dev/null +++ b/01-RESEARCH/026-the-graphical-session-as-modules/01-what-the-workstations-run.md @@ -0,0 +1,141 @@ +# 01 — What the workstations run + +Measured 2026-10-04 on the two workstations of one installation, read-only: a laptop with a hybrid +GPU and an internal panel, and a desktop with one GPU and two external monitors. Both run the same +predecessor-generated desktop. File equality was checked by checksum across the two machines. + +## How a session starts + +The chain is the same on both: + +1. The login manager (`lemurs`, built from the distribution's user repository, its package now in + the official one) runs its X setup script on a virtual terminal. +2. That script sources the login shell's profile files, then `~/.xprofile`, then the system's + `xinitrc.d` drop-ins, then merges `~/.Xresources`. +3. `~/.xprofile` reuses the systemd user manager's bus, then sources `~/.xinitrc`. +4. `~/.xinitrc` sets up the session and ends with `exec i3`. + +The login manager's own window-manager entry (`exec startx`) is never reached. Its configuration +file uses a format two releases old, and an unmerged newer one sits beside it. + +**What `~/.xinitrc` does**, in order: + +1. Sources the system drop-ins, which import `DISPLAY` and `XAUTHORITY` into the user manager. +2. Starts the keyring and exports its ssh socket. +3. Exports the session's environment: + - `PATH`, with nine entries, one of them a directory that no longer exists; + - toolchain variables; + - `XDG_CONFIG_HOME` and `XDG_DATA_DIRS` (with flatpak); + - five GTK/Qt theme variables; + - the desktop's identity (`XDG_CURRENT_DESKTOP`, `XDG_SESSION_DESKTOP`); + - three of the operator's own variables. +4. Imports an explicit allowlist of ten of those into the user manager and D-Bus activation. It is + never `--all`, because: +5. a predecessor file of **secrets as environment variables** (package-registry and API tokens) is + sourced next. +6. Sets the screensaver and display power timeouts, restores the wallpaper, and starts the lock + watcher in a respawn loop. It is deliberately not a unit, because it needs the login session. +7. `exec i3`. + +**The account's environment, as of today, has three sources that disagree:** + +- this file, for the session; +- the mesh's `environment.sh`, for shells + ([ADR 0203](../../02-DECISIONS/0203-the-accounts-environment-is-one-modules-and-every-module-contributes-to-it.md)); +- `~/.config/environment.d/`, for the user manager. It holds the mesh's `50-mesh.conf`, and a + predecessor file that **sets `PATH` outright** and sorts after it. + +## The roles, and what fills them + +| role | software | where configured | +|---|---|---| +| login manager | lemurs | `/etc/lemurs/*` (identical on both, and to the predecessor's source) | +| session start and environment | the login manager's X setup, `~/.xprofile`, `~/.xinitrc`, `xinitrc.d`, the D-Bus import, `environment.d` | `~/.xprofile`, `~/.xinitrc`, `~/.config/environment.d/*` | +| display server | Xorg (`xorg-server`, `xinit`, the X apps; vendor drivers per GPU) | **no** `xorg.conf.d`; monitors by `xrandr` scripts | +| monitor layout | `xrandr` scripts (arandr), a hotplug rule on the laptop | `~/.screenlayout/`, a scripts folder, a window-manager fragment | +| window manager | i3 4.25 | `~/.config/i3/config` and `config.d/*`, a reload watcher (user unit) | +| bar | i3bar with i3status-rust | `~/.config/i3status-rust/*`, 14 themes, a bar watchdog (user unit) | +| terminal | xterm (the only terminal installed) | `~/.Xresources.d/xterm`, the window manager's binding, the compositor's opacity rule | +| compositor | picom | `~/.config/picom/picom.conf` | +| launcher and menus | rofi | `~/.config/rofi/*`, launcher, power-menu and theme-picker scripts | +| notifier | dunst (D-Bus activated) | `~/.config/dunst/dunstrc`, `dunstrc.d/*` | +| lock, idle, display power | xss-lock and i3lock-color, `xset` | `~/.xinitrc`, a lock script | +| clipboard | greenclip, xclip | `greenclip.toml` | +| wallpaper | feh | `~/.fehbg` (points into the predecessor's tree) | +| theming | Adwaita dark, qt5ct/qt6ct, the desktop portal (GTK backend pinned) | GTK `settings.ini`, `qt*ct.conf`, `portals.conf`, an appearance script, `.Xresources` cursor | +| fonts | Hack and Meslo Nerd fonts in `~/.local/share/fonts` (not packaged), noto | `~/.Xresources.d/xft` (DPI fixed at 96) | +| keyboard | nothing set; the default layout; vendor keys via triggerhappy on the laptop | window-manager bindings, `/etc/triggerhappy` | + +**Packages:** every piece except two is in the distribution's official repositories, and the login +manager now is too. The two exceptions are the lock screen's colour build (`i3lock-color`) and the +clipboard manager (`rofi-greenclip`). The Nerd fonts exist as official packages, but both machines +carry hand-copied files instead. + +## Identical, different, and why + +**Byte-identical on both machines:** + +- the session files: `.xinitrc`, `.xprofile`, `.Xresources` and its drop-ins; +- the i3 main configuration and two of its fragments; +- the bar's top configuration and themes; +- picom, rofi, the GTK and Qt settings, the portal configuration, the login manager. + +**Different, by cause:** + +| cause | what | +|---|---| +| hardware | the monitor layout script; the bar's battery block; the laptop's power and vendor-key units and udev rules | +| misassignment | the desktop carries the **laptop's** hardware fragments: the vendor-key daemon and its triggers, the backlight rule, the brightness drop-in, a touchpad reset, and the laptop's monitor layouts, in an older version | +| drift | the notifier's position and corner radius; a "temporary" window-manager fragment from a test; the bar watchdog disabled; a second Qt configuration tool; different font builds | +| a stale session | the desktop's session began before two fixes, so it runs two notification daemons and two portals, and its user manager lacks the desktop's identity | + +**Dead references:** the window manager starts a polkit agent that is installed on neither machine, +so there is no polkit agent at all. `PATH` names a directory that does not exist. + +**Per-machine values inside shared files:** + +- the DPI; +- absolute home paths, in the clipboard configuration and the flatpak data directories; +- the laptop's panel name, inside a fragment both machines carry. + +## User units the desktop needs + +| unit | does | laptop | desktop | +|---|---|---|---| +| reload watcher | reloads the window manager and bar when their files change | on | on | +| bar watchdog | restarts a dead bar | on | off | +| clipboard daemon | from its package | via the window manager | unit **and** window manager | +| vendor power profile, memory guard | laptop power | on | — | + +None is managed. Applying them as the account needs the host's user scope +([ADR 0177](../../02-DECISIONS/0177-a-unit-may-be-user-scoped-and-the-service-manager-is-a-node-seat.md)), +which is still an open change. + +## The predecessor's module + +One manifest of 983 lines covers the window manager, bar, launcher, notifier, compositor, lock +screen, session bootstrap, theming and scripts. It: + +- has four *flavors*: i3, laptop (i3 plus the monitor wizard and hotplug), desktop (i3 plus + nothing) and a laptop model (laptop plus vendor keys); +- has about **105 theme variables** substituted into templates: border, gaps, fonts, workspace + names, every colour of bar, launcher, notifier and lock screen, compositor opacity, cursor, idle + times, Qt and GTK theme names; +- enables the two user units from an install hook. + +Separate modules held the login manager and the display server (one flavor, `xorg`, with a comment +calling `wayland` "the intended sibling"). The shell module held no graphical part. + +## Wayland and sway + +**Nothing exists.** There is no compositor, no sway configuration, no Wayland session entry, and the +login manager's Wayland directory is empty. What is installed is libraries: + +- Wayland itself and the Qt Wayland plugins, which other packages pull in; +- `xwayland`, explicitly installed and required by nothing; +- on the desktop, an orphaned compositor library from another desktop environment, and that + environment's portal backend, pulled in by a game launcher. The portal configuration pins + against it. + +Every piece a sway session needs is in the official repositories: the compositor, its lock screen, +a terminal (`foot`), a bar (`waybar`), a notifier (`mako`) and `xwayland`. diff --git a/01-RESEARCH/026-the-graphical-session-as-modules/02-the-questions-and-the-options.md b/01-RESEARCH/026-the-graphical-session-as-modules/02-the-questions-and-the-options.md new file mode 100644 index 0000000..7600ac6 --- /dev/null +++ b/01-RESEARCH/026-the-graphical-session-as-modules/02-the-questions-and-the-options.md @@ -0,0 +1,123 @@ +# 02 — The questions and the options + +Seven questions. Each has its options and a starting position, which is what this effort tests, not +what it has decided. + +## 1. How finely the desktop splits into modules + +| | option | for | against | +|---|---|---|---| +| G1 | One desktop module, as the predecessor had | one assignment | flavors again, per machine; ADR 0174 refuses them, and the evidence shows a flavor landing on the wrong machine | +| G2 | **One module per piece of software:** `lemurs`, `xorg`, `i3`, `i3status-rust`, `xterm`, `picom`, `rofi`, `dunst`, `xss-lock` with the lock screen, `greenclip`, `feh`, a theme module, a fonts module | each is what it declares; a machine gets exactly what is assigned; the same split already works for the shell and its plugins | about thirteen assignments per workstation | +| G3 | G2, plus a named **set** the controller assigns as one (for example *the X desktop*) | G2's precision with G1's convenience | a set is a new controller concept | + +**Starting position: G2.** Whether a set is worth a record is left until the thirteen assignments +have been done by hand once. + +## 2. The seats + +Research 018 listed the candidates. ADR 0204 has since put the login shell in the mesh's own set, +because a role with a protocol should not depend on one module's registration. The same reasoning +applies here: + +| seat | holders | protocol, first verbs | +|---|---|---| +| `node-login-manager` | lemurs, greetd | which sessions it offers, the default session | +| `node-display-server` | xorg, sway | `displays`, `layout` | +| `node-display-session` | i3, sway | `reload`, `workspaces`, `windows` | +| `node-terminal-emulator` | xterm, foot, alacritty | which terminal `$TERMINAL` names; `open` | +| `node-bar`, `node-compositor`, `node-launcher`, `node-notifier`, `node-lock-screen`, `node-clipboard` | the pieces above, and their Wayland counterparts | one verb or none each, until a use asks for one | + +**A compositor that is its own server holds two seats.** Sway is both the display server and the +display session. A module may claim several seats, so this needs nothing new. + +**Starting position:** the first four seats are in the mesh's own set. The companion seats are +added only as each holder is written; for those, a module without a seat is acceptable at first. + +## 3. One module requiring another seat to be held + +i3 needs an X server held on its node, and sway needs nothing below it. A terminal needs a session. +To-be 37 left open how that is said. + +| | option | for | against | +|---|---|---|---| +| R1 | A seat **delivers a provision** (`x11-display`, `wayland-display`) and a module requires it at node scope. The seat table has a `delivers` field already, and requirements already resolve | existing machinery; the refusal names the seat and its possible holders, which design 27 already lists | a node-scoped requirement that never crosses machines has to be stated as such | +| R2 | A new field, *needs the seat X held* | reads plainly | a second way to say what R1 says | +| R3 | Nothing; assign carefully | — | the mistake the evidence shows (a laptop's fragments on a desktop) is exactly an unchecked assignment | + +**Starting position: R1.** `xorg` and `sway` each deliver what they serve. `i3`, `picom` and `xss-lock` +require `x11-display`. `foot` requires a Wayland display, and xterm requires an X one, which a Wayland +session gives through `xwayland`. + +## 4. Who starts the session, and with what environment + +Today `~/.xinitrc` is a hand-kept second environment and the session's whole start script. + +| | option | for | against | +|---|---|---|---| +| S1 | The display server's module writes `~/.xinitrc` **into**: a mesh block at the start that sources the account's environment (`environment.sh`), merges the X resources, and runs the session's contributed start lines. The session holder's module contributes its `exec` line. The operator's lines stay after the block | one environment for shells, the session and the user manager; nothing to keep in step | the order inside `.xinitrc` becomes the slot order of a contribution (question 5) | +| S2 | The login manager's module owns the session script under `/etc` | system scope; no home file | the environment is the account's, and the script is the same for every account | +| S3 | Leave `.xinitrc` the operator's | nothing to build | the third environment stays | + +**Starting position: S1.** + +- The desktop's identity (`XDG_CURRENT_DESKTOP`) and the theme variables become **environment + contributions** (ADR 0203) from `i3` and from the theme module. They then also reach the user + manager through `environment.d`, which replaces most of today's allowlist import. +- The secrets file stays out of the environment until research 027 settles how a secret reaches an + account. + +## 5. How other modules contribute to a holder's file + +The terminal's settings are X resources. A bar, a launcher binding and a hardware module's key +bindings are window-manager configuration. Autostarts are the session's. ADR 0204 built slot +contributions for shells only. + +| | option | for | against | +|---|---|---|---| +| C1 | **The tool's own drop-in directory**, where it has one: i3's `include`, dunst's `dunstrc.d`, X resources' `#include`, XDG autostart entries, `environment.d`. Each contributor owns its own file there | no mesh change; the tools already read these directories; unassigning removes the file | each contributor names a path in another tool's directory (ADR 0204 rejected this for shells, where no drop-in convention exists); ordering is by file name | +| C2 | **ADR 0204's mechanism generalised:** `contributes` text *for a format* (`zsh`, `xresources`, `i3`, `xinitrc`) in a slot, placed by the holder's placeholder | one mechanism, checked by the controller, order declared | every format must be named in the controller; a bigger change to ADR 0204 | +| C3 | C1 where the tool has a drop-in convention, C2 where it does not (`.xinitrc`, `.Xresources` order) | uses each tool's own grain | two mechanisms to learn | + +**Starting position: C3**, with the boundary drawn by the tools. A tool that reads a directory gets +drop-ins. A file without one gets slots. This means amending ADR 0204's "shell" to "a format", which +is a progressive extension rather than a reversal. + +## 6. What varies per machine + +| what | today | option | +|---|---|---| +| monitor layout | per-machine `xrandr` scripts, monitor names baked in | a **setting** of `xorg` (issue 168), and a `layout` verb of the display server seat | +| DPI, fonts' size | fixed in an X resource | a setting | +| battery block, vendor keys, brightness, touchpad | a laptop model's flavor | **a hardware module** per machine model, contributing its window-manager fragment, bar block and udev rules. The desktop simply is not assigned it | +| theme (the 105 variables) | template substitution | settings of each tool's module, after issue 168 closes (ADR 0174). Until then each module carries today's values as its default | + +**Starting position:** + +- Hardware modules for what follows the machine. +- Defaults now, settings after issue 168, for what the operator varies. +- The monitor layout waits for settings. Until then it is an operator-owned script the display + server's block calls if present. + +## 7. Wayland and sway + +Nothing of a Wayland session exists, and every piece is officially packaged. "Wayland" is a protocol, +not a piece of software, so it has no module of its own. Its parts are `sway` (server and session), +`swaylock`, `foot`, `waybar`, `mako`, and `xwayland` for X clients. + +**Starting position:** + +- The seats and the requirements (questions 2 and 3) are designed so that sway fits from the first + day. +- The X stack is built first, because it is what runs. +- `sway` and its companions are written after that, and proven on one workstation as a second + session the login manager offers beside i3. That lets the operator try it without losing the + working desktop. + +## Prerequisites this effort cannot remove + +- **User-scoped units** (mesh-host #72) for the reload watcher and the bar watchdog. +- **Settings** (issue 168) for monitors and theme values. +- **The two packages not in the official repositories:** the lock screen's colour build and the + clipboard manager. Each is ADR 0205's case, a pinned archive, or a choice of an official + alternative (`i3lock` without colours; `clipmenu`/`cliphist`). 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 new file mode 100644 index 0000000..60742e2 --- /dev/null +++ b/01-RESEARCH/027-the-system-layer-as-modules/00-overview.md @@ -0,0 +1,53 @@ +--- +status: active +initiated: 2026-10-04 +touches: + - 02-DECISIONS/0165-container-runtime-is-what-a-machine-can-run-and-a-running-runtime-is-its-holders-health.md + - 02-DECISIONS/0166-the-container-runtime-is-a-node-seat-and-the-host-creates-containers-through-its-holder.md + - 02-DECISIONS/0203-the-accounts-environment-is-one-modules-and-every-module-contributes-to-it.md + - 02-DECISIONS/0205-software-the-distribution-does-not-package-ships-as-a-pinned-archive-of-the-module.md + - 03-DESIGN/01-to-be/37-the-operators-machine.md + - 03-DESIGN/01-to-be/38-building-the-operators-machine.md +became: [] +--- + +# 027 — The system layer as modules + +## What is investigated + +What runs on the machines below the operator's home and outside the mesh's own services, and which +of it should be modules. That covers: + +- the container runtime and its tools; +- privilege (sudo); +- the package manager and the software it cannot install; +- time, locale, the kernel and boot; +- log rotation; +- the machine-specific daemons the workstations and servers carry: printing, bluetooth, VPN + clients, virtualisation, storage, sharing. + +## Why + +The operator asked for the system level beside the graphical session. In particular: + +- a `docker` module (decided in principle by the proposed ADRs 0165 and 0166, never built); +- a `docker-compose` module for development work, assigned **only to the two workstations**. + +Measured in [01](01-what-the-machines-run.md): on four machines, almost nothing at this level is +owned by a module. The pieces differ by machine for no recorded reason. Three findings are security +matters on their own. + +## What it touches + +- **The container runtime seat** (ADRs 0165 and 0166, both proposed). +- **The host's `package` shape**, which installs from the distribution's official repositories only, + while the workstations carry 67 and 114 packages from elsewhere. +- **How a secret reaches the account's environment.** ADR 0203 forbids it in the contributed + environment, but a predecessor file supplies such secrets today. +- **The facts the mesh assumes and never declares,** above all that the operator account escalates + without a prompt. + +## Documents + +- [01 — What the machines run](01-what-the-machines-run.md): evidence. +- [02 — Candidates and questions](02-candidates-and-questions.md) diff --git a/01-RESEARCH/027-the-system-layer-as-modules/01-what-the-machines-run.md b/01-RESEARCH/027-the-system-layer-as-modules/01-what-the-machines-run.md new file mode 100644 index 0000000..0810cec --- /dev/null +++ b/01-RESEARCH/027-the-system-layer-as-modules/01-what-the-machines-run.md @@ -0,0 +1,103 @@ +# 01 — What the machines run + +Measured 2026-10-04 on four machines, read-only, including the host's own record of what it applied: +two servers (the anchor and a home server) and two workstations (a laptop and a desktop). "Owned" +means a module the mesh assigns declares it. + +## The container runtime + +| | anchor | home server | laptop | desktop | +|---|---|---|---|---| +| docker | 29.8.2 | 29.8.2 | 29.7.2 | 29.7.2 | +| compose | 5.5.1 | 5.6.0 | 5.5.0 | 5.5.0 | +| buildx | 0.37.2 | — | — | — | +| podman | — | 6.1.3 | 6.1.0 | 6.1.0 | +| `docker.socket` | disabled | enabled | enabled | enabled | +| `containerd.service` | disabled | disabled | disabled | **enabled** | +| `daemon.json` beyond the shared keys | direct routing, two more insecure registries | log rotation (100 MB × 10) | — | — | +| docker group | operator, **a CI user** | operator | operator | operator | + +**Ownership:** + +- The `docker` package is owned on one machine only, by the installer's bootstrap, not by a module. +- `docker.service` is declared indirectly, by the name resolver and the private-network modules, + which each merge their own keys into `daemon.json`. +- Nothing owns the socket, containerd, compose, buildx or the group. + +**Compose in use:** + +- On the servers, no running container belongs to a compose project. Their compose files are + pre-mesh trees under the operator's and root's homes, plus a dangling enabled unit for one of them. +- On the workstations, compose runs development stacks, and pre-mesh service trees sit under a + top-level directory. + +The mesh marks its own containers with a host label. On the workstations, a handful of unlabelled +development and test containers run beside its build agent. + +## Privilege + +- The operator account escalates **without a prompt on all four machines**. The mesh relies on this, + but it is set by hand in `/etc/sudoers` (a `wheel` rule on two machines, the account named on + two), and nothing declares it. +- On the anchor, a **CI user from the predecessor** keeps passwordless sudo and docker membership, + and a predecessor drop-in in `sudoers.d` survives. +- On the desktop, the operator account is also in the **`root` group**. + +## The package manager + +- `pacman.conf` is stock except on one server (parallel downloads). +- The mirror list was generated once by a tool that is no longer installed. On the anchor, it is the + hosting provider's single mirror. +- An AUR helper is installed everywhere. +- **Packages from outside the official repositories:** 2 on the anchor, 21 on the home server, + 67 on the laptop, 114 on the desktop. They include: + - the agent CLI, which a catalogue module declares as a package and the host cannot install; + - a VPN client; + - a remote-access client; + - printer drivers; + - GPU tools; + - a kernel module built from source (DKMS) for a storage filesystem; + - a snap daemon. + +## Time, locale, kernel, boot + +| | anchor | home server | laptop | desktop | +|---|---|---|---|---| +| time zone, keymap | **another zone**, a non-US console keymap | local zone, unset | local zone, unset | local zone, unset | +| time sync | timesyncd plus a provider drop-in | timesyncd | timesyncd | **ntpd**, timesyncd disabled | +| bootloader | grub (BIOS) | systemd-boot **and** grub | systemd-boot | systemd-boot **and** grub | +| kernels | one | two, plus a DKMS filesystem module | one | one, plus a DKMS controller driver | +| microcode | **none** | yes | yes | **none** | +| swap | RAID partition | partition | zram, a file and a partition | partition | +| log rotation timer | not found | enabled | not found | not found | + +## Daemons and services no module owns + +- **All four:** avahi. +- **Workstations:** + - a VPN client daemon (both); + - virtualisation (incus) with a hand-made unit that inserts container-runtime firewall rules (both); + - printing and bluetooth; + - GPU and power tuning per model; + - a remote-access daemon (laptop); + - snap and flatpak (desktop); + - the local model server, run from a hand-written unit although a catalogue module for it exists + (desktop); + - Samba sharing and a network filesystem mount from the home server (desktop). A second mount is + failing, and its **credential is written in clear in `/etc/fstab`**. +- **Servers:** + - a storage pool (about 167 TB) with its import, mount and scrub units, an NFS server and Samba + sharing (home server); + - traffic and sensor monitoring (home server); + - a DHCP client daemon the catalogue has a module for but does not assign there (home server); + - cron, an entropy daemon, and the **legacy `iptables` services**, which run beside the mesh's own + filter (anchor). +- **Not found anywhere:** a backup agent, a monitoring agent, a second VPN mesh. + +## What is plain debris + +- Dangling enabled-unit links on three machines. +- Predecessor blocks in `/etc/hosts` on both servers. +- The CI user, and the predecessor sudoers drop-in, on the anchor. +- Pre-mesh compose trees on the anchor, the home server and the desktop. +- Unlabelled test containers on the workstations. diff --git a/01-RESEARCH/027-the-system-layer-as-modules/02-candidates-and-questions.md b/01-RESEARCH/027-the-system-layer-as-modules/02-candidates-and-questions.md new file mode 100644 index 0000000..3ea28d6 --- /dev/null +++ b/01-RESEARCH/027-the-system-layer-as-modules/02-candidates-and-questions.md @@ -0,0 +1,87 @@ +# 02 — Candidates and questions + +## Decided by the operator on 2026-10-04 + +- **`docker`** holds the container runtime seat on every machine, as ADRs 0165 and 0166 propose. Those + records are promoted from proposed when it is built. +- **`docker-compose` is a module of its own,** the distribution's package and nothing else. It is + assigned **only to the two workstations**, for development work. The servers run nothing through + compose. + +## Candidate modules + +**On every machine:** + +| module | owns | first reason | +|---|---|---| +| `docker` | the packages (runtime, containerd), the service and socket, `daemon.json`'s base keys (live restore, log rotation), the docker group's members | four machines, four configurations, one owner on one | +| `sudo` | the operator account's escalation as a drop-in, declared | the mesh's tools rely on it (to-be 38 WP4) and nothing states it | +| `pacman` | `pacman.conf`'s few keys, the mirror list and its refresher, cache cleaning | mirrors generated once and never again | +| `time-sync` | timesyncd and its drop-ins | two daemons across four machines | +| `locale` | locale, time zone, console keymap | one machine differs, with no record why | +| `kernel` | the kernel packages, microcode, initramfs presets | two machines without microcode | +| `logrotate` | the timer and the base configuration | rotation runs on one machine of four | +| `avahi` | the daemon and name-service switch entry | on all four, owned by none | + +**On the workstations only:** + +- `docker-compose`; +- `lemurs`, the login manager (research 026); +- a VPN client module; +- `incus` with its forward unit (the lab module declares the package on one workstation only); +- `cups` with the printer's driver; +- `bluetooth`; +- per-model **hardware** modules: GPU, power, vendor keys, brightness. These are the same modules + research 026 needs for the desktop's fragments. + +**On the servers only:** + +- `zfs` with its scrub timer, and the long-term kernel it builds against; +- `nfs-server`; +- `samba`; +- `vnstat`, `lm_sensors`. + +`cron` on the anchor serves one stock file and can go. So can the entropy daemon on a modern +kernel. + +**Retire, not model:** the legacy `iptables` services on the anchor. They duplicate the mesh's +filter, which is ADR 0100's ground. + +## Questions this effort has to answer + +1. **Software outside the official repositories.** The host's `package` shape installs from the + official repositories only. A catalogue module already declares an AUR package (the agent CLI), + which no machine could install, and the workstations carry 181 such packages between them. + + | | option | for | against | + |---|---|---|---| + | P1 | ADR 0205's pinned vendored archive, per piece | exists | wrong for packages that build native code or kernel modules | + | P2 | **The build machine builds AUR packages into a package repository the mesh serves** from its artifact store. The host then installs them as packages, signed | one shape for every package; pinned, reviewed and built once | a repository to serve and a signing key to keep | + | P3 | An AUR helper on each machine, driven by the host | nothing to serve | builds on every machine, unpinned: the predecessor's `git clone` in another form | + + Starting position: P2, for anything with native code. ADR 0205 stays for plain files such as a + theme. + +2. **Secrets in the account's environment.** A predecessor file feeds package-registry and API tokens + to the session. ADR 0203 refuses secrets in contributed values, because they travel in the clear. + The candidate is ADR 0182's third class: a module's own process writes a mode-0600 file of + exports, from secrets the vault hands it over the bus, and the shell and the session source it. + This needs its own record. + +3. **Per-machine sizing and drivers.** The swap layout, the GPU, the storage pool and the boot + loader are facts of one machine's hardware. They belong in hardware modules, or in settings + (issue 168), not in the shared ones. + +4. **What a module may leave behind.** Compose is installed on both servers, unowned. The mesh + removes nothing it did not make. The choice is between an operator's one-off removal and a + server-side `absent` declaration. + +## Security findings, independent of any module + +1. A filesystem credential in clear text in a workstation's `/etc/fstab`, for a mount that is failing + anyway. +2. A predecessor CI user with passwordless sudo and docker membership on the anchor, and a + predecessor sudoers drop-in. +3. The operator account in the `root` group on one workstation. + +Each is one small change. None waits for a module.