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)." }