Der Client reichte jeden Download an den System-Browser weiter. Dateien,
die die Seite selbst erzeugt (blob:/data:, z. B. alle Downloads im
Zertifikat-Manager), kann der Browser nicht abrufen - Windows zeigte
nur "Holen Sie sich eine App, um diesen blob-Link zu oeffnen" (VM 8233).
Solche Downloads speichert die App jetzt selbst (Ordner Downloads) und
meldet Dateiname und Ordner; http/https-Downloads gehen weiter an den
Browser.
Dazu CHANGELOG und Quick-Doku zu 261001-l4q.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
hosteurope.de liefert im HTML nur einen leeren data:-Platzhalter, das
echte Symbol setzt erst JavaScript; /favicon.ico antwortet mit HTML. Die
Kachel zeigte deshalb nur den Buchstaben. Scheitert das gespeicherte
Symbol, fragt getIconBytes jetzt einmal den DuckDuckGo-Symboldienst -
nur fuer oeffentlich erreichbare Seiten, interne Hostnamen verlassen das
Haus nicht; kennt der Dienst nichts (404), bleibt es beim Buchstaben.
Wirkt auch fuer bestehende Favoriten.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Der Fokus auf das Titelfeld lag im selben Effekt wie der Escape-Listener
mit Abhaengigkeit onClose. Die Kachel uebergibt onClose inline und
zeichnet alle 10 s neu (NOW_TICK_MS) - der Effekt lief jedes Mal erneut
und holte den Cursor aus der Beschreibung zurueck in den Titel. Fokus
jetzt nur beim Oeffnen, Escape ueber eine Ref.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Im Desktop-Client unter Windows tat ein Klick auf Favoriten und andere
Links mit target=_blank nichts, waehrend window.open (Such-Widget) ueber
on_new_window im System-Browser landete (VM 8233 nachgestellt).
DesktopExternalLinks leitet im Client Links- und Mittelklicks auf solche
http/https-Links auf window.open um; von der Seite verhinderte Klicks
(Favoriten im Bearbeiten-Modus) bleiben verhindert.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Neue Felder loginHintDirectory/loginHintLocal (Platzhalter, Pflicht, max. 1000),
Migration 20260930170000 (nullable, leer = Standard aus @tessera/shared).
Knopf Passwort festlegen und Gueltigkeitshinweis bleiben fest; local-no-link
wird nie erzeugt und bleibt fest. Vorschau springt beim Bearbeiten auf die
passende Kontoart. Lokal im Browser nachgewiesen.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Administrator -> Willkommensmail: Betreff, Ueberschrift, Einleitung, Abschluss je
Mandant (Tabelle WelcomeMailTemplate, RLS je Mandant, Migration 20260930150000);
Platzhalter {{name}} {{vorname}} {{benutzername}} {{email}} {{adresse}} {{firma}},
unbekannte -> 400 bzw. Hinweis beim Tippen; Werte escaped, Vorlage reiner Text.
Live-Vorschau per API gerendert, Testmail an die eigene Adresse ohne Token,
Zuruecksetzen auf Standard. Feste Bausteine (Kopf, Zugangsdaten, Anmeldehinweis,
Knoepfe, Fusszeile) bleiben immer drin.
Kopf: Wellenzelle dunkel statt weiss, Streifen 600x40, Inhalt 24 px naeher –
keine weisse Luecke, wenn OWA das CID-Bild nicht zeigt.
Lokal nachgewiesen: Hinweis/Sperre bei {{xyz}}, Speichern, Testmail (Link nur
/login), echte Mail mit eigener Vorlage und 7-Tage-Link.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Nur bei gueltiger Signatur und ohne ausstehenden Kennwortwechsel; next ueber
sanitizeNextPath, /login als Ziel -> Dashboard. Gesperrte Konten: API lehnt
ab, Oberflaeche loescht das Cookie serverseitig, keine Schleife.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
POST /users/:id/welcome-mail (gleiche Rechte wie Bearbeiten, jederzeit sendbar),
GET /users/welcome-mail/status; HTML-Mail (Tabellenlayout, Inline-Stile,
Kopfbild als CID-PNG aus assets/mail/welcome-header.svg, erzeugt mit
scripts/render-mail-header.mjs) plus Textfassung. Verzeichniskonten: Hinweis
auf Windows-Passwort; lokale Konten: Link Passwort festlegen (7 Tage, einmalig).
Neue Spalte User.welcomeMailSentAt (Migration 20260930120000). Benutzerliste:
Spalte Letzte Anmeldung, Zeilenaktionen als Symbole. Dockerfile kopiert
apps/api/assets. Lokal per MailHog nachgewiesen.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
iframes liegen dauerhaft in einem Behaelter im Portal-Rahmen und werden per
position: fixed deckungsgleich ueber den Platzhalter der Modulseite gelegt;
beim Wegnavigieren nur versteckt (visibility), nie neu eingehaengt. Name/Adresse
je Modul im Sitzungsspeicher, Nachladen im Hintergrund, 404 verwirft. Abmelden
und Loeschen leeren. Im Browser nachgewiesen: gleiches iframe-Element und kein
neuer Seitenabruf nach Dashboard -> Modul B -> Modul A; folgt Seitenleiste
ein-/ausgeklappt und Handybreite.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Die Einpassung nimmt max(Leinwandhoehe, Rasterhoehe) (fitCanvasToContent).
Anlass: Dashboard des Nutzers 940 px hoch bei Leinwand 849 px, dadurch
scrollte es ueberall. Im Bearbeitungsmodus bleibt die Hoehe vom Beginn des
Bearbeitens stehen, damit der Massstab beim Ziehen nicht wandert.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Spaltenmindestbreite 76 -> 52 px (Abstand zwischen den Symbolen ~59 -> ~27 px
bei einer 373 px breiten Kachel). LauncherLabel misst den Titel einzeilig in
12 px; passt er nicht, 10 px, zweizeilig mit Silbentrennung und Auslassung.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Je Reiter wird die Flaeche des ersten Desktop-Bildschirms als __canvas im
Layout-JSON gespeichert (ohne API/DB-Aenderung, GRID_VERSION bleibt 3).
Das Raster rendert in Leinwandbreite und wird per transform: scale(min(bw/cw, bh/ch))
eingepasst, Schrift eingeschlossen, ohne Scrollen; unter 768 px wie bisher.
Ziehen/Groesse aendern unter Skalierung ueber eine eigene Positionsstrategie
(createScaledStrategy aus react-grid-layout 2.2.3 rechnet den Rasterversatz falsch).
Im Browser nachgewiesen: 1920x1080 -> 1366x768 (Faktor 0,66), Ziehen +200 px
folgt der Maus, 700 px ohne Skalierung.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- Layout mit neuerer Rasterversion wird nie gespeichert, Bearbeiten gesperrt mit Hinweis
- Kalender minW 11 (~260 px bei lg), Breiten je Breakpoint auf Spaltenzahl begrenzt
- optimistische Ruecksetzung nur, wenn noch der gesetzte Wert steht
- Titel-Schalter mit fester Beschriftung + aria-pressed
- Hintergrund-Dialog: Fokus rein/zurueck, Tab bleibt im Dialog
- Loeschen eines Bildes setzt eine darauf zeigende Hintergrund-Wahl zurueck
- Uebersetzungen und CHANGELOG
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- E-Mail-Planer: Anspruch vor dem Senden (genau eine Mail je Faelligkeit, hoechstens 3 Versuche), Systemlesen nur fuer die Kandidatenabfrage
- MailService.sendReminderEmail (Berliner Zeit, nur Text), GET /reminders/email-status, Haken im Formular mit Erklaerung
- Zugriffsklassifikation und Erlaubnisliste fuer forSystem nachgezogen, Aenderungsliste und Anwenderanleitung
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Name- und Hinweiszeile ueber dem Rahmen entfallen (Name steht schon in der
App-Leiste, Nutzerwunsch 29.09.); der Link wandert per Portal in
HEADER_ACTIONS_SLOT_ID. Ungenutzter Schluessel customModules.embedHint weg.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Der Tray-Eintrag installierte das beim letzten Check abgelegte Update. Die
Download-Adresse liefert aber immer den aktuellen Installer; nach einem
Server-Update passte die alte Signatur nicht zur neuen Datei ("signature
verification failed", danach Browser-Rueckfall; Nutzer 29.09.). Jetzt
prueft der Klick erst frisch (install_after) und installiert das Ergebnis.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Opt-out-Klasse field-plain fuer die Fluent-Unterkante; im Dunkelmodus
wirkte sie im Such-Widget wie eine weisse Linie (Nutzerwunsch 29.09.).
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
CUSTOM_MODULE_CATEGORIES = MODULE_CATEGORIES + custom-modules; API prueft
dagegen, das Formular bietet sie an. Die Seitenleiste zeigt die Gruppe wie
jede Kategorie nur mit Eintrag und stellt sie immer ans Ende. Nutzerwunsch
29.09.; ohne Migration (category ist Freitext mit IsIn-Pruefung).
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Die Zentrierung der belegten Spalten (Design Mosaik, Runde 3) liess
Widgets nach dem Bearbeiten springen, z. B. ein einzelnes Widget oben
links in die Seitenmitte (Nutzer, live 29.09.). Auf Wunsch ersatzlos
entfernt: Ansicht = Bearbeitungsraster. centeringOffset, breakpointFor
und die ungenutzte Prop onInsetChange entfallen.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Die Webansicht verwarf window.open und Links mit target=_blank still:
Suche-Widget und "In neuem Tab oeffnen" (XFrame, eigene Module,
Favoriten) taten im Client nichts. on_new_window reicht http/https-
Adressen an den System-Browser weiter und lehnt das neue Fenster ab;
andere Schemata werden verworfen (external_target, mit Test).
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Hover-Anheben samt Schatten ersatzlos entfernt (Wunsch des Nutzers:
Kacheln statisch, unabhaengig von Maus/Touch). Einblenden beim Laden
bleibt. CHANGELOG und Anwender-Anleitung angepasst.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- Neu-Eintrag in Alltagssprache
- Layout-Wächter der Modulordner kennt den Ordner custom als bewusste Ausnahme ohne Zugriffsschranke
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Neuer Schalter im Bearbeitungsmodus (neben dem Griff) setzt hideTitle in
der Widget-Konfiguration (setWidgetConfig im Dashboard-Store, optimistisch
mit Ruecksetzen); in der Ansicht entfaellt die Titelzeile per
data-hide-title, Aktionen der Titelzeile bleiben oben rechts. Kategorien der
Seitenleiste 14 px, Moduleintraege 13 px / 32 px hoch. Version 1.5.2.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
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>
- 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>
- 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>
docs/anleitung-anwender.md: neuer Absatz "Mehrere Dashboards (Reiter)" im
Dashboard-Abschnitt, Alltagssprache - mehrere Dashboards nebeneinander,
Ziehen legt den Standard fest, Anlegen/Umbenennen/Loeschen im
Bearbeitungsmodus, der letzte Reiter bleibt.
CHANGELOG.md: ein Stichpunkt unter "Unveroeffentlicht" > "Neu" - was der
Benutzer sieht, mit dem ausdruecklichen Hinweis, dass vorhandene Kacheln
unveraendert auf dem ersten Reiter liegen bleiben.
docs/mandantentrennung-zugriffsklassifikation.md: Endstand nach Task 2
nachgerechnet (nicht aus Task 1 abgeschrieben) - Bereich dashboard 24->28
gebunden (Task 2 bringt vier weitere `tenantPrisma.dashboard.`-Rohtreffer:
createDashboard/renameDashboard/deleteDashboard), Summe 193->197. Die
Begruendungsspalte des Paares dashboard.service.ts/dashboard nennt jetzt
auch Task 2 (withTenantTransaction fuer deleteDashboard/reorderDashboards,
Muster favorites.service.ts/reorder). Paarzahl (75) unveraendert - Task 2
fuegt keine neuen (Datei,Modell)-Paare hinzu, nur weitere Rohtreffer
bestehender Paare.
Alle Tore nachgemessen: api 1240 Tests in 77 Dateien gruen (>= 1202/77),
web 693 Tests in 82 Dateien gruen (>= 661), type-check 4/4, lint 5/5 mit
genau 53 Warnungen in web, `prisma migrate diff` weiterhin ohne Unterschied.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Abschnitt "Unveroeffentlicht" in "1.3.1 - 2026-09-23" umbenannt, neuer leerer
Abschnitt darueber. Enthalten: Bilder im Dateibereich, Modul-Kacheln nur fuer
berechtigte Benutzer, Raster misst seine Breite auch aus dem Leerzustand.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- eine Kachel ohne Bauteil (entfernter Typ oder gesperrtes Modul) zeigt
statt des rohen Typnamens den Satz `widgets.unavailable`, zentriert und
grau; Schluessel in de.json und en.json
- Entwicklerdoku: neuer Abschnitt "Eine Kachel zum Modul" im
Modul-Walkthrough — die drei verbliebenen Stellen und was eine Kachel
mit moduleSlug automatisch tut
- Changelog unter "Unveroeffentlicht - Geaendert"
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- Changelog unter Unveroeffentlicht -> Geaendert: Bilder liegen im
Dateibereich, vorhandene ziehen beim ersten Start automatisch um
- Betriebsanleitung Kap. 6: user-files nennt die Bilderrahmen-Bilder und
haelt fest, dass pg_dump allein sie nicht mehr enthaelt
- Todo fuer Stufe 2 (DROP data, storagePath NOT NULL) mit Vorbedingung,
Migrationsname und den Nacharbeiten an Spec und Klassifikation
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- Changelog: Stichpunkt direkt nach dem XFrame-Stichpunkt unter Unveroeffentlicht -> Neu
- Anwenderhandbuch: je ein Satz in der Widget-Tabellenzeile und im Absatz "Dashboard > Widgets"
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>