diff --git a/.planning/.continue-here.md b/.planning/.continue-here.md
index 39fc0c9..b80378a 100644
--- a/.planning/.continue-here.md
+++ b/.planning/.continue-here.md
@@ -4,151 +4,146 @@ phase: null
task: null
total_tasks: null
status: paused
-last_updated: 2026-09-22T14:15:00.000Z
+last_updated: 2026-09-23T13:15:42.473Z
---
-Kein laufender Meilenstein. Alle 18 Phasen sind abgeschlossen; seit der Freigabe
-1.2.0 laeuft die Arbeit als Quick-Tasks. **Version 1.3.0 wurde am 22.09.2026
-freigegeben** (Tag `v1.3.0` auf `d146234`, Abbilder `live` und `v1.3.0`,
-Gitea-Release mit `Tessera-Setup-1.3.0.exe` und `Tessera-1.3.0.AppImage`).
+Kein laufender Meilenstein; die Arbeit laeuft als Quick-Tasks. **Version 1.3.1 ist am
+23.09. freigegeben** (Tag `v1.3.1` auf `ad004b2`, Abbilder `live` + `v1.3.1`, Gitea-Release
+mit beiden Desktop-Paketen).
-`main == origin/main` auf `1315f37`, Arbeitsbaum sauber, CI gruen. Der lokale
-Docker-Stack laeuft mit genau diesem Stand (web, api, db).
+**14 Commits liegen lokal und sind NICHT gepusht.** Arbeitsbaum sauber. Der lokale Stack
+laeuft mit dem Proxmox-Stand (web, api, db neu gebaut).
-Unterbrochen wurde NICHT mitten in einer Aufgabe — alle acht Auftraege dieser
-Sitzung sind fertig, nachgewiesen und gepusht. Der naechste Auftrag (Proxmox)
-ist inhaltlich geklaert, wartet aber auf Zugangsdaten des Nutzers.
+Unterbrochen wurde NICHT mitten in einer Aufgabe: das Proxmox-Modul ist vollstaendig gebaut,
+geprueft und die drei Befunde aus dem Rundgang sind behoben. Offen ist EIN Befund aus der
+Abnahme (siehe Restarbeit) und der Push.
-Diese Sitzung (21.09. abends bis 22.09. nachmittags):
+Diese Sitzung (22.09. abends bis 23.09. nachmittags):
-- quick-260921-pi9 — Dashboard-Widget „Bilderrahmen" (Upload oder https-Adresse, Diashow, Grossansicht)
-- quick-260921-qd3 — Dashboard-Widget „XFrame" (Webseite als Rahmen, Sandbox ohne Top-Navigation)
-- quick-260922-frg — Tray-Update-Eintrag nennt den Grund einer fehlgeschlagenen Pruefung, Klick prueft erneut, Pruefung alle 4 h
-- fast `747a4d4` — Download-Knoepfe im Desktop-Client oeffnen den System-Browser (waren ohne Funktion)
-- quick-260922-ge2 — XFrame: Ausschnitt waehlen und einpassen, Zoom, „Nur anzeigen"
-- **Freigabe 1.3.0** — CHANGELOG abgeschlossen, `live` vorgezogen, Tag gepusht, drei CI-Laeufe gruen
-- quick-260922-hk4 — Bilderrahmen-Bilder in den Dateibereich `user-files` statt in die Datenbank, automatischer Umzug beim Start, Selbstheilung aus der alten Spalte
-- quick-260922-m1h — Widget-Typen an EINER Stelle, Katalog aus der Registry + Modulfilter, Kachel kennt ihr Modul
+- **quick-260922-vdk** — Dashboard-Raster misst seine Breite auch aus dem Leerzustand heraus.
+ Meldung kam aus dem **Linux-Client**; Ursache war ein `useEffect(..., [])`, das den
+ ResizeObserver nie anhaengte, wenn das Dashboard beim Einhaengen leer war. Breite blieb auf
+ dem Startwert 1200 -> rechts ein toter Streifen. Im echten AppImage gegengemessen.
+- **Platte aufgeraeumt** — 3,6 GB frei -> 66 GB. Nur Wegwerf-Sachen (Docker-Build-Cache 27,9 GB,
+ 58 verwaiste Image-Schichten 43,3 GB, verwaiste CI-Volumes).
+- **Freigabe 1.3.1** — CHANGELOG abgeschlossen, `live` vorgezogen, Tag gepusht.
+- **quick-260923-ad9** — Dashboard-Reiter: mehrere Dashboards je Benutzer, per Ziehen sortierbar,
+ der erste ist der Standard. Bestand wandert per Migration in den ersten Reiter.
+- **quick-260923-dhh** — Proxmox-Modul (PVE/PBS/PMG), nur beobachten, sieben Aufgaben.
+- **quick-260923-ku6** — drei Befunde aus dem Proxmox-Rundgang behoben.
-Jeder Punkt wurde im Browser (Playwright-MCP) gegen den lokalen Stack geprueft;
-die Pruefprotokolle stehen in den jeweiligen SUMMARY.md unter `.planning/quick/`.
+Jeder Punkt wurde im Browser bzw. im echten Client geprueft; die Protokolle stehen in den
+jeweiligen SUMMARY.md unter `.planning/quick/`.
-1. **Proxmox-Modul** (PVE, PBS, PMG) — **nur beobachten**, keine Eingriffe.
- Seite: Server anbinden, VMs/Container mit CPU, Arbeitsspeicher, Plattenplatz
- und Erreichbarkeit; bei PBS Sicherungslaeufe und Pruefstatus, bei PMG die
- Mail-Zahlen (zugestellt, gefiltert, blockiert, Quarantaene).
-2. **Proxmox-Kachel** — kompakte Fassung ueber den neuen Weg (drei Stellen,
- siehe unten). Vorschlag fuer den Inhalt steht in der Sitzung: Ampel je Server
- + drei Balken; PBS: Alter der letzten Sicherung, Pruefergebnis, freier Platz;
- PMG: Tageszahlen in einer Zeile. Idee fuer spaeter: eine Sammelkachel
- „Alles in Ordnung?" mit einer Zeile je Server.
+1. **Offener Befund der Abnahme (zuerst):** `sumOrNull` in
+ `apps/api/src/proxmox/proxmox-normalize.ts` liefert bei EINEM fehlenden Teilwert die halbe
+ Summe statt `null` — also einen stillen Falschwert genau dort, wo die Feldnamen am
+ schlechtesten belegt sind (PMG, Annahme A5). Ein Test fuer „nur eine Haelfte vorhanden“
+ fehlt bisher ganz.
+2. **Kleinbefund:** „Jetzt aktualisieren“ auf der Proxmox-Modulseite wird allen mit
+ Modulzugriff gezeigt; der Endpunkt verlangt aber ADMIN/SUPER_ADMIN. Bei anderen passiert
+ beim Klick nichts.
+3. **Push** (14 Commits) und CI abwarten.
+4. **Proxmox-Dashboard-Kachel** als eigener kleiner Auftrag ueber den Weg aus 260922-m1h
+ (`WIDGET_TYPES` + `WIDGET_MODULE_SLUGS` + `registerWidget`).
+5. **Freigabe 1.4.0**, sobald Reiter und Proxmox auf alpha bestaetigt sind (neue Funktionen,
+ also Minor, nicht Patch).
-- **Bilder auf die Festplatte, nicht in die Datenbank** — Grund ist die Sicherung
- (`pg_dump` von Hand; 30 Bilder à 5 MiB je Benutzer waeren 150 MB pro Benutzer
- im Abzug), nicht die Geschwindigkeit, und die Einheitlichkeit mit Avataren
- (`user-files/avatars`) und DKV-Exporten.
-- **Zweistufige Umstellung:** Spalte `data` bleibt vorerst stehen; `getBytes`
- stellt eine fehlende Datei daraus wieder her. DROP erst, wenn alpha UND live
- einmal mit dieser Version gelaufen sind — Todo liegt unter
- `.planning/todos/pending/2026-09-22-dashboard-image-data-spalte-entfernen.md`.
-- **Proxmox: nur beobachten**, Zugriff ueber die normale Modulfreigabe
- (Nutzeransage 22.09.).
-- **Kacheln gesperrter Module erscheinen gar nicht erst im Katalog**
- (Nutzeransage 22.09.) — so umgesetzt in m1h.
-- **Basic-Auth am Proxy vor alpha bleibt** (Nutzerentscheidung). Aus dem
- Firmennetz greift eine Ausnahme; von aussen 401, und der Client sagt das seit
- frg selbst. **Nicht erneut vorschlagen, das Thema ist entschieden.**
+- **Proxmox: nur beobachten.** Einzige nicht-lesende Anfrage ist die Ticket-Anmeldung; sie liegt
+ an genau einer Stelle und `proxmox-nur-lesen.spec.ts` zaehlt sie gegen eine benannte Konstante.
+- **Keine SSRF-Adresssperre** — Proxmox steht per Definition im internen Netz, eine Sperre wuerde
+ jede echte Adresse blockieren. Schutz ist, dass nur ein Administrator Adressen eintraegt.
+- **PMG nur Benutzer/Passwort** (Recherche A1, Forenbeleg). Faellt beim Test auf, wenn es doch
+ Token kann — dann nachruesten.
+- **Zertifikats-Ausnahme je Serverzeile**, niemals global.
+- **Dashboard-Reiter:** der erste Reiter ist der Standard; „als Favorit festlegen“ heisst nach
+ vorn ziehen. Kein zusaetzliches Kennzeichen.
+- **Dashboard-Raster:** belegter Platz bleibt gesperrt, nichts weicht aus. Nutzeransage 22.09.
+- **KEIN Umbau der Proxmox-Modulseite.** Der Nutzer hat den Wunsch nach mehr Detailgrad und
+ Statusfarben am 23.09. ausdruecklich zurueckgezogen („vergiss das letzte, was ich geschrieben
+ habe“). **Nicht von selbst wieder aufgreifen.**
-- Proxmox braucht Zugangsdaten und Serveradressen des Nutzers (API-Token, nur
- lesend, z. B. Rolle `PVEAuditor`). Der Nutzer legt sie morgen an. Planung und
- Modulskelett koennen vorher entstehen, die Anbindung nicht getestet werden.
+- Die Proxmox-Feldnamen bei PBS und PMG sind nicht aus erster Quelle belegt (A2/A3/A5). Nur der
+ Test des Nutzers auf alpha gegen echte Server klaert das. Die Auswertung ist deshalb nachsichtig
+ gebaut, und jede Feldnamenliste liegt als EINE benannte Konstante in `proxmox-normalize.ts`.
+- Live steht moeglicherweise noch auf 1.3.0: der Nutzer hat gezogen, bevor die `live`-Abbilder
+ fertig waren (Tag-Lauf war zuerst rot). Ein zweiter `pull` steht aus, unbestaetigt.
## Required Reading (in order)
-1. `.planning/quick/260922-m1h-dashboard-widgets-ein-modul-bringt-seine/260922-m1h-SUMMARY.md` — Abschnitt „So fuegt man kuenftig eine Modul-Kachel hinzu": drei Stellen statt sieben.
-2. `docs/anleitung-entwicklung.md` — Modul-Walkthrough (Backend + Frontend) und der neue Abschnitt „Eine Kachel zum Modul".
-3. `.planning/quick/260922-hk4-bilderrahmen-bilder-auf-die-festplatte/260922-hk4-SUMMARY.md` — Dateiablage, wenn das Proxmox-Modul jemals Dateien speichert.
-4. `.planning/STATE.md` — Abschnitte „Current Position" und die letzten Zeilen der Quick-Tabelle.
+1. `.planning/quick/260923-dhh-proxmox-modul-pve-pbs-und-pmg-anbinden-n/260923-dhh-VERIFICATION.md`
+ — der offene Befund steht dort mit Reproduktion.
+2. `.planning/quick/260923-dhh-.../260923-dhh-RESEARCH.md` — Annahmen-Log A1…A5, die einzige
+ Stelle, an der steht, was an der Proxmox-Anbindung belegt und was abgeleitet ist.
+3. `.planning/quick/260923-ku6-.../260923-ku6-SUMMARY.md` — die Merge-Regel des Verbindungstests
+ (Formular vs. gespeichert, Geheimnisfelder).
+4. `.planning/STATE.md` — Abschnitt „Current Position“ und die letzten Zeilen der Quick-Tabelle.
## Critical Anti-Patterns (do NOT repeat these)
-- [ANTI-PATTERN]: Planannahmen ueber den Bestand ungeprueft uebernehmen → m1h: der Plan
- behauptete, `apps/web` importiere `@tessera/shared` bereits; es gab KEINE
- Abhaengigkeit, und zwei Kommentare hielten das als Absicht fest. Der Executor
- hat vor der ersten Zeile Code nachgemessen (Bau, Produktions-Abbild, natives
- Type-Stripping unter `node:24-alpine`) statt der Annahme zu folgen.
- **Mitigation:** jede Plan-Behauptung ueber vorhandene Abhaengigkeiten oder
- Muster vor dem Umsetzen einmal am Code pruefen.
-- [ANTI-PATTERN]: Vorschau und Darstellung mit unterschiedlichen Layoutmassen →
- ge2: die Kachel nutzte eine andere Rahmenhoehe als die Vorschau, wodurch Seiten
- mit fensterhoehen-abhaengigem Layout (`vh`) an anderer Stelle lagen als
- ausgewaehlt. **Mitigation:** Auswahl und Darstellung immer gegen dieselben
- Masse rechnen.
-- [ANTI-PATTERN]: `position: fixed` in einer Dashboard-Kachel → pi9: die
- Grossansicht blieb auf die Kachelflaeche beschraenkt, weil `react-grid-item`
- eine CSS-`transform` traegt und damit zum Bezugsrahmen wird.
- **Mitigation:** Overlays aus einer Kachel per `createPortal` in `document.body`
- rendern (Muster: Kalender-Tooltip, jetzt auch `picture-frame-lightbox.tsx`).
-- [ANTI-PATTERN]: Playwright klickt in einem per `transform` skalierten iframe
- nicht → ge2. **Mitigation:** Klickpunkt umrechnen und per
- `elementFromPoint` + `mouse.click` pruefen; ist eine Werkzeuggrenze, kein Produktfehler.
+- [ANTI-PATTERN]: Im Desktop-Client gegen `getBoundingClientRect()`/`getComputedStyle()` messen →
+ 260922-vdk: die Werte blieben auf dem ALTEN Stand, obwohl `style.width` bereits richtig war.
+ WebKitGTK friert die Animationsuhr ein, wenn das Fenster im Hintergrund liegt, und die
+ `width`-Uebergangsanimation bleibt stehen. **Mitigation:** im Client gegen die GESETZTEN Werte
+ messen (`style.width`, `style.transform`) oder gegen die React-Eigenschaften aus dem Fiber.
+- [ANTI-PATTERN]: Ein Bestaetigungsfenster nur ueber `[role="dialog"]` suchen → der Loeschen-Dialog
+ der Reiter traegt `role="alertdialog"`; die Pruefung sah „es passiert nichts“, obwohl das Fenster
+ offen war. **Mitigation:** auf beide Rollen abfragen.
+- [ANTI-PATTERN]: Nach dem Tag sofort auf dem Server `pull` ausfuehren → eine Freigabe loest DREI
+ Pipelines aus; faellt der Tag-Lauf um (bei 1.3.1: ein flackernder Test mit 5-Sekunden-Grenze),
+ werden Abbild-Bau und Desktop-Pakete UEBERSPRUNGEN, und `pull` holt still den alten Stand.
+ **Mitigation:** erst pruefen, dass die Abbilder `live`/`beta` einen neuen Zeitstempel tragen,
+ dann ziehen. Todo zum flackernden Test liegt unter `.planning/todos/pending/`.
+- [ANTI-PATTERN]: Eine Vermutung ueber die Ursache aus einem Bildausschnitt ableiten → beim
+ Raster-Fehler fuehrte der erste Verdacht („eine Nachbarkachel blockiert“) in die Irre; erst das
+ volle Fenster und das Rueckrechnen der Spaltenbreite (51,5 px, letzte Spalte 13) haben die echte
+ Ursache gezeigt. **Mitigation:** bei Bildbefunden das GANZE Fenster anfordern, nicht den
+ Ausschnitt, und die Geometrie nachrechnen.
## Infrastructure State
-- **Lokaler Stack:** `docker compose` mit web, api, db laeuft auf dem Stand
- `1315f37` (`up -d --build` am 22.09. nachmittags). `up` allein baut NICHT neu.
- DB ohne Host-Port — Prisma vom Host ueber die Container-IP
+- **Lokaler Stack:** `docker compose` mit web, api, db, gebaut auf dem Proxmox-Stand.
+ `up` allein baut NICHT neu. DB ohne Host-Port — Prisma vom Host ueber die Container-IP
(`docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' tessera-ctl-db-1`,
`tessera:tessera_dev`).
-- **Testdaten lokal:** im Admin-Dashboard stehen ein Bilderrahmen (zwei Bilder)
- und ein XFrame auf `example.com` mit Ausschnitt. Harmlos, darf bleiben.
-- **alpha** (`alpha.tessera.ctl.de`) wurde am 22.09. auf `80a0d23` gezogen; die
- spaeteren Commits (hk4, m1h) sind dort noch nicht drauf. Basic-Auth am Proxy
- bleibt — von aussen 401, deshalb Messungen gegen alpha nur am Proxy vorbei
- (auf dem Testserver `docker compose exec api` gegen `localhost:3001` oder
- Host-Port 3000).
-- **Live** (`tessera.ctl.de`) laeuft noch auf 1.2.0; der Pull auf 1.3.0 steht beim
- Nutzer aus.
-- **Desktop-Client:** neuester CI-Stempel `5aa577a` (Lauf 405). Der Nutzer muss
- ihn einmal per Browser installieren, danach laeuft das Update ueber das Tray.
+- **Proxmox-Nachbau:** Node-Skript mit selbstsigniertem Zertifikat im Scratchpad
+ (`scratchpad/fake-proxmox.mjs`, Port 8006, aus dem api-Container ueber `172.21.0.1` erreichbar).
+ Laeuft noch; `/tmp` ueberlebt keinen Neustart, das Skript ist aber schnell neu gebaut.
+ Endpunkte: `/api2/json/cluster/resources`, `/status/datastore-usage`,
+ `/admin/datastore/{name}/snapshots`, `/statistics/mail`, `POST /access/ticket`.
+- **Lokale Testdaten (duerfen weg):** zwei Proxmox-Server in der DB („Nachbau PVE“ und
+ „Nachbau kaputth“, letzterer absichtlich unerreichbar), Proxmox im Marktplatz aktiviert,
+ im Admin-Dashboard ein Reiter „Dashboard“ mit 5 Kacheln.
+- **alpha** (`alpha.tessera.ctl.de`): Stand 1.3.1-Beta; Reiter und Proxmox fehlen dort noch,
+ weil nicht gepusht.
+- **Live** (`tessera.ctl.de`): 1.3.1 freigegeben; ob der Server sie wirklich zieht, ist offen.
-Die Sitzung war eine lange Kette kleiner, vollstaendig abgeschlossener Auftraege.
-Der rote Faden am Ende: Der Nutzer will als naechstes ein Proxmox-Modul, das
-zusaetzlich als Kachel auf dem Dashboard erscheint — und kuenftig sollen weitere
-Module dasselbe tun. Deshalb wurde zuerst das Fundament geraeumt (m1h), damit
-eine Modul-Kachel drei Handgriffe kostet statt sieben und Kacheln gesperrter
-Module automatisch verschwinden. Das Geruest dafuer (`WIDGET_MODULE_SLUGS`,
-serverseitiger Filter in `dashboard.service.ts`) ist vorhanden und noch leer;
-Proxmox waere der erste Eintrag.
-
-Fuer Proxmox selbst ist vorgemerkt: Serveradressen traegt nur ein Administrator
-ein (damit ist die Adresse eine bewusste Freigabe statt beliebiger Eingabe), fuer
-genau diese Adressen werden Zertifikatsfehler toleriert (Muster:
-`favorites/icon-discovery.service.ts`, undici-Dispatcher — Nodes globales `fetch`
-ignoriert ihn), Zugangsdaten verschluesselt per `CryptoService` (Muster
-`ldap-config.service.ts`), Abfrage im Hintergrund je Mandant nach dem Muster
-`dkv-scheduler.service.ts` (`onApplicationBootstrap`, nicht `onModuleInit`).
+Der rote Faden: erst ein gemeldeter Fehler aus dem Linux-Client (Kachel liess sich nicht ganz
+nach rechts ziehen), der sich als Breitenmessung entpuppte; dann Freigabe; dann zwei Wuensche des
+Nutzers nacheinander — Dashboard-Reiter und das Proxmox-Modul. Beim Proxmox-Modul ist die
+Besonderheit, dass hier KEIN echter Server steht: deshalb wurde ein Nachbau gebaut, die Auswertung
+bewusst nachsichtig ausgelegt und jede Feldnamenliste an genau eine Stelle gelegt, damit der
+Nutzer sie nach seinem Test auf alpha in einem Griff korrigieren kann.
-Start with: Proxmox-Modul planen (`/gsd-quick` mit eigenem Plan wie bei ge2/hk4) —
-Datenmodell fuer Serverzugaenge (Adresse, Typ `pve|pbs|pmg`, verschluesselter
-Token), Abfrage im Hintergrund je Mandant, Modulskelett nach
-`docs/anleitung-entwicklung.md`, Seite mit Serverliste und Auslastung. Die
-Kachel kommt danach als eigener kleiner Auftrag ueber den neuen Weg. Vorher beim
-Nutzer abholen: Serveradressen und die lesenden API-Token.
+Start with: den offenen Befund der Abnahme beheben — `sumOrNull` in
+`apps/api/src/proxmox/proxmox-normalize.ts` muss `null` liefern, sobald EIN Teilwert fehlt
+(heute `(a ?? 0) + (b ?? 0)`), plus ein Test fuer „nur eine Haelfte vorhanden“. Gleich mit
+erledigen: „Jetzt aktualisieren“ nur fuer ADMIN/SUPER_ADMIN anzeigen. Danach Tore laufen lassen,
+committen, die 14 Commits pushen und die CI abwarten.
diff --git a/.planning/HANDOFF.json b/.planning/HANDOFF.json
index 9bb01d1..607feb4 100644
--- a/.planning/HANDOFF.json
+++ b/.planning/HANDOFF.json
@@ -1,45 +1,49 @@
{
"version": "1.0",
- "timestamp": "2026-09-22T14:15:00.000Z",
+ "timestamp": "2026-09-23T13:15:42.473Z",
"phase": null,
- "phase_name": "kein laufender Meilenstein — Quick-Tasks nach der Freigabe 1.3.0",
+ "phase_name": "kein laufender Meilenstein — Quick-Tasks; zuletzt Proxmox-Modul",
"phase_dir": null,
"plan": null,
"task": null,
"total_tasks": null,
"status": "paused",
"completed_tasks": [
- {"id": 1, "name": "quick-260921-pi9 Bilderrahmen-Widget", "status": "done", "commit": "737974b,c080580,c3b4597,8bf3601"},
- {"id": 2, "name": "quick-260921-qd3 XFrame-Widget", "status": "done", "commit": "d63d9f5,20a9eb2"},
- {"id": 3, "name": "quick-260922-frg Tray-Update nennt den Grund, prueft alle 4 h", "status": "done", "commit": "d73aad1"},
- {"id": 4, "name": "fast Download-Knoepfe im Desktop-Client", "status": "done", "commit": "747a4d4"},
- {"id": 5, "name": "quick-260922-ge2 XFrame-Ausschnitt, Zoom, Nur anzeigen", "status": "done", "commit": "445b1d3,30fdd99,cf70a19"},
- {"id": 6, "name": "Freigabe 1.3.0", "status": "done", "commit": "d146234 (Tag v1.3.0)"},
- {"id": 7, "name": "quick-260922-hk4 Bilder in den Dateibereich statt in die Datenbank", "status": "done", "commit": "9039cea,8cbfb8b,82472ee"},
- {"id": 8, "name": "quick-260922-m1h Modul bringt seine Kachel selbst mit", "status": "done", "commit": "56c07c3,8be0725"}
+ {"id": 1, "name": "quick-260922-vdk Dashboard-Raster misst seine Breite auch aus dem Leerzustand", "status": "done", "commit": "d9f2af3,cf67c8a,39b1f74"},
+ {"id": 2, "name": "Freigabe 1.3.1 (CHANGELOG, live-Zweig, Tag v1.3.1, Gitea-Release, Desktop-Pakete)", "status": "done", "commit": "ad004b2 (Tag v1.3.1)"},
+ {"id": 3, "name": "Todo notiert: flackernder Test tenant-selector blockierte die Freigabe", "status": "done", "commit": "fcad460"},
+ {"id": 4, "name": "quick-260923-ad9 Dashboard-Reiter (mehrere Dashboards, Ziehen sortiert, erster ist Standard)", "status": "done", "commit": "9c51823,df7a5e7,d34f682,05feaa3,58ce88e,0094a60"},
+ {"id": 5, "name": "quick-260923-dhh Proxmox-Modul PVE/PBS/PMG, nur beobachten", "status": "done", "commit": "3a1bfd9,4f8a368,998aba9,fccaf8d,723cf68,06fcdc0,3091b04"},
+ {"id": 6, "name": "quick-260923-ku6 drei Befunde aus dem Proxmox-Rundgang behoben", "status": "done", "commit": "710034c,f1bb7f7,a9e0d5b"},
+ {"id": 7, "name": "Platte aufgeraeumt (Docker-Build-Cache, verwaiste Images, CI-Volumes)", "status": "done", "commit": null}
],
"remaining_tasks": [
- {"id": 9, "name": "Proxmox-Modul (PVE/PBS/PMG), nur beobachten — Plan schreiben und bauen", "status": "not_started"},
- {"id": 10, "name": "Proxmox-Kachel (kompakte Version) ueber den neuen Weg", "status": "not_started"}
+ {"id": 8, "name": "OFFENER BEFUND der Abnahme: sumOrNull in normalizePmg liefert bei EINEM fehlenden Teilwert die halbe Summe statt null (stiller Falschwert)", "status": "not_started"},
+ {"id": 9, "name": "Kleinbefund: 'Jetzt aktualisieren' wird allen mit Modulzugriff gezeigt, der Endpunkt verlangt aber ADMIN — Klick bleibt bei anderen wirkungslos", "status": "not_started"},
+ {"id": 10, "name": "Push (14 Commits liegen lokal) und CI abwarten", "status": "not_started"},
+ {"id": 11, "name": "Proxmox-Dashboard-Kachel als eigener Auftrag (Weg aus quick-260922-m1h)", "status": "not_started"},
+ {"id": 12, "name": "Freigabe 1.4.0, wenn Reiter und Proxmox auf alpha bestaetigt sind", "status": "not_started"}
],
"blockers": [
- {"description": "Proxmox braucht Zugangsdaten des Nutzers (API-Token, nur lesend) und die Server-Adressen", "type": "human_action", "workaround": "Nutzer legt sie morgen an; Planung und Geruest koennen vorher entstehen"}
+ {"description": "Proxmox-Feldnamen bei PBS und PMG sind nicht aus erster Quelle belegt (Annahmen A2/A3/A5) — nur der Test des Nutzers gegen echte Server klaert das", "type": "external", "workaround": "Auswertung ist nachsichtig gebaut: fehlendes/anders benanntes Feld -> 'unbekannt', nie Absturz. Feldnamenlisten liegen je als EINE benannte Konstante in proxmox-normalize.ts"},
+ {"description": "Der Nutzer prueft Proxmox selbst auf alpha gegen seine echten Server; hier gibt es keinen echten PVE/PBS/PMG", "type": "human_action", "workaround": "Lokal laeuft ein selbst gebauter Nachbau (HTTPS, selbstsigniert) im Scratchpad — siehe context_notes"}
],
"async_jobs": [],
"human_actions_pending": [
- {"action": "Live-Server auf 1.3.0 ziehen (docker compose -f docker-compose.prod.yml pull && up -d --force-recreate api web)", "context": "Version 1.3.0 ist freigegeben, Abbilder live/v1.3.0 liegen bereit", "blocking": false},
- {"action": "Neuen Desktop-Client einmal per Browser installieren", "context": "Danach laeuft das Update ueber das Tray-Symbol; Live hatte den Updater bis 1.2.0 nicht", "blocking": false},
- {"action": "Proxmox-API-Token (nur lesend, z. B. Rolle PVEAuditor) fuer PVE, PBS und PMG anlegen und die Server-Adressen bereithalten", "context": "Voraussetzung fuer das naechste Modul; der Nutzer macht das morgen", "blocking": true}
+ {"action": "Live-Server auf 1.3.1 ziehen und in der Seitenleiste 'v1.3.1 · Live' pruefen", "context": "Der Nutzer hat am 23.09. zu frueh gezogen (der Tag-Lauf war wegen eines flackernden Tests rot, die live-Abbilder entstanden erst um 07:37/07:38 nach dem Neustart). Er meldete danach '1.3.0' — ein zweiter pull steht aus, unbestaetigt.", "blocking": false},
+ {"action": "Nach dem Push: alpha ziehen und die Dashboard-Reiter ausprobieren", "context": "Reiter liegen seit 0094a60 in der Beta, CI war gruen. Datenbankaenderung laeuft beim API-Start automatisch mit.", "blocking": false},
+ {"action": "Proxmox auf alpha einrichten: Server anlegen (Adresse, Token oder Benutzer/Passwort), Zertifikats-Ausnahme setzen, 'Verbindung testen'", "context": "Erst dieser Test klaert die offenen Feldnamen-Annahmen. Nur-Lese-Rolle: PVE PVEAuditor; bei PBS und PMG die jeweils lesende Rolle.", "blocking": false}
],
"decisions": [
- {"decision": "Bilderrahmen-Bilder liegen im Dateibereich user-files, nicht als bytea in der Datenbank", "rationale": "Sicherung laeuft per pg_dump von Hand; 30 Bilder a 5 MiB je Benutzer waeren 150 MB pro Benutzer im Abzug. Geschwindigkeit war NICHT das Argument. Dazu Einheitlichkeit mit Avataren und DKV-Exporten.", "phase": null},
- {"decision": "Spalte data bleibt vorerst stehen, DROP erst nach nachgewiesenem Lauf auf alpha und live", "rationale": "Zweistufige Umstellung; getBytes stellt eine fehlende Datei aus data wieder her (alter pg_dump + leeres Volume).", "phase": null},
- {"decision": "Widget-Typen an EINER Stelle (packages/shared), Katalog filtert nach Modulzugriff", "rationale": "Vorarbeit fuer Proxmox und weitere Modul-Kacheln; vorher sieben Hartkodierungen je Kachel.", "phase": null},
- {"decision": "Proxmox zunaechst NUR beobachten, keine Eingriffe; Zugriff ueber die normale Modulfreigabe", "rationale": "Ausdrueckliche Ansage des Nutzers am 22.09.", "phase": null},
- {"decision": "Kacheln gesperrter Module erscheinen gar nicht erst im Katalog", "rationale": "Ausdrueckliche Ansage des Nutzers am 22.09.", "phase": null},
- {"decision": "Basic-Auth am Proxy vor alpha bleibt", "rationale": "Entscheidung des Nutzers; aus dem Firmennetz greift eine Ausnahme. Nicht mehr ansprechen.", "phase": null}
+ {"decision": "Proxmox: nur beobachten, keine Eingriffe — einzige nicht-lesende Anfrage ist die Ticket-Anmeldung, maschinell begrenzt durch proxmox-nur-lesen.spec.ts", "rationale": "Ausdrueckliche Nutzeransage 22./23.09.", "phase": null},
+ {"decision": "Keine SSRF-Adresssperre nach Vorbild isPublicHttpUrl", "rationale": "Proxmox steht per Definition im internen Netz — eine Sperre wuerde jede echte Adresse blockieren. Schutz ist stattdessen, dass nur ein Administrator Adressen eintraegt.", "phase": null},
+ {"decision": "PMG nur Benutzer/Passwort, kein API-Token", "rationale": "Recherche A1: PMG kennt offenbar keine Token (Forenbeleg, keine Primaerquelle). Faellt beim Test auf, wenn es doch geht — dann nachruesten.", "phase": null},
+ {"decision": "Zertifikats-Ausnahme je Serverzeile, niemals global", "rationale": "Muster LdapConfig.tlsRejectUnauthorized + undici-Dispatcher aus favorites/icon-discovery.service.ts", "phase": null},
+ {"decision": "Dashboard-Reiter: der ERSTE Reiter ist der Standard, 'als Favorit festlegen' = nach vorn ziehen; kein zusaetzliches Kennzeichen", "rationale": "Nutzer praezisierte sich selbst mit 'bzw.' — verschiebbare Reiter, erster ist Standard", "phase": null},
+ {"decision": "Dashboard-Raster: belegter Platz bleibt gesperrt, nichts weicht aus (preventCollision bleibt)", "rationale": "Ausdrueckliche Nutzeransage 22.09.: 'Da wo schon ein widget ist, soll keins hinkommen, nichts verschieben.'", "phase": null},
+ {"decision": "KEIN Umbau der Proxmox-Modulseite (Detailgrad/Statusfarben)", "rationale": "Der Nutzer hat den Wunsch am 23.09. ausdruecklich zurueckgezogen: 'vergiss das letzte, was ich geschrieben habe'. Nicht von selbst wieder aufgreifen.", "phase": null}
],
"uncommitted_files": [],
- "next_action": "Proxmox-Modul planen: Prisma-Modelle fuer Serverzugaenge (Adresse, Typ pve|pbs|pmg, Token verschluesselt per CryptoService), Poller je Mandant nach dem Muster dkv-scheduler (onApplicationBootstrap), Modul-Skelett nach docs/anleitung-entwicklung.md, danach die Kachel ueber den neuen Weg (WIDGET_TYPES + WIDGET_MODULE_SLUGS + registerWidget).",
- "context_notes": "Sitzung lief ueber 1,5 Tage: zwei neue Widgets, drei Desktop-Korrekturen, Freigabe 1.3.0, Speicherumstellung, Widget-Aufraeumen. Alles gepusht, main == origin/main auf 1315f37, Arbeitsbaum sauber, CI gruen. Der lokale Docker-Stack laeuft mit dem aktuellen Stand; Testfavoriten/Test-Widgets im Admin-Dashboard sind lokal stehen geblieben (harmlos). Naechster Schritt ist inhaltlich klar, haengt aber an den Zugangsdaten des Nutzers."
+ "next_action": "Den offenen Befund der Abnahme beheben: sumOrNull in apps/api/src/proxmox/proxmox-normalize.ts muss null liefern, sobald EIN Teilwert fehlt (heute: (a ?? 0) + (b ?? 0), also halbe Summe als vollstaendige Zahl). Test fuer 'nur eine Haelfte vorhanden' ergaenzen (fehlt heute in proxmox-normalize.spec.ts). Gleich mit erledigen: 'Jetzt aktualisieren' nur fuer ADMIN/SUPER_ADMIN anzeigen. Danach Tore laufen lassen, committen, pushen, CI abwarten.",
+ "context_notes": "Sitzung vom 22.09. abends bis 23.09. nachmittags. Reihenfolge: Raster-Breitenfehler (im ECHTEN Linux-Client nachgemessen, nicht im Browser) -> Platte aufgeraeumt (3,6 GB frei -> 66 GB) -> Freigabe 1.3.1 -> Dashboard-Reiter -> Proxmox-Modul. 14 Commits liegen lokal und sind NICHT gepusht. Lokale Umgebung: Container laufen mit dem Proxmox-Stand; im lokalen Dashboard des Admin liegt ein Reiter 'Dashboard' mit 5 Kacheln; in der lokalen DB stehen ZWEI Test-Proxmox-Server ('Nachbau PVE' auf https://172.21.0.1:8006 und 'Nachbau kaputth' auf Port 9999, letzterer absichtlich unerreichbar) und das Proxmox-Modul ist im Marktplatz aktiviert — alles Testdaten, duerfen weg. Der Proxmox-Nachbau (Node-Skript + selbstsigniertes Zertifikat) liegt im Scratchpad unter /tmp/claude-1000/-home-vicolab-projects-tessera-ctl/3048d06f-c57f-475e-a181-e61dc35ebe9a/scratchpad/fake-proxmox.mjs und laeuft dort noch; /tmp ueberlebt einen Neustart nicht, das Skript ist aber in 20 Zeilen neu gebaut (Endpunkte: /api2/json/cluster/resources, /status/datastore-usage, /admin/datastore/{name}/snapshots, /statistics/mail, POST /access/ticket)."
}