// Prisma schema for LNPaywall generator client { provider = "prisma-client-js" } datasource db { provider = "sqlite" url = env("DATABASE_URL") } model User { id String @id @default(uuid()) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt status String @default("ACTIVE") // ACTIVE, DISABLED role String @default("CREATOR") // CREATOR, ADMIN displayName String email String? @unique emailVerified Boolean @default(false) passwordHash String? nostrPubkey String? @unique avatarUrl String? defaultCurrency String @default("sats") // OAuth providers googleId String? @unique githubId String? @unique // Payout configuration lightningAddress String? lnurlp String? // Subscription subscriptionTier String @default("FREE") // FREE, PRO subscriptionExpiry DateTime? // Relations paywalls Paywall[] sales Sale[] sessions Session[] auditLogs AuditLog[] } model Session { id String @id @default(uuid()) userId String refreshToken String @unique userAgent String? ipAddress String? createdAt DateTime @default(now()) expiresAt DateTime user User @relation(fields: [userId], references: [id], onDelete: Cascade) } model Paywall { id String @id @default(uuid()) creatorId String status String @default("ACTIVE") // ACTIVE, ARCHIVED, DISABLED createdAt DateTime @default(now()) updatedAt DateTime @updatedAt // Content title String description String? coverImageUrl String? originalUrl String originalUrlType String @default("URL") // URL, YOUTUBE, NOTION, PDF, LOOM, GDOCS, GITHUB, OTHER // Preview previewMode String @default("NONE") // NONE, TEXT_PREVIEW, IMAGE_PREVIEW previewContent String? // Pricing priceSats Int // Access rules accessExpirySeconds Int? maxDevices Int @default(3) maxSessions Int @default(5) // Embed settings allowEmbed Boolean @default(true) allowedEmbedOrigins String @default("[]") // JSON array as string for SQLite // Customization requireEmailReceipt Boolean @default(false) customSuccessMessage String? customBranding String? // JSON as string // URL slug String? @unique // Relations creator User @relation(fields: [creatorId], references: [id], onDelete: Cascade) checkoutSessions CheckoutSession[] accessGrants AccessGrant[] sales Sale[] } model CheckoutSession { id String @id @default(uuid()) paywallId String createdAt DateTime @default(now()) status String @default("PENDING") // PENDING, PAID, EXPIRED, CANCELED amountSats Int paymentProvider String @default("lnbits") paymentRequest String? // Lightning invoice paymentHash String? @unique expiresAt DateTime buyerHint String? // IP hash + user agent hash buyerEmail String? // Relations paywall Paywall @relation(fields: [paywallId], references: [id], onDelete: Cascade) accessGrant AccessGrant? sale Sale? } model Buyer { id String @id @default(uuid()) createdAt DateTime @default(now()) email String? emailVerified Boolean @default(false) nostrPubkey String? notes String? // Relations accessGrants AccessGrant[] sales Sale[] } model AccessGrant { id String @id @default(uuid()) paywallId String checkoutSessionId String? @unique buyerId String? createdAt DateTime @default(now()) expiresAt DateTime? status String @default("ACTIVE") // ACTIVE, REVOKED tokenId String @unique @default(uuid()) lastUsedAt DateTime? usageCount Int @default(0) deviceFingerprints String @default("[]") // JSON array as string // Relations paywall Paywall @relation(fields: [paywallId], references: [id], onDelete: Cascade) checkoutSession CheckoutSession? @relation(fields: [checkoutSessionId], references: [id]) buyer Buyer? @relation(fields: [buyerId], references: [id]) } model Sale { id String @id @default(uuid()) paywallId String creatorId String checkoutSessionId String? @unique buyerId String? createdAt DateTime @default(now()) amountSats Int platformFeeSats Int netSats Int paymentProvider String providerReference String? status String @default("CONFIRMED") // CONFIRMED, REFUNDED, CHARGEBACK, DISPUTED // Relations paywall Paywall @relation(fields: [paywallId], references: [id]) creator User @relation(fields: [creatorId], references: [id]) checkoutSession CheckoutSession? @relation(fields: [checkoutSessionId], references: [id]) buyer Buyer? @relation(fields: [buyerId], references: [id]) } model WebhookEvent { id String @id @default(uuid()) createdAt DateTime @default(now()) provider String eventType String rawPayload String // JSON as string processedAt DateTime? status String @default("pending") error String? } model AuditLog { id String @id @default(uuid()) createdAt DateTime @default(now()) actorId String? actorType String // creator, admin, system action String resourceType String resourceId String? ipAddress String? metadata String? // JSON as string actor User? @relation(fields: [actorId], references: [id]) }