datasource db { provider = "postgresql" url = env("DATABASE_URL") directUrl = env("DIRECT_URL") } generator client { provider = "prisma-client-js" binaryTargets = ["native", "debian-openssl-1.1.x"] previewFeatures = ["tracing"] } model Activity { id String @id @default(uuid()) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt deleted DateTime? text String // Used to link the task or activity to external apps sourceURL String? integrationAccount IntegrationAccount? @relation(fields: [integrationAccountId], references: [id]) integrationAccountId String? rejectionReason String? workspace Workspace @relation(fields: [workspaceId], references: [id]) workspaceId String WebhookDeliveryLog WebhookDeliveryLog[] ConversationHistory ConversationHistory[] IngestionQueue IngestionQueue[] } model AuthorizationCode { id String @id @default(cuid()) code String @unique personalAccessToken PersonalAccessToken? @relation(fields: [personalAccessTokenId], references: [id], onDelete: Cascade, onUpdate: Cascade) personalAccessTokenId String? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt } model Conversation { id String @id @default(uuid()) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt deleted DateTime? unread Boolean @default(false) title String? user User @relation(fields: [userId], references: [id]) userId String workspace Workspace? @relation(fields: [workspaceId], references: [id]) workspaceId String? status String @default("pending") // Can be "pending", "running", "completed", "failed", "need_attention" ConversationHistory ConversationHistory[] } model ConversationExecutionStep { id String @id @default(uuid()) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt deleted DateTime? thought String message String actionId String? actionOutput String? actionInput String? actionStatus String? metadata Json? @default("{}") conversationHistory ConversationHistory @relation(fields: [conversationHistoryId], references: [id]) conversationHistoryId String } model ConversationHistory { id String @id @default(uuid()) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt deleted DateTime? message String userType UserType activity Activity? @relation(fields: [activityId], references: [id]) activityId String? context Json? thoughts Json? user User? @relation(fields: [userId], references: [id]) userId String? conversation Conversation @relation(fields: [conversationId], references: [id]) conversationId String ConversationExecutionStep ConversationExecutionStep[] } model Entity { id String @id @default(cuid()) name String @unique // e.g., "User", "Issue", "Task", "Automation" metadata Json // Store field definitions and their types // Relations spaceEntities SpaceEntity[] createdAt DateTime @default(now()) updatedAt DateTime @updatedAt } model IngestionQueue { id String @id @default(cuid()) // Relations space Space? @relation(fields: [spaceId], references: [id]) spaceId String? // Queue metadata data Json // The actual data to be processed output Json? // The processed output data status IngestionStatus priority Int @default(0) workspaceId String workspace Workspace @relation(fields: [workspaceId], references: [id]) activity Activity? @relation(fields: [activityId], references: [id]) activityId String? // Error handling error String? retryCount Int @default(0) // Timestamps createdAt DateTime @default(now()) updatedAt DateTime @updatedAt processedAt DateTime? } model IngestionRule { id String @id @default(uuid()) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt deleted DateTime? name String? // Optional human-readable rule name text String // Free-flowing text rule description (mandatory) source String // Source/integration this rule applies to (mandatory) isActive Boolean @default(true) // Enable/disable rule (mandatory) workspace Workspace @relation(fields: [workspaceId], references: [id]) workspaceId String user User @relation(fields: [userId], references: [id]) userId String } model IntegrationAccount { id String @id @default(uuid()) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt deleted DateTime? integrationConfiguration Json accountId String? settings Json? isActive Boolean @default(true) integratedBy User @relation(references: [id], fields: [integratedById]) integratedById String integrationDefinition IntegrationDefinitionV2 @relation(references: [id], fields: [integrationDefinitionId]) integrationDefinitionId String workspace Workspace @relation(references: [id], fields: [workspaceId]) workspaceId String Activity Activity[] oauthIntegrationGrants OAuthIntegrationGrant[] @@unique([accountId, integrationDefinitionId, workspaceId]) } model IntegrationDefinitionV2 { id String @id @default(uuid()) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt deleted DateTime? name String @unique slug String description String icon String config Json? spec Json @default("{}") version String? url String? workspace Workspace? @relation(references: [id], fields: [workspaceId]) workspaceId String? IntegrationAccount IntegrationAccount[] } model InvitationCode { id String @id @default(cuid()) code String @unique users User[] createdAt DateTime @default(now()) } model OAuthAuthorizationCode { id String @id @default(cuid()) code String @unique // OAuth2 specific fields clientId String userId String redirectUri String scope String? state String? codeChallenge String? codeChallengeMethod String? expiresAt DateTime used Boolean @default(false) // Relations client OAuthClient @relation(fields: [clientId], references: [id], onDelete: Cascade) user User @relation(fields: [userId], references: [id], onDelete: Cascade) workspace Workspace @relation(fields: [workspaceId], references: [id], onDelete: Cascade) workspaceId String createdAt DateTime @default(now()) updatedAt DateTime @updatedAt } model OAuthAccessToken { id String @id @default(cuid()) token String @unique clientId String userId String scope String? expiresAt DateTime revoked Boolean @default(false) // Relations client OAuthClient @relation(fields: [clientId], references: [id], onDelete: Cascade) user User @relation(fields: [userId], references: [id], onDelete: Cascade) workspace Workspace @relation(fields: [workspaceId], references: [id], onDelete: Cascade) workspaceId String createdAt DateTime @default(now()) updatedAt DateTime @updatedAt } model OAuthClient { id String @id @default(cuid()) clientId String @unique clientSecret String name String description String? // Redirect URIs (comma-separated for simplicity) redirectUris String // Allowed scopes (comma-separated) allowedScopes String @default("read") // Grant types allowed grantTypes String @default("authorization_code") // PKCE support requirePkce Boolean @default(false) clientType String @default("regular") // Client metadata logoUrl String? homepageUrl String? // Integration hub webhook support webhookUrl String? webhookSecret String? // GitHub-style features isActive Boolean @default(true) // Workspace relationship (like GitHub orgs) workspace Workspace? @relation(fields: [workspaceId], references: [id], onDelete: Cascade) workspaceId String? // Created by user (for audit trail) createdBy User? @relation(fields: [createdById], references: [id]) createdById String? // Relations oauthAuthorizationCodes OAuthAuthorizationCode[] accessTokens OAuthAccessToken[] refreshTokens OAuthRefreshToken[] integrationGrants OAuthIntegrationGrant[] oAuthClientInstallation OAuthClientInstallation[] createdAt DateTime @default(now()) updatedAt DateTime @updatedAt } model OAuthClientInstallation { id String @id @default(cuid()) // The OAuth client being installed oauthClient OAuthClient @relation(fields: [oauthClientId], references: [id], onDelete: Cascade) oauthClientId String // The workspace where it's installed workspace Workspace @relation(fields: [workspaceId], references: [id], onDelete: Cascade) workspaceId String // Installation metadata installedBy User @relation(fields: [installedById], references: [id]) installedById String installedAt DateTime @default(now()) uninstalledAt DateTime? // Installation status isActive Boolean @default(true) // Installation-specific settings settings Json? grantedScopes String? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt @@unique([oauthClientId, workspaceId]) } model OAuthRefreshToken { id String @id @default(cuid()) token String @unique clientId String userId String scope String? expiresAt DateTime revoked Boolean @default(false) // Relations client OAuthClient @relation(fields: [clientId], references: [id], onDelete: Cascade) user User @relation(fields: [userId], references: [id], onDelete: Cascade) workspace Workspace @relation(fields: [workspaceId], references: [id], onDelete: Cascade) workspaceId String createdAt DateTime @default(now()) updatedAt DateTime @updatedAt } model OAuthIntegrationGrant { id String @id @default(cuid()) // OAuth client that has access client OAuthClient @relation(fields: [clientId], references: [id], onDelete: Cascade) clientId String // User who granted access user User @relation(fields: [userId], references: [id], onDelete: Cascade) userId String // Integration account that was granted integrationAccount IntegrationAccount @relation(fields: [integrationAccountId], references: [id], onDelete: Cascade) integrationAccountId String // When access was granted/revoked grantedAt DateTime @default(now()) revokedAt DateTime? isActive Boolean @default(true) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt @@unique([clientId, userId, integrationAccountId]) } model PersonalAccessToken { id String @id @default(cuid()) /// If generated by the CLI this will be "cli", otherwise user-provided name String /// This is the token encrypted using the ENCRYPTION_KEY encryptedToken Json /// This is shown in the UI, with ******** obfuscatedToken String /// This is used to find the token in the database hashedToken String @unique user User @relation(fields: [userId], references: [id]) userId String revokedAt DateTime? lastAccessedAt DateTime? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt authorizationCodes AuthorizationCode[] } model Space { id String @id @default(cuid()) name String description String? autoMode Boolean @default(false) // Relations user User @relation(fields: [userId], references: [id]) userId String // Space's enabled entities enabledEntities SpaceEntity[] createdAt DateTime @default(now()) updatedAt DateTime @updatedAt IngestionQueue IngestionQueue[] } model SpaceEntity { id String @id @default(cuid()) // Relations space Space @relation(fields: [spaceId], references: [id]) spaceId String entity Entity @relation(fields: [entityId], references: [id]) entityId String // Custom settings for this entity in this space settings Json? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt @@unique([spaceId, entityId]) } model User { id String @id @default(cuid()) email String @unique authenticationMethod AuthenticationMethod authenticationProfile Json? authenticationExtraParams Json? authIdentifier String? @unique displayName String? name String? avatarUrl String? memoryFilter String? // Adding memory filter instructions admin Boolean @default(false) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt marketingEmails Boolean @default(true) confirmedBasicDetails Boolean @default(false) onboardingComplete Boolean @default(false) referralSource String? personalAccessTokens PersonalAccessToken[] InvitationCode InvitationCode? @relation(fields: [invitationCodeId], references: [id]) invitationCodeId String? Space Space[] Workspace Workspace? IntegrationAccount IntegrationAccount[] WebhookConfiguration WebhookConfiguration[] Conversation Conversation[] ConversationHistory ConversationHistory[] IngestionRule IngestionRule[] // OAuth2 relations oauthAuthorizationCodes OAuthAuthorizationCode[] oauthAccessTokens OAuthAccessToken[] oauthRefreshTokens OAuthRefreshToken[] oauthClientsCreated OAuthClient[] oauthIntegrationGrants OAuthIntegrationGrant[] oAuthClientInstallation OAuthClientInstallation[] UserUsage UserUsage? } model UserUsage { id String @id @default(uuid()) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt deleted DateTime? availableCredits Int @default(0) usedCredits Int @default(0) user User @relation(fields: [userId], references: [id]) userId String @unique } model WebhookConfiguration { id String @id @default(cuid()) url String secret String? isActive Boolean @default(true) eventTypes String[] // List of event types this webhook is interested in, e.g. ["activity.created"] user User? @relation(fields: [userId], references: [id]) userId String? workspace Workspace? @relation(fields: [workspaceId], references: [id]) workspaceId String? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt WebhookDeliveryLog WebhookDeliveryLog[] } model WebhookDeliveryLog { id String @id @default(cuid()) webhookConfiguration WebhookConfiguration @relation(fields: [webhookConfigurationId], references: [id]) webhookConfigurationId String activity Activity? @relation(fields: [activityId], references: [id]) activityId String? status WebhookDeliveryStatus responseStatusCode Int? responseBody String? error String? deliveredAt DateTime @default(now()) createdAt DateTime @default(now()) } model Workspace { id String @id @default(uuid()) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt deleted DateTime? name String slug String @unique icon String? integrations String[] userId String? @unique user User? @relation(fields: [userId], references: [id]) IngestionQueue IngestionQueue[] IntegrationAccount IntegrationAccount[] IntegrationDefinitionV2 IntegrationDefinitionV2[] Activity Activity[] WebhookConfiguration WebhookConfiguration[] Conversation Conversation[] IngestionRule IngestionRule[] OAuthClient OAuthClient[] OAuthClientInstallation OAuthClientInstallation[] OAuthAuthorizationCode OAuthAuthorizationCode[] OAuthAccessToken OAuthAccessToken[] OAuthRefreshToken OAuthRefreshToken[] } enum AuthenticationMethod { GOOGLE MAGIC_LINK } enum IngestionStatus { PENDING PROCESSING COMPLETED FAILED CANCELLED } enum UserType { Agent User System } enum WebhookDeliveryStatus { SUCCESS FAILED }