The dashboard showed "No Cameras Connected" despite the API returning the
camera:
- middleware.Timeout + http.Server.WriteTimeout (10s) cancelled the
long-lived /api/v1/events/stream every 10s, before any 30s status event
could arrive — so the SSE-fed store never populated. Drop the global
request timeout and set WriteTimeout=0 (closed-LAN kiosk).
- The SPA never seeded from GET /api/v1/cameras (SSE only pushes on change).
Fetch the list once on mount and setCameras().
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Implements MQTT subscriber (internal/mqtt/subscriber.go) that:
- Connects to Mosquitto broker with auto-reconnect
- Subscribes to remoterig/cameras/+/status, +/heartbeat, +/announce
- Parses and validates incoming messages per MQTT contract
- Inserts status_logs with duplicate prevention
- Auto-detects recording state changes and manages recording_events
- Broadcasts camera status changes via SSE hub
- Camera auto-registration via announce (MAC-based, sequential cam-NNN)
- Heartbeat watchdog marks cameras offline after 120s silence
- Wired into main.go with graceful degradation (warns if broker unreachable)
Dependency: github.com/eclipse/paho.mqtt.golang v1.5.0
Closes CUB-232.