Files
projectbrain-Public/backend/prisma/schema.prisma
T

1968 lines
60 KiB
Plaintext

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