Skip to content

Ent Schema Reference

Reference for the SystemForge Ent schemas in identity/ent/schema. Table names come from each schema's entsql annotation; every table uses the sf_ prefix. Columns marked "FK" are foreign keys created from the schema's edges.

Identity Schemas

Every actor is a Principal. Its type selects a one-to-one extension: Human for people, ServicePrincipal for backend services, Application for OAuth client applications, and Agent for AI agents. Credentials, upstream login identities, and organization memberships all belong to the principal.

Principal

Table: sf_principals

Principal is the unified identity root representing any type of actor: human, application, agent, or service.

Field Type Constraints Description
id UUID PK, immutable Primary key
created_at time immutable Creation time
updated_at time — Last modification time
type enum immutable Type of principal: human, application, agent, service
identifier string unique, not empty Unique identifier (email, client_id, service@org)
display_name string not empty Human-readable display name
active bool default: true Whether the principal is active
capabilities JSON — Principal capabilities (can_access_ui, can_delegate, etc.)
allowed_scopes JSON — Scopes this principal can request
metadata JSON nullable Custom metadata
organization_id UUID FK → Organization, nullable Organization this principal belongs to

type values: human, application, agent, service

Edges:

  • organization → Organization (M2O)
  • human → Human (O2O)
  • application → Application (O2O)
  • agent → Agent (O2O)
  • service_principal → ServicePrincipal (O2O)
  • credentials → Credential (O2M)
  • external_identities → ExternalIdentity (O2M)
  • principal_tokens → PrincipalToken (O2M)
  • principal_memberships → PrincipalMembership (O2M)
  • owned_organizations → Organization (O2M)
  • owned_oauth_apps → OAuthApp (O2M)
  • oauth_consents → OAuthConsent (O2M)
  • sent_invites → Invite (O2M)
  • owned_listings → Listing (O2M)
  • purchased_licenses → License (O2M)
  • seat_assignments → SeatAssignment (O2M)
  • assigned_seats → SeatAssignment (O2M)

Human

Table: sf_humans

Human-specific principal data. This is a one-to-one extension of Principal where type="human".

Field Type Constraints Description
id UUID PK, immutable Primary key
created_at time immutable Creation time
updated_at time — Last modification time
email string unique, not empty Primary email address
given_name string nullable First/given name
family_name string nullable Last/family name
avatar_url string nullable Profile picture URL
locale string nullable, default: en Preferred locale (e.g., en-US)
timezone string nullable, default: UTC Preferred timezone (e.g., America/Los_Angeles)
is_platform_admin bool default: false Cross-organization admin access
last_login_at time nullable Last successful login timestamp
email_verified_at time nullable When email was verified
principal_id UUID FK → Principal, unique, immutable Reference to parent Principal

Edges:

  • principal → Principal (O2O)

ServicePrincipal

Table: sf_service_principals

Backend service-specific principal data. This is a one-to-one extension of Principal where type="service".

Field Type Constraints Description
id UUID PK, immutable Primary key
created_at time immutable Creation time
updated_at time — Last modification time
service_type string not empty Type of service (e.g., backend, worker, gateway)
description string nullable Service description
last_used_at time nullable Last time this service account was used
allowed_ips JSON — IP addresses/CIDRs allowed to use this service account
principal_id UUID FK → Principal, unique, immutable Reference to parent Principal
created_by UUID FK → Principal, nullable Principal who created this service account

Edges:

  • principal → Principal (O2O)
  • creator → Principal (O2O)

Application

Table: sf_applications

OAuth application-specific principal data. This is a one-to-one extension of Principal where type="application".

Field Type Constraints Description
id UUID PK, immutable Primary key
created_at time immutable Creation time
updated_at time — Last modification time
client_id string unique, not empty, immutable Public OAuth client identifier
description string nullable Application description
logo_url string nullable Application logo URL
app_type enum default: web web=confidential, spa/native=public+PKCE, machine=client_credentials
redirect_uris JSON — Allowed redirect URIs
allowed_grants JSON — Allowed grant types
allowed_response_types JSON — Allowed response types
access_token_ttl int default: 900 Access token TTL in seconds (default 15 min)
refresh_token_ttl int default: 604800 Refresh token TTL in seconds (default 7 days)
refresh_token_rotation bool default: true Rotate refresh tokens on use
first_party bool default: false First-party apps skip consent screen
public bool default: false Public clients cannot keep secrets
principal_id UUID FK → Principal, unique, immutable Reference to parent Principal

