Watch
1
0
Fork
You've already forked SouveraineOS
0

docs: TASK-29 — record the app rewrite and the polkit blocker

This commit is contained in:
Fimeg 2026-07-26 08:02:40 -04:00
commit fccee4ba3d

View file

@ -1,8 +1,9 @@
# TASK 29 — SouveraineOS Updater: finish it and put it through the pipeline
**Status:** **shipped 2026-07-25.** Builds, runs, and installs on the phone by
`pacman -Syu` from the `edge` archive. The app itself still needs real work —
see "What it still needs" at the bottom. **Size:** the pipeline half is done.
**Status:** **shipped 2026-07-25; app rewritten 2026-07-26.** Builds, runs, and
installs on the phone by `pacman -Syu` from the `edge` archive. Read
"The app itself, 2026-07-26" and "What it still needs" at the bottom — the one
thing blocking it now is that nothing in the session can authorise pacman.
The Updater is a Rust/Qt rewrite of the GTK/Python `pachub`. New code, new name
— it is not a fork to be maintained against upstream. It is also the first
@ -140,23 +141,65 @@ which is how it survived from the start.
Not verified: the on-screen window. Offscreen proves construction; the visible
check is Casey's, at the device.
## The app itself, 2026-07-26
The pipeline half shipped first; this is the program. `0.1.r7.g82b1429` on the
phone.
- **The package list is a `QAbstractListModel`.** `PackageManager` is the model
*and* the controller — one QObject, rows as roles. The JSON string is gone.
- **Nothing touches pacman on the GUI thread.** Every invokable hands off to a
`std::thread` and comes back through `CxxQtThread::queue`. Privileged output
streams into the log a line at a time while it runs.
- **The catalog cache is keyed to pacman's own databases** (mtime of
`local/` plus each `sync/*.db`), so a `-Syu` in a terminal invalidates it.
Age alone is still a 6h ceiling.
- **`pacman -Ss .` / `-Qs .` instead of `-Sl`.** `-Sl` carries no description —
its `[installed]` marker was landing in the description column. Installed
version now wins over the offered one, and detail merges `-Si` with `-Qi`
(install date, reason and reverse deps exist only in the local database).
- **Privileged calls take an argv.** `pacman -S --noconfirm ${name}` through
`sh -c` was a command-injection hole in the one program that then runs pacman
as root.
- **Theme + drawn icons.** `Theme.qml` is culver's palette; icons are stroked
paths (`Icons.qml`, `Glyph.qml`). The phone image has **no emoji font**, so
every 📦 / 🔍 / ⚡ in the first build was a tofu box.
- New first-party app icon, in the culver / player family.
- 9 unit tests, up from zero.
Five things that had to be found the hard way:
- **Qt logs to the journal, not stderr, whenever `JOURNAL_STREAM` is set**
and it always is under systemd, which the Gitea runner is. The CI smoke test
was therefore blind to every QML error; it only ever saw main.rs's own line.
`QT_FORCE_STDERR_LOGGING=1` is now set there, with `LC_ALL=C.UTF-8` so Qt's
locale notice does not count as output.
- **`font.families` does not exist on the QML font value type in Qt 6.11.**
Assigning it makes the whole component unavailable. Theme picks one installed
family with `Qt.fontFamilies()` instead.
- **`AbstractButton.icon` is FINAL** — a subclass declaring `property string
icon` fails at creation, which is a null root.
- **`pm: pm` binds a property to itself.** The right-hand side resolves in the
child's own scope first. Everything through it reads undefined.
- **A Control lays its contentItem into the content rect**, so anchoring inside
that rect fights the layout; and `Dialog` sizes its content from itself, so a
wrapped paragraph in one is a binding loop.
## What it still needs
- **Every pacman call is synchronous inside the invokable.** `full_upgrade` and
`rate_mirrors` will freeze the UI for their whole duration. Culver's
`CxxQtThread` + command-channel pattern is the fix.
- **`PackageCache::load()` has no TTL.** `SYNCDB_TTL` (6h) exists but applies
only to `SyncDbCache`, which `load_packages` never calls. So the merged list
is served forever and only `invalidate_all()` clears it — meaning a `pacman`
run *outside* the app leaves the Updater showing stale data indefinitely.
- **QML audit, not yet done.** The whole package set crosses as a JSON string
and is reparsed on every filter keystroke; this wants a real
`QAbstractListModel`. `pm` is passed untyped into the views.
- **The SVG is still `mrks1469`'s artwork, renamed.** GPL-2.0 so redistribution
is fine, but it is not first-party. Replace it.
- `updater-core::auth` shells out to `pkexec`; behaviour with no polkit agent
running is still unverified.
- `cargo test` runs zero tests.
- **No polkit agent runs in the phone session** (verified 2026-07-26: `pkexec
--disable-internal-agent` → "No authentication agent found"). So every
privileged action — install, remove, upgrade, sync — fails. The Updater now
says exactly that instead of reporting a bare failure, but the agent is the
shell's to run, and until it does the app is read-only on the device.
- `rate-mirrors` is not in the phone image; the action is hidden unless the
binary exists. `paccache` and `reflector` are absent too.
- No cancel: a running `-Syu` can be watched but not stopped.
- AUR support was deleted with `aur.rs` — it was dead code that never parsed a
version, and there is no helper on the phone. Foreign packages are still
listed and upgraded by pacman; building from the AUR is not offered.
- The on-screen window on the phone is still Casey's check. Both layouts are
verified by headless render on archdev (Xvfb + the shipped binary).
## Connects to