Skip to content

Data Models

Complete Entity Reference

This document provides detailed field-level descriptions for all database entities in Cerberus IAM.

Global Entities

Permission

Purpose: System-wide permissions for RBAC

FieldTypeDescription
idUUIDPrimary key
nameStringHuman-readable name (e.g., "Read Users")
slugStringMachine-readable identifier (e.g., "users:read")
descriptionString?Optional permission description
createdAtDateTimeCreation timestamp
updatedAtDateTimeLast update timestamp

Relations:

  • roles: Many-to-many with Role

Indexes:

  • Unique on name
  • Unique on slug

Permission Format:

  • resource:action (e.g., users:read, roles:create)
  • resource:* for all actions on resource
  • * for super admin (all permissions)

Scope

Purpose: OAuth 2.0 / OIDC scopes

FieldTypeDescription
idUUIDPrimary key
nameStringScope identifier (e.g., "openid", "profile")
displayNameStringHuman-readable name
descriptionStringScope description for consent screen
isDefaultBooleanIncluded by default in token requests
isSystemBooleanSystem scope, cannot be modified
categoryString?Grouping category
createdAtDateTimeCreation timestamp
updatedAtDateTimeLast update timestamp

Standard OIDC Scopes:

  • openid: Required for OIDC (triggers ID token)
  • profile: User profile claims (name, picture, etc.)
  • email: Email address
  • address: Physical address
  • phone: Phone number

JWK

Purpose: JWT signing keys with rotation support

FieldTypeDescription
idUUIDPrimary key
kidStringKey ID (included in JWT header)
algStringAlgorithm: "EdDSA" or "RS256"
publicKeyStringPEM-encoded public key
privateKeyStringPEM-encoded private key (encrypted at rest)
isActiveBooleanCurrently used for signing
createdAtDateTimeCreation timestamp
updatedAtDateTimeLast update timestamp

Key Rotation:

  • New keys created every JWKS_ROTATE_DAYS (default: 30 days)
  • Old keys kept active for verification (grace period)
  • Deactivated keys retained for audit/debugging

Tenant-Scoped Entities

Organisation

Purpose: Root tenant entity

FieldTypeDescription
idUUIDPrimary key
nameStringOrganisation name (unique)
slugStringURL-friendly identifier (unique)
emailStringPrimary contact email (unique)
phoneString?Contact phone number
websiteString?Organisation website
ownerIdUUID?User ID of organisation owner
statusEnumtrial, active, suspended, cancelled
allowedCallbackUrlsJSON?Allowed OAuth callback URLs
allowedLogoutUrlsJSON?Allowed post-logout redirect URLs
allowedOriginsJSON?CORS allowed origins
sessionLifetimeIntegerSession duration in seconds (default: 3600)
sessionIdleTimeoutIntegerIdle timeout in seconds (default: 1800)
requireMfaBooleanEnforce MFA for all users
allowedMfaMethodsJSON?Allowed MFA methods (e.g., ["totp", "sms"])
passwordPolicyJSON?Password requirements (minLength, uppercase, etc.)
tokenLifetimePolicyJSON?Custom token lifetimes
brandingJSON?UI customization (logo, colors, etc.)
metadataJSON?Custom metadata
createdAtDateTimeCreation timestamp
updatedAtDateTimeLast update timestamp
deletedAtDateTime?Soft delete timestamp

Relations:

  • owner: One-to-one with User
  • users: One-to-many with User
  • teams: One-to-many with Team
  • roles: One-to-many with Role
  • clients: One-to-many with Client
  • sessions: One-to-many with Session
  • tokens: One-to-many with Token
  • auditLogs: One-to-many with AuditLog

User

Purpose: User accounts