app_type values: web, spa, native, machine

Edges:

  • principal → Principal (O2O)
  • issued_tokens → PrincipalToken (O2M)

Agent

Table: sf_agents

AI agent-specific principal data. This is a one-to-one extension of Principal where type="agent".

Field Type Constraints Description
id UUID PK, immutable Primary key
created_at time immutable Creation time
updated_at time — Last modification time
model_id string not empty AI model identifier (e.g., claude-3-opus)
version string nullable Agent version
capability_constraints JSON — Capabilities this agent is constrained to
resource_constraints JSON — Resources this agent can access
max_token_lifetime int default: 3600 Maximum token lifetime in seconds (default 1 hour)
session_id string nullable Current session identifier
requires_confirmation bool default: true Whether actions require human confirmation
delegating_principal_id UUID FK → Principal, nullable Principal who delegated authority to this agent
principal_id UUID FK → Principal, unique, immutable Reference to parent Principal

Edges:

  • principal → Principal (O2O)
  • delegating_principal → Principal (O2O)

Credential

Table: sf_credentials

Unified credentials. Credentials can be passwords, API keys, keypairs, WebAuthn credentials, or TOTP secrets.

Field Type Constraints Description
id UUID PK, immutable Primary key
type enum — Type of credential
identifier string nullable Unique identifier for this credential (e.g., key prefix)
secret_hash string nullable, sensitive Hashed secret (Argon2id for passwords/secrets, SHA256 for tokens)
public_key string nullable Public key (PEM format) for keypair credentials
key_algorithm string nullable Key algorithm (RS256, ES256, etc.)
key_id string unique, nullable Key ID for keypair credentials (used in JWT kid header)
webauthn_credential_id bytes nullable WebAuthn credential ID
webauthn_public_key bytes nullable WebAuthn public key (COSE format)
webauthn_aaguid string nullable WebAuthn authenticator AAGUID
webauthn_sign_count uint32 nullable, default: 0 WebAuthn signature counter
scopes JSON — Scopes this credential grants
active bool default: true Whether this credential is active
expires_at time nullable When this credential expires (nil = never)
revoked bool default: false Whether this credential has been revoked
revoked_at time nullable When this credential was revoked
revoked_reason string nullable Reason for revocation
last_used_at time nullable Last time this credential was used
last_used_ip string nullable IP address of last use
name string nullable Human-readable name for this credential
metadata JSON nullable Custom metadata
created_at time immutable Creation time
updated_at time — Last modification time
principal_id UUID FK → Principal Principal that owns this credential

type values: password, api_key, keypair, webauthn, totp, client_secret

Unique constraint: (type, identifier)

Edges:

  • principal → Principal (M2O)

ExternalIdentity

Table: sf_external_identities

Links a Principal to an upstream login identity (e.g. a GitHub or Google account). The (provider, subject) pair is the stable key used to find the principal on every social login; email is recorded for information and verified-email linking only.

Field Type Constraints Description
id UUID PK, immutable Primary key
created_at time immutable Creation time
updated_at time — Last modification time
provider string not empty, immutable Upstream provider name (e.g., github, google)
subject string not empty, immutable Stable user ID at the provider (GitHub numeric id, Google sub)
email string nullable Email last reported by the provider
email_verified bool default: false Whether the provider asserted the email is verified
last_login_at time nullable Last successful login through this identity
principal_id UUID FK → Principal Principal this upstream identity is linked to

Unique constraint: (provider, subject)

Edges:

  • principal → Principal (M2O)

Organization

Table: sf_organizations

Field Type Constraints Description
id UUID PK, immutable Primary key
created_at time immutable Creation time
updated_at time — Last modification time
name string not empty
slug string unique, not empty URL-safe identifier
org_type enum default: team personal=user namespace, team=shared org, enterprise=large org
logo_url string nullable
description string nullable Organization description
website_url string nullable Organization website
settings JSON nullable App-specific configuration
active bool default: true
owner_principal_id UUID FK → Principal, nullable For personal orgs, the principal who owns this namespace

org_type values: personal, team, enterprise

