Skip to content

Directory Records

A directory record is Roster’s normalized representation of a user, group, organization unit, role, or external email from an external provider. Directory records give participants and the resolver a stable Roster record to reference without treating Roster as the source of truth for identity data.

Directory records are separate from authentication identities. An identity authorizes access to Roster. A directory record represents someone or something that may handle workflow responsibility.

Supported connector families include CSV, Microsoft Entra ID, Okta, Google Workspace, Workday, and LDAP or Active Directory. See Directory Connectors for connector setup and live-browse behavior.

TypeRepresentsCommon use
userHuman or service user from a provider directory.Direct participant membership and delegated coverage.
groupProvider group or distribution list.Participant membership that expands through group members.
org_unitOrganization unit, department, cost center, or region.Routing context, metadata, and organization membership.
roleProvider or business role.Responsibility context and role-based membership.
external_emailEmail address that is not backed by a provider account.External reviewers, contacts, or escalation recipients.

Directory records keep a small canonical profile:

  • record type
  • display name
  • primary email when available
  • description
  • source links
  • metadata
  • membership edges

The canonical profile is intentionally narrow. Provider-specific fields stay on explicit source fields or allowlisted metadata so Roster can search, resolve, and audit directory data without copying every provider attribute into the primary record.

When multiple sources are attached to the same record, the primary directory source owns the canonical profile fields such as display name, primary email, and description. Secondary connector values stay on directory_record_sources and directory_record_metadata so source-specific differences remain visible without overwriting the canonical record.

A source record connects a directory record back to one provider connection. It stores the provider, external ID, source type, source display fields, and refresh timing. Raw provider payloads are not stored.

Source records preserve provenance. When a record is enriched by another connector, Roster can keep the stable directory record while recording which provider supplied each source value.

Directory metadata stores structured provider or business context such as:

{
"department": "Finance",
"region": "EMEA",
"cost_center": "FIN-420"
}

Metadata values can be text, number, boolean, timestamp, or JSON. Metadata may also reference the source that supplied it, which lets admins understand where a resolved value came from.

Directory records can be linked to other directory records. A group can include users, an organization unit can include members, and a source connector can mark whether the relationship is direct, transitive, or organization-based.

Roster uses these relationships during participant and delegation resolution. Member listings on a participant show direct participant associations. Resolver behavior expands group associations through readable nested subgroups up to 10 levels below the attached root (level 0) by default, then applies active delegations. The server setting ROSTER_DIRECTORY_GROUP_MAX_DEPTH configures 1–32 subgroup levels consistently for resolution and directory details. Attach only the parent group; shared groups and cycles preserve a unique set of effective identities. Participant association counts still count direct associations, while the participant’s associated-user total counts effective user identities. Existing Resolve contact presentation remains unchanged.

See the connector compatibility matrix for supported relationship formats and source limitations. Nested expansion uses readable group-to-group edges from the primary directory; secondary sources enrich records. Okta’s flat memberships remain supported without inferring a hierarchy.

Administrators can open a record under Directory → Records and select the Members tab:

  • For a user, only Member of is shown. It lists the user’s direct groups and their indirect parent groups; users do not have a Members section.
  • For a group, Members lists direct and indirect users and subgroups. Member of lists the group’s direct and indirect parent groups.
  • Each related record appears once, labeled Direct, Indirect, or Direct and indirect when both relationships exist. The detail overview counts match these unique displayed relationships.

For example, if Parent contains Team and Team contains Alice, Parent lists Team as direct and Alice as indirect. Alice’s Member of list shows Team as direct and Parent as indirect. A group with no parent has an empty Member of list.

The calculation follows at most ten group-to-group links; a directly associated group is the starting point for a user’s parent-group calculation. This limit is currently fixed, with no Docker environment variable or admin setting. Recorded relationships remain visible for inspection, but only fresh direct relationships from the active primary directory can bridge to additional groups. Computed indirect relationships have no stored source or refresh timestamp of their own, so those fields appear empty. These views do not grant access to projects or administration.

Roster does not edit upstream provider accounts. Connector refresh jobs update already-cached directory records, sources, and metadata from provider data. For cached group records already attached to participants, refresh jobs also discover reachable subgroups and reconcile their direct membership edges in participant_record_members. Existing associations gain indirect members at refresh without manual reconstruction. Jobs do not import every upstream user or group or synchronize unrelated memberships. Incomplete discovery is reported explicitly; see nested groups.

Use participant membership to decide which records can handle workflow action. Use identities, roles, scopes, and project ownership to decide who can manage Roster itself.