Alarms and Incidents
FusionX · technical brief

Alarms and incidents are two different things

An alarm is a state a device is asserting. An incident is a unit of work a person owns. They are linked, and they must never be coupled — because machine state flaps, and human work must not.

Alarm — device state, owned by the field Incident — human work, owned by a person

The two lifecycles, and the four places they touch

This is the whole design in one picture. Each column is its own state machine with its own owner. The arrows between them are the only couplings that exist — and three of the four deliberately do less than you might expect.

ALARM · THE DEVICE INCIDENT · THE WORK owned by the exchange owned by an operator RAISED ACKNOWLEDGED CLEARED a human said "seen" the device stopped asserting OPEN ACKNOWLEDGED IN PROGRESS RESOLVING RESOLVED CLOSED opens one — but only if a policy says so writes a timeline note it does NOT acknowledge the incident a clear does NOT resolve the incident the detector resetting is not the operator finishing resolving asks the exchange to acknowledge it asks — the exchange decides, and never clears
The asymmetry is the point. A raise can create work. A clear cannot destroy it. The alarm side is a fact reported by equipment; the incident side is a claim about what a person did. Only a person moves the blue chain forward — with one exception, bottom left to right: resolving asks the exchange to acknowledge, because resolving is a stronger version of the same statement and making an operator say it twice is busywork.
Why a clear must not resolve. If clearing closed the incident, a detector that reset itself at 03:12 would silently close work nobody had looked at — and the record would show a resolved incident with no operator, no reason and no action. Instead the incident stays open and the timeline gains a line saying the source cleared before anyone acknowledged it. That line is the evidence that something was missed.

When does an alarm become an incident?

Four gates, in this order. Any one of them can end the journey — and when it does, the alarm carries on exactly as it always did. Nothing about alarm handling depends on this layer succeeding.

ALARM raised Layer available? schema, tables reachable Source known? alarm: · call: · camera: correlation key Already open? one open incident per source, enforced Policy matches? first by sort order, filter + priority floor yes yes no yes INCIDENT opened, severity from the policy nono yesno Degrades to nothing Malformed — not an incident Attach as a repeat Alarm only THE ALARM IS HANDLED EITHER WAY queue row · operator console · acknowledgement · rules · event history — none of it depends on an incident existing
Read the downward arrows. They are the "alarm, no incident" outcomes, and each one is a deliberate decision rather than a failure. The amber bar underneath is the guarantee that makes the whole layer safe to add: whatever happens above it, the alarm still reaches an operator.

The four gates in detail

  1. Is the layer available? Every entry point is wrapped and returns nothing on failure. A broken incident schema produces no incidents — it never produces a missing alarm.
  2. Can we say what this is about? A correlation key is built from alarm_def_id + input_id, else a station, else a camera. If none of those are present the event is malformed, and an event you cannot name the source of is not an incident. This gate was added after a test run produced twenty-seven incidents titled "ALARM" with nothing to correlate against.
  3. Is one already open for this source? A unique index enforces one open incident per correlation key. A repeat attaches to the existing incident as a timeline entry instead of creating another — which is what stops a chattering detector producing an incident per frame.
  4. Does a policy match? Policies are evaluated in sort order; the first whose event type, field filter and minimum-priority floor all match wins, and supplies the severity. No match means no incident.

Alarm only, no incident — every case

These are the situations where an alarm exists and no new incident does. Five are by design; one is a safety net.

CaseWhat happensWhy it is right
Below every priority floor
by policy
No policy matches, so no incident opens. The alarm still queues, still sounds, still acknowledges. A door-held-open or a line fault is a maintenance signal, not a unit of investigative work. Give it a queue row and a report, not an owner and an SLA.
Repeat while one is open
deduplicated
Attaches to the open incident as "Repeat activation" and marks the source active again. One event in the world is one incident. A detector cycling twelve times is still one thing happening.
No identifiable source
malformed
No correlation key, so nothing is created at all. An incident with no source cannot be correlated, shown on a map, or acted on. It is noise wearing a work item's clothes.
Policy disabled
by policy
Skipped during matching. Lets a site run alarm-only during commissioning, then switch incidents on when the procedures are agreed.
Clear or acknowledge with no open incident
no-op
Returns nothing; no incident is retro-created. An acknowledgement is not a reason to start tracking work that was never tracked.
Incident layer failed
safety net
Exception is swallowed and logged; alarm handling is untouched. The layer is beside the alarm path, never in front of it. It degrades to nothing.

And the reverse: incidents that did not come from an alarm

The correlation key supports three source kinds, so an incident can open from a call (call:<station>) or a camera detection (camera:<id>) as readily as from an alarm point. The policy table keys on event type, so the same machinery covers all three without special cases.

What your system is actually configured to do

These are the live policy rows on your server right now, in evaluation order.

OrderPolicyPriority floorSeverityState
10Life-safety only≥ 50CriticalEnabled
20Security and life-safety≥ 42HighEnabled
30Named alarm types (explicit)—HighDisabled
30All other alarmsnoneMediumEnabled
Worth a decision. The last row is a catch-all with no priority floor, and it is enabled. That means every alarm with a valid source currently becomes an incident — the "below every floor" case in the table above cannot happen on your system today. Your only alarm-without-incident outcomes right now are repeats, malformed events, and layer failure.

