ADR 0001: Single active tenant (agency_id) per access token

Status

Accepted (design phase)

Context

The platform is multi-tenant: many agencies share one deployment. Users may have multiple memberships (e.g. a lead with the same mobile under agency A and agency B; or a partner who works for one agency only, but the same pattern applies).

Access tokens must tell the API which tenant context applies to each request so that queries can enforce agency_id scoping without ambiguity.

Alternatives:

  1. Single active tenant per access token — Each JWT contains exactly one agency_id (and related membership_id, lead_id or partner_id).
  2. Multi-tenant claims — One JWT lists all agencies the user may access; the client sends a header to pick the active one.
  3. No tenant in token — Resolve tenant only from hostname/header every time; sub alone is insufficient for row-level checks.

Decision

Use option 1: each access token encodes one active agency_id and the membership relevant to that agency (see auth-and-multitenancy.md §7).

To act in another agency context, the client calls a switch context (or re-login) flow and receives new access (and refresh) tokens.

Consequences

Positive

  • Authorization logic stays simple: request.agency_id == token.agency_id for tenant-scoped endpoints.
  • Fewer mistakes than inferring tenant from optional headers alone.
  • Aligns with “one session, one workspace” mental model.

Negative

  • Switching agency requires a round-trip to obtain new tokens (acceptable for web and mobile).
  • Refresh token strategy must define whether refresh is bound to one tenant or can rotate context (recommend: issue tenant-scoped refresh or re-auth for context switch).

Compliance

This ADR does not block future optional listing of “available memberships” in a separate unprivileged endpoint for UX; it only restricts what the bearer token may access in one hop.