Commit Graph

100 Commits

Author SHA1 Message Date
schalli af87c2c112 feat(dashboard): auf jedem Bildschirm dasselbe Bild – Leinwand je Reiter, massstaeblich skaliert
Tessera CI/CD / Lint & Type Check (push) Successful in 50s
Tessera CI/CD / Tests (push) Successful in 1m20s
Tessera CI/CD / Desktop-Pakete bauen (push) Successful in 18s
Tessera CI/CD / Build & Publish Images (push) Successful in 2m54s
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>
2026-09-30 11:19:27 +02:00
schalli bd73fa5e74 docs(proxmox): Lesezugang anlegen – API-Token fuer PVE/PBS, eigener Auditor-Benutzer fuer PMG
PMG kennt keine API-Token (Proxmox-Bugzilla 5849, offen); Schritt-fuer-Schritt
fuer Oberflaeche und Kommandozeile, Rolle an Benutzer UND Token.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-30 11:12:13 +02:00
schalli 12214a948e fix(dashboard): Rasterversion schuetzen, Kalender-Mindestbreite, Breiten je Breakpoint, Hintergrund
- 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>
2026-09-30 03:20:16 +02:00
schalli 6879c756f2 feat(260929-if2): Erinnerung zusaetzlich per E-Mail, Doku und Aenderungsliste
- 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>
2026-09-29 14:11:22 +02:00
schalli 709b41a007 feat(260929-if2): faellige Erinnerungen erledigen, spaeter erinnern, bearbeiten und loeschen
- API: Aendern (409 wenn faellig), Spaeter erinnern (409 wenn nicht faellig, setzt E-Mail-Spur zurueck), Loeschen; fremde Kennungen 404
- Kachel: faellige Zeilen hervorgehoben mit Erledigt und drei Spaeter-Optionen, kuenftige mit Bearbeiten und Loeschen
- Zeit-Hilfen (morgen zur gleichen Uhrzeit), Zugriffsklassifikation nachgemessen

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-29 14:11:22 +02:00
schalli 325c5ddbf2 feat(260929-if2): Erinnerungen anlegen und zur Faelligkeit benachrichtigen (Tracer)
- Reminder-Tabelle mit Zeilenschutz (Mandant+Benutzer, Systemlesen fuer den E-Mail-Planer), API reminders (Liste, Anlegen)
- Kachel "Erinnerungen", globaler Melder im Portalrahmen (Browser und Desktop, je Faelligkeit einmal)
- Desktop: Laufzeit-Berechtigung fuer Benachrichtigungen nur fuer die gespeicherte Server-Adresse
- Zugriffsklassifikation nachgemessen

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-29 14:11:22 +02:00
schalli 4ff9a239fd feat: Kategorie "Eigene Module" fuer selbst angelegte Eintraege
Tessera CI/CD / Lint & Type Check (push) Successful in 48s
Tessera CI/CD / Tests (push) Successful in 1m27s
Tessera CI/CD / Desktop-Pakete bauen (push) Successful in 19s
Tessera CI/CD / Build & Publish Images (push) Successful in 3m33s
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>
2026-09-29 11:24:56 +02:00
schalli 8f41bd26bd docs(260929-dzu): Eigene Module fuer jeden Benutzer im CHANGELOG und den Anleitungen
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-29 10:29:56 +02:00
schalli bc4c0119de fix(web): Widgets nicht mehr zur Mitte versetzen
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>
2026-09-29 10:13:03 +02:00
schalli c703d87a1c feat(260929-dzu): persoenliche eigene Module je Benutzer (API, Migration, Zeilenschutz)
- ownerUserId (NULL = gemeinsam, sonst persoenlich) mit Zeilenschutz nach Muster SearchProvider
- GET nur gemeinsame + eigene, fremde persoenliche Eintraege 404
- POST fuer jeden Benutzer, shared nur fuer Administratoren (403)
- PATCH/DELETE: persoenlich nur Besitzer, gemeinsam nur Administrator
- Zugriffsklassifikation nachgemessen: 61/223/6

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-29 10:09:08 +02:00
schalli acd3c7a05f style(web): Widgets heben sich beim Darueberfahren nicht mehr an
Tessera CI/CD / Lint & Type Check (push) Successful in 51s
Tessera CI/CD / Tests (push) Successful in 1m20s
Tessera CI/CD / Desktop-Pakete bauen (push) Successful in 18s
Tessera CI/CD / Build & Publish Images (push) Successful in 3m11s
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>
2026-09-29 09:34:45 +02:00
schalli b9d87be360 feat(api,web): eigene Module — Tabelle, API, Seitenleiste, Rahmen-Seite
- Tabelle CustomModule mit Zeilenschutz (tenant_isolation_policy), Migration 20260929120000
- API /custom-modules: Lesen für jeden Angemeldeten, Schreiben nur Administrator, nur https ohne Zugangsdaten
- Seitenleiste zeigt eigene Module unter ihrer Kategorie, Rahmen-Seite mit Sandbox und „In neuem Tab öffnen“
- MODULE_CATEGORIES als gemeinsame Liste, Zugriffsklassifikation nachgemessen fortgeschrieben

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-29 07:25:33 +02:00
schalli cb45d2663a docs(260928-ujj): CHANGELOG und Anleitungen fuer Design Mosaik
- Unveroeffentlicht: Hintergrundwahl (Neu), neues Aussehen (Geaendert), Resize-Fehler (Behoben)
- Anwender-Anleitung: App-Leiste, Seitenleiste, Anmeldeseite, Befehlsleiste, Hintergrund, Kalender
- Entwickler-Anleitung: User.dashboardBackground, PATCH /users/me/dashboard-background, parseDashboardBackground

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-28 22:18:51 +02:00
schalli 0aaa15240d feat(260928-ujj): Dashboard-Hintergrund pro Benutzer in der Datenbank
- 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>
2026-09-28 22:13:49 +02:00
schalli b3b7b5d5e5 docs(260925-bow): Was-ist-neu-Fenster in CHANGELOG, Anwender- und Entwicklerdoku
- 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>
2026-09-25 08:54:38 +02:00
schalli 4fa5aafc54 docs(260925-bow): RLS-Buchfuehrung nachgemessen (user 8/17/0, Summe 61/216/6)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-25 08:50:06 +02:00
schalli dd54ec5d42 feat(260924-m4n): Bilderrahmen Stufe 2 - alte Bildspalte data entfernt, storagePath Pflicht
- 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>
2026-09-24 16:09:36 +02:00
schalli 602a45c8b6 docs(260924-i8v): Proxmox-Kachel in Anwender- und Entwicklerdoku und im Changelog
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-24 13:33:48 +02:00
schalli 3d266418fc docs(quick-260923-lrr): Favoriten-Symbol hochladen, CHANGELOG, Zugriffsklassifikation nachgetragen
Tessera CI/CD / Lint & Type Check (push) Successful in 51s
Tessera CI/CD / Tests (push) Successful in 1m17s
Tessera CI/CD / Desktop-Pakete bauen (push) Successful in 18s
Tessera CI/CD / Build & Publish Images (push) Successful in 3m11s
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-23 16:20:29 +02:00
schalli 61f95c8c52 feat(260923-lrr): Web — versionierte Symbol-Adresse, Datei-Auswahl, Entfernen-Knopf
- favorites-api.ts: FavoriteRequestError (Grund iconUrlUnreachable/iconTooLarge/
  iconInvalidType/iconUploadFailed), uploadFavoriteIcon/removeFavoriteIcon,
  FAVORITE_ICON_MAX_BYTES, Felder uploadedIconMime/iconVersion
