This document is the deeper companion to AGENTS.md. It explains how the service boots, how authentication flows move through the codebase, and which pieces tend to matter during maintenance.
Request handling is assembled in this order:
- src/server.ts
- src/models/index.ts
- src/db.ts
- src/config/bootstrapSystemConfig.ts
- src/app.ts
- src/lib/loadRoutes.ts
Important implications:
- Models must initialize before route handlers run.
- The process will fail fast on missing database or required system configuration.
- Route registration is file-system driven, so every
*.routes.tsfile insrc/routesis mounted automatically.
Global behavior is configured in src/app.ts:
helmet- JSON body parsing
- CORS
- cookie parsing
- request logging
- rate limiting and slow-down outside test mode
- development-only OpenAPI and Swagger UI
- generic error and 404 handlers
Route modules use src/lib/createRouter.ts and src/lib/defineRoute.ts. defineRoute is more than syntactic sugar:
- parses params/query/body with Zod
- registers OpenAPI metadata
- can validate JSON responses against Zod schemas
- optionally attaches auth middleware through the
authproperty
If request parsing or OpenAPI output looks wrong, inspect the route definition before the controller.
Primary files:
Behavior:
- validates email/phone
- finds or creates the user
- issues an ephemeral token
- optionally sends or returns phone OTP delivery info
- stores bootstrap token in a cookie when present
Registration does not itself create the long-lived session. It prepares the user for OTP, magic link, or WebAuthn completion.
Primary files:
Behavior:
- requires ephemeral auth for generation and verification endpoints
- supports both registration verification and login verification
- can either send messages directly or return delivery payloads to an external caller
Primary files:
Behavior:
- requires ephemeral auth to request the link
- stores hashed token plus device fingerprint data
- verification endpoint marks the token used
- polling endpoint finalizes the login/session if the same device later confirms it
Primary files:
Behavior:
- start endpoints generate registration/authentication challenges
- finish endpoints verify browser responses with
@simplewebauthn/server - successful completion issues a real session
- registration/login completion can also trigger bootstrap admin promotion
Primary files:
- src/services/sessionIssuance.ts
- src/services/sessionService.ts
- src/controllers/authentication.ts
- src/controllers/sessions.ts
Key concepts:
- refresh tokens are opaque random values stored only as bcrypt hashes
- access tokens are signed JWTs using the JWKS-managed signing key
- cookie auth can silently refresh sessions
- session reuse detection revokes the replacement chain
When debugging auth bugs, inspect both the token code and the sessions table behavior. The middleware validates both JWT claims and backing session state.
AUTH_MODE changes the public contract of several endpoints.
- tokens are primarily communicated via cookies
- cookie middleware is the normal auth path
- session issuance writes
seamless_access,seamless_refresh, andseamless_ephemeral
- more endpoints return token material in JSON
- bearer validation is used more heavily
- refresh endpoints expect bearer credentials rather than browser cookies
When modifying a controller that returns auth state, verify both branches. Many regressions in this codebase would only show up in one mode.
The process relies on .env or runtime env vars for:
- database connection
- issuer/origin metadata
- bootstrap toggles
- service token secrets
- production signing/JWKS material
- optional direct messaging provider credentials
Reference points:
Bootstrapped runtime values include:
app_namedefault_rolesavailable_roles- token TTLs
- rate limiting config
- WebAuthn RP ID
- allowed origins
Reference points:
- src/config/systemConfig.envMap.ts
- src/schemas/systemConfig.schema.ts
- src/controllers/systemConfig.ts
The cache in getSystemConfig() is process-local. Any write path should invalidate it.
Direct delivery lives in:
Supported direct transports:
- AWS email
- AWS SMS
- Twilio SMS
Flows can opt out of direct sending and instead return delivery payloads by sending x-seamless-auth-delivery-mode: external.
This split is important when writing tests or integrating with an upstream orchestration service.
Useful tables/models to understand early:
userscredentialssessionsauth_eventsmagic_linkssystem_configbootstrap_invites
Model definitions live in src/models. Migrations live in src/migrations.
The test suite uses Vitest with:
- unit tests for utilities, middleware, services, config, and OpenAPI generation
- integration tests for route/controller behavior
- e2e and smoke tests for higher-level flow coverage
Reference points:
Practical guidance:
- use unit tests for small auth helper changes
- use integration tests when touching controllers or middleware
- update OpenAPI tests if you change route schemas or docs generation
- Some routes declare auth through
middleware: [attachAuthMiddleware(...)]instead of theauthfield. That works at runtime, but OpenAPI security metadata is only added by theauthfield today. defineRouteexpectsschemas, plural. Usingschemasilently skips request parsing and docs wiring.- Cookie names in runtime code are
seamless_access,seamless_refresh, andseamless_ephemeral. Confirm docs and tests against those exact names. system_configcan mask env changes after first bootstrap because the DB value becomes authoritative.- Silent refresh and refresh-token matching depend on scanning active sessions and comparing bcrypt hashes, so session-heavy scenarios are worth extra care.
- Read the relevant route file.
- Read the controller.
- Read the service/helper/model touched by the controller.
- Check the corresponding test file before editing.
- If changing auth or schema behavior, inspect OpenAPI impact too.
- Run
npm run build,npm run lint, and targeted tests before wrapping up.