Event → alert/notification pipeline · 2 service bundles · 2 companies · run 2026-10-04 · branch feat/event-outbox-e4 on mapp.doriai.com
PASS Event delivered end-to-end from the (mock) MLC to the correct per-company MQTT contact point, for both companies. Email channel blocked by missing Gmail credentials (see caveats).
| Concept | Model |
|---|---|
| Contact points | Root / system level (Dori company) — one shared pool; platform-admin managed; visible to every company. |
| Notification routes | Per company — each route wires an event → a root contact point. |
| Events for routing | Scoped to the company's service bundles (what its cameras run). |
| Notify gate | Trigger fires pg_notify when is_notification OR an active route matches (no is_message/is_trigger). |
| MLC | edge_simulator (mock MLC) — POST /sim/inject/inference. |
| Company | Service bundle → events (notify) | Routes (event → contact point) |
|---|---|---|
| Acme Warehousing (co 2) | Warehouse Vision: Pallet Jam ✓, Forklift NearMiss ✓, Pallet Clear ✗ | Pallet Jam → Ops MQTT C2 dori/2/alerts + Ops Email C2; Forklift NearMiss → Ops MQTT C2 |
| RetailCo Stores (co 3) | Retail Vision: Shelf Empty ✓, Queue Overflow ✓, Shelf Restocked ✗ | Shelf Empty → Ops MQTT C3 dori/3/alerts + Ops Email C3; Queue Overflow → Ops MQTT C3 |
Contact points are root-level (shared pool of 5): Ops MQTT, Ops MQTT C2/C3, Ops Email C2/C3. Each company also has credentials, an MLC + config, a user (entity), a location and a camera (device).
| # | Check | Result |
|---|---|---|
| 1 | Root contact points visible to any company (global pool) | PASS — 5 root contact points listed |
| 2 | Events scoped to each company's bundles | PASS — co2 = Warehouse events, co3 = Retail events |
| 3 | Routes are per company; new route references a root contact point | PASS |
| 4 | Inject Pallet Jam (Acme) → inference_event written, company resolved via job→device | PASS |
| 5 | CIM dispatch via routes | PASS — dispatched-via-routes |
| 6 | MQTT alert delivered to the correct per-company topic | PASS |
| 7 | Email alert delivered | BLOCKED — Gmail creds missing on host |
MQTT messages captured on the broker (the payoff):
dori/2/alerts Pallet Jam on 1: ← Acme (Warehouse Vision) dori/3/alerts Shelf Empty on 2: ← RetailCo (Retail Vision)
CIM dispatch log:
event_process type=Pallet Jam company=2 -> dispatched-via-routes (1 recipients) event_process type=Shelf Empty company=3 -> dispatched-via-routes (1 recipients)
send_gmail needs /app/config/client_secret.json (Gmail OAuth) or a test webhook (EMAIL_TEST_WEBHOOK). Not present on the box, so email routes error. The route resolution and recipient selection (incl. address resolved from the assigned user entity) work; only the actual send is blocked.docker-compose.yml predates the test services, so the broker ran as a standalone mosquitto container on the app network. It is not in compose and won't survive a stack restart — add mosquitto to the deployed compose for persistent MQTT.EVENT_METHOD=mqtt (default kafka), so route-based MQTT alerts never reached the broker. CIM now connects the MQTT publisher unconditionally.Related: event pipeline design · Notifications Console · DB data model · ICD data model