Architecture

Authentication & multi-tenancy

Identity, roles, organization scoping, the operator vs GP contexts, plan gating, and the tenant lifecycle.

Authentication is built on better-auth (@repo/auth) with a Drizzle adapter. The same auth layer provides organizations, memberships, and the operator capabilities the Command Center relies on.

Identity & sessions

A signed-in user has a session row carrying a userId, an activeOrganizationId (the tenant the session is currently acting within), and optionally an impersonatedBy value for operator support sessions. On sign-in, activeOrganizationId is hydrated from the user's lastActiveOrganizationId so a returning user lands back in their organization.

Supported methods are email + password, magic links, passkeys, and two-factor; no third-party identity providers are offered. Self-serve signup is disabled. The platform is invitation-only, so new users arrive through an organization invitation.

Two kinds of role

The platform separates a global role from an organization role:

RoleWhereMeaning
user.role = 'admin'Global (on the user)Platform operator. Unlocks the Command Center and all cross-tenant procedures.
member.rolePer organizationowner, admin, or member within that organization. Gates fund-level actions like inviting members or managing policies.

A helper treats a user as an organization admin if they are an owner/admin member or a global platform admin.

Operator context vs GP workspace

Operator (Command Center)GP user (workspace)
Identifying roleGlobal adminOrganization member
Active organizationOrg-agnostic; acts across tenantsAlways scoped to one organization
Routes/operator/*, /admin/*/{organizationSlug}/*
Data reachAll tenants, via audited proceduresOnly their organization's data

Operator routes are guarded in the layout: a non-admin visiting /operator is redirected away.

Admin/operator access additionally requires two-factor authentication to be enabled on the account (enforced by default). A platform admin who hasn't set up 2FA is redirected to /admin-2fa-required instead of reaching /admin or /operator.

Organization scoping

Tenant isolation is enforced in the API, not left to the UI. Org-scoped procedures resolve an acting organization from the session (or, for operators, from an explicit context) and reject the call if the caller is not a member. Knowledge queries additionally filter on tenantScope and organizationId, so one tenant can never retrieve another tenant's documents.

Global knowledge (the operator-managed library) is readable by every tenant by design. It is the shared playbook. Organization-scoped knowledge is visible only within its own organization.

Plan-based feature gating

Each organization has a plan tier that gates features and sets usage limits:

PlanAdvisorPolicy HubLP ReportingMonthly run cap
bot_only✔ (global playbook only)500
policy_hub✔ (org + global)2,000
full✔ (org + global)✔ (flag also required)10,000

LP Reporting is gated twice: the full plan and the per-organization lp_reporting feature flag. Both the server (requireReportingPlan) and the navigation model check both, so a tenant with only one of the two never sees reporting routes it cannot use.

FlagControls
lp_reportingThe LP Reporting route group and its nav items
advisor_hubAdvisor hub surfaces, including operator Retrieval Preview
advisor_guidanceFolder Registry and Advisor Guide

Flags are resolved per organization and fail closed — an unset flag is off.

Gating is enforced in two places: API middleware (a plan backstop and a usage-cap check that runs before any metered AI call) and the workspace navigation, which only shows features the plan includes. A request that exceeds the monthly run cap is rejected before it spends; a request that cannot resolve an organization is rejected as well. The effective cap is the explicit usageCounter.runsCap if set, otherwise the plan default.

Tenant lifecycle

An organization is active, inactive (no members), or suspended:

  • Suspend sets organization.suspendedAt. The workspace layout reads this and blocks entry for that tenant's users.
  • Reactivate clears suspendedAt.

Both actions are operator-only and recorded in the audit log. See the runbook on plans & lifecycle.

Support sessions (join as support)

Operators can open a support session to view the product as a specific user inside a tenant. The flow records support.impersonation_started in the audit log (with the operator's identity and an optional reason), sets session.impersonatedBy, and acts as the target user until the operator ends the session, which records support.impersonation_ended. The original operator is always the recorded actor, so impersonated actions remain attributable.

On this page