The fourth panel this desktop handed to GNOME Settings, and the last one worth owning. Driverless only, deliberately. Adding a printer that describes its own capabilities over IPP is supported; choosing a PPD or fetching a vendor driver is not, and the page says so rather than pretending. That restraint is the whole design: a wrong driver produces a printer that accepts jobs, reports success, and prints nothing, which is the worst failure this page could ship because it looks like it worked. A printer old enough to need a PPD stays a job for the system printer tool. Printers and the queue are separate cards because they answer separate questions. Which printers exist is one; where a document went is the other, and it is the one that actually brings someone here -- so the queue is a single list across every printer. Device URIs are validated by scheme before reaching CUPS, whose backends run as root. file: and pipe: do not lead to a printer and are refused here rather than further down. This machine has no printer, so the page was built against a temporary CUPS queue that was created, exercised through the service, and removed; the service was confirmed to observe the removal rather than merely perform it. Discovery and the driverless add path are verified by their refusals rather than against hardware. Claude-Session: https://claude.ai/code/session_01BRvzt4H8XXLPVH5MyYdk9L
222 lines
10 KiB
Markdown
222 lines
10 KiB
Markdown
# Desktop integration: the parts an OS owns that we still hand to someone else
|
|
|
|
Written 2026-08-19, after the default-applications work landed.
|
|
|
|
Settings is now a superpowered control panel, and files open in the right
|
|
applications. What remains are the jobs a desktop environment is expected to own
|
|
but that this one currently delegates, ignores, or leaves to whatever GNOME
|
|
component happens to be installed.
|
|
|
|
Six items, ordered so each one is useful the day it lands rather than only at the
|
|
end. Effort labels are relative to each other, not to the clock.
|
|
|
|
## What the probe found
|
|
|
|
Two of these are far cheaper than assumed:
|
|
|
|
- **`sushi` 50 is already installed** and owns `org.gnome.NautilusPreviewer`, so
|
|
Quick Look is a wiring-and-declaring job, not a build.
|
|
- **Vicinae script commands already exist and are repo-managed**
|
|
(`config/local/share/vicinae/scripts/panama/`, linked by
|
|
`setup/scripts/link-vicinae-scripts`), so launcher search is a generator on top
|
|
of a mechanism that works.
|
|
|
|
And two need software this machine does not have: `restic` (backups) is not
|
|
installed, and nothing enumerates the keyring beyond lock state.
|
|
|
|
---
|
|
|
|
## Phase 1 — Finish the file-opening story (small)
|
|
|
|
Curating defaults only helps if the applications are actually present. A fresh
|
|
install seeds `org.gnome.Loupe`, `org.gnome.Papers` and `org.gnome.Decibels`
|
|
only when they exist; otherwise it correctly leaves the role alone and the
|
|
machine falls back to installation order — the exact problem we just fixed.
|
|
|
|
- Declare Loupe, Papers, Decibels, Nautilus, mpv and sushi so a fresh machine
|
|
actually has what seeding prefers.
|
|
- Wire preview.
|
|
- Extend the family contract to assert every preferred handler is a declared
|
|
package.
|
|
|
|
**Done when** a fresh machine gets the same handlers this one has, and the
|
|
contract fails loudly if a curated application is not a declared dependency.
|
|
|
|
**Landed 2026-08-19.** The previewer answers on `org.gnome.NautilusPreviewer2`,
|
|
not the `NautilusPreviewer` interface its bus name suggests, and it opened
|
|
*tiled* -- shoving the file manager aside for something meant to be an overlay
|
|
-- so it now has a float-and-center window rule. No compositor keybind: the
|
|
selection to preview lives in the file manager, and nothing outside it knows
|
|
what is selected. `xdg-utils` and `desktop-file-utils` were also undeclared,
|
|
which the dependency contract caught the moment seeding started calling them.
|
|
|
|
## Phase 2 — Make GTK applications wear our accent (small)
|
|
|
|
The named accents theme our own surfaces; Loupe, Papers, Nautilus and every other
|
|
libadwaita application still render in GNOME blue. GNOME exposes
|
|
`org.gnome.desktop.interface accent-color` as an enum (blue, teal, green,
|
|
yellow, orange, red, pink, purple, slate).
|
|
|
|
- Give each named accent a nearest-GNOME-enum member in `Theme.qml`, beside the
|
|
dark/light pair it already carries.
|
|
- Apply it alongside the existing GTK theme write, so one accent change moves
|
|
both worlds.
|
|
- Contract: every named accent maps to a member the enum actually publishes,
|
|
read from `gsettings range` rather than a hardcoded list.
|
|
|
|
**Done when** switching accent visibly recolors Papers and Nautilus.
|
|
|
|
## Phase 3 — Disks and storage (medium)
|
|
|
|
There is no way to see what is using the disk, and removable media is handled by
|
|
`udiskie` in the tray with no surface in Settings. `udisks2` is installed.
|
|
|
|
- Helper `panama-disks`: JSON snapshot of filesystems, sizes, usage, mount
|
|
points, removable devices, and SMART health where the device exposes it.
|
|
- Page: usage bars per filesystem, removable devices with mount / unmount /
|
|
eject, and "open in Files".
|
|
- **Deliberately out of scope: partitioning and formatting.** A settings pane is
|
|
the wrong place to hand someone a way to erase a disk in two clicks; that stays
|
|
with GNOME Disks, which we can launch.
|
|
|
|
**Done when** the page answers "what is filling my drive" and "is it safe to pull
|
|
this USB stick out".
|
|
|
|
**Landed 2026-08-19.** Built as mock A over mock B on one scroll rather than
|
|
tabs: every other settings page is a scrolling card stack, and a tab would not be
|
|
deep-linkable from the launcher command or from search.
|
|
|
|
Three things the page had to get right, each now pinned by a contract, because
|
|
each is a way it could quietly lie:
|
|
|
|
- `/` and `/home` are one btrfs filesystem sharing one pool of free space. `df`
|
|
reports them separately, and a page that copies `df` shows double the free
|
|
space that exists.
|
|
- zram is a block device and is not storage. Counting it as a drive would
|
|
overstate this machine by 8 GB.
|
|
- unmount and eject refuse anything not on a removable drive. The UI is what
|
|
asks, and a UI can be wrong.
|
|
|
|
Adding the page also found a fourth hard-coded page list in `ShellState.qml`.
|
|
Missing from it, a page does not error -- `openSettings()` falls back to "home",
|
|
so the launcher command opens the wrong page and logs nothing. There is now a
|
|
registry contract holding the sidebar, the shell switch, and the allow-list
|
|
together.
|
|
|
|
## Phase 4 — Launcher-native settings search (small)
|
|
|
|
Settings has a search index. The launcher has script commands. They do not know
|
|
about each other, so finding a setting means opening Settings first.
|
|
|
|
- Generate one script command per settings page from the same schema that feeds
|
|
in-app search, with the page's keywords, so typing "night light" in the
|
|
launcher opens that page directly.
|
|
- Generator gets a `--check` staleness mode, matching `panama-settings-docs`.
|
|
- Contract: every page has a command, every command resolves to a real page.
|
|
|
|
**Done when** the launcher is the fastest way to reach any setting.
|
|
|
|
**Landed 2026-08-19.** The product prefix is gone from all eighteen hand-written
|
|
commands. The nineteen generated ones are titled "Settings: <page>" -- not
|
|
branding, which was the thing being dropped, but a qualifier: a bare page label
|
|
collides with the feature of the same name ("Screen Intelligence" is both a thing
|
|
you open and a page about it), and two commands sharing a title are
|
|
indistinguishable in a launcher.
|
|
|
|
Six pages turned out to have no search vocabulary at all -- sound, privacy,
|
|
region, accounts, home-phone, about -- because their contents come from the
|
|
system rather than our schema. That was an in-app search gap too: "volume" found
|
|
nothing in Settings either. They now carry entries, so both surfaces improved.
|
|
|
|
## Phase 5 — Keychain and secrets (medium, security-sensitive)
|
|
|
|
`panama-keyring` knows whether the keyring is locked and can unlock it. Nothing
|
|
can see what is *in* it, so managing a stored credential means installing
|
|
Seahorse.
|
|
|
|
- Extend the helper to enumerate collections and items through libsecret,
|
|
returning **attributes and labels only**.
|
|
- Page: unlock state, lock/unlock, items grouped by collection, delete, change
|
|
password.
|
|
- Rules that are non-negotiable and get their own contracts: a secret value never
|
|
appears in a snapshot, never reaches a command line (argv is world-readable via
|
|
`/proc`), never lands in a log or an error message, and is revealed only on an
|
|
explicit per-item request.
|
|
|
|
**Done when** a stored password can be found, inspected and removed without
|
|
leaving Settings, and the contracts prove no value leaks on the way.
|
|
|
|
**Landed 2026-08-19.** Built into Privacy & Security rather than as its own
|
|
page: that page already claimed the topic, already had the keyring rows, and
|
|
already answered the "saved passwords" search. A new page would have been a
|
|
fourth page-registry edit for a card.
|
|
|
|
The list is collapsed until asked for -- opening Privacy should not enumerate
|
|
someone's passwords as a side effect -- and copying puts the value on the
|
|
clipboard without it ever entering Quickshell: the helper reads it, writes it to
|
|
`wl-copy` on stdin, and a detached guard clears it about a minute later only if
|
|
the clipboard still holds it, comparing a SHA-256 rather than the password.
|
|
|
|
Seahorse is not installed, so changing a keyring's password is not offered.
|
|
Claiming a button that hands off to a missing application would be worse than
|
|
not having it.
|
|
|
|
## Phase 6 — Backups (large, staged)
|
|
|
|
The one genuinely missing safety net. `restic` is not installed.
|
|
|
|
- **6a** — destination and repository setup, plus a manual snapshot. Repository
|
|
password lives in the keyring (which is why this follows phase 5), never in the
|
|
repo and never on argv.
|
|
- **6b** — a systemd user timer, with the page showing schedule, last run, and
|
|
failures.
|
|
- **6c** — restore: browse a snapshot and copy files out.
|
|
|
|
Blast radius: writes to a destination the user chooses. Nothing in this phase
|
|
modifies or deletes existing data; restore copies out rather than over.
|
|
|
|
**Done when** losing the home directory is an inconvenience rather than a
|
|
catastrophe.
|
|
|
|
---
|
|
|
|
## Order and reasoning
|
|
|
|
Phases 1 and 2 finish work already in flight and are visible immediately. Phase 3
|
|
is self-contained and answers a question people actually ask. Phase 4 is small
|
|
but changes daily habit. Phase 5 must precede 6 because 6 needs somewhere safe to
|
|
keep a repository password. Phase 6 is the largest and is staged so each part
|
|
stands alone.
|
|
|
|
|
|
---
|
|
|
|
## Deprecating GNOME Settings
|
|
|
|
Not removing it -- making it unnecessary. Tracked here because "which panels do
|
|
we own" is a question that otherwise gets answered one panel at a time.
|
|
|
|
**Owned (2026-08-19).** Users and Sharing. Users drives accountsservice, the same
|
|
daemon GNOME's panel drives, so a name or picture set here is what the login and
|
|
lock screens read. Sharing covers remote login and remote desktop, and reports
|
|
file and media sharing as absent rather than offering a switch for software that
|
|
is not installed.
|
|
|
|
**Owned (2026-08-19, later).** Printers, driverless only. Adding a printer that
|
|
describes its own capabilities over IPP is supported; choosing a PPD or fetching
|
|
a vendor driver is not, and the page says so. That restraint is the point: a
|
|
wrong driver produces a printer that accepts jobs, reports success, and prints
|
|
nothing, which is the worst failure this page could ship because it looks like it
|
|
worked. A printer old enough to need a PPD stays a system-config-printer job.
|
|
|
|
**Still handed to GNOME.** Color, Wacom, and Universal Access. Each
|
|
wraps hardware-specific tooling with no D-Bus surface worth reimplementing, and
|
|
each launches with XDG_CURRENT_DESKTOP=GNOME because gnome-control-center refuses
|
|
to run otherwise. Digital Wellbeing is deliberately absent: it configures
|
|
gnome-shell's own screen-time reporting, which does not run here.
|
|
|
|
**Note.** This machine has no printer, so the page was built against a temporary
|
|
CUPS queue that was created, exercised, and removed. The driverless add path
|
|
itself is verified by construction and by its refusals rather than against
|
|
hardware; the first real printer added here is worth watching.
|