- favorites-widget.tsx: Proxy-Bild traegt ?v=<iconVersion> (Cache-Bust nach
  Aenderung), Remount-Key um iconVersion/uploadedIconMime erweitert, eigenes
  Symbol im Hinzufuegen- und Bearbeitungsformular waehlen, Entfernen-Knopf,
  Fehlermeldung (role=alert) im Formular, Platzhalter jetzt uebersetzbar
- de.json/en.json: neun neue Texte unter widgets.favorites
- CHANGELOG.md und Anwenderhandbuch ergaenzt

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-23 16:13:05 +02:00
schalli 7704372c3c feat(260923-lrr): API — Favoriten-Symbol hochladen, Vorrang, Versionszaehler, Abrufprobe
- 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>
2026-09-23 16:04:29 +02:00
schalli 3091b04673 docs(260923-dhh): Proxmox-Modul Aufgabe 7 - Dokumentation und Nachmessung aller Tore
- docs/anleitung-anwender.md: neuer Abschnitt "Proxmox" (Modulzahl vier
  auf fuenf korrigiert) — was das Modul zeigt, Server anlegen, NUR-LESE-
  Rolle je Produkt, PMG nur Benutzer/Passwort, Zertifikatspruefungs-
  Schalter, "Verbindung testen", "unbekannt", D-01 ausdruecklich
  festgehalten. Plan nannte "docs/anwenderhandbuch.md" (existiert nicht
  im Repo) — echter Dateiname ist docs/anleitung-anwender.md, dort
  angewendet (Rule 3, blockierender Pfadfehler)
