generator client { provider = "prisma-client-js" } datasource db { provider = "postgresql" url = env("DATABASE_URL") } enum UserRole { ADMIN USER } enum OrganizationType { COMPANY SCHOOL GOVERNMENT LAB OTHER } enum LicenseCode { FREE EDU PRO } model User { id String @id @default(uuid()) @db.Uuid email String @unique passwordHash String @map("password_hash") name String? role UserRole @default(USER) isActive Boolean @default(true) @map("is_active") lastLoginAt DateTime? @map("last_login_at") @db.Timestamptz(3) profileImageData Bytes? @map("profile_image_data") profileImageMime String? @map("profile_image_mime") profileImageUpdatedAt DateTime? @map("profile_image_updated_at") @db.Timestamptz(3) createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(3) updatedAt DateTime @updatedAt @map("updated_at") @db.Timestamptz(3) refreshTokens RefreshToken[] handoffTokens HandoffToken[] affiliations UserAffiliation[] userLicenses UserLicense[] appRoles UserAppRole[] @@map("users") } model UserAppRole { id String @id @default(uuid()) @db.Uuid userId String @map("user_id") @db.Uuid appKey String @map("app_key") roleCode String @map("role_code") assignedById String? @map("assigned_by") @db.Uuid assignedAt DateTime @default(now()) @map("assigned_at") @db.Timestamptz(3) startsAt DateTime? @map("starts_at") @db.Timestamptz(3) endsAt DateTime? @map("ends_at") @db.Timestamptz(3) createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(3) updatedAt DateTime @updatedAt @map("updated_at") @db.Timestamptz(3) user User @relation(fields: [userId], references: [id], onDelete: Cascade) @@unique([userId, appKey, roleCode]) @@index([appKey, roleCode]) @@index([userId, appKey]) @@map("user_app_roles") } model License { id String @id @default(uuid()) @db.Uuid code LicenseCode @unique name String description String? defaultDurationDays Int? @default(365) @map("default_duration_days") isActive Boolean @default(true) @map("is_active") createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(3) updatedAt DateTime @updatedAt @map("updated_at") @db.Timestamptz(3) userLicenses UserLicense[] @@index([isActive]) @@map("licenses") } model UserLicense { id String @id @default(uuid()) @db.Uuid userId String @map("user_id") @db.Uuid licenseId String @map("license_id") @db.Uuid startsAt DateTime @default(now()) @map("starts_at") @db.Timestamptz(3) expiresAt DateTime? @map("expires_at") @db.Timestamptz(3) assignedById String? @map("assigned_by") @db.Uuid createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(3) user User @relation(fields: [userId], references: [id], onDelete: Cascade) license License @relation(fields: [licenseId], references: [id], onDelete: Restrict) @@index([userId, startsAt]) @@index([licenseId]) @@map("user_licenses") } model Organization { id String @id @default(uuid()) @db.Uuid name String type OrganizationType @default(OTHER) domain String? isActive Boolean @default(true) @map("is_active") createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(3) updatedAt DateTime @updatedAt @map("updated_at") @db.Timestamptz(3) affiliations UserAffiliation[] @@unique([name, type]) @@index([isActive, type]) @@map("organizations") } model UserAffiliation { id String @id @default(uuid()) @db.Uuid userId String @map("user_id") @db.Uuid organizationId String @map("organization_id") @db.Uuid department String? position String? isPrimary Boolean @default(false) @map("is_primary") startsAt DateTime? @map("starts_at") @db.Timestamptz(3) endsAt DateTime? @map("ends_at") @db.Timestamptz(3) createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(3) updatedAt DateTime @updatedAt @map("updated_at") @db.Timestamptz(3) user User @relation(fields: [userId], references: [id], onDelete: Cascade) organization Organization @relation(fields: [organizationId], references: [id], onDelete: Restrict) @@index([userId, isPrimary]) @@index([organizationId]) @@map("user_affiliations") } model RefreshToken { id String @id @default(uuid()) @db.Uuid userId String @map("user_id") @db.Uuid tokenHash String @unique @map("token_hash") expiresAt DateTime @map("expires_at") @db.Timestamptz(3) revokedAt DateTime? @map("revoked_at") @db.Timestamptz(3) createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(3) user User @relation(fields: [userId], references: [id], onDelete: Cascade) @@index([userId]) @@map("refresh_tokens") } model HandoffToken { id String @id @default(uuid()) @db.Uuid userId String @map("user_id") @db.Uuid tokenHash String @unique @map("token_hash") audienceApp String @map("audience_app") expiresAt DateTime @map("expires_at") @db.Timestamptz(3) usedAt DateTime? @map("used_at") @db.Timestamptz(3) createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(3) user User @relation(fields: [userId], references: [id], onDelete: Cascade) @@index([userId]) @@map("handoff_tokens") } model LoginNotice { id String @id @default(uuid()) @db.Uuid title String body String linkUrl String? @map("link_url") isActive Boolean @default(true) @map("is_active") startsAt DateTime? @map("starts_at") @db.Timestamptz(3) endsAt DateTime? @map("ends_at") @db.Timestamptz(3) priority Int @default(0) createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(3) updatedAt DateTime @updatedAt @map("updated_at") @db.Timestamptz(3) @@index([isActive, priority]) @@map("login_notices") }