System anatomy / Elytra + Ascendra

One employee change.
Three separate systems.

Follow a leaver from the HR transaction to a disabled Entra account. Each boundary has its own state, authority and failure modes.

HR factsIGA decisionsExternal account stateIllustrative sequence numbers · No live tenant connection
Paused · illustrative timing
A simulated HR-to-identity machine An HR laptop connects to Elytra's Convex server and persistent database. Ascendra pulls events through an authenticated HTTP connection into a separate Convex database. A scheduled Graph call disables a user in the Entra directory. Read the text below the drawing for each simulated state. ELYTRA / CONVEX AASCENDRA / CONVEX BMICROSOFT ENTRA ID Own database · functions · operator authOwn database · functions · operator authSeparate tenant · external directory HR OPERATOR / ELYTRAEmployee E-1005employment: active End employment IGA CONSOLE / ASCENDRAEmployee E-1005identity: activeGraph sync: waiting CONVEX BACKEND mutationHTTP APIcron HR DATABASEemployeesoutboxEvents127 · 128 CONVEX BACKEND pollingestGraph IGA DATABASEidentitiesoutboxCursorlastSequence: 128 MICROSOFT GRAPHApp credentials PATCH /users/{id}accountEnabled: falsethen POST revokeSignInSessions TENANT DIRECTORY E-1005account: enabledsessions: not revoked HTTPS / pullBearer secret Atomic HR + outbox commitLocal commit → scheduled actionGraph result → sync log 6 h: read HR snapshots · findings only15 min: check Entra account state

Conceptual machines represent the managed Convex services, not physical server topology. On small screens, scroll the drawing sideways. Press Play to send event 129 through the system.

1 / 6 · HR records the departureExample: E-1005 → employmentStatus: terminated

The moving dot follows an event through the pipeline. Final success includes account disable and session revocation; existing access tokens may remain valid. The HR outbox retains its event after consumption. Animation speed does not represent cron timing.

Inspect the database tables and integration boundaries
01 / Source of truth

Elytra

Independent Convex deployment A
Own database, backend functions and operator auth

React interface → Convex mutation

HR operator ends employment

Employee E-1005 becomes terminated.

HR database

Convex A
One atomic mutation
employeesemploymentStatus → terminated
lifecycleEventsHuman-readable HR history
outboxEventsAppend-only integration feed
127128129…

employee.terminated
sequence · employeeNumber · occurredAt · payload

countersAllocates the next sequence

State change and event commit together.
No downstream database participates.

Public HTTP API / read-only

Expose committed events

GET /api/events?since=128

Bearer secret checked by Elytra.
Returns events after the cursor.

HTTPS

Request ←
Events →

Pull, not push
02 / Identity governance

Ascendra

Independent Convex deployment B
Own database, backend functions and operator auth

Cron → Convex action / every minute

Read cursor, fetch new events

outboxCursor.lastSequence = 128
HTTP request uses the shared secret.

Normalize → applyEvents mutation

Validate and materialize

Accept extra fields. Quarantine malformed events. Preserve source event time.

IGA database

Convex B
identitiesHR facts + provisioning state
outboxCursorLast handled sequence → 129
auditEvents / syncEventsLocal decisions and sync results
ingestDeadLetterMalformed event + reason
integrationHealthLast poll, errors and source timing

Ingest commits local changes, cursor and scheduled work atomically. Roles, requests and certifications also live here.

Scheduled action / after local commit

Resolve and provision account state

Employment + IGA decisions → desired state.
This leaver: disable the Entra account.

Graph API

Write →
Result ←

App credentials
03 / Target directory

Microsoft Entra ID

Separate tenant · Outside Convex

Application permissions

Microsoft Graph

Client credentials authenticate Ascendra.
Create, update or disable real accounts.

Tenant directory

User accountaccountEnabled → false
Group membershipsGrant/revoke for mapped roles
Entra audit logDirectory-side evidence

The actual account state belongs to Entra. A local identity update is not proof of a successful Graph operation.

Response → Ascendra

Record success or failure

Sync results return to Ascendra's database. Failures stay visible for retry and investigation.

Follow an offboarding

Step through the boundaries.

1. HR records the departure

An HR operator terminates the employee. Elytra commits the employment record, lifecycle history and outbox event together.

Example: E-1005 → employmentStatus: terminated

Independent safety nets

Events tell you what changed. Reconciliation checks what is true.

Every 6 hours

Ascendra ← HR snapshots

GET /api/employees
GET /api/departments

Compare current HR records with identities. Detect missing, divergent or incorrectly deprovisioned records. Deduplicate findings for review.

Detection only. No writes back to HR.
Every 15 minutes

Ascendra ↔ Entra account state

Read accountEnabled through Graph. If an account should be disabled but is enabled, disable it. If an active account is unexpectedly disabled, flag it for review instead of re-enabling it.

Missing accounts are recorded. Group drift is outside this check.
On poll / sync

Health, quarantine and audit

An HTTP failure is recorded in integration health. An invalid event is quarantined. Graph results are tracked separately from ingest progress.

Cursor progress ≠ successful provisioning.
Scheduled dates and other downstream work

Elytra runs a daily transition job at 02:00 UTC. Due start and end dates become actual employment transitions and produce outbox events through the same HR mutation path.

For a termination, Ascendra also schedules FinanceApp SCIM synchronization and evaluation of non-human identities owned by the departing employee. These are separate effects of the identity change; Microsoft Graph is the Entra provisioning path, while SCIM is the downstream application path.

Operator sessions authenticate each app's human users. The shared Bearer secret authenticates the HR-to-IGA HTTP integration. Ascendra's Entra client credentials authenticate its Graph calls. These are three distinct authentication boundaries.

Explore the Anatomy message-queue model

Anatomy's interactive figure illustrates the producer → buffer → consumer idea. Elytra is the producer and Ascendra is the consumer. Pause consumers in the figure to see why buffering matters.