- docs/anleitung-entwicklung.md: proxmox als Vorlage fuer ein Modul mit
  Fremdsystem-Zugaengen und Hintergrundabfrage verlinkt, undici-
  Dispatcher-Falle als Merksatz ergaenzt (war noch nicht dokumentiert)
- docs/mandantentrennung-zugriffsklassifikation.md: Bereichsuebersicht
  und Summenzeile fuer Aufgabe 5 nachgezogen (war nach Aufgabe 5 noch
  offen) — proxmox jetzt 0/11/1, Summe 61/208/7, mit der Gate-Schleife
  nachgemessen

Endstand aller Tore gegen die Ausgangswerte des Plans:
- api-Tests: 1311 (Ausgangswert 1240, Ziel >=1240)
- web-Tests: 708 (Ausgangswert 693, Ziel >=693)
- type-check: 4/4
- lint: 5/5
- Biome-Warnungen apps/web: 53 (Ausgangswert 53, exakt unveraendert)

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-23 14:48:39 +02:00
schalli fccaf8db0f feat(260923-dhh): Proxmox-Modul Aufgabe 4 - Hintergrundabfrage je Mandant, Verbindungstest
- proxmox-scheduler.service.ts: ein Cron-Auftrag je aktivem Mandant
  (proxmox-poll:<tenantId>), onApplicationBootstrap (nicht onModuleInit,
  Tender-Muster), Abfrageintervall = kleinstes pollIntervalMin der
  aktiven Server, ein fehlgeschlagener Server bricht die Tick-Schleife
  nicht ab, refreshTenant() zieht nach jedem Speichern sofort nach
- proxmox.service.ts: loadActiveServersForScheduler() als einziger
  forSystem()-Aufruf des Moduls (Erlaubnisliste in
  rls-access-inventory.spec.ts), testConnection() schreibt nicht ins
  Zwischenlager, pollServer() bekommt eine Zehn-Sekunden-Sperre (T-DHH-06)
- proxmox.controller.ts: POST servers/:id/test, create() zieht den
  Planer nach dem Anlegen sofort nach
- Zugriffsklassifikation: proxmoxServer wechselt auf system-gebunden
  (Startpfad des Planers), proxmoxServerStatus bleibt gebunden

Tore: api 1306/1306 (>=1240), type-check 4/4, rls-access-inventory
und rls-coverage gruen.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-23 14:34:11 +02:00
schalli 3a1bfd943e feat(260923-dhh): Proxmox-Modul Aufgabe 1 - PVE per Token, Ende-zu-Ende
- ProxmoxServer/ProxmoxServerStatus mit RLS (tenant_isolation_policy +
  system_read_policy auf ProxmoxServer fuer den kommenden Planer)
- proxmox-auth.ts (Token-Kopfzeilen PVE/PBS), proxmox-client.service.ts
  (proxmoxGet, ausschliesslich lesend, Dispatcher je Aufruf aus
  tlsRejectUnauthorized, nie global)
- proxmox.service.ts: Server anlegen (Geheimnis verschluesselt,
  select ohne Geheimnisfelder), Serverliste, PVE-Abfrage mit
  nachsichtiger Grundauswertung (Knoten/Gaeste)
- Controller/Modul/Seed nach Domaincheck-Vorbild, Kategorie
  "infrastructure", @UseModule('proxmox') + @Roles auf Schreibwegen
- Modulseite (duenne Liste) + proxmox-api.ts + Registrierung in
  MODULE_REGISTRY
- Zugriffsklassifikation nachgezogen (rls-access-inventory.spec.ts gruen)

Tore: api 1247/1247 (>=1240), web 693/693, type-check 4/4, lint 5/5,
Biome apps/web 53 Warnungen (unveraendert).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-23 10:17:33 +02:00
schalli 58ce88e29f docs(quick-260923-ad9): Anwenderhandbuch, Changelog und Nachmessung aller Tore - Task 5
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>
2026-09-23 08:21:05 +02:00
schalli 9c518238f5 feat(quick-260923-ad9): Datenmodell, Migration und Reiter-Grundlage - Task 1
Neues Modell Dashboard (D-01/D-02/D-09): position statt Standard-Feld,
kein Unique auf (userId, position) - Umsortieren schreibt spaeter alle
Positionen einer Transaktion neu. WidgetInstance/DashboardLayout haengen
jetzt am Reiter statt am Benutzer (DashboardLayout.dashboardId @unique
ersetzt userId @unique).

