Skip to content

Search is only available in production builds. Try building and previewing the site to test it out locally.

Logical Architecture

The architecture of @frame/auth builds on Better Auth’s native flexibility to compose the identity layer through plugins and strict configuration.

graph LR
    A(Central Auth Configuration) --> B(Server Instance)
    A --> C(React Client)

    B --> D[NestJS Validation]
    B --> E[Next.js Auth API]

    C --> F[Next.js useSession Hooks]

Better Auth is modular by design. In FRAME, we inject functionality through official and custom plugins:

  • Internationalization Support: Full integration of @better-auth/i18n so emails, error messages, and authentication flows respect the user’s language (essential for a locale-aware ecosystem).
  • Organization Access Control: Better Auth organization clients and the server instance share the access-control definition and standard roles exported from src/permissions.ts.

To make a new OAuth provider (for example, Google or GitHub) or sign-in flow available everywhere:

  1. Define the Plugin/Provider: In the central configuration file, inject the extension into the plugins list or define the secret keys for socialProviders.
  2. Update the Drizzle Adapter: If the provider requires new columns, update @frame/models first, then map the field in Auth’s database configuration.
  3. Export the Client: Ensure the client (createAuthClient) regenerates correctly, deriving its full typing from your new configuration so TypeScript picks it up in apps/next.

src/permissions.ts is the canonical organization permission vocabulary. It defines product resources, standard roles, typed permission constants, and the conversion used by Better Auth’s hasPermission API.

RoleOrganization managementProduct data
ownerFull organization, member, and invitation controlCats and owners: CRUD
adminOrganization update, member, and invitation controlCats and owners: CRUD
memberNo management permissionsCats and owners: read

The global user role and organization membership role are separate. A global administrator can enter the platform /admin area, but organization data still requires membership and an organization permission.

  1. Add the resource actions to organizationAccessControl and assign them to the standard roles.
  2. Add reusable entries to ORGANIZATION_PERMISSIONS instead of constructing permission objects at call sites.
  3. Configure both the Better Auth server organization plugin and client organization plugin with the shared access control and roles.
  4. Enforce the permission in NestJS and scope persistence by organizationId.
  5. Use the shared permission in Next.js only to control action visibility; never treat hidden UI as authorization enforcement.
  6. Add role-matrix and denied-access tests.

The rationale and complete enforcement boundary are recorded in ADR 0003.