generator client { provider = "prisma-client-js" } datasource db { provider = "postgresql" url = env("DATABASE_URL") } enum PriorityLevel { LOW MEDIUM HIGH } enum UserRole { USER ADMIN } enum ContentPageType { FAQ MANUAL } enum OverallScoreMethod { EQUAL_ALL_MODULES EQUAL_ANSWERED_MODULES WEIGHTED_ANSWERED_MODULES } enum OrganizationDocumentType { ACTA_CONSTITUTIVA } enum StrategicDiagnosticEvidenceSection { TECHNICAL EXPERIENCE ORGANIZATION PUBLIC_PROCUREMENT } enum WorkshopProgressStatus { NOT_STARTED WATCHED EVIDENCE_SUBMITTED APPROVED REJECTED SKIPPED } enum WorkshopEvidenceValidationStatus { PENDING APPROVED REJECTED ERROR } enum LicitationSource { MUNICIPAL_OPEN_PORTAL PNT MUNICIPAL_BACKUP LICITAYA } enum LicitationProcedureType { LICITACION_PUBLICA INVITACION_RESTRINGIDA ADJUDICACION_DIRECTA UNKNOWN } enum LicitationCategory { GOODS SERVICES WORKS MIXED UNKNOWN } enum SyncRunStatus { SUCCESS PARTIAL FAILED } enum ProposalStatus { DRAFT IN_PROGRESS SUBMITTED ARCHIVED } enum LicitationReviewStatus { NEW REVIEWED INTERESTED DISCARDED } enum NormativeDocumentType { BASES_LICITACION CONVOCATORIA REGLAMENTO LEY OTRO } enum NormativeAnalysisMethod { DIRECT OCR } enum NormativeConfidence { LOW MEDIUM HIGH } enum NormativeRiskLevel { ALTO MEDIO BAJO } enum OfficialNormativeSourceType { LEY REGLAMENTO LINEAMIENTO PORTAL } enum NormativeVerificationStatus { SUCCESS WARNING FAILED } enum MunicipalOpenPortalType { GENERIC SAN_PEDRO_ASPX } enum ContractStatus { ACTIVE COMPLETED PAUSED CANCELLED } enum ContractDeliverableStatus { PENDING DELIVERED APPROVED REJECTED OVERDUE } enum ContractPaymentStatus { REGISTERED CONFIRMED DISPUTED } enum ContractDocumentKind { SIGNED_CONTRACT ADDENDUM DELIVERABLE_EVIDENCE PAYMENT_EVIDENCE OTHER } enum LegalCaseType { CONTRACT_BREACH PAYMENT_RETENTION UNJUST_SANCTION CONTRACT_DISPUTE } enum LegalCaseSeverity { LOW MEDIUM HIGH } enum LegalCaseStatus { OPEN IN_PROGRESS ESCALATED RESOLVED CLOSED } enum LegalJurisdictionLevel { FEDERAL STATE MUNICIPAL } enum AuditSimulationStatus { DRAFT COMPLETED } enum AuditSimulationSectionStatus { READY WARNING CRITICAL } enum AiSuggestionStatus { GENERATED ACCEPTED DISMISSED EXPIRED } enum ModulePlanKey { PLAN_2_4 PLAN_5_7 PLAN_8_10 } enum ModulePlanPurchaseStatus { PENDING APPROVED REJECTED CANCELLED EXPIRED } model User { id String @id @default(cuid()) email String @unique passwordHash String name String? role UserRole @default(USER) emailVerifiedAt DateTime? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt organization Organization? companyProfile CompanyProfile? organizationDocs OrganizationDocument[] strategicDiagnosticEvidenceDocs StrategicDiagnosticEvidenceDocument[] workshopProgresses DevelopmentWorkshopProgress[] workshopEvidenceDocs DevelopmentWorkshopEvidence[] proposals Proposal[] proposalDocuments ProposalDocument[] licitationPreferences LicitationUserPreference[] normativeAnalyses NormativeAnalysisHistory[] contracts ContractRecord[] contractExtractionHistories ContractExtractionHistory[] legalCases LegalCase[] legalDiagnoses LegalDiagnosis[] legalDocuments LegalDocument[] auditSimulations AuditSimulation[] institutionalDossierSnapshots InstitutionalDossierSnapshot[] verificationTokens EmailVerificationToken[] responses Response[] results AssessmentResult[] aiSuggestions AiSuggestion[] modulePlanPurchases ModulePlanPurchase[] modulePlanSubscriptions ModulePlanSubscription[] } model Organization { id String @id @default(cuid()) userId String @unique name String tradeName String? rfc String? legalRepresentative String? incorporationDate String? deedNumber String? notaryName String? stateOfIncorporation String? companyType String? fiscalAddress String? businessPurpose String? industry String? operatingState String? municipality String? companySize String? yearsOfOperation String? annualRevenueRange String? hasGovernmentContracts Boolean? country String? primaryObjective String? actaExtractedData Json? actaLookupDictionary Json? actaUploadedAt DateTime? onboardingCompletedAt DateTime? strategicDiagnosticData Json? strategicDiagnosticScores Json? strategicDiagnosticCompletedAt DateTime? companyProfile CompanyProfile? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt user User @relation(fields: [userId], references: [id], onDelete: Cascade) documents OrganizationDocument[] strategicDiagnosticEvidenceDocs StrategicDiagnosticEvidenceDocument[] } model OrganizationDocument { id String @id @default(cuid()) organizationId String userId String type OrganizationDocumentType fileName String storedFileName String filePath String mimeType String sizeBytes Int checksumSha256 String? extractedData Json? extractedTextSnippet String? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade) user User @relation(fields: [userId], references: [id], onDelete: Cascade) @@unique([organizationId, type]) @@unique([userId, type]) @@index([type]) } model StrategicDiagnosticEvidenceDocument { id String @id @default(cuid()) organizationId String userId String section StrategicDiagnosticEvidenceSection category String fileName String storedFileName String filePath String mimeType String sizeBytes Int checksumSha256 String? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade) user User @relation(fields: [userId], references: [id], onDelete: Cascade) @@index([organizationId, section]) @@index([userId, section]) @@index([createdAt]) } model DiagnosticModule { id String @id @default(cuid()) key String @unique name String description String? sortOrder Int @default(0) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt questions Question[] results AssessmentResult[] recommendations Recommendation[] workshops DevelopmentWorkshop[] } model DevelopmentWorkshop { id String @id @default(cuid()) key String @unique moduleId String title String summary String videoUrl String durationMinutes Int @default(0) evidenceRequired String learningObjectives Json? sortOrder Int @default(0) isActive Boolean @default(true) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt module DiagnosticModule @relation(fields: [moduleId], references: [id], onDelete: Cascade) progresses DevelopmentWorkshopProgress[] evidences DevelopmentWorkshopEvidence[] @@index([moduleId, sortOrder]) @@index([isActive, sortOrder]) } model DevelopmentWorkshopProgress { id String @id @default(cuid()) workshopId String userId String status WorkshopProgressStatus @default(NOT_STARTED) watchedAt DateTime? skippedAt DateTime? completedAt DateTime? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt workshop DevelopmentWorkshop @relation(fields: [workshopId], references: [id], onDelete: Cascade) user User @relation(fields: [userId], references: [id], onDelete: Cascade) @@unique([workshopId, userId]) @@index([userId, status]) @@index([workshopId, status]) } model DevelopmentWorkshopEvidence { id String @id @default(cuid()) workshopId String userId String validationStatus WorkshopEvidenceValidationStatus @default(PENDING) validationReason String? validationConfidence Float? validatedAt DateTime? fileName String storedFileName String filePath String mimeType String sizeBytes Int checksumSha256 String? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt workshop DevelopmentWorkshop @relation(fields: [workshopId], references: [id], onDelete: Cascade) user User @relation(fields: [userId], references: [id], onDelete: Cascade) @@index([userId, workshopId, createdAt]) @@index([workshopId, validationStatus]) } model Question { id String @id @default(cuid()) key String @unique moduleId String prompt String helpText String? sortOrder Int @default(0) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt module DiagnosticModule @relation(fields: [moduleId], references: [id], onDelete: Cascade) answerOptions AnswerOption[] responses Response[] @@index([moduleId, sortOrder]) } model AnswerOption { id String @id @default(cuid()) key String @unique questionId String label String weight Int sortOrder Int @default(0) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt question Question @relation(fields: [questionId], references: [id], onDelete: Cascade) responses Response[] @@index([questionId, sortOrder]) } model Response { id String @id @default(cuid()) userId String questionId String answerOptionId String evidence Json? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt user User @relation(fields: [userId], references: [id], onDelete: Cascade) question Question @relation(fields: [questionId], references: [id], onDelete: Cascade) answerOption AnswerOption @relation(fields: [answerOptionId], references: [id], onDelete: Cascade) @@unique([userId, questionId]) @@index([userId]) } model AssessmentResult { id String @id @default(cuid()) userId String moduleId String? overallScore Float? moduleScore Float? metadata Json? calculatedAt DateTime @default(now()) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt user User @relation(fields: [userId], references: [id], onDelete: Cascade) module DiagnosticModule? @relation(fields: [moduleId], references: [id], onDelete: SetNull) @@index([userId, calculatedAt]) @@index([moduleId]) } model Recommendation { id String @id @default(cuid()) key String @unique moduleId String? title String description String priority PriorityLevel @default(MEDIUM) isTemplate Boolean @default(true) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt module DiagnosticModule? @relation(fields: [moduleId], references: [id], onDelete: SetNull) @@index([moduleId]) } model ContentPage { id String @id @default(cuid()) type ContentPageType slug String @unique title String content String sortOrder Int @default(0) isPublished Boolean @default(true) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt @@index([type, sortOrder]) } model ScoringConfig { id String @id @default(cuid()) key String @unique lowScoreThreshold Int @default(70) overallScoreMethod OverallScoreMethod @default(EQUAL_ALL_MODULES) moduleWeights Json? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt } model EmailVerificationToken { id String @id @default(cuid()) userId String token String @unique expiresAt DateTime consumedAt DateTime? createdAt DateTime @default(now()) user User @relation(fields: [userId], references: [id], onDelete: Cascade) @@index([userId]) @@index([expiresAt]) } model ModulePlanPurchase { id String @id @default(cuid()) userId String planKey ModulePlanKey status ModulePlanPurchaseStatus @default(PENDING) externalReference String @unique mercadoPreferenceId String? mercadoPaymentId String? mercadoOrderId String? checkoutUrl String? amount Decimal @db.Decimal(14, 2) currency String @default("MXN") requestJson Json? responseJson Json? approvedAt DateTime? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt user User @relation(fields: [userId], references: [id], onDelete: Cascade) subscriptions ModulePlanSubscription[] @@index([userId, planKey, createdAt]) @@index([status, updatedAt]) @@index([mercadoPaymentId]) } model ModulePlanSubscription { id String @id @default(cuid()) userId String planKey ModulePlanKey sourcePurchaseId String? isActive Boolean @default(true) startsAt DateTime @default(now()) expiresAt DateTime? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt user User @relation(fields: [userId], references: [id], onDelete: Cascade) sourcePurchase ModulePlanPurchase? @relation(fields: [sourcePurchaseId], references: [id], onDelete: SetNull) @@unique([userId, planKey]) @@index([userId, isActive, expiresAt]) } model Municipality { id String @id @default(cuid()) stateCode String stateName String municipalityCode String municipalityName String openPortalUrl String? openPortalType MunicipalOpenPortalType @default(GENERIC) openSyncIntervalDays Int @default(7) lastOpenSyncAt DateTime? pntSubjectId String? pntEntityId String? pntSectorId String? pntEntryUrl String? backupUrl String? scrapingEnabled Boolean @default(true) isActive Boolean @default(true) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt licitations Licitation[] syncRuns SyncRun[] @@unique([stateCode, municipalityCode]) @@index([stateCode, municipalityName]) @@index([isActive, scrapingEnabled]) } model Licitation { id String @id @default(cuid()) municipalityId String source LicitationSource sourceRecordId String tenderCode String? procedureType LicitationProcedureType @default(UNKNOWN) title String description String? category LicitationCategory? @default(UNKNOWN) isOpen Boolean @default(true) openingDate DateTime? closingDate DateTime? publishDate DateTime? eventDates Json? amount Decimal? @db.Decimal(14, 2) currency String? status String? supplierAwarded String? documents Json? rawSourceUrl String? rawPayload Json lastSeenAt DateTime @default(now()) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt municipality Municipality @relation(fields: [municipalityId], references: [id], onDelete: Cascade) userPreferences LicitationUserPreference[] normativeAnalyses NormativeAnalysisHistory[] @@unique([municipalityId, source, sourceRecordId]) @@index([municipalityId, isOpen, closingDate]) @@index([municipalityId, publishDate]) @@index([procedureType, category]) @@index([amount]) @@index([createdAt]) } model SyncRun { id String @id @default(cuid()) startedAt DateTime @default(now()) finishedAt DateTime? municipalityId String? source LicitationSource status SyncRunStatus @default(SUCCESS) stats Json? error String? municipality Municipality? @relation(fields: [municipalityId], references: [id], onDelete: SetNull) @@index([municipalityId, startedAt]) @@index([source, status, startedAt]) } model CompanyProfile { id String @id @default(cuid()) userId String @unique organizationId String? @unique locations Json? categoriesSupported Json? keywords Json? minAmount Decimal? @db.Decimal(14, 2) maxAmount Decimal? @db.Decimal(14, 2) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt user User @relation(fields: [userId], references: [id], onDelete: Cascade) organization Organization? @relation(fields: [organizationId], references: [id], onDelete: SetNull) } model LicitationUserPreference { id String @id @default(cuid()) userId String licitationId String status LicitationReviewStatus @default(NEW) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt user User @relation(fields: [userId], references: [id], onDelete: Cascade) licitation Licitation @relation(fields: [licitationId], references: [id], onDelete: Cascade) @@unique([userId, licitationId]) @@index([userId, status]) @@index([licitationId, status]) } model NormativeAnalysisHistory { id String @id @default(cuid()) userId String sourceLicitationId String? fileName String documentType NormativeDocumentType issuingEntity String? methodUsed NormativeAnalysisMethod numPages Int warnings Json? extractedChars Int confidence NormativeConfidence viabilityScore Int riskLevel NormativeRiskLevel executiveSummary String result Json analyzedAt DateTime @default(now()) deletedAt DateTime? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt user User @relation(fields: [userId], references: [id], onDelete: Cascade) sourceLicitation Licitation? @relation(fields: [sourceLicitationId], references: [id], onDelete: SetNull) @@index([userId, analyzedAt]) @@index([userId, deletedAt]) @@index([sourceLicitationId]) } model Proposal { id String @id @default(cuid()) userId String sourceLicitationId String? title String issuingEntity String summary String @default("") workflowDraft Json? currentStep Int @default(1) completionPercent Int @default(0) readyForSubmissionAt DateTime? status ProposalStatus @default(DRAFT) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt user User @relation(fields: [userId], references: [id], onDelete: Cascade) documents ProposalDocument[] contracts ContractRecord[] @@index([userId, status]) @@index([updatedAt]) @@index([sourceLicitationId]) } model ContractRecord { id String @id @default(cuid()) userId String sourceProposalId String? title String counterpartyEntity String contractNumber String? contractType String startDate DateTime? endDate DateTime? totalAmount Decimal? @db.Decimal(14, 2) currency String @default("MXN") status ContractStatus @default(ACTIVE) description String @default("") createdAt DateTime @default(now()) updatedAt DateTime @updatedAt user User @relation(fields: [userId], references: [id], onDelete: Cascade) sourceProposal Proposal? @relation(fields: [sourceProposalId], references: [id], onDelete: SetNull) deliverables ContractDeliverable[] payments ContractPayment[] documents ContractDocument[] extractions ContractExtractionHistory[] legalCases LegalCase[] @@index([userId, status, endDate]) @@index([sourceProposalId]) @@index([updatedAt]) } model ContractDeliverable { id String @id @default(cuid()) contractId String title String dueDate DateTime? amountLinked Decimal? @db.Decimal(14, 2) status ContractDeliverableStatus @default(PENDING) deliveredAt DateTime? approvedAt DateTime? notes String @default("") createdAt DateTime @default(now()) updatedAt DateTime @updatedAt contract ContractRecord @relation(fields: [contractId], references: [id], onDelete: Cascade) @@index([contractId, status, dueDate]) @@index([dueDate]) } model ContractPayment { id String @id @default(cuid()) contractId String amount Decimal @db.Decimal(14, 2) paymentDate DateTime invoiceNumber String? concept String @default("") status ContractPaymentStatus @default(REGISTERED) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt contract ContractRecord @relation(fields: [contractId], references: [id], onDelete: Cascade) @@index([contractId, paymentDate]) @@index([status, paymentDate]) } model ContractDocument { id String @id @default(cuid()) contractId String fileName String filePath String mimeType String sizeBytes Int checksumSha256 String? kind ContractDocumentKind @default(OTHER) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt contract ContractRecord @relation(fields: [contractId], references: [id], onDelete: Cascade) @@index([contractId, kind, createdAt]) } model ContractExtractionHistory { id String @id @default(cuid()) contractId String? userId String engine String model String? resultJson Json warningsJson Json? analyzedAt DateTime @default(now()) createdAt DateTime @default(now()) contract ContractRecord? @relation(fields: [contractId], references: [id], onDelete: SetNull) user User @relation(fields: [userId], references: [id], onDelete: Cascade) @@index([userId, analyzedAt]) @@index([contractId, analyzedAt]) } model LegalCase { id String @id @default(cuid()) userId String contractId String? caseType LegalCaseType severity LegalCaseSeverity counterparty String description String amountAtRisk Decimal? @db.Decimal(14, 2) status LegalCaseStatus @default(OPEN) openedAt DateTime @default(now()) resolvedAt DateTime? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt user User @relation(fields: [userId], references: [id], onDelete: Cascade) contract ContractRecord? @relation(fields: [contractId], references: [id], onDelete: SetNull) diagnoses LegalDiagnosis[] escalationLogs LegalEscalationStepLog[] documents LegalDocument[] @@index([userId, status, severity]) @@index([contractId]) } model LegalDiagnosis { id String @id @default(cuid()) userId String legalCaseId String? stepIndex Int @default(1) totalSteps Int @default(4) answersJson Json recommendedRouteJson Json createdAt DateTime @default(now()) updatedAt DateTime @updatedAt user User @relation(fields: [userId], references: [id], onDelete: Cascade) legalCase LegalCase? @relation(fields: [legalCaseId], references: [id], onDelete: SetNull) @@index([userId, updatedAt]) @@index([legalCaseId]) } model LegalEscalationStepLog { id String @id @default(cuid()) legalCaseId String routeStepKey String completedAt DateTime? notes String @default("") createdAt DateTime @default(now()) updatedAt DateTime @updatedAt legalCase LegalCase @relation(fields: [legalCaseId], references: [id], onDelete: Cascade) @@unique([legalCaseId, routeStepKey]) @@index([legalCaseId, completedAt]) } model LegalDocument { id String @id @default(cuid()) legalCaseId String? userId String templateKey String? aiGenerated Boolean @default(false) title String content String createdAt DateTime @default(now()) updatedAt DateTime @updatedAt legalCase LegalCase? @relation(fields: [legalCaseId], references: [id], onDelete: SetNull) user User @relation(fields: [userId], references: [id], onDelete: Cascade) @@index([userId, createdAt]) @@index([legalCaseId, createdAt]) } model LegalDirectoryEntity { id String @id @default(cuid()) jurisdictionLevel LegalJurisdictionLevel name String scopeTagsJson Json websiteUrl String? phone String? email String? stateCode String? municipalityCode String? isActive Boolean @default(true) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt @@index([jurisdictionLevel, isActive]) @@index([stateCode, municipalityCode, isActive]) } model AuditSimulation { id String @id @default(cuid()) userId String name String auditType String status AuditSimulationStatus @default(DRAFT) overallScore Int? completedAt DateTime? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt user User @relation(fields: [userId], references: [id], onDelete: Cascade) sections AuditSimulationSection[] responses AuditChecklistResponse[] @@index([userId, status, updatedAt]) } model AuditSimulationSection { id String @id @default(cuid()) simulationId String key String score Int? status AuditSimulationSectionStatus @default(READY) findingsJson Json? recommendationsJson Json? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt simulation AuditSimulation @relation(fields: [simulationId], references: [id], onDelete: Cascade) @@unique([simulationId, key]) @@index([status]) } model AuditChecklistResponse { id String @id @default(cuid()) simulationId String questionKey String answer String evidenceRefsJson Json? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt simulation AuditSimulation @relation(fields: [simulationId], references: [id], onDelete: Cascade) @@index([simulationId, questionKey]) } model InstitutionalDossierSnapshot { id String @id @default(cuid()) userId String generatedAt DateTime @default(now()) payloadJson Json createdAt DateTime @default(now()) user User @relation(fields: [userId], references: [id], onDelete: Cascade) @@index([userId, generatedAt]) } model ProposalDocument { id String @id @default(cuid()) proposalId String userId String fileName String storedFileName String filePath String mimeType String sizeBytes Int checksumSha256 String? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt proposal Proposal @relation(fields: [proposalId], references: [id], onDelete: Cascade) user User @relation(fields: [userId], references: [id], onDelete: Cascade) @@index([proposalId, createdAt]) @@index([userId, createdAt]) } model OfficialNormativeSource { id String @id stateCode String stateName String municipalityCode String? municipalityName String? authorityName String title String officialUrl String sourceType OfficialNormativeSourceType versionLabel String? isPilot Boolean @default(false) lastKnownHash String? lastVerifiedAt DateTime? nextCheckAt DateTime? lastStatus NormativeVerificationStatus? lastMessage String? lastChangedAt DateTime? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt @@index([stateCode, municipalityCode, isPilot]) @@index([nextCheckAt]) @@index([lastStatus, lastVerifiedAt]) } model OfficialNormativeSuggestion { id String @id @default(cuid()) stateCode String municipalityCode String? authorityName String title String officialUrl String sourceType OfficialNormativeSourceType notes String? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt @@index([stateCode, municipalityCode, createdAt]) } model AiSuggestion { id String @id @default(cuid()) userId String moduleKey String featureKey String subjectType String subjectId String inputHash String requestJson Json responseJson Json confidence Float? engine String model String? usageJson Json? warningsJson Json? promptVersion String status AiSuggestionStatus @default(GENERATED) actedAt DateTime? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt user User @relation(fields: [userId], references: [id], onDelete: Cascade) @@unique([userId, moduleKey, featureKey, subjectType, subjectId, inputHash], map: "ai_suggestion_dedupe") @@index([userId, moduleKey, featureKey, createdAt]) @@index([status, updatedAt]) @@index([inputHash]) }