aboutsummaryrefslogtreecommitdiffstats
path: root/docs
diff options
context:
space:
mode:
authorDanilo M. <danix@danix.xyz>2026-10-21 10:03:29 +0200
committerDanilo M. <danix@danix.xyz>2026-10-21 10:03:29 +0200
commitcfb7b22b6754b8315a249af6f367f4ab5871fe21 (patch)
tree9f367f2c8a82f034d22cead360b8061a2e27c707 /docs
parent6b8aa1a47ce73101956c205314eb18dbeb9429a2 (diff)
downloadquickshell-cfb7b22b6754b8315a249af6f367f4ab5871fe21.tar.gz
quickshell-cfb7b22b6754b8315a249af6f367f4ab5871fe21.zip
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 <noreply@anthropic.com>
Diffstat (limited to 'docs')
-rw-r--r--docs/superpowers/specs/2026-10-21-sb-builder-settings-design.md92
1 files changed, 92 insertions, 0 deletions
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": <file text, "" when missing>,
+ "defaults": <DEFAULTS>, "path": <config 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 <ssh_options> <target> 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.