// Datenmodell von ProxDeploy. Namensabbildung zur Vorgabe: siehe CLAUDE.md. // Modelle kommen mit dem Issue dazu, das sie braucht – der Plan in docs/architektur.md // zeigt das Zielbild. generator client { provider = "prisma-client" output = "../src/generated/prisma" } datasource db { provider = "postgresql" } enum Rolle { ADMIN OPERATOR } enum Quelle { WEB CLI API SYSTEM } model Benutzer { id String @id @default(cuid()) benutzername String @unique anzeigename String email String? /// argon2id; leer bei Benutzern, die sich nur per OIDC anmelden. passwortHash String? oidcSubjekt String? @unique rolle Rolle @default(OPERATOR) aktiv Boolean @default(true) /// Persönliche Standardwerte im Assistenten. standards Json? erstelltAm DateTime @default(now()) geaendertAm DateTime @updatedAt protokoll Protokoll[] } /// Audit-Log. Nur anhängen – ein Trigger verweigert UPDATE und DELETE. model Protokoll { id BigInt @id @default(autoincrement()) zeit DateTime @default(now()) benutzerId String? benutzer Benutzer? @relation(fields: [benutzerId], references: [id], onDelete: SetNull) quelle Quelle aktion String ziel String? details Json? ip String? @@index([zeit]) @@index([benutzerId, zeit]) } model Einstellung { schluessel String @id wert Json geaendertAm DateTime @updatedAt } /// Ein Proxmox-VE-Einzelhost oder -Cluster. Geheimnisse liegen AES-256-GCM-verschlüsselt (v1.…). model Server { id String @id @default(cuid()) /// Kurzname, auch für die CLI (`--server rz1`). name String @unique /// Anzeigename, z. B. „Rechenzentrum 1“. titel String /// https://host:8006 url String /// user@realm!tokenid tokenId String tokenGeheimnis String /// Aus: nur ein gepinnter Fingerprint zählt. An: Systemvertrauen (+ optional Pin). tlsPruefen Boolean @default(false) /// SHA-256 des Serverzertifikats, Großbuchstaben mit Doppelpunkten. fingerabdruck String? sshAktiv Boolean @default(false) sshBenutzer String @default("root") sshPort Int @default(22) sshPrivat String? sshOeffentlich String? /// Gepinnte Host-Keys je Node: { "pve01": "SHA256:…" }. sshHostSchluessel Json? templateVmidVon Int @default(9000) templateVmidBis Int @default(9999) gastVmidVon Int @default(100) /// Statische Adresse für die Template-Vorbereitung ohne SSH: { bridge, vlan, ip, gateway }. bauNetz Json? /// Standard-Node, -Storage, -Bridge für den Assistenten. standards Json? /// Bericht des letzten Verbindungstests inkl. Fähigkeiten (VerbindungsBericht, #003). letzterTest Json? erreichbar Boolean? pveVersion String? geprueftAm DateTime? erstelltAm DateTime @default(now()) geaendertAm DateTime @updatedAt } enum Herkunft { KATALOG EIGEN } /// Spiegel von catalog/distros/*.yaml. Die Datei ist maßgeblich; nur `aktiv` gehört der Datenbank. model Distribution { id String @id name String familie String /// Validierter Inhalt der YAML-Datei. definition Json quelltext String dateiHash String aktiv Boolean @default(true) /// Gesetzt, wenn die Datei aus dem Katalog verschwunden ist – die Zeile bleibt für den Verlauf. entferntAm DateTime? synchronisiertAm DateTime geaendertVonId String? } /// Profile aus catalog/profiles/*.yaml (KATALOG, schreibgeschützt) und eigene aus der GUI (EIGEN). model Profil { id String @id name String beschreibung String? familien String[] herkunft Herkunft definition Json /// YAML wie eingegeben – Kommentare bleiben erhalten. quelltext String dateiHash String? aktiv Boolean @default(true) entferntAm DateTime? synchronisiertAm DateTime? geaendertVonId String? geaendertAm DateTime @updatedAt }