Skip to content

Organization Sync Prisma Schema

Full Prisma schema for syncing organization, application, and SSO provider data from AuthVital.

The SDK expects this schema structure. Add it to your schema.prisma:

Organization Model

// =============================================================================
// AuthVital Organization Sync Models
// =============================================================================
// These models mirror organization-level data from AuthVital.
// Table names use "av_" prefix to distinguish from your app's tables.
// =============================================================================

model Organization {
  // ═══════════════════════════════════════════════════════════════════════════
  // CORE IDENTITY
  // ═══════════════════════════════════════════════════════════════════════════
  id                      String    @id                           // AuthVital tenant ID
  name                    String                                  // Display name
  slug                    String    @unique                       // URL-safe identifier

  // ═══════════════════════════════════════════════════════════════════════════
  // SUBSCRIPTION & BILLING
  // ═══════════════════════════════════════════════════════════════════════════
  plan                    String    @default("free")              // free, starter, pro, enterprise

  // ═══════════════════════════════════════════════════════════════════════════
  // SETTINGS
  // ═══════════════════════════════════════════════════════════════════════════
  allowSignups            Boolean   @default(true) @map("allow_signups")      // Self-signup enabled?
  requireMfa              Boolean   @default(false) @map("require_mfa")       // MFA required for all users?
  allowedEmailDomains     String[]  @default([]) @map("allowed_email_domains") // Restrict signups to domains
  sessionLifetimeMinutes  Int       @default(480) @map("session_lifetime_minutes") // Session duration
  passwordPolicy          String    @default("standard") @map("password_policy")   // standard, strict

  // ═══════════════════════════════════════════════════════════════════════════
  // STATUS
  // ═══════════════════════════════════════════════════════════════════════════
  status                  String    @default("active")            // active, suspended, deleted
  suspendedAt             DateTime? @map("suspended_at")          // When suspended (if applicable)
  suspendedBySub          String?   @map("suspended_by_sub")      // Who suspended (subject ID)
  suspendedReason         String?   @map("suspended_reason")      // Why suspended

  // ═══════════════════════════════════════════════════════════════════════════
  // AUDIT TRAIL
  // ═══════════════════════════════════════════════════════════════════════════
  createdBySub            String?   @map("created_by_sub")        // Who created (subject ID)

  // ═══════════════════════════════════════════════════════════════════════════
  // SYNC METADATA
  // ═══════════════════════════════════════════════════════════════════════════
  syncedAt                DateTime  @default(now()) @map("synced_at")         // Last sync timestamp
  createdAt               DateTime  @default(now()) @map("created_at")        // Record creation time
  updatedAt               DateTime  @updatedAt @map("updated_at")             // Last update time

  // ═══════════════════════════════════════════════════════════════════════════
  // RELATIONSHIPS
  // ═══════════════════════════════════════════════════════════════════════════
  applications            Application[]
  ssoProviders            SsoProvider[]

  // ═══════════════════════════════════════════════════════════════════════════
  // INDEXES
  // ═══════════════════════════════════════════════════════════════════════════
  @@index([slug])
  @@index([plan])
  @@index([status])

  // ═══════════════════════════════════════════════════════════════════════════
  // TABLE NAME - Uses "av_" prefix
  // ═══════════════════════════════════════════════════════════════════════════
  @@map("av_organizations")
}

Application Model

model Application {
  // ═══════════════════════════════════════════════════════════════════════════
  // CORE IDENTITY
  // ═══════════════════════════════════════════════════════════════════════════
  id                        String    @id                           // AuthVital application ID
  organizationId            String    @map("organization_id")       // Parent organization
  organization              Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)

  name                      String                                  // Display name
  description               String?                                 // Optional description
  clientId                  String    @unique @map("client_id")     // OAuth client ID
  applicationType           String    @map("application_type")      // web, spa, native, machine

  // ═══════════════════════════════════════════════════════════════════════════
  // OAUTH CONFIGURATION
  // ═══════════════════════════════════════════════════════════════════════════
  redirectUris              String[]  @default([]) @map("redirect_uris")           // Allowed redirect URIs
  postLogoutRedirectUris    String[]  @default([]) @map("post_logout_redirect_uris") // Post-logout URIs
  allowedScopes             String[]  @default([]) @map("allowed_scopes")          // Permitted scopes
  grantTypes                String[]  @default([]) @map("grant_types")             // authorization_code, etc.
  tokenEndpointAuthMethod   String    @default("client_secret_basic") @map("token_endpoint_auth_method")

  // ═══════════════════════════════════════════════════════════════════════════
  // TOKEN CONFIGURATION
  // ═══════════════════════════════════════════════════════════════════════════
  accessTokenTtlSeconds     Int       @default(3600) @map("access_token_ttl_seconds")   // 1 hour default
  refreshTokenTtlSeconds    Int       @default(604800) @map("refresh_token_ttl_seconds") // 7 days default

  // ═══════════════════════════════════════════════════════════════════════════
  // STATUS
  // ═══════════════════════════════════════════════════════════════════════════
  isActive                  Boolean   @default(true) @map("is_active")

  // ═══════════════════════════════════════════════════════════════════════════
  // AUDIT TRAIL
  // ═══════════════════════════════════════════════════════════════════════════
  createdBySub              String?   @map("created_by_sub")        // Who created (subject ID)

  // ═══════════════════════════════════════════════════════════════════════════
  // SYNC METADATA
  // ═══════════════════════════════════════════════════════════════════════════
  syncedAt                  DateTime  @default(now()) @map("synced_at")
  createdAt                 DateTime  @default(now()) @map("created_at")
  updatedAt                 DateTime  @updatedAt @map("updated_at")

  // ═══════════════════════════════════════════════════════════════════════════
  // INDEXES
  // ═══════════════════════════════════════════════════════════════════════════
  @@index([organizationId])
  @@index([clientId])
  @@index([isActive])

  // ═══════════════════════════════════════════════════════════════════════════
  // TABLE NAME
  // ═══════════════════════════════════════════════════════════════════════════
  @@map("av_applications")
}

SSO Provider Model

model SsoProvider {
  // ═══════════════════════════════════════════════════════════════════════════
  // CORE IDENTITY
  // ═══════════════════════════════════════════════════════════════════════════
  id                  String    @id                           // AuthVital SSO provider ID
  organizationId      String    @map("organization_id")       // Parent organization
  organization        Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)

  providerType        String    @map("provider_type")         // google, microsoft, okta, saml, oidc
  displayName         String    @map("display_name")          // Display name for login UI

  // ═══════════════════════════════════════════════════════════════════════════
  // PROVIDER CONFIGURATION
  // ═══════════════════════════════════════════════════════════════════════════
  clientId            String?   @map("client_id")             // OAuth client ID (if applicable)
  issuer              String?                                 // OIDC issuer URL
  authorizationEndpoint String? @map("authorization_endpoint") // OAuth authorization URL
  tokenEndpoint       String?   @map("token_endpoint")        // OAuth token URL
  userinfoEndpoint    String?   @map("userinfo_endpoint")     // OIDC userinfo URL

  // ═══════════════════════════════════════════════════════════════════════════
  // DOMAIN CONFIGURATION
  // ═══════════════════════════════════════════════════════════════════════════
  domains             String[]  @default([])                  // Email domains that trigger this SSO

  // ═══════════════════════════════════════════════════════════════════════════
  // ATTRIBUTE MAPPING (stored as JSON)
  // ═══════════════════════════════════════════════════════════════════════════
  attributeMapping    Json      @default("{}") @map("attribute_mapping") // Map provider claims to AuthVital

  // ═══════════════════════════════════════════════════════════════════════════
  // STATUS
  // ═══════════════════════════════════════════════════════════════════════════
  isEnabled           Boolean   @default(true) @map("is_enabled")

  // ═══════════════════════════════════════════════════════════════════════════
  // AUDIT TRAIL
  // ═══════════════════════════════════════════════════════════════════════════
  createdBySub        String?   @map("created_by_sub")        // Who created (subject ID)

  // ═══════════════════════════════════════════════════════════════════════════
  // SYNC METADATA
  // ═══════════════════════════════════════════════════════════════════════════
  syncedAt            DateTime  @default(now()) @map("synced_at")
  createdAt           DateTime  @default(now()) @map("created_at")
  updatedAt           DateTime  @updatedAt @map("updated_at")

  // ═══════════════════════════════════════════════════════════════════════════
  // INDEXES
  // ═══════════════════════════════════════════════════════════════════════════
  @@index([organizationId])
  @@index([providerType])
  @@index([isEnabled])

  // ═══════════════════════════════════════════════════════════════════════════
  // UNIQUE CONSTRAINT (one provider type per org)
  // ═══════════════════════════════════════════════════════════════════════════
  @@unique([organizationId, providerType])

  // ═══════════════════════════════════════════════════════════════════════════
  // TABLE NAME
  // ═══════════════════════════════════════════════════════════════════════════
  @@map("av_sso_providers")
}

