Skip to content

Incidents

An incident is a device, a time window, a set of model results, and the evidence behind them. It is not a notification and not a verdict.

Field Meaning
Title Short, generated from the models that fired
Severity info, low, medium, high, critical
Score 0–100, with its history over time
Status open, investigating, resolved, false_positive
Devices The devices involved
Models Which detection models produced it
Evidence The source records, in order
Workflow history Every status change, with actor, comment and sequence
Revision Incremented on every write

Each model result links to the specific persisted analysis result that produced it, with its own reason and evidence identifiers. You can always get from “this incident exists” to “because this model saw these records at this time”. Since 0.38 the reason of a beaconing or scan result is the detector’s full measurement — interval_cv=0.0312,period_seconds=60.00,…,destination=… or unique_ports=60,window_seconds=60,hosts=3,destination=… — and a policy= token at its end says when a role, a shared destination or the learned baseline withdrew the verdict; the models page has the grammar.

An incident is one per device, model and pattern, and it grows rather than multiplies: a series that keeps beaconing updates its incident, and since 0.38 a scan is keyed by the destination’s /24 (IPv6 /64), so a device sweeping a subnet is one incident with more hosts and evidence every hour, not one incident per host.

Raw payloads have a retention window. Observation evidence stays resolvable for 90 days, past the payload’s own expiry, so an incident from last month is still explicable even after the underlying raw record has aged out.

If an evidence identifier cannot be resolved — its source record is unavailable, or its record kind has no public form — it is listed separately as unresolved. It is never silently relabelled as model output, because “the model said so” and “we no longer have the record” are very different statements.

Changing status requires the analyst role, takes a comment, and appends to the history. Four statuses, and the honest ones matter most:

  • investigating — someone is looking.
  • resolved — dealt with.
  • false_positive — the detection was wrong. This is the feedback that makes the models better, and it is worth spending the thirty seconds on.

A device can open at most five new incidents on one UTC day (the model file’s aggregation.max_new_incidents_per_device_per_day; see aggregation). The sixth and every later candidate of that day are folded into one overflow incident per device and day:

Identifier inc_overflow_… (stable per tenant, device and day)
Title Further findings beyond the daily cap
Summary “and N more on beyond the cap of 5 …”, followed by the folded titles with their counts (Periodic destination contact ×3, Destination port scan ×1)
Models the union of the folded models
Evidence the union of the folded evidence, so every folded candidate is still explicable

It is an ordinary detection incident on the wire and in the list: it is delivered to the sinks once when it opens, escalated only when a later fold carries a higher score, and it goes through the same workflow. The interface shows it as a normal incident, without a display of its own. Read it as a count, not as a finding: a device that fills its cap on a day is a device with a role or a threshold to look at — the learning-phase checklist says how — and the folded candidates keep updating the overflow incident rather than opening their own. Incidents that already exist are updated whatever the count; the cap only bounds what is new.

If enabled, an analyst can be asked to explain an incident. It returns a title, a narrative, hypotheses with confidence values, recommendations, and the list of evidence identifiers it was given — plus the model name and prompt version that produced it, so an odd answer is traceable rather than mysterious.

Its state is always visible: not_requested, queued, running, complete, failed, provider_disabled, budget_exhausted, or — since 0.39 — quota_exhausted, the licence’s monthly quota rather than your daily budget.

Four hard rules:

  1. Off by default. It requires an explicit provider, an explicit model name, a nonzero daily budget and explicit token rates. Nyxtrace contains no guessed prices.
  2. Metadata only. Addresses, domains, ports, times, scores. No payloads, no credentials, no whole log files.
  3. Read only. It can never approve a proposal, change a threshold, activate a model or execute an action.
  4. A disabled provider or an exhausted budget is an explicit error. There is no automatic paid fallback and no hidden retry.

Network data is treated as attacker-controlled input: host names, user agents and DNS names go into the request as data, never as instructions.

There is also a deep mode. In this version it is a workflow label that uses the same bounded request as the standard mode — it does not enable extra tools, retries or spend. It is documented that way rather than implying more.

Switching the analyst on — the variables, the budget arithmetic and the licence feature — is an operator task: see the OpenAI analyst.

A local summary of new devices and active incidents is available for a given date. It is local metadata only — retrieving it does not send a message anywhere. Sending is a sink connector’s job — the webhook delivers every new, escalated and closed incident to a receiver of your choice, and the chat sinks (Pro) post the same as a message to Telegram, Discord, Slack or Matrix.