Initial import
This commit is contained in:
351
packages/db/prisma/schema.prisma
Normal file
351
packages/db/prisma/schema.prisma
Normal file
@@ -0,0 +1,351 @@
|
||||
generator client {
|
||||
provider = "prisma-client-js"
|
||||
}
|
||||
|
||||
datasource db {
|
||||
provider = "postgresql"
|
||||
url = env("DATABASE_URL")
|
||||
}
|
||||
|
||||
enum SubscriptionStatus {
|
||||
pending_activation
|
||||
active
|
||||
past_due
|
||||
canceled
|
||||
expired
|
||||
}
|
||||
|
||||
enum PaymentInvoiceStatus {
|
||||
pending
|
||||
paid
|
||||
expired
|
||||
canceled
|
||||
}
|
||||
|
||||
enum GenerationMode {
|
||||
text_to_image
|
||||
image_to_image
|
||||
}
|
||||
|
||||
enum GenerationRequestStatus {
|
||||
queued
|
||||
running
|
||||
succeeded
|
||||
failed
|
||||
canceled
|
||||
}
|
||||
|
||||
enum GenerationAttemptStatus {
|
||||
started
|
||||
succeeded
|
||||
failed
|
||||
}
|
||||
|
||||
enum ProviderFailureCategory {
|
||||
transport
|
||||
timeout
|
||||
provider_5xx
|
||||
provider_4xx_user
|
||||
insufficient_funds
|
||||
unknown
|
||||
}
|
||||
|
||||
enum ProviderKeyState {
|
||||
active
|
||||
cooldown
|
||||
out_of_funds
|
||||
manual_review
|
||||
disabled
|
||||
}
|
||||
|
||||
enum UsageLedgerEntryType {
|
||||
cycle_reset
|
||||
generation_success
|
||||
manual_adjustment
|
||||
refund
|
||||
}
|
||||
|
||||
enum TelegramPairingStatus {
|
||||
pending
|
||||
completed
|
||||
expired
|
||||
revoked
|
||||
}
|
||||
|
||||
enum AdminActorType {
|
||||
system
|
||||
web_admin
|
||||
telegram_admin
|
||||
cli_operator
|
||||
}
|
||||
|
||||
model User {
|
||||
id String @id @default(cuid())
|
||||
email String @unique
|
||||
passwordHash String
|
||||
passwordResetVersion Int @default(0)
|
||||
isAdmin Boolean @default(false)
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
subscriptions Subscription[]
|
||||
invoices PaymentInvoice[]
|
||||
generationRequests GenerationRequest[]
|
||||
usageLedgerEntries UsageLedgerEntry[]
|
||||
sessions UserSession[]
|
||||
passwordResetTokens PasswordResetToken[]
|
||||
}
|
||||
|
||||
model UserSession {
|
||||
id String @id @default(cuid())
|
||||
userId String
|
||||
tokenHash String @unique
|
||||
expiresAt DateTime
|
||||
revokedAt DateTime?
|
||||
lastSeenAt DateTime?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@index([userId, createdAt])
|
||||
@@index([expiresAt, revokedAt])
|
||||
}
|
||||
|
||||
model PasswordResetToken {
|
||||
id String @id @default(cuid())
|
||||
userId String
|
||||
tokenHash String @unique
|
||||
expiresAt DateTime
|
||||
consumedAt DateTime?
|
||||
createdAt DateTime @default(now())
|
||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@index([userId, createdAt])
|
||||
@@index([expiresAt, consumedAt])
|
||||
}
|
||||
|
||||
model SubscriptionPlan {
|
||||
id String @id @default(cuid())
|
||||
code String @unique
|
||||
displayName String
|
||||
monthlyRequestLimit Int
|
||||
monthlyPriceUsd Decimal @db.Decimal(12, 2)
|
||||
billingCurrency String
|
||||
isActive Boolean @default(true)
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
subscriptions Subscription[]
|
||||
}
|
||||
|
||||
model Subscription {
|
||||
id String @id @default(cuid())
|
||||
userId String
|
||||
planId String
|
||||
status SubscriptionStatus
|
||||
renewsManually Boolean @default(true)
|
||||
activatedAt DateTime?
|
||||
currentPeriodStart DateTime?
|
||||
currentPeriodEnd DateTime?
|
||||
canceledAt DateTime?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||
plan SubscriptionPlan @relation(fields: [planId], references: [id], onDelete: Restrict)
|
||||
invoices PaymentInvoice[]
|
||||
|
||||
@@index([userId, status])
|
||||
}
|
||||
|
||||
model PaymentInvoice {
|
||||
id String @id @default(cuid())
|
||||
userId String
|
||||
subscriptionId String?
|
||||
provider String
|
||||
providerInvoiceId String? @unique
|
||||
status PaymentInvoiceStatus
|
||||
currency String
|
||||
amountCrypto Decimal @db.Decimal(20, 8)
|
||||
amountUsd Decimal? @db.Decimal(12, 2)
|
||||
paymentAddress String?
|
||||
expiresAt DateTime?
|
||||
paidAt DateTime?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||
subscription Subscription? @relation(fields: [subscriptionId], references: [id], onDelete: SetNull)
|
||||
|
||||
@@index([userId, status])
|
||||
}
|
||||
|
||||
model GenerationRequest {
|
||||
id String @id @default(cuid())
|
||||
userId String
|
||||
mode GenerationMode
|
||||
status GenerationRequestStatus @default(queued)
|
||||
providerModel String
|
||||
prompt String
|
||||
sourceImageKey String?
|
||||
resolutionPreset String
|
||||
batchSize Int
|
||||
imageStrength Decimal? @db.Decimal(4, 3)
|
||||
idempotencyKey String? @unique
|
||||
terminalErrorCode String?
|
||||
terminalErrorText String?
|
||||
requestedAt DateTime @default(now())
|
||||
startedAt DateTime?
|
||||
completedAt DateTime?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||
attempts GenerationAttempt[]
|
||||
assets GeneratedAsset[]
|
||||
usageLedgerEntry UsageLedgerEntry?
|
||||
|
||||
@@index([userId, status, requestedAt])
|
||||
}
|
||||
|
||||
model GenerationAttempt {
|
||||
id String @id @default(cuid())
|
||||
generationRequestId String
|
||||
providerKeyId String
|
||||
attemptIndex Int
|
||||
status GenerationAttemptStatus @default(started)
|
||||
usedProxy Boolean @default(false)
|
||||
directFallbackUsed Boolean @default(false)
|
||||
failureCategory ProviderFailureCategory?
|
||||
providerHttpStatus Int?
|
||||
providerErrorCode String?
|
||||
providerErrorText String?
|
||||
startedAt DateTime @default(now())
|
||||
completedAt DateTime?
|
||||
createdAt DateTime @default(now())
|
||||
generationRequest GenerationRequest @relation(fields: [generationRequestId], references: [id], onDelete: Cascade)
|
||||
providerKey ProviderKey @relation(fields: [providerKeyId], references: [id], onDelete: Restrict)
|
||||
|
||||
@@unique([generationRequestId, attemptIndex])
|
||||
@@index([providerKeyId, startedAt])
|
||||
}
|
||||
|
||||
model GeneratedAsset {
|
||||
id String @id @default(cuid())
|
||||
generationRequestId String
|
||||
objectKey String @unique
|
||||
mimeType String
|
||||
width Int?
|
||||
height Int?
|
||||
bytes Int?
|
||||
createdAt DateTime @default(now())
|
||||
generationRequest GenerationRequest @relation(fields: [generationRequestId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@index([generationRequestId])
|
||||
}
|
||||
|
||||
model UsageLedgerEntry {
|
||||
id String @id @default(cuid())
|
||||
userId String
|
||||
generationRequestId String? @unique
|
||||
entryType UsageLedgerEntryType
|
||||
deltaRequests Int
|
||||
cycleStartedAt DateTime?
|
||||
cycleEndsAt DateTime?
|
||||
note String?
|
||||
createdAt DateTime @default(now())
|
||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||
generationRequest GenerationRequest? @relation(fields: [generationRequestId], references: [id], onDelete: SetNull)
|
||||
|
||||
@@index([userId, createdAt])
|
||||
}
|
||||
|
||||
model ProviderProxy {
|
||||
id String @id @default(cuid())
|
||||
label String @unique
|
||||
baseUrl String
|
||||
isActive Boolean @default(true)
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
providerKeys ProviderKey[]
|
||||
}
|
||||
|
||||
model ProviderKey {
|
||||
id String @id @default(cuid())
|
||||
providerCode String
|
||||
label String @unique
|
||||
apiKeyCiphertext String
|
||||
apiKeyLastFour String
|
||||
state ProviderKeyState @default(active)
|
||||
roundRobinOrder Int
|
||||
consecutiveRetryableFailures Int @default(0)
|
||||
cooldownUntil DateTime?
|
||||
lastErrorCategory ProviderFailureCategory?
|
||||
lastErrorCode String?
|
||||
lastErrorAt DateTime?
|
||||
balanceMinorUnits BigInt?
|
||||
balanceCurrency String?
|
||||
balanceRefreshedAt DateTime?
|
||||
proxyId String?
|
||||
disabledAt DateTime?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
proxy ProviderProxy? @relation(fields: [proxyId], references: [id], onDelete: SetNull)
|
||||
attempts GenerationAttempt[]
|
||||
statusEvents ProviderKeyStatusEvent[]
|
||||
|
||||
@@index([providerCode, state, roundRobinOrder])
|
||||
}
|
||||
|
||||
model ProviderKeyStatusEvent {
|
||||
id String @id @default(cuid())
|
||||
providerKeyId String
|
||||
fromState ProviderKeyState?
|
||||
toState ProviderKeyState
|
||||
reason String
|
||||
errorCategory ProviderFailureCategory?
|
||||
errorCode String?
|
||||
actorType AdminActorType
|
||||
actorRef String?
|
||||
metadata Json?
|
||||
createdAt DateTime @default(now())
|
||||
providerKey ProviderKey @relation(fields: [providerKeyId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@index([providerKeyId, createdAt])
|
||||
}
|
||||
|
||||
model TelegramPairing {
|
||||
id String @id @default(cuid())
|
||||
telegramUserId String
|
||||
telegramUsername String?
|
||||
displayNameSnapshot String
|
||||
codeHash String
|
||||
expiresAt DateTime
|
||||
status TelegramPairingStatus @default(pending)
|
||||
completedAt DateTime?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@index([telegramUserId, status])
|
||||
@@index([expiresAt, status])
|
||||
}
|
||||
|
||||
model TelegramAdminAllowlistEntry {
|
||||
telegramUserId String @id
|
||||
telegramUsername String?
|
||||
displayNameSnapshot String
|
||||
pairedAt DateTime @default(now())
|
||||
revokedAt DateTime?
|
||||
isActive Boolean @default(true)
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
}
|
||||
|
||||
model AdminAuditLog {
|
||||
id String @id @default(cuid())
|
||||
actorType AdminActorType
|
||||
actorRef String?
|
||||
action String
|
||||
targetType String
|
||||
targetId String?
|
||||
metadata Json?
|
||||
createdAt DateTime @default(now())
|
||||
|
||||
@@index([targetType, targetId, createdAt])
|
||||
@@index([actorType, createdAt])
|
||||
}
|
||||
Reference in New Issue
Block a user