Files
kapteins-daagbok/server/prisma/schema.prisma
T
elpatron 2428313a22 feat: Web Push für Logbuch-Eigner bei Crew-Sync
Benachrichtigt Owner optional per VAPID/Web Push, wenn Collaborators
Änderungen synchronisieren — ohne Klartext-Inhalte, mit Opt-in in den
Einstellungen, Custom Service Worker und Deep-Link zum Logbuch.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-30 11:36:03 +02:00

192 lines
5.4 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?
}
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 Credential {
id String @id @default(uuid())
userId String
credentialId String @unique
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[]
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 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])
}