Sigra.Scope.Hydration (Sigra v1.20.0)

Copy Markdown View Source

Pure scope-hydration contract shared between Sigra.Plug.LoadActiveOrganization (Plug pipeline) and the generated UserAuth.on_mount callback (LiveView).

Given a (scope, config, session), returns a fully populated %Scope{} or a fail-closed error tuple. This module is the SINGLE place scope hydration lives. Any future scope augmentation — impersonation (v1.2), feature flags, passkey context — extends this function.

Fail-closed contract

On stale pointer (:not_a_member) or deleted org (:org_not_found), callers MUST clear session.active_organization_id and re-run Sigra.Organizations.select_active_organization/3. See Sigra.Plug.LoadActiveOrganization (Plan 14-02) for the orchestration.

The hydrator NEVER raises. It calls the non-raising Sigra.Organizations.fetch_organization/2 (not get_organization!/2) specifically to keep Ecto.NoResultsError out of the request pipeline (PITFALLS O-6).

Purity

This module performs only the reads necessary to resolve the active organization and the calling user's membership in it. It writes nothing: no session mutation, no audit event, no cache update. Calling hydrate/3 twice with the same inputs yields structurally-equal scopes.

Source of truth: Phase 14 CONTEXT.md D-01 / D-14 / D-23.

Summary

Functions

Hydrates the given scope with :active_organization and :membership based on session.active_organization_id.

Types

hydrate_error()

@type hydrate_error() :: :not_a_member | :org_not_found

Functions

hydrate(scope, config, session)

@spec hydrate(scope :: struct(), config :: map(), session :: Sigra.Session.t()) ::
  {:ok, struct()} | {:error, hydrate_error()}

Hydrates the given scope with :active_organization and :membership based on session.active_organization_id.

Returns {:ok, scope} unchanged when the session has no active organization pointer. Returns {:ok, scope} with the org and membership populated on the happy path. Returns {:error, :not_a_member} when the session points at an org the user was removed from. Returns {:error, :org_not_found} when the session points at a hard-deleted or soft-deleted org.

The config argument is the Sigra.Organizations config map (the same shape produced by the private __validate_config__! helper in Sigra.Organizations), NOT the top-level Sigra.Config.t(). Callers in the plug/on_mount paths resolve this from the generated wrapper module.