generator client { provider = "prisma-client-js" } datasource db { provider = "mysql" url = env("DATABASE_URL") } enum ProjectStatus { ACTIVE ARCHIVED } enum EnvironmentKind { TEST PRODUCTION } enum DeployRunStatus { PENDING QUEUED RUNNING SUCCESS FAILED CANCELED } enum DeployRunTrigger { MANUAL GITEA_WEBHOOK RETRY } enum RunStepStatus { PENDING RUNNING SUCCESS FAILED SKIPPED CANCELED } enum SecretProvider { JENKINS GITEA WECOM LLM INTERNAL } enum AgentInvocationPurpose { RISK_SUMMARY FAILURE_DIAGNOSIS RUNBOOK_QA RELEASE_NOTES INCIDENT_REVIEW } enum OutboxStatus { PENDING SENT FAILED DEAD } model Project { id String @id @default(cuid()) key String @unique name String repositoryUrl String? @db.VarChar(512) defaultBranch String @default("develop") status ProjectStatus @default(ACTIVE) metadata Json? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt environments Environment[] deployJobs DeployJob[] deployRuns DeployRun[] @@map("projects") } model Environment { id String @id @default(cuid()) projectId String name EnvironmentKind displayName String createdAt DateTime @default(now()) updatedAt DateTime @updatedAt project Project @relation(fields: [projectId], references: [id], onDelete: Cascade) deployJobs DeployJob[] deployRuns DeployRun[] @@unique([projectId, name]) @@index([projectId]) @@map("environments") } model DeployJob { id String @id @default(cuid()) projectId String environmentId String jenkinsJobPath String jenkinsParameters Json? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt project Project @relation(fields: [projectId], references: [id], onDelete: Cascade) environment Environment @relation(fields: [environmentId], references: [id], onDelete: Cascade) deployRuns DeployRun[] @@unique([projectId, environmentId]) @@index([environmentId]) @@map("deploy_jobs") } model DeployRun { id String @id @default(cuid()) projectId String environmentId String jobId String? status DeployRunStatus @default(PENDING) trigger DeployRunTrigger @default(MANUAL) ref String operator String idempotencyKey String @unique jenkinsQueueId String? jenkinsBuildNumber Int? failureSummary String? @db.Text metadata Json? version Int @default(1) startedAt DateTime? finishedAt DateTime? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt project Project @relation(fields: [projectId], references: [id], onDelete: Restrict) environment Environment @relation(fields: [environmentId], references: [id], onDelete: Restrict) job DeployJob? @relation(fields: [jobId], references: [id], onDelete: SetNull) steps RunStep[] auditLogs AuditLog[] agentInvocations AgentInvocation[] outboxMessages OutboxMessage[] @@index([projectId, environmentId, createdAt]) @@index([status, createdAt]) @@map("deploy_runs") } model RunStep { id String @id @default(cuid()) deployRunId String bpmnNodeId String name String status RunStepStatus @default(PENDING) order Int @default(0) errorSummary String? @db.Text metadata Json? startedAt DateTime? finishedAt DateTime? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt deployRun DeployRun @relation(fields: [deployRunId], references: [id], onDelete: Cascade) @@unique([deployRunId, bpmnNodeId]) @@index([deployRunId, order]) @@map("run_steps") } model AuditLog { id String @id @default(cuid()) deployRunId String? actorId String? actorName String? action String resourceType String resourceId String? requestId String? sourceIp String? userAgent String? before Json? after Json? parameterDigest Json? createdAt DateTime @default(now()) deployRun DeployRun? @relation(fields: [deployRunId], references: [id], onDelete: SetNull) @@index([resourceType, resourceId, createdAt]) @@index([actorId, createdAt]) @@map("audit_logs") } model Secret { id String @id @default(cuid()) provider SecretProvider scopeType String scopeId String name String encryptedValue String @db.Text version Int @default(1) rotatedAt DateTime? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt @@unique([provider, scopeType, scopeId, name]) @@index([scopeType, scopeId]) @@map("secrets") } model AgentInvocation { id String @id @default(cuid()) deployRunId String? purpose AgentInvocationPurpose actorId String? actorName String? model String? promptVersion String inputDigest Json outputDigest Json? tokenEstimate Int? status String errorSummary String? @db.Text createdAt DateTime @default(now()) completedAt DateTime? deployRun DeployRun? @relation(fields: [deployRunId], references: [id], onDelete: SetNull) @@index([purpose, createdAt]) @@index([deployRunId, createdAt]) @@map("agent_invocations") } model OutboxMessage { id String @id @default(cuid()) deployRunId String? channel String template String payload Json status OutboxStatus @default(PENDING) attemptCount Int @default(0) nextAttemptAt DateTime? lastError String? @db.Text idempotencyKey String @unique createdAt DateTime @default(now()) updatedAt DateTime @updatedAt deployRun DeployRun? @relation(fields: [deployRunId], references: [id], onDelete: SetNull) @@index([status, nextAttemptAt]) @@map("outbox_messages") }