Sigra.Admin.Organizations.Detail (Sigra v1.1.0)

Copy Markdown View Source

Org-scoped data layer for the admin organization overview surface.

Provides the member roster and the set of pending invitations for a single organization. Both surfaces are inherently per-org: there is no global-scope behavior. Every query authorizes the admin scope against the requested organization and filters by organization_id, so an org-admin can never see another organization's members or invitations (fails closed).

Host schemas are resolved by namespace inference (optional_schema/2), mirroring Sigra.Admin.Users.Detail. When a membership or invitation schema is absent (legacy installs), the corresponding function returns [] rather than raising.

Summary

Functions

Returns the member roster for the admin scope's organization.

Returns only the pending invitations for the admin scope's organization.

Types

invitation_row()

@type invitation_row() :: %{
  email: String.t() | nil,
  role: atom() | String.t() | nil,
  expires_at: DateTime.t() | nil,
  expired?: boolean()
}

member_row()

@type member_row() :: %{
  user: struct(),
  role: atom() | String.t() | nil,
  confirmed?: boolean(),
  locked?: boolean(),
  deletion_scheduled?: boolean(),
  display_name: String.t() | nil
}

Functions

member_roster(config, admin_scope)

@spec member_roster(map(), Sigra.Admin.Scope.t()) :: [member_row()]

Returns the member roster for the admin scope's organization.

Each row is a map with the full user struct, the membership role, derived confirmed?/locked? status flags, and a display label. Returns [] when no membership schema can be resolved. Rows are ordered owners -> admins -> members, then by downcased display name (falling back to email).

Fails closed: authorizes the org scope and filters by organization_id.

pending_invitations(config, admin_scope)

@spec pending_invitations(map(), Sigra.Admin.Scope.t()) :: [invitation_row()]

Returns only the pending invitations for the admin scope's organization.

Pending means accepted_at IS NULL AND revoked_at IS NULL. Each row carries an expired? flag computed in Elixir against the current time (expires_at < now) to avoid DB-time skew. Returns [] when no invitation schema can be resolved.

Fails closed: authorizes the org scope and filters by organization_id.