Digital Identity Update & Merge Integration Guide
PIS Interoperability Layer
1. Purpose of This Document
This document defines how consuming systems MUST process identity update events published by the Population Information System (PIS).
It applies to systems that:
- Persist identity data locally, and
- Reference identities from domain records such as payroll, benefits, licensing, or payments.
The objective is to ensure:
- Correctness of downstream domain data
- Protection against duplicate identities
- Safe, deterministic handling of identity merges
2. Event Model Overview
PIS publishes a single event type for all identity changes:
biographic-api.persons.updatedEach event contains:
- A canonical identity snapshot
- An optional merge instruction
ℹ️ Note
There are no separate merge events.
Snapshot updates, UPN changes, and identity merges are all delivered through the same update stream.
3. Canonical Identity Snapshot
Each event contains the full current state of the identity after all updates and merges.
Key fields
| Field | Description |
|---|---|
identity.id | Stable primary identity identifier |
identity.version | Identity version |
identity.currentUPN | Current UPN |
identity.UPNs | All historical UPNs |
| Biographic attributes | Names, DOB, sex, etc. |
ℹ️ Important
The snapshot represents future truth, not a diff.
It already reflects the final state after merges and updates.
4. Merge Instruction (merge)
If present, the merge object MUST be interpreted as an instruction to reconcile downstream state.
Merge schema
{
"version": 1,
"fromIdentityIds": ["IDENTITY_ID"],
"fromIdentityUpns": ["UPN"]
}Semantics
merge.version
A monotonically increasing value per identity.
Used to detect whether a new merge must be handled.fromIdentityIds
The complete list of absorbed identity IDs.fromIdentityUpns
Optional convenience for legacy systems that still index by UPN.
⚠️ Warning
Themergeobject is the only authoritative merge signal.
Audit or historical fields MUST NOT be used to infer merges.
5. Sample Payload
The following example illustrates the canonical update event structure and where the merge instruction appears. This is a representative example based on the published event schema.
{
"id": "694a7258e2d01b431f89afcc",
"type": "biographic-api.persons.updated",
"data": {
"id": "607417dcd6527600122216ee",
"group": "citizen",
"status": "active",
"version": 2,
"currentUPN": "4850110280892",
"UPNs": ["4850110280892", "4850110730110"],
"dateOfBirth": "1985-01-10T00:00:00.000Z",
"sexAtBirth": "female",
"names": {
"asOnId": {
"first": "نادیە",
"second": "توفیق",
"third": "محمد",
"fourth": ""
},
"first": {
"original": "نادیە",
"in_english_characters": "",
"in_latin_characters": "نادیە",
"in_arabic_characters": "نادیە"
},
"middle": {
"original": "توفیق",
"in_english_characters": "",
"in_latin_characters": "توفیق",
"in_arabic_characters": "توفیق"
},
"last": {
"original": "محمد",
"in_english_characters": "",
"in_latin_characters": "محمد",
"in_arabic_characters": "محمد"
},
"surname": {
"original": "",
"in_english_characters": "",
"in_latin_characters": "",
"in_arabic_characters": ""
}
},
"merge": {
"version": 1,
"fromIdentityIds": ["607418bc4e0a4a0012f55fd4"],
"fromIdentityUpns": ["4850110730110"]
}
},
"datacontenttype": "application/json",
"time": "2025-12-23T10:43:37.010Z",
"source": "pis-biographic-api"
}ℹ️ Note
Fields such asauditSettingsmay exist in some producer implementations but are considered internal and non-contractual. Integrators MUST rely only on themergeinstruction and the canonical snapshot fields documented above.
⚠️ Warning
Note how theUPNsfield already contains the UPN of the discarded identity (referenced inmerge.fromIdentityUpns). This is a crucial distinction as you must not update the snapshot before removing the other identity. This is because in case you have a DB uniqueness constraint on UPN, updating the snapshot before removing the other identity will cause a unique constraint error.
Therefore, it's is crucial to transactionally remove the discarded identity THEN update the current identity with the snapshot update.
6. Mandatory Processing Order (CRITICAL)
For every event, consumers MUST follow the steps below in the exact order.
Step 1 — Idempotency
Deduplicate events using the event identifier.
ℹ️ Note
Duplicate events may occur due to at-least-once delivery semantics.
Duplicate events MUST be ignored.
Step 2 — Check Merge Version FIRST
Before updating any identity snapshot:
if incoming merge.version > local merge_version:
merge handling is required🚨 CRITICAL
This check MUST occur before applying any snapshot update.
Skipping or reordering this step will result in inconsistent domain data.
Step 3 — Merge Resolution
If merge handling is required, consumers MUST choose one of the following paths.
Option A — Automatic Merge
Use this option if your domain rules allow automatic reconciliation.
Steps:
- Reassign all domain records referencing
fromIdentityIds - Deactivate or delete absorbed identities
- Update the locally stored
merge_version
⚠️ Warning
All steps above MUST be executed transactionally.
Option B — Manual Merge Review
Use this option if domain rules require human approval.
Steps:
- Create a merge review case
- Suspend identity snapshot updates
- Apply merge only after human approval
If a new event is received:
- If
merge.versionis greater than the stored version:- Discard the previously queued merge review
- Restart the process using the new event
- If equal or lower:
- Ignore the event
🚨 CRITICAL
Identity snapshots MUST NOT be updated while a merge review is pending.
Step 4 — Snapshot Update
The identity snapshot MUST be applied:
- After automatic merge completion, or
- After manual merge approval
❌ DO NOT
Apply snapshot updates before merge resolution.
This WILL cause data corruption and irrecoverable inconsistencies.
7. Design Guarantees
PIS guarantees that:
- Each update contains the full canonical identity state
- Merge instructions are complete and monotonic
- Absorbed identities will never reappear as survivors
- Event replay is safe
- Consumers never need to reconstruct merge chains
8. Summary for Integrators
To integrate safely:
- Subscribe to identity update events
- Store identities by
identity.id - Reference identities by ID, not UPN
- Always check
merge.versionfirst - Resolve merges before applying snapshots
✅ Following this order is mandatory to ensure correctness, auditability, and long-term system integrity.
