Rules
A rule is a true-or-false expression over an event and its features, plus a weight. When it's true, its weight is added to the score and its reason is recorded.
A typology is the real-world pattern a rule is trying to catch, such as "fan-in to a mule wallet". A typology pack is a ready-made set of rules for common patterns.
The rule language
Rules are written in the Common Expression Language (CEL), a small expression language from Google that can't loop forever or touch the network. An expression is compiled when you save it, so a broken one is rejected then and never reaches a live payment.
Here is a rule from the built-in pack:
key structuring_below_threshold
version 1
weight 60
expr amount >= 4500.0 && amount < 5000.0
&& features["near_threshold_count_24h"] >= 3
detail repeated transfers just below the reporting threshold within 24h
The thresholds in the built-in pack are placeholders. Set them to match your own reporting limits.
Variables
| Variable | Type | Value |
|---|---|---|
type | string | The event type |
amount | double | Amount value, 0 if none |
currency, rail | string | As sent, or empty |
source_id | string | The event's source.entity_id, or empty |
destination_id | string | The event's destination.entity_id, or empty |
features | map of string to int | Counters for the source |
dest_features | map of string to int | The same counters for the destination |
Money moves from the source to the destination. Every counter covers the 24 hours up to and including this event, and only events that had already arrived when this one did.
| Counter | Counts |
|---|---|
txn_count_24h | Events the source sent |
near_threshold_count_24h | Of those, how many were just under the reporting threshold: from 4,500 up to but not including 5,000 unless you set SENTINEL_NEAR_THRESHOLD_LOW and SENTINEL_NEAR_THRESHOLD_HIGH |
in_count_24h | Payments the entity received |
in_value_24h | Their total, in whole units |
in_senders_24h | How many different senders paid it |
in_senders_1h | The same, in the last hour |
out_count_24h | Payments the entity made |
out_value_24h | Their total, in whole units |
out_receivers_24h | How many different receivers it paid |
dormant_days | Whole days since its previous payment in or out, 0 if it has none |
seen_before | 1 if it had any earlier payment, otherwise 0 |
A counter that doesn't apply reads as 0, so a rule never fails on a missing key. Values add up amounts in whatever currency the events used; Sentinel doesn't convert between currencies. Compare amount with a decimal (4500.0), because CEL won't compare a double with a whole number.
Who a rule is about
Each rule has a subject: source (the default) or destination. It decides whose alert a match goes on. A fan-in rule looks at money arriving at the destination, so it's about the destination, and its alert is on the receiving wallet rather than on one of the many senders.
When rules about both parties fire on the same event, the alert goes to the party whose rules added more points.
Scoring
- Every active rule runs on every event scored in sync mode. The weights of the rules that match are added up and capped at 100.
- A score of 50 or more is
review, and 90 or more isblock. These thresholds are fixed in the current release. - Reasons are stored with the rule key and version, so a decision from last year can still be explained exactly.
- If a rule errors at run time, it's skipped and the error is logged. It's never quietly treated as "didn't match".
- The counter values used, for both parties, are stored with the decision, so the inputs are kept as well as the outcome.
The built-in pack
An organisation with no active rules of its own is scored by six built-in rules. Their thresholds are placeholders until they're tuned with real data; set your own to match your reporting limits and customers.
| Key | About | Weight | Fires when |
|---|---|---|---|
structuring_below_threshold | sender | 60 | The amount is just under the threshold and the sender has made 3 or more such transfers in 24 hours |
high_velocity_24h | sender | 30 | The sender has made 20 or more transactions in 24 hours |
fan_in_unrelated_senders | receiver | 50 | 10 or more different senders paid the receiver within an hour |
fan_out_after_credit | sender | 50 | The sender received 5,000 or more and paid 10 or more different receivers within 24 hours |
dormant_then_active | receiver | 50 | The receiver had no activity for 90 days or more and now gets 1,000 or more |
pass_through | sender | 40 | The sender paid out 90% or more of the 5,000 or more it received within 24 hours |
As soon as you activate a rule of your own, only your active rules run. To keep the built-in rules and edit them like any other, run sentinel-admin rules seed -org <org> first. It installs them as active rules, and only works while the organisation has no rule versions.
Changing a rule safely
Rules are versioned. You never edit a live rule. You create a new version, and a second person approves it.
Draft
Write the rule on the New rule screen, or with POST /v1/rules. Using an existing key creates that rule's next version. Nothing changes in production.
Backtest
Replay the draft against stored events with POST /v1/rules/{id}/backtest, or from the rule's page in the dashboard. You see how many events it would have flagged and, if another version is live, how many it would newly flag and how many it would stop flagging. This stops you flooding analysts by accident.
Approve
Someone with a different API key activates it with POST /v1/rules/{id}/activate. The key that wrote the draft can't approve it.
Live
The new version is active and the old one is retired. Every version is kept, with who wrote it and who approved it, and both actions are in the audit log.
Not built yet
- Shadow mode, where a rule scores live events without affecting decisions.
- Precision tracking: how often a rule's alerts turn out to be real.
- Configurable decision thresholds. Review at 50 and block at 90 are fixed.
- Device and phone counters, such as several wallets sharing one device. Events can carry a
devicebut nothing counts it yet. - Maintained typology packs delivered as signed updates. The planned packs cover fan-in and fan-out, structuring, dormant accounts waking up, round-tripping, agent self-dealing, SIM swap followed by a drain, shared devices and IDs, pass-through accounts, high-risk corridors, and card patterns such as card testing.