- Complete monorepo structure with pnpm workspaces - Prisma database schema with 20+ entities - NestJS API with 9 core modules - BullMQ orchestration worker - AWS and Azure provider adapters - Docker Compose infrastructure - Complete documentation
390 lines
12 KiB
Plaintext
390 lines
12 KiB
Plaintext
generator client {
|
|
provider = "prisma-client-js"
|
|
}
|
|
|
|
datasource db {
|
|
provider = "postgresql"
|
|
url = env("DATABASE_URL")
|
|
}
|
|
|
|
// ============================================================================
|
|
// TENANCY & IDENTITY
|
|
// ============================================================================
|
|
|
|
model Tenant {
|
|
id String @id @default(uuid())
|
|
name String
|
|
slug String @unique
|
|
status String @default("active") // active, suspended, terminated
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
users User[]
|
|
orders ServiceOrder[]
|
|
services Service[]
|
|
apiKeys ApiKey[]
|
|
webhookEndpoints WebhookEndpoint[]
|
|
providerAccounts ProviderAccount[]
|
|
invoices Invoice[]
|
|
|
|
@@map("tenants")
|
|
}
|
|
|
|
model User {
|
|
id String @id @default(uuid())
|
|
tenantId String
|
|
email String @unique
|
|
name String
|
|
status String @default("active")
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
tenant Tenant @relation(fields: [tenantId], references: [id])
|
|
roles Role[]
|
|
orders ServiceOrder[]
|
|
|
|
@@map("users")
|
|
}
|
|
|
|
model Role {
|
|
id String @id @default(uuid())
|
|
userId String
|
|
name String // admin, operator, viewer
|
|
permissions Json @default("{}")
|
|
createdAt DateTime @default(now())
|
|
|
|
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
|
|
@@map("roles")
|
|
}
|
|
|
|
// ============================================================================
|
|
// PROVIDERS & CONNECTIVITY
|
|
// ============================================================================
|
|
|
|
model Provider {
|
|
id String @id @default(uuid())
|
|
name String
|
|
type String // aws, azure, carrier, exchange
|
|
status String @default("active")
|
|
metadata Json @default("{}")
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
endpoints Endpoint[]
|
|
productOfferings ProductOffering[]
|
|
orders ServiceOrder[]
|
|
accounts ProviderAccount[]
|
|
|
|
@@map("providers")
|
|
}
|
|
|
|
model ProviderAccount {
|
|
id String @id @default(uuid())
|
|
tenantId String
|
|
providerId String
|
|
accountId String
|
|
credentials Json // encrypted
|
|
status String @default("active")
|
|
metadata Json @default("{}")
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
tenant Tenant @relation(fields: [tenantId], references: [id])
|
|
provider Provider @relation(fields: [providerId], references: [id])
|
|
|
|
@@unique([tenantId, providerId, accountId])
|
|
@@map("provider_accounts")
|
|
}
|
|
|
|
model Endpoint {
|
|
id String @id @default(uuid())
|
|
providerId String
|
|
kind String // cloud_region, datacenter, exchange, customer_site
|
|
region String?
|
|
metro String?
|
|
location String?
|
|
status String @default("available")
|
|
metadata Json @default("{}")
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
provider Provider @relation(fields: [providerId], references: [id])
|
|
sourceOrders ServiceOrder[] @relation("SourceEndpoint")
|
|
targetOrders ServiceOrder[] @relation("TargetEndpoint")
|
|
|
|
@@map("endpoints")
|
|
}
|
|
|
|
// ============================================================================
|
|
// CATALOG & PRODUCTS
|
|
// ============================================================================
|
|
|
|
model ProductOffering {
|
|
id String @id @default(uuid())
|
|
providerId String
|
|
name String
|
|
description String?
|
|
type String // cloud_interconnect, multi_cloud, partner_connect
|
|
status String @default("active")
|
|
pricing Json @default("{}")
|
|
metadata Json @default("{}")
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
provider Provider @relation(fields: [providerId], references: [id])
|
|
orders ServiceOrder[]
|
|
|
|
@@map("product_offerings")
|
|
}
|
|
|
|
// ============================================================================
|
|
// ORDERS & SERVICES
|
|
// ============================================================================
|
|
|
|
model Quote {
|
|
id String @id @default(uuid())
|
|
tenantId String
|
|
productOfferingId String
|
|
sourceEndpointId String
|
|
targetEndpointId String
|
|
bandwidthMbps Int
|
|
monthlyRecurring Decimal @db.Decimal(10, 2)
|
|
setupFee Decimal @db.Decimal(10, 2)
|
|
currency String @default("USD")
|
|
validUntil DateTime
|
|
status String @default("draft") // draft, valid, expired, accepted
|
|
metadata Json @default("{}")
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
@@map("quotes")
|
|
}
|
|
|
|
model ServiceOrder {
|
|
id String @id @default(uuid())
|
|
tenantId String
|
|
userId String
|
|
productOfferingId String
|
|
providerId String
|
|
sourceEndpointId String
|
|
targetEndpointId String
|
|
bandwidthMbps Int
|
|
status String @default("draft")
|
|
externalReference String?
|
|
quoteId String?
|
|
metadata Json @default("{}")
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
tenant Tenant @relation(fields: [tenantId], references: [id])
|
|
user User @relation(fields: [userId], references: [id])
|
|
productOffering ProductOffering @relation(fields: [productOfferingId], references: [id])
|
|
provider Provider @relation(fields: [providerId], references: [id])
|
|
sourceEndpoint Endpoint @relation("SourceEndpoint", fields: [sourceEndpointId], references: [id])
|
|
targetEndpoint Endpoint @relation("TargetEndpoint", fields: [targetEndpointId], references: [id])
|
|
service Service?
|
|
provisioningTasks ProvisioningTask[]
|
|
|
|
@@map("service_orders")
|
|
}
|
|
|
|
model Service {
|
|
id String @id @default(uuid())
|
|
orderId String @unique
|
|
tenantId String
|
|
status String @default("provisioning")
|
|
activatedAt DateTime?
|
|
suspendedAt DateTime?
|
|
terminatedAt DateTime?
|
|
metadata Json @default("{}")
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
order ServiceOrder @relation(fields: [orderId], references: [id])
|
|
tenant Tenant @relation(fields: [tenantId], references: [id])
|
|
usageRecords UsageRecord[]
|
|
inventoryRecords InventoryRecord[]
|
|
|
|
@@map("services")
|
|
}
|
|
|
|
// ============================================================================
|
|
// PROVISIONING & ORCHESTRATION
|
|
// ============================================================================
|
|
|
|
model ProvisioningTask {
|
|
id String @id @default(uuid())
|
|
orderId String
|
|
taskType String // validate, provision, configure, activate
|
|
status String @default("pending")
|
|
adapterName String?
|
|
externalTaskId String?
|
|
retryCount Int @default(0)
|
|
maxRetries Int @default(3)
|
|
error String?
|
|
metadata Json @default("{}")
|
|
startedAt DateTime?
|
|
completedAt DateTime?
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
order ServiceOrder @relation(fields: [orderId], references: [id])
|
|
|
|
@@map("provisioning_tasks")
|
|
}
|
|
|
|
// ============================================================================
|
|
// INVENTORY & MONITORING
|
|
// ============================================================================
|
|
|
|
model InventoryRecord {
|
|
id String @id @default(uuid())
|
|
serviceId String
|
|
recordType String // connection, circuit, port
|
|
externalId String
|
|
providerData Json @default("{}")
|
|
status String
|
|
lastSyncedAt DateTime @default(now())
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
service Service @relation(fields: [serviceId], references: [id])
|
|
|
|
@@map("inventory_records")
|
|
}
|
|
|
|
// ============================================================================
|
|
// BILLING
|
|
// ============================================================================
|
|
|
|
model UsageRecord {
|
|
id String @id @default(uuid())
|
|
serviceId String
|
|
recordType String // bandwidth, port_hour, data_transfer
|
|
quantity Decimal @db.Decimal(15, 4)
|
|
unit String
|
|
startTime DateTime
|
|
endTime DateTime
|
|
metadata Json @default("{}")
|
|
createdAt DateTime @default(now())
|
|
|
|
service Service @relation(fields: [serviceId], references: [id])
|
|
|
|
@@map("usage_records")
|
|
}
|
|
|
|
model Invoice {
|
|
id String @id @default(uuid())
|
|
tenantId String
|
|
invoiceNumber String @unique
|
|
status String @default("draft")
|
|
subtotal Decimal @db.Decimal(10, 2)
|
|
tax Decimal @db.Decimal(10, 2)
|
|
total Decimal @db.Decimal(10, 2)
|
|
currency String @default("USD")
|
|
periodStart DateTime
|
|
periodEnd DateTime
|
|
dueDate DateTime
|
|
paidAt DateTime?
|
|
metadata Json @default("{}")
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
tenant Tenant @relation(fields: [tenantId], references: [id])
|
|
|
|
@@map("invoices")
|
|
}
|
|
|
|
// ============================================================================
|
|
// API & WEBHOOKS
|
|
// ============================================================================
|
|
|
|
model ApiKey {
|
|
id String @id @default(uuid())
|
|
tenantId String
|
|
name String
|
|
keyHash String @unique
|
|
scopes Json @default("[]")
|
|
status String @default("active")
|
|
lastUsedAt DateTime?
|
|
expiresAt DateTime?
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
tenant Tenant @relation(fields: [tenantId], references: [id])
|
|
|
|
@@map("api_keys")
|
|
}
|
|
|
|
model WebhookEndpoint {
|
|
id String @id @default(uuid())
|
|
tenantId String
|
|
url String
|
|
events Json @default("[]")
|
|
secret String
|
|
status String @default("active")
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
tenant Tenant @relation(fields: [tenantId], references: [id])
|
|
deliveries WebhookDelivery[]
|
|
|
|
@@map("webhook_endpoints")
|
|
}
|
|
|
|
model WebhookDelivery {
|
|
id String @id @default(uuid())
|
|
endpointId String
|
|
eventType String
|
|
payload Json
|
|
status String @default("pending")
|
|
attempts Int @default(0)
|
|
lastAttempt DateTime?
|
|
response String?
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
endpoint WebhookEndpoint @relation(fields: [endpointId], references: [id])
|
|
|
|
@@map("webhook_deliveries")
|
|
}
|
|
|
|
// ============================================================================
|
|
// AUDIT & INCIDENTS
|
|
// ============================================================================
|
|
|
|
model AuditEvent {
|
|
id String @id @default(uuid())
|
|
aggregateType String
|
|
aggregateId String
|
|
eventType String
|
|
actorId String?
|
|
actorType String?
|
|
payload Json @default("{}")
|
|
ipAddress String?
|
|
userAgent String?
|
|
createdAt DateTime @default(now())
|
|
|
|
@@index([aggregateType, aggregateId])
|
|
@@index([eventType])
|
|
@@index([createdAt])
|
|
@@map("audit_events")
|
|
}
|
|
|
|
model Incident {
|
|
id String @id @default(uuid())
|
|
tenantId String?
|
|
serviceId String?
|
|
severity String // critical, high, medium, low
|
|
status String @default("open")
|
|
title String
|
|
description String
|
|
metadata Json @default("{}")
|
|
resolvedAt DateTime?
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
@@map("incidents")
|
|
}
|