generator client { provider = "prisma-client-js" } datasource db { provider = "mysql" url = env("DATABASE_URL") } model User { id String @id @default(cuid()) email String @unique name String? password String? @db.Text image String? emailVerified DateTime? role UserRole @default(USER) isActive Boolean @default(true) // Relations projects Project[] sessions Session[] accounts Account[] apiKeys ApiKey[] auditLogs AuditLog[] createdAt DateTime @default(now()) updatedAt DateTime @updatedAt } model Project { id String @id @default(cuid()) name String description String? slug String @unique repositoryUrl String? isPublic Boolean @default(false) // Relations ownerId String owner User @relation(fields: [ownerId], references: [id]) collaborators ProjectCollaborator[] deployments Deployment[] environments Environment[] createdAt DateTime @default(now()) updatedAt DateTime @updatedAt @@index([ownerId]) @@index([slug]) } model ProjectCollaborator { id String @id @default(cuid()) projectId String userId String role CollaboratorRole @default(DEVELOPER) project Project @relation(fields: [projectId], references: [id]) user User @relation(fields: [userId], references: [id]) createdAt DateTime @default(now()) @@unique([projectId, userId]) } model Deployment { id String @id @default(cuid()) projectId String status DeploymentStatus @default(PENDING) version String commitHash String? logs String? @db.Text url String? project Project @relation(fields: [projectId], references: [id]) startedAt DateTime @default(now()) finishedAt DateTime? createdAt DateTime @default(now()) @@index([projectId]) @@index([status]) } model Environment { id String @id @default(cuid()) projectId String name String type EnvironmentType @default(DEVELOPMENT) variables Json // {key: value} secrets project Project @relation(fields: [projectId], references: [id]) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt @@unique([projectId, name]) } model ApiKey { id String @id @default(cuid()) userId String name String key String @unique permissions String[] // ["read", "write", "delete"] expiresAt DateTime? lastUsed DateTime? user User @relation(fields: [userId], references: [id]) createdAt DateTime @default(now()) @@index([userId]) @@index([key]) } model AuditLog { id String @id @default(cuid()) userId String? action String resourceType String resourceId String? details Json? ipAddress String? userAgent String? user User? @relation(fields: [userId], references: [id]) createdAt DateTime @default(now()) @@index([userId]) @@index([resourceType, resourceId]) @@index([createdAt]) } // Authentication models (NextAuth) model Account { id String @id @default(cuid()) userId String type String provider String providerAccountId String refresh_token String? @db.Text access_token String? @db.Text expires_at Int? token_type String? scope String? id_token String? @db.Text session_state String? user User @relation(fields: [userId], references: [id], onDelete: Cascade) @@unique([provider, providerAccountId]) } model Session { id String @id @default(cuid()) sessionToken String @unique userId String expires DateTime user User @relation(fields: [userId], references: [id], onDelete: Cascade) } model VerificationToken { identifier String token String @unique expires DateTime @@unique([identifier, token]) } // Enums enum UserRole { USER MODERATOR ADMIN SUPER_ADMIN } enum CollaboratorRole { VIEWER DEVELOPER MAINTAINER OWNER } enum DeploymentStatus { PENDING BUILDING DEPLOYING SUCCESS FAILED CANCELLED } enum EnvironmentType { DEVELOPMENT STAGING PRODUCTION }