phase: 09_wall_remote_page
**Phase 09 — final verification pass (all 3 tasks already in `complete/`; phase work was in the working tree, verified, nothing needed fixing)**
**Gates** — `uv run ruff check . && uv run ruff format --check .` → clean; `uv run pyright` → 0 errors; `uv run pytest` → **360 passed, 5 skipped** (only the realdisplay rung), coverage 96% total / 95% app.py; `MIRROR_REALDISPLAY=1 uv run pytest -m realdisplay` → 4 passed, 1 skipped (documented host limitation: no audio source on the real X11 path); `uv run pytest tests/e2e/test_remote_control.py` → 8/8 passed; `node --check` on every `static/*.js` → all pass.
**Completion criteria** — all met: (1) "Show on wall" stages on the display, asserted on display DOM + `/api/kiosk` ✓; (2) Back/Fullscreen + untouched second controller converge (TestConvergence) ✓; (3) `/api/streams` reports `viewers: 0` / `watching: 0` with only `/remote` open (TestACostsNothing) ✓; (4) followers count displays only — 0/1/1 with a second controller (TestFollowers) ✓; (5) controller works with no display: `followers: 0`, state stored (protocol test + e2e) ✓; (6) e2e + full `-m e2e` + realdisplay all green ✓; (7) README + SECURITY.md updated, Silverblue default now `/kiosk` (installer, conf, gnome script, checker) ✓; (8) suite 100% green, coverage >90% on new code ✓; (9) PLAN.md untouched; AGENTS.md changed only for a stale statement ✓.
**Documentation** — README.md reviewed in full against code (page table, quickstart, env-var table vs `config.py`/`debug.py`, presets, keys, deployment, kiosk section): no inconsistencies found. AGENTS.md: fixed the one stale statement introduced by this phase ("Four pages" → "Five pages"); no other staleness, nothing added.
**Decisions** — no repo changes were required; the one realdisplay skip is a pre-documented environment fact, not a failure.
**Next pending phase** — none; `todo/` held only phase 09.
This commit is contained in:
@@ -10,6 +10,7 @@ your network:
|
||||
| **Share** | `/mirror` (also `/share`) | Picks a window, screen, or tab via the OS-native picker and mirrors it. |
|
||||
| **Watch** | `/watch` | Shows every screen currently being mirrored; click a tile to take the stage. |
|
||||
| **Kiosk** | `/kiosk` | A chrome-free wall for an unattended display: no header, no counts — the net pill is the only chrome, and the shared layout state (below) arranges it. |
|
||||
| **Remote** | `/remote` | A controller for the shared wall, from a laptop or a phone: lists the live mirrors and the wall's state and sends the decisions (show this, back to the wall, full screen) — no video, no bandwidth. |
|
||||
| **Index** | `/` | Signpost + live count of mirrors. |
|
||||
|
||||
Any number of people can mirror at the same time and any number of people can
|
||||
@@ -32,6 +33,7 @@ Then, from another machine on the LAN:
|
||||
http://<this-machine>:8055/mirror # to share
|
||||
http://<this-machine>:8055/watch # to watch
|
||||
http://<this-machine>:8055/kiosk # the unattended wall (kiosk display)
|
||||
http://<this-machine>:8055/remote # drive the wall from this device
|
||||
```
|
||||
|
||||
Linux is the primary target. On Linux the native picker is X11/Wayland's own
|
||||
@@ -78,6 +80,20 @@ same `arrange` intent, so a controller and a display converge on one state
|
||||
(`m` is local-only: a display never becomes audible because another machine
|
||||
asked).
|
||||
|
||||
### Driving an unattended wall
|
||||
|
||||
The shared state exists for a box with no keyboard: point the box at `/kiosk`,
|
||||
open `/remote` on a phone, and press **Show on wall** — the box stages that
|
||||
mirror, and **Back to the wall** and **Full screen** do the same for their
|
||||
decisions. When a keyboard is plugged into the box, the wall keys still work
|
||||
there, and a keypress performs the change *and* publishes the same `arrange`
|
||||
intent, so a key on the box is seen by every controller — a controller and a
|
||||
display converge on one state. Fullscreen is **requested, not promised**: a
|
||||
remote command carries no user activation, so the browser may refuse the
|
||||
request; the in-page stage fills the viewport anyway (and the kiosk box's
|
||||
window manager forces the window fullscreen). The state lives in the server's
|
||||
memory only: a restart returns the wall to a wall.
|
||||
|
||||
## Configuration
|
||||
|
||||
Environment variables (all optional; a `.env` file is loaded if present):
|
||||
@@ -180,9 +196,9 @@ from this side:
|
||||
A wall display is a Fedora Silverblue box running the locked-down GNOME Kiosk
|
||||
session, auto-logged in as `kiosk`, with Firefox in `--kiosk` mode pointed at
|
||||
the wall. It is set up and repaired entirely over SSH — no keyboard, no console,
|
||||
no monitor. The display page is `/kiosk`; the installer default still opens
|
||||
`/watch` and an existing `kiosk.conf` URL wins, so moving a box is the
|
||||
one-line re-point in [the runbook](docs/kiosk-silverblue.md#two-endpoints-watch-and-kiosk). A brand-new box layers the kiosk packages once first
|
||||
no monitor. The display page is `/kiosk`, and it is the installer default
|
||||
too; an existing `kiosk.conf` URL wins over the default, so moving a box is
|
||||
the one-line re-point in [the runbook](docs/kiosk-silverblue.md#two-endpoints-watch-and-kiosk). A brand-new box layers the kiosk packages once first
|
||||
(`rpm-ostree install gnome-kiosk gnome-kiosk-script-session`, then a reboot);
|
||||
after that these two commands are both the setup and the repair path:
|
||||
|
||||
|
||||
Reference in New Issue
Block a user