sourcebot/packages/db/prisma/schema.prisma
2025-10-28 20:27:33 -07:00

437 lines
11 KiB
Text
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// 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 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 /// Full repo name, including the vcs hostname (ex. github.com/sourcebot-dev/sourcebot)
displayName String? /// Display name of the repo for UI (ex. sourcebot-dev/sourcebot)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
isFork Boolean
isArchived Boolean
isPublic Boolean @default(false)
metadata Json /// For schema see repoMetadataSchema in packages/shared/src/types.ts
cloneUrl String
webUrl String?
connections RepoToConnection[]
imageUrl String?
permittedUsers UserToRepoPermission[]
permissionSyncJobs RepoPermissionSyncJob[]
permissionSyncedAt DateTime? /// When the permissions were last synced successfully.
jobs RepoIndexingJob[]
indexedAt DateTime? /// When the repo was last indexed successfully.
indexedCommitHash String? /// The commit hash of the last indexed commit (on HEAD).
external_id String /// The id of the repo in the external service
external_codeHostType String /// The type of the external service (e.g., github, gitlab, etc.)
external_codeHostUrl String /// The base url of the external service (e.g., https://github.com)
org Org @relation(fields: [orgId], references: [id], onDelete: Cascade)
orgId Int
searchContexts SearchContext[]
@@unique([external_id, external_codeHostUrl, orgId])
@@index([orgId])
}
enum RepoIndexingJobStatus {
PENDING
IN_PROGRESS
COMPLETED
FAILED
}
enum RepoIndexingJobType {
INDEX
CLEANUP
}
model RepoIndexingJob {
id String @id @default(cuid())
type RepoIndexingJobType
status RepoIndexingJobStatus @default(PENDING)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
completedAt DateTime?
metadata Json? /// For schema see repoIndexingJobMetadataSchema in packages/shared/src/types.ts
errorMessage String?
repo Repo @relation(fields: [repoId], references: [id], onDelete: Cascade)
repoId Int
}
enum RepoPermissionSyncJobStatus {
PENDING
IN_PROGRESS
COMPLETED
FAILED
}
model RepoPermissionSyncJob {
id String @id @default(cuid())
status RepoPermissionSyncJobStatus @default(PENDING)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
completedAt DateTime?
errorMessage String?
repo Repo @relation(fields: [repoId], references: [id], onDelete: Cascade)
repoId Int
}
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
repos RepoToConnection[]
// The type of connection (e.g., github, gitlab, etc.)
connectionType String
syncJobs ConnectionSyncJob[]
/// When the connection was last synced successfully.
syncedAt DateTime?
// The organization that owns this connection
org Org @relation(fields: [orgId], references: [id], onDelete: Cascade)
orgId Int
@@unique([name, orgId])
}
enum ConnectionSyncJobStatus {
PENDING
IN_PROGRESS
COMPLETED
FAILED
}
model ConnectionSyncJob {
id String @id @default(cuid())
status ConnectionSyncJobStatus @default(PENDING)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
completedAt DateTime?
warningMessages String[]
errorMessage String?
connection Connection @relation(fields: [connectionId], references: [id], onDelete: Cascade)
connectionId Int
}
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])
@@index([repoId, connectionId])
}
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
permissionSyncJobs UserPermissionSyncJob[]
permissionSyncedAt DateTime?
}
enum UserPermissionSyncJobStatus {
PENDING
IN_PROGRESS
COMPLETED
FAILED
}
model UserPermissionSyncJob {
id String @id @default(cuid())
status UserPermissionSyncJobStatus @default(PENDING)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
completedAt DateTime?
errorMessage String?
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
userId String
}
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.
}