// Prisma schema for RayLab Core - Phase 1 // PostgreSQL datasource. DATABASE_URL must be set in environment. generator client { provider = "prisma-client-js" } datasource db { provider = "postgresql" url = env("DATABASE_URL") } model User { id String @id @default(uuid()) @db.Uuid authentikId String? @unique authentikUserId String? @unique authentikSubject String? @unique username String? @db.VarChar(255) @unique email String? @db.VarChar(320) @unique name String? @db.VarChar(255) picture String? isActive Boolean @default(true) deletedAt DateTime? lastSeenAt DateTime? lastSyncedAt DateTime? syncStatus String? storageQuota BigInt? @default(10737418240) storageUsed BigInt? @default(0) metadata Json? userRoles UserRole[] auditLogs AuditLog[] lastGroupHash String? @db.Text createdAt DateTime @default(now()) updatedAt DateTime @updatedAt @@index([authentikId]) @@index([username]) @@index([email]) } model Role { id String @id @default(uuid()) @db.Uuid code String @unique @db.VarChar(100) name String @db.VarChar(255) displayName String? @db.VarChar(255) description String? isDefault Boolean @default(false) rolePermissions RolePermission[] userRoles UserRole[] mappings AuthGroupRoleMapping[] createdAt DateTime @default(now()) updatedAt DateTime @updatedAt } model Permission { id String @id @default(uuid()) @db.Uuid code String @unique @db.VarChar(150) name String @db.VarChar(255) displayName String? @db.VarChar(255) description String? rolePermissions RolePermission[] createdAt DateTime @default(now()) updatedAt DateTime @updatedAt } model RolePermission { id String @id @default(uuid()) @db.Uuid role Role @relation(fields: [roleId], references: [id], onDelete: Cascade) roleId String @db.Uuid permission Permission @relation(fields: [permissionId], references: [id], onDelete: Cascade) permissionId String @db.Uuid createdAt DateTime @default(now()) @@unique([roleId, permissionId]) @@index([roleId]) @@index([permissionId]) } enum UserRoleSource { AUTHENTIK SYSTEM } model UserRole { id String @id @default(uuid()) @db.Uuid user User @relation(fields: [userId], references: [id], onDelete: Cascade) userId String @db.Uuid role Role @relation(fields: [roleId], references: [id], onDelete: Cascade) roleId String @db.Uuid source UserRoleSource @default(AUTHENTIK) syncedAt DateTime @default(now()) createdAt DateTime @default(now()) @@unique([userId, roleId]) @@index([userId]) @@index([roleId]) } model AuthGroupRoleMapping { id String @id @default(uuid()) @db.Uuid authGroup String @db.VarChar(255) role Role @relation(fields: [roleId], references: [id], onDelete: Cascade) roleId String @db.Uuid createdAt DateTime @default(now()) updatedAt DateTime @updatedAt @@index([authGroup]) } model AuditLog { id String @id @default(uuid()) @db.Uuid user User? @relation(fields: [userId], references: [id], onDelete: SetNull) userId String? @db.Uuid action String @db.VarChar(200) resource String? @db.VarChar(200) resourceId String? details Json? createdAt DateTime @default(now()) @@index([userId]) @@index([action]) } model ScheduledJob { id String @id @default(uuid()) @db.Uuid name String @db.VarChar(255) payload Json? cron String? runAt DateTime? status String @db.VarChar(50) @default("pending") attempts Int @default(0) lastRunAt DateTime? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt @@index([name]) @@index([status]) } model MediaObject { id String @id @default(uuid()) @db.Uuid ownerUserId String? @db.Uuid owner User? @relation(fields: [ownerUserId], references: [id], onDelete: SetNull) storageKey String @db.VarChar(1024) filename String? @db.VarChar(1024) mimeType String? @db.VarChar(255) size BigInt? isPublic Boolean @default(false) metadata Json? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt @@index([ownerUserId]) @@index([storageKey]) } model Application { id String @id @default(uuid()) @db.Uuid code String @unique @db.VarChar(100) name String @db.VarChar(255) description String? icon String? url String? applicationsClaim String @unique @db.VarChar(255) isActive Boolean @default(true) displayOrder Int @default(0) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt @@index([code]) @@index([applicationsClaim]) }