merge: display-management (Stages 0-5 §6A + keep-alive hardening + gaming-rig)

Merges display-mgmt-stage0 — the user-configurable virtual-display policy layer above the
per-compositor backends. On-glass validated (KWin .116 + Mutter .21; Windows compile-verified .173):

- Policy surface (keep_alive · topology · conflict · identity · layout · max) →
  display-settings.json, console-editable via /api/v1/display/{settings,state,release,layout} + a
  dedicated "Virtual displays" console section. All five axes enforced, not just stored.
- Lifecycle: pure state machine + Linux keep-alive pool (registry + DisplayLease ownership split),
  incl. keep_alive=forever/Pinned (freed via /display/release); topology extend/primary/exclusive
  (group-aware); per-client identity (KWin per-slot names → KDE scaling round-trips); mode_conflict
  admission (Windows default reject, single-capturer IDD); §6A multi-monitor (display groups +
  layout engine + console arrangement table — several clients as monitors of one desktop).
- Keep-alive reconnect hardened: same-client zombie preempt (never a 2nd display), deliberate-quit
  skip-linger (QUIT_CLOSE_CODE), tunable idle timeout (PUNKTFUNK_IDLE_TIMEOUT_MS).

Conflicts (packaging/{arch,debian}/README.md firewall docs): kept main's ufw/nft port commands +
the branch's --data-port documentation. build + clippy -D warnings + cargo test --workspace
(18 suites, 0 failed) green on the merged tree.
This commit is contained in:
2026-07-05 18:22:17 +00:00
42 changed files with 6256 additions and 483 deletions
+8 -3
View File
@@ -374,9 +374,14 @@ sudo firewall-cmd --reload
default unit):
- **QUIC control plane: UDP 9777** (default `--port`; change with `--port N`).
- **Data plane: an *ephemeral* UDP port** — `punktfunk1-host` binds `0.0.0.0:0` and tells the client which
port it got, so there is **no fixed data port to open**. For a restrictive firewall you'd need to
allow the ephemeral UDP range; the repo does not pin one.
- **Data plane: a separate UDP port** — by default *random* (`0.0.0.0:0`), so there is **no fixed
port to open**. Video flows host → client, but the client sends the first packet (a hole-punch): if
firewalld drops it, the host waits ~2.5 s and falls back to the client-reported address and streams
anyway, so you normally **leave the data port closed**. To skip that ~2.5 s fallback, pin it with
`serve --data-port <PORT>` (or `PUNKTFUNK_DATA_PORT`) and open exactly that one port with
`firewall-cmd --add-port=<PORT>/udp`. A fixed port serves one session at a time (concurrent ones
fall back to random + hole-punch) and streams to the client's reported address (flat LAN /
non-remapping forward only).
```sh
# Only if you run `punktfunk1-host`: