Files
zeekayandHanzo Dev ec5a4686cf Take upstream's name off the last identifiers that carried it
What was left was all internal naming, none of it rendered — the strings a
user actually sees had already been changed. Cleared so a grep for the
upstream brand returns only the attribution that is supposed to be there.

  - components/shared/icons/papermark-sparkle.tsx deleted. It was imported
    into components/view/nav.tsx and never rendered, so this is dead code,
    not a rename.
  - components/emails/year-in-review-papermark.tsx -> year-in-review.tsx,
    and PapermarkYearInReviewEmailProps -> YearInReviewEmailProps. The email
    body was already Hanzo Dataroom throughout; only the file and the
    interface still said otherwise.
  - PAPERMARK_HEADERS -> APP_HEADERS. Its value already read from
    NEXT_PUBLIC_APP_NAME.
  - papermarkUserId -> authenticatedUserId on TusAuthenticatedRequest.
  - isPapermarkUrl -> isDataroomUrl, and its condition no longer tests
    dataroom.hanzo.ai/view/ twice — a rewrite had collapsed two upstream
    domains into one and left the || behind.
  - the shadow database in prisma/add-migration.sh, and two comments.

LICENSE and LLM.md keep every mention: AGPL-3.0 with upstream's copyright
line, and the note recording what this is forked from. Per HIP-0137 those do
not get edited, and the point of this commit is that the brand should appear
where the licence requires it and nowhere else.

Co-authored-by: Hanzo Dev <[email protected]>
2026-08-04 18:58:57 -07:00

209 lines
9.5 KiB
Plaintext

