Commit Graph
3 Commits
Author SHA1 Message Date
ducoterra d43eb407f8 phase: 03_audio_share
Build and Push Containers / test (push) Successful in 35s
Build and Push Containers / build-and-push-app (push) Successful in 11s
**Phase 03 final verification pass — complete, 100% green.**

- Verified all 4 tasks done in `complete/03_audio_share/`; confirmed implementation in `watch.js` (one composed `MediaStream` per tile, staged-only `setMuted()` policy, `data-audio` state), `share.js` (precise `NotAllowedError` rethrow, 3 honest `#stat-audio` states, mid-share audio republish), conftest flags, and the new `tests/e2e/test_audio_share.py` (11 tests, all **passed** — none skipped).
- **Criteria:** (1) viewer inbound audio `bytesReceived` strictly increases + composed stream 1 video/1 audio track while frames still decode — **passed**; (2) staged-only audio via keyboard `m`, mouse button, and `unstage()` re-mute — **passed**; (3) `shared`/`silent`/`not offered` + mid-share audio loss updates panel, roster and tiles — **passed**; (4) cancelled picker reports cancellation, single attempt — **passed**; (5) SECURITY.md §4 Audio, README platform notes, kiosk doc all describe shipped behaviour incl. Linux/PipeWire reality — **verified**; (6) full gate — **passed** (below).
- **Gates:** `uv run ruff check . && uv run ruff format --check .` → clean; `uv run pyright` → 0 errors; `uv run pytest` → 245 passed, 4 skipped (only the `MIRROR_REALDISPLAY`-gated X11 tests); `MIRROR_REALDISPLAY=1 uv run pytest -m realdisplay` → 3 passed, 1 skipped (real-capture audio: documented skip naming the exact host/flag reason, per task 04).
- **Docs:** README.md reviewed in full against code (env table, CLI flags, routes, kiosk key table, quickstart, audio notes) — consistent, no changes needed. AGENTS.md — all commands/paths/coverage claims verified accurate, no stale statements, no changes needed.
- **Defect fixed (pre-existing):** `docs/kiosk-silverblue.md` + `install-kiosk.sh`, `kiosk.conf`, `gnome-kiosk-script` used `mirror.reeselink.com` while README/SECURITY.md use `mirror.reeseapps.com` (the deployment domain, consistent with the fleet); corrected 7 occurrences in 4 files.
- No live-infrastructure changes; realdisplay suite ran on private Xvfb only.
- **Next pending phase:** `04_reachable_share_cta`.
2026-11-01 22:40:30 -05:00
ducoterra 2e79430ac7 docs: what actually gates access, now that there is a deployment
Build and Push Containers / test (push) Failing after 8s
Build and Push Containers / build-and-push-app (push) Skipped
The internal deployment exists (deployments repo, `mirror/`: quadlet, nginx
edge, certbot, route53, VM SOP), so the docs that said "the real fix is HTTPS"
were describing a future that has arrived from a different direction — TLS
terminates in nginx on the service VM, not in this process, and there is no
`--https` flag here.

SECURITY.md's trust model said "trusted: anyone who can open a TCP connection".
With an allow list in production that sentence was simply no longer true, so the
table now names the address space, and a new section says what the list is and
what it is not: one wall (network/nginx) and one belt (the app, for the path
that bypasses nginx at 127.0.0.1:8080), plus the thing neither can do — once two
browsers are in the room their media never asks the server again, and it can
never tell you *who*, only *where from*. Saying "defence in depth" about that
would have been the dishonest version.

PLAN.md gains A19 (TLS + admission in production, LOCKED) and A18 becomes
deprioritised rather than deleted — standalone `mirror serve --https` is still
worth having for offline/ad-hoc use, it just stopped being the thing blocking
cross-device sharing, and candidate phase 1 is now share-page resilience.
AGENTS.md gains the two rules most likely to be broken by a well-meaning edit:
trust XFF only from a trusted proxy, and change the nginx and app lists in the
same commit.

LLM-Generated: true
2026-11-01 17:47:31 -05:00
ducoterra 896cca2f23 docs: plan, agent operating rules, and an honest security model
PLAN.md locks the architectural decisions (WebRTC mesh with the sharer as
sole offerer, JSON-only signaling, in-memory roster with no database, no
auth, no CDN, Linux as the reference platform) and records the roster rules,
the verification ladder, and the constraints that are accepted rather than
hidden: the secure-context requirement, mesh upload scaling with watcher
count, and the Wayland portal's per-share prompt.

Phases are deliberately not written yet -- the prototype and its tests came
first, so .agents/phases/todo/ holds only a README pointing at the candidate
phase list in PLAN.md section 7.

SECURITY.md answers the question a no-auth tool has to answer: not "who is
allowed in" but "where is this allowed to run". It separates what an
unauthenticated LAN visitor can do from the guarantees that are enforced and
named to a test, and tells users the two things they will actually hit --
that http://<lan-ip> hides getDisplayMedia, and that on Wayland the
compositor asks every time and mirror must not work around it.

LLM-Generated: true
2026-11-01 16:54:28 -05:00