FieldTypeDescription
idUUIDPrimary key
organisationIdUUIDParent organisation
firstNameStringFirst name
lastNameStringLast name
middleNameString?Middle name
nameStringFull name (computed from first + last)
emailStringEmail address (unique globally)
emailVerifiedAtDateTime?Email verification timestamp
phoneString?Phone number
phoneVerifiedAtDateTime?Phone verification timestamp
passwordString?Argon2id hash (null for SSO users)
profilePhotoPathString?Profile photo storage path
externalIdString?ID from external identity provider
identityProviderString"local", "google", "saml", etc. (default: "local")
mfaEnabledBooleanMFA enrollment status
mfaMethodsJSON?Enabled MFA methods
totpSecretString?TOTP secret (encrypted)
backupCodesJSON?MFA backup codes (hashed)
lastLoginAtDateTime?Last successful login
lastLoginIpString?IP address of last login
loginCountIntegerTotal login count
blockedAtDateTime?Account blocked timestamp
blockedReasonString?Reason for blocking
lockedAtDateTime?Account locked timestamp (failed logins)
metadataJSON?Custom metadata
createdAtDateTimeCreation timestamp
updatedAtDateTimeLast update timestamp
deletedAtDateTime?Soft delete timestamp

Relations:

  • organisation: Many-to-one with Organisation
  • roles: Many-to-many with Role
  • teams: Many-to-many with Team
  • sessions: One-to-many with Session
  • tokens: One-to-many with Token
  • refreshTokens: One-to-many with RefreshToken
  • consents: One-to-many with Consent

Unique Constraints:

  • email globally unique
  • [organisationId, email] composite unique

Role

Purpose: RBAC roles

FieldTypeDescription
idUUIDPrimary key
organisationIdUUIDParent organisation
nameStringRole name (e.g., "Admin")
slugStringMachine identifier (e.g., "admin")
descriptionString?Role description
isDefaultBooleanAssigned to new users by default
createdAtDateTimeCreation timestamp
updatedAtDateTimeLast update timestamp

Relations:

  • organisation: Many-to-one with Organisation
  • permissions: Many-to-many with Permission
  • users: Many-to-many with User
  • invitations: One-to-many with Invitation

Unique Constraints:

  • [organisationId, slug] composite unique

Team

Purpose: User grouping

FieldTypeDescription
idUUIDPrimary key
organisationIdUUIDParent organisation
nameStringTeam name
slugStringMachine identifier
descriptionString?Team description
createdAtDateTimeCreation timestamp
updatedAtDateTimeLast update timestamp

Relations:

  • organisation: Many-to-one with Organisation
  • members: Many-to-many with User

Unique Constraints:

  • [organisationId, slug] composite unique

Client

Purpose: OAuth 2.0 / OIDC client applications

FieldTypeDescription
idUUIDPrimary key
organisationIdUUIDParent organisation
nameStringClient name
descriptionString?Client description
clientIdStringPublic client identifier (globally unique)
clientSecretString?Argon2id hash (null for public clients)
clientTypeEnumconfidential or public
grantTypesJSONAllowed grant types (array)
redirectUrisJSONAllowed redirect URIs (array)
allowedOriginsJSON?CORS allowed origins (array)
scopesJSONAllowed scopes (array)
requirePkceBooleanRequire PKCE (Proof Key for Code Exchange)
requireConsentBooleanShow consent screen
tokenEndpointAuthMethodEnumclient_secret_basic, client_secret_post, none
accessTokenLifetimeIntegerAccess token lifetime (seconds)
refreshTokenLifetimeIntegerRefresh token lifetime (seconds)
idTokenLifetimeIntegerID token lifetime (seconds)
logoUriString?Client logo URL
policyUriString?Privacy policy URL
tosUriString?Terms of service URL
isActiveBooleanClient is active
isFirstPartyBooleanTrusted first-party client (skip consent)
revokedBooleanClient has been revoked
createdAtDateTimeCreation timestamp
updatedAtDateTimeLast update timestamp
deletedAtDateTime?Soft delete timestamp

Relations:

  • organisation: Many-to-one with Organisation
  • tokens: One-to-many with Token
  • refreshTokens: One-to-many with RefreshToken
  • authorizationCodes: One-to-many with AuthorizationCode
  • consents: One-to-many with Consent

Grant Types:

  • authorization_code: Standard OAuth flow
  • refresh_token: Token refresh
  • client_credentials: Machine-to-machine (future)

Token

Purpose: Access tokens (JWT records)