model Link {
id String @id @default(cuid())
document Document? @relation(fields: [documentId], references: [id], onDelete: Cascade)
documentId String? // This can be nullable, representing links without documents
dataroom Dataroom? @relation(fields: [dataroomId], references: [id], onDelete: Cascade)
dataroomId String? // This can be nullable, representing links without datarooms
linkType String @default("DOCUMENT_LINK") // This will store the type of the link
url String? @unique
name String? // Link name
slug String? // Link slug for pretty URLs
expiresAt DateTime? // Optional expiration date
password String? // Optional password for link protection
allowList Json @default("[]")// Array of emails and domains allowed to view the document
denyList Json @default("[]")// Array of emails and domains denied to view the document
emailProtected Boolean @default(true) // Optional email protection
emailAuthenticated Boolean @default(false) // Optional email authentication flag
allowDownload Boolean? @default(false) // Optional give user a option to allow to download the document
isArchived Boolean @default(false) // Indicates if the link is archived
deletedAt DateTime? // Soft delete timestamp
views View[]
domain Domain? @relation(fields: [domainId], references: [id], onDelete: SetNull)
domainId String? // This can be nullable, representing links without custom domains
domainSlug String? // This will store the domain's slug even if the domain is deleted
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
enableNotification Boolean? @default(true) // Optional give user a option to pause/resume the notifications
enableFeedback Boolean? @default(false) // Optional give user a option to enable the reactions toolbar
enableQuestion Boolean? @default(false) // Optional give user a option to enable the question feedback
enableScreenshotProtection Boolean? @default(false) // Optional give user a option to enable the screenshot protection
feedback Feedback?
enableAgreement Boolean? @default(false) // Optional give user a option to enable the terms and conditions
agreement Agreement? @relation(fields: [agreementId], references: [id], onDelete: SetNull)
agreementId String? // This can be nullable, representing links without agreements
showBanner Boolean? @default(false) // Optional give user a option to show the banner and end of document signup form
enableWatermark Boolean? @default(false) // Optional give user a option to enable the watermark
watermarkConfig Json? // This will store the watermark configuration: {text: "Confidential", isTiled: false, color: "#000000", fontSize: 12, opacity: 0.5, rotation: 30, position: "top-right"}
// group links
audienceType String @default("GENERAL") // This will store the audience type of the link
groupId String?
group ViewerGroup? @relation(fields: [groupId], references: [id], onDelete: SetNull)
// granular permissions
permissionGroupId String?
permissionGroup PermissionGroup? @relation(fields: [permissionGroupId], references: [id], onDelete: SetNull)
// custom metatags
metaTitle String? // This will be the meta title of the link
metaDescription String? // This will be the meta description of the link
metaImage String? // This will be the meta image of the link
metaFavicon String? // This will be the meta favicon of the link
enableCustomMetatag Boolean? @default(false) // Optional give user a option to enable the custom metatag
// custom welcome message (overrides brand welcome message)
welcomeMessage String? // Custom welcome message for this specific link
// conversation
enableConversation Boolean @default(false) // Controls if conversations are allowed on this link
conversations Conversation[]
// FAQ system
dataroomFaqItems DataroomFaqItem[]
// AI chats
enableAIAgents Boolean? @default(false) // Enable AI agents for this link
chats Chat[]
// upload
enableUpload Boolean? @default(false) // Optional give user a option to enable the upload document function
isFileRequestOnly Boolean? @default(false) // Optional give user a option to enable the file request only
uploadFolderId String? // This can be nullable, indicating upload to root folder, either document folder or dataroom folder
enableIndexFile Boolean? @default(false)
uploadedDocuments DocumentUpload[]
teamId String?
team Team? @relation(fields: [teamId], references: [id], onDelete: Cascade)
ownerId String?
owner User? @relation("LinkOwner", fields: [ownerId], references: [id], onDelete: SetNull)
customFields CustomField[]
tags TagItem[]
viewerInvitations ViewerInvitation[]
// visitor groups for allow-list
visitorGroups LinkVisitorGroup[]
// workflow entry link
workflow Workflow?
@@unique([domainSlug, slug])
@@index([documentId])
@@index([teamId])
@@index([documentId, isArchived]) // Performance optimization for active links filtering
@@index([permissionGroupId]) // Performance optimization for permission group queries
@@index([deletedAt]) // Performance optimization for filtering deleted links
@@index([ownerId]) // Performance optimization for link owner queries
}
model LinkPreset {
id String @id @default(cuid())
name String
teamId String
team Team @relation(fields: [teamId], references: [id], onDelete: Cascade)
pId String? @unique
enableCustomMetaTag Boolean? @default(false) // Optional give user a option to enable the custom metatag
metaTitle String? // This will be the meta title of the link
metaDescription String? // This will be the meta description of the link
metaImage String? // This will be the meta image of the link
metaFavicon String? // This will be the meta favicon of the link
enableNotification Boolean? @default(false)
emailProtected Boolean? @default(true)
emailAuthenticated Boolean? @default(false)
allowDownload Boolean? @default(false)
enableAllowList Boolean? @default(false)
allowList Json@default("[]")
enableDenyList Boolean? @default(false)
denyList Json@default("[]")
expiresIn Int? // how many days from link creation until it expires in seconds
enableScreenshotProtection Boolean? @default(false)
expiresAt DateTime?
enablePassword Boolean? @default(false)
password String?
enableWatermark Boolean? @default(false)
watermarkConfig Json? //{text: "Confidential", isTiled: false, color: "#000000", fontSize: 12, opacity: 0.5, rotation: 30, position: "top-right"}
enableAgreement Boolean? @default(false)
agreementId String?
enableCustomFields Boolean? @default(false)
customFields Json? //[{type: "SHORT_TEXT", identifier: "name", label: "Name", required: true}]
showBanner Boolean? @default(false) // Optional give user a option to show the "Powered by" banner
welcomeMessage String? // Custom welcome message for links created from this preset
isDefault Boolean @default(false)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@index([teamId])
}
model VisitorGroup {
id String @id @default(cuid())
name String
emails Json @default("[]")// List of emails and domains (e.g., "[email protected]", "@example.org")
teamId String
team Team @relation(fields: [teamId], references: [id], onDelete: Cascade)
links LinkVisitorGroup[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@index([teamId])
}
model LinkVisitorGroup {
id String @id @default(cuid())
linkId String
link Link @relation(fields: [linkId], references: [id], onDelete: Cascade)
visitorGroupId String
visitorGroup VisitorGroup @relation(fields: [visitorGroupId], references: [id], onDelete: Cascade)
createdAt DateTime @default(now())
@@unique([linkId, visitorGroupId])
@@index([linkId])
@@index([visitorGroupId])
}
model CustomField {
id String @id @default(cuid())
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
type String
identifier String
label String
placeholder String?
required Boolean @default(false)
disabled Boolean @default(false)
link Link @relation(fields: [linkId], references: [id], onDelete: Cascade)
linkId String
orderIndex Int @default(0)
@@index([linkId])
}
model CustomFieldResponse {
id String @id @default(cuid())
data Json // Store the custom field responses as a JSON object [{ "identifier": "value", "label": "value", "response:" }]
viewId String @unique
view View @relation(fields: [viewId], references: [id], onDelete: Cascade)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@index([viewId])
}