ec11dd8d2b
Benutzerweiter Vessel-Pool (E2E, Sync, Migration von Legacy-Yachts) mit LogbookVesselSelection und LogbookVesselPicker. Profil mit Accordion (Flotte & Crew); Demo und Onboarding-Tour inkl. profile_vessel_pool. Co-authored-by: Cursor <cursoragent@cursor.com>
255 lines
7.2 KiB
Plaintext
255 lines
7.2 KiB
Plaintext
datasource db {
|
|
provider = "postgresql"
|
|
url = env("DATABASE_URL")
|
|
}
|
|
|
|
generator client {
|
|
provider = "prisma-client-js"
|
|
}
|
|
|
|
model User {
|
|
id String @id @default(uuid())
|
|
username String @unique
|
|
createdAt DateTime @default(now())
|
|
encryptedMasterKeyPrf String? // Encrypted using PRF-derived key
|
|
encryptedMasterKeyPrfIv String?
|
|
encryptedMasterKeyPrfTag String?
|
|
encryptedMasterKeyRec String // Encrypted using 12-word recovery phrase
|
|
encryptedMasterKeyRecIv String
|
|
encryptedMasterKeyRecTag String
|
|
credentials Credential[]
|
|
logbooks Logbook[]
|
|
collaborations Collaboration[]
|
|
pushSubscriptions PushSubscription[]
|
|
notificationPrefs UserNotificationPrefs?
|
|
appearancePrefs UserAppearancePrefs?
|
|
personPool PersonPayload[]
|
|
vesselPool VesselPayload[]
|
|
}
|
|
|
|
model PushSubscription {
|
|
id String @id @default(uuid())
|
|
userId String
|
|
endpoint String @unique
|
|
p256dh String
|
|
auth String
|
|
userAgent String?
|
|
locale String?
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
|
|
@@index([userId])
|
|
}
|
|
|
|
model UserNotificationPrefs {
|
|
userId String @id
|
|
collaboratorChangesEnabled Boolean @default(false)
|
|
updatedAt DateTime @updatedAt
|
|
|
|
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
}
|
|
|
|
model UserAppearancePrefs {
|
|
userId String @id
|
|
theme String @default("auto")
|
|
colorScheme String @default("auto")
|
|
updatedAt DateTime @updatedAt
|
|
|
|
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
}
|
|
|
|
model Credential {
|
|
id String @id @default(uuid())
|
|
userId String
|
|
credentialId String @unique
|
|
label String?
|
|
publicKey Bytes
|
|
counter BigInt
|
|
transports String[] // WebAuthn transports list
|
|
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
|
|
@@index([userId])
|
|
}
|
|
|
|
model Logbook {
|
|
id String @id @default(uuid())
|
|
userId String
|
|
encryptedTitle String
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
|
|
// E2E Encrypted key for the owner (encrypted with owner's master key)
|
|
encryptedKey String?
|
|
iv String?
|
|
tag String?
|
|
|
|
yachts YachtPayload[]
|
|
crews CrewPayload[]
|
|
logbookCrewSelection LogbookCrewSelectionPayload?
|
|
logbookVesselSelection LogbookVesselSelectionPayload?
|
|
deviations DeviationPayload[]
|
|
entries EntryPayload[]
|
|
photos PhotoPayload[]
|
|
gpsTracks GpsTrackPayload[]
|
|
collaborators Collaboration[]
|
|
invitations Invitation[]
|
|
|
|
@@index([userId])
|
|
}
|
|
|
|
model Collaboration {
|
|
id String @id @default(uuid())
|
|
logbookId String
|
|
userId String
|
|
role String // "READ" | "WRITE"
|
|
|
|
// The Logbook Key encrypted with this collaborator's master key
|
|
encryptedLogbookKey String
|
|
iv String
|
|
tag String
|
|
|
|
createdAt DateTime @default(now())
|
|
|
|
logbook Logbook @relation(fields: [logbookId], references: [id], onDelete: Cascade)
|
|
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
|
|
@@unique([logbookId, userId])
|
|
}
|
|
|
|
model Invitation {
|
|
token String @id @default(uuid())
|
|
logbookId String
|
|
role String // "READ" | "WRITE"
|
|
createdAt DateTime @default(now())
|
|
expiresAt DateTime
|
|
|
|
logbook Logbook @relation(fields: [logbookId], references: [id], onDelete: Cascade)
|
|
}
|
|
|
|
model YachtPayload {
|
|
id String @id @default(uuid())
|
|
logbookId String @unique
|
|
encryptedData String
|
|
iv String
|
|
tag String
|
|
updatedAt DateTime @updatedAt
|
|
logbook Logbook @relation(fields: [logbookId], references: [id], onDelete: Cascade)
|
|
}
|
|
|
|
model CrewPayload {
|
|
id String @id @default(uuid())
|
|
logbookId String
|
|
payloadId String
|
|
encryptedData String
|
|
iv String
|
|
tag String
|
|
updatedAt DateTime @updatedAt
|
|
logbook Logbook @relation(fields: [logbookId], references: [id], onDelete: Cascade)
|
|
|
|
@@unique([logbookId, payloadId])
|
|
}
|
|
|
|
model PersonPayload {
|
|
id String @id @default(uuid())
|
|
userId String
|
|
payloadId String
|
|
encryptedData String
|
|
iv String
|
|
tag String
|
|
updatedAt DateTime @updatedAt
|
|
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
|
|
@@unique([userId, payloadId])
|
|
@@index([userId])
|
|
}
|
|
|
|
model LogbookCrewSelectionPayload {
|
|
id String @id @default(uuid())
|
|
logbookId String @unique
|
|
encryptedData String
|
|
iv String
|
|
tag String
|
|
updatedAt DateTime @updatedAt
|
|
logbook Logbook @relation(fields: [logbookId], references: [id], onDelete: Cascade)
|
|
}
|
|
|
|
model VesselPayload {
|
|
id String @id @default(uuid())
|
|
userId String
|
|
payloadId String
|
|
encryptedData String
|
|
iv String
|
|
tag String
|
|
updatedAt DateTime @updatedAt
|
|
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
|
|
@@unique([userId, payloadId])
|
|
@@index([userId])
|
|
}
|
|
|
|
model LogbookVesselSelectionPayload {
|
|
id String @id @default(uuid())
|
|
logbookId String @unique
|
|
encryptedData String
|
|
iv String
|
|
tag String
|
|
updatedAt DateTime @updatedAt
|
|
logbook Logbook @relation(fields: [logbookId], references: [id], onDelete: Cascade)
|
|
}
|
|
|
|
model DeviationPayload {
|
|
id String @id @default(uuid())
|
|
logbookId String @unique
|
|
encryptedData String
|
|
iv String
|
|
tag String
|
|
updatedAt DateTime @updatedAt
|
|
logbook Logbook @relation(fields: [logbookId], references: [id], onDelete: Cascade)
|
|
}
|
|
|
|
model EntryPayload {
|
|
id String @id @default(uuid())
|
|
logbookId String
|
|
payloadId String
|
|
encryptedData String
|
|
iv String
|
|
tag String
|
|
updatedAt DateTime @updatedAt
|
|
logbook Logbook @relation(fields: [logbookId], references: [id], onDelete: Cascade)
|
|
|
|
@@unique([logbookId, payloadId])
|
|
@@index([logbookId])
|
|
}
|
|
|
|
model PhotoPayload {
|
|
id String @id @default(uuid())
|
|
logbookId String
|
|
payloadId String
|
|
entryId String
|
|
encryptedData String
|
|
iv String
|
|
tag String
|
|
updatedAt DateTime @updatedAt
|
|
logbook Logbook @relation(fields: [logbookId], references: [id], onDelete: Cascade)
|
|
|
|
@@unique([logbookId, payloadId])
|
|
@@index([logbookId])
|
|
@@index([entryId])
|
|
}
|
|
|
|
model GpsTrackPayload {
|
|
id String @id @default(uuid())
|
|
logbookId String
|
|
entryId String @unique
|
|
encryptedData String
|
|
iv String
|
|
tag String
|
|
updatedAt DateTime @updatedAt
|
|
logbook Logbook @relation(fields: [logbookId], references: [id], onDelete: Cascade)
|
|
|
|
@@index([logbookId])
|
|
}
|