4413045f-d05e-4d7a-a70d-81d6be253c85
This commit is contained in:
1 parent
762f3d7373
commit
c6adc67479
18 files changed
+5263
-1
No files matched your search
@@ -105,6 +105,7 @@ model Company {
|
||||
expenses Expense[]
|
||||
tickets Ticket[]
|
||||
agencyApplication AgencyApplication?
|
||||
instances Instance[]
|
||||
}
|
||||
|
||||
model Person {
|
||||
@@ -291,6 +292,10 @@ model License {
|
||||
stripeSubscriptionId String?
|
||||
stripePriceId String?
|
||||
|
||||
// Link to the tenant instance (1:1). Set when this license has a deployed
|
||||
// instance on the Dokploy server.
|
||||
instance Instance?
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
activations LicenseActivation[]
|
||||
}
|
||||
@@ -892,3 +897,90 @@ model CustomFieldValue {
|
||||
|
||||
@@unique([entityType, entityId, fieldDefId])
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Tenant Instance Provisioning (PRD §6: SaaS demo + paid instances via Dokploy)
|
||||
// ---------------------------------------------------------------------------
|
||||
// AOS runs at dfmpanel.eu. Each license may have a tenant instance: an isolated
|
||||
// deployment of restov1 (or another product) running on the Dokploy server,
|
||||
// reachable under <random>.dfmpanel.eu (demo) or the customer's own domain.
|
||||
//
|
||||
// Lifecycle:
|
||||
// requested -> provisioning -> demo_active --(subscribe)--> active
|
||||
// | |
|
||||
// (expired/cancelled) (sub cancelled)
|
||||
// v v
|
||||
// grace <-------------------+
|
||||
// |
|
||||
// (grace elapsed)
|
||||
// v
|
||||
// deleting -> deleted
|
||||
// failed (retried, then alerts operator)
|
||||
|
||||
model Instance {
|
||||
id String @id @default(cuid())
|
||||
licenseId String? @unique // link to License (1:1, nullable for orphan cleanup)
|
||||
license License? @relation(fields: [licenseId], references: [id])
|
||||
companyId String // owning customer
|
||||
company Company @relation(fields: [companyId], references: [id])
|
||||
product String // 'restov1', 'aos-cms', ... (which template to deploy)
|
||||
status String @default("requested") // requested|provisioning|demo_active|active|grace|deleting|deleted|failed
|
||||
plan String @default("pro") // starter|pro|enterprise (resource limits)
|
||||
// Subdomain on the platform domain (e.g. "k7f3a9" -> k7f3a9.dfmpanel.eu)
|
||||
subdomain String @unique
|
||||
// Dokploy server id (for future multi-server; v1 single server)
|
||||
serverId String @default("default")
|
||||
// Lifecycle timestamps
|
||||
demoExpiresAt DateTime?
|
||||
graceEndsAt DateTime?
|
||||
deletedAt DateTime?
|
||||
// Custom domain (customer's own domain, verified via TXT)
|
||||
customDomain String?
|
||||
domainVerificationToken String?
|
||||
domainVerifiedAt DateTime?
|
||||
// Dokploy resource IDs (returned by Dokploy API on creation)
|
||||
dokployAppId String?
|
||||
dokployDbId String?
|
||||
dokployDbName String?
|
||||
dokployDbUser String?
|
||||
dokployDbPassword String? // stored encrypted in production; demo ok plaintext dev
|
||||
// Hetzner DNS record ID (null if using wildcard DNS)
|
||||
dnsRecordId String?
|
||||
// Admin login link (one-time, demo only)
|
||||
adminLoginToken String?
|
||||
adminLoginExpiresAt DateTime?
|
||||
// Provisioning log + metadata
|
||||
metadata String? // JSON: { gitRepo, gitBranch, imageTag, resources }
|
||||
lastError String?
|
||||
lastErrorAt DateTime?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
events InstanceEvent[]
|
||||
jobs ProvisioningJob[]
|
||||
}
|
||||
|
||||
model InstanceEvent {
|
||||
id String @id @default(cuid())
|
||||
instanceId String
|
||||
instance Instance @relation(fields: [instanceId], references: [id], onDelete: Cascade)
|
||||
type String // provision.start, provision.dokploy.created, provision.dns.created, provision.ok, delete.start, delete.dokploy.removed, delete.ok, suspend, reactivate, domain.verify, domain.attached, etc.
|
||||
step String? // sub-step identifier
|
||||
result String // ok|error|pending
|
||||
details String? // JSON
|
||||
createdAt DateTime @default(now())
|
||||
}
|
||||
|
||||
model ProvisioningJob {
|
||||
id String @id @default(cuid())
|
||||
instanceId String
|
||||
instance Instance @relation(fields: [instanceId], references: [id], onDelete: Cascade)
|
||||
kind String // provision|delete|domain|suspend|reactivate
|
||||
step String // current step in the sequence
|
||||
attempts Int @default(0)
|
||||
maxAttempts Int @default(5)
|
||||
lastError String?
|
||||
status String @default("pending") // pending|running|done|failed
|
||||
nextRunAt DateTime @default(now())
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
}
|
||||
Reference in new issue
Block a user