generator client { provider = "prisma-client-js" binaryTargets = ["native", "linux-musl-openssl-3.0.x"] } datasource db { provider = "postgresql" url = env("DATABASE_URL") } enum ProjectStatus { active archived paused } enum FeatureStatus { todo in_progress done } enum FeatureLifecycle { feature_candidate planned active implemented verified production_proven deprecated archived } enum ApprovalState { pending approved rejected blocked } enum EvidenceStrength { weak medium strong verified } enum VerificationState { unverified needs_evidence verified blocked } enum ReviewStatus { pending accepted rejected merged converted } enum UserRole { owner member } enum ProjectAccessRole { owner editor reviewer reader } enum GiteaAccessMode { read_only read_write } enum RepositoryRole { primary frontend backend infra docs shared other } enum RepositorySyncStatus { unverified ready degraded unavailable } enum PortfolioRepositoryStatus { discovered onboarded excluded unavailable } enum DeliveryStatus { draft awaiting_approval approved executing validating pull_request_open merged verified released blocked failed cancelled superseded } enum DeliveryChangeOperation { create update delete rename } enum DeliveryValidationStatus { pending passed failed skipped } enum ExternalOperationStatus { prepared executing succeeded failed unknown } enum AnalysisJobKind { portfolio_health } enum AnalysisJobStatus { queued running succeeded partial failed cancelled } enum AnalysisJobItemStatus { pending running succeeded failed cancelled } enum FindingSeverity { info warning critical } enum FindingStatus { new triaged issue_open investigating planned fixing verifying resolved regressed suppressed } enum InvestigationStatus { collecting ready concluded planned fixing verifying resolved failed cancelled } enum IssueSyncMode { manual review automatic } enum EntityType { project project_dna workspace_state feature_group feature evidence context_pack context_pack_section memory_rule knowledge_item documentation_item review_queue_item capture_item accepted_truth_item project_update operating_log_entry current_state_report release_evidence_record handoff_bundle codex_task codex_run_import blueprint_graph blueprint_node blueprint_node_run brainstorm_session initiative repository_finding finding_investigation gitea_issue idempotency_record entity_relation activity_event } model Project { id String @id @default(cuid()) slug String @unique readableId String? name String description String domain String status ProjectStatus @default(active) health Int @default(0) healthStatus String activeContextPackId String? createdBy String @default("system") updatedBy String? sourceType String @default("fixture_seed") archivedAt DateTime? deletedAt DateTime? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt dna ProjectDNA? workspaceState WorkspaceState? featureGroups FeatureGroup[] features Feature[] evidence Evidence[] contextPacks ContextPack[] memoryRules MemoryRule[] knowledgeItems KnowledgeItem[] documentationItems DocumentationItem[] reviewQueueItems ReviewQueueItem[] captureItems CaptureItem[] acceptedTruthItems AcceptedTruthItem[] projectUpdates ProjectUpdate[] operatingLogEntries OperatingLogEntry[] currentStateReports CurrentStateReport[] releaseEvidenceRecords ReleaseEvidenceRecord[] handoffBundles HandoffBundle[] codexTasks CodexTask[] codexRunImports CodexRunImport[] entityRelations EntityRelation[] activityEvents ActivityEvent[] blueprintGraphs BlueprintGraph[] blueprintNodes BlueprintNode[] blueprintNodeRuns BlueprintNodeRun[] brainstormSessions BrainstormSession[] initiatives Initiative[] memberships ProjectMembership[] giteaRepositories GiteaRepositoryLink[] sourceItems ProjectSource[] portfolioRepositories PortfolioRepository[] deliveryPlans DeliveryPlan[] repositoryFindings RepositoryFinding[] findingInvestigations FindingInvestigation[] findingAutomationPolicy FindingAutomationPolicy? externalOperations ExternalOperation[] outboxEvents OutboxEvent[] mcpAuditEvents McpAuditEvent[] workGraphNodes WorkGraphNode[] workGraphDependencies WorkGraphDependency[] workGraphAuditEvents WorkGraphAuditEvent[] workGraphEvidence WorkGraphEvidence[] savedViews ProjectSavedView[] portfolioPins ProjectPortfolioPin[] diagnosticRuns DiagnosticRun[] definitionOfDone ProjectDefinitionOfDone? @@index([status]) @@index([activeContextPackId]) @@index([deletedAt]) @@index([updatedAt]) } model PortfolioRepository { id String @id @default(cuid()) owner String repository String projectId String? description String? defaultBranch String htmlUrl String? private Boolean @default(true) archived Boolean @default(false) canPush Boolean @default(false) status PortfolioRepositoryStatus @default(discovered) exclusionReason String? firstSeenAt DateTime @default(now()) lastSeenAt DateTime @default(now()) onboardedAt DateTime? excludedAt DateTime? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt project Project? @relation(fields: [projectId], references: [id], onDelete: SetNull) @@unique([owner, repository]) @@index([status, lastSeenAt]) @@index([projectId]) } model GiteaRepositoryLink { id String @id @default(cuid()) projectId String owner String repository String defaultBranch String accessMode GiteaAccessMode @default(read_write) role RepositoryRole @default(primary) isPrimary Boolean @default(true) syncStatus RepositorySyncStatus @default(unverified) capabilitiesJson Json? linkedBy String lastVerifiedAt DateTime? lastSyncAt DateTime? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt project Project @relation(fields: [projectId], references: [id], onDelete: Cascade) deliveryRuns DeliveryRun[] analysisJobItems AnalysisJobItem[] repositoryFindings RepositoryFinding[] sourceItems ProjectSource[] @@unique([owner, repository]) @@index([projectId, isPrimary]) @@index([projectId, role]) @@index([owner, repository]) } model ProjectSource { id String @id @default(cuid()) projectId String repositoryLinkId String? title String kind String @default("document") inputMode String @default("git") path String? url String? content String summary String status String @default("processed") branch String? contentSha String? commitSha String? lastSyncedAt DateTime? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt project Project @relation(fields: [projectId], references: [id], onDelete: Cascade) repositoryLink GiteaRepositoryLink? @relation(fields: [repositoryLinkId], references: [id], onDelete: Cascade) @@unique([repositoryLinkId, path]) @@index([projectId, status]) @@index([repositoryLinkId, lastSyncedAt]) } model AnalysisJob { id String @id @default(cuid()) kind AnalysisJobKind @default(portfolio_health) status AnalysisJobStatus @default(queued) actor String requestJson Json requestHash String activeDedupeKey String? @unique progressCurrent Int @default(0) progressTotal Int @default(0) summaryText String? summaryJson Json? errorCode String? cancelRequestedAt DateTime? queuedAt DateTime @default(now()) startedAt DateTime? heartbeatAt DateTime? completedAt DateTime? expiresAt DateTime createdAt DateTime @default(now()) updatedAt DateTime @updatedAt items AnalysisJobItem[] @@index([status, queuedAt]) @@index([actor, createdAt]) @@index([expiresAt]) } model AnalysisJobItem { id String @id @default(cuid()) jobId String repositoryLinkId String? projectId String? projectSlug String? projectName String? owner String repository String defaultBranch String accessMode GiteaAccessMode sequence Int status AnalysisJobItemStatus @default(pending) summary String? detailJson Json? findingCount Int @default(0) errorCode String? startedAt DateTime? completedAt DateTime? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt job AnalysisJob @relation(fields: [jobId], references: [id], onDelete: Cascade) repositoryLink GiteaRepositoryLink? @relation(fields: [repositoryLinkId], references: [id], onDelete: SetNull) findingOccurrences FindingOccurrence[] @@unique([jobId, owner, repository]) @@index([jobId, sequence]) @@index([projectId, createdAt]) @@index([repositoryLinkId, createdAt]) } model RepositoryFinding { id String @id @default(cuid()) fingerprint String @unique projectId String? repositoryLinkId String? owner String repository String ruleCode String subject String title String message String severity FindingSeverity confidence Int @default(90) riskScore Int @default(0) status FindingStatus @default(new) occurrenceCount Int @default(1) clearCount Int @default(0) firstSeenAt DateTime @default(now()) lastSeenAt DateTime @default(now()) resolvedAt DateTime? suppressedAt DateTime? suppressedUntil DateTime? suppressionReason String? lastAnalysisJobId String? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt project Project? @relation(fields: [projectId], references: [id], onDelete: SetNull) repositoryLink GiteaRepositoryLink? @relation(fields: [repositoryLinkId], references: [id], onDelete: SetNull) occurrences FindingOccurrence[] issueLink GiteaIssueLink? investigations FindingInvestigation[] @@index([projectId, status, severity]) @@index([repositoryLinkId, status]) @@index([owner, repository, status]) @@index([lastSeenAt]) } model FindingOccurrence { id String @id @default(cuid()) findingId String analysisJobItemId String observed Boolean @default(true) detailJson Json? createdAt DateTime @default(now()) finding RepositoryFinding @relation(fields: [findingId], references: [id], onDelete: Cascade) analysisJobItem AnalysisJobItem @relation(fields: [analysisJobItemId], references: [id], onDelete: Cascade) @@unique([findingId, analysisJobItemId]) @@index([analysisJobItemId]) } model GiteaIssueLink { id String @id @default(cuid()) findingId String @unique owner String repository String issueNumber Int issueUrl String state String @default("open") title String bodyFingerprint String lastSyncedAt DateTime @default(now()) closedAt DateTime? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt finding RepositoryFinding @relation(fields: [findingId], references: [id], onDelete: Cascade) @@unique([owner, repository, issueNumber]) @@index([state, updatedAt]) } model FindingInvestigation { id String @id @default(cuid()) findingId String projectId String? deliveryPlanId String? @unique status InvestigationStatus @default(collecting) actor String contextJson Json diagnosis String? rootCause String? proposedChangesJson Json @default("[]") confidence Int? conclusion String? startedAt DateTime @default(now()) concludedAt DateTime? completedAt DateTime? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt finding RepositoryFinding @relation(fields: [findingId], references: [id], onDelete: Cascade) project Project? @relation(fields: [projectId], references: [id], onDelete: SetNull) deliveryPlan DeliveryPlan? @relation(fields: [deliveryPlanId], references: [id], onDelete: SetNull) @@index([findingId, createdAt]) @@index([projectId, status]) } model FindingAutomationPolicy { id String @id @default(cuid()) projectId String @unique enabled Boolean @default(true) issueSyncMode IssueSyncMode @default(review) minimumSeverity FindingSeverity @default(warning) minimumOccurrences Int @default(2) maxIssuesPerRun Int @default(5) autoCloseResolved Boolean @default(true) autoReopenRegressed Boolean @default(true) scheduledAnalysis Boolean @default(true) scheduleMinutes Int @default(1440) updatedBy String @default("system") createdAt DateTime @default(now()) updatedAt DateTime @updatedAt project Project @relation(fields: [projectId], references: [id], onDelete: Cascade) } model AnalysisWorkerHeartbeat { id String @id instanceId String status String activeJobId String? detail String? startedAt DateTime lastSeenAt DateTime updatedAt DateTime @updatedAt @@index([lastSeenAt]) } model AutonomyExecutorHeartbeat { id String @id instanceId String runId String? status String activeProjectId String? detail String? startedAt DateTime lastSeenAt DateTime updatedAt DateTime @updatedAt @@index([lastSeenAt]) } model DeliveryPlan { id String @id @default(cuid()) projectId String initiativeId String? @unique slug String title String intent String priority String @default("normal") problem String desiredOutcome String usersJson Json @default("[]") goalsJson Json nonGoalsJson Json @default("[]") acceptanceCriteriaJson Json implementationPlanJson Json risksJson Json @default("[]") validationCommandsJson Json status DeliveryStatus @default(awaiting_approval) approvalState ApprovalState @default(pending) approvedAt DateTime? approvedBy String? reviewFeedback String? version Int @default(1) createdBy String @default("system") updatedBy String? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt project Project @relation(fields: [projectId], references: [id], onDelete: Cascade) initiative Initiative? @relation(fields: [initiativeId], references: [id], onDelete: SetNull) runs DeliveryRun[] findingInvestigation FindingInvestigation? @@unique([projectId, slug]) @@index([projectId, status]) @@index([projectId, updatedAt]) } model DeliveryRun { id String @id @default(cuid()) deliveryPlanId String repositoryLinkId String branch String baseBranch String baseCommitSha String? headSha String? status DeliveryStatus @default(executing) pullRequestNumber Int? pullRequestUrl String? pullRequestTitle String? pullRequestState String? mergeCommitSha String? startedAt DateTime @default(now()) pullRequestOpenedAt DateTime? mergedAt DateTime? verifiedAt DateTime? completedAt DateTime? createdBy String @default("system") updatedBy String? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt deliveryPlan DeliveryPlan @relation(fields: [deliveryPlanId], references: [id], onDelete: Cascade) repositoryLink GiteaRepositoryLink @relation(fields: [repositoryLinkId], references: [id], onDelete: Restrict) changes DeliveryFileChange[] validations DeliveryValidation[] operations ExternalOperation[] @@unique([repositoryLinkId, branch]) @@index([deliveryPlanId, status]) @@index([pullRequestNumber]) } model DeliveryFileChange { id String @id @default(cuid()) deliveryRunId String path String previousPath String? operation DeliveryChangeOperation beforeSha String? afterSha String? commitSha String? actor String createdAt DateTime @default(now()) deliveryRun DeliveryRun @relation(fields: [deliveryRunId], references: [id], onDelete: Cascade) @@index([deliveryRunId, createdAt]) @@index([deliveryRunId, path]) } model DeliveryValidation { id String @id @default(cuid()) deliveryRunId String command String checkName String? status DeliveryValidationStatus @default(pending) provider String? externalRunId String? externalUrl String? headSha String? summary String? verifiedAt DateTime? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt deliveryRun DeliveryRun @relation(fields: [deliveryRunId], references: [id], onDelete: Cascade) @@index([deliveryRunId, status]) @@index([deliveryRunId, headSha]) } model ExternalOperation { id String @id @default(cuid()) operationId String @unique projectId String deliveryRunId String? actor String action String targetJson Json status ExternalOperationStatus @default(prepared) resultJson Json? errorCode String? startedAt DateTime? completedAt DateTime? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt project Project @relation(fields: [projectId], references: [id], onDelete: Cascade) deliveryRun DeliveryRun? @relation(fields: [deliveryRunId], references: [id], onDelete: SetNull) @@index([projectId, status, createdAt]) @@index([deliveryRunId, createdAt]) } model OutboxEvent { id String @id @default(cuid()) eventId String @unique projectId String aggregateType String aggregateId String eventType String payloadJson Json attempts Int @default(0) publishedAt DateTime? lastError String? createdAt DateTime @default(now()) project Project @relation(fields: [projectId], references: [id], onDelete: Cascade) @@index([projectId, createdAt]) @@index([publishedAt, createdAt]) } model McpAuditEvent { id String @id @default(cuid()) projectId String? operationId String @unique actor String toolName String repository String? branch String? outcome String errorCode String? durationMs Int metadataJson Json? createdAt DateTime @default(now()) project Project? @relation(fields: [projectId], references: [id], onDelete: SetNull) @@index([projectId, createdAt]) @@index([toolName, createdAt]) @@index([outcome, createdAt]) } model User { id String @id @default(cuid()) username String @unique passwordHash String role UserRole @default(owner) credentialVersion Int @default(1) disabledAt DateTime? lastLoginAt DateTime? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt sessions AuthSession[] memberships ProjectMembership[] externalIdentities ExternalIdentity[] oidcLoginAttempts OidcLoginAttempt[] } model ExternalIdentity { id String @id @default(cuid()) provider String tenantId String subject String userId String displayName String? preferredUsername String? lastLoginAt DateTime? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt user User @relation(fields: [userId], references: [id], onDelete: Cascade) @@unique([provider, tenantId, subject]) @@unique([provider, userId]) @@index([userId]) } model OidcLoginAttempt { id String @id @default(cuid()) stateHash String @unique provider String purpose String userId String? codeVerifier String nonce String returnTo String expiresAt DateTime createdAt DateTime @default(now()) user User? @relation(fields: [userId], references: [id], onDelete: Cascade) @@index([expiresAt]) @@index([userId]) } model AuthSession { id String @id @default(cuid()) tokenHash String @unique csrfToken String userId String credentialVersion Int expiresAt DateTime lastSeenAt DateTime @default(now()) revokedAt DateTime? createdAt DateTime @default(now()) user User @relation(fields: [userId], references: [id], onDelete: Cascade) @@index([userId, expiresAt]) @@index([expiresAt]) } model ProjectMembership { id String @id @default(cuid()) projectId String userId String role ProjectAccessRole @default(owner) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt project Project @relation(fields: [projectId], references: [id], onDelete: Cascade) user User @relation(fields: [userId], references: [id], onDelete: Cascade) @@unique([projectId, userId]) @@index([userId]) } model ProjectDNA { id String @id @default(cuid()) projectId String @unique vision String goalsJson Json nonGoalsJson Json targetAudience String principlesJson Json metricsJson Json maturityStage String revision Int @default(1) createdBy String @default("system") updatedBy String? sourceType String @default("fixture_seed") createdAt DateTime @default(now()) updatedAt DateTime @updatedAt project Project @relation(fields: [projectId], references: [id], onDelete: Cascade) } model WorkspaceState { id String @id @default(cuid()) projectId String @unique activeContextPackId String? primaryObjective String activeSection String notesJson Json createdBy String @default("system") updatedBy String? sourceType String @default("fixture_seed") createdAt DateTime @default(now()) updatedAt DateTime @updatedAt project Project @relation(fields: [projectId], references: [id], onDelete: Cascade) @@index([projectId, activeContextPackId]) } model FeatureGroup { id String @id @default(cuid()) projectId String slug String? readableId String? name String description String? focusArea String? archivedAt DateTime? deletedAt DateTime? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt project Project @relation(fields: [projectId], references: [id], onDelete: Cascade) features Feature[] @@unique([projectId, slug]) @@unique([projectId, readableId]) @@index([projectId]) @@index([projectId, deletedAt]) } model Feature { id String @id @default(cuid()) projectId String featureGroupId String slug String? readableId String? name String description String status FeatureStatus @default(todo) lifecycle FeatureLifecycle @default(feature_candidate) intent String? confidence Int @default(0) health Int @default(0) approvalState ApprovalState @default(pending) evidenceStrength EvidenceStrength? verificationState VerificationState? verifiedAt DateTime? verifiedBy String? trustJson Json? provenanceJson Json? createdBy String @default("system") updatedBy String? sourceType String @default("fixture_seed") archivedAt DateTime? deletedAt DateTime? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt project Project @relation(fields: [projectId], references: [id], onDelete: Cascade) featureGroup FeatureGroup @relation(fields: [featureGroupId], references: [id]) @@unique([projectId, slug]) @@unique([projectId, readableId]) @@index([projectId]) @@index([projectId, status]) @@index([projectId, lifecycle]) @@index([projectId, featureGroupId]) @@index([projectId, name]) @@index([projectId, deletedAt]) } model Evidence { id String @id @default(cuid()) projectId String slug String? readableId String? type String source String confidence Int @default(0) approvalState ApprovalState @default(pending) evidenceStrength EvidenceStrength @default(weak) verificationState VerificationState? reason String trustJson Json? provenanceJson Json? metadataJson Json? lastSeen DateTime verifiedAt DateTime? verifiedBy String? createdBy String @default("system") updatedBy String? sourceType String @default("fixture_seed") archivedAt DateTime? deletedAt DateTime? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt project Project @relation(fields: [projectId], references: [id], onDelete: Cascade) @@unique([projectId, slug]) @@unique([projectId, readableId]) @@index([projectId]) @@index([projectId, type]) @@index([projectId, approvalState]) @@index([projectId, evidenceStrength]) @@index([projectId, lastSeen]) @@index([projectId, deletedAt]) } model ContextPack { id String @id @default(cuid()) projectId String slug String? readableId String? title String category String summary String generatedBy String confidence Int @default(0) approvalState ApprovalState @default(pending) qualityJson Json? trustJson Json? provenanceJson Json? metadataJson Json? createdBy String @default("system") updatedBy String? sourceType String @default("fixture_seed") archivedAt DateTime? deletedAt DateTime? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt project Project @relation(fields: [projectId], references: [id], onDelete: Cascade) sections ContextPackSection[] @@unique([projectId, slug]) @@unique([projectId, readableId]) @@index([projectId]) @@index([projectId, category]) @@index([projectId, generatedBy]) @@index([projectId, createdAt]) @@index([projectId, deletedAt]) } model ContextPackSection { id String @id @default(cuid()) projectId String contextPackId String slug String? title String sectionType String orderIndex Int contentJson Json metadataJson Json? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt contextPack ContextPack @relation(fields: [contextPackId], references: [id], onDelete: Cascade) @@unique([contextPackId, slug]) @@index([projectId]) @@index([contextPackId, orderIndex]) @@index([projectId, sectionType]) } model MemoryRule { id String @id @default(cuid()) projectId String slug String? readableId String? title String rule String scope String category String severity String includeInContextPacks Boolean @default(false) confidence Int @default(0) approvalState ApprovalState @default(pending) evidenceStrength EvidenceStrength? verificationState VerificationState? verifiedAt DateTime? verifiedBy String? trustJson Json? provenanceJson Json? createdBy String @default("system") updatedBy String? sourceType String @default("fixture_seed") archivedAt DateTime? deletedAt DateTime? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt project Project @relation(fields: [projectId], references: [id], onDelete: Cascade) @@unique([projectId, slug]) @@unique([projectId, readableId]) @@index([projectId]) @@index([projectId, scope]) @@index([projectId, category]) @@index([projectId, severity]) @@index([projectId, includeInContextPacks]) @@index([projectId, deletedAt]) } model KnowledgeItem { id String @id @default(cuid()) projectId String slug String? readableId String? title String category String content String source String confidence Int @default(0) includeInContextPacks Boolean @default(false) approvalState ApprovalState @default(pending) evidenceStrength EvidenceStrength? verificationState VerificationState? verifiedAt DateTime? verifiedBy String? trustJson Json? provenanceJson Json? metadataJson Json? createdBy String @default("system") updatedBy String? sourceType String @default("fixture_seed") archivedAt DateTime? deletedAt DateTime? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt project Project @relation(fields: [projectId], references: [id], onDelete: Cascade) @@unique([projectId, slug]) @@unique([projectId, readableId]) @@index([projectId]) @@index([projectId, category]) @@index([projectId, source]) @@index([projectId, createdAt]) @@index([projectId, deletedAt]) } model DocumentationItem { id String @id @default(cuid()) projectId String slug String? readableId String? title String kind String status String approvalState ApprovalState @default(pending) content String? metadataJson Json? trustJson Json? provenanceJson Json? createdBy String @default("system") updatedBy String? sourceType String @default("fixture_seed") archivedAt DateTime? deletedAt DateTime? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt project Project @relation(fields: [projectId], references: [id], onDelete: Cascade) @@unique([projectId, slug]) @@unique([projectId, readableId]) @@index([projectId]) @@index([projectId, kind]) @@index([projectId, status]) @@index([projectId, approvalState]) @@index([projectId, deletedAt]) } model CaptureItem { id String @id @default(cuid()) projectId String slug String? readableId String? type String title String content String source String status String classificationType String? confidence Int? evidenceStrength EvidenceStrength? suggestedAction String? linkedReviewItemId String? metadataJson Json? provenanceJson Json? createdBy String @default("system") updatedBy String? sourceType String @default("fixture_seed") archivedAt DateTime? deletedAt DateTime? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt project Project @relation(fields: [projectId], references: [id], onDelete: Cascade) @@unique([projectId, slug]) @@unique([projectId, readableId]) @@index([projectId]) @@index([projectId, status]) @@index([projectId, type]) @@index([projectId, classificationType]) @@index([projectId, linkedReviewItemId]) @@index([projectId, createdAt]) @@index([projectId, deletedAt]) } model ReviewQueueItem { id String @id @default(cuid()) projectId String slug String? readableId String? type String title String description String priority String status ReviewStatus @default(pending) source String confidence Int @default(0) approvalState ApprovalState @default(pending) evidenceStrength EvidenceStrength @default(weak) verificationState VerificationState @default(unverified) suggestedAction String notes String? payloadJson Json? provenanceJson Json? createdEntityType EntityType? createdEntityId String? targetEntityType EntityType? targetEntityId String? verifiedAt DateTime? verifiedBy String? createdBy String @default("system") updatedBy String? sourceType String @default("fixture_seed") archivedAt DateTime? deletedAt DateTime? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt project Project @relation(fields: [projectId], references: [id], onDelete: Cascade) @@unique([projectId, slug]) @@unique([projectId, readableId]) @@index([projectId]) @@index([projectId, status]) @@index([projectId, type]) @@index([projectId, priority]) @@index([projectId, createdAt]) @@index([projectId, deletedAt]) } model Initiative { id String @id @default(cuid()) projectId String slug String? readableId String? title String intent String status String @default("proposed") priority String @default("normal") featureIdsJson Json @default("[]") approvalState ApprovalState @default(pending) confidence Int @default(0) sourceBrainstormId String? reviewItemId String? metadataJson Json? provenanceJson Json? createdBy String @default("api") updatedBy String? sourceType String @default("brainstorm_cpu") archivedAt DateTime? deletedAt DateTime? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt project Project @relation(fields: [projectId], references: [id], onDelete: Cascade) deliveryPlan DeliveryPlan? @@unique([projectId, slug]) @@unique([projectId, readableId]) @@index([projectId]) @@index([projectId, status]) @@index([projectId, approvalState]) @@index([projectId, sourceBrainstormId]) @@index([projectId, deletedAt]) } model BrainstormSession { id String @id @default(cuid()) projectId String slug String? readableId String? title String prompt String scope String mode String status String @default("exploring") targetEntityId String? targetEntityType String? generatedBy String @default("manual") contextSummary String ideasJson Json clustersJson Json outcomesJson Json selectedIdeaIdsJson Json nextActionsJson Json metadataJson Json? createdBy String @default("api") updatedBy String? sourceType String @default("brainstorm_cpu") archivedAt DateTime? deletedAt DateTime? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt project Project @relation(fields: [projectId], references: [id], onDelete: Cascade) @@unique([projectId, slug]) @@unique([projectId, readableId]) @@index([projectId]) @@index([projectId, scope]) @@index([projectId, mode]) @@index([projectId, status]) @@index([projectId, targetEntityType, targetEntityId]) @@index([projectId, deletedAt]) } model IdempotencyRecord { id String @id @default(cuid()) projectId String? method String path String key String requestHash String statusCode Int responseJson Json createdAt DateTime @default(now()) expiresAt DateTime @@unique([method, path, key]) @@index([projectId]) @@index([expiresAt]) } model EntityRelation { id String @id @default(cuid()) projectId String sourceEntityType EntityType sourceEntityId String targetEntityType EntityType targetEntityId String relationshipType String metadataJson Json? createdBy String @default("system") sourceType String @default("fixture_seed") archivedAt DateTime? deletedAt DateTime? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt project Project @relation(fields: [projectId], references: [id], onDelete: Cascade) @@index([projectId]) @@index([projectId, sourceEntityType, sourceEntityId]) @@index([projectId, targetEntityType, targetEntityId]) @@index([projectId, relationshipType]) @@index([projectId, deletedAt]) } model AcceptedTruthItem { id String @id @default(cuid()) projectId String slug String? readableId String? sourceReviewItemId String kind String title String summary String status String @default("accepted") source String confidence Int @default(0) approvalState ApprovalState @default(approved) evidenceStrength EvidenceStrength @default(weak) verificationState VerificationState @default(verified) payloadJson Json? provenanceJson Json? createdBy String @default("api") updatedBy String? sourceType String @default("review_queue") verifiedAt DateTime? verifiedBy String? archivedAt DateTime? deletedAt DateTime? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt project Project @relation(fields: [projectId], references: [id], onDelete: Cascade) @@unique([projectId, slug]) @@unique([projectId, readableId]) @@index([projectId]) @@index([projectId, sourceReviewItemId]) @@index([projectId, kind]) @@index([projectId, status]) @@index([projectId, createdAt]) @@index([projectId, deletedAt]) } model ProjectUpdate { id String @id @default(cuid()) projectId String slug String? readableId String? sourceTruthItemId String kind String title String summary String targetArea String status String @default("ready") confidence Int @default(0) approvalState ApprovalState @default(pending) evidenceStrength EvidenceStrength @default(weak) payloadJson Json? provenanceJson Json? createdBy String @default("api") updatedBy String? sourceType String @default("accepted_truth") appliedAt DateTime? archivedAt DateTime? deletedAt DateTime? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt project Project @relation(fields: [projectId], references: [id], onDelete: Cascade) @@unique([projectId, slug]) @@unique([projectId, readableId]) @@index([projectId]) @@index([projectId, sourceTruthItemId]) @@index([projectId, targetArea]) @@index([projectId, status]) @@index([projectId, createdAt]) @@index([projectId, deletedAt]) } model OperatingLogEntry { id String @id @default(cuid()) projectId String slug String? readableId String? timestamp DateTime @default(now()) type String title String summary String linkedEntityIdsJson Json source String importance String @default("normal") payloadJson Json? provenanceJson Json? createdBy String @default("api") updatedBy String? sourceType String @default("runtime") archivedAt DateTime? deletedAt DateTime? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt project Project @relation(fields: [projectId], references: [id], onDelete: Cascade) @@unique([projectId, slug]) @@unique([projectId, readableId]) @@index([projectId]) @@index([projectId, type]) @@index([projectId, timestamp]) @@index([projectId, deletedAt]) } model CurrentStateReport { id String @id @default(cuid()) projectId String slug String? readableId String? generatedAt DateTime @default(now()) existsJson Json worksJson Json uncertainJson Json brokenJson Json currentRisksJson Json pendingReviewItemIdsJson Json activeContextPackId String? recommendedNextActionsJson Json source String @default("runtime") approvalState ApprovalState @default(pending) payloadJson Json? provenanceJson Json? createdBy String @default("api") updatedBy String? sourceType String @default("runtime") archivedAt DateTime? deletedAt DateTime? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt project Project @relation(fields: [projectId], references: [id], onDelete: Cascade) @@unique([projectId, slug]) @@unique([projectId, readableId]) @@index([projectId]) @@index([projectId, generatedAt]) @@index([projectId, approvalState]) @@index([projectId, deletedAt]) } model ReleaseEvidenceRecord { id String @id @default(cuid()) projectId String slug String? readableId String? capturedAt DateTime @default(now()) kind String title String summary String status String @default("captured") command String? outputText String? route String? source String @default("runtime_readiness") confidence Int @default(100) approvalState ApprovalState @default(approved) evidenceStrength EvidenceStrength @default(verified) verificationState VerificationState @default(verified) metadataJson Json? provenanceJson Json? createdBy String @default("api") updatedBy String? sourceType String @default("release_evidence") verifiedAt DateTime? verifiedBy String? archivedAt DateTime? deletedAt DateTime? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt project Project @relation(fields: [projectId], references: [id], onDelete: Cascade) @@unique([projectId, slug]) @@unique([projectId, readableId]) @@index([projectId]) @@index([projectId, kind]) @@index([projectId, status]) @@index([projectId, capturedAt]) @@index([projectId, verificationState]) @@index([projectId, deletedAt]) } model HandoffBundle { id String @id @default(cuid()) projectId String slug String? readableId String? target String title String markdown String qualityScore Int @default(0) sourceTruthItemIdsJson Json sourceReviewItemIdsJson Json sourceCaptureItemIdsJson Json sourceProjectUpdateIdsJson Json? sourceOperatingLogEntryIdsJson Json? status String @default("ready") approvalState ApprovalState @default(pending) payloadJson Json? provenanceJson Json? createdBy String @default("api") updatedBy String? sourceType String @default("runtime") archivedAt DateTime? deletedAt DateTime? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt project Project @relation(fields: [projectId], references: [id], onDelete: Cascade) codexTasks CodexTask[] @@unique([projectId, slug]) @@unique([projectId, readableId]) @@index([projectId]) @@index([projectId, target]) @@index([projectId, status]) @@index([projectId, createdAt]) @@index([projectId, deletedAt]) } model CodexTask { id String @id @default(cuid()) projectId String slug String? readableId String? handoffBundleId String? goal String contextPackId String? constraintsJson Json relevantFilesJson Json doNotBreakRulesJson Json validationCommandsJson Json expectedReportFormat String outputImportInstructions String approvalState ApprovalState @default(pending) status String @default("draft") payloadJson Json? provenanceJson Json? createdBy String @default("api") updatedBy String? sourceType String @default("handoff") archivedAt DateTime? deletedAt DateTime? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt project Project @relation(fields: [projectId], references: [id], onDelete: Cascade) handoffBundle HandoffBundle? @relation(fields: [handoffBundleId], references: [id], onDelete: SetNull) @@unique([projectId, slug]) @@unique([projectId, readableId]) @@index([projectId]) @@index([projectId, handoffBundleId]) @@index([projectId, status]) @@index([projectId, approvalState]) @@index([projectId, deletedAt]) } model CodexRunImport { id String @id @default(cuid()) projectId String slug String? readableId String? codexTaskId String? sourceRun String summary String extractedReviewItemIdsJson Json status String @default("imported") payloadJson Json? provenanceJson Json? createdBy String @default("api") updatedBy String? sourceType String @default("codex_output") archivedAt DateTime? deletedAt DateTime? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt project Project @relation(fields: [projectId], references: [id], onDelete: Cascade) @@unique([projectId, slug]) @@unique([projectId, readableId]) @@index([projectId]) @@index([projectId, codexTaskId]) @@index([projectId, status]) @@index([projectId, deletedAt]) } model ActivityEvent { id String @id @default(cuid()) projectId String entityType EntityType entityId String eventType String actor String payloadJson Json? createdAt DateTime @default(now()) project Project @relation(fields: [projectId], references: [id], onDelete: Cascade) @@index([projectId]) @@index([projectId, entityType, entityId]) @@index([projectId, eventType]) @@index([projectId, createdAt]) } model WorkGraphNode { id String @id @default(cuid()) projectId String stableKey String source String sourceId String type String title String canonicalLifecycle String @default("ready") domainLifecycle String @default("pending") scope String @default("committed") priority Int @default(50) phase String? risk String @default("normal") blockingStatus String @default("open") executionEligibility String @default("blocked") blockReason String? owner String? leaseToken String? leaseExpiresAt DateTime? attemptCount Int @default(0) consecutiveFailureCount Int @default(0) recoveryStartedAt DateTime? lastMeaningfulProgressAt DateTime? completionEvidenceJson Json? metadataJson Json? supersededById String? completedAt DateTime? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt project Project @relation(fields: [projectId], references: [id], onDelete: Cascade) dependencies WorkGraphDependency[] @relation("WorkGraphNodeDependencies") dependents WorkGraphDependency[] @relation("WorkGraphNodeDependents") auditEvents WorkGraphAuditEvent[] evidence WorkGraphEvidence[] supersededBy WorkGraphNode? @relation("WorkGraphSupersession", fields: [supersededById], references: [id], onDelete: SetNull) supersedes WorkGraphNode[] @relation("WorkGraphSupersession") @@unique([projectId, stableKey]) @@unique([projectId, source, sourceId]) @@index([projectId, executionEligibility, priority]) @@index([projectId, canonicalLifecycle]) @@index([projectId, scope]) @@index([projectId, leaseExpiresAt]) @@index([projectId, updatedAt]) @@index([projectId, supersededById]) } model WorkGraphDependency { id String @id @default(cuid()) projectId String nodeId String dependsOnNodeId String dependencyType String @default("blocks") createdBy String @default("system") createdAt DateTime @default(now()) project Project @relation(fields: [projectId], references: [id], onDelete: Cascade) node WorkGraphNode @relation("WorkGraphNodeDependencies", fields: [nodeId], references: [id], onDelete: Cascade) dependsOnNode WorkGraphNode @relation("WorkGraphNodeDependents", fields: [dependsOnNodeId], references: [id], onDelete: Cascade) @@unique([nodeId, dependsOnNodeId]) @@index([projectId, nodeId]) @@index([projectId, dependsOnNodeId]) } model WorkGraphAuditEvent { id String @id @default(cuid()) projectId String nodeId String? eventType String actor String summary String payloadJson Json? createdAt DateTime @default(now()) project Project @relation(fields: [projectId], references: [id], onDelete: Cascade) node WorkGraphNode? @relation(fields: [nodeId], references: [id], onDelete: Cascade) @@index([projectId, createdAt]) @@index([projectId, nodeId, createdAt]) @@index([projectId, eventType]) } model WorkGraphEvidence { id String @id @default(cuid()) projectId String nodeId String kind String referenceType String referenceId String status String @default("observed") summary String metadataJson Json? verifiedAt DateTime? createdAt DateTime @default(now()) project Project @relation(fields: [projectId], references: [id], onDelete: Cascade) node WorkGraphNode @relation(fields: [nodeId], references: [id], onDelete: Cascade) @@unique([nodeId, kind, referenceType, referenceId]) @@index([projectId, nodeId]) @@index([projectId, status]) } model ProjectDefinitionOfDone { id String @id @default(cuid()) projectId String @unique requirementsJson Json scopePolicyJson Json status String @default("incomplete") satisfiedCount Int @default(0) requirementCount Int @default(0) lastEvaluatedAt DateTime? lastEvidenceAt DateTime? evaluationJson Json? createdBy String @default("system") updatedBy String? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt project Project @relation(fields: [projectId], references: [id], onDelete: Cascade) @@index([status, lastEvaluatedAt]) } model ProjectSavedView { id String @id @default(cuid()) ownerKey String projectId String? name String scope String @default("portfolio") filtersJson Json isPinned Boolean @default(false) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt project Project? @relation(fields: [projectId], references: [id], onDelete: Cascade) @@unique([ownerKey, scope, name]) @@index([ownerKey, scope, updatedAt]) @@index([projectId, updatedAt]) } // Per-user project pins are deliberately separate from pinned saved views: // one is a reusable filter shortcut, the other controls what appears in it. model ProjectPortfolioPin { id String @id @default(cuid()) ownerKey String projectId String createdAt DateTime @default(now()) project Project @relation(fields: [projectId], references: [id], onDelete: Cascade) @@unique([ownerKey, projectId]) @@index([ownerKey, createdAt]) @@index([projectId]) } model DiagnosticRun { id String @id @default(cuid()) projectId String? scope String @default("platform") status String @default("running") summary String? checksJson Json repairPlanJson Json? startedAt DateTime @default(now()) completedAt DateTime? createdBy String @default("system") createdAt DateTime @default(now()) project Project? @relation(fields: [projectId], references: [id], onDelete: Cascade) @@index([projectId, createdAt]) @@index([scope, status, createdAt]) } model BlueprintGraph { id String @id @default(cuid()) projectId String slug String? readableId String? archetypeId String archetypeLabel String depth String status String @default("planned") documentRoot String @default("docs/") intakeSummary String assumptionsJson Json exportManifestJson Json recommendedNextActionsJson Json metadataJson Json? createdBy String @default("api") updatedBy String? sourceType String @default("blueprint_engine") archivedAt DateTime? deletedAt DateTime? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt project Project @relation(fields: [projectId], references: [id], onDelete: Cascade) nodes BlueprintNode[] runs BlueprintNodeRun[] @@unique([projectId, slug]) @@unique([projectId, readableId]) @@index([projectId]) @@index([projectId, archetypeId]) @@index([projectId, status]) @@index([projectId, deletedAt]) } model BlueprintNode { id String @id @default(cuid()) projectId String graphId String templateId String kind String title String cluster String status String @default("pending") generationOrder Int requiredDepth String dependsOnJson Json dependencyTitlesJson Json blockedByJson Json outputPath String purpose String requiredContextJson Json qualityChecksJson Json producesJson Json promptPreview String contextSelectionJson Json documentationItemId String? reviewItemId String? latestRunId String? staleReason String? metadataJson Json? createdBy String @default("api") updatedBy String? sourceType String @default("blueprint_engine") archivedAt DateTime? deletedAt DateTime? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt project Project @relation(fields: [projectId], references: [id], onDelete: Cascade) graph BlueprintGraph @relation(fields: [graphId], references: [id], onDelete: Cascade) runs BlueprintNodeRun[] @@unique([graphId, templateId]) @@index([projectId]) @@index([projectId, graphId]) @@index([projectId, status]) @@index([projectId, cluster]) @@index([projectId, outputPath]) @@index([projectId, deletedAt]) } model BlueprintNodeRun { id String @id @default(cuid()) projectId String graphId String nodeId String status String @default("needs_review") generatedBy String @default("deterministic") inputSnapshotJson Json prompt String draftMarkdown String qualityReportJson Json documentationItemId String? reviewItemId String? metadataJson Json? createdBy String @default("api") updatedBy String? sourceType String @default("blueprint_engine") archivedAt DateTime? deletedAt DateTime? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt project Project @relation(fields: [projectId], references: [id], onDelete: Cascade) graph BlueprintGraph @relation(fields: [graphId], references: [id], onDelete: Cascade) node BlueprintNode @relation(fields: [nodeId], references: [id], onDelete: Cascade) @@index([projectId]) @@index([projectId, graphId]) @@index([projectId, nodeId]) @@index([projectId, status]) @@index([projectId, createdAt]) @@index([projectId, deletedAt]) }