// This is your Prisma schema file, // learn more about it in the docs: https://pris.ly/d/prisma-schema generator client { provider = "prisma-client-js" } datasource db { provider = "postgresql" url = env("DATABASE_URL") } enum RepoIndexingStatus { NEW IN_INDEX_QUEUE INDEXING INDEXED FAILED IN_GC_QUEUE GARBAGE_COLLECTING GARBAGE_COLLECTION_FAILED } enum ConnectionSyncStatus { SYNC_NEEDED IN_SYNC_QUEUE SYNCING SYNCED SYNCED_WITH_WARNINGS FAILED } enum StripeSubscriptionStatus { ACTIVE INACTIVE } enum ChatVisibility { PRIVATE PUBLIC } model Repo { id Int @id @default(autoincrement()) name String displayName String? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt /// When the repo was last indexed successfully. indexedAt DateTime? isFork Boolean isArchived Boolean metadata Json // For schema see repoMetadataSchema in packages/backend/src/types.ts cloneUrl String webUrl String? connections RepoToConnection[] imageUrl String? repoIndexingStatus RepoIndexingStatus @default(NEW) permittedUsers UserToRepoPermission[] // The id of the repo in the external service external_id String // The type of the external service (e.g., github, gitlab, etc.) external_codeHostType String // The base url of the external service (e.g., https://github.com) external_codeHostUrl String org Org @relation(fields: [orgId], references: [id], onDelete: Cascade) orgId Int searchContexts SearchContext[] @@unique([external_id, external_codeHostUrl, orgId]) } model SearchContext { id Int @id @default(autoincrement()) name String description String? repos Repo[] org Org @relation(fields: [orgId], references: [id], onDelete: Cascade) orgId Int @@unique([name, orgId]) } model Connection { id Int @id @default(autoincrement()) name String config Json isDeclarative Boolean @default(false) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt /// When the connection was last synced successfully. syncedAt DateTime? repos RepoToConnection[] syncStatus ConnectionSyncStatus @default(SYNC_NEEDED) syncStatusMetadata Json? // The type of connection (e.g., github, gitlab, etc.) connectionType String // The organization that owns this connection org Org @relation(fields: [orgId], references: [id], onDelete: Cascade) orgId Int @@unique([name, orgId]) } model RepoToConnection { addedAt DateTime @default(now()) connection Connection @relation(fields: [connectionId], references: [id], onDelete: Cascade) connectionId Int repo Repo @relation(fields: [repoId], references: [id], onDelete: Cascade) repoId Int @@id([connectionId, repoId]) } model Invite { /// The globally unique invite id id String @id @default(cuid()) /// Time of invite creation createdAt DateTime @default(now()) /// The email of the recipient of the invite recipientEmail String /// The user that created the invite host User @relation(fields: [hostUserId], references: [id], onDelete: Cascade) hostUserId String /// The organization the invite is for org Org @relation(fields: [orgId], references: [id], onDelete: Cascade) orgId Int @@unique([recipientEmail, orgId]) } model AccountRequest { id String @id @default(cuid()) createdAt DateTime @default(now()) requestedBy User @relation(fields: [requestedById], references: [id], onDelete: Cascade) requestedById String @unique org Org @relation(fields: [orgId], references: [id], onDelete: Cascade) orgId Int @@unique([requestedById, orgId]) } model Org { id Int @id @default(autoincrement()) name String domain String @unique createdAt DateTime @default(now()) updatedAt DateTime @updatedAt members UserToOrg[] connections Connection[] repos Repo[] secrets Secret[] apiKeys ApiKey[] isOnboarded Boolean @default(false) imageUrl String? metadata Json? // For schema see orgMetadataSchema in packages/web/src/types.ts memberApprovalRequired Boolean @default(true) stripeCustomerId String? stripeSubscriptionStatus StripeSubscriptionStatus? stripeLastUpdatedAt DateTime? /// List of pending invites to this organization invites Invite[] /// The invite id for this organization inviteLinkEnabled Boolean @default(false) inviteLinkId String? audits Audit[] accountRequests AccountRequest[] searchContexts SearchContext[] chats Chat[] } enum OrgRole { OWNER MEMBER GUEST } model UserToOrg { joinedAt DateTime @default(now()) /// The linked organization org Org @relation(fields: [orgId], references: [id], onDelete: Cascade) orgId Int /// The linked user user User @relation(fields: [userId], references: [id], onDelete: Cascade) userId String role OrgRole @default(MEMBER) @@id([orgId, userId]) } model Secret { orgId Int key String encryptedValue String iv String createdAt DateTime @default(now()) org Org @relation(fields: [orgId], references: [id], onDelete: Cascade) @@id([orgId, key]) } model ApiKey { name String hash String @id @unique createdAt DateTime @default(now()) lastUsedAt DateTime? org Org @relation(fields: [orgId], references: [id], onDelete: Cascade) orgId Int createdBy User @relation(fields: [createdById], references: [id], onDelete: Cascade) createdById String } model Audit { id String @id @default(cuid()) timestamp DateTime @default(now()) action String actorId String actorType String targetId String targetType String sourcebotVersion String metadata Json? org Org @relation(fields: [orgId], references: [id], onDelete: Cascade) orgId Int @@index([actorId, actorType, targetId, targetType, orgId]) // Fast path for analytics queries – orgId is first because we assume most deployments are single tenant @@index([orgId, timestamp, action, actorId], map: "idx_audit_core_actions_full") // Fast path for analytics queries for a specific user @@index([actorId, timestamp], map: "idx_audit_actor_time_full") } // @see : https://authjs.dev/concepts/database-models#user model User { id String @id @default(cuid()) name String? email String? @unique hashedPassword String? emailVerified DateTime? image String? accounts Account[] orgs UserToOrg[] accountRequest AccountRequest? accessibleRepos UserToRepoPermission[] /// List of pending invites that the user has created invites Invite[] apiKeys ApiKey[] chats Chat[] createdAt DateTime @default(now()) updatedAt DateTime @updatedAt } model UserToRepoPermission { createdAt DateTime @default(now()) repo Repo @relation(fields: [repoId], references: [id], onDelete: Cascade) repoId Int user User @relation(fields: [userId], references: [id], onDelete: Cascade) userId String @@id([repoId, userId]) } // @see : https://authjs.dev/concepts/database-models#account model Account { id String @id @default(cuid()) userId String type String provider String providerAccountId String refresh_token String? access_token String? expires_at Int? token_type String? scope String? id_token String? session_state String? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt user User @relation(fields: [userId], references: [id], onDelete: Cascade) @@unique([provider, providerAccountId]) } // @see : https://authjs.dev/concepts/database-models#verificationtoken model VerificationToken { identifier String token String expires DateTime @@unique([identifier, token]) } model Chat { id String @id @default(cuid()) name String? createdBy User @relation(fields: [createdById], references: [id], onDelete: Cascade) createdById String createdAt DateTime @default(now()) updatedAt DateTime @updatedAt org Org @relation(fields: [orgId], references: [id], onDelete: Cascade) orgId Int visibility ChatVisibility @default(PRIVATE) isReadonly Boolean @default(false) messages Json // This is a JSON array of `Message` types from @ai-sdk/ui-utils. }