Skip to content

Directory Integrations

Melvin PETIT edited this page Jun 16, 2026 · 1 revision

Directory Integrations

DataShield syncs the employee directory from your identity provider. Five connector types are pull-based (DataShield fetches users on demand); SCIM is push-based and documented separately in SCIM Provisioning.

Connector code lives in src/lib/directory/. Each connector exports a fetch<Provider>Users(config) returning a normalized DirectoryUser[]:

type DirectoryUser = {
  email: string
  firstName: string
  lastName: string
  department?: string
}

Supported providers

Type (DirectoryType) Connector Required config
AZURE_AD azure.ts tenantId, clientId, clientSecret
GOOGLE_WORKSPACE google.ts serviceAccountEmail, privateKey, delegatedAdminEmail, domain
LDAP ldap.ts host, port, ssl, bindDN, bindPassword, baseDN, userFilter
AWS_DIRECTORY aws.ts accessKeyId, secretAccessKey, region, identityStoreId
OKTA okta.ts domain, apiToken
SCIM inbound push bearerToken (see SCIM Provisioning)

All config blobs are encrypted at rest with AES-256-GCM before being stored in DirectoryConnection.encryptedConfig. See Security.

Sync behaviour

syncDirectoryConnection(connectionId, companyId) in directory/sync.ts:

  1. Loads the connection (scoped to the company), decrypts its config, and dispatches to the right connector by type.
  2. On a connector error, marks the connection ERROR with the message and rethrows.
  3. Upserts employees in batches of 25 (Promise.all per batch) to bound write concurrency and avoid exhausting the connection pool.
  4. On success, sets status = ACTIVE, lastSyncAt, lastSyncCount, clears errorMessage.

Returns { synced }.

Partial updates only. The upsert never overwrites an existing field with an empty value: buildUpdate includes a field only when the connector actually provided it. This protects manually entered data and fields a given IdP does not expose.

Managing connections

Connections are managed via the Data Sources page and these endpoints:

Endpoint Action
POST /api/directory Create a connection (ADMIN)
PATCH/DELETE /api/directory/[id] Update / remove a connection (ADMIN)
POST /api/directory/[id]/test Validate credentials, return a user count
POST /api/directory/[id]/sync Trigger a sync now

A SCIM connection cannot be pull-synced: triggering a sync on it throws, because provisioning is driven by your IdP. See SCIM Provisioning.

Clone this wiki locally