FieldTypeDescription
idUUIDPrimary key
jtiStringJWT ID (unique, included in JWT)
clientIdUUIDIssuing client
userIdUUID?Resource owner (null for client credentials)
organisationIdUUIDParent organisation
tokenTypeString"Bearer"
scopesJSONGranted scopes (array)
audienceString?Token audience
issuedAtDateTimeToken issuance time
expiresAtDateTimeToken expiration time
revokedAtDateTime?Manual revocation timestamp
lastUsedAtDateTime?Last time token was used
ipAddressString?IP address at issuance
userAgentString?User agent at issuance
createdAtDateTimeCreation timestamp
updatedAtDateTimeLast update timestamp

Relations:

  • client: Many-to-one with Client
  • user: Many-to-one with User
  • organisation: Many-to-one with Organisation
  • refreshToken: One-to-one with RefreshToken

Indexes:

  • Unique on jti
  • Index on clientId, userId, organisationId, expiresAt

RefreshToken

Purpose: Long-lived tokens for obtaining new access tokens

FieldTypeDescription
idUUIDPrimary key
tokenStringSHA-256 hash of refresh token (unique)
accessTokenIdUUIDAssociated access token
clientIdUUIDIssuing client
userIdUUIDResource owner
organisationIdUUIDParent organisation
scopesJSONGranted scopes (array)
expiresAtDateTimeToken expiration time
revokedAtDateTime?Revocation timestamp
familyIdUUIDToken family ID (rotation chain)
parentTokenIdUUID?Previous token in rotation chain
createdAtDateTimeCreation timestamp
updatedAtDateTimeLast update timestamp

Relations:

  • accessToken: One-to-one with Token
  • client: Many-to-one with Client
  • user: Many-to-one with User
  • organisation: Many-to-one with Organisation
  • parent: Self-relation (token family tree)
  • children: Self-relation (token family tree)

Token Family Pattern:

  • All tokens from same authorization have same familyId
  • Each rotation creates new token with current as parentTokenId
  • Reuse detection: If revoked token used → revoke entire family

AuthorizationCode

Purpose: OAuth authorization codes (short-lived, single-use)

FieldTypeDescription
idUUIDPrimary key
codeStringAuthorization code (unique, random)
clientIdUUIDRequesting client
userIdUUIDAuthorizing user
organisationIdUUIDParent organisation
redirectUriStringCallback URL
scopesJSONRequested scopes (array)
codeChallengeString?PKCE code challenge
codeChallengeMethodEnum?plain or S256
expiresAtDateTimeCode expiration (10 minutes)
revokedAtDateTime?Used/revoked timestamp
createdAtDateTimeCreation timestamp
updatedAtDateTimeLast update timestamp

Relations:

  • client: Many-to-one with Client
  • user: Many-to-one with User
  • organisation: Many-to-one with Organisation

Lifecycle:

  • Created during /oauth2/authorize
  • Exchanged once at /oauth2/token
  • Deleted or revoked after exchange

Purpose: User consent to grant client access

FieldTypeDescription
idUUIDPrimary key
userIdUUIDConsenting user
clientIdUUIDClient being authorized
organisationIdUUIDParent organisation
scopesJSONGranted scopes (array)
expiresAtDateTime?Consent expiration (null = permanent)
revokedAtDateTime?User revoked consent
createdAtDateTimeCreation timestamp
updatedAtDateTimeLast update timestamp

Relations:

  • user: Many-to-one with User
  • client: Many-to-one with Client
  • organisation: Many-to-one with Organisation

Unique Constraints:

  • [userId, clientId] composite unique

Session

Purpose: Admin UI sessions (cookie-based)

FieldTypeDescription
idUUIDPrimary key
userIdUUIDSession owner
organisationIdUUIDParent organisation
sessionTokenStringSHA-256 hash (unique)
ipAddressStringIP address at session creation
userAgentStringBrowser user agent
lastActivityAtDateTimeLast request timestamp
expiresAtDateTimeSession expiration
createdAtDateTimeCreation timestamp
updatedAtDateTimeLast update timestamp

Relations:

  • user: Many-to-one with User
  • organisation: Many-to-one with Organisation

Lifecycle:

  • Created at login
  • Updated on each request (lastActivityAt)
  • Deleted at logout or expiration

AuditLog

Purpose: Audit trail for compliance

