Commit Graph
13 Commits
Author SHA1 Message Date
Media 7e6b916963 feat: add isolated utility export modes 2026-08-12 18:48:03 -05:00
Media b934b69e5a feat: persist isolated utility export jobs 2026-08-12 18:21:29 -05:00
Media 8db46df69e fix: enforce Player download height limit 2026-08-12 18:18:38 -05:00
Media c2544c44c7 fix: close Audio Router self-echo PUBACK/subscription-delivery race
publish_router_mode registered its self-echo correlation marker before
publishing but removed it in a finally block the instant the QoS 1 publish()
call observed its PUBACK. A broker may legally deliver a Controller's own
subscription copy of that same publish after the PUBACK, since MQTT does not
order the two; when that happened, the Controller mistook its own late echo
for live operator intent and relinquished automatic restoration ownership.

Keep the marker claimable for a short, bounded mqtt.router_echo_grace_seconds
window (default 2s) after the PUBACK instead of clearing it immediately.
Genuine external/operator commands are unaffected: once the grace window
elapses, a matching payload is still correctly treated as operator intent
and ownership is relinquished as before.

Verified with deterministic fake-clock unit tests plus a real Mosquitto
broker integration test (tests/test_router_echo_mosquitto_integration.py,
skipped automatically when Docker is unavailable).
2026-08-07 17:13:54 -05:00
Media 270ede8b77 fix: allow genuinely new playlist ingest without fresh Player evidence
The evidence gate on enqueue_download blocked every download, including a
URL that could only land in a slot store.reserve_download already proves is
empty and unguarded. After a Controller-only restart with the Player still
connected and idle, no fresh detailed status ever arrives, so this could
deadlock all new ingest indefinitely even though nothing unsafe would occur.

Narrow the gate to only require fresh evidence when the URL already occupies
a non-empty slot (refresh/reuse). Deletion, expiry, and cleanup/recovery
gating are unchanged.
2026-08-07 17:01:39 -05:00
Media 5e81403be3 feat: overhaul video player controller 2026-08-06 20:08:12 -05:00
Media 72cc66df92 fix: pass mqtt credentials through compose 2026-08-06 19:30:22 -05:00
Media 63ea314b18 build: harden controller v2 runtime 2026-08-06 19:23:02 -05:00
Media 3ee7f94d72 feat: coordinate authoritative playback and audio routing 2026-08-06 18:52:01 -05:00
Media 8b3bdae8a0 feat: reduce authoritative player mqtt state 2026-08-06 17:41:07 -05:00
Media 45083207b4 feat: reserve downloads and protect slot cleanup 2026-08-06 17:34:11 -05:00
Media 3ff9ba4637 feat: add atomic state store and legacy migration 2026-08-06 17:31:02 -05:00
Media 9091f27283 test: characterize contracts and make startup explicit 2026-08-06 17:24:20 -05:00