Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
-- AlterTable
ALTER TABLE "Transaction" ADD COLUMN "failureReason" TEXT;
ALTER TABLE "Transaction" ADD COLUMN "latencyMs" INTEGER;
ALTER TABLE "Transaction" ADD COLUMN "tenantId" TEXT;
ALTER TABLE "Transaction" ADD COLUMN "vaultId" TEXT;

-- CreateTable
CREATE TABLE "Vault" (
"id" TEXT NOT NULL PRIMARY KEY,
"tenantId" TEXT NOT NULL,
"aum" REAL NOT NULL DEFAULT 0,
"tvlUsd" TEXT,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" DATETIME NOT NULL,
"deletedAt" DATETIME
);

-- CreateTable
CREATE TABLE "Strategy" (
"id" TEXT NOT NULL PRIMARY KEY,
"name" TEXT NOT NULL,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" DATETIME NOT NULL
);

-- CreateTable
CREATE TABLE "Allocation" (
"id" TEXT NOT NULL PRIMARY KEY,
"vaultId" TEXT NOT NULL,
"strategyId" TEXT NOT NULL,
"amount" REAL NOT NULL DEFAULT 0,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" DATETIME NOT NULL,
CONSTRAINT "Allocation_vaultId_fkey" FOREIGN KEY ("vaultId") REFERENCES "Vault" ("id") ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT "Allocation_strategyId_fkey" FOREIGN KEY ("strategyId") REFERENCES "Strategy" ("id") ON DELETE CASCADE ON UPDATE CASCADE
);

-- CreateTable
CREATE TABLE "ExposureBreach" (
"id" TEXT NOT NULL PRIMARY KEY,
"vaultId" TEXT NOT NULL,
"strategyId" TEXT NOT NULL,
"attemptedAmount" TEXT NOT NULL,
"reason" TEXT NOT NULL,
"timestamp" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
);

-- CreateTable
CREATE TABLE "WalletTenantAssociation" (
"id" TEXT NOT NULL PRIMARY KEY,
"walletAddress" TEXT NOT NULL,
"tenantId" TEXT NOT NULL,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"deletedAt" DATETIME
);

-- CreateIndex
CREATE INDEX "Vault_tenantId_idx" ON "Vault"("tenantId");

-- CreateIndex
CREATE INDEX "Vault_deletedAt_idx" ON "Vault"("deletedAt");

-- CreateIndex
CREATE INDEX "Allocation_vaultId_idx" ON "Allocation"("vaultId");

-- CreateIndex
CREATE INDEX "Allocation_strategyId_idx" ON "Allocation"("strategyId");

-- CreateIndex
CREATE INDEX "ExposureBreach_vaultId_idx" ON "ExposureBreach"("vaultId");

-- CreateIndex
CREATE INDEX "ExposureBreach_strategyId_idx" ON "ExposureBreach"("strategyId");

-- CreateIndex
CREATE INDEX "ExposureBreach_timestamp_idx" ON "ExposureBreach"("timestamp");

-- CreateIndex
CREATE INDEX "WalletTenantAssociation_walletAddress_tenantId_idx" ON "WalletTenantAssociation"("walletAddress", "tenantId");

-- CreateIndex
CREATE INDEX "WalletTenantAssociation_tenantId_idx" ON "WalletTenantAssociation"("tenantId");

-- CreateIndex
CREATE INDEX "Transaction_vaultId_tenantId_timestamp_idx" ON "Transaction"("vaultId", "tenantId", "timestamp" DESC);

84 changes: 77 additions & 7 deletions backend/prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,17 @@ model SharePriceSnapshot {
}

model Transaction {
id String @id @default(uuid())
user String
amount String
type String
status String?
referralCode String?
timestamp DateTime @default(now())
id String @id @default(uuid())
user String
amount String
type String
status String?
referralCode String?
vaultId String?
tenantId String?
latencyMs Int?
failureReason String?
timestamp DateTime @default(now())

// Issue #895 – query optimisation indices
// Ordered by timestamp DESC to match the default sort on the list endpoint.
Expand All @@ -56,6 +60,7 @@ model Transaction {
@@index([status, timestamp(sort: Desc)])
@@index([user, type, timestamp(sort: Desc)])
@@index([user, status, timestamp(sort: Desc)])
@@index([vaultId, tenantId, timestamp(sort: Desc)])
}

model Referral {
Expand Down Expand Up @@ -605,6 +610,71 @@ model WriteAheadAuditEntry {
@@index([actor])
}

// ─── Vault Strategy Allocation & Exposure Guardrails ─────────────────────────

model Vault {
id String @id @default(uuid())
tenantId String
aum Float @default(0)
tvlUsd String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
deletedAt DateTime?

allocations Allocation[]

@@index([tenantId])
@@index([deletedAt])
}

model Strategy {
id String @id @default(uuid())
name String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt

allocations Allocation[]
}

model Allocation {
id String @id @default(uuid())
vaultId String
strategyId String
amount Float @default(0)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt

vault Vault @relation(fields: [vaultId], references: [id], onDelete: Cascade)
strategy Strategy @relation(fields: [strategyId], references: [id], onDelete: Cascade)

@@index([vaultId])
@@index([strategyId])
}

model ExposureBreach {
id String @id @default(uuid())
vaultId String
strategyId String
attemptedAmount String
reason String
timestamp DateTime @default(now())

@@index([vaultId])
@@index([strategyId])
@@index([timestamp])
}

// ─── Tenant Boundary ─────────────────────────────────────────────────────────

model WalletTenantAssociation {
id String @id @default(uuid())
walletAddress String
tenantId String
createdAt DateTime @default(now())
deletedAt DateTime?

@@index([walletAddress, tenantId])
@@index([tenantId])
model IdempotencyKey {
id String @id @default(uuid())
keyId String
Expand Down
Loading