The section below covers how to change that. It may be exactly what you want while the incident workflow is being proven; it is not usually what you want in steady state, because it puts faults and nuisance alarms into the same owned-work queue as a fence breach, and the queue stops meaning anything.

The shape I would recommend

  1. Life safety → CRITICAL incident. Fire, medical, duress. Owned immediately, escalation on a timer. Already configured.
  2. Security → HIGH incident. Fence, intrusion, forced door. Owned, investigated, reasoned. Already configured.
  3. Faults and maintenance → alarm only. Line faults, tampers, camera-unreachable, door-held-open. Give the catch-all a priority floor so these stop opening incidents, and read them from Event History and the daily report instead.
  4. Review the boundary quarterly using your own data: any alarm type that opens incidents which are closed with no action is a candidate to demote; any alarm-only type that keeps generating phone calls is a candidate to promote.

Controlling which alarms become incidents

Three questions come up immediately, and they have different answers: one is yes and configured, one is yes but has no screen yet, and one is genuinely not built.

1. Is every alarm creating an incident right now?

Yes — on your system today, every alarm with an identifiable source becomes an incident. Not because the design says so, but because the catch-all policy All other alarms is enabled with no priority floor, so it matches everything the two narrower policies did not. Repeats still attach rather than duplicate, and malformed events still create nothing — but no alarm type is currently excluded on purpose.

2. Can the backend decide, per alarm type, incident or just an alarm?

Yes. That is exactly what incident_policy is for, and it takes two independent kinds of rule which can be combined:

ControlFieldWhat it expresses
Name the alarm types match_filter A JSON filter on the event's own fields, e.g. {"alarm_def_id": [11, 13]} — only these alarm types open incidents. A list is OR within the key; several keys are AND across them.
Set an importance floor min_priority "Anything at least this important", without naming types — so a new alarm type inherits the right behaviour the day it is created, instead of being forgotten.
Order the rules sort_order First match wins, so a narrow life-safety policy can sit in front of a broad one without ambiguity.
Turn one off enabled Disabled policies are skipped. Disabling the catch-all is the single switch that turns "everything is an incident" into "only what I named".
Set the severity severity The matched policy supplies the incident's opening severity, so importance is configuration rather than something derived in code — and an operator who has now looked at it can raise or lower it, which the timeline records by name.

An alarm that matches no policy is still a fully working alarm. It queues, sounds, shows on the wall, acknowledges at the exchange, fires rules and lands in Event History. It simply does not become a unit of owned work.

The simplest control is on the alarm type itself. Every alarm type carries a Create an incident switch on Alarms → edit type. On, it opens an incident somebody owns. Off, it is handled as an alarm only. Fire, duress and intrusion stay on; station faults and tampers come off. The type list shows the setting as Incident or Alarm only so the whole estate is readable at a glance, and the switch is checked before any policy is consulted — so the answer never depends on which policy happened to match.

It fails safe by allowing: an unreadable flag, or a project image restored from before the switch existed, opens incidents as it always did rather than silently stopping them.
Still no screen for the policy table. The per-type switch covers whether; the policies still set the opening severity and can express "anything above this priority" without naming types. Their API is live — GET/POST /api/admin/incident-policies — and the table is read on every event, so changes apply with no restart. But there is no page under Settings that edits them, so severity tuning is still done through the API or the database.

3. Can an operator turn an alarm into an incident?

Yes — from the ACTIONS menu on the alarm row. An alarm that has no incident, because its type is alarm-only, now offers Raise incident beside Acknowledge. The operator is taken straight into the incident workspace, with the alarm point's camera and its place on the map already attached.

Two properties make it safe to offer. It deduplicates against automatic creation: the incident is built with the same correlation key the engine would have used, so if a policy has already opened one for that point the operator is handed that incident rather than a second one — one event in the world stays one incident however it came to exist. And the timeline records that a person chose it, by name, because an incident that exists because someone overrode the configuration is the most interesting kind, and reading it back later must not look identical to one a policy opened.

Permission is Incident/create, granted to exactly the roles that can already take ownership of an incident: if you may own one, you may raise one. That mirroring is deliberate — it stays true for custom roles a site invents later, which a hardcoded role list would miss.

What a complete answer would look like

  1. Decide type by type which alarms are work and which are signals, using the Create an incident switch. That is now the primary control; a priority floor on the catch-all policy remains available for "anything above this level", without naming types.
  2. Switch the noisy types off on the Alarms page — station faults, tampers, camera-unreachable. One checkbox each, and the type list then reads as a summary of which alarms are work and which are signals. Built
  3. Operator escalation for the one that turns out to matter, from the alarm row's ACTIONS menu. Built
  4. Add the policy screen under Settings, editing the rows the API already serves: enable, order, filter, floor, severity. That is what is still missing, and it is where severity tuning lives.
  5. Consider the reverse too — dismissing an incident that should not have been one, recorded with a reason, which is the data you need to tune the policies at the next review.

