feat(260923-dhh): Proxmox-Modul Aufgabe 1 - PVE per Token, Ende-zu-Ende
- ProxmoxServer/ProxmoxServerStatus mit RLS (tenant_isolation_policy +
system_read_policy auf ProxmoxServer fuer den kommenden Planer)
- proxmox-auth.ts (Token-Kopfzeilen PVE/PBS), proxmox-client.service.ts
(proxmoxGet, ausschliesslich lesend, Dispatcher je Aufruf aus
tlsRejectUnauthorized, nie global)
- proxmox.service.ts: Server anlegen (Geheimnis verschluesselt,
select ohne Geheimnisfelder), Serverliste, PVE-Abfrage mit
nachsichtiger Grundauswertung (Knoten/Gaeste)
- Controller/Modul/Seed nach Domaincheck-Vorbild, Kategorie
"infrastructure", @UseModule('proxmox') + @Roles auf Schreibwegen
- Modulseite (duenne Liste) + proxmox-api.ts + Registrierung in
MODULE_REGISTRY
- Zugriffsklassifikation nachgezogen (rls-access-inventory.spec.ts gruen)
Tore: api 1247/1247 (>=1240), web 693/693, type-check 4/4, lint 5/5,
Biome apps/web 53 Warnungen (unveraendert).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -651,3 +651,54 @@ model TenderRssFeedSource {
|
||||
@@unique([userId, url])
|
||||
@@index([userId])
|
||||
}
|
||||
|
||||
// Quick-Auftrag 260923-dhh — Proxmox-Modul (PVE/PBS/PMG), nur beobachten (D-01).
|
||||
//
|
||||
// Vorbild ist `CalendarSource` (mehrere verschluesselte Fremdsystem-Zugaenge
|
||||
// je Mandant), NICHT `DkvModuleConfig` (Singleton je Mandant): ein Mandant
|
||||
// traegt hier beliebig viele Server ein. `authMethod` waehlt zwischen einem
|
||||
// API-Token (`tokenId`/`encryptedTokenSecret`) und Benutzer/Passwort
|
||||
// (`username`/`encryptedPassword`); PMG kennt laut Recherche nur Letzteres
|
||||
// (DTO lehnt Token bei PMG serverseitig ab, D-03). `tlsRejectUnauthorized`
|
||||
// ist woertlich der Feldname aus `LdapConfig` — Voreinstellung "pruefen",
|
||||
// pro Zeile umschaltbar, nie global (D-04).
|
||||
model ProxmoxServer {
|
||||
id String @id @default(uuid())
|
||||
tenantId String
|
||||
name String
|
||||
productType String // 'pve' | 'pbs' | 'pmg'
|
||||
baseUrl String
|
||||
authMethod String // 'token' | 'password'
|
||||
tokenId String?
|
||||
encryptedTokenSecret String? // AES-256-GCM ciphertext (iv:authTag:ciphertext hex), wie CalendarSource.encryptedPassword
|
||||
username String?
|
||||
encryptedPassword String? // AES-256-GCM ciphertext (iv:authTag:ciphertext hex)
|
||||
tlsRejectUnauthorized Boolean @default(true)
|
||||
isActive Boolean @default(true)
|
||||
pollIntervalMin Int @default(5)
|
||||
position Int @default(0)
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
status ProxmoxServerStatus?
|
||||
|
||||
@@index([tenantId])
|
||||
}
|
||||
|
||||
// Zwischenlager (D-05): der Hintergrunddienst (Aufgabe 4) beschreibt diese
|
||||
// Zeile, die Modulseite liest ausschliesslich daraus — nie live bei Proxmox.
|
||||
model ProxmoxServerStatus {
|
||||
id String @id @default(uuid())
|
||||
serverId String @unique
|
||||
server ProxmoxServer @relation(fields: [serverId], references: [id], onDelete: Cascade)
|
||||
tenantId String
|
||||
lastPolledAt DateTime?
|
||||
lastOkAt DateTime?
|
||||
reachable Boolean @default(false)
|
||||
errorKind String?
|
||||
errorDetail String?
|
||||
metrics Json?
|
||||
rawSample Json?
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@index([tenantId])
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user