Closes #1. The Flask event-timeline was dead: `broadcast_sse_event` existed in `vigilar/web/blueprints/events.py` but had zero call sites. Clients subscribed to `/events/stream`, received the initial "connected" message, and then only keepalives — a page refresh was required to see new events. (Web Push via VAPID was independent and already worked.) The root cause was a process-boundary gap: the events subsystem runs in its own OS process and emits to MQTT, while the Flask app runs in a separate process with no MQTT client of its own. This change adds a thin bridge: - EventProcessor._handle_event now publishes a classified summary (id, ts, type, severity, source_id, payload) to a new topic `Topics.EVENTS_PUBLISHED = "vigilar/events/published"` right after `insert_event()`. Classification logic stays in one place. - A new module `vigilar/web/sse_bridge.py` provides `forward_event` (MQTT handler) and `start_sse_bridge(cfg)` (creates a MessageBus, subscribes forward_event to EVENTS_PUBLISHED, connects, returns the bus). - `vigilar/main.py:_run_web` starts the bridge after `create_app(cfg)` and disconnects it on shutdown. Bridge failure is logged but does not kill the web process — the UI still works without live updates. - `create_app` is deliberately NOT changed. Keeping the bridge out of the app factory means no existing test triggers a real MQTT connection, and the bridge stays a production-only concern wired by the supervisor. Tests (all added with TDD, RED verified before GREEN): - tests/unit/test_events.py::TestEventsPublishedBroadcast — asserts `_handle_event` publishes the classified payload for a motion event and does NOT publish for unclassified topics (heartbeats). - tests/unit/test_sse_bridge.py — asserts `forward_event` reaches SSE subscribers, and `start_sse_bridge` wires the handler to `Topics.EVENTS_PUBLISHED` on a connected bus (fake bus, no real MQTT in tests). Also refreshes the docs that previously flagged the dead SSE as a known limitation (operator guide, web architecture doc). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2.1 KiB
2.1 KiB