Type: explanation · Last reviewed: 2026-07-18
An alarm that opens in the background is useless if nobody sees it. Pulse Historian's notifications engine is the delivery layer that turns an event — an alarm opening, and (in future) a process crashing, a license expiring, or a backup failing — into something a person actually notices: a desktop toast, an in-app banner, a bell-badge count, a live browser feed, and optionally an email. This page explains how a notification reaches the right person; for the rules that raise alarms in the first place, see How monitoring & alarms work.
Applies to: whole platform · today the monitor is the only producer wired to send notifications.
A notification is persisted first, delivered second. That ordering matters: because every notification is stored, a user who was offline when it fired still sees it — the browser feed replays everything they missed the moment they reconnect, and the desktop bell shows an unread count that survives a restart. Live delivery is best-effort on top of a durable record, not the record itself.
| Channel | What it is | Who sees it |
|---|---|---|
| Desktop OS toast | A native operating-system notification fired by the Tauri app | Whoever is at the machine running the app |
| In-app banner | A toast rendered inside the app's webview | The logged-in desktop user |
| Bell badge | The unread-count number on the navbar bell | Every session of the recipient |
| Browser SSE feed | A live Server-Sent Events stream that pushes new notifications to open browser tabs and replays anything missed | LAN browser sessions of the recipient |
| An optional outbound email, sent through the Mail/SMTP service, when a notification carries an email address | The addressed recipient |
Email is not a live channel like the others — it is handled separately by the mail service and store-and-forward queue, so a notification is never held up waiting for an SMTP server.
Under the hood → Notifications Engine § Transports.
Notifications are not broadcast to everyone. Each one is either addressed to one user (by email) or scoped to a slice of the hierarchy — an organization, a site, or a unit. The engine then shows a notification to a person only when it is theirs:
An admin sees everything. This reuses the same hierarchy grants (orgs_id / sites_id / units_id) carried in the login token that gate metadata access — so notification visibility lines up with what a user is already allowed to see.
Today's caveat: alarm notifications from the monitor tag only the unit they came from (not the site or org), so their visibility currently rides on unit-scope grants or the admin role. Under the hood → Notifications Engine § Monitor feed.
Every notification carries a severity — info, warn, error, or critical — that the UI uses to style it and (in future) choose a toast sound. It also has a read state: unread notifications drive the bell badge; marking one read is idempotent and only ever affects your own view of it.
Notifications don't pile up forever. A retention sweep purges read notifications older than a configurable age (default 30 days). Unread notifications are always kept, so a returning operator still sees their backlog rather than a silently-emptied bell.
Using the canonical dataset (acme-power / plant-1 / boiler-2 / default_grid):
idfan_vibration for boiler-2 crosses its > threshold (see monitoring). The monitor opens an AlarmEvent.error-severity notification (a >-comparison alarm is treated as "danger"), tagged with units_id = boiler-2, linking to /alarms/{id}.alarm event · monitor rule · scope · RBAC