16 Commits

Author SHA1 Message Date
adlee-was-taken
09b59e3bb5 feat: wire MQTT → SSE bridge so the event timeline updates live
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>
2026-04-05 16:55:27 +00:00
adlee-was-taken
1633e8b34e docs: final verification pass fixes
Convert the "Where to go next" items in the architecture overview from
plain text to proper Markdown links. This was the only finding from the
Task 18 verification pass; everything else (links, commands, TOML
coverage, subsystem coverage, terminology) is self-consistent across
the 17 new doc files.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 10:26:02 -04:00
adlee-was-taken
5e0d6c8320 docs: add web subsystem reference 2026-04-05 09:50:27 -04:00
adlee-was-taken
c4d119310a docs: add health subsystem reference 2026-04-05 09:48:54 -04:00
adlee-was-taken
07f5f341e6 docs: add pets subsystem reference 2026-04-05 09:48:12 -04:00
adlee-was-taken
58622722c7 docs: add presence subsystem reference 2026-04-05 09:47:35 -04:00
adlee-was-taken
843daf9c0b docs: add highlights subsystem reference 2026-04-05 09:47:07 -04:00
adlee-was-taken
d3db384c35 docs: add storage subsystem reference 2026-04-05 09:46:39 -04:00
adlee-was-taken
62696e919c docs: add ups subsystem reference 2026-04-05 09:46:06 -04:00
adlee-was-taken
87d2df1446 docs: add sensors subsystem reference 2026-04-05 09:45:41 -04:00
adlee-was-taken
c1779dfdb8 docs: add alerts subsystem reference 2026-04-05 09:45:12 -04:00
adlee-was-taken
226a473d4d docs: add events subsystem reference 2026-04-05 09:44:41 -04:00
adlee-was-taken
67b8dd672c docs: add detection subsystem reference 2026-04-05 09:44:06 -04:00
adlee-was-taken
c8d8421112 docs: add camera subsystem reference 2026-04-05 09:42:29 -04:00
adlee-was-taken
484235f74c docs: add coding conventions reference 2026-04-05 09:39:47 -04:00
adlee-was-taken
d38b0c4e25 docs: add architecture overview
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 09:36:37 -04:00