Merge branch 'main' into feat/signing-reminders

This commit is contained in:
Ephraim Atta-Duncan
2025-08-22 05:05:00 +00:00
977 changed files with 92471 additions and 41466 deletions

View File

@ -39,7 +39,6 @@ enum Role {
model User {
id Int @id @default(autoincrement())
name String?
customerId String? @unique
email String @unique
emailVerified DateTime?
password String? // Todo: (RR7) Remove after RR7 migration.
@ -53,23 +52,23 @@ model User {
avatarImageId String?
disabled Boolean @default(false)
accounts Account[]
sessions Session[]
documents Document[]
subscriptions Subscription[]
passwordResetTokens PasswordResetToken[]
ownedTeams Team[]
ownedPendingTeams TeamPending[]
teamMembers TeamMember[]
twoFactorSecret String?
twoFactorEnabled Boolean @default(false)
twoFactorBackupCodes String?
url String? @unique
accounts Account[]
sessions Session[]
passwordResetTokens PasswordResetToken[]
ownedOrganisations Organisation[]
organisationMember OrganisationMember[]
twoFactorSecret String?
twoFactorEnabled Boolean @default(false)
twoFactorBackupCodes String?
folders Folder[]
documents Document[]
templates Template[]
profile UserProfile?
verificationTokens VerificationToken[]
apiTokens ApiToken[]
templates Template[]
securityAuditLogs UserSecurityAuditLog[]
webhooks Webhook[]
siteSettings SiteSettings[]
@ -79,15 +78,6 @@ model User {
@@index([email])
}
model UserProfile {
id String @id @default(cuid())
enabled Boolean @default(false)
userId Int @unique
bio String?
User User? @relation(fields: [userId], references: [id], onDelete: Cascade)
}
model TeamProfile {
id String @id @default(cuid())
enabled Boolean @default(false)
@ -107,6 +97,7 @@ enum UserSecurityAuditLogType {
PASSKEY_UPDATED
PASSWORD_RESET
PASSWORD_UPDATE
SESSION_REVOKED
SIGN_OUT
SIGN_IN
SIGN_IN_FAIL
@ -190,8 +181,8 @@ model Webhook {
updatedAt DateTime @default(now()) @updatedAt
userId Int
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
teamId Int?
team Team? @relation(fields: [teamId], references: [id], onDelete: Cascade)
teamId Int
team Team @relation(fields: [teamId], references: [id], onDelete: Cascade)
webhookCalls WebhookCall[]
}
@ -227,8 +218,8 @@ model ApiToken {
createdAt DateTime @default(now())
userId Int?
user User? @relation(fields: [userId], references: [id], onDelete: Cascade)
teamId Int?
team Team? @relation(fields: [teamId], references: [id], onDelete: Cascade)
teamId Int
team Team @relation(fields: [teamId], references: [id], onDelete: Cascade)
}
enum SubscriptionStatus {
@ -243,16 +234,46 @@ model Subscription {
planId String @unique
priceId String
periodEnd DateTime?
userId Int?
teamId Int? @unique
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
cancelAtPeriodEnd Boolean @default(false)
team Team? @relation(fields: [teamId], references: [id], onDelete: Cascade)
user User? @relation(fields: [userId], references: [id], onDelete: Cascade)
customerId String
@@index([userId])
organisationId String @unique
organisation Organisation @relation(fields: [organisationId], references: [id], onDelete: Cascade)
@@index([organisationId])
}
/// @zod.import(["import { ZClaimFlagsSchema } from '@documenso/lib/types/subscription';"])
model SubscriptionClaim {
id String @id @default(cuid())
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
name String
locked Boolean @default(false)
teamCount Int
memberCount Int
flags Json /// [ClaimFlags] @zod.custom.use(ZClaimFlagsSchema)
}
/// @zod.import(["import { ZClaimFlagsSchema } from '@documenso/lib/types/subscription';"])
model OrganisationClaim {
id String @id
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
originalSubscriptionClaimId String?
organisation Organisation?
teamCount Int
memberCount Int
flags Json /// [ClaimFlags] @zod.custom.use(ZClaimFlagsSchema)
}
model Account {
@ -312,12 +333,47 @@ enum DocumentVisibility {
ADMIN
}
enum FolderType {
DOCUMENT
TEMPLATE
}
model Folder {
id String @id @default(cuid())
name String
userId Int
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
teamId Int
team Team @relation(fields: [teamId], references: [id], onDelete: Cascade)
pinned Boolean @default(false)
parentId String?
parent Folder? @relation("FolderToFolder", fields: [parentId], references: [id], onDelete: Cascade)
documents Document[]
templates Template[]
createdAt DateTime @default(now())
updatedAt DateTime @default(now()) @updatedAt
subfolders Folder[] @relation("FolderToFolder")
visibility DocumentVisibility @default(EVERYONE)
type FolderType
@@index([userId])
@@index([teamId])
@@index([parentId])
@@index([type])
}
/// @zod.import(["import { ZDocumentAuthOptionsSchema } from '@documenso/lib/types/document-auth';", "import { ZDocumentFormValuesSchema } from '@documenso/lib/types/document-form-values';"])
model Document {
id Int @id @default(autoincrement())
externalId String? /// @zod.string.describe("A custom external ID you can use to identify the document.")
userId Int /// @zod.number.describe("The ID of the user that created this document.")
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
id Int @id @default(autoincrement())
qrToken String? /// @zod.string.describe("The token for viewing the document using the QR code on the certificate.")
externalId String? /// @zod.string.describe("A custom external ID you can use to identify the document.")
userId Int /// @zod.number.describe("The ID of the user that created this document.")
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
teamId Int
team Team @relation(fields: [teamId], references: [id], onDelete: Cascade)
authOptions Json? /// [DocumentAuthOptions] @zod.custom.use(ZDocumentAuthOptionsSchema)
formValues Json? /// [DocumentFormValues] @zod.custom.use(ZDocumentFormValuesSchema)
visibility DocumentVisibility @default(EVERYONE)
@ -327,23 +383,27 @@ model Document {
fields Field[]
shareLinks DocumentShareLink[]
documentDataId String
documentData DocumentData @relation(fields: [documentDataId], references: [id], onDelete: Cascade)
documentMeta DocumentMeta?
createdAt DateTime @default(now())
updatedAt DateTime @default(now()) @updatedAt
completedAt DateTime?
deletedAt DateTime?
teamId Int?
team Team? @relation(fields: [teamId], references: [id])
templateId Int?
template Template? @relation(fields: [templateId], references: [id], onDelete: SetNull)
source DocumentSource
useLegacyFieldInsertion Boolean @default(false)
documentData DocumentData @relation(fields: [documentDataId], references: [id], onDelete: Cascade)
template Template? @relation(fields: [templateId], references: [id], onDelete: SetNull)
auditLogs DocumentAuditLog[]
folder Folder? @relation(fields: [folderId], references: [id], onDelete: SetNull)
folderId String?
@@unique([documentDataId])
@@index([userId])
@@index([status])
@@index([folderId])
}
model DocumentAuditLog {
@ -421,6 +481,8 @@ model DocumentMeta {
language String @default("en")
distributionMethod DocumentDistributionMethod @default(EMAIL)
emailSettings Json? /// [DocumentEmailSettings] @zod.custom.use(ZDocumentEmailSettingsSchema)
emailReplyTo String?
emailId String?
reminderInterval DocumentReminderInterval @default(NONE)
lastReminderSentAt DateTime?
@ -547,36 +609,199 @@ model DocumentShareLink {
@@unique([documentId, email])
}
enum OrganisationType {
PERSONAL
ORGANISATION
}
model Organisation {
id String @id
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
type OrganisationType
name String
url String @unique
avatarImageId String?
customerId String? @unique
subscription Subscription?
organisationClaimId String @unique
organisationClaim OrganisationClaim @relation(fields: [organisationClaimId], references: [id])
members OrganisationMember[]
invites OrganisationMemberInvite[]
groups OrganisationGroup[]
teams Team[]
emailDomains EmailDomain[]
organisationEmails OrganisationEmail[]
avatarImage AvatarImage? @relation(fields: [avatarImageId], references: [id], onDelete: SetNull)
ownerUserId Int
owner User @relation(fields: [ownerUserId], references: [id], onDelete: Cascade)
organisationGlobalSettingsId String @unique
organisationGlobalSettings OrganisationGlobalSettings @relation(fields: [organisationGlobalSettingsId], references: [id])
}
model OrganisationMember {
id String @id
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
userId Int
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
organisationId String
organisation Organisation @relation(fields: [organisationId], references: [id], onDelete: Cascade)
organisationGroupMembers OrganisationGroupMember[]
@@unique([userId, organisationId])
}
model OrganisationMemberInvite {
id String @id
createdAt DateTime @default(now())
email String
token String @unique
status OrganisationMemberInviteStatus @default(PENDING)
organisationId String
organisation Organisation @relation(fields: [organisationId], references: [id], onDelete: Cascade)
organisationRole OrganisationMemberRole
}
model OrganisationGroup {
id String @id
name String?
type OrganisationGroupType
organisationRole OrganisationMemberRole
organisationId String
organisation Organisation @relation(fields: [organisationId], references: [id], onDelete: Cascade)
organisationGroupMembers OrganisationGroupMember[]
teamGroups TeamGroup[]
}
model OrganisationGroupMember {
id String @id
groupId String
group OrganisationGroup @relation(fields: [groupId], references: [id], onDelete: Cascade)
organisationMember OrganisationMember @relation(fields: [organisationMemberId], references: [id], onDelete: Cascade)
organisationMemberId String
@@unique([organisationMemberId, groupId])
}
model TeamGroup {
id String @id
organisationGroupId String
organisationGroup OrganisationGroup @relation(fields: [organisationGroupId], references: [id], onDelete: Cascade)
teamRole TeamMemberRole
teamId Int
team Team @relation(fields: [teamId], references: [id], onDelete: Cascade)
@@unique([teamId, organisationGroupId])
}
enum OrganisationGroupType {
INTERNAL_ORGANISATION
INTERNAL_TEAM
CUSTOM
}
enum OrganisationMemberRole {
ADMIN
MANAGER
MEMBER
}
enum TeamMemberRole {
ADMIN
MANAGER
MEMBER
}
enum TeamMemberInviteStatus {
enum OrganisationMemberInviteStatus {
ACCEPTED
PENDING
DECLINED
}
model TeamGlobalSettings {
teamId Int @unique
/// @zod.import(["import { ZDocumentEmailSettingsSchema } from '@documenso/lib/types/document-email';"])
model OrganisationGlobalSettings {
id String @id
organisation Organisation?
documentVisibility DocumentVisibility @default(EVERYONE)
documentLanguage String @default("en")
includeSenderDetails Boolean @default(true)
includeSigningCertificate Boolean @default(true)
includeAuditLog Boolean @default(false)
documentTimezone String? // Nullable to allow using local timezones if not set.
documentDateFormat String @default("yyyy-MM-dd hh:mm a")
typedSignatureEnabled Boolean @default(true)
uploadSignatureEnabled Boolean @default(true)
drawSignatureEnabled Boolean @default(true)
emailId String?
email OrganisationEmail? @relation(fields: [emailId], references: [id])
emailReplyTo String?
// emailReplyToName String? // Placeholder for future feature.
emailDocumentSettings Json /// [DocumentEmailSettings] @zod.custom.use(ZDocumentEmailSettingsSchema)
brandingEnabled Boolean @default(false)
brandingLogo String @default("")
brandingUrl String @default("")
brandingCompanyDetails String @default("")
brandingHidePoweredBy Boolean @default(false)
}
team Team @relation(fields: [teamId], references: [id], onDelete: Cascade)
/// @zod.import(["import { ZDocumentEmailSettingsSchema } from '@documenso/lib/types/document-email';"])
model TeamGlobalSettings {
id String @id
team Team?
documentVisibility DocumentVisibility?
documentLanguage String?
documentTimezone String?
documentDateFormat String?
includeSenderDetails Boolean?
includeSigningCertificate Boolean?
includeAuditLog Boolean?
typedSignatureEnabled Boolean?
uploadSignatureEnabled Boolean?
drawSignatureEnabled Boolean?
emailId String?
email OrganisationEmail? @relation(fields: [emailId], references: [id])
emailReplyTo String?
// emailReplyToName String? // Placeholder for future feature.
emailDocumentSettings Json? /// [DocumentEmailSettingsNullable] @zod.custom.use(ZDocumentEmailSettingsSchema)
brandingEnabled Boolean?
brandingLogo String?
brandingUrl String?
brandingCompanyDetails String?
}
model Team {
@ -585,48 +810,25 @@ model Team {
url String @unique
createdAt DateTime @default(now())
avatarImageId String?
customerId String? @unique
ownerUserId Int
members TeamMember[]
invites TeamMemberInvite[]
teamEmail TeamEmail?
emailVerification TeamEmailVerification?
transferVerification TeamTransferVerification?
teamGlobalSettings TeamGlobalSettings?
avatarImage AvatarImage? @relation(fields: [avatarImageId], references: [id], onDelete: SetNull)
teamEmail TeamEmail?
emailVerification TeamEmailVerification?
avatarImage AvatarImage? @relation(fields: [avatarImageId], references: [id], onDelete: SetNull)
profile TeamProfile?
owner User @relation(fields: [ownerUserId], references: [id], onDelete: Cascade)
subscription Subscription?
profile TeamProfile?
documents Document[]
templates Template[]
apiTokens ApiToken[]
webhooks Webhook[]
}
documents Document[]
templates Template[]
folders Folder[]
apiTokens ApiToken[]
webhooks Webhook[]
teamGroups TeamGroup[]
model TeamPending {
id Int @id @default(autoincrement())
name String
url String @unique
createdAt DateTime @default(now())
customerId String @unique
ownerUserId Int
organisationId String
organisation Organisation @relation(fields: [organisationId], references: [id], onDelete: Cascade)
owner User @relation(fields: [ownerUserId], references: [id], onDelete: Cascade)
}
model TeamMember {
id Int @id @default(autoincrement())
teamId Int
createdAt DateTime @default(now())
role TeamMemberRole
userId Int
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
team Team @relation(fields: [teamId], references: [id], onDelete: Cascade)
@@unique([userId, teamId])
teamGlobalSettingsId String @unique
teamGlobalSettings TeamGlobalSettings @relation(fields: [teamGlobalSettingsId], references: [id], onDelete: Cascade)
}
model TeamEmail {
@ -649,33 +851,6 @@ model TeamEmailVerification {
team Team @relation(fields: [teamId], references: [id], onDelete: Cascade)
}
model TeamTransferVerification {
teamId Int @id @unique
userId Int
name String
email String
token String @unique
completed Boolean @default(false)
expiresAt DateTime
createdAt DateTime @default(now())
clearPaymentMethods Boolean @default(false)
team Team @relation(fields: [teamId], references: [id], onDelete: Cascade)
}
model TeamMemberInvite {
id Int @id @default(autoincrement())
teamId Int
createdAt DateTime @default(now())
email String
status TeamMemberInviteStatus @default(PENDING)
role TeamMemberRole
token String @unique
team Team @relation(fields: [teamId], references: [id], onDelete: Cascade)
@@unique([teamId, email])
}
enum TemplateType {
PUBLIC
PRIVATE
@ -697,11 +872,14 @@ model TemplateMeta {
uploadSignatureEnabled Boolean @default(true)
drawSignatureEnabled Boolean @default(true)
templateId Int @unique
template Template @relation(fields: [templateId], references: [id], onDelete: Cascade)
redirectUrl String?
language String @default("en")
templateId Int @unique
template Template @relation(fields: [templateId], references: [id], onDelete: Cascade)
redirectUrl String?
language String @default("en")
emailSettings Json? /// [DocumentEmailSettings] @zod.custom.use(ZDocumentEmailSettingsSchema)
emailReplyTo String?
emailId String?
}
/// @zod.import(["import { ZDocumentAuthOptionsSchema } from '@documenso/lib/types/document-auth';"])
@ -710,8 +888,6 @@ model Template {
externalId String?
type TemplateType @default(PRIVATE)
title String
userId Int
teamId Int?
visibility DocumentVisibility @default(EVERYONE)
authOptions Json? /// [DocumentAuthOptions] @zod.custom.use(ZDocumentAuthOptionsSchema)
templateMeta TemplateMeta?
@ -721,15 +897,26 @@ model Template {
publicTitle String @default("")
publicDescription String @default("")
team Team? @relation(fields: [teamId], references: [id], onDelete: Cascade)
templateDocumentData DocumentData @relation(fields: [templateDocumentDataId], references: [id], onDelete: Cascade)
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
recipients Recipient[]
fields Field[]
directLink TemplateDirectLink?
documents Document[]
useLegacyFieldInsertion Boolean @default(false)
userId Int
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
teamId Int
team Team @relation(fields: [teamId], references: [id], onDelete: Cascade)
templateDocumentData DocumentData @relation(fields: [templateDocumentDataId], references: [id], onDelete: Cascade)
recipients Recipient[]
fields Field[]
directLink TemplateDirectLink?
documents Document[]
folder Folder? @relation(fields: [folderId], references: [id], onDelete: SetNull)
folderId String?
@@unique([templateDocumentDataId])
@@index([userId])
}
model TemplateDirectLink {
@ -807,6 +994,49 @@ model AvatarImage {
id String @id @default(cuid())
bytes String
team Team[]
user User[]
team Team[]
user User[]
organisation Organisation[]
}
enum EmailDomainStatus {
PENDING
ACTIVE
}
model EmailDomain {
id String @id
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
status EmailDomainStatus @default(PENDING)
selector String @unique
domain String @unique
publicKey String
privateKey String
organisationId String
organisation Organisation @relation(fields: [organisationId], references: [id], onDelete: Cascade)
emails OrganisationEmail[]
}
model OrganisationEmail {
id String @id
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
email String @unique
emailName String
// replyTo String?
emailDomainId String
emailDomain EmailDomain @relation(fields: [emailDomainId], references: [id], onDelete: Cascade)
organisationId String
organisation Organisation @relation(fields: [organisationId], references: [id], onDelete: Cascade)
organisationGlobalSettings OrganisationGlobalSettings[]
teamGlobalSettings TeamGlobalSettings[]
}