From cfb7b22b6754b8315a249af6f367f4ab5871fe21 Mon Sep 17 00:00:00 2001 From: "Danilo M." Date: Wed, 21 Oct 2026 10:03:29 +0200 Subject: docs: spec the sb-builder settings pages Two pages under SB Builder in the settings window: the GUI's config.toml edited in place, and the helper's config on the VM through new config-get/config-set commands, so the helper keeps validating what is written to it. The sb-builder half is built in that repo. Co-Authored-By: Claude Opus 5.5 --- .../specs/2026-10-21-sb-builder-settings-design.md | 92 ++++++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 docs/superpowers/specs/2026-10-21-sb-builder-settings-design.md (limited to 'docs') diff --git a/docs/superpowers/specs/2026-10-21-sb-builder-settings-design.md b/docs/superpowers/specs/2026-10-21-sb-builder-settings-design.md new file mode 100644 index 0000000..e40a1d3 --- /dev/null +++ b/docs/superpowers/specs/2026-10-21-sb-builder-settings-design.md @@ -0,0 +1,92 @@ +# sb-builder settings pages + +sb-builder (a PyQt6 GUI in its own repo, `../sb-builder`) has two TOML +configs and no UI to edit either: the GUI's own +`$XDG_CONFIG_HOME/sb-builder/config.toml` on this desktop, and the helper's +`/etc/sb-builder/config.toml` on the build VM. Both get settings pages here, +in the `desktop/` settings window, under a group "SB Builder", the way +qtmaildir's four pages sit under "Mail". + +## Pages + +`desktop/modules/sbbuilder/`: + +- `Sbb.qml`, the singleton both pages share: two drafts (desktop, VM), each + with the text last read, `dirty`, `invalid`, `error`, `save()`, + `discard()`, `refresh()`, as `Qtm.qml` does for one. +- `Toml.js`, a line editor for the TOML these two files use: top-level and + `[section]` keys whose values are strings, integers, booleans and arrays of + strings, one key per line. It reads a value, sets one (in place, or + appended to its section, the section appended when missing), unsets one + (commented out with `#` where it stands, reactivated when set again), and + lists a section's keys. Comments and order survive. Values it writes are + TOML basic strings with `\` and `"` escaped. `test_toml.js` is its check, + run with `node`. +- **Desktop** page (`SbbDesktopModule.qml`), over the GUI config through a + watched, atomic `FileView`: remote target and ssh options, the two refresh + intervals, notifications on/off and one switch per event, the VM's libvirt + URI, domain and autostart, the initial publish state, the nvchecker + keyfile, the repository path. +- **Build VM** page (`SbbVmModule.qml`): the helper's thirteen keys and the + `[manifests]` table as rows, removable, with an add row (package, URL). + +Every field follows the settings window's rules (`desktop/README.md`): it +edits the draft as typed, Save in the page header writes, Discard drops, +a save over a file changed since the draft began is refused. An emptied +field unsets its key and the placeholder names the default. Numbers are +range-checked (refresh intervals: whole seconds, at least 1), a refused one +holds Save back. Lists (`ssh_options`, `overlays`) are one field, entries +separated by spaces; an entry holding a space is a `ponytail:` ceiling, +editable only by hand. + +The desktop defaults are mirrored from sb-builder's `config.py` DEFAULTS +(`ponytail:` a key added there needs adding here). The VM defaults come +from the helper itself. + +## The VM side + +The helper's config is root's file on another machine, and the helper is a +trust boundary: it runs a fixed command table and validates what reaches it. +So the page never writes the file by hand over ssh. sb-builder's helper gains +two commands: + +- `sbb-remote config-get`: JSON `{"text": , + "defaults": , "path": }`. +- `sbb-remote config-set`: the new file text on stdin. Parsed with + `tomllib`; refused, with the reason as its error, on a parse error, an + unknown key or a value of the wrong type (the checks `load_config` already + makes, `[manifests]` values strings). Accepted, it copies the old file to + `.bak` and replaces it atomically (temp file, rename). stdin input has a + precedent in `gpg-unlock`. + +The page runs `ssh sbb-remote config-get` with the +target and options from the desktop page's saved config (not its draft), on +every open of the window and from a reload button. Save pipes the draft to +`config-set`. The helper's error, or ssh's, lands in the SaveBar. With the +VM down the page says so and its fields are read-only. The helper reads its +config on every call, so a saved change applies to the next one. + +The VM draft's "changed on disk" check compares the text config-get last +returned against a fresh config-get just before config-set. + +## sb-builder's side + +Owned by that repo, built there: + +- the two helper commands above, with `test_remote.py` cases: accepted text + written and `.bak` made, bad TOML, unknown key, wrong type refused with the + file untouched; helper VERSION bumped in `remote/sbb-remote` and + `sb_builder/__init__.py`; deploying with `./install.sh --remote` is asked + first. +- the GUI watches its config file (`QFileSystemWatcher`, re-added after each + change since an atomic write replaces the inode) and calls its existing + `reload_config`, so a save from the settings page applies live. File, + Reload config stays. +- a note in its README that both configs have settings pages in Keystone, + and that the files remain hand-editable. + +## Out of scope + +The phantom deps file, hint files and anything else the helper reads besides +its config. Editing configs of a VM other than the one `remote.target` +names. -- cgit v1.2.3