Identity Resolution
Identity resolution is built into the query language in Relata, not bolted on. The engine maintains an IdentityIndex (a materialised view over relata-identity) that maps every observed canonical identity value — phone, email, IMEI, IP, BTC address, Aadhaar, … — to the entity it belongs to, even when the same entity appears under different surface forms across different sources.
The Identity datatype
An Identity wraps a CanonicalKind and a deterministic binary encoding. The canonical catalogue ships 75 kinds today (the enum is #[non_exhaustive] with reserved headroom) — phone, email, IMEI, MMSI, IBAN, VIN, BTC address, mobile-money tokens, OT/ICS identifiers, etc.
| Surface | Source |
|---|---|
crates/relata-canonical/src/lib.rs | The 75-kind enum + validators |
docs/src/end-users/limits.md | Honest list of which kinds ship validators vs detection gates |
A few kinds (GSTIN, BTC address, FARA) ship validators but no SmartIngest detection gate — they round-trip but are not auto-detected from free text.
SQL operators
-- Universal lookup by value
SELECT * FROM LOOKUP_IDENTITY('+919876543210')
-- Resolution modes: canonical / cluster / fuse
SELECT * FROM RESOLVE_IDENTITIES('alice@example.com')
SELECT * FROM RESOLVE_IDENTITIES('alice@example.com', 'cluster')
-- Column projection form
SELECT name, RESOLVE_IDENTITY(email) AS identity
FROM PersonResolution modes
| Mode | Behaviour |
|---|---|
canonical (default) | Pick the canonical surface form. |
cluster | Return the whole cluster of identities linked to this value. |
fuse | Dispatch the EnrichmentRule chain. Register rules via POST /ontology/enrichment-rules. Returns a descriptive error when no rules are registered — no silent fallback to cluster mode. |
SmartIngest — auto-detection at write time
SmartIngest (relata-detect) auto-detects canonical identities in free-text fields at write time and links them into the IdentityIndex. Two-phase: eager detection on ingest, lazy enrichment on read.
# Default detector packs
RELATA_DETECT_PACKS=network,contact,crypto
# Opt-in packs
RELATA_DETECT_PACKS=network,contact,crypto,financial,payment,social,transport,device,ics
# Or all / none
RELATA_DETECT_PACKS=all| Pack | What it detects |
|---|---|
network (default) | IPv4/IPv6, MAC, URL, domain |
contact (default) | Phone, email |
crypto (default) | BTC / ETH addresses |
financial (opt-in) | IBAN, SWIFT, account numbers |
payment (opt-in) | Card numbers, UPI IDs |
social (opt-in) | Handles, profile URLs |
transport (opt-in) | MMSI, IMO, flight numbers |
device (opt-in) | IMEI, IMSI, ESN |
ics (opt-in) | Modbus, OPC UA, DNP3, S7, IEC 61850 |
relata detect "<text>"always runs all detector packs;RELATA_DETECT_PACKSonly governs HTTP/ingestand per-row ingest paths.
Identity operators
The IdentityClient typed client wraps the surface in the Python SDK:
from relata import RelataClient, IdentityClient
with RelataClient(url, bearer_token=token, purpose="identity-match") as client:
id_client = IdentityClient.from_client(client)
# label / uncertainty, lookup tables, ERASE SUBJECTGraph traversal between identities
Once identities are linked, you can walk the identity graph with IDENTITY_PATH and PATHS_BETWEEN:
-- All paths between two entities (max 4 hops)
SELECT * FROM PATHS_BETWEEN('person-123', 'org-456', max_hops => 4)See also
- Governance — ACL, cell masking, egress filtering
- SQL Reference — full operator list
- Limits — canonical type coverage