Skip to content

Data model

Scribe stores identity data as entries. Each entry has a type, identifiers, attributes, and a history of changes. See Architecture for how these fit into the sync and query pipeline. Click any element below to jump to its reference section.

Each element is clickable. Entry type links to type configuration, identifiers link to format documentation, attribute groups link to their reference sections, and change events link to event documentation.
Data Model

How entries, identifiers, attributes, and events relate

Every entry can be referenced by four formats. All channels accept all formats.

FormatExampleWhen to use
GlobalIddXNlcjo5aXgFastest lookup — use the id from query results
UUID550e8400-e29b-41d4-a716-446655440000External system integration
UOID12345Legacy numeric references
DNcn=john,ou=users,dc=example,dc=comLDAP compatibility

GlobalId is the recommended default. It’s URL-safe (no escaping needed), stable (assigned once, never changes), and fast (the entry type is encoded in the ID, so lookups skip type resolution). The canonical attribute name is entryID, with id as a convenience alias. Treat it as an opaque string.

Entries carry three categories of attributes: user data synced from the source directory, operational metadata managed by Scribe, and virtual attributes computed at query time.

Every entry carries metadata alongside user-defined data. Request them with the + directive (REST: ?fields=+, LDAP: add + to the attribute list) or by name.

CanonicalAliasesPurpose
entryIDidURL-safe global identifier
entryUOIDuoidInternal numeric database row ID
entryDNdnDistinguished Name (full LDAP path)
entryUUIDuuid, objectGUID, nsuniqueid, guid, ibm-entryuuid, dominoUNIDRFC 4122 UUID with product-specific aliases
entryTypetypeEntry type name (User, Group, etc.)
entryRDNrdn, relativeDNPath relative to the entry type’s base DN
entryNameFirst RDN value (the “simple name”)
eTagetag, entryCSN, revisionChange tracking token
createTimestampcreatedAt, whenCreatedCreation time
modifyTimestampupdatedAt, whenChangedLast modification time
verifiedTimestampverifiedAt, lastVerifiedAtLast verification against source

Responses always use canonical names, even when you request an alias. Both forms work in filters and projections.

Two attributes give shorter alternatives to the full DN:

  • entryName — the name portion. For cn=John Doe,ou=users,dc=example,dc=com, entryName is John Doe. Uses an indexed SQL function for fast lookups.
  • entryRDN — the path relative to the type’s configured base. For the same entry under base ou=users,dc=example,dc=com, entryRDN is cn=John Doe.

Both support case-insensitive filtering, sorting, and projection across all channels.

Some attributes are computed at query time rather than stored. The classic example is memberOf, which finds all groups containing a user without storing membership on the user entry.

Virtual attributes are configured per transcribe. See Transcribes configuration for the full syntax.

An entry type groups directory entries of the same kind — users, groups, devices. Each type maps to a transcribe that defines what to sync (base DN, filter, scope, attributes, indexes).

See Architecture > Transcribes for how entry types work in the sync pipeline.

Every change Scribe detects produces an immutable event:

Immutable Event Log

Every change recorded, any point in time queryable

09:14
+
User created
09:22
Δ
Email changed
09:35
Δ
Group added
09:41
Account disabled
now
?
Time-travel query
John Doe
email
groups
status
Add Modify Delete Query
TypeCarries
addFull attribute set of the new entry
modifyDiff — which attribute changed, how, and to what value
moveOld and new DN
deleteEntry identifier

Events are append-only. Each has a unique position (commit + index) and a timestamp. The entries table is a materialized view derived from these events — nothing is ever updated or deleted in the event log. This is what makes point-in-time queries and full audit history possible.

See Architecture > Events for how change detection works.

MODIFY events provide three representations of the change. All use delta semantics (what changed, not the full state):

FormatDescriptionWhen to use
diffAttribute-level operations: SET, ADD, REMOVEInternal processing, full detail
patchJSON Patch style with /attribute/- for array additionsJSON Patch-compatible consumers
mergeJSON Merge Patch style with changed values onlySimple consumers that just want the new values
data {
... on ModifyData {
diff { attribute operation value }
patch { operation path value }
merge { attribute values }
}
}

All three formats are available in the GraphQL and REST channels.

Time-based parameters (at, since, until, range) accept flexible formats: ISO timestamps, durations, relative expressions (now-1h), and natural language (yesterday, last 3 days). See Filters > Temporal references for the complete format table.