Migration 20260923120000_dashboard_tabs: Zeilenschutz mit Mandant- UND
Benutzerdimension (Form 20260911120000/20260921120000), Bestands-
uebernahme fuer jeden Benutzer mit Kacheln oder Anordnung VOR den
Fremdschluesseln (D-03) - gemessen: 0 Kacheln/Anordnungen ohne Reiter,
genau 2 Reiter auf Position 0.

dashboard.service.ts: listDashboards() (Transaktionssperre gegen
doppelte Erstanlage, T-AD9-07), Riegel assertOwnedDashboard() (fail-
closed gegen fremde Reiter, T-AD9-01/02/03) - getLayout/saveLayout/
getWidgets/addWidget laufen jetzt ueber dashboardId statt userId.
GET /dashboard/tabs neu; die vier bestehenden Wege reichen die Reiter-
Kennung durch. Verhalten fuer den Benutzer unveraendert (ein Reiter,
wie bisher) - Task 2 ergaenzt Anlegen/Umbenennen/Loeschen/Umsortieren.

dashboard.service.spec.ts: 43 Tests (31 alte unveraendert + 12 neue fuer
Reiter-Anlage, -Reihenfolge und den Fremdreiter-Riegel bei allen vier
Wegen). Zugriffsklassifikation nachgerechnet: 75 Paare (+1), Bereich
dashboard 21->24 gebunden.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-23 07:56:38 +02:00
schalli 8be0725577 docs(quick-260922-m1h): Hinweis bei gesperrter Kachel, Changelog und Entwicklerdoku
- 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>
2026-09-22 16:06:25 +02:00
schalli 8cbfb8b69d docs(quick-260922-hk4): Changelog, Betriebsanleitung und Todo zur data-Spalte
- 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>
2026-09-22 15:25:31 +02:00
schalli 9039cea686 refactor(quick-260922-hk4): Bilderrahmen-Bilder in user-files statt in der Datenbank
- Bytes liegen unter user-files/dashboard-images/<userId>/<id>.<ext>, die
  Zeile haelt nur noch storagePath (Muster User.avatarPath)
- Dateiname immer servergeneriert: UUID der Zeile + Endung aus dem
  ERKANNTEN Mime-Typ, originalName kommt in keinem Pfad vor (T-HK4-01)
- Migration 20260922120000: storagePath dazu, data wird NULLbar, kein DROP
  (zweistufig, T-HK4-03); system_read_policy fuer den Umzug
- onApplicationBootstrap zieht Altbestand automatisch um: systemgebunden
  lesen, je Zeile mandantengebunden schreiben (Muster DKV-Planer)
- Upload nimmt die Zeile bei fehlgeschlagenem Schreiben zurueck, Loeschen
  entfernt die Datei mit, fehlende Datei -> 404 (T-HK4-04)
- 11 neue Dienst-Tests gegen ein echtes Temp-Verzeichnis (kein fs-Mock)
- Zugriffsklassifikation: Stand system-gebunden, Zahlen nachgemessen

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-22 15:22:47 +02:00
schalli 30fdd99724 docs(quick-260922-ge2): Changelog und Anwenderhandbuch - XFrame-Ausschnitt, Zoom, Nur anzeigen
- 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>
2026-09-22 12:13:42 +02:00
schalli 20a9eb2c8c docs(quick-260921-qd3): Changelog und Anwenderhandbuch - XFrame-Widget
- CHANGELOG: Stichpunkt als erster unter "Unveroeffentlicht -> Neu"
- Anwenderhandbuch: Zeile in der Widget-Tabelle, erweiterter Satz zu den
  Widget-Einstellungen, Absatz-Zusatz unter "Dashboard > Widgets"

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-21 19:20:28 +02:00
schalli c3b45974f5 docs(quick-260921-pi9): Changelog und Anwenderhandbuch - Bilderrahmen-Widget
- CHANGELOG.md: erster Stichpunkt unter Unveroeffentlicht -> Neu
- docs/anleitung-anwender.md: Zeile in der Widget-Tabelle, Absatz zur
  Bildverwaltung unter Dashboard > Widgets
- umlaut-dictionary.ts: „Webadresse“ und „Bildausschnitt“ als korrektes
  Deutsch auf die Erlaubnisliste des Umlaut-Waechters (der volle Web-Testlauf
  hatte die beiden neuen ss-Woerter aus de.json gemeldet)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-21 18:59:06 +02:00
