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") }