Concepts

Entities and the graph

The people, accounts, devices and agents Sentinel keeps profiles for, and how they connect.

Sentinel models who your customers are, how they connect, and what they do. Decisions, alerts, cases and filings all hang off those three ideas.

Entities

An entity is anything Sentinel keeps a profile for. You create or update one with POST /v1/entities. IDs are yours, so use the IDs your own systems already use.

KindRepresentsTypical attributes
customerA person or business you serveName, date of birth, national ID, KYC result, risk tier
accountA bank or ledger accountCurrency, opened date, product
walletA mobile money or e-money walletOperator, phone number, tier, opened date
deviceA phone or browser seen on your platformFingerprint, OS, first seen
agentA cash-in / cash-out agent or merchantLocation, operator, till number
counterpartySomeone on the other side who isn't your customerName, institution, country

Attributes are free-form JSON. Send what you have now and add fields later without a migration.

A link records that two entities are related, with the first and last time it was seen. Every event with a source.entity_id adds links, and replaying an event changes nothing:

RelationFromToRecorded when
paidThe senderThe receiverThe event names both source.entity_id and destination.entity_id
uses_deviceThe senderThe deviceThe event has a device.id

Reading links back with GET /v1/entities/{id}/links also follows them one step: who paid this entity (paid_by), who used a device (device_user), and anyone else who used one of its devices (shares_device). Each linked entity comes with its open alert, if it has one.

If an event names someone you never registered, Sentinel adds a placeholder entity so the link has two ends. A placeholder's kind is a guess, so it's never shown; register the entity with POST /v1/entities and its real kind and attributes take over.

The entity graph

Together, the links form the entity graph. Patterns often show in connections rather than single transactions. One wallet receiving from 23 senders looks odd. The same wallet sharing a phone with four others and cashing out at an agent who serves all five looks much worse.

The alert panel's Linked entities list is built from the graph today, and the built-in rules count senders and receivers.

Not built yet: the Network graph screen, links for phone numbers and national IDs, ownership links (a customer and their wallets), and rules that count shared devices.

Core tables

Every table except the screening lists carries an org_id, so one install can hold several organisations with complete separation.

TableKey columnsNotes
entitiesorg_id, id, kind, attributes (jsonb), created_at, updated_atYour IDs
entity_linkssrc_id, dst_id, relation, first_seen, last_seenpaid and uses_device, filled from events
eventsid, idempotency_key (unique), type, occurred_at, amount_value, currency, rail, source_id, destination_id, payload (jsonb)source_id and destination_id are the event's source.entity_id and destination.entity_id
decisionsevent_id (unique), decision, risk_score, reasons (jsonb), features (jsonb)One decision per event
alertsdecision_id, event_id, source_id, status, priority, occurrences, assigned_to, dispositionOne open alert per source
alert_decisionsalert_id, decision_idEvery decision on an alert
alert_notesalert_id, author, bodyNotes on alerts
rulesrule_key, version, expr, weight, subject, status, created_by, approved_byEvery version is kept
screening_lists, screening_entriescode, version, ref, name, categoryShared by the whole install
screeningsreference, status, subject, matches, listsEach result as it was returned
audit_logseq, actor, action, target_type, target_id, data, prev_hash, hashAppend-only
api_keysname, key_hash (unique), key_prefix, created_by, revoked_atHashes only

Cases, reports and users are part of the product design. Their tables don't exist yet.

Sentinel is a Somu Labs product. © 2026 Somu Labs Ltd.