Fünf Distributionen (Debian 12/13, Ubuntu 22.04/24.04/26.04) und drei Profile liegen unter catalog/ und werden beim Start abgeglichen. Die Datei ist maßgeblich für den Inhalt, die Datenbank nur für „aktiv“; verschwundene Einträge werden markiert, nicht gelöscht. Unbekannte Schlüssel sind Fehler, damit Tippfehler nicht still verschwinden; eine kaputte Datei wird mit Pfad gemeldet und übersprungen, statt den Start zu verhindern. Prüfsummen-Parser kennt das Debian-, Ubuntu- und BSD-Format; bei mehreren LXC-Templates gewinnt die höchste Version. Closes #004 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
142 lines
4.2 KiB
Plaintext
142 lines
4.2 KiB
Plaintext
// 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
|
||
}
|