Grilling: Package ownership + ADR 0004 amendment #40

Closed
opened 2026-09-02 18:31:24 +00:00 by xavierk · 1 comment
Owner

Parent map: Fenris deb + rpm release plan

Question

Define dpkg/rpm ownership: file lists for the /opt/fenris venv, helpers, units, polkit policy; /etc/fenris conffile semantics; fenris group creation (maintainer script vs sysusers.d/tmpfiles.d); dormant-install parity (never enable/start units); uninstall vs purge mapping against the old manifest model; postinst inheriting ADR 0004 snapshot + forward-only migration semantics. Output: ADR amendment outline.

Parent map: [Fenris deb + rpm release plan](https://git.bongbetic.com/xavierk/Fenris/issues/33) ## Question Define dpkg/rpm ownership: file lists for the /opt/fenris venv, helpers, units, polkit policy; /etc/fenris conffile semantics; fenris group creation (maintainer script vs sysusers.d/tmpfiles.d); dormant-install parity (never enable/start units); uninstall vs purge mapping against the old manifest model; postinst inheriting ADR 0004 snapshot + forward-only migration semantics. Output: ADR amendment outline.
xavierk added this to the Wayfinder: Fenris deb + rpm release plan milestone 2026-09-02 18:31:24 +00:00
xavierk added the wayfinder:grilling label 2026-09-02 18:31:24 +00:00
xavierk added a new dependency 2026-09-02 18:34:08 +00:00
xavierk added a new dependency 2026-09-02 18:34:09 +00:00
xavierk added a new dependency 2026-09-02 18:34:10 +00:00
xavierk self-assigned this 2026-09-02 19:55:09 +00:00
Author
Owner

Resolution

All 8 recommendations accepted. Package ownership decisions:

  1. Units → /usr/lib/systemd/system (vendor placement; /etc stays admin-only for drop-ins + enable-state). Dormant parity: postinst does daemon-reload only — never enable, never preset, never start; no preset file shipped.
  2. fenris group via /usr/lib/sysusers.d/fenris.conf (g fenris -) + explicit systemd-sysusers invocation in postinst/%post — declarative, immediate on all four matrix targets (systemd ≥ 249 everywhere).
  3. /var/lib/fenris via /usr/lib/tmpfiles.d/fenris.conf (d /var/lib/fenris 2750 root fenris -) + systemd-tmpfiles --create in postinst. Package owns the directory only (deb %dir / rpm %dir); observations.db, WAL sidecars, .bak never owned, never ghosted (rpm ghost-erase would kill the store — violates uninstall-keeps-store).
  4. /etc/fenris/fenris.conf ships as deb conffile / rpm %config(noreplace), placeholder-commented default, no active device selector. dpkg remove keeps it (≡ uninstall), purge removes it (≡ make purge); documented rpm wrinkle: unmodified config removed on erase, modified survives as .rpmsave.
  5. Wrapper → /usr/bin/fenris for packages (FHS; /usr/local is local-admin territory). make install keeps /usr/local/bin. Coexistence handling deferred to "Grilling: Migration path from make-install systems to packages" (#41).
  6. Removal mapping: deb remove ≈ make uninstall; deb purge ≈ make purge (+ .bak, groupdel); rpm erase ≈ make uninstall, purge = documented manual command. prerm/%preun: sanctioned disable (fenris-monitor disable --now → closes period user_disabled) on remove/erase only — never on upgrade (deb prerm upgrade-case is a no-op; rpm %preun gated on $1 -eq 0).
  7. postinst upgrade mechanics (deb postinst / rpm %post, upgrade case): snapshot observations.db → .bak (one generation) → forward-only migration via inline /opt/fenris/bin/python3 -c "…migrate_to_latest…" (same shape as make upgrade, zero new polkit-reachable binaries — /usr/libexec/fenris stays exactly fenris-monitor + fenris-collect) → daemon-reload → restart fenris-collect.timer only if unit contents changed AND active. Install case: daemon-reload only.
  8. No auto legacy import from packages (no checkout exists at install time). fenris import <path> is the only import path; ADR 0004 §5 auto-detect scope narrowed to make install.

The hand-rolled /var/lib/fenris/manifest.txt model is retired: ownership is the dpkg/rpm DB; manifest never ships; leftover-manifest cleanup on make-install→package upgrade belongs to "Grilling: Migration path from make-install systems to packages" (#41).

ADR 0004 amendment outline (input to "Task: Compose release spec + ADR amending 0004" (#42))

  • §1 Delivery: packages (Gitea registry deb+rpm via nfpm, per "Grilling: Lock channel + toolchain" (#38)) become primary; make install demoted to dev fallback.
  • §2 Layout and manifest: units → /usr/lib/systemd/system; manifest model removed (dpkg/rpm DB is the manifest); add sysusers.d + tmpfiles.d fragments; wrapper /usr/bin/fenris for packages.
  • §3 Privilege: unchanged — root maintainer scripts, runtime elevation exclusively polkit.
  • §4 Dormant install: restated for packages — postinst = daemon-reload only, no enable/preset/start.
  • §5 Legacy import: auto-detect scoped to make install only.
  • §6 Upgrade: maintainer-script inheritance — snapshot + inline-python forward-only migration + daemon-reload + conditional timer restart (deb postinst / rpm %post).
  • §7 Rollback: unchanged one-generation semantics; note package downgrade additionally blocked by forward-only store version refusal.
  • §8 Removal: remove/purge/erase mapping table; prerm sanctioned-disable with upgrade guard; rpm manual purge documented.
  • New section: conffile semantics — placeholder default, noreplace on both formats.

Open item for spec composition (#42), not this ticket: the conffile initial-write mechanism (root-owned /etc/fenris/fenris.conf — who writes the device selector, given ADR 0003 lists no config verb on fenris-monitor) predates this map; verify during composition.

## Resolution All 8 recommendations accepted. Package ownership decisions: 1. **Units → /usr/lib/systemd/system** (vendor placement; `/etc` stays admin-only for drop-ins + enable-state). Dormant parity: postinst does `daemon-reload` only — never enable, never preset, never start; no preset file shipped. 2. **`fenris` group via /usr/lib/sysusers.d/fenris.conf** (`g fenris -`) + explicit `systemd-sysusers` invocation in postinst/%post — declarative, immediate on all four matrix targets (systemd ≥ 249 everywhere). 3. **/var/lib/fenris via /usr/lib/tmpfiles.d/fenris.conf** (`d /var/lib/fenris 2750 root fenris -`) + `systemd-tmpfiles --create` in postinst. Package owns the *directory only* (deb `%dir` / rpm `%dir`); `observations.db`, WAL sidecars, `.bak` never owned, never ghosted (rpm ghost-erase would kill the store — violates uninstall-keeps-store). 4. **/etc/fenris/fenris.conf ships as deb conffile / rpm %config(noreplace)**, placeholder-commented default, no active device selector. dpkg remove keeps it (≡ uninstall), purge removes it (≡ make purge); documented rpm wrinkle: unmodified config removed on erase, modified survives as `.rpmsave`. 5. **Wrapper → /usr/bin/fenris** for packages (FHS; /usr/local is local-admin territory). `make install` keeps /usr/local/bin. Coexistence handling deferred to "Grilling: Migration path from make-install systems to packages" (#41). 6. **Removal mapping**: deb `remove` ≈ make uninstall; deb `purge` ≈ make purge (+ `.bak`, groupdel); rpm erase ≈ make uninstall, purge = documented manual command. prerm/%preun: sanctioned disable (`fenris-monitor disable --now` → closes period `user_disabled`) on remove/erase only — **never on upgrade** (deb prerm upgrade-case is a no-op; rpm %preun gated on `$1 -eq 0`). 7. **postinst upgrade mechanics** (deb postinst / rpm %post, upgrade case): snapshot `observations.db` → `.bak` (one generation) → forward-only migration via inline `/opt/fenris/bin/python3 -c "…migrate_to_latest…"` (same shape as `make upgrade`, zero new polkit-reachable binaries — /usr/libexec/fenris stays exactly fenris-monitor + fenris-collect) → `daemon-reload` → restart `fenris-collect.timer` only if unit contents changed AND active. Install case: `daemon-reload` only. 8. **No auto legacy import from packages** (no checkout exists at install time). `fenris import <path>` is the only import path; ADR 0004 §5 auto-detect scope narrowed to `make install`. The hand-rolled `/var/lib/fenris/manifest.txt` model is retired: ownership is the dpkg/rpm DB; manifest never ships; leftover-manifest cleanup on make-install→package upgrade belongs to "Grilling: Migration path from make-install systems to packages" (#41). ### ADR 0004 amendment outline (input to "Task: Compose release spec + ADR amending 0004" (#42)) - **§1 Delivery**: packages (Gitea registry deb+rpm via nfpm, per "Grilling: Lock channel + toolchain" (#38)) become primary; `make install` demoted to dev fallback. - **§2 Layout and manifest**: units → `/usr/lib/systemd/system`; manifest model removed (dpkg/rpm DB is the manifest); add sysusers.d + tmpfiles.d fragments; wrapper `/usr/bin/fenris` for packages. - **§3 Privilege**: unchanged — root maintainer scripts, runtime elevation exclusively polkit. - **§4 Dormant install**: restated for packages — postinst = `daemon-reload` only, no enable/preset/start. - **§5 Legacy import**: auto-detect scoped to `make install` only. - **§6 Upgrade**: maintainer-script inheritance — snapshot + inline-python forward-only migration + `daemon-reload` + conditional timer restart (deb postinst / rpm %post). - **§7 Rollback**: unchanged one-generation semantics; note package downgrade additionally blocked by forward-only store version refusal. - **§8 Removal**: remove/purge/erase mapping table; prerm sanctioned-disable with upgrade guard; rpm manual purge documented. - **New section: conffile semantics** — placeholder default, `noreplace` on both formats. Open item for spec composition (#42), not this ticket: the conffile initial-write mechanism (root-owned `/etc/fenris/fenris.conf` — who writes the device selector, given ADR 0003 lists no config verb on `fenris-monitor`) predates this map; verify during composition.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Reference: xavierk/Fenris#40