---
module: transactions.browser
title: Transactions Browser
tab: Claude
order: 40
audience: dev
---

Act-without-guessing reference. Confirmed from source unless marked `(unverified)`.

## Ownership

- **Data owner:** `hiveops-journal` (DB `hiveiq_journal`). All transaction reads/writes live here.
- **Frontend:** `hiveops-transactions` → image `hiveiq-transactions-frontend`, port `5178`, `transactions.bcos.cloud`. Svelte SPA, no DB, no Kafka.
- **BFF proxy:** `hiveops-transactions` backend, port `8098`, stateless, JWT-auth, forwards to journal/devices/AI.
- **ATM + group lists:** `hiveops-devices` (via proxy `/api/atms`, `/api/atm-groups`).
- **Adoons analyze:** real impl in `hiveops-ai` `IncidentAiController` (`POST /api/adoons/analyze-journey`, `X-Internal-Secret`, not user JWT).

## Endpoints (METHOD path — auth)

| METHOD | Path | Auth |
|---|---|---|
| GET | `/api/journal/transactions` | `isAuthenticated()` + institution scope |
| GET | `/api/journal/transactions/{id}` | `isAuthenticated()` (403 on scope mismatch) |
| PATCH | `/api/journal/transactions/{id}/adoons-analysis` | `isAuthenticated()` |
| GET | `/api/journal/cassette-config?atmId=` | `isAuthenticated()` |
| GET | `/api/journal/cheques/by-sequence?atmId=&txnId=` | JWT (`/api/**`) |
| GET | `/api/journal/cheques/{id}/preview` | JWT → PNG bytes |
| GET | `/api/journal/files?atmId=&page=&size=&journalType=` | `hasAnyRole('MSP_ADMIN','BCOS_ADMIN')` |
| GET/PUT | `/api/journal/admin/rules` (+`/rules/structured`, `/tcr-rules`, `/tcr-rules/raw`) | `MSP_ADMIN`/`BCOS_ADMIN` |
| POST | `/api/journal/admin/reload-rules`, `/reparse-all`, `/tcr-rules/reload`, `/reconcile`, `/archive-now` | `MSP_ADMIN`/`BCOS_ADMIN` |
| GET/POST | `/adoons/status`, `/adoons/analyze-journey` (frontend calls; routed via BFF/nginx) | `(unverified)` — see gotchas |

`/api/journal/transactions` params: `atmId` (repeatable), `from`, `to` (YYYY-MM-DD), `type`, `result` (`SUCCESS`/`FAIL`/`TIMEOUT`), `pan`, `amountMin`, `amountMax` (dollars, ×100→cents server-side), `journalType` (`JRN_ATM`|`NH_TCR`), `foreignOnly`, `page`, `size`.

## Tables (`hiveiq_journal`)

- `journal_transactions` — hot (<90d)
- `journal_transactions_archive` — cold (>90d)
- `journal_files`, `journal_gaps`, `atm_institution_map`, `cheque_image`

## Kafka topics (owned by journal; NOT used by the browser read path)

- `journal.parse-requests` / `journal.parse-requests.{INSTITUTION}`
- `journal.file-parsed`
- `hiveops.journal.transactions.recorded`
- `journal.replenishments`

## Scoping (`InstitutionContext.resolveScope()`)

- `BCOS_ADMIN` / `ADMIN` / `USER` → `null` = all institutions.
- `CUSTOMER` → single institution key.
- `MSP_ADMIN` → granted key list (from JWT credentials).
- Filter applied on `journal_transactions.institution`.

## Gotchas

- Only the journal **upload-role** container serves these endpoints (`@ConditionalOnProperty journal.role=upload`); worker containers return nothing/404 for `/api/journal/**`.
- Ranges >90 days read the archive table + trigger a client confirm dialog (`ARCHIVE_CUTOFF_DAYS=90`, `journal.archive.days=90`).
- `journalType` (ATM/TCR) is only sent when **no single ATM** is selected.
- `SEQ #` `"0"` stored null, rendered `-`. Amounts are cents (`amountCents`), displayed `/100`.
- `foreignOnly=true` = surcharge/fee > $0.
- After any journal redeploy: `POST /api/journal/admin/reconcile` or PENDING files stay stranded.
- `amountMin`/`amountMax` are `Long` (whole dollars) server-side; the SPA input allows `step=0.01` — a decimal value produces a 500 (bug, see uncertainties).
- The SPA fires a transaction reload on every `pan` keystroke (no debounce).
- Adoons `analyze-journey` real handler (`hiveops-ai`) is `X-Internal-Secret`-gated, not user-JWT — the frontend cannot hit it directly; it goes through the AI-URL proxy target (default `hiveiq-incident:8081`).

## Do NOT

- Do NOT add transaction endpoints/tables to `hiveops-transactions` or incident — transaction data is journal-owned.
- Do NOT expect Kafka in the browser read path; it is synchronous JPA over `journal_transactions`.
- Do NOT assume `MSP_ADMIN` sees all institutions — it is scoped; only `BCOS_ADMIN`/`ADMIN`/`USER` are unscoped.
- Do NOT point admin rule/reparse calls at a worker container — upload role only.
- Do NOT call `hiveops-ai` `/api/adoons/analyze-journey` with a user JWT — it needs `X-Internal-Secret`.
- Do NOT brand `hiveops-ai` as anything but **Adoons** in user-facing copy.