Edges:

  • oauth_apps → OAuthApp (O2M)
  • principals → Principal (O2M)
  • principal_memberships → PrincipalMembership (O2M)
  • owner → Principal (M2O)
  • invites → Invite (O2M)
  • listings → Listing (O2M)
  • licenses → License (O2M)
  • subscription → Subscription (O2O)

PrincipalMembership

Table: sf_principal_memberships

Principal-organization memberships for every principal type, with an app-defined role and an active flag for soft deactivation.

Field Type Constraints Description
id UUID PK, immutable Primary key
created_at time immutable Creation time
updated_at time — Last modification time
role string not empty App-defined role (e.g., owner, admin, member)
permissions JSON nullable Optional fine-grained permissions
active bool default: true Whether this membership is active
organization_id UUID FK → Organization
principal_id UUID FK → Principal

Unique constraint: (principal_id, organization_id)

Edges:

  • principal → Principal (M2O)
  • organization → Organization (M2O)

Invite

Table: sf_invites

Organization invitations. Invites allow existing members to invite new users to join an organization.

Field Type Constraints Description
id UUID PK, immutable Primary key
created_at time immutable Creation time
updated_at time — Last modification time
email string not empty Email address of the invitee
role string not empty, default: member Role to assign when invite is accepted
token string unique, not empty, sensitive Secure token for invite URL
status enum default: pending Current status of the invite
message string nullable Personal message from inviter
expires_at time — When this invite expires
accepted_at time nullable When the invite was accepted
accepted_by_principal_id UUID nullable Principal who accepted the invite
resend_count int default: 0 Number of times invite was resent
last_sent_at time — When invite was last sent/resent
organization_id UUID FK → Organization Organization the invite is for
inviter_principal_id UUID FK → Principal Principal who created the invite

status values: pending, accepted, declined, expired, revoked

Edges:

  • organization → Organization (M2O)
  • inviter → Principal (M2O)

Session and Token Schemas

PrincipalToken

Table: sf_principal_tokens

Holds OAuth 2.0 access and refresh tokens for principals. This replaces OAuthToken with principal-centric token management.

Field Type Constraints Description
id UUID PK, immutable Primary key
principal_type enum — Type of the principal (denormalized for fast lookup)
access_token_signature string unique SHA256 signature of access token
refresh_token_signature string unique, nullable SHA256 signature of refresh token
family_id UUID — Token family for refresh rotation
scopes JSON — Granted scopes
audience JSON — Token audience
capabilities JSON — Capabilities granted to this token
delegation_chain JSON — Chain of principal IDs in delegation (root to current)
dpop_jkt string nullable DPoP JWK thumbprint for proof-of-possession
session_id string nullable BFF session ID if applicable
request_data string nullable Serialized Fosite request for introspection
access_expires_at time — When access token expires
refresh_expires_at time nullable When refresh token expires
revoked bool default: false
revoked_at time nullable
revoked_reason string nullable
client_ip string nullable
user_agent string nullable
last_used_at time nullable
created_at time immutable Creation time
issued_by_app_id UUID FK → Application, nullable Application principal that issued this token
principal_id UUID FK → Principal Principal this token represents
parent_token_id UUID FK → PrincipalToken, nullable Parent token ID (for delegated tokens)

principal_type values: human, application, agent, service

Edges:

  • principal → Principal (M2O)
  • issued_by_app → Application (M2O)
  • child_tokens → PrincipalToken (O2O)

LoginSession

Table: sf_login_sessions

Holds SystemAuth browser login sessions (the __Host-sf_login cookie). Only a SHA-256 hash of the opaque session token is stored.

Field Type Constraints Description
id UUID PK, immutable Primary key
token_hash string unique, immutable Hex SHA-256 of the session token; the token itself is never stored
principal_id UUID immutable Authenticated principal
provider string nullable, immutable Upstream provider used to sign in
created_at time immutable When the session was established
expires_at time immutable Absolute session expiry

LoginState

Table: sf_login_states

Holds in-flight upstream OAuth logins started by SystemAuth social login. Rows are single-use and short-lived; only a SHA-256 hash of the OAuth state value is stored.

Field Type Constraints Description
id UUID PK, immutable Primary key
state_hash string unique, immutable Hex SHA-256 of the OAuth state value
provider string immutable Upstream provider the flow was started for
redirect_url string nullable, immutable Validated post-login destination
nonce string nullable, immutable, sensitive OpenID Connect nonce
pkce_verifier string nullable, immutable, sensitive PKCE code verifier for the upstream token exchange
expires_at time immutable When the in-flight login expires