What the operator works in

The container is only worth having if the work happens inside it. Everything below is one screen: where it is, what the camera saw, what the system did, and what has been done about it — so nobody has to hold an incident together across four tabs.

On the screenWhy it is there
A progress strip across the six states The status pill only ever showed the current one, so "how far along is this" meant knowing the order by heart. Done, current and still-to-come, at a glance.
The plan, filling its pane, centred on the alarm Letterboxing a site plan into a small pane spent most of it on background and left the marker a few pixels across, on the one panel whose job is to say where.
The camera bound to that point, already open Nobody should have to find it in a tree while an alarm is standing.
Thirty seconds before the alarm The useful question is what happened in the run-up, and the live view cannot answer it. One button replays the recorded video with the wall-clock time on the picture and a marker at the exact moment the alarm fired.
The alarm type, in words A point id says which detector. "Fire Alarm" says what you are responding to.
Severity as a control, not a label The policy's severity is a default set before anybody looked. The operator who has now looked can change it, and the timeline records who and from what.
A face against every operator action A timeline is read to find out who did what. Attribution as a grey name at the end of a sentence is the last thing the eye reaches.
What FusionX did, truthfully Requested, sent, confirmed, failed, timed out — as separate words, so an announcement that was sent but never confirmed says exactly that.
Severity is five levels and reads as five bars. INFO, LOW, MEDIUM, HIGH, CRITICAL map one to one onto the meter in the incident list, so the level is exact rather than an impression — and the word stays beside it, because bars alone never say which end is high to somebody seeing the screen for the first time.

How the rest of the industry models this

The alarm/incident split is not a FusionX invention. It is the settled pattern across PSIM platforms, alarm receiving centres and IT service management alike, and it exists because every one of those fields learned the same lesson: the volume of things that happen is far larger than the volume of things a person can own.

EVENT ALARM INCIDENT CASE anything that happened worth showing someone worth owning worth investigating rationalisation policy + deduplication investigation does it need action? does it need an owner? does it need a file? 10⁵ / day 10³ / day 10¹–10² / day a handful Orders of magnitude are indicative of a mid-size estate — the ratio is the point, not the numbers.
Each arrow is a filter with a question attached. Systems get into trouble when a stage is skipped — when every event becomes an alarm (alarm flood), or every alarm becomes an incident (a work queue nobody can triage).
FieldWhere the line sitsWhat FusionX shares with it
PSIM
Genetec, Milestone, SureView, Advancis, CNL
Alarm from a device; an operator "action plan" or procedure is the work item. Plans are per-situation, not per-device, with ordered steps and per-step audit. The event → filter → ordered steps → audit structure, and the deliberate decision not to copy branching or operator-ticked checklists.
Alarm receiving centres
EN 50518 and similar
Signal arrives; the centre logs a handling record with response times and a documented outcome. The signal and the handling are separate records by regulation. Response-time measurement from the ring, an append-only handling record, and attribution on every state change.
Process alarm management
ISA-18.2, EEMUA 191
The famous rule: if it does not require operator action, it is not an alarm. Rationalisation demotes the rest to events, targeting roughly one alarm per ten minutes per operator. Exactly the argument for putting a priority floor on the catch-all policy — the discipline is the same one level up.
IT service management
ITIL, ServiceNow, PagerDuty
Event management is separate from incident management. Monitoring raises alerts; only some become incidents, which have an owner, a state machine, an SLA and a post-incident review. The state machine with attribution, deduplication on a correlation key, and the rule that automated recovery does not close a human's ticket.

The mechanisms every mature system has

MechanismProblem it solvesIn FusionX
Correlation / dedupe keyOne real-world event producing many signalsYes — unique index on the open key, enforced under race
Chatter suppressionA flapping detector flooding the work queueYes — repeats attach as timeline entries
Policy-driven severityHardcoded importance that no site can tuneYes — ordered policy table, filters and priority floors
Acknowledge ≠ resolve"Seen" being mistaken for "handled"Yes — separate states, separately attributed
No auto-close on clearMachine recovery silently closing human workYes — explicit, with a timeline note when it happens unattended
Many alarms → one incidentA fire panel producing forty points for one firePartial — same source correlates; grouping different sources into one incident is manual
Escalation timers / SLAWork sitting unowned overnightPartial — unacknowledged counters and an unwatched-queue trigger, but no per-incident SLA clock
Procedure attached to the workOperators improvising under pressureAdjacent — rules automate the steps; there is no operator-ticked checklist by design
Post-incident reviewLearning nothing from last monthYes — append-only timeline plus the truthful action ladder
Where FusionX is deliberately stricter than most. Two places. First, the acknowledgement is authoritative at the exchange rather than set locally, so the board shows what the exchange believes rather than what the console hoped. Second, automated actions record what was asked separately from what came back — requested, sent, confirmed, failed, timed out — so an announcement that was sent but never confirmed by the amplifier says exactly that. Most systems log "action executed" and leave you to find out otherwise.