Context
@stackra/identity’s local driver is built on Better Auth (0087). Better
Auth brings its own hook system, database adapters, an admin plugin and an organization plugin. Used as shipped, it would
bypass the container, the outbox, check() and tenancy. The owner studied thallesp/nestjs-better-auth and settled how it
fits.
Decision
- Hooks are container-discovered classes.
@AuthHookswith@BeforeAuthand@AfterAuth, and@AuthDbHookswith@BeforeCreateand@AfterCreate('user'and the other tables). They are composed beforebetterAuth()is built and validated at gen time. A hook’s only side effect is an outbox event (0078). - All app authorization goes through iam
check(), and each action declaresauth: none | optional | required. The Better Auth admin plugin is for operators only, and it is audited. The Better Auth organization plugin is not used as tenancy. - Stackra owns the Better Auth MikroORM adapter, built with
createAdapterFactoryand checked with@better-auth/test-utils. Auth tables are model classes, migrations are MikroORM’s, and ids are UUIDv7 throughcustomIdGenerator. user,session,accountandverificationare global tables: no RLS, and accessed through an identity-only database role. Memberships live in tenancy and iam, with RLS.- Package shape: entries
contracts, core,node,react,nativeandtesting. The generated Encore app (0091) exposes a raw/api/auth/*endpoint and anauthHandlerthat accepts a cookie or a bearer token. Mobile uses@better-auth/expowith SecureStore. The future remote Figentra OS driver verifies tokens against JWKS. - A spike proves the raw wildcard path, cookies and the OAuth callback through the generated Encore app.
Consequences
- Better Auth stays behind the identity contract: other packages see
check(), outbox events and tenancy memberships, never Better Auth objects. - Maintaining an adapter is a standing chore that tracks Better Auth releases, with the upstream test utilities as its gate.
- Global auth tables are an explicit, reviewed exception to tenant row-level security. The identity-only role limits who can read them.
Enforcement
Planned: the adapter suite from@better-auth/test-utils in the identity package’s __tests__; a gen-time check that hooks
only write outbox events; a migration check that only the four auth tables lack RLS; the security-tenancy-reviewer agent on
every change. Nothing checks this today.
Supersedes and sources
Supersedes: none. Details 0087. Sources: owner decisions in chat, 2026-10-19 (Round 9 I1 to I4 and the identity shape). Reference studied:thallesp/nestjs-better-auth.