ConsentGrant

Table: sf_consent_grants

Records one scope a principal granted to an OAuth client on the SystemAuth consent page. One row per (principal, client, scope) keeps concurrent grants race-free without read-modify-write.

Field Type Constraints Description
id UUID PK, immutable Primary key
principal_id string immutable Principal that granted consent
client_id string immutable OAuth client ID that received consent
scope string immutable Granted scope
granted_at time immutable

Unique constraint: (principal_id, client_id, scope)

OAuth Schemas

Tables used by the embedded OAuth 2.0 / OpenID Connect server. Tokens and authorization codes record the authenticated principal in subject; it is empty for client_credentials tokens.

OAuthApp

Table: sf_oauth_apps

OAuth 2.0 applications/clients.

Field Type Constraints Description
id UUID PK, immutable Primary key
client_id string unique, not empty, immutable Public client identifier
name string not empty Human-readable app name
description string nullable
logo_url string nullable
app_type enum default: web web=confidential, spa/native=public+PKCE, service/machine=client_credentials
redirect_uris JSON — Allowed redirect URIs
allowed_scopes JSON — Scopes this app can request
allowed_grants JSON — Allowed grant types
allowed_response_types JSON — Allowed response types
access_token_ttl int default: 900 Access token TTL in seconds (default 15 min)
refresh_token_ttl int default: 604800 Refresh token TTL in seconds (default 7 days)
refresh_token_rotation bool default: true Rotate refresh tokens on use
first_party bool default: false First-party apps skip consent screen
public bool default: false Public clients cannot keep secrets
active bool default: true
revoked_at time nullable
metadata JSON nullable Custom metadata
created_at time immutable Creation time
updated_at time — Last modification time
organization_id UUID FK → Organization, nullable Organization scope (optional)
owner_id UUID FK → Principal Principal that owns this app

app_type values: web, spa, native, service, machine

Edges:

  • owner → Principal (M2O)
  • organization → Organization (M2O)
  • secrets → OAuthAppSecret (O2M)
  • tokens → OAuthToken (O2M)
  • auth_codes → OAuthAuthCode (O2M)
  • consents → OAuthConsent (O2M)

OAuthAppSecret

Table: sf_oauth_app_secrets

Holds client secrets for OAuth apps. Multiple secrets can exist for rotation purposes.

Field Type Constraints Description
id UUID PK, immutable Primary key
secret_hash string not empty, sensitive Argon2id hash of the secret
secret_prefix string — First few chars for identification
expires_at time nullable When this secret expires
last_used_at time nullable
revoked bool default: false
revoked_at time nullable
created_at time immutable Creation time
app_id UUID FK → OAuthApp OAuth app this secret belongs to

Edges:

  • app → OAuthApp (M2O)

OAuthToken

Table: sf_oauth_tokens

Holds OAuth 2.0 access and refresh tokens.

Field Type Constraints Description
id UUID PK, immutable Primary key
subject string nullable Authenticated subject (principal ID); empty for client_credentials
access_token_signature string unique SHA256 signature of access token
refresh_token_signature string unique, nullable SHA256 signature of refresh token
family_id UUID — Token family for refresh rotation
scopes JSON — Granted scopes
audience JSON — Token audience
session_id string nullable BFF session ID if applicable
request_data string nullable Serialized Fosite request for introspection
access_expires_at time — When access token expires
refresh_expires_at time nullable When refresh token expires
revoked bool default: false
revoked_at time nullable
revoked_reason string nullable
client_ip string nullable
user_agent string nullable
last_used_at time nullable
created_at time immutable Creation time
app_id UUID FK → OAuthApp OAuth app that issued this token

Edges:

  • app → OAuthApp (M2O)

OAuthAuthCode

Table: sf_oauth_auth_codes

Holds OAuth 2.0 authorization codes.