schalli 737974b653 feat(quick-260921-pi9): Bilderrahmen-API - Bilder je Benutzer in der Datenbank, Magic-Byte-Pruefung, 5 MiB / 30 Stueck
- Prisma-Modell DashboardImage (bytea) mit Migration 20260921120000: Tabelle,
  Indizes, RLS ENABLE/FORCE und tenant_isolation_policy mit Benutzerdimension
- dashboard-image-rules.ts: detectImageMime ueber Magic Bytes (PNG/JPEG/GIF/
  WebP), Grenzen 5 MiB je Datei und 30 je Benutzer
- DashboardImagesService: list/upload/getBytes/remove, je Methode
  forTenant(prisma, tenantId, userId); Besitz = Mandant UND Benutzer, sonst 404
- DashboardImagesController unter dashboard/images: GET, POST (FileInterceptor
  image, 5 MiB, eine Datei), GET :id mit Content-Type aus dem erkannten Typ,
  Cache-Control private, nosniff, Content-Disposition inline ohne Dateinamen,
  CSP sandbox; DELETE :id
- CreateWidgetDto kennt 'picture-frame'
- Klassifikationsdokument: neues Paar dashboard-images.service.ts/
  dashboardImage; Bereichs- und Summenzeilen nachgemessen (dashboard 12->18,
  settings 3->4 und bug-reports waren in der Summe nie mitgezaehlt)
- Befund: Prisma-Bytes verlangt Uint8Array<ArrayBuffer>, multers Buffer wird
  ohne Zusicherung abgelehnt - Kopie per new Uint8Array(buffer) statt Cast

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-21 18:47:07 +02:00
schalli 97a6836444 docs(quick-260921-bi2): Entwickleranleitung auf Endstand 465/386/79 gebracht
Der Lint-Abschnitt trug noch den Zwischenstand aus Aufgabe 1 (754/633/121).
Jetzt der tatsaechliche Endstand nach allen drei Aufgaben, beide Ausnahmen
weiterhin begruendet, plus die namentlich benannten Folgeaufgaben: fuenf
zurueckgestellte a11y-Regeln, die bewusst nicht angewendete
noUselessSwitchCase-Fundstelle, und die vier gemeldeten D-03-Symptomfunde.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TPPB4ApQxzSU1rwV2Ffj9J
2026-09-21 09:43:40 +02:00
schalli 8d1c8f320b chore(quick-260921-bi2): Lint-Konfiguration bereinigen, Messgrundlage herstellen
- overrides fuer Testdateien (noExplicitAny off) und apps/api (useImportType off, siehe
  Regelbeschreibung "Caveat with TypeScript experimental decorators")
- Fixture-Ausnahme in files.includes ohne angehaengten Doppelstern (Biome-Hinweis
  useBiomeIgnoreFolder befolgt)
- Entwickleranleitung auf den neuen Stand gebracht: 754 Befunde (633 echt, 121 Test), beide
  Ausnahmen begruendet, Folgeaufgaben benannt

Rueckstand: 2923 -> 754, Fehlerstufe weiterhin 0. security-Regelgruppe unangetastet.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TPPB4ApQxzSU1rwV2Ffj9J
2026-09-21 08:46:06 +02:00
schalli 6f0f05aa00 docs(tooling): Entwickler-Anleitung um echten Lint-Umfang und Warnungs-Rueckstand ergaenzt
- pnpm lint prueft seit #35 echt (biome lint . je Workspace), CI-Schritt Lint blockiert entsprechend
- Fehler stoppen den Lauf, Stilhinweise laufen als Warnungen mit (rund 2800 offen: any-Familie, Barrierefreiheit apps/web) — bewusst eigener Durchlauf, nicht Teil dieses Vorgangs
- Klargestellt: pnpm lint formatiert nicht, dafuer separat biome format --write von Hand

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TPPB4ApQxzSU1rwV2Ffj9J
2026-09-21 07:07:11 +02:00
schalli e2a79467df docs: Fehlermeldungen — Herkunft (Browser/Desktop-App, Betriebssystem, Version) und Betreff-Kürzel (Handbücher, CHANGELOG)
Damit Betreiber im Postfach sofort erkennen, ob eine Meldung aus einem
Browser oder der Desktop-App kommt (und mit welchem Stand), beschreiben
Administrationshandbuch und Betriebshandbuch das neue Betreff-Kürzel und
die Zeile "Herkunft"; das Betriebshandbuch erklaert zusaetzlich den Fall
eines alten Desktop-Clients ohne Details.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016g2npLxzH5gZpg8s2S6vKh
2026-09-18 12:37:07 +02:00
schalli 7479cb485f docs: Desktop-App — Update in der App (Handbücher, CI-Secrets, CHANGELOG)
Tessera CI/CD / Lint & Type Check (push) Successful in 48s
Tessera CI/CD / Tests (push) Successful in 1m8s
Tessera CI/CD / Desktop-Pakete bauen (push) Successful in 7m56s
Tessera CI/CD / Build & Publish Images (push) Successful in 3m12s
- Anwenderhandbuch: Menüeintrag "Update installieren", Ablauf per Klick
  unter Windows/Linux, Fehlerfall, https-Bedingung, einmaliger Wechsel für
  Clients bis 1.2.0
