generator client { provider = "prisma-client-js" } datasource db { provider = "postgresql" url = env("DATABASE_URL") } enum UserRole { user admin super_admin } enum UserStatus { active disabled deleted } enum ProviderStatus { disabled healthy degraded error } enum ModelStatus { draft enabled disabled deprecated } enum ApiKeyMode { platform user_own hybrid } enum AuthType { bearer api_key custom } enum GenerationMode { text_to_image image_to_image } enum GenerationQuality { standard hd ultra } enum ResolutionTier { one_k @map("1k") two_k @map("2k") four_k @map("4k") } enum AspectRatio { square @map("1:1") landscape_4_3 @map("4:3") portrait_3_4 @map("3:4") landscape_16_9 @map("16:9") portrait_9_16 @map("9:16") ultrawide_21_9 @map("21:9") } enum GenerationGroupStatus { queued running partial_succeeded succeeded failed canceled } enum GenerationTaskStatus { created queued dispatching running uploading post_processing moderating succeeded failed retrying canceled expired } enum AssetKind { reference master landscape portrait thumbnail preview download_zip } enum AssetStatus { temporary active deleted failed } enum WallpaperStatus { draft published hidden rejected deleted } enum ModerationStatus { pending passed rejected manual_review } enum ProviderCallStatus { started success failed } enum DevicePlatform { web ios android desktop } model User { id String @id @default(uuid()) @db.Uuid email String @unique @db.VarChar(255) name String? @db.VarChar(80) passwordHash String @map("password_hash") @db.VarChar(255) roles UserRole[] @default([user]) status UserStatus @default(active) userApiKeys UserApiKey[] generationGroups GenerationGroup[] wallpapers Wallpaper[] preferences UserPreference? devices Device[] createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") @@map("users") } model UserApiKey { id String @id @default(uuid()) @db.Uuid userId String @map("user_id") @db.Uuid providerId String @map("provider_id") @db.Uuid name String @db.VarChar(80) maskedKey String @map("masked_key") @db.VarChar(120) encryptedKey String @map("encrypted_key") @db.Text baseUrl String? @map("base_url") @db.VarChar(512) defaultModelId String? @map("default_model_id") @db.Uuid enabled Boolean @default(true) metadata Json @default("{}") user User @relation(fields: [userId], references: [id], onDelete: Cascade) provider Provider @relation(fields: [providerId], references: [id], onDelete: Restrict) defaultModel Model? @relation(fields: [defaultModelId], references: [id], onDelete: SetNull) createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") deletedAt DateTime? @map("deleted_at") @@index([userId, enabled]) @@index([providerId]) @@map("user_api_keys") } model Provider { id String @id @default(uuid()) @db.Uuid slug String @unique @db.VarChar(80) displayName String @map("display_name") @db.VarChar(120) baseUrl String? @map("base_url") @db.VarChar(512) authType AuthType @default(bearer) @map("auth_type") status ProviderStatus @default(healthy) keyMode ApiKeyMode @default(hybrid) @map("key_mode") supportsUserKeys Boolean @default(true) @map("supports_user_keys") supportsPlatformKeys Boolean @default(true) @map("supports_platform_keys") healthCheckPath String? @map("health_check_path") @db.VarChar(255) rateLimitPerMinute Int? @map("rate_limit_per_minute") metadata Json @default("{}") models Model[] userApiKeys UserApiKey[] generationGroups GenerationGroup[] providerCallLogs ProviderCallLog[] createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") @@map("providers") } model Model { id String @id @default(uuid()) @db.Uuid providerId String @map("provider_id") @db.Uuid slug String @db.VarChar(160) displayName String @map("display_name") @db.VarChar(160) status ModelStatus @default(enabled) keyMode ApiKeyMode @default(hybrid) @map("key_mode") capability Json pricing Json? defaultParams Json @default("{}") @map("default_params") sortOrder Int @default(0) @map("sort_order") provider Provider @relation(fields: [providerId], references: [id], onDelete: Cascade) sizePresets ModelSizePreset[] userApiKeys UserApiKey[] generationGroups GenerationGroup[] generationTasks GenerationTask[] generatedAssets GeneratedAsset[] providerCallLogs ProviderCallLog[] wallpapers Wallpaper[] createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") @@unique([providerId, slug]) @@index([status, sortOrder]) @@map("models") } model ModelSizePreset { id String @id @default(uuid()) @db.Uuid modelId String @map("model_id") @db.Uuid aspectRatio AspectRatio @map("aspect_ratio") resolution ResolutionTier width Int height Int providerSizeValue String? @map("provider_size_value") @db.VarChar(80) native Boolean @default(true) requiresUpscale Boolean @default(false) @map("requires_upscale") model Model @relation(fields: [modelId], references: [id], onDelete: Cascade) @@unique([modelId, aspectRatio, resolution]) @@map("model_size_presets") } model GenerationGroup { id String @id @default(uuid()) @db.Uuid userId String @map("user_id") @db.Uuid providerId String @map("provider_id") @db.Uuid modelId String @map("model_id") @db.Uuid userApiKeyId String? @map("user_api_key_id") @db.Uuid status GenerationGroupStatus @default(queued) mode GenerationMode prompt String @db.Text negativePrompt String? @map("negative_prompt") @db.Text resolution ResolutionTier quality GenerationQuality @default(standard) batchSize Int @default(1) @map("batch_size") seed Int? privacy String @default("private") @db.VarChar(24) metadata Json @default("{}") user User @relation(fields: [userId], references: [id], onDelete: Cascade) provider Provider @relation(fields: [providerId], references: [id], onDelete: Restrict) model Model @relation(fields: [modelId], references: [id], onDelete: Restrict) tasks GenerationTask[] assets GeneratedAsset[] wallpapers Wallpaper[] createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") @@index([userId, createdAt]) @@index([status, createdAt]) @@map("generation_groups") } model GenerationTask { id String @id @default(uuid()) @db.Uuid groupId String @map("group_id") @db.Uuid modelId String @map("model_id") @db.Uuid status GenerationTaskStatus @default(created) mode GenerationMode aspectRatio AspectRatio @map("aspect_ratio") resolution ResolutionTier quality GenerationQuality @default(standard) priority Int @default(0) attempt Int @default(0) maxAttempts Int @default(3) @map("max_attempts") progress Int @default(0) errorCode String? @map("error_code") @db.VarChar(120) errorMessage String? @map("error_message") @db.Text lockedAt DateTime? @map("locked_at") startedAt DateTime? @map("started_at") completedAt DateTime? @map("completed_at") group GenerationGroup @relation(fields: [groupId], references: [id], onDelete: Cascade) model Model @relation(fields: [modelId], references: [id], onDelete: Restrict) assets GeneratedAsset[] providerCallLogs ProviderCallLog[] createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") @@index([status, priority, createdAt], map: "idx_generation_tasks_status_priority") @@index([groupId]) @@map("generation_tasks") } model GeneratedAsset { id String @id @default(uuid()) @db.Uuid groupId String @map("group_id") @db.Uuid taskId String? @map("task_id") @db.Uuid providerId String? @map("provider_id") @db.Uuid modelId String? @map("model_id") @db.Uuid kind AssetKind status AssetStatus @default(temporary) width Int? height Int? mimeType String? @map("mime_type") @db.VarChar(120) bucket String? @db.VarChar(120) objectKey String? @map("object_key") @db.VarChar(512) storageUrl String? @map("storage_url") @db.Text publicUrl String? @map("public_url") @db.Text blurHash String? @map("blur_hash") @db.VarChar(255) byteSize BigInt? @map("byte_size") sha256 String? @db.VarChar(64) metadata Json @default("{}") group GenerationGroup @relation(fields: [groupId], references: [id], onDelete: Cascade) task GenerationTask? @relation(fields: [taskId], references: [id], onDelete: SetNull) model Model? @relation(fields: [modelId], references: [id], onDelete: SetNull) wallpapers Wallpaper[] createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") @@index([groupId]) @@index([taskId]) @@map("generated_assets") } model Wallpaper { id String @id @default(uuid()) @db.Uuid userId String @map("user_id") @db.Uuid groupId String? @map("group_id") @db.Uuid assetId String? @map("asset_id") @db.Uuid modelId String? @map("model_id") @db.Uuid title String @db.VarChar(160) description String? @db.Text prompt String? @db.Text status WallpaperStatus @default(draft) isFeatured Boolean @default(false) @map("is_featured") tags String[] @default([]) metadata Json @default("{}") user User @relation(fields: [userId], references: [id], onDelete: Cascade) group GenerationGroup? @relation(fields: [groupId], references: [id], onDelete: SetNull) asset GeneratedAsset? @relation(fields: [assetId], references: [id], onDelete: SetNull) model Model? @relation(fields: [modelId], references: [id], onDelete: SetNull) moderationRecords ModerationRecord[] publishedAt DateTime? @map("published_at") createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") @@index([status, isFeatured, publishedAt], map: "idx_wallpapers_status_featured_published") @@index([userId, createdAt]) @@map("wallpapers") } model ModerationRecord { id String @id @default(uuid()) @db.Uuid wallpaperId String? @map("wallpaper_id") @db.Uuid assetId String? @map("asset_id") @db.Uuid status ModerationStatus @default(pending) reason String? @db.Text metadata Json @default("{}") reviewerId String? @map("reviewer_id") @db.Uuid wallpaper Wallpaper? @relation(fields: [wallpaperId], references: [id], onDelete: Cascade) createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") @@index([status, createdAt]) @@map("moderation_records") } model ProviderCallLog { id String @id @default(uuid()) @db.Uuid taskId String? @map("task_id") @db.Uuid providerId String @map("provider_id") @db.Uuid modelId String? @map("model_id") @db.Uuid userApiKeyId String? @map("user_api_key_id") @db.Uuid status ProviderCallStatus latencyMs Int? @map("latency_ms") errorCode String? @map("error_code") @db.VarChar(120) errorMessage String? @map("error_message") @db.Text requestId String? @map("request_id") @db.VarChar(160) providerCost Decimal? @map("provider_cost") @db.Decimal(12, 6) metadata Json @default("{}") task GenerationTask? @relation(fields: [taskId], references: [id], onDelete: SetNull) provider Provider @relation(fields: [providerId], references: [id], onDelete: Restrict) model Model? @relation(fields: [modelId], references: [id], onDelete: SetNull) createdAt DateTime @default(now()) @map("created_at") @@index([taskId, createdAt], map: "idx_provider_logs_task") @@index([providerId, createdAt]) @@map("provider_call_logs") } model UserPreference { id String @id @default(uuid()) @db.Uuid userId String @unique @map("user_id") @db.Uuid defaultModelId String? @map("default_model_id") @db.Uuid defaultResolution ResolutionTier? @map("default_resolution") defaultAspectRatios String[] @default([]) @map("default_aspect_ratios") defaultPrivacy String @default("private") @map("default_privacy") @db.VarChar(24) metadata Json @default("{}") user User @relation(fields: [userId], references: [id], onDelete: Cascade) createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") @@map("user_preferences") } model Device { id String @id @default(uuid()) @db.Uuid userId String? @map("user_id") @db.Uuid platform DevicePlatform appVersion String? @map("app_version") @db.VarChar(40) pushToken String? @map("push_token") @db.Text metadata Json @default("{}") user User? @relation(fields: [userId], references: [id], onDelete: Cascade) createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") @@index([userId, platform]) @@map("devices") } model Notification { id String @id @default(uuid()) @db.Uuid userId String? @map("user_id") @db.Uuid title String @db.VarChar(160) body String @db.Text readAt DateTime? @map("read_at") metadata Json @default("{}") createdAt DateTime @default(now()) @map("created_at") @@index([userId, readAt, createdAt]) @@map("notifications") } model AppConfig { key String @id @db.VarChar(120) value Json description String? @db.Text updatedAt DateTime @updatedAt @map("updated_at") @@map("app_config") }