Field Type Constraints Description
id UUID PK, immutable Primary key
code_signature string unique SHA256 signature of the authorization code
subject string nullable Authenticated subject (principal ID) the code was issued for
code_challenge string nullable PKCE code challenge
code_challenge_method string nullable, default: S256 PKCE challenge method (S256)
redirect_uri string — Redirect URI from authorization request
scopes JSON — Requested scopes
state string nullable State parameter from request
nonce string nullable OIDC nonce
request_data string nullable Serialized Fosite request
expires_at time — When this code expires (short-lived, ~10 min)
used bool default: false Whether code has been exchanged
used_at time nullable
client_ip string nullable
user_agent string nullable
created_at time immutable Creation time
app_id UUID FK → OAuthApp OAuth app this code was issued to

Edges:

  • app → OAuthApp (M2O)

OAuthConsent

Table: sf_oauth_consents

Tracks user consent for OAuth apps. First-party apps skip consent; third-party apps require explicit approval.

Field Type Constraints Description
id UUID PK, immutable Primary key
scopes JSON — Scopes the user consented to
granted bool default: true Whether consent is currently active
granted_at time — When consent was first granted
last_used_at time nullable Last time this consent was used for authorization
revoked bool default: false
revoked_at time nullable
revoked_reason string nullable user_initiated, admin_revoked, app_deleted, etc.
created_at time immutable Creation time
updated_at time — Last modification time
app_id UUID FK → OAuthApp OAuth app that received consent
principal_id UUID FK → Principal Principal who granted consent

Unique constraint: (principal_id, app_id)

Edges:

  • principal → Principal (M2O)
  • app → OAuthApp (M2O)

Marketplace Schemas

Listing

Table: sf_listings

A marketplace product listing.

Field Type Constraints Description
id UUID PK, immutable Primary key
product_type string not empty Type of product: course, dashboard_template, etc.
product_id UUID nullable Reference to the actual product (optional for drafts)
title string not empty
description string nullable
pricing_model enum default: free
price_cents int64 default: 0 Price in cents (0 for free)
currency string default: USD ISO 4217 currency code
status enum default: draft
metadata JSON nullable App-specific metadata
created_at time immutable Creation time
updated_at time — Last modification time
published_at time nullable When the listing was published
creator_org_id UUID FK → Organization Organization that created this listing
owner_id UUID FK → Principal Principal who owns this listing

pricing_model values: free, one_time, subscription, per_seat

status values: draft, pending_review, published, archived

Edges:

  • creator_org → Organization (M2O)
  • owner → Principal (M2O)
  • licenses → License (O2M)

License

Table: sf_licenses

A marketplace license entitlement.

Field Type Constraints Description
id UUID PK, immutable Primary key
license_type enum default: unlimited
seats int nullable Number of seats (nil for unlimited)
used_seats int default: 0 Currently assigned seats
valid_from time — When the license becomes active
valid_until time nullable When the license expires (nil for perpetual)
stripe_subscription_id string nullable Stripe subscription ID for recurring licenses
created_at time immutable Creation time
updated_at time — Last modification time
listing_id UUID FK → Listing The marketplace listing this license grants access to
organization_id UUID FK → Organization The organization that holds this license
purchased_by UUID FK → Principal Principal who purchased this license

license_type values: seat_based, team, unlimited

Unique constraint: (listing_id, organization_id)

Edges:

  • listing → Listing (M2O)
  • organization → Organization (M2O)
  • purchaser → Principal (M2O)
  • seat_assignments → SeatAssignment (O2M)

Subscription

Table: sf_subscriptions

A platform subscription.

Field Type Constraints Description
id UUID PK, immutable Primary key
plan_tier string not empty, default: free Plan name: free, starter, pro, enterprise
status enum default: active
current_period_start time —
current_period_end time —
stripe_subscription_id string unique, nullable
stripe_customer_id string nullable
cancel_at_period_end bool default: false
created_at time immutable Creation time
updated_at time — Last modification time
organization_id UUID FK → Organization, unique The subscribing organization

status values: active, trialing, past_due, canceled, unpaid

Edges:

  • organization → Organization (O2O)

SeatAssignment

Table: sf_seat_assignments

A license seat assignment.

Field Type Constraints Description
id UUID PK, immutable Primary key
assigned_at time immutable
license_id UUID FK → License The license this seat belongs to
principal_id UUID FK → Principal The principal assigned to this seat
assigned_by UUID FK → Principal Principal who made this assignment

Unique constraint: (license_id, principal_id)

Edges:

  • license → License (M2O)
  • principal → Principal (M2O)
  • assigner → Principal (M2O)