Wiki
Architecture

Authentication

Better Auth, organizations, sessions, and the shared signing secret.

Authentication and organization membership are handled by Better Auth, configured in packages/auth and mounted by the server under /api/auth/*.

Organizations & dynamic access control

The organization plugin provides multi-tenancy — organizations, members, invitations, and teams. On top of it, dynamic access control powers the RBAC system: the statement, static roles, and runtime dynamic roles ("groups").

The RBAC source of truth (packages/auth/src/permissions.ts) is deliberately server-free so it can be imported by both the server and the browser bundle — never import the database or server code into it. See Permissions.

Enterprise identity

Two further plugins cover enterprise sign-in, both configured per organization from the app rather than from the environment:

  • SSO — OIDC (and, server-side, SAML) identity providers. Registration is restricted to organization owners/admins, and a provider stays inert until its e-mail domain is verified by DNS TXT record.
  • SCIM — directory sync. Tokens are stored hashed, must belong to an organization, and reach the server under /api/auth/scim/v2/* — which is why the auth routes accept PUT/PATCH/DELETE as well.

See Single Sign-On & SCIM for the setup flow.

Sessions & cookies

Sessions are cookie-based and signed with BETTER_AUTH_SECRET:

  • Over HTTPS: SameSite=None; Secure — supports web and API on different subdomains.
  • Over plain HTTP: falls back to SameSite=Lax, so localhost and LAN pilots work without TLS.

One secret, several services

BETTER_AUTH_SECRET signs sessions and the page-scoped collab tokens. The collab service must be given the same secret so it can verify those tokens. Keep it with your backups — a restore can't validate existing sessions without it.

Rate limiting

The server applies per-IP rate limits, tuned separately for the API and the auth routes:

  • RATE_LIMIT_MAX — general API requests/minute.
  • RATE_LIMIT_AUTH_MAX — auth routes/minute.
  • RATE_LIMIT_SCIM_MAX — SCIM routes/minute. Deliberately much wider: a directory sync is one request per user from a single IP, which the auth ceiling would throttle within seconds.

White-labeling

APP_NAME sets the display name used in auth flows, so a deployment can present its own product name.

On this page