3 Commits
Author SHA1 Message Date
ekklesiaandClaude Opus 5 dfd42f6fdf feat: give the rooms a line to the church broker
The first piece of turning these machines into connected endpoints.
classroom-mqtt is one small service per room that subscribes, validates
what arrives, and hands the work to commands that already exist.

Nothing in the room depends on it. A broker that is down, a network that
is missing, a machine with no broker configured at all — each is a
service sitting quietly, not a classroom that fails. Nothing waits for
it at boot and the shipped default is off, so every existing classroom
upgrades into this release with messaging disabled until a broker
exists.

The room is the hostname, which is already how these machines are named.
Topics carry no product name because the broker is the church's and
these are just rooms: classroom/notify/all, classroom/notify/<room>, and
a retained classroom/status/<room> so anyone asking later can be told
which rooms are up without waiting for them to say so again.
Notifications are events and are never retained; status is state and is.

Stale messages cannot come back, which is the property that matters most
and has two halves. The session is clean, so a broker never hands over a
backlog from while the room was off. And retained notifications are
refused on arrival, because otherwise one would replay into every room
at every reboot forever. The honest limit is written down: MQTT only
flags a retained message when it is replayed to a new subscription, so a
retained publish delivered live is indistinguishable from an ordinary
one and is shown once — which is right, since it is live at that moment,
and the replay is the actual hazard.

Delivery reuses the session-aware sender rather than a second copy of
it. classroom-notify-test grew into the real thing, so it is now
classroom-notify with the sample sender a wrapper over it, and its 36
tests came along.

The broker password lives in device.conf, so that file stops being world
readable: 0640 root:classroom, which everything that reads it already
satisfies.

Transport logic is kept free of any broker library so it can be tested
without one — 40 checks on room identity, the topic contract and which
payloads become notifications. Separately verified against a real
mosquitto: connect, subscribe, retained status, per-room and all-room
delivery, urgency, duplicate and expired and malformed messages ignored,
the broker killed with the daemon surviving, reconnect, and a stale
retained notification left on the broker not reaching the screen when a
room boots.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-06 14:41:49 -05:00
ekklesiaandClaude Opus 5 ffd18edf7e fix: deliver test notifications into the classroom session
The classroom desktop belongs to the classroom user and mako sits on
that user's D-Bus session. An administrator over SSH is in a different
session where nothing owns org.freedesktop.Notifications, so notify-send
asked D-Bus to start a second mako, which had no display to open and
timed out with NoReply.

Find the running sway process for the classroom user and deliver into
its session instead. XDG_RUNTIME_DIR and the bus address are read from
that process, falling back to /run/user/<uid> and its bus socket when
the environment cannot be read — root has ptrace access on the endpoint,
but that is not somewhere to be brittle. The Wayland display is read the
same way, and failing that from the wayland-N.lock sway holds open, so
no socket name is ever assumed. notify-send only needs the bus, so a
display that cannot be resolved is not worth refusing to send over.

Refuses to send when mako is not already running, rather than letting
D-Bus start one, and says plainly what is wrong when there is no
session, no privileges, or no bus socket. --dry-run reports what it
resolved without sending.

Behaviour inside the session is unchanged, and the sample notifications
and styling are untouched.

The tests stand a real background process in for sway so /proc/<pid>/environ
is genuine rather than mocked, and cover both invocation paths plus the
fallbacks and every refusal. The build runs them.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-04 17:38:44 -05:00
ekklesiaandClaude Opus 5 6b133bdc3e feat: settle Chrome and notifications into the classroom look
Chrome stays a full browser. The managed policy only removes the things
a volunteer should never be asked about — the first-run tour, the
default-browser prompt, sync and sign-in promos, the profile picker —
and pins the Home button to Wonder Ink so there is always one obvious
way back. Startup URL is a recommended policy rather than a managed one,
so a teacher can still change it. Nothing restricts where they browse,
and the profile is untouched, so YouTube and other logins survive
reboots and updates.

Notifications were still stock mako, which looked nothing like the rest
of the shell. Give them the dock's palette: the same dark slate, the
same hairline white border, rounded, white text, top right. Kept a
little more opaque than the dock so text stays readable over video, and
on the overlay layer so a parent-call alert can still reach someone
watching a fullscreen DVD.

mako was only ever reaching the session through D-Bus activation. Start
it from the sway config so it is running before anything needs it.

classroom-notify-test sends a sample so the styling can be checked
without waiting for a real event.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-04 17:07:05 -05:00