- Betriebshandbuch Kap. 10: Signierschlüssel (Secrets, Ablage, Sicherung,
  Verlust), Kontrollzeile /desktop/update, Manifest-Felder, zwei Fehlerbilder
- Entwicklungshandbuch: lokal `tauri build --no-sign`, Hinweise zu tauri dev
- ci-cd-setup.md: die zwei neuen Secrets, Bau-Schritte signieren,
  Fehlerbild "no private key"
- CHANGELOG: eine Zeile unter Unveröffentlicht → Neu

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-17 15:36:58 +02:00
schalli 4d485432c0 docs: Desktop-App — Server-Adresse sehen und ändern (Handbuch, CHANGELOG)
- Neuer Unterabschnitt „Server-Adresse ändern" vor „Automatischer Start": wo die Adresse steht (Hinweistext, Menüzeile, Einstellungen → Desktop-App) und wie sie geändert wird (Rechtsklick → „Server-Adresse ändern…" → Setup-Seite → „Verbinden"/„Abbrechen")
- Tray-Liste ergänzt um „Verbunden mit …" (erste Zeile) und „Server-Adresse ändern…"; Hinweis auf den Tooltip nach der Liste; Erststart-Absatz verlinkt den neuen Unterabschnitt
- CHANGELOG.md: zwei Desktop-App-Stichpunkte unter Unveröffentlicht / Neu angehängt, fremde Zeilen unverändert (per git diff gegengeprüft)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-17 14:53:26 +02:00
schalli b023d6f726 docs: Favoriten-Sortierung und Symbol-Ersatzweg im CHANGELOG und Anwenderhandbuch; Nachtraege zur Mandantenbindung
- CHANGELOG.md: je ein Stichpunkt unter Neu (Sortierpfeile) und Behoben
  (Symbol trotz Zertifikatsfehler/interner Adresse)
- docs/anleitung-anwender.md: Tabellenzeile „Favoriten" nennt die Pfeile
  und den Browser-Ersatzweg fuer das Symbol
- docs/mandantentrennung-zugriffsklassifikation.md: Nachtrag zu
  favoriteLink — reorder() laeuft ueber withTenantTransaction() ohne
  Benutzerdimension in der Sitzung, Stand bleibt gebunden
- prisma-tenant.extension.ts: Kopfkommentar-Nachtrag, favorites.service.ts
  (reorder) ist der erste Nutzer-CRUD-Aufrufer von withTenantTransaction()
  — nur Kommentartext, Funktionscode unveraendert (prisma-tenant.extension.spec.ts
  und rls-access-inventory.spec.ts weiterhin gruen)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-17 14:41:28 +02:00
schalli e7633e15de docs: CI-Desktop-Bau nur bei geaendertem Desktop-Stand — Betriebshandbuch, CI-Runbook, Entwicklungsanleitung, CHANGELOG
- anleitung-betrieb.md Kap. 10: neuer Unterabschnitt "Wann gebaut wird und
  wann Pakete uebernommen werden", Job-Dauer-Satz und Fehlerbilder-Tabelle
  ergaenzt
- ci-cd-setup.md Abschnitt 4: Absatz zum Ueberspringen bei unveraendertem
  Desktop; Abschnitt 6: neuer Fehlerbehebungs-Eintrag
- anleitung-entwicklung.md: Absatz zum CI-Ueberspringen bei "Desktop-App
  lokal bauen"
- CHANGELOG.md: ein Stichpunkt unter Unveroeffentlicht/Geaendert

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-17 14:28:54 +02:00
schalli 507556f158 fix(ci): Release-Anhaenge nie ueber die oeffentliche Gitea-Adresse hochladen
Tessera CI/CD / Lint & Type Check (push) Successful in 49s
Tessera CI/CD / Tests (push) Successful in 1m8s
Tessera CI/CD / Desktop-Pakete bauen (push) Successful in 4m57s
Tessera CI/CD / Build & Publish Images (push) Successful in 3m9s
publish-release.sh ignoriert GITHUB_API_URL/GITHUB_SERVER_URL (git.vicolab.de
hinter dem Proxy bricht grosse Uploads ab -- Release 1.2.0 blieb dadurch
zunaechst ohne Anhaenge). Im CI wird das Host-Gateway des Job-Containers aus
/proc/net/route ermittelt und Gitea direkt auf Port 3002 angesprochen, lokal
localhost:3002; GITEA_API bleibt als Override. Gateway-Weg aus Job-Netz
gegen die Gitea-API verifiziert; Anhaenge fuer v1.2.0 vom Host nachgetragen.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-17 13:48:17 +02:00
schalli 2cd4adc85b feat(desktop): Windows-Installer auf Deutsch mit Tessera-Grafik und -Symbol; CHANGELOG, Handbuch
- bundle.windows.nsis in tauri.conf.json: Deutsch ohne Sprachauswahl,
  Tessera-Icon, Kopf-/Seitenbild, currentUser (kein Admin noetig)
- icons/nsis-header.bmp (150x57), icons/nsis-sidebar.bmp (164x314) ergaenzt
- CHANGELOG: vier neue Desktop-App-Stichpunkte (Beta-Hinweis, Installer,
  Download-Links, Kontextmenue)
- anleitung-anwender.md: Installationsassistent-Satz, Tray-Eintrag erklaert
- anleitung-entwicklung.md: Ort der nsis-Konfiguration, Pruefweg per CI
- Schema-Pruefung (node) und cargo check gruen

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-17 12:39:25 +02:00
schalli b6d90136d1 fix(desktop): Hauptfenster startet mit setup.html statt fehlender index.html; Rust-Bau in der Pipeline auf 4 Prozesse begrenzt
Bedienprobe des Users: Installer und Start liefen, dann schwarzes Fenster
"asset not found: index.html". Das Fenster "main" hatte keine Startseite,
Tauri nimmt dann index.html; die Erststart-Seite heisst setup.html (Altlast
aus Phase 6, in keinem echten Paket sichtbar geworden). CARGO_BUILD_JOBS=4,
weil 8 parallele rustc-Prozesse den gemeinsam genutzten Runner-Host (15 GB)
an die Speichergrenze brachten; Betriebshandbuch Kap. 10 ergaenzt.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-17 09:19:19 +02:00
schalli 8f2069b845 docs(18-06): Betriebshandbuch Kapitel 10, CI/CD-Runbook Job desktop, Entwicklungshandbuch
- Betriebshandbuch: neues Kapitel 10 (Pipeline-Herkunft, Ablageort im Abbild,
  Release-Anhaenge, DESKTOP_DIST_DIR, Fehlerbilder-Tabelle); Kapitel 9 um
  Satz zu Desktop-Paketen im Freigabe-Tag ergaenzt
- CI/CD-Runbook: aus drei werden vier Jobs, Job desktop ausfuehrlich
  beschrieben (Cross-Bau, Cache-Reihenfolge, Cache-vs-upload-artifact-
  Begruendung), Fehlerbehebung um drei Unterabschnitte ergaenzt
  (Job desktop, cache miss, Release-Upload 413)
- Entwicklungshandbuch: apps/desktop ist kein Grundgeruest mehr, neuer
  Abschnitt "Desktop-App lokal bauen", Testabschnitt um vitest src/desktop
  und cargo check/clippy ergaenzt

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-16 17:22:49 +02:00
schalli 43c7061cb3 docs(18-06): Anwenderhandbuch Kapitel Desktop-App, CHANGELOG-Stichpunkt
- Neues Kapitel "Desktop-App" (9 Unterabschnitte: Was es ist, Herunterladen,
  Installation Windows/Linux, Erster Start, Infobereich/Beenden, Automatischer
  Start, Neue Version, Fehlerbilder), Inhaltsverzeichnis um Punkt 8 ergaenzt
- CHANGELOG-Stichpunkt unter Unveroeffentlicht/Neu im Wortlaut von D-17

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-16 17:20:20 +02:00
schalli 39ea1474a5 feat: Link-Widget restlos entfernt (Web, API, Migration, Handbuch, Changelog)
- Web: Union-Mitglied, Constraints, Icon, Registry-Eintrag, wire-Funktion,
  Katalog, Seiten-Verdrahtung, Tests und i18n (de/en) fuer den Typ link
  entfernt; link-widget.tsx/.test.tsx geloescht
- API: create-widget.dto.ts (@IsIn-Liste) und widget-module-map.ts
  (Kommentare) auf sieben Typen angepasst; schema.prisma unveraendert
- Neue Migration 20260916120000_remove_link_widget: eine idempotente
  DELETE-Anweisung auf WidgetInstance, FavoriteLink kaskadiert ueber den
  bestehenden FK; wird in diesem Auftrag NICHT ausgefuehrt
- Neuer widget-wrapper-Test belegt den grauen Fallback fuer unbekannte
  Widget-Typen (Bestandsverhalten, jetzt festgeschrieben)
- Handbuch (Widget-Tabelle, Einstellungs-Hinweise) und CHANGELOG
  (Geaendert/Entfernt/Behoben) aktualisiert
- Web: 52 Dateien / 344 Tests gruen, tsc Exit 0; API: tsc Exit 0,
  dashboard-Spec 31 Tests gruen

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-16 13:44:09 +02:00
schalli 6d8c7c46a8 feat(web): CalendarConfig im Einstellungsfeld, Changelog- und Handbuch-Eintrag
- Kalender-Zweig im Einstellungsfeld ersetzt den englischen Fliesstext durch CalendarConfig (Monatsansicht ein/aus, Anzahl Termine 0..10, Zeitraum 7/14/30/60/90) nach Muster ClockConfig; Speichern per partiellem updateWidgetConfig
- Paneltest um drei Kalender-Tests erweitert (7/7 gruen), next-intl-Mock interpoliert jetzt {platzhalter}
- CHANGELOG.md: zweiter Eintrag unter Unveroeffentlicht/Geaendert; Anwenderhandbuch: Widget-Tabellenzeile und Dashboard-Widgets-Absatz ergaenzt
- Gesamtlauf: 51 Testdateien / 332 Tests gruen, Type-Check Exit 0 (quick-260916-htc)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-16 13:12:48 +02:00
schalli c5f4adeeed docs(quick-260916-dcz): Betriebshandbuch Kapitel 9 (Changelog-Schritt, Gitea-Release, Seite Was ist neu), Anwender-, Entwicklungs- und CI-Handbuch
Tessera CI/CD / Lint & Type Check (push) Successful in 45s
Tessera CI/CD / Tests (push) Successful in 1m0s
Tessera CI/CD / Build & Publish Images (push) Successful in 2m51s
- Betrieb Kapitel 9: Vorschritt CHANGELOG.md vor dem Tag, automatischer Gitea-Release samt Verhalten bei fehlendem Abschnitt, Erstfreigabe v1.0.0 in der Vergangenheit, vierter Erkennungsweg "Was ist neu"
- Anwender: Satz zur Versionszeile in "Aufbau der Oberflaeche", neuer Abschnitt "Was ist neu" vor den Stolpersteinen, Inhaltsverzeichnis; Abschnitt "Dashboard" (dyv) unangetastet
- Entwicklung: Regel "Aenderungsliste" unter Konventionen und Fallstricke (Bauzeit-Einbettung, Importdisziplin, Kanalregel, Release-Skript)
- CI-Setup (ASCII): REGISTRY_TOKEN mit repository: write, vier Schritte im Job publish, Release je Tag, API-Basis im Job-Container

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018N9CD3ebPKm1b32bPpBknY
2026-09-16 11:25:10 +02:00
schalli cf97b5b64b docs(quick-260916-dyv): Anwenderhandbuch — Bearbeiten-Schalter unten rechts, ganze Kachel ziehbar, Mindestgroessen
Tessera CI/CD / Lint & Type Check (push) Successful in 48s
Tessera CI/CD / Tests (push) Successful in 56s
Tessera CI/CD / Build & Publish Images (push) Successful in 2m52s
- Abschnitt Dashboard: Stift-Schalter unten rechts, Haekchen "Aenderungen
  speichern" und "Widget hinzufuegen" daneben
- Ziehen an beliebiger Stelle der Kachel (Eingabefelder, Knoepfe, Links
  ausgenommen), grauer Griff am oberen Rand, Ablegen nur auf freiem Platz
- Mindestgroesse = gerade noch bedienbar; Entfernen-Symbol rechts im Griff

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018N9CD3ebPKm1b32bPpBknY
2026-09-16 10:43:01 +02:00