Der Knopf Bearbeiten belegte eine eigene Zeile ueber den Widgets. Die
Aktionen rendern jetzt per Portal in einen Einhaengepunkt rechts in der
Kopfzeile (HEADER_ACTIONS_SLOT_ID); in der Ansicht nur der Stift, im
Bearbeitungsmodus Hintergrund, Widget hinzufuegen und Fertig. Version 1.5.1.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- Nur Formatierung und Importreihenfolge, keine Verhaltensaenderung
- Betrifft ausschliesslich Befunde, die der Merge neu eingebracht hat
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- Spalte User.dashboardBackground (JSONB) samt Migration
- PATCH /users/me/dashboard-background, geprueft mit parseDashboardBackground aus @tessera/shared (Allowlist, UUID-Bildkennung)
- getMe liefert dashboardBackground normalisiert neben accentColor
- Web liest die Wahl aus dem Auth-Store, speichert ueber die Server-Aktion, alte localStorage-Wahl wird einmalig uebernommen
- Hinweistext: gilt auf jedem Geraet
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- PATCH me/dashboard-background: Allowlist, UUID-Bildkennung, Mandantenbindung
- getMe liefert dashboardBackground normalisiert
- Web: Uebernahme der alten localStorage-Wahl, Hook liest aus dem Auth-Store
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Rueckmeldung Runde 3: die Reiter in der Seitenleiste gefallen nicht -
zurueck auf den Stand vor 8532b63 (Umschalter in der Kopfzeile). Statt
dessen sitzt die Begruessung jetzt zweizeilig im sonst leeren unteren
Bereich der Seitenleiste ueber "Einklappen"; ueber den Kacheln bleibt nur
die Befehlsleiste rechts.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- Dashboard-Reiter stehen in der aufgeklappten Seitenleiste als Liste
unter "Dashboard" (Ziehen sortiert senkrecht, Umbenennen/Loeschen/Neu
im Bearbeitungsmodus); eingeklappt und auf dem Handy wie bisher in der
Kopfzeile. Die Kopfzeile zeigt sonst den Namen des Dashboards.
- Begruessung einzeilig auf Hoehe der Befehlsleiste.
- Kachel-Groesse: kollidiert die gezogene Groesse mit einem Nachbarn, wird
nur die freie Achse uebernommen - vorher verwarf react-grid-layout mit
preventCollision die ganze Aenderung, sobald die Maus eine Zeile nach
unten wackelte (Favoriten liessen sich deshalb oft nicht schmaler ziehen).
- Ansicht: belegte Spalten mittig, Begruessung/Befehlsleiste ruecken mit.
- Kalender: einzeilige Terminliste mit "Heute"/"Morgen" in Akzentfarbe,
Ort im Tooltip, Standardhoehe 16 statt 12.
- Hintergrund "Bluete" im Dunkelmodus weggelassen (Farbstufen), Ersatz Nebel.
- Kacheln: Symbol-Chip in der Akzentfarbe, leichtes Anheben beim Zeigen,
gestaffeltes Einblenden beim Laden (ohne bei reduzierter Bewegung).
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Begruessung nach Tageszeit mit Datum, Befehlsleiste oben rechts statt
schwebendem Knopf, einheitliche Kachel-Kopfzeilen mit Symbol, Kalender
mit Pfeilknoepfen, runden Tagen und Terminpunkten, Favoriten als
36-px-Zeilen bzw. App-Starter-Kacheln, Notiz-Kaestchen im Akzent,
leerer Zustand mit drei Vorschlaegen.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Statt bunter Modulfarben neutrale graue Kacheln; gelb (persoenliche
Akzentfarbe) nur fuer den gewaehlten Eintrag der Seitenleiste und den
Seitenkopf des Moduls. Schrift auf Akzentflaechen wird jetzt je nach
Akzentfarbe hell oder dunkel gewaehlt (readableOnAccent). Anmelde-
Mosaik und Dashboard-Hintergruende nur noch in Gelb, Grau, Graphit;
Salbei ersetzt durch Kiesel.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Einheitliche Seitenkoepfe mit Modul-Kachel, Knopf- und Linkklassen
statt gelber Schrift, Karten ohne harte Rahmen, Tabellenkoepfe ohne
Grossbuchstaben, Marktplatz mit Fluent-Reitern, Filterpillen und
Kachel-Karten, Einstellungs-/Verwaltungsnavigation mit Auswahlpille,
leere Zustaende mit Symbol im Kreis, Proxmox ohne leuchtende Schatten.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Einheitliche Kachel-Kopfzeile, ruhigere Notiz-/Kalender-/Favoriten-
Darstellung, 12 px Raster-Abstand, gestrichelte Kontur und Griff im
Bearbeitungsmodus. Neuer Knopf Hintergrund: Keiner, fuenf eingebaute
(Nebel, Salbei, Bluete, Duenen, Mosaik) oder eigenes Bild aus den
Bilderrahmen-Bildern; Prototyp speichert im localStorage je Benutzer.
Mit Hintergrund werden Kacheln Mica-artig durchscheinend (Kontrast
>= 4,5:1 auch im schlechtesten Fall).
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Ab lg links 45 % dunkles Panel (Ton der App-Leiste) mit Bildmarke,
Claim und stillem Mosaik aus den Modulfarben; rechts die Anmeldekarte
auf der Arbeitsflaeche. Darunter nur die Karte.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Kopfzeile 48 px dunkel mit Seitentitel statt immer Startseite,
Dashboard-Reiter mit Akzent-Unterstrich; Seitenleiste mit
Auswahlpille, Modul-Kacheln, aufgeklappten Kategorien und gefuelltem
Suchfeld; eingeklappt nur Kacheln. Einheitlicher PageHeader.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Jedes Modul bekommt Farbe und Symbol (tender-radar Ocker, dkv-fleet
Petrol, cert-manager Violett, domaincheck Blau, proxmox Rotorange,
unbekannte stabil per Hash). Kategorien in Alltagssprache; dazu die
Texte fuer die neue Anmeldeseite.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- CHANGELOG Unveroeffentlicht -> Neu
- Anwenderhandbuch: Fenster nach einem Versionswechsel
- Entwicklerdoku: erweiterte Importregel fuer @/lib/changelog, Versionsquelle,
Endpunkte, Spalte, Folge fuer die Freigabe
- Kopfkommentare changelog.ts und next.config.ts angepasst
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- UserService.create (Admin-Anlage, beide LDAP-Wege) und AdminSeedService
setzen lastSeenReleaseVersion = getRunningRelease(), null auf dev
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- release-notes.ts: reine Auswahl der Versionsabschnitte aus CHANGELOG.md
- release-notice-actions.ts ('use server'): Abruf und Merken ueber die API
- ReleaseNoticeDialog: barrierefreies Fenster, Eintraege ueber ChangelogView (variant plain)
- ReleaseNoticeHost in AppShell: einmal je Seitenladung, merkt erst beim Schliessen
- Texte releaseNotice in de.json und en.json
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- selectReleaseNotice: Bereich, Deckel 3, null, unparsebar, nur Neu/Geaendert/Behoben
- Server-Aktionen: Cookie, Antwortform, Fehler still
- Fenster: role=dialog, Fokusfalle, alle Schliesswege genau einmal
- Host: merkt erst beim Schliessen, nicht auf /change-password, StrictMode
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- packages/shared: parseReleaseVersion, compareReleaseVersions, ReleaseNoticeResponse
- getRunningRelease(): einzige Quelle der laufenden Version (APP_VERSION der API)
- User.lastSeenReleaseVersion (nullbar, Migration 20260925120000)
- GET /users/me/release-notice, POST /users/me/release-seen (gebunden an Benutzer und Mandant)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- parseReleaseVersion/compareReleaseVersions/getRunningRelease
- GET me/release-notice, POST me/release-seen: Format, nicht ueber laufend,
nie absenken, Mandanten- und Benutzerbindung, ReleaseSeenDto
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- Migration 20260924120000_dashboard_image_drop_data: Schutzpruefung
(bricht ab, solange eine Zeile ohne storagePath existiert; row_security
aus, damit ein Eigentuemer ohne BYPASSRLS nicht still 0 Zeilen sieht),
dann NOT NULL, DROP COLUMN data, DROP POLICY system_read_policy
- Dienst: Bootstrap-Umzug samt forSystem() und Selbstheilung aus data
entfernt; Upload vergibt die UUID selbst, Zeile gleich mit Pfad
- FORSYSTEM_ALLOWED_CALL_SITES, Tests, Zugriffsklassifikation (per
Gate-Schleife gemessen: 61/213/6) nachgezogen
- Betriebshandbuch Kap. 4: Hinweis und Wiederherstellungsweg bei Abbruch
- Todo 2026-09-22 nach completed/
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- tenant-selector: Komponenten statisch statt im Test dynamisch importiert
(Laden zaehlte in die 5-s-Frist des ersten Tests), SUPER_ADMIN/ADMIN in
zwei it aufgetrennt
- marketplace/marketplace-filters: gleiche Umstellung; userEvent an die
falsche Uhr gekoppelt statt auf shouldAdvanceTime zu warten
- proxmox-widget: Rendern wartet das erste Laden in act() ab (81 Warnungen weg)
- Todo 2026-09-23 nach completed/
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- ProxmoxServerPicker gemeinsam fuer Kachel und Einstellungsformular
- Bearbeitungsmodus: entprelltes Titelfeld, Server auswaehlen statt Liste, sofort gespeichert
- ProxmoxWidgetConfigForm unter Einstellungen > Dashboard, Titel-Zusatz in der Kopfzeile
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- Auswahl-Bauteil: Reihenfolge nach position, Produktwort, Aufraeumen geloeschter Kennungen
- Einstellungsformular: Laden, Fehler, Leer, onChange fuer Titel und Auswahl
- Einstellungsbereich: Zweig proxmox mit Titel-Zusatz in der Kopfzeile
- Kachel im Bearbeitungsmodus: entprellter Titel, Auswahl statt Liste, schliesst beim Verlassen
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- Zeilen nach down, warn, ok, idle, orphan mit genau einer Kennzahl, unbekannt statt 0
- config.serverIds filtert Liste und Balken, nur geloeschte Kennungen: eigener Satz
- Ansichtsmodus Links auf /modules/proxmox, Bearbeitungsmodus ohne Links
- Groessenstufen per Container-Query, Nachladen alle 60 s, pausiert bei verborgenem Tab
- formatPercent/formatCount einmal in components/proxmox, ServerCard nutzt sie
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- Typ proxmox am Ende von WIDGET_TYPES, WIDGET_MODULE_SLUGS = { proxmox: 'proxmox' }
- gemeinsame Statusteile (proxmox-status, HealthBar, status-styles) nach components/proxmox/
- HealthBar variant compact: 6 px, ohne Legende, aria-hidden
- Registry 3/4/8/8, Katalog-/Registry-/API-Tests auf die erste Modul-Kachel umgestellt
- ProxmoxWidget liest nur listServers, zeigt Lade-, Leer-, Fehlerzustand
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- Kopfzeile unter 640 px nur mit Bildmarke, damit die Dashboard-Reiter
lesbar bleiben (vorher war vom Reiter nur "Das" zu sehen)
- Proxmox-Karten strecken sich nicht mehr auf gleiche Zeilenhoehe
- PBS-Pruefstatus auf Deutsch ("Pruefung fehlgeschlagen"), Rohwert als title
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Gedaempfte muted-Schrift fiele auf 2,75:1 (hell) bzw. 3,0:1 (dunkel),
gemessen; Produktname, Adresse und Fussangabe bleiben deshalb voll lesbar.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- Kopfzeile bekommt Einhaengepunkt header-center-slot; auf / entfaellt der Text Startseite
- DashboardTabs rendert per createPortal dorthin, eigene Zeile ueber dem Raster entfaellt
- eingelassene Spur mit erhabenem aktivem Reiter, waagrecht scrollbar mit weicher Randausblendung
- role=tablist/tab, Pfeiltasten/Pos1/Ende, sichtbarer Fokusring, aktiver Reiter wird ins Bild gescrollt
- Plus-Knopf ausserhalb der Spur, Loeschdialog am Dokumentkoerper, Ziehhinweis als sr-only/Tooltip
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- Statusfarben als OKLCH-Tokens (Flaeche + kontrastgepruefte Textvariante) und Well-Token
- Gesundheitsbalken mit Legende und vorgelesener Zusammenfassung
- Karten nach Zustand sortiert, Statusleiste, getoenter Schatten, Statuspille
- Messwerte in eingelassenen Feldern: PVE-Knoten mit Balken, PBS-Fuellstand/Sicherung/Pruefung, PMG-Zahlfelder
- offline & verwaist: gestrichelt, gedaempft, keine alten Messwerte
- Skelett-Karten beim Laden, Leerzustand als Well, relative Zeitangaben
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- serverHealth mit Vorrang fuer offline & verwaist (isActive=false)
- THRESHOLDS als einzige Schwellenquelle, meterLevel fuer Balken
- Sortierung/Zusammenfassung je Zustand, formatAge ueber Intl.RelativeTimeFormat
- null erzeugt nie eine Warnung (24 Tests)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- FavoriteLink: neue Spalten uploadedIconMime/iconVersion (Migration 20260923160000)
- favorite-icon-files.ts: Erkennung PNG/JPEG/GIF/WebP/ICO/SVG, Pfadbildung ohne
Byte aus der Anfrage im Pfad (T-LRR-01), best-effort Dateientfernung
- FavoritesService: uploadIcon/removeUploadedIcon, Vorrang der hochgeladenen
Datei in getIconBytes, Abrufprobe fuer eine neue iconUrl (422 statt stiller
Speicherung), iconVersion-Erhoehung bei jeder Aenderung der Symbolquelle
- FavoritesController: POST/DELETE /favorites/:id/icon, Cache-Control private
- T-LRR-07 (Restrisiko aus dem Plan-Threat-Model geschlossen, ueber den Plan
hinaus): DashboardService.removeWidget/deleteDashboard raeumen jetzt die
Symboldateien der per Datenbank-Kaskade mitgeloeschten Favoriten auf
(best effort, nie blockierend)
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
html-to-image laedt jedes <img> per fetch nach; ein einziges Bild ohne CORS
(z. B. ein direkt von der Website geholtes Favoriten-Symbol) liess die ganze
Aufnahme scheitern, im Dialog blieb das Haekchen "Bildschirmfoto beifuegen"
gesperrt. Nicht ladbare Bilder werden jetzt zum transparenten Pixel; scheitert
die Aufnahme trotzdem, folgt ein zweiter Versuch ohne Bilder und Rahmen.
Im Linux-Client 1.3.1 nachgestellt und nach dem Fix gegengeprueft.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Bei kurzen Linknamen blieb rechts viel Leerraum; minW 3 -> 1. Der Titel
kuerzt mit Auslassungszeichen, das Symbol bleibt stehen.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Zwei weitere Nachbesserungen aus dem Rundgang zu 260923-dhh, beide in
ServerCard.tsx und deshalb in einem Commit:
Befund 2: ein frisch angelegter, noch nie abgefragter Server zeigte
faelschlich "Ein unerwarteter Fehler ist aufgetreten" — die leere
Zwischenlagerzeile aus createServer hat `reachable: false` und
`errorKind: null`, was bisher blind in die Fehler-Uebersetzung `unbekannt`
lief. Neuer ruhiger Zustand fuer `status.lastPolledAt === null`, der auf
"Jetzt aktualisieren" verweist; die bestehenden Fehlermeldungen (inkl.
`unbekannt` fuer echte unbekannte Fehler) bleiben fuer `lastPolledAt !== null`
unveraendert.
Befund 3: die Klasse `uppercase` sass auf der ganzen Statuszeile und faerbte
dadurch auch die Adresse gross ("PVE — HTTPS://..."). Jetzt nur noch auf dem
Produktkuerzel.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Nachbesserung aus dem Browser-Rundgang zu 260923-dhh (Befund 1): "Verbindung
testen" pruefte bislang immer den in der Datenbank gespeicherten Server, nicht
das ungespeicherte Formular. Eine im Formular abgeschaltete Zertifikatspruefung
oder ein neu eingetipptes Token-Geheimnis wurden dadurch beim Test ignoriert
und erst nach "Speichern" wirksam — eine Falle fuer genau den Ablauf, den
Nutzer instinktiv waehlen (eintippen, testen, dann erst speichern).
Neues `TestProxmoxServerDto` plus Merge-Baustein `resolveEffectiveTestServer`
in `ProxmoxService`: normale Felder folgen dem Formular (auch wenn absichtlich
geleert), Geheimnisfelder folgen der bestehenden "leer -> gespeicherten Wert
behalten"-Regel, weil `ServerForm` sie beim Laden nie aus der Datenbank
vorbefuellt. Neue Route `POST servers/test` (ohne `:id`) deckt die Neuanlage
ab, wo es noch keinen gespeicherten Server gibt. Der Testen-Knopf steht jetzt
immer zur Verfuegung, nicht mehr nur nach dem ersten Speichern.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- ServerCard.tsx: einzige Stelle, die einen Messwert in Text verwandelt
(formatMetric) — null wird ueberall "unbekannt", nie 0/NaN/leer;
verzweigt ueber productType auf PVE/PBS/PMG; PBS ohne Sicherung zeigt
"noch keine Sicherung" statt eines Fehlers; nicht erreichbarer Server
zeigt Klartext-Ursache plus Zeitpunkt der letzten erfolgreichen Messung
- page.tsx: "Jetzt aktualisieren" fragt alle Server neu ab und laedt die
Liste danach neu, waehrend des Laufs gesperrt; ruhiger Hinweis bei
leerer Liste mit Weg zu den Einstellungen; Link zu den Einstellungen
nur fuer Administratoren sichtbar (Anzeige, kein Zugriffsriegel)
- proxmox-api.ts: ProxmoxMetrics-Union (Pve/Pbs/Pmg) fuer typsichere
Verzweigung im Frontend
- umlaut-dictionary.ts: zwei weitere korrekte Woerter auf die
Positivliste (Messung, Prozessorlast)
Tore: web 708/708 (>=693), type-check 4/4, Biome apps/web 53 Warnungen
(unveraendert).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- proxmox.service.ts: updateServer (Muster LdapConfigService.updateConfig
- nicht gesendet laesst unveraendert, leer loescht, gefuellt
verschluesselt neu; PMG+Token auch beim Bearbeiten abgelehnt, geprueft
gegen den EFFEKTIVEN Stand nach Zusammenfuehren), deleteServer
- proxmox.controller.ts: PUT/DELETE servers/:id, beide zusaetzlich mit
scheduler.refreshTenant() nach dem Schreiben
- Frontend: proxmox-api.ts (updateServer/deleteServer/testServer),
settings/page.tsx (Rollenpruefung nur Anzeige, Serverliste,
Loeschen mit Rueckfrage), ServerForm.tsx (PMG bietet Token gar nicht
an, Geheimnisfelder nie vorbefuellt, Zertifikatspruefung-Schalter
Standard "pruefen", Verbindungstest mit Klartext-Fehlertext)
- umlaut-dictionary.ts: zwei neue, bereits korrekte Woerter
(bewusst/gemessene) auf die Positivliste des Regressions-Waechters
Tore: api 1311/1311 (>=1240), web 701/701 (>=693), type-check 4/4,
lint 5/5, Biome apps/web 53 Warnungen (unveraendert).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>