fix: make an existing classroom converge into the Plasma appliance
A real room upgraded to 0.1.45 and came up as stock Debian Plasma with the old Waybar across the top, mako still catching notifications, and a lock screen on an account that has no password. The cause was one line, and it was in the lab: the harness handed the session under test XDG_CONFIG_DIRS by hand, so every result it had ever produced was a result about a machine somebody had already configured. On a machine SDDM starts the session through PAM, PAM does not read /etc/environment.d, and Debian's own plasma-workspace env.sh then set the variable from scratch — so the classroom's settings directory was not in the cascade at all. No layout, no lock policy, no Kiosk restrictions. The settings now arrive the way Plasma delivers them, through a file in /etc/xdg/plasma-workspace/env. Around that: the look and feel is immutable on its own key so a stale profile cannot answer for it; the palette is composed into the package, because naming a colour scheme does not produce one and the dark bar had been coming from a technician's hand; the desktop reset converges another desktop's appearance state and keeps the room's own; and classroom-migrate stops, deactivates and masks the old shell, including the D-Bus activation that brought mako back while the panel was down — found only by killing the panel on a migrated machine. device.conf loses COMPOSITOR and comes off the hyprland channel, which would otherwise have handed the room the experiment back. The lab stops flattering the package: it restarts the machine, lets SDDM actually autologin, and asks a fresh install and a machine upgraded from the Hyprland package the same sixty questions. Both answer identically, twice, and the panel still comes back from eight SIGKILLs. Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
co-authored by
Claude Opus 5
parent
6050144e5d
commit
926668dc9b
+199
-11
@@ -937,6 +937,165 @@ ekklesia-classroom-tv.service small, supervised, ours
|
||||
adapters arrive today; the commands get measured before anything is
|
||||
built on them.
|
||||
|
||||
## The upgrade that failed
|
||||
|
||||
The clean-install result was real and the migration was not. A classroom
|
||||
machine that had been through the sway build and then the Hyprland
|
||||
experiment took the 0.1.45 package and came up as **stock Debian Plasma**:
|
||||
kickoff, a pager, a full system tray, the Debian wallpaper, the old Waybar
|
||||
still across the top, mako still catching notifications — and then a lock
|
||||
screen, on an account that has no password. Somebody had to give the
|
||||
appliance account a password over SSH to get back in.
|
||||
|
||||
None of that was visible here, because the lab had been answering an
|
||||
easier question than the one a room asks.
|
||||
|
||||
### Reproducing it
|
||||
|
||||
One line of the harness:
|
||||
|
||||
```
|
||||
tools/lab/lab plasma-up: -e XDG_CONFIG_DIRS=/etc/ekklesia-classroom/xdg:/etc/xdg
|
||||
```
|
||||
|
||||
The lab had been handing the session under test the very setting whose
|
||||
delivery was the thing in doubt. Removing it and starting the session the
|
||||
way a machine does reproduced the failure exactly: 23 applets, kickoff,
|
||||
pager, system tray, Debian wallpaper — `docs/screenshots/migration-before.png`
|
||||
is that screen, and it is the teacher's screen.
|
||||
|
||||
### Root causes
|
||||
|
||||
**1. The classroom's settings never reached the session.** Everything the
|
||||
room is — the panel layout, the lock screen that must never appear, the
|
||||
idle behaviour, every Kiosk restriction — lives in
|
||||
`/etc/ekklesia-classroom/xdg`, and reaches Plasma only if that directory
|
||||
is in `XDG_CONFIG_DIRS`. It was set in `/etc/environment.d`, which
|
||||
systemd's **user manager** reads. SDDM starts the session through PAM, and
|
||||
PAM does not read `/etc/environment.d`. Debian's own
|
||||
`/etc/xdg/plasma-workspace/env/env.sh` then set the variable from scratch,
|
||||
because it was empty, and `startplasma` pushed its own environment back
|
||||
into the user manager — so the value was not merely bypassed, it was
|
||||
overwritten for every user service too. Measured in the session that came
|
||||
up:
|
||||
|
||||
```
|
||||
XDG_CONFIG_DIRS=/home/classroom/.config/kdedefaults:/etc/xdg:/usr/share/desktop-base/kf5-settings
|
||||
LookAndFeelPackage = org.debian.desktop
|
||||
Autolock = (unset, so on)
|
||||
shell_access = (unset, so allowed)
|
||||
```
|
||||
|
||||
The stock panel, the lock screen and the absence of every Kiosk
|
||||
restriction are all that one line.
|
||||
|
||||
**2. Deleting the panel configuration made it worse.** The desktop reset
|
||||
removes `plasma-org.kde.plasma.desktop-appletsrc` before the shell starts
|
||||
so that the bar always comes from the package. With the look and feel
|
||||
unresolvable, Plasma rebuilt the **Debian** default layout instead. The
|
||||
reset was correct and was pointed at the wrong answer.
|
||||
|
||||
**3. Naming a colour scheme does not produce one.** `ColorScheme=EkklesiaDark`
|
||||
is a label; KConfig reads the actual colours from `[Colors:*]` groups in
|
||||
kdeglobals, and nothing was putting them there except a technician having
|
||||
run `classroom-theme` once by hand. The clean-install screenshots looked
|
||||
right for a reason the package did not own. A machine with no user
|
||||
profile got Breeze light — confirmed here the moment a profile was
|
||||
cleared.
|
||||
|
||||
**4. A stale user profile outranks the package.** `~/.config/kdeglobals`
|
||||
sits ahead of every system directory, and `~/.config/kdedefaults` ahead of
|
||||
ours. A migrated machine carried a Breeze-light palette in both.
|
||||
|
||||
**5. The old shell was still being started.** `waybar.service` was
|
||||
activated through `graphical-session.target.wants` — and, found only by
|
||||
running the crash-recovery suite on a migrated machine, **mako came back
|
||||
through D-Bus**: the panel was killed, something sent a notification while
|
||||
nothing owned `org.freedesktop.Notifications`, and D-Bus started mako from
|
||||
the file `mako-notifier` ships. Deactivating the systemd unit would not
|
||||
have been enough.
|
||||
|
||||
And one more that had not bitten yet: `device.conf` still said
|
||||
`CHANNEL=hyprland`, so the next release published on that channel would
|
||||
have handed the room the Hyprland experiment back.
|
||||
|
||||
### The fix
|
||||
|
||||
| | |
|
||||
| --- | --- |
|
||||
| `config/plasma/env/zz-ekklesia-classroom.sh` | new. `/etc/xdg/plasma-workspace/env/` is sourced by `startplasma` for every session; the name sorts after Debian's `env.sh`, so it appends rather than replaces, and it is a no-op if the directory is already there. This is the root fix. |
|
||||
| `config/plasma/xdg/kdeglobals` | `LookAndFeelPackage[$i]` — per-entry immutability, so no leftover profile and no stray write can answer that question differently. The palette stays writable, because `classroom-theme` may change it. |
|
||||
| `tools/build-kdeglobals` | new. Composes the shipped kdeglobals from the session policy **and** `EkklesiaDark.colors`, so the room is dark because the package says so. One source of truth: it composes, it does not duplicate. |
|
||||
| `scripts/classroom-desktop-reset` | asserts the cascade and repairs it for the shell about to start if it is wrong; removes another desktop's look and feel defaults and a foreign palette; keeps an Ekklesia one; clears a user power profile. |
|
||||
| `scripts/classroom-migrate` | new. Stops, deactivates and masks the old shell's units, removes activation from all three directories it can live in, removes hand-written unit files that no Debian package owns, clears old autostart entries, removes the login shell that used to start sway, and migrates `device.conf`. Run from `postinst` on every install. |
|
||||
| `config/dbus/fr.emersion.mako.service` | new. Shadows mako's D-Bus activation from `/usr/local/share`, where the session bus looks first. `Exec=/bin/false`, which is what a machine with no notification daemon does anyway. |
|
||||
| `config/plasma/xdg/powermanagementprofilesrc` | profiles immutable at the profile level, not just on the button subgroups: PowerDevil loads an idle action when it finds a group for it, so a writable profile is one a leftover user file can add a suspend to. |
|
||||
| `config/systemd/logind-ekklesia-classroom.conf` | `IdleAction=ignore` as well. |
|
||||
| `config/sddm/ekklesia-classroom.conf` | uid range 1000–1999. The first migrated room's classroom account was uid 1001 and would not have appeared in the greeter at all. |
|
||||
|
||||
### What device.conf means now
|
||||
|
||||
`COMPOSITOR` and `HYPR_APPEARANCE` are removed on upgrade. There is one
|
||||
desktop stack and nothing left for them to choose; a stale value is an
|
||||
instruction this package cannot carry out.
|
||||
|
||||
`CHANNEL=hyprland` becomes `CHANNEL=classroom-v2`. Not `stable` and not
|
||||
`canary`: both are the sway line, and a release published there would
|
||||
convert a v2 machine back. **That channel is not published yet**, so a
|
||||
migrated machine takes no updates until it is — which is the honest state
|
||||
of an unpublished experiment, and better than being quietly reverted.
|
||||
Everything else in the file, the broker password included, is rewritten
|
||||
line by line and byte-for-byte.
|
||||
|
||||
### The tests that would have caught it
|
||||
|
||||
- `tools/lab/lab plasma-up` no longer sets `XDG_CONFIG_DIRS`. The package
|
||||
has to put it there, the way it has to on a machine.
|
||||
- `tools/lab/lab reboot` — a real restart of the machine under test: new
|
||||
PID 1, new user manager, every drop-in and generator read again. **SDDM
|
||||
autologin genuinely runs here**: it authenticates the classroom through
|
||||
PAM and launches the Plasma session, and then has no display hardware to
|
||||
draw on. Both scenarios now go through it.
|
||||
- `tools/lab/converged-check` — 60 properties of a converged machine,
|
||||
asked of the running system and never of the repository. Both scenarios
|
||||
run the same list, because a fresh install and a migrated one have to be
|
||||
indistinguishable from a teacher's chair.
|
||||
- `tools/lab/dirty-upgrade` — the Hyprland package actually installed,
|
||||
with sway, waybar and mako behind it; Waybar activated in all three
|
||||
directories; an autostart entry; a device.conf asking for a compositor
|
||||
that is gone; a Breeze-light profile in both places that outrank the
|
||||
package; a stock panel already built; and a user power profile that
|
||||
would suspend the room. Then the new package, a reboot, and the
|
||||
questions.
|
||||
- `tests/test-migration.sh` — 41 source-level checks, one per reason the
|
||||
failure happened.
|
||||
|
||||
### Results
|
||||
|
||||
| | |
|
||||
| --- | --- |
|
||||
| dirty upgrade → converged | 60 / 60 |
|
||||
| installed a second time over itself | 60 / 60, device.conf unchanged |
|
||||
| clean install → converged | 60 / 60 |
|
||||
| panel killed eight times | back every time, 2.2–7.4s |
|
||||
| compositor killed twice | 0.1–0.4s |
|
||||
| audio policy killed three times | active every time |
|
||||
| the room's light theme across a logout | survived |
|
||||
| every test script | 11 / 11 |
|
||||
|
||||
`docs/screenshots/migration-after.png` and `v2-from-package.png` are the
|
||||
migrated machine and the fresh one. They are the same desktop.
|
||||
|
||||
### One regression this pass made and caught
|
||||
|
||||
The first version of the reset deleted `~/.config/kdedefaults`
|
||||
unconditionally. Plasma treats that directory as the record of which look
|
||||
and feel is in force, so deleting it made Plasma re-apply the look and
|
||||
feel at every login — which throws away the room's chosen palette.
|
||||
Measured: `classroom-theme light`, log out, and the bar came back dark.
|
||||
The rule is now whose the defaults are: the classroom's are kept, another
|
||||
desktop's are removed.
|
||||
|
||||
## Unresolved risks
|
||||
|
||||
In the order I would worry about them.
|
||||
@@ -960,10 +1119,13 @@ In the order I would worry about them.
|
||||
tries disturbs the session enough to close the card. The name was
|
||||
typed through a lab-only `--child` argument. **Type a name on the
|
||||
bench before a Sunday.**
|
||||
4. **SDDM is configured and untested.** It cannot be exercised in a
|
||||
container, and it is the thing that starts the session. If the config is
|
||||
wrong the room boots to nothing. This is the first thing to check on a
|
||||
VM or a bench machine, and it is why the checklist below starts there.
|
||||
4. **SDDM has never put a picture on a screen.** More is known than
|
||||
before: in the lab it really does autologin, authenticating the
|
||||
classroom through PAM and launching the Plasma session — that is now
|
||||
one of the checks. What it cannot do in a container is find a display
|
||||
to draw on, so everything from the compositor's first frame onwards is
|
||||
still a bench test. It remains the first thing to check on a VM or a
|
||||
bench machine.
|
||||
5. **No real audio hardware has been through the policy.** The decision is
|
||||
well tested; applying it is not. A wrong `pactl set-card-profile` on
|
||||
real hardware is a silent room.
|
||||
@@ -988,7 +1150,17 @@ In the order I would worry about them.
|
||||
registered from the packaged entry and its action opens a shell —
|
||||
verified over D-Bus — but key injection cannot reach the nested
|
||||
session, so `Meta+Ctrl+Alt+Shift+K` itself is unpressed.
|
||||
13. **Ctrl+Alt+T is still registered.** Konsole's own entry declares it
|
||||
13. **Idle behaviour is configured and unobserved.** No suspend, no dim,
|
||||
no blank and no lock are all now in the package, immutable, and read
|
||||
back correctly from a migrated session. Nothing in a container goes
|
||||
idle, so none of it has been watched not happening. **Leave a bench
|
||||
machine alone for an hour.**
|
||||
14. **The v2 channel does not exist yet.** A migrated machine is moved to
|
||||
`CHANNEL=classroom-v2` so that a stable or Hyprland release cannot
|
||||
take it back, and nothing is published there. Until it is, a v2
|
||||
machine takes no updates at all. That is deliberate; it is also a
|
||||
thing to remember before leaving one in a room.
|
||||
15. **Ctrl+Alt+T is still registered.** Konsole's own entry declares it
|
||||
and the registration survives being shadowed. It is inert, because
|
||||
Konsole refuses to open a shell under the classroom's
|
||||
`shell_access=false` — measured — but it rests on that one
|
||||
@@ -1078,6 +1250,16 @@ The existing Debian classroom test VM should be kept.
|
||||
package, hidden from every application list, granting no privilege.
|
||||
* **Long-Escape investigated and recommended against**, with the two
|
||||
clean alternatives written down.
|
||||
* **The migration failure found on a real room and fixed in the package**:
|
||||
the settings directory now reaches the session the way Plasma delivers
|
||||
it, the look and feel cannot be answered for by a stale profile, the
|
||||
palette is in the package rather than in somebody's home directory, and
|
||||
the old shell is stopped, deactivated, masked and — the one that was
|
||||
only found by killing the panel — unable to come back through D-Bus.
|
||||
* **The lab stopped flattering the package**: it no longer sets the
|
||||
session's configuration path by hand, it restarts the machine, and it
|
||||
asks a fresh install and a machine upgraded from the Hyprland
|
||||
experiment the same sixty questions. Both answer them identically.
|
||||
|
||||
**Next**, in order:
|
||||
|
||||
@@ -1090,11 +1272,17 @@ The existing Debian classroom test VM should be kept.
|
||||
disc. These three are the only things left that a container cannot
|
||||
answer, and each of them is a Sunday-morning path. Add the power
|
||||
button and the maintenance chord to that list.
|
||||
2. Publish `0.1.45~plasma1` to a channel of its own, the way the Hyprland
|
||||
milestone did, so a stable or canary room can never be offered it.
|
||||
3. Bench-test SDDM: autologin, and that ending the session brings the
|
||||
classroom back rather than a shell.
|
||||
4. When the CEC adapters have been exercised, replace the computer volume
|
||||
2. Publish the v2 channel. `classroom-migrate` already moves a migrated
|
||||
room onto `CHANNEL=classroom-v2`, and nothing serves that manifest
|
||||
yet, so those machines are taking no updates at all. This is now the
|
||||
first packaging job rather than a tidy-up.
|
||||
3. Take the upgraded VM through the same list by hand:
|
||||
`tools/lab/converged-check` is the shape of it, and the things a
|
||||
container cannot answer are the lock screen never appearing after an
|
||||
hour alone, and the machine still being there on Monday.
|
||||
4. Bench-test SDDM on hardware: autologin all the way to a picture, and
|
||||
that ending the session brings the classroom back rather than a shell.
|
||||
5. When the CEC adapters have been exercised, replace the computer volume
|
||||
applet with a television control, behind the service boundary in
|
||||
*Television control, and where CEC will fit*.
|
||||
5. Live View, when the rest is quiet.
|
||||
6. Live View, when the rest is quiet.
|
||||
|
||||
Reference in New Issue
Block a user