-- 260923-dhh — Proxmox-Modul (PVE/PBS/PMG), nur beobachten (D-01). -- -- Zweck: zwei neue Tabellen fuer das Proxmox-Modul. `ProxmoxServer` traegt -- die vom Administrator eingetragenen Server (Name, Typ, Adresse, Zugang, -- verschluesselt) — mehrere Zeilen je Mandant, Vorbild `CalendarSource`, -- NICHT `DkvModuleConfig` (Singleton je Mandant). `ProxmoxServerStatus` ist -- das Zwischenlager (D-05): der Hintergrunddienst (Aufgabe 4) beschreibt -- diese Zeile, die Modulseite liest ausschliesslich daraus. -- -- Von Hand geschrieben (Vorbild 20260923120000_dashboard_tabs), von Hand -- gepflegter Kopfkommentar Pflicht bei jeder RLS-Migration in diesem Projekt. -- -- Zeilenschutz (D-08, Pflicht — sonst schlaegt rls-coverage.spec.ts fehl): -- beide Tabellen tragen `tenantId` und `tenant_isolation_policy` OHNE -- Benutzerdimension (`USING ("tenantId" = current_tenant_id())`, Form aus -- `DkvModuleConfig`, Migration 20260909140000) — Proxmox-Server sind -- Verwaltungsdaten des Mandanten, nicht persoenliche Daten eines einzelnen -- Benutzers. -- -- Zusaetzlich NUR auf "ProxmoxServer" eine `system_read_policy` (Form aus -- 20260914120000_rls_system_context_read): der Hintergrunddienst aus -- Aufgabe 4 muss beim Start ueber `forSystem()` die aktiven Server ALLER -- Mandanten sehen, um je Mandant einen eigenen Cron-Auftrag zu registrieren -- (Muster DKV-/Tender-Planer). "ProxmoxServerStatus" bekommt diese Regel -- BEWUSST NICHT — geschrieben wird dort ausschliesslich je Zeile -- mandantengebunden (`forTenant(prisma, tenantId)`), ein Systemlesezugriff -- auf das Zwischenlager hat keinen Aufrufer. -- -- Rechte fuer die Anwendungsrolle tessera_app kommen automatisch ueber -- ALTER DEFAULT PRIVILEGES aus 20260909130000_rls_app_role — hier nichts zu -- tun. -- -- WICHTIG: wie alle bisherigen RLS-Migrationen wirken diese Regeln erst, -- wenn die Anwendung als Rolle ohne Umgehungsrecht verbindet (Schalter -- heute AUS, siehe docs/mandantentrennung-datenbankrolle.md). -- 1) ProxmoxServer CREATE TABLE "ProxmoxServer" ( "id" TEXT NOT NULL, "tenantId" TEXT NOT NULL, "name" TEXT NOT NULL, "productType" TEXT NOT NULL, "baseUrl" TEXT NOT NULL, "authMethod" TEXT NOT NULL, "tokenId" TEXT, "encryptedTokenSecret" TEXT, "username" TEXT, "encryptedPassword" TEXT, "tlsRejectUnauthorized" BOOLEAN NOT NULL DEFAULT true, "isActive" BOOLEAN NOT NULL DEFAULT true, "pollIntervalMin" INTEGER NOT NULL DEFAULT 5, "position" INTEGER NOT NULL DEFAULT 0, "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, "updatedAt" TIMESTAMP(3) NOT NULL, CONSTRAINT "ProxmoxServer_pkey" PRIMARY KEY ("id") ); CREATE INDEX "ProxmoxServer_tenantId_idx" ON "ProxmoxServer"("tenantId"); ALTER TABLE "ProxmoxServer" ENABLE ROW LEVEL SECURITY; ALTER TABLE "ProxmoxServer" FORCE ROW LEVEL SECURITY; CREATE POLICY tenant_isolation_policy ON "ProxmoxServer" USING ("tenantId" = current_tenant_id()); CREATE POLICY system_read_policy ON "ProxmoxServer" FOR SELECT USING (is_system_context()); -- 2) ProxmoxServerStatus — Zwischenlager, 1:1 je Server, Loeschweitergabe. CREATE TABLE "ProxmoxServerStatus" ( "id" TEXT NOT NULL, "serverId" TEXT NOT NULL, "tenantId" TEXT NOT NULL, "lastPolledAt" TIMESTAMP(3), "lastOkAt" TIMESTAMP(3), "reachable" BOOLEAN NOT NULL DEFAULT false, "errorKind" TEXT, "errorDetail" TEXT, "metrics" JSONB, "rawSample" JSONB, "updatedAt" TIMESTAMP(3) NOT NULL, CONSTRAINT "ProxmoxServerStatus_pkey" PRIMARY KEY ("id") ); CREATE UNIQUE INDEX "ProxmoxServerStatus_serverId_key" ON "ProxmoxServerStatus"("serverId"); CREATE INDEX "ProxmoxServerStatus_tenantId_idx" ON "ProxmoxServerStatus"("tenantId"); ALTER TABLE "ProxmoxServerStatus" ADD CONSTRAINT "ProxmoxServerStatus_serverId_fkey" FOREIGN KEY ("serverId") REFERENCES "ProxmoxServer"("id") ON DELETE CASCADE ON UPDATE CASCADE; ALTER TABLE "ProxmoxServerStatus" ENABLE ROW LEVEL SECURITY; ALTER TABLE "ProxmoxServerStatus" FORCE ROW LEVEL SECURITY; CREATE POLICY tenant_isolation_policy ON "ProxmoxServerStatus" USING ("tenantId" = current_tenant_id());