---
module: aria.precursor-alerts
title: Precursor Alerts
tab: Claude
order: 40
audience: dev
---

Terse agent reference. Owned by **hiveops-aria** (port 8095, DB `hiveiq_aria`). All facts below confirmed in code.

## Ownership
- Service: `hiveops-aria` — sole owner of detection + storage + API for this feature.
- Frontend: `hiveops-aria/frontend/src/components/PrecursorAlerts.svelte`, view id `sequences`.

## Endpoints (all `@PreAuthorize("hasRole('BCOS_ADMIN')")`)
| METHOD | Path | Notes |
|--------|------|-------|
| GET | `/api/aria/sequences` | params: `resolved` (bool), `sequenceType` (JACKPOTTING\|SKIMMING\|UNKNOWN), `deviceAgentId`, `page` (0), `size` (25); Page<> sorted `triggeredAt` desc |
| GET | `/api/aria/sequences/{id}/events` | `{id}` = alert Long id; returns `List<ThreatEvent>` by `sequence_id`; 404 if alert missing |
| POST | `/api/aria/sequences/{id}/resolve` | idempotent; sets `resolved_at`+`resolved_by`(JWT email); no un-resolve endpoint |
| POST | `/api/aria/ingest/events` | upstream source; `permitAll`, gated by header `X-Service-Secret` vs `ARIA_SERVICE_SECRET` (open if blank) |

## Tables (`hiveiq_aria`)
- `precursor_sequence_alert` — the alert record.
- `threat_event` — source signals; `sequence_id` links events to an alert.

## Kafka (produced only; NO consumers in aria)
- `hiveops.aria.sequences` — one per raised alert, key=`deviceAgentId`, payload `AriaSequenceEvent` (JSON).
- `hiveops.aria.threats` — per HIGH/CRITICAL ingested event, key=`deviceAgentId`.

## Roles
- BCOS_ADMIN **only** for all sequence endpoints. NOT `hasAnyRole('MSP_ADMIN','BCOS_ADMIN')`. MSP_ADMIN → 403.

## Detection facts
- Window `ARIA_SEQUENCE_WINDOW_MINUTES` default 15.
- Needs ≥2 device events in window AND `PHYSICAL_ACCESS` phase, else no alert.
- JACKPOTTING = has `MALWARE_STAGING` or `MALWARE_EXECUTION`. SKIMMING = signal `CARD_READER_TAMPER` or `USB_INSERTION`.
- One active (unresolved) alert per device — dedup guard blocks new alerts until resolved.

## Gotchas
- `deviceAgentId` filter overrides `resolved`+`sequenceType` (returns all statuses for that device).
- `AriaSequenceEvent.alertId` = random UUID, NOT the DB alert id; use `sequenceId`/`deviceAgentId` to correlate.
- Alerts are auto-generated on ingestion; no manual create endpoint.
- `resolved_by` = `"unknown"` if JWT principal email absent.
- Auto-refresh is client-side 60s poll (`localStorage aria_alerts_autoRefresh`); does not affect backend.

## Do NOT
- Do NOT call these with an MSP_ADMIN token expecting data (403).
- Do NOT expect a re-open/un-resolve endpoint — none exists.
- Do NOT assume alerts appear without a `PHYSICAL_ACCESS` phase and ≥2 correlated events.
- Do NOT look for these tables/topics in incident/journal/devices — everything is in `hiveops-aria` / `hiveiq_aria`.
- Do NOT treat `AriaSequenceEvent.alertId` as a foreign key to `precursor_sequence_alert`.
- Do NOT invent an admin "force alert" or "auto-response" action from this screen (auto-response shutdown is off by default).
