Transaction monitoring
Rules your compliance team wrote, and can defend line by line
Transactions arrive canonically and idempotently. Rules are authored in a closed, typed vocabulary, simulated against real history before anyone approves them, and versioned so a two-year-old alert can still be replayed against the rule that raised it. Every alert carries the evidence that produced it, not just a score.
Detection is a decision support system, not an adjudication. The platform raises, prioritises and explains; a person triages, and closing an alert is a permissioned act with a recorded reason.
The problem
A monitoring system is judged by the alerts it cannot explain
Every institution can produce alerts. The expensive failures are in the second question: why did this fire, why did that one not, and what would have happened if the threshold had been different.
A threshold change is a project
When a rule lives in code, tuning it means a specification, a developer, a release and a regression window. So thresholds do not get tuned, false positives accumulate, and the queue is managed by hiring rather than by calibration.The alert outlives its reason
A rule edited in place takes its own history with it. Six months later the alert says the rule name and a score, the rule says something different, and nobody can reconstruct what the system actually evaluated on the day it fired.The same file, monitored twice
A retried batch, a replayed settlement window or an overlapping export inflates every aggregate a structuring rule computes, and produces duplicate alerts on the same activity — which then has to be dispositioned twice and reported once.
How it works
Ingest, evaluate, explain
The path a transaction takes is short and every step of it leaves something behind. The two refusal stages are the ones that keep the numbers honest: an invalid row is quarantined rather than dropped, and an aggregation across mixed currencies is refused rather than summed.
Integration service
Transactions arrive on a machine credential that cannot read anything
A core banking scheduler, a switch or a PSP authenticates with a tenant-scoped service-account credential holding only ingest permissions. The credential is a high-entropy opaque bearer revealed once and stored only as a digest; it can be rotated and revoked, its last-used and expiry metadata is inspectable, and it cannot impersonate a human or bypass human multi-factor policy. A service account that could read the customer book would make every integration a data-exfiltration path; this one is refused even with a valid token.Platform
One canonical shape, whichever door the transaction came through
Single-event and CSV batch ingest normalise onto the same six required facts — account reference, external reference, booking timestamp, direction, amount in integer minor units and currency — plus the optional dimensions that make rules worth writing: value date, channel, counterparty name, counterparty account and bank, corridor country and narrative. Amounts are never floating point and currency is never implied, so an aggregate cannot quietly add naira to dollars.Platform
A retry is a retry, and a bad row is a quarantined row
The idempotency key is resolved from the source system and its external reference, so re-sending after a timeout produces the same outcome rather than a second transaction and a second alert. Batches stage and resume, so a file that fails halfway continues rather than restarting. Rows that fail validation are quarantined with a bounded diagnostic that does not echo the submitted values back, and the accepted, duplicate and quarantined counts are what the source owner reconciles against their own ledger.Compliance administrator
Rules are authored against a closed, typed vocabulary
Rule expressions are written in a bounded expression language over a controlled vocabulary of transaction, customer and aggregate terms — closed and typed, so an expression referring to something that does not exist fails at authoring rather than evaluating to nothing at three in the morning. Query windows and aggregation shapes are bounded and indexed, which is what stops a well-meaning rule from becoming an unbounded scan across the transaction table.Compliance administrator
Simulate against real history before anyone approves it
A candidate rule can be run over historical transactions to show the alert volume it would have produced and the trace evidence behind each one. Simulation cannot activate anything: turning the rule on is a separate proposal that a different person approves, and the activated version is immutable. Old versions are retained so an alert raised last year replays against the rule that actually raised it, not against its successor. The activation control stays locked until a replay has been recorded against that exact version — a rule cannot be proposed for production on the strength of its author’s confidence alone.Platform
The alert carries its own evidence
An alert records the typology, priority and score, the rule and rule version, the transactions it evaluated and the evaluation trace — the evaluator returns evidence rather than a bare boolean, which is the difference between an alert you can defend and a number you have to trust. The trace is immutable. Related alerts on the same subject are correlated so an investigator sees the pattern rather than six separate rows.Analyst, then MLRO
Triage is bounded work with a recorded disposition
The queue is filtered by priority and by subject, and counts what is past its response window, unassigned, or already escalated. It reports its own bound honestly: the queue endpoint takes a page size and no position, so when more alerts match than are shown the screen says to narrow the filter rather than presenting a partial list as the whole queue. An analyst assigns, inspects the linked transactions and the trace, and either closes with a required reason or escalates into a case. Several alerts can be assigned or closed together, with one reason recorded per alert; an alert already attached to a case is shown but cannot be selected.Platform
The decision path stays synchronous; the fan-out does not
The alert decision itself is atomic — the state change and its audit record commit together. The downstream fan-out to audit projections and analytics goes through a retriable outbox, so a slow analytics write cannot hold up or partially apply a compliance decision. Operational metrics carry no tenant or customer labels, because a metrics system with customer identifiers in it is a second copy of the customer database with none of the controls.
In the product
The alert queue and the alert detail
Two screens carry the daily work: a prioritised, filterable queue, and a detail view where the rule that fired, the transactions it looked at and the trace it produced are all on one page.
Placeholder — TODO: capture the alert queue and alert detail screen (/alerts and /alerts/{id}) from a seeded demonstration tenant — no screenshot of it exists yet. Replace with sourced, approved content before this page is made public.
/alerts and /alerts/{id}alert queue and alert detail
Screenshot slot. Capture from a seeded demonstration tenant with synthetic data and replace this frame. Do not substitute a mock-up of the interface.
What the capture must show
- Prioritised queuePriority filters, counts for what is past its response window, unassigned or already escalated, and an explicit statement when more alerts match than the page can show.
- Rule and version on the alertWhich rule fired and which immutable version of it, so the alert stays reproducible after the rule is tuned.
- Why this alert firedThe rule predicate exactly as the engine runs it, the named thresholds resolved for that customer's segment, the aggregates computed over the window, and the window bounds and evaluation time.
- EvidenceThe transactions the evaluation used — booked time, direction, amount, channel, counterparty and narrative — totalled per currency, never across currencies.
- Recurrence, not duplicationRepeats of the same behaviour join a correlation group and show a count, so the queue is not filled with near-identical rows and the count reads as recurrence rather than as noise to dismiss.
- Disposition controlsAssign, close with a reason, or escalate into a case — with the actions this role may not take shown as refusals rather than hidden.
Controls
What makes an alert defensible
These are the properties an examiner tests when they ask you to reproduce a detection decision from two years ago.
Idempotency on the ingest path
Source system and external reference resolve an idempotency key, and unique keys enforce it in the database rather than in application logic. Re-asking is safe; the replay test in the release suite proves the same external reference does not produce a second alert.Money is integer minor units with an explicit currency
No floating point anywhere on the amount path, and mixed currencies are never silently aggregated — an aggregation across them is refused rather than summed into a number that looks like a threshold breach and is not.Simulation cannot activate
Running a rule against history and turning it on are different operations with different permissions. A maker proposes, a checker approves the immutable digest, and activation and its audit record commit in the same transaction.Evaluators return evidence, not booleans
The evaluation result carries what was examined and what satisfied the expression. That is what makes the alert explainable at review, replayable at audit, and tunable without guesswork.Evidence links are subject-consistent
Alerts feed casework, and the case workspace refuses evidence that resolves to more than one subject party. A case that could combine two unrelated customers is a filing that names the wrong person.A dormant rule is reported as dormant
The rule library counts how many rules have no active version and warns when any do, rather than reporting a coverage percentage. A library of twelve rules with three live is not seventy-five per cent monitored — it is nine typologies nobody is watching, and an installation running that way looks exactly like an institution with a clean book.The machine that writes cannot read
Ingest permissions are closed in code and revalidated both at assignment and at authentication. A service account presenting a valid token is still refused any customer, case or report content — proven by a negative test, not by configuration discipline.
Where the edges are
What monitoring does not do
Two of these are frequently sold as features elsewhere, and both would be a misrepresentation here.
In the product today
- Single-event and CSV batch ingest with idempotency, row-level quarantine, resumable batches and reconcilable accepted, duplicate and quarantined counts.
- Rule authoring in a closed typed vocabulary with bounded query windows, simulation against historical data, maker-checker activation and retained versions.
- Alerts carrying typology, priority, score, rule version, linked transactions and an immutable evaluation trace, with correlation across a subject.
- Prioritised queues with keyset pagination, assignment, closure with a recorded reason, and escalation into a subject-consistent case.
- Automatic generation of a currency threshold report from monitored transactions, subject to the same schema and approval gates as any other report.
Not claimed here
- A machine-learning detection model. Detection is rule-based and explainable by design; there is no behavioural model here that produces a score nobody can decompose. The model inventory screen exists to govern models, not to imply one is shipped.
- A vendor-specific core banking connector. Transactions arrive over the published ingest contract or as a canonical CSV, and mapping one bank's export onto that format is a declarative mapping written during implementation, not a Go release.
- Real-time payment interdiction as a default posture. The adapter vocabulary includes a hold and a release instruction for a switch that supports it, but no switch adapter is built, and the platform never originates a payment.
- Load-test evidence at your volumes. Sizing figures in the infrastructure documentation are extrapolated, not measured, and are stated there as a provisioning starting point and a load-test target rather than a service level.
Keep reading
Related capabilities
An alert is the beginning of the work, not the end of it. What happens next, and how the transaction got here in the first place.
Bring a typology
We will write one of your rules in the session
Pick a typology you monitor today — structuring, rapid movement, corridor exposure, dormancy reactivation — and we will author it in the vocabulary, simulate it against seeded history, and show you the trace it produces.