generator client { provider = "prisma-client-js" } datasource db { provider = "postgresql" url = env("DATABASE_URL") } enum PreviewStatus { PROVISIONING BUILDING RUNNING FAILED STOPPED IGNORED } enum JobType { DEPLOY STOP INACTIVITY_STOP } enum JobStatus { PENDING RUNNING DONE FAILED } model User { id Int @id @default(autoincrement()) username String @unique @db.VarChar(128) passwordHash String @db.VarChar(256) isAdmin Boolean @default(false) isFounder Boolean @default(false) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt giteaUsername String? @db.VarChar(128) giteaPAT String? @db.Text giteaInstanceUrl String? @db.VarChar(512) awsAccessKeyId String? @db.VarChar(256) awsSecretAccessKey String? @db.Text awsRegion String? @db.VarChar(64) sessions Session[] repoConfigs RepoConfig[] webhookToken WebhookToken? noConfigComments NoConfigComment[] } model Session { id Int @id @default(autoincrement()) hash String @db.VarChar(512) userId Int user User @relation(fields: [userId], references: [id], onDelete: Cascade) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt } model RepoConfig { id Int @id @default(autoincrement()) userId Int user User @relation(fields: [userId], references: [id], onDelete: Cascade) repoOwner String @db.VarChar(128) repoName String @db.VarChar(128) isEnabled Boolean @default(false) giteaWebhookId String? @db.VarChar(128) denyList String[] instanceType String @default("t2.medium") @db.VarChar(64) inactivityHours Float @default(12) port Int @default(3000) envVars Json @default("{}") useDockerCompose Boolean @default(false) composeFilePath String? @db.VarChar(512) aptPackages String[] setupCommands String[] buildCommands String[] postBuildCommands String[] runCommand String? @db.Text createdAt DateTime @default(now()) updatedAt DateTime @updatedAt previews Preview[] @@unique([repoOwner, repoName]) } model Preview { id Int @id @default(autoincrement()) repoConfigId Int repoConfig RepoConfig @relation(fields: [repoConfigId], references: [id], onDelete: Cascade) prNumber Int prTitle String @db.VarChar(512) commitSha String @db.VarChar(64) instanceId String? @db.VarChar(64) instanceIp String? @db.VarChar(64) port Int @default(3000) status PreviewStatus @default(PROVISIONING) logs String @default("") @db.Text pid Int? sshPrivateKey String? @db.Text sshKeyName String? @db.VarChar(128) giteaCommentId Int? lastActivityAt DateTime @default(now()) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt stoppedAt DateTime? jobs Job[] } model Job { id Int @id @default(autoincrement()) previewId Int? preview Preview? @relation(fields: [previewId], references: [id], onDelete: Cascade) type JobType status JobStatus @default(PENDING) payload Json @default("{}") error String? @db.Text createdAt DateTime @default(now()) startedAt DateTime? finishedAt DateTime? } model WebhookToken { id Int @id @default(autoincrement()) userId Int @unique user User @relation(fields: [userId], references: [id], onDelete: Cascade) token String @db.VarChar(256) createdAt DateTime @default(now()) } model NoConfigComment { id Int @id @default(autoincrement()) userId Int user User @relation(fields: [userId], references: [id], onDelete: Cascade) repoOwner String @db.VarChar(128) repoName String @db.VarChar(128) prNumber Int createdAt DateTime @default(now()) @@unique([userId, repoOwner, repoName, prNumber]) } model AdminSettings { id Int @id @default(1) defaultInstanceType String @default("t2.medium") @db.VarChar(64) maxConcurrentInstancesPerUser Int @default(5) logSizeLimitBytes Int @default(1048576) previewRetentionDays Int @default(30) webhookRateLimitPerMinute Int @default(10) contactEmail String @default("") @db.VarChar(256) }