User Data Model

Overview

The User object represents an authenticated user in the Business Platform. It extends TenantEntity and contains identity, permission, and profile information alongside platform-specific metadata.

Core Fields

Field Type Description
id string Unique identifier for the user
email string Canonical email address. Single source of truth — profileFields.email only stores privacy metadata
emailVerified boolean Better Auth flag indicating the email has been verified
image string | null Profile image URL (from Better Auth / OAuth providers)
displayName string Human-readable display name (computed from profileFields, not stored)
language string Preferred UI language as an ISO 639-1 code (e.g. "de", "en"). When set, overrides browser detection and is used by server-rendered content such as emails
permissions string[] List of permissions in the format {TENANT_ID}::{PERMISSION}, e.g. 67f3b695bb457009cc645282::read
profileFields UserProfileFields Map of custom profile field values
badges EarnedBadge[] Array of badges earned by the user (see Badges)
passwordChangeDisabled boolean If true, the user cannot change their password
projectCreationDisabled boolean If true, the user cannot create new projects
profileFieldChangeDisabled boolean If true, the user cannot edit their own profile fields
messagingDisabled boolean If true, the user cannot create messages or message threads
isPlatformOwner boolean If true, the user has platform-wide admin access (e.g. can run migrations)
recentProjects Record<string, number> Map of projectId → last-opened timestamp (ms)
lastSeenReleaseVersion string Last release version the user has seen (for multi-device release-notes tracking)
personalAgentPermissions Record<string, Record<string, { read, write }>> Per-project, per-type AI tool permissions for the personal agent
optInDecisions UserOptInDecision[] Record of the user's opt-in decisions

Badges

Users earn badges as they complete key actions on the platform. The badges field on the User object stores all badges a user has earned.

EarnedBadge

Each entry in the badges array conforms to the EarnedBadge interface:

Field Type Description
name string The unique identifier of the badge (see Badge Names)
earnedAt number Unix timestamp (milliseconds) indicating when the badge was awarded

Example:

{
  "badges": [
    {
      "name": "projectCreated",
      "earnedAt": 1713800000000
    },
    {
      "name": "firstApplicationCreated",
      "earnedAt": 1713900000000
    }
  ]
}

Badge Names

The following badge names are defined in BADGE_NAMES:

Constant Value Awarded When
PROJECT_CREATED "projectCreated" User successfully creates their first project
FIRST_ACTION_CREATED "firstActionCreated" User creates their first action within a project
FIRST_PROJECT_MEMBER_INVITE "firstProjectMemberInvite" User invites the first member to a project
FIRST_DATA_TYPE_CREATED "firstDataTypeCreated" User creates their first data type
FIRST_APPLICATION_CREATED "firstApplicationCreated" User creates their first application

Badge Awarding Behavior

  • Badges are awarded at most once per user. If a user already holds a badge, subsequent qualifying actions do not re-award it.
  • Badge checks occur server-side via the checkBadge utility after the relevant resource is successfully created.
  • When a badge is newly awarded, the user receives a system notification.
  • Badge data is persisted on the User document in the badges array.

Viewing Badges

Users can view their earned and locked badges through the Badges button in the user profile panel. The modal displays:

  • Earned badges — shown with a success border, badge icon, description, and the date the badge was earned.
  • Locked badges — shown in greyscale with a lock indicator, listing what needs to be done to earn them.

The overall progress is shown as a count: earned / total available.

LocalAuthUser

LocalAuthUser is a session-scoped subset of User used during request handling. The projection lives in packages/server/src/auth/session-user-freshness.ts and is an explicit allow-list — only the fields listed here are copied from the User document onto the session and become available on the client as page.data.session.user.

Field Type Description
id string User identifier
createdAt number Creation timestamp (ms)
updatedAt number Last-update timestamp (ms)
tenantId string Tenant the user belongs to
email string Canonical email address
permissions string[] Effective permissions for the session
profileFields UserProfileFields Profile field values
badges EarnedBadge[] Earned badges, mirrored from the User document
optInDecisions UserOptInDecision[] Opt-in decisions
revision number Document revision number used for optimistic concurrency
passwordChangeDisabled boolean Mirrored flag
projectCreationDisabled boolean Mirrored flag
profileFieldChangeDisabled boolean Mirrored flag
messagingDisabled boolean Mirrored flag
isPlatformOwner boolean Mirrored flag
recentProjects Record<string, number> Mirrored map of projectId → timestamp (ms)
lastSeenReleaseVersion string Mirrored last-seen release version
language string Preferred UI language (ISO 639-1 code); used by the client to pre-set i18n on session hydration
personalAgentPermissions Record<string, Record<string, { read, write }>> Personal-agent tool permissions

Fields on User that are not carried into LocalAuthUser (e.g. image, emailVerified) must be re-fetched server-side when needed.

Schema Validation

The UserSchema validates the badges field as an array of objects, each requiring both name (string) and earnedAt (number) properties. Documents that do not conform to this shape will fail validation.