FieldTypeDescription
idUUIDPrimary key
organisationIdUUIDParent organisation
userIdUUID?Actor (null for system events)
clientIdUUID?Client if API request
eventTypeStringEvent type (e.g., "user.login")
eventCategoryEnumauth, user, client, permission, system
actionEnumcreate, read, update, delete, login, logout
resourceTypeString?Affected resource type
resourceIdUUID?Affected resource ID
ipAddressStringRequest IP address
userAgentStringRequest user agent
metadataJSON?Additional event data
successBooleanEvent success status
errorMessageString?Error message if failed
createdAtDateTimeEvent timestamp

Relations:

  • organisation: Many-to-one with Organisation
  • user: Many-to-one with User
  • client: Many-to-one with Client

Indexes:

  • Index on organisationId, userId, clientId, eventType, createdAt

Invitation

Purpose: User invitations

FieldTypeDescription
idUUIDPrimary key
organisationIdUUIDParent organisation
emailStringInvitee email
roleIdUUIDAssigned role
teamIdsJSON?Assigned teams (array of UUIDs)
tokenStringInvitation token (unique, random)
invitedByIdUUID?Inviting user
acceptedAtDateTime?Acceptance timestamp
expiresAtDateTimeInvitation expiration (7 days)
createdAtDateTimeCreation timestamp
updatedAtDateTimeLast update timestamp

Relations:

  • organisation: Many-to-one with Organisation
  • role: Many-to-one with Role
  • invitedBy: Many-to-one with User

ApiKey

Purpose: API key authentication

FieldTypeDescription
idUUIDPrimary key
organisationIdUUIDParent organisation
nameStringKey name/description
keyPrefixStringFirst 8 chars (for display)
keyHashStringArgon2id hash of full key
scopesJSONAllowed scopes (array)
lastUsedAtDateTime?Last usage timestamp
expiresAtDateTime?Key expiration
revokedAtDateTime?Revocation timestamp
createdAtDateTimeCreation timestamp
updatedAtDateTimeLast update timestamp

Relations:

  • organisation: Many-to-one with Organisation

Key Format:

cerb_live_<prefix>_<random>

WebhookEndpoint

Purpose: Webhook event delivery

FieldTypeDescription
idUUIDPrimary key
organisationIdUUIDParent organisation
clientIdUUID?Associated client (optional)
urlStringWebhook endpoint URL
secretEncryptedStringAES-256-GCM encrypted signing secret
eventsJSONSubscribed events (array)
isActiveBooleanWebhook is active
lastTriggeredAtDateTime?Last delivery attempt
failureCountIntegerConsecutive failure count
createdAtDateTimeCreation timestamp
updatedAtDateTimeLast update timestamp

Relations:

  • organisation: Many-to-one with Organisation
  • client: Many-to-one with Client

EmailVerificationToken

Purpose: Email verification tokens

FieldTypeDescription
idUUIDPrimary key
userIdUUIDUser verifying email
tokenStringVerification token (unique, random)
expiresAtDateTimeToken expiration (24 hours)
consumedAtDateTime?Verification timestamp
createdAtDateTimeCreation timestamp

Relations:

  • user: Many-to-one with User

PasswordResetToken

Purpose: Password reset tokens

FieldTypeDescription
idUUIDPrimary key
userIdUUIDUser resetting password
tokenStringReset token (unique, random)
expiresAtDateTimeToken expiration (1 hour)
consumedAtDateTime?Reset completion timestamp
createdAtDateTimeCreation timestamp

Relations:

  • user: Many-to-one with User

SamlConnection

Purpose: SAML SSO configuration

FieldTypeDescription
idUUIDPrimary key
organisationIdUUIDParent organisation
nameStringConnection name
enabledBooleanConnection is active
idpEntityIdStringIdP entity identifier
idpSsoUrlStringIdP SSO URL
idpCertificateStringIdP x509 certificate (PEM)
spEntityIdStringService Provider entity ID
spAcsUrlStringAssertion Consumer Service URL
attributeMappingJSONSAML attribute to user field mapping
domainsJSONEmail domains for this connection (array)
createdAtDateTimeCreation timestamp
updatedAtDateTimeLast update timestamp

Relations:

  • organisation: Many-to-one with Organisation

Released under the MIT License.