Generated

Generated Forms-Service Auth Integration

A source-driven trace from authClient.token() through records-service middleware and into SurrealDB authenticate(token).

AuthFormsSurrealGenerated
This file is generated from the live auth and records-service source files. Do not edit it by hand; regenerate it from apps/docs-site/ with bun run generate.

Generated from: apps/core/auth/src/platform/better-auth/auth.ts, apps/core/auth/src/index.ts, apps/delta/records-service/src/index.ts, apps/delta/records-service/src/middleware/surreal-auth.ts, apps/delta/application-list/src/features/forms-management/forms-api.ts, apps/delta/audits/src/platform/service-clients/api-client.ts, packages/auth/permissions/src/hono.ts, packages/database/migrations/migrations/0123_nela_scoped_jwt_access.surql

Forms-service auth flow
Forms-service auth flow

What this page is tracing

  • The browser-side Better Auth client call that retrieves a JWT for records-service.
  • The point where records-service verifies that JWT with auth-service JWKS and Better Auth-backed security rules.
  • The handoff where the same token becomes a SurrealDB-authenticated connection through db.authenticate(token).
  • The optional token-exchange branch for non-crown databases such as nela.

Flow checkpoints

  • The browser retrieves a Better Auth JWT with authClient.token() before it calls protected records-service routes.
  • records-service mounts surrealAuthMiddleware on /api/* before route handlers, so auth runs before business logic touches request state.
  • createAuthMiddleware() verifies the JWT with auth-service JWKS and can rehydrate Better Auth session data when route logic needs current active context rather than raw token claims alone.
  • The middleware can also call back into auth-service for active organization / workspace / team context, so Better Auth remains the source of truth for scope resolution.
  • The current records-service middleware uses the same JWT directly against SurrealDB by creating a request-scoped connection and calling db.authenticate(token).
  • If a service needs a non-default database, auth-service can exchange the token first; the live target list currently includes nela.

Frontend token handoff examples

  • apps/delta/audits/src/platform/service-clients/api-client.ts calls authClient.token() and sends Authorization: Bearer <jwt>.

Better Auth modules shaping this path

ModuleWhy it matters to records-service
JWTSigns the downstream token, exposes JWKS, and defines the Surreal-facing ns / db / ac claims.
Two FactorAdds the second-factor state that surfaces as twoFactorEnabled, which records-service requires before protected access.
Email OTPDrives verification and recovery OTP flows that ultimately feed the emailVerified claim the middleware enforces.
OrganizationKeeps organization and team membership inside the Better Auth session that downstream services can rehydrate.
WorkspaceAdds active workspace and team context so downstream services know which scope the user is operating in.
PermissionsFeeds the role-template and custom-permission pipeline that becomes the request ability in records-service.
Admin AccessAdds privileged admin flows on top of the same Better Auth runtime, even though ordinary forms traffic only consumes the signed JWT output.
External StructureExtends Better Auth with partner and delegated-access context that rides beside the same JWT/session model.
Organization ArchiveExtends organization lifecycle handling inside auth-service without changing how records-service verifies tokens.

JWT claims detected in the auth app

The current Better Auth JWT payload includes: ns, db, ac, sub, id, email, role, null, emailVerified, twoFactorEnabled, false, twoFactorMethod, twoFactorMethods, activeWorkspaceId, activeOrganizationId, activeTeamId, orgRole, teamRole.

Those claims matter because the token is not only verified at the HTTP edge; it is also reused by SurrealDB, where ACCESS policies can inspect values such as $token.ns, $token.db, $token.ac, and $token.sub.

Where Better Auth sits relative to records-service

  • Better Auth itself lives inside auth-service; records-service does not run Better Auth directly.
  • The browser asks Better Auth for a JWT through the client SDK, then forwards that JWT to records-service.
  • records-service trusts only tokens that validate against auth-service JWKS and match the expected issuer/audience.
  • Crown Better Auth extensions such as workspace, organization, and permissions shape the active scope and permission context that downstream middleware consumes.
  • @crown/better-auth-permissions is the bridge that turns the Better Auth token/session world into userDb, userContext, and ability on the Hono request.

Source checkpoints

StageEvidenceWhat it proves
Browser gets a JWTapps/delta/application-list/src/features/forms-management/forms-api.ts, apps/delta/audits/src/platform/service-clients/api-client.tsFrontend code calls authClient.token() and forwards the JWT as a bearer token before it calls records-service.
Better Auth signs the tokenapps/core/auth/src/platform/better-auth/auth.tsThe current JWT lifetime is 15m and the keypair uses EdDSA / Ed25519.
records-service guards /api/*apps/delta/records-service/src/index.ts, apps/delta/records-service/src/middleware/surreal-auth.tsThe middleware requires verified email + two-factor enabled before protected routes run.
JWT becomes request contextpackages/auth/permissions/src/hono.tscreateAuthMiddleware() verifies JWKS, resolves Better Auth session/context, loads custom roles, and builds the request ability.
Same JWT reaches Surrealpackages/auth/permissions/src/hono.ts, apps/delta/records-service/src/middleware/surreal-auth.tsThe shared auth middleware authenticates the underlying Surreal connection with the request token.
Alternate DB tokensapps/core/auth/src/index.ts, packages/database/migrations/migrations/0123_nela_scoped_jwt_access.surqlThe token exchange route can mint a database-specific JWT, and the nela access migration shows Surreal validating db = nela and ac = nela.

Alternate database note

The current records-service configuration points createSurrealAuthMiddleware() at the default crown database, so it uses the incoming Better Auth JWT directly. The token-exchange route still matters because the middleware can request a new JWT before calling db.authenticate() when a service needs a different Surreal database or access scope.

Generation note

  • This page is regenerated from the auth app, records-service, and the shared auth middleware.
  • If the token shape, security gates, or Surreal authentication path change, the next docs generation run updates this page and its flow diagram automatically.