367 lines
13 KiB
SQL
367 lines
13 KiB
SQL
-- CreateSchema
|
|
CREATE SCHEMA IF NOT EXISTS "public";
|
|
|
|
-- CreateEnum
|
|
CREATE TYPE "SubscriptionStatus" AS ENUM ('pending_activation', 'active', 'past_due', 'canceled', 'expired');
|
|
|
|
-- CreateEnum
|
|
CREATE TYPE "PaymentInvoiceStatus" AS ENUM ('pending', 'paid', 'expired', 'canceled');
|
|
|
|
-- CreateEnum
|
|
CREATE TYPE "GenerationMode" AS ENUM ('text_to_image', 'image_to_image');
|
|
|
|
-- CreateEnum
|
|
CREATE TYPE "GenerationRequestStatus" AS ENUM ('queued', 'running', 'succeeded', 'failed', 'canceled');
|
|
|
|
-- CreateEnum
|
|
CREATE TYPE "GenerationAttemptStatus" AS ENUM ('started', 'succeeded', 'failed');
|
|
|
|
-- CreateEnum
|
|
CREATE TYPE "ProviderFailureCategory" AS ENUM ('transport', 'timeout', 'provider_5xx', 'provider_4xx_user', 'insufficient_funds', 'unknown');
|
|
|
|
-- CreateEnum
|
|
CREATE TYPE "ProviderKeyState" AS ENUM ('active', 'cooldown', 'out_of_funds', 'manual_review', 'disabled');
|
|
|
|
-- CreateEnum
|
|
CREATE TYPE "UsageLedgerEntryType" AS ENUM ('cycle_reset', 'generation_success', 'manual_adjustment', 'refund');
|
|
|
|
-- CreateEnum
|
|
CREATE TYPE "TelegramPairingStatus" AS ENUM ('pending', 'completed', 'expired', 'revoked');
|
|
|
|
-- CreateEnum
|
|
CREATE TYPE "AdminActorType" AS ENUM ('system', 'web_admin', 'telegram_admin', 'cli_operator');
|
|
|
|
-- CreateTable
|
|
CREATE TABLE "User" (
|
|
"id" TEXT NOT NULL,
|
|
"email" TEXT NOT NULL,
|
|
"passwordHash" TEXT NOT NULL,
|
|
"passwordResetVersion" INTEGER NOT NULL DEFAULT 0,
|
|
"isAdmin" BOOLEAN NOT NULL DEFAULT false,
|
|
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
"updatedAt" TIMESTAMP(3) NOT NULL,
|
|
|
|
CONSTRAINT "User_pkey" PRIMARY KEY ("id")
|
|
);
|
|
|
|
-- CreateTable
|
|
CREATE TABLE "SubscriptionPlan" (
|
|
"id" TEXT NOT NULL,
|
|
"code" TEXT NOT NULL,
|
|
"displayName" TEXT NOT NULL,
|
|
"monthlyRequestLimit" INTEGER NOT NULL,
|
|
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
|
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
"updatedAt" TIMESTAMP(3) NOT NULL,
|
|
|
|
CONSTRAINT "SubscriptionPlan_pkey" PRIMARY KEY ("id")
|
|
);
|
|
|
|
-- CreateTable
|
|
CREATE TABLE "Subscription" (
|
|
"id" TEXT NOT NULL,
|
|
"userId" TEXT NOT NULL,
|
|
"planId" TEXT NOT NULL,
|
|
"status" "SubscriptionStatus" NOT NULL,
|
|
"renewsManually" BOOLEAN NOT NULL DEFAULT true,
|
|
"activatedAt" TIMESTAMP(3),
|
|
"currentPeriodStart" TIMESTAMP(3),
|
|
"currentPeriodEnd" TIMESTAMP(3),
|
|
"canceledAt" TIMESTAMP(3),
|
|
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
"updatedAt" TIMESTAMP(3) NOT NULL,
|
|
|
|
CONSTRAINT "Subscription_pkey" PRIMARY KEY ("id")
|
|
);
|
|
|
|
-- CreateTable
|
|
CREATE TABLE "PaymentInvoice" (
|
|
"id" TEXT NOT NULL,
|
|
"userId" TEXT NOT NULL,
|
|
"subscriptionId" TEXT,
|
|
"provider" TEXT NOT NULL,
|
|
"providerInvoiceId" TEXT,
|
|
"status" "PaymentInvoiceStatus" NOT NULL,
|
|
"currency" TEXT NOT NULL,
|
|
"amountCrypto" DECIMAL(20,8) NOT NULL,
|
|
"amountUsd" DECIMAL(12,2),
|
|
"paymentAddress" TEXT,
|
|
"expiresAt" TIMESTAMP(3),
|
|
"paidAt" TIMESTAMP(3),
|
|
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
"updatedAt" TIMESTAMP(3) NOT NULL,
|
|
|
|
CONSTRAINT "PaymentInvoice_pkey" PRIMARY KEY ("id")
|
|
);
|
|
|
|
-- CreateTable
|
|
CREATE TABLE "GenerationRequest" (
|
|
"id" TEXT NOT NULL,
|
|
"userId" TEXT NOT NULL,
|
|
"mode" "GenerationMode" NOT NULL,
|
|
"status" "GenerationRequestStatus" NOT NULL DEFAULT 'queued',
|
|
"providerModel" TEXT NOT NULL,
|
|
"prompt" TEXT NOT NULL,
|
|
"sourceImageKey" TEXT,
|
|
"resolutionPreset" TEXT NOT NULL,
|
|
"batchSize" INTEGER NOT NULL,
|
|
"imageStrength" DECIMAL(4,3),
|
|
"idempotencyKey" TEXT,
|
|
"terminalErrorCode" TEXT,
|
|
"terminalErrorText" TEXT,
|
|
"requestedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
"startedAt" TIMESTAMP(3),
|
|
"completedAt" TIMESTAMP(3),
|
|
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
"updatedAt" TIMESTAMP(3) NOT NULL,
|
|
|
|
CONSTRAINT "GenerationRequest_pkey" PRIMARY KEY ("id")
|
|
);
|
|
|
|
-- CreateTable
|
|
CREATE TABLE "GenerationAttempt" (
|
|
"id" TEXT NOT NULL,
|
|
"generationRequestId" TEXT NOT NULL,
|
|
"providerKeyId" TEXT NOT NULL,
|
|
"attemptIndex" INTEGER NOT NULL,
|
|
"status" "GenerationAttemptStatus" NOT NULL DEFAULT 'started',
|
|
"usedProxy" BOOLEAN NOT NULL DEFAULT false,
|
|
"directFallbackUsed" BOOLEAN NOT NULL DEFAULT false,
|
|
"failureCategory" "ProviderFailureCategory",
|
|
"providerHttpStatus" INTEGER,
|
|
"providerErrorCode" TEXT,
|
|
"providerErrorText" TEXT,
|
|
"startedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
"completedAt" TIMESTAMP(3),
|
|
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
|
|
CONSTRAINT "GenerationAttempt_pkey" PRIMARY KEY ("id")
|
|
);
|
|
|
|
-- CreateTable
|
|
CREATE TABLE "GeneratedAsset" (
|
|
"id" TEXT NOT NULL,
|
|
"generationRequestId" TEXT NOT NULL,
|
|
"objectKey" TEXT NOT NULL,
|
|
"mimeType" TEXT NOT NULL,
|
|
"width" INTEGER,
|
|
"height" INTEGER,
|
|
"bytes" INTEGER,
|
|
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
|
|
CONSTRAINT "GeneratedAsset_pkey" PRIMARY KEY ("id")
|
|
);
|
|
|
|
-- CreateTable
|
|
CREATE TABLE "UsageLedgerEntry" (
|
|
"id" TEXT NOT NULL,
|
|
"userId" TEXT NOT NULL,
|
|
"generationRequestId" TEXT,
|
|
"entryType" "UsageLedgerEntryType" NOT NULL,
|
|
"deltaRequests" INTEGER NOT NULL,
|
|
"cycleStartedAt" TIMESTAMP(3),
|
|
"cycleEndsAt" TIMESTAMP(3),
|
|
"note" TEXT,
|
|
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
|
|
CONSTRAINT "UsageLedgerEntry_pkey" PRIMARY KEY ("id")
|
|
);
|
|
|
|
-- CreateTable
|
|
CREATE TABLE "ProviderProxy" (
|
|
"id" TEXT NOT NULL,
|
|
"label" TEXT NOT NULL,
|
|
"baseUrl" TEXT NOT NULL,
|
|
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
|
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
"updatedAt" TIMESTAMP(3) NOT NULL,
|
|
|
|
CONSTRAINT "ProviderProxy_pkey" PRIMARY KEY ("id")
|
|
);
|
|
|
|
-- CreateTable
|
|
CREATE TABLE "ProviderKey" (
|
|
"id" TEXT NOT NULL,
|
|
"providerCode" TEXT NOT NULL,
|
|
"label" TEXT NOT NULL,
|
|
"apiKeyCiphertext" TEXT NOT NULL,
|
|
"apiKeyLastFour" TEXT NOT NULL,
|
|
"state" "ProviderKeyState" NOT NULL DEFAULT 'active',
|
|
"roundRobinOrder" INTEGER NOT NULL,
|
|
"consecutiveRetryableFailures" INTEGER NOT NULL DEFAULT 0,
|
|
"cooldownUntil" TIMESTAMP(3),
|
|
"lastErrorCategory" "ProviderFailureCategory",
|
|
"lastErrorCode" TEXT,
|
|
"lastErrorAt" TIMESTAMP(3),
|
|
"balanceMinorUnits" BIGINT,
|
|
"balanceCurrency" TEXT,
|
|
"balanceRefreshedAt" TIMESTAMP(3),
|
|
"proxyId" TEXT,
|
|
"disabledAt" TIMESTAMP(3),
|
|
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
"updatedAt" TIMESTAMP(3) NOT NULL,
|
|
|
|
CONSTRAINT "ProviderKey_pkey" PRIMARY KEY ("id")
|
|
);
|
|
|
|
-- CreateTable
|
|
CREATE TABLE "ProviderKeyStatusEvent" (
|
|
"id" TEXT NOT NULL,
|
|
"providerKeyId" TEXT NOT NULL,
|
|
"fromState" "ProviderKeyState",
|
|
"toState" "ProviderKeyState" NOT NULL,
|
|
"reason" TEXT NOT NULL,
|
|
"errorCategory" "ProviderFailureCategory",
|
|
"errorCode" TEXT,
|
|
"actorType" "AdminActorType" NOT NULL,
|
|
"actorRef" TEXT,
|
|
"metadata" JSONB,
|
|
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
|
|
CONSTRAINT "ProviderKeyStatusEvent_pkey" PRIMARY KEY ("id")
|
|
);
|
|
|
|
-- CreateTable
|
|
CREATE TABLE "TelegramPairing" (
|
|
"id" TEXT NOT NULL,
|
|
"telegramUserId" TEXT NOT NULL,
|
|
"telegramUsername" TEXT,
|
|
"displayNameSnapshot" TEXT NOT NULL,
|
|
"codeHash" TEXT NOT NULL,
|
|
"expiresAt" TIMESTAMP(3) NOT NULL,
|
|
"status" "TelegramPairingStatus" NOT NULL DEFAULT 'pending',
|
|
"completedAt" TIMESTAMP(3),
|
|
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
"updatedAt" TIMESTAMP(3) NOT NULL,
|
|
|
|
CONSTRAINT "TelegramPairing_pkey" PRIMARY KEY ("id")
|
|
);
|
|
|
|
-- CreateTable
|
|
CREATE TABLE "TelegramAdminAllowlistEntry" (
|
|
"telegramUserId" TEXT NOT NULL,
|
|
"telegramUsername" TEXT,
|
|
"displayNameSnapshot" TEXT NOT NULL,
|
|
"pairedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
"revokedAt" TIMESTAMP(3),
|
|
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
|
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
"updatedAt" TIMESTAMP(3) NOT NULL,
|
|
|
|
CONSTRAINT "TelegramAdminAllowlistEntry_pkey" PRIMARY KEY ("telegramUserId")
|
|
);
|
|
|
|
-- CreateTable
|
|
CREATE TABLE "AdminAuditLog" (
|
|
"id" TEXT NOT NULL,
|
|
"actorType" "AdminActorType" NOT NULL,
|
|
"actorRef" TEXT,
|
|
"action" TEXT NOT NULL,
|
|
"targetType" TEXT NOT NULL,
|
|
"targetId" TEXT,
|
|
"metadata" JSONB,
|
|
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
|
|
CONSTRAINT "AdminAuditLog_pkey" PRIMARY KEY ("id")
|
|
);
|
|
|
|
-- CreateIndex
|
|
CREATE UNIQUE INDEX "User_email_key" ON "User"("email");
|
|
|
|
-- CreateIndex
|
|
CREATE UNIQUE INDEX "SubscriptionPlan_code_key" ON "SubscriptionPlan"("code");
|
|
|
|
-- CreateIndex
|
|
CREATE INDEX "Subscription_userId_status_idx" ON "Subscription"("userId", "status");
|
|
|
|
-- CreateIndex
|
|
CREATE UNIQUE INDEX "PaymentInvoice_providerInvoiceId_key" ON "PaymentInvoice"("providerInvoiceId");
|
|
|
|
-- CreateIndex
|
|
CREATE INDEX "PaymentInvoice_userId_status_idx" ON "PaymentInvoice"("userId", "status");
|
|
|
|
-- CreateIndex
|
|
CREATE UNIQUE INDEX "GenerationRequest_idempotencyKey_key" ON "GenerationRequest"("idempotencyKey");
|
|
|
|
-- CreateIndex
|
|
CREATE INDEX "GenerationRequest_userId_status_requestedAt_idx" ON "GenerationRequest"("userId", "status", "requestedAt");
|
|
|
|
-- CreateIndex
|
|
CREATE INDEX "GenerationAttempt_providerKeyId_startedAt_idx" ON "GenerationAttempt"("providerKeyId", "startedAt");
|
|
|
|
-- CreateIndex
|
|
CREATE UNIQUE INDEX "GenerationAttempt_generationRequestId_attemptIndex_key" ON "GenerationAttempt"("generationRequestId", "attemptIndex");
|
|
|
|
-- CreateIndex
|
|
CREATE UNIQUE INDEX "GeneratedAsset_objectKey_key" ON "GeneratedAsset"("objectKey");
|
|
|
|
-- CreateIndex
|
|
CREATE INDEX "GeneratedAsset_generationRequestId_idx" ON "GeneratedAsset"("generationRequestId");
|
|
|
|
-- CreateIndex
|
|
CREATE UNIQUE INDEX "UsageLedgerEntry_generationRequestId_key" ON "UsageLedgerEntry"("generationRequestId");
|
|
|
|
-- CreateIndex
|
|
CREATE INDEX "UsageLedgerEntry_userId_createdAt_idx" ON "UsageLedgerEntry"("userId", "createdAt");
|
|
|
|
-- CreateIndex
|
|
CREATE UNIQUE INDEX "ProviderProxy_label_key" ON "ProviderProxy"("label");
|
|
|
|
-- CreateIndex
|
|
CREATE UNIQUE INDEX "ProviderKey_label_key" ON "ProviderKey"("label");
|
|
|
|
-- CreateIndex
|
|
CREATE INDEX "ProviderKey_providerCode_state_roundRobinOrder_idx" ON "ProviderKey"("providerCode", "state", "roundRobinOrder");
|
|
|
|
-- CreateIndex
|
|
CREATE INDEX "ProviderKeyStatusEvent_providerKeyId_createdAt_idx" ON "ProviderKeyStatusEvent"("providerKeyId", "createdAt");
|
|
|
|
-- CreateIndex
|
|
CREATE INDEX "TelegramPairing_telegramUserId_status_idx" ON "TelegramPairing"("telegramUserId", "status");
|
|
|
|
-- CreateIndex
|
|
CREATE INDEX "TelegramPairing_expiresAt_status_idx" ON "TelegramPairing"("expiresAt", "status");
|
|
|
|
-- CreateIndex
|
|
CREATE INDEX "AdminAuditLog_targetType_targetId_createdAt_idx" ON "AdminAuditLog"("targetType", "targetId", "createdAt");
|
|
|
|
-- CreateIndex
|
|
CREATE INDEX "AdminAuditLog_actorType_createdAt_idx" ON "AdminAuditLog"("actorType", "createdAt");
|
|
|
|
-- AddForeignKey
|
|
ALTER TABLE "Subscription" ADD CONSTRAINT "Subscription_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
|
|
|
-- AddForeignKey
|
|
ALTER TABLE "Subscription" ADD CONSTRAINT "Subscription_planId_fkey" FOREIGN KEY ("planId") REFERENCES "SubscriptionPlan"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
|
|
|
-- AddForeignKey
|
|
ALTER TABLE "PaymentInvoice" ADD CONSTRAINT "PaymentInvoice_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
|
|
|
-- AddForeignKey
|
|
ALTER TABLE "PaymentInvoice" ADD CONSTRAINT "PaymentInvoice_subscriptionId_fkey" FOREIGN KEY ("subscriptionId") REFERENCES "Subscription"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
|
|
|
-- AddForeignKey
|
|
ALTER TABLE "GenerationRequest" ADD CONSTRAINT "GenerationRequest_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
|
|
|
-- AddForeignKey
|
|
ALTER TABLE "GenerationAttempt" ADD CONSTRAINT "GenerationAttempt_generationRequestId_fkey" FOREIGN KEY ("generationRequestId") REFERENCES "GenerationRequest"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
|
|
|
-- AddForeignKey
|
|
ALTER TABLE "GenerationAttempt" ADD CONSTRAINT "GenerationAttempt_providerKeyId_fkey" FOREIGN KEY ("providerKeyId") REFERENCES "ProviderKey"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
|
|
|
-- AddForeignKey
|
|
ALTER TABLE "GeneratedAsset" ADD CONSTRAINT "GeneratedAsset_generationRequestId_fkey" FOREIGN KEY ("generationRequestId") REFERENCES "GenerationRequest"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
|
|
|
-- AddForeignKey
|
|
ALTER TABLE "UsageLedgerEntry" ADD CONSTRAINT "UsageLedgerEntry_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
|
|
|
-- AddForeignKey
|
|
ALTER TABLE "UsageLedgerEntry" ADD CONSTRAINT "UsageLedgerEntry_generationRequestId_fkey" FOREIGN KEY ("generationRequestId") REFERENCES "GenerationRequest"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
|
|
|
-- AddForeignKey
|
|
ALTER TABLE "ProviderKey" ADD CONSTRAINT "ProviderKey_proxyId_fkey" FOREIGN KEY ("proxyId") REFERENCES "ProviderProxy"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
|
|
|
-- AddForeignKey
|
|
ALTER TABLE "ProviderKeyStatusEvent" ADD CONSTRAINT "ProviderKeyStatusEvent_providerKeyId_fkey" FOREIGN KEY ("providerKeyId") REFERENCES "ProviderKey"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
|
|