init
This commit is contained in:
commit
c54e888458
67 files changed
+5933
No files matched your search
@@ -0,0 +1,201 @@
|
||||
-- CreateEnum
|
||||
CREATE TYPE "UserRole" AS ENUM ('USER', 'ADMIN');
|
||||
|
||||
-- CreateEnum
|
||||
CREATE TYPE "AuthProvider" AS ENUM ('google', 'email');
|
||||
|
||||
-- CreateEnum
|
||||
CREATE TYPE "AccountStatus" AS ENUM ('active', 'disabled');
|
||||
|
||||
-- CreateEnum
|
||||
CREATE TYPE "LedgerKind" AS ENUM ('welcomeGrant', 'settle', 'refund', 'topup', 'adjustment');
|
||||
|
||||
-- CreateEnum
|
||||
CREATE TYPE "GatewayJobStatus" AS ENUM ('posted', 'acked', 'delivered', 'claimed', 'cancelled', 'timed_out', 'failed');
|
||||
|
||||
-- CreateEnum
|
||||
CREATE TYPE "TopupStatus" AS ENUM ('requires_payment', 'processing', 'succeeded', 'credited', 'failed', 'refunded');
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "User" (
|
||||
"id" TEXT NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
"email" TEXT NOT NULL,
|
||||
"emailVerified" BOOLEAN NOT NULL DEFAULT false,
|
||||
"verificationToken" TEXT,
|
||||
"authProvider" "AuthProvider" NOT NULL,
|
||||
"googleSub" TEXT,
|
||||
"passwordHash" TEXT,
|
||||
"role" "UserRole" NOT NULL DEFAULT 'USER',
|
||||
"stripeCustomerId" TEXT,
|
||||
"country" TEXT,
|
||||
|
||||
CONSTRAINT "User_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "ApiKey" (
|
||||
"id" TEXT NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"key" TEXT NOT NULL,
|
||||
"name" TEXT NOT NULL DEFAULT '',
|
||||
"lastUsedAt" TIMESTAMP(3),
|
||||
"scopeMaxXbzzPerDay" DECIMAL(78,0),
|
||||
"modelAllowlist" TEXT[] DEFAULT ARRAY[]::TEXT[],
|
||||
"userId" TEXT NOT NULL,
|
||||
|
||||
CONSTRAINT "ApiKey_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "Account" (
|
||||
"id" TEXT NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
"status" "AccountStatus" NOT NULL DEFAULT 'active',
|
||||
"balanceXbzzWei" DECIMAL(78,0) NOT NULL DEFAULT 0,
|
||||
"reservedXbzzWei" DECIMAL(78,0) NOT NULL DEFAULT 0,
|
||||
"userId" TEXT NOT NULL,
|
||||
|
||||
CONSTRAINT "Account_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "LedgerEntry" (
|
||||
"id" TEXT NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"kind" "LedgerKind" NOT NULL,
|
||||
"deltaXbzzWei" DECIMAL(78,0) NOT NULL,
|
||||
"idempotencyKey" TEXT NOT NULL,
|
||||
"note" TEXT,
|
||||
"accountId" TEXT NOT NULL,
|
||||
"gatewayJobId" TEXT,
|
||||
"topupId" TEXT,
|
||||
|
||||
CONSTRAINT "LedgerEntry_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "GatewayJob" (
|
||||
"id" TEXT NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
"routingId" TEXT NOT NULL,
|
||||
"onChainJobId" TEXT,
|
||||
"requestHash" TEXT,
|
||||
"responseHash" TEXT,
|
||||
"provider" TEXT NOT NULL,
|
||||
"modelId" TEXT NOT NULL,
|
||||
"estimatedMaxXbzzWei" DECIMAL(78,0) NOT NULL,
|
||||
"actualXbzzWei" DECIMAL(78,0),
|
||||
"status" "GatewayJobStatus" NOT NULL DEFAULT 'posted',
|
||||
"postedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"ackedAt" TIMESTAMP(3),
|
||||
"deliveredAt" TIMESTAMP(3),
|
||||
"claimedAt" TIMESTAMP(3),
|
||||
"ackDeadline" TIMESTAMP(3),
|
||||
"deliveryDeadline" TIMESTAMP(3),
|
||||
"promptTokens" INTEGER,
|
||||
"completionTokens" INTEGER,
|
||||
"promptRedacted" TEXT,
|
||||
"responseRedacted" TEXT,
|
||||
"errorMessage" TEXT,
|
||||
"userId" TEXT NOT NULL,
|
||||
|
||||
CONSTRAINT "GatewayJob_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "Topup" (
|
||||
"id" TEXT NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
"status" "TopupStatus" NOT NULL DEFAULT 'requires_payment',
|
||||
"stripePaymentIntent" TEXT NOT NULL,
|
||||
"amountUsdCents" INTEGER NOT NULL,
|
||||
"creditedXbzzWei" DECIMAL(78,0),
|
||||
"usdPerXbzzAtCredit" DECIMAL(18,8),
|
||||
"error" TEXT,
|
||||
"userId" TEXT NOT NULL,
|
||||
|
||||
CONSTRAINT "Topup_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "User_email_key" ON "User"("email");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "User_verificationToken_key" ON "User"("verificationToken");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "User_googleSub_key" ON "User"("googleSub");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "User_stripeCustomerId_key" ON "User"("stripeCustomerId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "User_authProvider_googleSub_idx" ON "User"("authProvider", "googleSub");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "ApiKey_key_key" ON "ApiKey"("key");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "ApiKey_userId_idx" ON "ApiKey"("userId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "Account_userId_key" ON "Account"("userId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "LedgerEntry_idempotencyKey_key" ON "LedgerEntry"("idempotencyKey");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "LedgerEntry_accountId_createdAt_idx" ON "LedgerEntry"("accountId", "createdAt" DESC);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "LedgerEntry_kind_idx" ON "LedgerEntry"("kind");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "GatewayJob_routingId_key" ON "GatewayJob"("routingId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "GatewayJob_onChainJobId_key" ON "GatewayJob"("onChainJobId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "GatewayJob_userId_createdAt_idx" ON "GatewayJob"("userId", "createdAt" DESC);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "GatewayJob_status_idx" ON "GatewayJob"("status");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "GatewayJob_onChainJobId_idx" ON "GatewayJob"("onChainJobId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "Topup_stripePaymentIntent_key" ON "Topup"("stripePaymentIntent");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "Topup_userId_createdAt_idx" ON "Topup"("userId", "createdAt" DESC);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "Topup_status_idx" ON "Topup"("status");
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "ApiKey" ADD CONSTRAINT "ApiKey_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "Account" ADD CONSTRAINT "Account_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "LedgerEntry" ADD CONSTRAINT "LedgerEntry_accountId_fkey" FOREIGN KEY ("accountId") REFERENCES "Account"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "LedgerEntry" ADD CONSTRAINT "LedgerEntry_gatewayJobId_fkey" FOREIGN KEY ("gatewayJobId") REFERENCES "GatewayJob"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "LedgerEntry" ADD CONSTRAINT "LedgerEntry_topupId_fkey" FOREIGN KEY ("topupId") REFERENCES "Topup"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "GatewayJob" ADD CONSTRAINT "GatewayJob_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "Topup" ADD CONSTRAINT "Topup_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
@@ -0,0 +1,3 @@
|
||||
# Please do not edit this file manually
|
||||
# It should be added in your version-control system (e.g., Git)
|
||||
provider = "postgresql"
|
||||
@@ -0,0 +1,223 @@
|
||||
// Hosted T4T Gateway — Prisma schema.
|
||||
//
|
||||
// One operator wallet handles all on-chain transactions. Tenants are off-chain
|
||||
// ledger entries denominated in xBZZ wei (Decimal(78, 0) holds any uint256).
|
||||
// USD is never in the billing path — only in `Topup` rows for Phase 2 Stripe.
|
||||
|
||||
generator client {
|
||||
provider = "prisma-client-js"
|
||||
}
|
||||
|
||||
// Connection URL + seed config live in prisma.config.ts (Prisma 7).
|
||||
datasource db {
|
||||
provider = "postgresql"
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Enums
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
enum UserRole {
|
||||
USER
|
||||
ADMIN
|
||||
}
|
||||
|
||||
enum AuthProvider {
|
||||
google
|
||||
email
|
||||
}
|
||||
|
||||
enum AccountStatus {
|
||||
active
|
||||
disabled
|
||||
}
|
||||
|
||||
enum LedgerKind {
|
||||
welcomeGrant
|
||||
settle
|
||||
refund
|
||||
topup
|
||||
adjustment
|
||||
}
|
||||
|
||||
enum GatewayJobStatus {
|
||||
posted
|
||||
acked
|
||||
delivered
|
||||
claimed
|
||||
cancelled
|
||||
timed_out
|
||||
failed
|
||||
}
|
||||
|
||||
enum TopupStatus {
|
||||
requires_payment
|
||||
processing
|
||||
succeeded
|
||||
credited
|
||||
failed
|
||||
refunded
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// User + auth
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
model User {
|
||||
id String @id @default(uuid())
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
email String @unique
|
||||
emailVerified Boolean @default(false)
|
||||
// Single-use email verification token (NULL once consumed). For Phase 1 we
|
||||
// surface this in the signup response in dev/test mode; Phase 1.5 wires up
|
||||
// a real outbound mailer and stops echoing the token back.
|
||||
verificationToken String? @unique
|
||||
authProvider AuthProvider
|
||||
googleSub String? @unique
|
||||
passwordHash String?
|
||||
role UserRole @default(USER)
|
||||
|
||||
// Phase 2 — Stripe handles billing address + sanctions screening
|
||||
stripeCustomerId String? @unique
|
||||
country String? // ISO 3166-1 alpha-2, mirrored from Stripe
|
||||
|
||||
account Account?
|
||||
apiKeys ApiKey[]
|
||||
gatewayJobs GatewayJob[]
|
||||
topups Topup[]
|
||||
|
||||
@@index([authProvider, googleSub])
|
||||
}
|
||||
|
||||
model ApiKey {
|
||||
id String @id @default(uuid())
|
||||
createdAt DateTime @default(now())
|
||||
key String @unique @default(uuid())
|
||||
name String @default("")
|
||||
lastUsedAt DateTime?
|
||||
scopeMaxXbzzPerDay Decimal? @db.Decimal(78, 0)
|
||||
modelAllowlist String[] @default([])
|
||||
|
||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||
userId String
|
||||
|
||||
@@index([userId])
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Account + ledger
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
model Account {
|
||||
id String @id @default(uuid())
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
status AccountStatus @default(active)
|
||||
balanceXbzzWei Decimal @default(0) @db.Decimal(78, 0)
|
||||
reservedXbzzWei Decimal @default(0) @db.Decimal(78, 0)
|
||||
|
||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||
userId String @unique
|
||||
|
||||
ledgerEntries LedgerEntry[]
|
||||
}
|
||||
|
||||
model LedgerEntry {
|
||||
id String @id @default(uuid())
|
||||
createdAt DateTime @default(now())
|
||||
kind LedgerKind
|
||||
deltaXbzzWei Decimal @db.Decimal(78, 0)
|
||||
idempotencyKey String @unique
|
||||
note String?
|
||||
|
||||
account Account @relation(fields: [accountId], references: [id], onDelete: Cascade)
|
||||
accountId String
|
||||
|
||||
gatewayJob GatewayJob? @relation(fields: [gatewayJobId], references: [id], onDelete: SetNull)
|
||||
gatewayJobId String?
|
||||
|
||||
topup Topup? @relation(fields: [topupId], references: [id], onDelete: SetNull)
|
||||
topupId String?
|
||||
|
||||
@@index([accountId, createdAt(sort: Desc)])
|
||||
@@index([kind])
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Gateway jobs (per-chat-completion, settled on JobClaimed)
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
model GatewayJob {
|
||||
id String @id @default(uuid())
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
// Routing
|
||||
routingId String @unique // local routing id (keccak of request hash etc.)
|
||||
onChainJobId String? @unique // bytes32 from JobEscrow.JobPosted
|
||||
requestHash String? // Swarm chunk ref of encrypted request
|
||||
responseHash String? // Swarm chunk ref of encrypted response
|
||||
|
||||
// Counterparties / model
|
||||
provider String // 0x address selected by the gateway
|
||||
modelId String
|
||||
|
||||
// Billing (xBZZ-denominated; markup baked in)
|
||||
estimatedMaxXbzzWei Decimal @db.Decimal(78, 0)
|
||||
actualXbzzWei Decimal? @db.Decimal(78, 0)
|
||||
|
||||
// Lifecycle
|
||||
status GatewayJobStatus @default(posted)
|
||||
postedAt DateTime @default(now())
|
||||
ackedAt DateTime?
|
||||
deliveredAt DateTime?
|
||||
claimedAt DateTime?
|
||||
ackDeadline DateTime?
|
||||
deliveryDeadline DateTime?
|
||||
|
||||
// Token accounting (from JobClaimed actualPayment)
|
||||
promptTokens Int?
|
||||
completionTokens Int?
|
||||
|
||||
// Optional payload retention (off by default; T4T_PERSIST_PAYLOADS-style)
|
||||
promptRedacted String?
|
||||
responseRedacted String?
|
||||
errorMessage String?
|
||||
|
||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||
userId String
|
||||
|
||||
ledgerEntries LedgerEntry[]
|
||||
|
||||
@@index([userId, createdAt(sort: Desc)])
|
||||
@@index([status])
|
||||
@@index([onChainJobId])
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Stripe top-ups (Phase 2)
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
model Topup {
|
||||
id String @id @default(uuid())
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
status TopupStatus @default(requires_payment)
|
||||
|
||||
stripePaymentIntent String @unique
|
||||
amountUsdCents Int
|
||||
|
||||
creditedXbzzWei Decimal? @db.Decimal(78, 0)
|
||||
usdPerXbzzAtCredit Decimal? @db.Decimal(18, 8)
|
||||
|
||||
error String?
|
||||
|
||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||
userId String
|
||||
|
||||
ledgerEntries LedgerEntry[]
|
||||
|
||||
@@index([userId, createdAt(sort: Desc)])
|
||||
@@index([status])
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
// Phase 1 has no seed data — accounts are created on signup.
|
||||
// Placeholder for future Config table (e.g. operator metadata) or test fixtures.
|
||||
import { PrismaClient } from '@prisma/client';
|
||||
|
||||
const prisma = new PrismaClient();
|
||||
|
||||
async function main() {
|
||||
console.log('No seed data to insert in v1.');
|
||||
}
|
||||
|
||||
main()
|
||||
.catch((err) => {
|
||||
console.error(err);
|
||||
process.exit(1);
|
||||
})
|
||||
.finally(async () => {
|
||||
await prisma.$disconnect();
|
||||
});
|
||||
Reference in new issue
Block a user