Optional: Audit Log Model

For compliance requirements, you may want to track all organization changes:

model OrganizationAuditLog {
  id              String   @id @default(cuid())
  organizationId  String   @map("organization_id")

  // ═══════════════════════════════════════════════════════════════════════════
  // EVENT DATA
  // ═══════════════════════════════════════════════════════════════════════════
  eventType       String   @map("event_type")        // tenant.created, application.updated, etc.
  entityType      String   @map("entity_type")       // organization, application, sso_provider
  entityId        String   @map("entity_id")         // ID of the affected entity

  // ═══════════════════════════════════════════════════════════════════════════
  // CHANGE DATA
  // ═══════════════════════════════════════════════════════════════════════════
  changedFields   String[] @default([]) @map("changed_fields")  // Fields that changed
  previousValues  Json     @default("{}") @map("previous_values") // Previous field values
  newValues       Json     @default("{}") @map("new_values")      // New field values

  // ═══════════════════════════════════════════════════════════════════════════
  // ACTOR
  // ═══════════════════════════════════════════════════════════════════════════
  changedBySub    String?  @map("changed_by_sub")    // Who made the change

  // ═══════════════════════════════════════════════════════════════════════════
  // TIMESTAMP
  // ═══════════════════════════════════════════════════════════════════════════
  createdAt       DateTime @default(now()) @map("created_at")

  // ═══════════════════════════════════════════════════════════════════════════
  // INDEXES
  // ═══════════════════════════════════════════════════════════════════════════
  @@index([organizationId])
  @@index([eventType])
  @@index([entityType, entityId])
  @@index([changedBySub])
  @@index([createdAt])

  @@map("av_organization_audit_logs")
}

Field Mapping Reference

How schema fields map to AuthVital webhook data:

Organization Fields

Schema Field Webhook Field Description
id tenant_id AuthVital tenant identifier
name name Display name
slug slug URL-safe identifier
plan plan Subscription plan
allowSignups settings.allow_signups Self-signup enabled
requireMfa settings.require_mfa MFA required for all
allowedEmailDomains settings.allowed_email_domains Domain restrictions
sessionLifetimeMinutes settings.session_lifetime_minutes Session duration
passwordPolicy settings.password_policy Password requirements
status Derived from event type active, suspended
createdBySub created_by_sub Creator subject ID

Application Fields

Schema Field Webhook Field Description
id application_id AuthVital app ID
organizationId tenant_id Parent tenant
name name Display name
description description App description
clientId client_id OAuth client ID
applicationType application_type web, spa, native, machine
redirectUris config.redirect_uris OAuth redirect URIs
allowedScopes config.allowed_scopes Permitted scopes
grantTypes config.grant_types OAuth grant types
accessTokenTtlSeconds config.access_token_ttl_seconds Token lifetime

SSO Provider Fields

Schema Field Webhook Field Description
id provider_id AuthVital provider ID
organizationId tenant_id Parent tenant
providerType provider_type google, okta, saml, etc.
displayName display_name Login UI label
clientId config.client_id OAuth client ID
domains config.domains Trigger domains
attributeMapping config.attribute_mapping Claim mapping
isEnabled is_enabled SSO active

Running Migrations

After adding the schema:

# Generate migration
npx prisma migrate dev --name add-organization-sync

# Generate Prisma client
npx prisma generate

Combine with Identity Sync

If you're using both Identity Sync and Organization Sync, you can add all models in a single migration:

npx prisma migrate dev --name add-authvital-sync