---
module: incident.journal-events
title: Journal Events
tab: Internal
order: 20
audience: internal
---

Ops/support view of the **Event Journal** screen (frontend component `JournalEvents.svelte`). It is a read-only, per-ATM event viewer served by **hiveops-incident**. There are no admin write actions in this view — the only mutation path is agent ingestion through hiveops-agent-proxy.

## Who can see it

- Read endpoints under `/api/journal-events/**` fall through to the `/api/**` rule in incident's `SecurityConfig` → `hasAnyRole('USER','CUSTOMER','ADMIN','MSP_ADMIN','QDS_ADMIN','BCOS_ADMIN')`.
- **Not admin-gated.** There is no `@PreAuthorize` on `JournalEventController` — any authenticated browser (`USER`) or JWT user can read journal events. This is intentional (it is a diagnostic view), unlike `/api/incident-management/**` which is `MSP_ADMIN`/`BCOS_ADMIN` only.
- `USER` = HiveIQ Browser session; `CUSTOMER`/`MSP_ADMIN` = customer JWT.

## What the screen actually calls

- Selecting an ATM → `GET /api/journal-events/atm/{atmId}/paginated?page=&size=&sort=eventTime,desc&hoursBack=24&eventTypes=...`
- `{atmId}` is the **numeric DB id** of the `atms` row, not the human `AT000123` agent id.
- Category checkboxes expand client-side into concrete `eventTypes` (e.g. `cardReader` → `CARD_READER_DETECTED`,`CARD_READER_FAIL`,`CARD_READER_RECOVERED`). The backend filters on the exact `eventType` strings passed.
- Default window is `hoursBack=24`; options are 1/6/24/72/168.

## First things to check when it misbehaves

1. **"No events" for an ATM you know is live** — widen Period to 168h and clear category filters first. Category filters are an allowlist of exact event-type strings; a type the agent sends that isn't in one of the 8 category groups (e.g. `ATM_IN_SERVICE`, `CASSETTE_INVENTORY`) will be hidden whenever any category is ticked.
2. **Events stop arriving entirely** — the problem is almost always upstream of this view. Ingestion is `agent → hiveops-agent-proxy (POST /api/journal-events) → incident POST /api/internal/journal-events`. Check agent-proxy logs and confirm `INTERNAL_SERVICE_SECRET` matches between agent-proxy and incident (mismatch → 401/403 on the internal call, agent-proxy returns the error upstream).
3. **Unknown event type "vanishes"** — if `eventType` isn't in incident's `event_type` lookup, the event is **not** stored in `journal_events`; it is recorded as an *event exception* and the ingest returns `202 Accepted`. So a missing event may be a not-yet-registered type, not a lost message. Check the event-exceptions/settings area.
4. **Empty screen with a red error banner** — a 401/403 from the read call means the browser session/JWT lacks one of the six roles above; a 5xx means incident-backend is down. Confirm `GET /actuator/health` on incident (port 8080).
5. **Wrong ATM's data / cross-institution** — see the scoping caveat below.

## Common failure modes + fixes

| Symptom | Likely cause | Fix |
|---|---|---|
| No new events fleet-wide | agent-proxy → incident internal call failing | Check `X-Internal-Secret` / `INTERNAL_SERVICE_SECRET` parity; check agent-proxy logs |
| Sporadic ingest 500s during morning reboot burst | Pessimistic lock contention (incident#212) between journal ingest and heartbeat | Already mitigated: `createEvent` is `@Retryable` (3 attempts, backoff). Persistent failures = investigate DB locks |
| Event type never appears in the table | Type not in `event_type` lookup → stored as exception, 202 | Register the event type, or confirm agent is sending the expected string |
| Times look off | `eventTime` parsed as `LocalDateTime` (no zone); unparseable → `now()` | Confirm agent sends ISO local date-time |
| "Details"/hardware fields empty on expand | Agent didn't populate cardReader*/cassette* fields for that type | Expected for non-hardware events |

## Notes

- Table/DB: `journal_events` in Postgres DB **`hiveiq_incident`** (incident owns it). No separate journal-events database.
- Ingestion also drives ATM service state: `ATM_IN_SERVICE`/`ATM_OUT_OF_SERVICE`/`SUPERVISOR_ENTER`/`SUPERVISOR_EXIT` flip device state as a side effect, and every known event runs auto-incident creation/recovery. So journal events are not purely cosmetic — a stuck ingest also freezes auto-incidents.
