--- phase: quick plan: 260923-le6 subsystem: proxmox-modul tags: [nestjs, next-intl, vitest, tdd, proxmox] requires: - phase: quick-260923-dhh provides: "Proxmox-Modul (PVE/PBS/PMG) inklusive normalizePmg und ServerCard; Abnahmebefund Wahrheit 7 (PMG-Teilsumme) blieb offen" provides: - "sumOrNull liefert null, sobald ein Teilwert einer PMG-Summe (Spam/Viren) fehlt oder unlesbar ist — nie mehr eine Teilsumme" - "ServerCard zeigt Nicht-Admins fuer nie abgefragte Server einen Hinweis ohne Knopfverweis (isAdmin-Eigenschaft, Vorgabe false)" - "Proxmox-Modulseite zeigt den Knopf 'Jetzt aktualisieren' nur ADMIN/SUPER_ADMIN" affects: [proxmox-modul, dashboard-kachel-proxmox] actuals: tokens: 4581 tasks: 3 commits: 4 plan_head_before: 6530ae5 tech-stack: added: [] patterns: - "isAdmin?: boolean (Vorgabe false) als sichere Eigenschaft fuer UI-Elemente, deren serverseitige Aktion rollenbeschraenkt ist (uebernimmt das bestehende Muster aus page.tsx, kein neuer Mechanismus)" key-files: created: - apps/web/src/app/(portal)/modules/proxmox/proxmox-page-roles.test.tsx modified: - apps/api/src/proxmox/proxmox-normalize.ts - apps/api/src/proxmox/proxmox-normalize.spec.ts - apps/web/src/app/(portal)/modules/proxmox/components/ServerCard.tsx - apps/web/src/app/(portal)/modules/proxmox/components/ServerCard.test.tsx - apps/web/src/messages/de.json - apps/web/src/messages/en.json - apps/web/src/app/(portal)/modules/proxmox/page.tsx key-decisions: - "Wortwahl fuer notPolledYetAutomatic: 'nach der naechsten automatischen Abfrage' statt 'in Kuerze', weil das Poll-Intervall je Server 1-1440 Minuten einstellbar ist und 'in Kuerze' nicht immer zutraefe" patterns-established: - "sumOrNull(a, b): null wenn a ODER b null ist (statt Ersatz-durch-Null) — Muster fuer jede zukuenftige Tageszahl aus zwei Teilwerten" requirements-completed: [] coverage: - id: D1 description: "PMG-Summe (Spam/Viren) ist null, sobald genau eine Haelfte fehlt oder unlesbar ist — in beide Richtungen (in/out), Paare unabhaengig voneinander" verification: - kind: unit ref: "apps/api/src/proxmox/proxmox-normalize.spec.ts#nur eine Haelfte vorhanden -> null (Spam, nur spamcount_in)" status: pass - kind: unit ref: "apps/api/src/proxmox/proxmox-normalize.spec.ts#nur eine Haelfte vorhanden -> null (Spam, nur spamcount_out)" status: pass - kind: unit ref: "apps/api/src/proxmox/proxmox-normalize.spec.ts#nur eine Haelfte vorhanden -> null (Viren, nur viruscount_in)" status: pass - kind: unit ref: "apps/api/src/proxmox/proxmox-normalize.spec.ts#nur eine Haelfte vorhanden -> null (Viren, nur viruscount_out)" status: pass - kind: unit ref: "apps/api/src/proxmox/proxmox-normalize.spec.ts#eine Haelfte ist nicht lesbar -> null (Spam, spamcount_out ist Text)" status: pass - kind: unit ref: "apps/api/src/proxmox/proxmox-normalize.spec.ts#Unabhaengigkeit der Paare: Spam unvollstaendig, Viren vollstaendig" status: pass human_judgment: false - id: D2 description: "Auf der Proxmox-Modulseite sehen nur ADMIN/SUPER_ADMIN den Knopf 'Jetzt aktualisieren'; USER und ein noch nicht geladener Benutzer sehen ihn nicht; ServerCard verweist Nicht-Admins nicht auf den Knopf" verification: - kind: unit ref: "apps/web/src/app/(portal)/modules/proxmox/proxmox-page-roles.test.tsx#Rolle USER: kein Knopf" status: pass - kind: unit ref: "apps/web/src/app/(portal)/modules/proxmox/proxmox-page-roles.test.tsx#kein Benutzer geladen (user: null): kein Knopf" status: pass - kind: unit ref: "apps/web/src/app/(portal)/modules/proxmox/proxmox-page-roles.test.tsx#Rolle ADMIN: Knopf sichtbar" status: pass - kind: unit ref: "apps/web/src/app/(portal)/modules/proxmox/proxmox-page-roles.test.tsx#Rolle SUPER_ADMIN: Knopf sichtbar" status: pass - kind: unit ref: "apps/web/src/app/(portal)/modules/proxmox/proxmox-page-roles.test.tsx#leere Serverliste bei ADMIN: weiterhin kein Knopf" status: pass - kind: unit ref: "apps/web/src/app/(portal)/modules/proxmox/components/ServerCard.test.tsx#260923-le6: isAdmin={false}, noch nie abgefragt -> automatischer Hinweis ohne Knopfverweis" status: pass - kind: unit ref: "apps/web/src/app/(portal)/modules/proxmox/components/ServerCard.test.tsx#260923-le6: isAdmin weggelassen -> verhaelt sich wie isAdmin={false}" status: pass human_judgment: false duration: 21min completed: 2026-09-23 status: complete --- # Quick Task 260923-le6: Zwei Abnahmebefunde des Proxmox-Moduls behoben Summary **PMG-Teilsumme wird null statt still falsch (sumOrNull), Aktualisieren-Knopf der Proxmox-Modulseite nur noch fuer ADMIN/SUPER_ADMIN sichtbar** ## Performance - **Duration:** 21 min - **Started:** 2026-09-23T13:12:00Z - **Completed:** 2026-09-23T13:33:50Z - **Tasks:** 3 - **Files modified:** 8 (7 geaendert, 1 neu) ## Accomplishments - `sumOrNull(a, b)` in `proxmox-normalize.ts` liefert `null`, sobald ein Teilwert (Spam oder Viren, je Richtung in/out) fehlt oder nicht lesbar ist — die bisherige stille Ersatz-durch-0-Addition ist vollstaendig entfernt. Damit ist Wahrheit 7 (Blocker) aus `260923-dhh-VERIFICATION.md` geschlossen. - `ServerCard` bekommt die optionale Eigenschaft `isAdmin` (Vorgabe `false`) und zeigt Nicht-Admins fuer einen nie abgefragten Server einen neuen Hinweistext (`proxmox.card.notPolledYetAutomatic`, de/en), der auf keinen Knopf verweist. - Die Proxmox-Modulseite zeigt den Knopf "Jetzt aktualisieren" nur noch, wenn `isAdmin` wahr ist (bestehende Variable wiederverwendet, kein neuer Rollen-Mechanismus), und reicht `isAdmin` an `ServerCard` weiter. ## Task Commits Alle Aufgaben wurden per TDD (RED -> GREEN) umgesetzt und einzeln committet: 1. **Aufgabe 1 (RED): PMG-Teilsumme-Tests** - `c13d657` (test) 2. **Aufgabe 1 (GREEN): sumOrNull korrigiert** - `2eb86e1` (fix) 3. **Aufgabe 2: ServerCard mit isAdmin und zweitem Hinweistext** - `2f8dd14` (fix) 4. **Aufgabe 3: Aktualisieren-Knopf nur fuer Admins** - `e1b191b` (fix) _Hinweis: Aufgabe 1 hatte planmaessig zwei Commits (RED/GREEN); Aufgaben 2 und 3 wurden je in einem Commit umgesetzt, wie im Plan vorgesehen (Tests zuerst rot gesehen, dann implementiert, ein Commit je Aufgabe)._ ## Files Created/Modified - `apps/api/src/proxmox/proxmox-normalize.ts` - `sumOrNull` liefert `null` bei fehlendem Teilwert statt Ersatz-durch-0 - `apps/api/src/proxmox/proxmox-normalize.spec.ts` - 6 neue Testfaelle fuer beide Richtungen (Spam/Viren), unlesbare Haelfte, Unabhaengigkeit der Paare - `apps/web/src/app/(portal)/modules/proxmox/components/ServerCard.tsx` - neue `isAdmin`-Eigenschaft (Vorgabe `false`), waehlt den Hinweistext fuer nie abgefragte Server - `apps/web/src/app/(portal)/modules/proxmox/components/ServerCard.test.tsx` - bestehenden Test auf `isAdmin` umgestellt, zwei neue Faelle (`isAdmin={false}`, weggelassen) - `apps/web/src/messages/de.json` / `en.json` - neuer Schluessel `proxmox.card.notPolledYetAutomatic` - `apps/web/src/app/(portal)/modules/proxmox/page.tsx` - Knopf nur bei `isAdmin`, reicht `isAdmin={isAdmin}` an `ServerCard` weiter - `apps/web/src/app/(portal)/modules/proxmox/proxmox-page-roles.test.tsx` (neu) - Seitentest mit 5 Faellen (USER, `user: null`, ADMIN, SUPER_ADMIN, leere Liste bei ADMIN) ## Decisions Made - Formulierung "Noch keine Abfrage gelaufen. Die Werte erscheinen nach der naechsten automatischen Abfrage." statt eines "in Kuerze"-Hinweises, weil das Poll-Intervall je Server zwischen 1 und 1440 Minuten liegen kann (`@Max(1440)`) — die gewaehlte Formulierung stimmt bei jedem Intervall und verweist auf keinen Knopf. - Keine weiteren Aenderungen an der Modulseite (Festlegung des Nutzers: kein Umbau, keine zusaetzlichen Details oder Statusfarben) — bestaetigt eingehalten. ## Deviations from Plan None - plan genau wie geschrieben ausgefuehrt. ## Issues Encountered None. ## Beobachtungen (nicht behoben, dem Nutzer zur Entscheidung vorgelegt) - **Inaktive Server:** Ein inaktiver, nie abgefragter Server (`isActive: false`) wird nicht automatisch abgefragt (`proxmox-scheduler.service.ts` fragt nur aktive Server ab). Der neue Nicht-Admin-Hinweistext "...erscheinen nach der naechsten automatischen Abfrage" trifft fuer diesen Randfall nicht ganz zu. Das ist ein vorbestehender Randfall — auch die Admin-Karte beachtet `isActive` heute nicht — und liegt ausserhalb dieses Auftrags (Festlegung: kein Umbau). Wird hier nur vermerkt, nicht behoben. ## Verifikation (alle gruen, wie im Plan verlangt) - `pnpm --filter api exec vitest run src/proxmox` - 82 Tests gruen (26 in `proxmox-normalize.spec.ts`, davon 6 neu) - `pnpm --filter web exec vitest run "src/app/(portal)/modules/proxmox" src/messages` - 32 Tests gruen - `pnpm --filter api type-check` und `pnpm --filter web type-check` - ohne Fehler - `biome lint` auf den 6 Plan-Dateien - ohne Befund - `biome check` auf der neuen Datei `proxmox-page-roles.test.tsx` - ohne Befund (nach `biome check --write` fuer Formatierung) - `biome check` auf den 5 vorbestehenden Dateien - weiterhin genau 6 Befunde (vorbestehende Formatierung + `organizeImports` in `page.tsx`), keine neuen Befunde — wie im Plan festgelegt nicht behoben (fremder Diff) - Keine Container-Neubauten, kein Deploy, keine Browserpruefung — wie im Plan vorgesehen ## User Setup Required None - keine externe Konfiguration noetig. ## Next Phase Readiness - Die offene Luecke (Wahrheit 7) aus `260923-dhh-VERIFICATION.md` ist geschlossen; das Proxmox-Modul hat keine bekannten offenen Abnahmebefunde mehr. - Offen beim Nutzer (keine Entscheidung noetig, nur zur Kenntnis): der oben vermerkte Randfall bei inaktiven, nie abgefragten Servern. ## Self-Check: PASSED Alle im Plan genannten Dateien wurden gefunden, alle vier Commits sind im Log nachweisbar. --- *Plan: 260923-le6* *Completed: 2026-09-23*