new·The score now tells you which way it movedA brain's exam only ever grows: its own material writes questions, and so does every question a real caller asked and did not get answered. The score is a percentage over that growing set, so a brain that learned more could post a smaller number — and this week three did. One of them answered two MORE questions than the week before and showed eighteen points less. Printed as a single percentage, that reads as decline to a reader and as punishment to anyone who contributes material.all news →
mozg.beta
Sign in

Better Auth · Concepts · all subjects

database/schema

12 notes, read out of this brain and free to use. Each one was extracted from a source and is re-checked against its exam.

User table core schema

The user table has these fields: id (string, primary key), name (string), email (string, unique), emailVerified (boolean), image (string, optional), createdAt (Date), updatedAt (Date).

Session table core schema

The session table has these fields: id (string, primary key), userId (string, foreign key to user.id with cascade delete), token (string, unique), expiresAt (Date), ipAddress (string, optional), userAgent (string, optional), createdAt (Date), updatedAt (Date).

Account table core schema

The account table has these fields: id (string, primary key), userId (string, foreign key to user.id with cascade delete), accountId (string, ID from SSO or equal to userId for credential accounts), providerId (string, ID of provider), accessToken (string, optional), refreshToken (string, optional), accessTokenExpiresAt (Date, optional), refreshTokenExpiresAt (Date, optional), scope (string, optional), idToken (string, optional), password (string, optional, for email/password auth), createdAt (Date), updatedAt (Date).

Verification table core schema

The verification table has these fields: id (string, primary key), identifier (string), value (string), expiresAt (Date), createdAt (Date), updatedAt (Date).

Better Auth requires email on every user record

Better Auth currently requires an email address on every user record. Most providers return one with the email scope, but several can legitimately omit it. When that happens, the OAuth flow fails with error=email_not_found or error=email_is_missing for the Generic OAuth plugin.

Providers without email: Apple, Discord, Facebook, GitHub, LinkedIn, Microsoft Entra ID, Roblox

The following providers can legitimately omit email in certain scenarios: - **Apple**: Every sign-in after the first (Apple only emits email on the initial consent). Stable fallback ID: profile.sub (stable per Apple Team). email_verified trust: Reliable; relay addresses are also flagged verified. - **Discord**: Phone-only accounts; email scope not granted. Stable fallback ID: profile.id (snowflake). email_verified trust: Reliable (dedicated verified field). - **Facebook**: No valid email on file, even with the email permission granted. Stable fallback ID: profile.id (app-scoped). email_verified trust: Unknown: Graph API exposes no per-email verification flag. - **GitHub**: User has set email to private; GitHub App lacks the "Email addresses" permission. Stable fallback ID: profile.id (numeric). email_verified trust: Reliable. - **LinkedIn**: No confirmed email on the member; email scope not granted. Stable fallback ID: profile.sub (pairwise per app). email_verified trust: Reliable when present. - **Microsoft Entra ID**: Managed users without a mail attribute, unless email is configured as an optional claim. Stable fallback ID: profile.oid plus profile.tid (or profile.sub). email_verified trust: Untrustworthy: Microsoft explicitly warns never to use for authorization. - **Roblox**: The default Roblox profile flow does not return an email; Better Auth currently falls back to preferred_username. Stable fallback ID: profile.sub (Roblox user ID). email_verified trust: Unknown for the default profile flow.

mapProfileToUser requires fields declared in user.additionalFields

Declare mapped fields in the user.additionalFields option and allow those fields as input. The same rule applies to stateless auth setups.

Security: keep server-owned fields at input: false

Keep security-sensitive fields such as roles, bans, internal flags, and organization membership at input: false. Do not enable input only so mapProfileToUser can persist a provider claim, because the same setting also lets generic sign-up and user-update requests supply that field.

input and returned control separate directions for fields

input and returned control separate directions. For example, { input: false, returned: true } defines a readable server-owned field. API input and mapProfileToUser cannot supply it, but Better Auth includes its stored value in responses.

rateLimit database schema

The rateLimit table contains the following fields: id (string, primary key, database ID), key (string, unique, unique identifier for each rate limit key), count (integer, number of requests made in current window), lastRequest (bigint, timestamp of last request in epoch milliseconds).

Session table fields

The session table stores session data with the following fields: id (unique identifier), token (session token used as the session cookie), userId (user ID of the user), expiresAt (expiration date), ipAddress (IP address of the user), userAgent (user agent header from the request).

Account table stores authentication data

The account table stores authentication data returned by providers, including access tokens, refresh tokens, and other provider-specific information. Each authentication method is called a provider (e.g., email/password, Google, GitHub).

Give your agent this brain