Directory Connectors
Roster separates the external system from the code that talks to it.
Terminology
Section titled “Terminology”| Term | Meaning |
|---|---|
| Provider | External source of truth such as Entra ID, Active Directory, Okta, Workday, SAP, or CSV. |
| Connector | Roster-owned integration code for one provider or provider family. |
| Resolver | Query path that uses materialized Roster data to answer routing questions. |
Authentication providers configured for human login are separate from roster data providers. In sync and resolver docs, provider means external roster data source.
Supported Connectors
Section titled “Supported Connectors”| Connector | Provider path | Notes |
|---|---|---|
entra | Microsoft Graph v1.0 | Microsoft Entra directory users and groups. |
okta | Okta Core API v1 | Okta directory users, groups, and memberships. |
google_workspace | Admin SDK Directory API v1 | Google Workspace users, groups, and memberships. |
workday | Workday RaaS JSON custom reports | Tenant-defined workers, organizations, memberships. |
ldap | LDAP v3 over LDAP or LDAPS | Active Directory or LDAP-compatible directories. |
csv | Mounted data volume, S3, or SFTP | File-based records for batch integration workflows. |
Use ldaps:// for production LDAP connectors. Plain ldap:// should be
limited to isolated directory sources that cannot present a valid LDAPS
certificate.
Connector Guides
Section titled “Connector Guides”Refresh and Storage
Section titled “Refresh and Storage”Refresh schedules use 5-field UTC cron expressions. When no schedule is set,
the worker defaults to hourly refresh with 0 * * * *.
Worker refresh starts from cached records and attached groups. It refreshes their profiles and discovers the readable subgroup hierarchy required by those group associations, reconciling direct edges at each level. It does not import an entire directory or unrelated groups. Existing saved associations benefit from the normal refresh schedule without configuration changes or reattachment.
For self-hosted deployments, encrypted provider secrets require:
ROSTER_PROVIDER_SECRET_ENCRYPTION_KEY=<generated-provider-secret-encryption-key>Live Browse vs Cached Search
Section titled “Live Browse vs Cached Search”The Platform participant picker can search some connectors live so admins do not need to materialize a full directory before selecting a user or group:
- CSV connectors read configured CSV files directly
- Microsoft Entra ID queries Microsoft Graph directly
- Okta queries the Okta Core API directly
- Google Workspace queries the Admin SDK Directory API directly
- Workday queries configured RaaS JSON custom report endpoints directly
- primary LDAP connectors query LDAP directly
Secondary LDAP connectors remain metadata sources for now. They are searched from materialized records when matching primary connector results.
After an admin selects a user or group, Roster caches only the selected record in
directory_records and directory_record_sources. Selected groups also cache
the direct membership edges needed through their subgroup hierarchy. Scheduled
refresh maintains that hierarchy without browsing unrelated groups.
Interactive group association reads direct membership before saving the association. To keep that request responsive and protect the directory and Roster database, a group can contain up to 10,000 direct members and the lookup must complete within 30 seconds. Use a smaller directory group if either limit is reached. Scheduled connector refreshes continue to maintain memberships for groups that have already been associated.
New records enter the cache through explicit actions such as live browse, manual association, or import flows. Scheduled worker refresh does not discover new standalone records on its own, except for direct members needed by an already-cached participant group, including reachable subgroup members.
Nested Groups
Section titled “Nested Groups”Attach the parent group only. Resolve includes effective users through up to
10 subgroup levels by default, with the attached root at level 0. Users
in a level-10 group are included; a new group at level 11 exceeds the default bound.
Set ROSTER_DIRECTORY_GROUP_MAX_DEPTH
to configure 1–32 levels at container startup. Shared groups
retain each parent relationship and cycles terminate without repeated users.
Graph membership and usage are deduplicated by stable directory identity.
Resolve’s existing contact presentation, including e-mail coalescing, is preserved.
Connector Compatibility
Section titled “Connector Compatibility”This matrix describes the nested-membership paths implemented in Roster. Source conditions and live validation are separate: a source permitting nested groups does not establish that every tenant or group type has been validated.
In this compatibility matrix, ✅ means implemented support under the stated conditions, including Workday’s required report contract; ❌ means native nesting is unavailable. These are support indicators, not live-test results.
| Connector | Nested-group support in Roster | Conditions and source limitations |
|---|---|---|
| ✅ Microsoft Entra ID | Supported for compatible security groups | Graph must return readable direct user/group memberships. The group type and tenant must allow nesting; Microsoft 365 groups cannot be nested. |
| ✅ LDAP / Active Directory | Supported for configured DN-based relationships | member and DN-only uniqueMember can identify users or groups within the configured search bases/classes. memberUid supplies direct users only. |
| ✅ CSV | Supported with typed membership rows | Group edges require group_external_id,member_type,member_external_id, with member_type=group. The legacy user-to-group format remains supported. |
| ✅ Google Workspace | Implemented when direct GROUP members are readable | Directory API responses must provide the direct group relationship and stable member IDs. Delegated access/read permissions must cover every reachable group. |
| ✅ Workday — conditional | Conditional on configured reports | User, group and membership reports must provide complete direct typed relationships with stable IDs. Flattened user lists do not establish a group hierarchy. |
| ❌ Okta | Native nesting not applicable; flat user membership supported | The source exposes group users rather than a native group-to-group hierarchy. Roster preserves the flat connector and does not infer missing parent/child edges. |
These membership rules apply to the primary directory source. Secondary connectors remain enrichment sources for matched records.
Microsoft documents which group types can be nested.
Google documents group members and required authorization.
The CSV guide and Workday guide
describe their file/report contracts. LDAP’s optional UID suffix form of
uniqueMember is unsupported; use the supported DN-based schema.
Why Okta Stays Flat
Section titled “Why Okta Stays Flat”Okta’s group documentation
states that native nested groups are unavailable. When importing nested AD
groups, Okta imports the groups and assigns users to them,
including the parent. That flattened user membership does not preserve an
authoritative group-to-group edge. Shared users alone cannot establish a parent/
child relationship, so Roster cannot faithfully reconstruct the original hierarchy.
The Okta connector continues to support users, groups, paging and flat membership
through /api/v1/groups/{id}/users; it has not been removed or disabled.
Live Validation Scope
Section titled “Live Validation Scope”Implemented support and completed live tests are separate. The Entra security- group fixture, OpenLDAP and real local CSV files were exercised on SQLite and PostgreSQL, including nested refresh and membership changes. A real Google Workspace parent with two subgroup levels also passed initial association and worker refresh on both engines, with unique users and complete coverage; its confirmed manual removal/restoration cycle returned 2 → 1 → 2 unique users without reassociation or identity changes. Its depth boundary and multi-page behavior remain unvalidated. Large-group Entra pagination, AD-specific GUID/member ranges and actual Workday reports still require validation. Local CSV results do not certify S3/SFTP storage or every source schema. The support conditions above remain applicable to each deployment.
In isolated fixture tests, model-backed Resolve also returned the exact expected
users through public REST and MCP for Entra, Google Workspace, OpenLDAP and local
CSV on both databases, using OpenAI Responses with gpt-5.5 at low effort. These
are fixed routing scenarios, not a general model-quality certification. Contact
identities are returned in result.users; the generated answer can name only
the responsible role, and model-generated reservations remain visible.
Shared Limits and Incomplete Coverage
Section titled “Shared Limits and Incomplete Coverage”Nested discovery is also bounded by 1,000 groups, 10,000 distinct users, 50,000 membership entries and 2,000 pages per root. Interactive association keeps its existing 10,000-direct-member and 30-second limits. Additional subgroup work uses the remaining time; background nested discovery has a 120-second per-root budget. These are Roster safeguards, not provider nesting limits or performance guarantees.
When only additional subgroup discovery is incomplete, Roster preserves the
complete root association and existing flat behavior, records incomplete
coverage and retries on refresh. Resolve uses its existing caveats field to
explain incomplete coverage. It must not be interpreted as a complete hierarchy.
An incomplete direct group snapshot never deletes or renews that group’s old
memberships; their original 24-hour expiry remains in effect. Independently
complete groups can still refresh. Write-side product quotas retain their
existing whole-group rollback behavior and do not truncate Resolve output.
API and MCP directory-record search remains cache-only. It searches Roster’s materialized records and does not call upstream connectors live.