diff --git a/decisions/0003-mqtt-como-espina-dorsal.md b/decisions/0003-mqtt-como-espina-dorsal.md new file mode 100644 index 0000000..af38ace --- /dev/null +++ b/decisions/0003-mqtt-como-espina-dorsal.md @@ -0,0 +1,51 @@ +# ADR-0003 · MQTT as the spine of the system + +**Status**: accepted +**Date**: 2026-05 + +## Context + +The platform has many independent processes that need to communicate: cameras → Frigate → enrichers → forensic engine → console → hub. Options considered: + +- **REST APIs everywhere**: tight coupling, polling overhead, hard to add subscribers. +- **gRPC streams**: better but still point-to-point, no topic-based filtering. +- **Kafka**: too heavy for edge devices, requires Zookeeper or KRaft, persistent disk-heavy. +- **NATS**: lightweight but newer, less ecosystem maturity. +- **MQTT**: mature, lightweight, broker available everywhere (Mosquitto), topic-based, retain messages, QoS levels, well-known TLS bridge mechanics. + +## Decision + +MQTT is the **spine** of the system. Mosquitto runs on the router as the local broker. Bridges to the hub are configured selectively, with topic remapping. Components communicate via MQTT topics with a documented contract (see `docs/01-architecture/mqtt-contract.md`). + +Key topics: + +``` +hai//events/ # detection events +hai//state/ # retained state (online, fps) +hai//snapshots/ # frame snapshots — NEVER bridged +hai//telemetry/ # raw telemetry — NEVER bridged +hai/_registry/announce # service discovery +hai/_registry/heartbeat/ # liveness +hai/healthd/health # selftest reports +hai/_bridge/status # bridge health (retained) +_cmd/ # commands incoming from hub +``` + +**Sovereignty principle**: snapshots and raw telemetry **never** bridge. Aggregated health does. Events do (with site prefix). The `bridge.conf` policy is in GitOps and visible in the UI. + +## Consequences + +**Good**: +- Adding a new subscriber is free (no config changes upstream). +- Selective bridging gives operational sovereignty as a programmable property. +- `mosquitto_sub` is a superb debugging tool always available. +- Retained messages handle late-joining subscribers correctly. + +**Bad / trade-offs**: +- MQTT 5 has features we want (response topics, message expiry) but Mosquitto's MQTT5 support is partial — we stay on MQTT 3.1.1 for compatibility. +- No native request-response semantics — we use `req-id` correlation in payloads where needed. +- Encryption at rest of the broker DB is not transparent — addressed via LUKS at the OS layer. + +## Alternatives considered + +See above. **Kafka** was the strongest alternative; rejected primarily for edge-device cost and operational complexity.