Skip to main content
This page covers the platform’s identity and tenancy model. For calling the API as an external program, see Authentication.

Login (Keycloak + NextAuth)

Users sign in through Keycloak (OpenID Connect); NextAuth manages the session. At login, Solya reads the user’s Keycloak groups:
  • Groups follow the convention tenant-<org-name> (e.g. tenant-adidas). Each resolves to an internal organization.
  • The special ops-admins group marks an operations administrator.
The resolved organizations are stored as the user’s available organizations, and the first becomes their default.

The session

A session carries the active organization and the user’s effective access in it:
  • organizationId / organizationName — the active organization.
  • availableOrganizationIds — every organization the user can access.
  • defaultOrganizationId — the fallback organization.
  • roles and effectivePermissions — the user’s roles and the union of permissions (direct + team) in the active organization.
  • currency, language, and an isOpsAdmin flag.

Organization scoping (multi-tenancy)

Every entity is scoped by organizationId, and the active organization is derived from the authenticated session, never from client input. Server actions and API routes resolve the organization, then services run all queries against it — so a user or token can only ever read or write their own organization’s data.

Switching organizations

A user who belongs to several organizations has an active one selected from (in order): their saved choice, then their default, then the first available. Switching changes the active organization for subsequent requests; roles and permissions are re-resolved for the newly active org.

Two ways in

CallerMechanism
Browser (human)NextAuth session cookie established via Keycloak
Program / agentAuthorization: Bearer solya_sa_… service-account token (org-scoped) — see Authentication
Both resolve to the same organization-scoped context, so the same endpoints serve both. Server actions enforce auth (and optional permissions); API routes do the same and additionally support an internal-bearer mode for internal services.