Provisioning Mappings and Lookups
Write-mappings, sync_mode, operators, provisioning lookups, and cross-system references.
Anatomy of a write-mapping
Each ConnectorInstance.provisioning_field_mappings
entry is a JSONB dictionary with these fields:
target_field— the name of the field on the target API (e.g.userPrincipalName)job_type—account_create/account_modify/grant/*(all)operator— how the value is rendered (see below)sync_mode—enforce/set_once/ignore_drift/skipapplies_to_account_types— empty = all types; a list = only for specific types
Operators — ways to compute a value
-
passthrough — a direct copy:
source_field: "identity.email"→ the target receives the identity's email. The fastest path for 80% of mappings. -
expression — a Jinja template:
{"\"{{ identity.first_name }}.{{ identity.last_name }}@example.com\""}. Can filter or transform:{"| lower"},{"| if_null('default')"}. -
constant — a fixed value for every account:
constant: "Member". -
lookup — query another system for the value.
lookup_schema_idpoints to a provisioning lookup row that describes the filter and return field. See the section below. -
account_attr — a cross-system reference:
account_attr("ad-corp", "samaccountname")reads the AD account's samAccountName for the same identity. This drives thedepends_on_systemsdependency graph (AD must sync before Entra). -
builtin — helpers:
gen_username(3 styles + accent normalization),slug,gen_uuid.
sync_mode — what the platform does when the target diverges
-
enforce — drift is written back. For attributes the platform treats as the source of truth (displayName, mail, job function).
-
set_once — write on create, then the target wins. For immutable identifiers (userPrincipalName after rollout).
-
ignore_drift — write on create and on modify, but do not write drift back during reconciliation. For attributes the target may legitimately change (last_signin_at, user-edited bio fields).
-
skip — never write. For read-only mappings that serve display only.
Provisioning lookups — cross-system reference resolution
Lookups let a mapping query the target API itself to resolve references. Example: a manager_id mapping on Entra:
lookup.target_object_name— which object to query (users)lookup.filter_template—{"userPrincipalName eq '{{ value }}'"}lookup.returns_field— which field to return (id)lookup.cache_scope—per_job/per_sync/per_tenantlookup.accept_stale_on_failure— on a target error: use the last cached value, or fail?
ℹ Good to know
Lookups are the number-one cause of slow provisioning on large tenants. Be careful with
per_jobscope on large batches; aper_syncscope with a higher time-to-live (TTL) often works better.
Per-account-type targeting
applies_to_account_types filters per type. Use
case: personal accounts get userPrincipalName
from identity.email, while admin-privileged accounts
get a-{"{first.last}"}@domain. Both mappings
write to the same target_field but for different
types.
Specificity: a mapping that names a type explicitly
wins over a generic (empty applies_to_account_types)
mapping on the same target_field.
Authority stays explicit at the write boundary
A mapping says how and whether RapidValue may write a field to this target. It does not silently establish precedence over every other source that can touch the same business fact. Combine the mapping with correlation, connector provenance and any upstream sync relationship, then verify the round trip.
See Source provenance and data authority for the shipped boundary and the universal matrix RapidValue does not currently claim.
Further reading: