Commit Graph

972 Commits

Author SHA1 Message Date
schalli a60c168587 docs(quick-260916-hiv): Kalenderquellen-Formular — URL-Platzhalter je Typ + EWS-Hinweis; Zusammenfassung, Aktenstand
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-16 12:49:28 +02:00
schalli 9439c33989 docs: Changelog-Eintrag fuer URL-Platzhalter im Kalenderquellen-Formular
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-16 12:47:25 +02:00
schalli 2306a6dee1 feat(web): typabhaengiger URL-Platzhalter + EWS-Hinweis im Kalenderquellen-Formular
- Platzhalter je Typ (CalDAV/ICS/Exchange-Graph/Exchange-EWS), ohne Typ weiterhin https://
- Grauer Hinweis unter dem Feld nur bei Exchange + EWS, unterhalb eines eventuellen Fehlers
- Neuer Komponententest mit 6 Faellen (TDD: rot vor der Implementierung)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-16 12:47:09 +02:00
schalli 618fbd6845 feat(web): fuenf Uebersetzungsschluessel fuer URL-Platzhalter im Kalenderquellen-Formular
- widgets.calendar.formFieldUrlPlaceholderEws|Graph|Caldav|Ics + formFieldUrlHintEws in de.json und en.json
- Platzhalter identisch in beiden Sprachen, Hinweistext uebersetzt

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-16 12:46:16 +02:00
schalli a5f30d432d docs(quick-260916-hiv): Plan — Kalenderquellen-Formular: URL-Platzhalter je Typ (EWS/Graph/CalDAV/ICS) + grauer EWS-Hinweis, i18n de/en, Komponententest, Changelog 2026-09-16 12:44:50 +02:00
schalli 2a820b630c docs: Arbeitsstand pausiert — v1.1.0 live, nichts angefangen; Handoff fuer die naechste Sitzung
Tessera CI/CD / Lint & Type Check (push) Successful in 50s
Tessera CI/CD / Tests (push) Successful in 58s
Tessera CI/CD / Build & Publish Images (push) Successful in 2m49s
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018N9CD3ebPKm1b32bPpBknY
2026-09-16 12:29:37 +02:00
schalli 29fe3d772a docs: Version 1.1.0 freigegeben — Tag, live-Abbilder, Gitea-Release durch die Pipeline; Aktenstand
Tessera CI/CD / Lint & Type Check (push) Successful in 47s
Tessera CI/CD / Tests (push) Successful in 1m1s
Tessera CI/CD / Build & Publish Images (push) Successful in 2m52s
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018N9CD3ebPKm1b32bPpBknY
2026-09-16 12:15:09 +02:00
schalli e0d4532327 docs: Version 1.1.0 freigegeben — Unveröffentlicht -> 1.1.0 (2026-09-16), neuer leerer Abschnitt Unveröffentlicht
Tessera CI/CD / Build & Publish Images (push) Successful in 3m6s
Tessera CI/CD / Lint & Type Check (push) Successful in 50s
Tessera CI/CD / Tests (push) Successful in 1m0s
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018N9CD3ebPKm1b32bPpBknY
v1.1.0
2026-09-16 12:02:35 +02:00
schalli 75ff8bb6f1 docs(quick-260916-dcz): Aenderungsliste abgeschlossen, verifiziert 8/8 und im Browser bewiesen — Zusammenfassung, Verifikation, Aktenstand
Tessera CI/CD / Lint & Type Check (push) Successful in 47s
Tessera CI/CD / Tests (push) Successful in 1m2s
Tessera CI/CD / Build & Publish Images (push) Successful in 2m44s
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018N9CD3ebPKm1b32bPpBknY
2026-09-16 11:43:41 +02:00
schalli c3d8e16eb3 fix(web): fehlende Uebersetzungen — Kalenderquellen-Formular (18 Schluessel), Kalender-Einstellungen (2), Marktplatz (1) in de/en nachgetragen; Changelog Behoben
Tessera CI/CD / Lint & Type Check (push) Successful in 51s
Tessera CI/CD / Tests (push) Successful in 1m41s
Tessera CI/CD / Build & Publish Images (push) Successful in 3m16s
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018N9CD3ebPKm1b32bPpBknY
2026-09-16 11:34:09 +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 6940bd05a1 ci(quick-260916-dcz): Gitea-Release je Freigabe-Tag aus CHANGELOG.md (publish-release.sh, idempotent, --dry-run), Schritt in ci.yml
- publish-release.sh: POSIX sh, Entscheidung anhand GITHUB_REF wie publish-images.sh, --tag/--dry-run, Abschnitt per awk, JSON nur per jq --arg, Token nur aus GITEA_TOKEN ueber Header-Datei, GET/tags -> PATCH oder POST, Exit 1 ohne Abschnitt
- ci.yml: vierter Schritt im Job publish mit GITEA_TOKEN aus secrets.REGISTRY_TOKEN ueber env
- Bewiesen: dry-run v1.0.0 (Body 2227 Zeichen), v9.9.9 Exit 1, main nichts zu tun, API-Basis aus GITHUB_SERVER_URL; Docker-Abbild traegt den Changelog nur im Server-Bundle (1/0); Release Tessera 1.0.0 (id 1) angelegt, zweiter Lauf PATCH, genau ein Release

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018N9CD3ebPKm1b32bPpBknY
2026-09-16 11:24:20 +02:00
schalli ba06db98c5 feat(quick-260916-dcz): CHANGELOG.md, Seite "Was ist neu" mit Kanalfilter, Versionszeile als Link, Bauzeit-Einbettung
- CHANGELOG.md (Wurzel): Unveroeffentlicht (bwo + dyv + diese Seite, 8 Punkte) und 1.0.0 – 2026-09-15 (11 Punkte aus den Handbuechern), Alltagssprache, echte Umlaute
- next.config.ts liest CHANGELOG.md zur Bauzeit nach env.TESSERA_CHANGELOG_MD; .dockerignore-Ausnahme !CHANGELOG.md und COPY-Zeile im Web-Dockerfile
- lib/changelog.ts: filterChangelogForChannel (live ohne Unveroeffentlicht, beta/dev mit "Noch nicht freigegeben (Beta)", leerer Abschnitt ausgeblendet), 10 Tests
- Server-Seite /changelog (MDEditor.Markdown + rehype-sanitize, Hinweis auf Beta, Leer-Text), 3 Tests; Versionszeile ist Link mit aria-label, 2 Tests
- de/en: sidebar.whatsNew und Namensraum changelog; Web-Suite 49/309, tsc 0

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018N9CD3ebPKm1b32bPpBknY
2026-09-16 11:20:22 +02:00
schalli 0db21627f5 docs(quick-260916-dcz): Plan revidiert (Runde 1) — Bezugspunkt 963fa36, Nachbesserung 260916-dyv in Unveroeffentlicht
Bezugs-Commit aller git-diff-Gates 7a6f42e -> 963fa36; Baseline Web 46/286 -> 47/294
(frisch gemessen), Zielzahlen 48/301 -> 49/309; Unveroeffentlicht = bwo + dyv + Seite
"Was ist neu" als eine Liste (2 Neu + 6 Geaendert) mit eigenem Zaehl-Gate; Hinweis,
dass der dyv-Stand des Dashboard-Abschnitts im Anwenderhandbuch unangetastet bleibt.
Von den 19 Plan-Dateien hat dyv nur de.json/en.json (dragHint) und
anleitung-anwender.md (Abschnitt Dashboard) beruehrt — Einfuegepunkte bleiben gueltig.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018N9CD3ebPKm1b32bPpBknY
2026-09-16 11:07:09 +02:00
schalli 963fa36cd7 docs(quick-260916-dyv): Nachbesserung abgeschlossen, verifiziert und im Browser bewiesen (Rechner-Minimum korrigiert) — Zusammenfassung, Verifikation, Aktenstand, Ledger #39 fixed
Tessera CI/CD / Lint & Type Check (push) Successful in 48s
Tessera CI/CD / Tests (push) Successful in 1m7s
Tessera CI/CD / Build & Publish Images (push) Successful in 2m43s
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018N9CD3ebPKm1b32bPpBknY
2026-09-16 11:03:42 +02:00
schalli 8792819e34 fix(quick-260916-dyv): Rechner-Mindesthoehe 10 statt 9 Zeilen — sechs Tastenreihen, unterste Reihe war bei 9 um 25 px abgeschnitten (Browser-Messung)
Tessera CI/CD / Lint & Type Check (push) Successful in 54s
Tessera CI/CD / Tests (push) Successful in 1m1s
Tessera CI/CD / Build & Publish Images (push) Successful in 2m58s
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018N9CD3ebPKm1b32bPpBknY
2026-09-16 10:57:55 +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
schalli dbbd54f5a1 feat(quick-260916-dyv): Bearbeiten-Schalter unten rechts (Rand oben 28 px), ganze Kachel als Griff mit Kopfleiste, cancel-Selektor, kein Ueberlappen beim Ablegen
- page.tsx: feste Aktionsleiste `fixed bottom-6 right-6 z-20` mit "Widget
  hinzufuegen" (nur Bearbeitungsmodus) links neben dem Stift/Haekchen; Block
  oben rechts und mt-8-Wrapper entfernt, Grid direkt im Container p-2
  (12 + 8 + 8 = 28 px statt 60 px); page.test.tsx NEU mit 3 Tests
- widget-wrapper.tsx: Karte ist im Bearbeitungsmodus der Griff (cursor-grab),
  20-px-Overlay-Kopfleiste mit Griff-Symbol und Tooltip dragHint, Loesch-Knopf
  in der Kopfleiste mit data-no-drag; Rumpf h-full unveraendert (Hoehenkette)
- dashboard-grid.tsx: WIDGET_DRAG_HANDLE_SELECTOR, WIDGET_DRAG_CANCEL_SELECTOR
  (input, textarea, select, button, a, [contenteditable], [data-no-drag],
  .widgetNoDrag), threshold 3; FREE_PLACEMENT_COMPACTOR = noCompactor +
  preventCollision: true (freie Platzierung bleibt, Commit c8f3361)
- dashboard-grid.test.tsx: Mock per importOriginal (echter noCompactor),
  Tests 6-8 (dragConfig-Pin, Compactor-Pin, cancel/handle-Semantik im DOM)
- edit-mode-toggle.tsx: schwebend (shadow-lg, inaktiv border + bg-card)
- de.json/en.json: widgets.dragHint

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018N9CD3ebPKm1b32bPpBknY
2026-09-16 10:41:49 +02:00
schalli dc992c9bc6 fix(quick-260916-dyv): Mindestgroessen inhaltsgetrieben (kleinste bedienbare Kachel je Typ), gespeicherte Minima ueberschrieben, Stoppuhr-Bedienleiste kompakt
- WIDGET_CONSTRAINTS: Minima aus dem Innenaufbau gerechnet (clock 2/2, search 6/2,
  calendar 3/3, note 4/4, calculator 3/9, favorites 3/3, link 3/2, stopwatch 4/3),
  Vorgaben unveraendert; Test A pinnt alle 32 Werte per toEqual
- dashboard-grid.tsx: effectiveLayouts (useMemo) ueberschreibt minW/minH jedes
  gespeicherten Eintrags in jedem Breakpoint aus den Konstanten und hebt zu
  kleine w/h auf das Minimum an — RGL 2.2.3 nimmt gespeicherte Eintraege
  woertlich (synchronizeLayoutWithChildren) und liest data-grid nur ohne Eintrag
- dashboard-grid.test.tsx: Test 5 angepasst, Test 9 (Ueberschreibung je
  Breakpoint, unbekannter Typ unveraendert) und Test 9b (h 8 -> 9, w >= minW bleibt)
- stopwatch-widget.tsx: Bedienleiste px-2 py-1 text-xs, Zeile gap-1 py-1, damit
  Stop + Runde + Reset in 4 Spalten passen und die Kachel auf 4x3 schrumpfen kann

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018N9CD3ebPKm1b32bPpBknY
2026-09-16 10:37:55 +02:00
schalli ec1b0ce582 docs(quick-260916-dyv): Plan — Dashboard-Nachbesserung: Mindestgroessen inhaltsgetrieben, Schalter unten rechts (Rand 28 px), ganze Kachel als Griff, kein Ueberlappen
Drei Aufgaben, 12 Dateien ausserhalb .planning. Gemessene Abweichungen vom
Auftrag: react-grid-layout 2.2.3 nimmt gespeicherte Layout-Eintraege woertlich
inklusive minW/minH und ignoriert data-grid (zweiter Grund fuer "nicht klein
genug" — Ueberschreibung beim Rendern noetig); die alten 12-Spalten-Minima sind
im feinen Raster nur fuer Uhr/Kalender brauchbar, Suche braucht 6 Spalten,
Rechner 9 Zeilen (heute bei 8 unten abgeschnitten), Stoppuhr nur mit kompakter
Bedienleiste; noCompactor ohne preventCollision springt bei Kollision und laesst
Ueberlappungen stehen (auch beim Vergroessern); cancel gewinnt in react-draggable
4.7.0 auch innerhalb des Griffs; widgetNoDrag ist ein toter Marker aus Phase 8.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018N9CD3ebPKm1b32bPpBknY
2026-09-16 10:29:11 +02:00
schalli df16f4682a docs(quick-260916-dcz): Plan — CHANGELOG.md in Alltagssprache, Seite "Was ist neu" mit Kanalfilter, Gitea-Release je Freigabe-Tag, Handbuecher
Drei Aufgaben, 19 Dateien ausserhalb .planning. Gemessene Abweichungen vom
Auftrag: .dockerignore schliesst Wurzel-*.md aus (Ausnahme !CHANGELOG.md noetig);
localhost:3002 ist aus dem CI-Job-Container nicht erreichbar (API-Basis aus
GITHUB_SERVER_URL); vier Module statt zwei in den Handbuechern. Bauweg per
env.TESSERA_CHANGELOG_MD in next.config.ts (webpack + Turbopack, Server-Bundle-only).
COVERAGE.md: Gitea-Release-API (POST/GET-by-tag/PATCH integriert, Rest begruendet aus).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018N9CD3ebPKm1b32bPpBknY
2026-09-16 10:03:06 +02:00
schalli 7a6f42ea74 docs(quick-260916-bwo): Dashboard-Umbau abgeschlossen, verifiziert 8/8 und im Browser bewiesen — Zusammenfassung, Verifikation, Aktenstand
Tessera CI/CD / Lint & Type Check (push) Successful in 48s
Tessera CI/CD / Tests (push) Successful in 1m6s
Tessera CI/CD / Build & Publish Images (push) Successful in 3m3s
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018N9CD3ebPKm1b32bPpBknY
2026-09-16 09:36:50 +02:00
schalli 1aefaa36c1 docs(quick-260916-bwo): Anwenderhandbuch — feines Raster, Uhrzeit skaliert mit der Kachel, Schriftgroesse in Punkt
Tessera CI/CD / Lint & Type Check (push) Successful in 49s
Tessera CI/CD / Tests (push) Successful in 57s
Tessera CI/CD / Build & Publish Images (push) Successful in 3m34s
- Bearbeitungs-Hinweis: Position und Groesse rasten in feinen Schritten ein
- Uhr-Zeile: Uhrzeit waechst mit der Kachel, feste Schriftgroesse in Punkt unter Einstellungen > Dashboard
- Satz zu den Widget-Einstellungen nennt die Uhr (Zeitzone und Schriftgroesse)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018N9CD3ebPKm1b32bPpBknY
2026-09-16 09:15:03 +02:00
schalli a175c00c18 feat(quick-260916-bwo): Abstaende halbiert — Seitenrahmen p-3 (alle Seiten), Dashboard p-2, Grid 8 px, Widget-Innenabstaende
- app-shell.tsx: main p-3 (12 px statt 24) — gilt fuer alle Seiten, Nachtrag des Users
- page.tsx: Container relative p-2, Umschalter right-2 top-2; mt-8 bleibt (Umschalter 36 px hoch, sonst Ueberlappung)
- link/favorites p-1, calendar p-1.5 (Zustandsansichten p-2), search px-1.5, note-Kopfzeile px-1.5
- Grid-Abstand 8 px bereits in Task 1, Uhr/Stoppuhr/Rechner-Innenabstaende bereits in 2a

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018N9CD3ebPKm1b32bPpBknY
2026-09-16 09:13:23 +02:00
schalli 2d8efe1a97 feat(quick-260916-bwo): Widget-Inhalt skaliert per Container-Queries (Uhr, Stoppuhr, Rechner), Punktgroesse der Uhrzeit einstellbar
- widget-wrapper.tsx: Rumpf ist Groessen-Container (@container-size) fuer cqw/cqh
- clock-font-size.ts (neu): Grenzen 8..200, resolveClockTimeFontSizePt nur fuer endliche Zahlen (T-BWO-01)
- clock-widget.tsx: Container-Query-Klassen mit clamp(), data-font-mode auto/fixed, Inline-pt nur bei Zahl, keine vw-Formel mehr, p-1
- stopwatch-widget.tsx: Anzeige per Container-Query, p-1.5; calculator-widget.tsx: Anzeige und Tasten skalieren, Tasten h-full min-h-7, p-1
- widget-settings-panel.tsx: Zahlenfeld Schriftgroesse der Uhrzeit (Blur/Enter, leer = automatisch, Fehlermeldung ausserhalb 8..200)
- de.json/en.json: widgets.clock.fontSizeLabel/fontSizeAuto/fontSizeHint/fontSizeInvalid (Sie-Form, Waechter gruen)
- Tests: Uhr +4, Stoppuhr +1, Rechner +1, widget-settings-panel.test.tsx neu (4)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018N9CD3ebPKm1b32bPpBknY
2026-09-16 09:12:02 +02:00
schalli 3f5afb0f54 feat(quick-260916-bwo): Dashboard-Raster verdoppelt (24 Spalten, 20 px, 8 px Abstand), Konstanten x2, einmalige Umrechnung gespeicherter Anordnungen mit Marker __gridVersion
- dashboard-grid.tsx: COLS 24/20/12/8/2, rowHeight 20, margin 8 (containerPadding folgt), Rueckfallwerte 4
- widget-registry.tsx: alle 32 Werte in WIDGET_CONSTRAINTS verdoppelt
- grid-layout-migration.ts (neu): migrateGridLayouts/withGridVersion, Marker nur im JSON, Idempotenz (T-BWO-02)
- dashboard-store.ts: Umrechnung beim Laden, Sofort-Speichern mit Marker, withGridVersion bei jedem saveLayout
- Tests: Migration 7 (neu), Store 6 (neu), Registry +1 (Tabelle), Grid +2 (Props ueber Mock), API-Spec +2 (Durchreichung __gridVersion, timeFontSizePt)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018N9CD3ebPKm1b32bPpBknY
2026-09-16 09:09:00 +02:00
schalli 50f201ecc1 docs(quick-260916-bwo): Plan — fails_when je Verify-Block ergaenzt (Pruefer-Warnung)
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018N9CD3ebPKm1b32bPpBknY
2026-09-16 09:02:47 +02:00
schalli 7eb2516278 docs(quick-260916-bwo): Plan fuer Dashboard — feineres Raster, skalierende Widget-Inhalte, halbe Abstaende
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018N9CD3ebPKm1b32bPpBknY
2026-09-16 09:00:26 +02:00
schalli 5f50c5faa0 docs: Todo — Desktop-Client auslieferungsreif machen (Versions-Check, Windows-Installer, Abnahme, CI-Bau)
Tessera CI/CD / Lint & Type Check (push) Successful in 44s
Tessera CI/CD / Tests (push) Successful in 52s
Tessera CI/CD / Build & Publish Images (push) Successful in 2m48s
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018N9CD3ebPKm1b32bPpBknY
2026-09-15 21:40:15 +02:00
schalli 18170d690b docs: v1.0.0 live auf tessera.ctl.de seit 2026-09-15 — Stand festgehalten, nichts offen
Tessera CI/CD / Lint & Type Check (push) Successful in 47s
Tessera CI/CD / Tests (push) Successful in 57s
Tessera CI/CD / Build & Publish Images (push) Successful in 2m44s
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018N9CD3ebPKm1b32bPpBknY
2026-09-15 16:25:42 +02:00
schalli 7d201a82ab docs: IMAGE_TAG, COMPOSE_FILE und TESSERA_BUGREPORT_TO in die Vorlage .env.prod.example aufgenommen; Handbuch-Hinweis angepasst
Tessera CI/CD / Lint & Type Check (push) Successful in 49s
Tessera CI/CD / Tests (push) Successful in 56s
Tessera CI/CD / Build & Publish Images (push) Successful in 2m47s
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018N9CD3ebPKm1b32bPpBknY
2026-09-15 09:12:40 +02:00
schalli db2e2c83fe docs: Erstfreigabe v1.0.0 festgehalten — Zweig live, CI 332/333/334 gruen, Registry live/v1.0.0; Tagesabschluss 2026-09-14
Tessera CI/CD / Lint & Type Check (push) Successful in 47s
Tessera CI/CD / Tests (push) Successful in 56s
Tessera CI/CD / Build & Publish Images (push) Successful in 2m46s
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018N9CD3ebPKm1b32bPpBknY
2026-09-14 17:39:48 +02:00
schalli e5098603b4 docs(quick-260914-m97): Fehler-melden-Knopf abgeschlossen, verifiziert 9/9 und im Browser bewiesen — Zusammenfassung, Verifikation, Aktenstand, Ledger #38 fixed
Tessera CI/CD / Build & Publish Images (push) Successful in 2m42s
Tessera CI/CD / Lint & Type Check (push) Successful in 46s
Tessera CI/CD / Tests (push) Successful in 53s
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018N9CD3ebPKm1b32bPpBknY
v1.0.0
2026-09-14 17:18:28 +02:00
schalli 77117de3d0 docs(quick-260914-m97): Handbuecher — Einen Fehler melden (Anwender), Feld Fehlermeldungen an (Administration), TESSERA_BUGREPORT_TO als Rueckfall (Betrieb)
Tessera CI/CD / Lint & Type Check (push) Successful in 43s
Tessera CI/CD / Tests (push) Successful in 55s
Tessera CI/CD / Build & Publish Images (push) Successful in 2m14s
- Anwender: neuer Abschnitt 8 mit Ablauf, Datenschutz-Hinweis (Bild zeigt die aktuelle Seite), was mitgeschickt wird, Rueckmeldungen; Kopfleiste nennt drei Bedienelemente; Stolperstein "kein Postfach"
- Administration: Kapitel 6 SMTP beschreibt das Feld Fehlermeldungen an (Drossel, 4 MB, Rueckfall, Datenschutz); zwei neue Zeilen in der Fehlersuche-Tabelle
- Betrieb: TESSERA_BUGREPORT_TO in der Konfigurationstabelle (Serverdatei von Hand ergaenzen, wie IMAGE_TAG) und in der Symptomtabelle

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018N9CD3ebPKm1b32bPpBknY
2026-09-14 16:53:40 +02:00
schalli b41be21190 feat(quick-260914-m97): Feld Fehlermeldungen an im SMTP-Formular — settings-api, Formular, i18n settings.smtp
- SmtpConfig.bugReportRecipient (string | null) und SaveSmtpPayload.bugReportRecipient (null loescht, fehlend bewahrt)
- Eingabefeld type=email hinter der Absenderadresse mit Hinweistext; Payload traegt immer trim() || null
- Zwei Komponententests: Vorbelegung aus GET, PUT-Payload mit Wert bzw. null
- i18n settings.smtp.bugReportRecipient / bugReportRecipientHelp in de und en

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018N9CD3ebPKm1b32bPpBknY
2026-09-14 16:51:36 +02:00
schalli 60b0ee8409 feat(quick-260914-m97): Fehler-melden-Knopf in der Kopfzeile — Bildschirmfoto vor dem Dialog (html-to-image 1.11.13), Fehlerpuffer, Dialog mit Vorschau, i18n bugReport
- Knopf (Kaefer-Symbol) unmittelbar vor dem Erscheinungsbild-Schalter; captureScreenshot() laeuft VOR dem Oeffnen, Test pinnt es im toPng-Mock
- computeCaptureSize (laengste Kante 1600 px, reine Funktion, getestet), dataUrlToBlob, sendBugReport als Multipart mit credentials und ohne Content-Type-Header
- error-buffer: Ringpuffer 20, window error/unhandledrejection, console.error (Original bleibt), fetch-Wrapper nur bei !ok ohne Anfrage-Rumpf/Suchteil/Kopfzeilen (T-M97-02), idempotent, SSR-sicher; installiert in app-shell
- Dialog mit Vorschau, Haekchen, Beschreibung, Meldungen je Status 409/413/429/502/allgemein, Admin-Link auf /admin/smtp
- i18n bugReport de/en, Allowlist um "passiert"; html-to-image exakt 1.11.13, Lockfile aktualisiert

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018N9CD3ebPKm1b32bPpBknY
2026-09-14 16:50:01 +02:00
schalli 54121c1721 feat(quick-260914-m97): Fehlermeldungen per E-Mail — Empfaenger in SmtpConfig (Migration), MailService-Anhaenge, Modul bug-reports mit Drossel, PNG-Pruefung und Mandant aus der Sitzung
- SmtpConfig.bugReportRecipient (nullable, additive Migration 20260914170000), DTO @IsOptional @IsEmail, SAFE_SELECT, getBugReportRecipient gebunden
- MailService: Versandkern deliver (wirft, Anhaenge), sendViaTenantTransport bleibt verschluckender Mantel (T-02-12), sendBugReport laesst Fehler durch
- POST /bug-reports: Multipart 4 MiB je Route, alle angemeldeten Rollen, Drossel 5/10 min -> 429, PNG-Signatur -> 400, kein Empfaenger -> 409, Versandfehler -> 502, eine Protokollzeile
- Falsifizierungen (a)-(d) als Specs; @Expose() im DTO, damit errors auch bei fehlendem Feld zu [] wird
- Doku-Zeile fuer rls-access-inventory, TESSERA_BUGREPORT_TO in docker-compose.prod.yml

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018N9CD3ebPKm1b32bPpBknY
2026-09-14 16:45:09 +02:00
schalli 17a7e5ef9b docs(quick-260914-m97): Plan revidiert (Runde 1) — Task 2 mit Commit-Grenze 2a/2b, computeCaptureSize automatisiert getestet, Dialog-Tests fuer 413/429/502/allgemein aus de.json
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018N9CD3ebPKm1b32bPpBknY
2026-09-14 16:34:41 +02:00
schalli 04f933c972 docs(quick-260914-m97): Plan fuer den Fehler-melden-Knopf — Bildschirmfoto vor dem Dialog, E-Mail mit PNG-Anhang, Empfaenger in SmtpConfig, Drossel und Falsifizierungen
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018N9CD3ebPKm1b32bPpBknY
2026-09-14 16:26:25 +02:00
schalli 5c42c558c4 docs(quick-260914-ku1): Kanaele und Versionsstempel abgeschlossen und verifiziert 8/8 — Zusammenfassung, Verifikation, Aktenstand
Tessera CI/CD / Lint & Type Check (push) Successful in 45s
Tessera CI/CD / Tests (push) Successful in 56s
Tessera CI/CD / Build & Publish Images (push) Successful in 3m52s
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018N9CD3ebPKm1b32bPpBknY
2026-09-14 16:01:13 +02:00
schalli ea6aa995b2 docs(quick-260914-ku1): Betriebshandbuch — Zwei Kanäle Live und Beta, Freigabe, Hotfix ohne Datenbankänderung, neuer Live-Server; ci-cd-setup auf gemessenen Stand
Tessera CI/CD / Lint & Type Check (push) Successful in 48s
Tessera CI/CD / Tests (push) Successful in 52s
Tessera CI/CD / Build & Publish Images (push) Successful in 3m34s
- anleitung-betrieb.md: neues Kapitel 9 (Kanal, IMAGE_TAG je Server, Freigabe,
  Hotfix-Ablauf mit Regel "Keine Datenbankaenderung als Hotfix", drei Kontrollwege,
  Einrichtung des Live-Servers, Erstfreigabe v1.0.0); Inhaltsverzeichnis, Tabelle in
  Kapitel 1, IMAGE_TAG in Kapitel 3, Etiketten in Kapitel 4, Startzeile in Kapitel 7
- ci-cd-setup.md: REGISTRY_TOKEN und Push ueber localhost:3002, Trigger main/live/v*,
  Jobs quality -> test -> publish, Etiketten- und Build-Arg-Tabellen, D-13 ueberholt,
  Tag-/Branch-Schutz-Empfehlung (T-KU1-04), Fehlerbehebung fuer den Stempel

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018N9CD3ebPKm1b32bPpBknY
2026-09-14 15:44:16 +02:00
schalli 9731501718 ci(quick-260914-ku1): zwei Kanaele — main -> beta+latest, Tag v* -> live+vX.Y.Z, Versionsstempel als Build-Args in beide Dockerfiles, IMAGE_TAG in docker-compose.prod.yml
- Dockerfiles: globale ARG APP_VERSION/APP_CHANNEL/APP_COMMIT/APP_BUILD_TIME (Vorgabe dev),
  web-builder setzt NEXT_PUBLIC_APP_* vor pnpm build (Bauzeit-Einbettung), runner-Stufen
  setzen ENV APP_* fuer die Laufzeit
- .gitea/scripts/publish-images.sh: Kanal und Etiketten allein aus GITHUB_REF, --print-plan
  ohne Docker, Zweig live ohne Tag = nichts zu tun (T-KU1-07)
- ci.yml: Trigger main, live und Tags v*; publish mit fetch-depth: 0 und Skriptaufruf
- docker-compose.prod.yml: image ...:${IMAGE_TAG:-beta} fuer web und api
- Falsifizierung lokal: mit Build-Args v9.9.9-test in API-Env, dist-Zeile und Web-Bundle
  (1 Datei), ohne Build-Args dev/dev und 0 Treffer im Bundle

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018N9CD3ebPKm1b32bPpBknY
2026-09-14 15:42:01 +02:00
schalli cdb571c509 feat(quick-260914-ku1): Versionsstempel — GET /health/version aus APP_*, VersionResponse, app-version.ts und Abzeichen v<Version> · <Kanal> in der Seitenleiste
- packages/shared: VersionResponse { name, version, channel, commit, buildTime }
- apps/api: health/app-version.ts (getAppVersion mit ||-Vorgaben dev/dev, formatAppVersionLine),
  HealthController.getVersion delegiert (bleibt @Public, T-KU1-03), main.ts protokolliert
  "Tessera API <version> (<channel>) <commit>" beim Start; neuer Spec mit 6 Tests
- apps/web: lib/app-version.ts (NEXT_PUBLIC_APP_* mit vollem Literalnamen, loadApiVersion
  memoisiert und still bei Fehler), AppVersionBadge unten in der Seitenleiste (auch mobil,
  nicht eingeklappt), sidebar.channel.{beta,live,dev} in de/en; 5 + 4 + 1 neue Tests
- Suiten: API 65 Dateien / 1060 Tests, Web 40 / 243, tsc in shared/api/web Exit 0

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018N9CD3ebPKm1b32bPpBknY
2026-09-14 15:32:50 +02:00
schalli 1cd4212df0 docs(quick-260914-ku1): Plan fuer zwei Auslieferungskanaele (Beta/Live), Versionsstempel in Abbilder, API und Seitenleiste, Hotfix-Ablauf im Betriebshandbuch
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018N9CD3ebPKm1b32bPpBknY
2026-09-14 15:23:25 +02:00
schalli 6c19451be9 docs: Mandantenfaehigkeit ruht auf Entscheidung des Users — 3a/Etappe 4 nicht weiterverfolgen; Lizenzmodell-Wunsch festgehalten
Tessera CI/CD / Lint & Type Check (push) Successful in 46s
Tessera CI/CD / Tests (push) Successful in 50s
Tessera CI/CD / Build & Publish Images (push) Successful in 7s
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018N9CD3ebPKm1b32bPpBknY
2026-09-14 13:51:23 +02:00
schalli 5f80582a37 docs(quick-260914-eym): Etappe 3c abgeschlossen und verifiziert 9/9 — Zusammenfassung, Verifikation, Aktenstand
Tessera CI/CD / Lint & Type Check (push) Successful in 47s
Tessera CI/CD / Tests (push) Successful in 58s
Tessera CI/CD / Build & Publish Images (push) Successful in 7s
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018N9CD3ebPKm1b32bPpBknY
2026-09-14 12:06:13 +02:00
schalli 939c8121a1 docs(quick-260914-eym): Etappe 3c abgeschlossen — Kritikschrift, Klassifikation, Auftrag, Datenbankrolle, WINDOWS #21/#30 geschlossen, Single-Flight-Riegel als Eintrag
Tessera CI/CD / Lint & Type Check (push) Successful in 50s
Tessera CI/CD / Tests (push) Successful in 53s
Tessera CI/CD / Build & Publish Images (push) Successful in 28s
- Kritikschrift: neuer Abschnitt "## Systemkontext (Etappe 3c, 260914-eym)"
  mit (y1) woertlicher Werkzeugausgabe und pg_policies der lebenden DB,
  (y2) Signaltabelle beider Fehlerrichtungen samt Rueckbau-Belegen (a)-(d),
  (y3) Leere-als-Abwesenheit je Pfad (kein Pfad loescht), (y4) bewusst
  nicht geloest, (y5) bewusst nicht angefasst; Nachtraege in (d4), (s4),
  (b4) und im Abschluss
- Klassifikation: Uebersichtstabelle mit dritter Spalte System, Werte
  nachgerechnet (61/179/5), Stand-Absatz 260914-eym (72 Paare, Klassen
  unveraendert, sieben Staende geaendert), sechs Regelschluesse im
  Hintergrunddienst-Abschnitt, admin-seed-Zeile mit 3c-Befund, 3c-Punkt
  unter "NICHT entscheidet" erledigt
- Auftrag: 3c als Erledigt vermerkt (3d64567/6e2a641), zwei neue Fallen
  unter "Werkzeuge und Fallen"
- Datenbankrolle: dritte Sitzungsvariable, Nachtrag zum Systemkontext und
  zur weiterhin gueltigen Vorher-Pruefung ohne-kontext-leer
- Ledger (ueber gsd-tools windows): #21 fixed, #30 fixed, #37 neu
  (prozessweiter Single-Flight-Riegel processInbox) — open 15 / waived 1 /
  fixed 21 / total 37, aus den Zeilen gezaehlt

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018N9CD3ebPKm1b32bPpBknY
2026-09-14 11:52:47 +02:00
schalli 6e2a641d76 feat(quick-260914-eym): Mail-Transport je Versand nach Mandant (WINDOWS #30), ldap/digest/matching ueber Systemkontext, vier Tabellen im Werkzeug, Erlaubnisliste vollstaendig
- mail: MailerModule-Fabrik und DB-Startpfad (findFirst beim Boot) ersatzlos
  entfernt; MailService baut je Versand einen nodemailer-Transport aus
  getDecryptedSmtpConfig(tenantId) des Empfaenger-Mandanten, Umgebungs-Kette
  (MAIL_* -> TESSERA_SMTP_* -> localhost:1025) nur als Rueckfall; Fehler
  weiter verschluckt (T-02-12), close() im finally; neue mail.service.spec.ts
  (4 Tests, T-GWH-03 geschlossen)
- settings: Startpfad-Methode samt vier Spec-Tests geloescht;
  auth: requestPasswordReset reicht user.tenantId durch (Spec-Zusicherung)
- ldap: getAllActiveConfigs und Nachverschluesselung lesen ueber forSystem
  (zwei Zuweisungen), Schreibzeile je Altzeile ueber forTenant(config.tenantId);
  Tests 301/306 umgedreht, neuer Altzeilen-Test
- tender-digest: Kandidatenabfrage ueber forSystem, Schleife gebunden (+1 Test)
- tender-matching: Profilabfrage ueber forSystem, Katalog (D-03) ungebunden (+1 Test)
- tender-notifications.integration.spec: Mock um forSystem
- Werkzeug: LdapConfig (15 Spalten), LdapFieldMapping (6), TenderMatch (8),
  TenderSavedSearch (8) je neun Kennungen plus Relations-Kennung
  ldapconfig-systemkontext-include-fieldmappings-beider-mandanten
  -> Alle 253 Pruefungen bestanden
- Detektor: FORSYSTEM_ALLOWED_CALL_SITES auf 4 Dateien / 5 Aufrufe;
  Proben-Empfaenger sysPrisma (Gate-Zaehlung, Name nicht hartkodiert)
- Klassifikation: 6 Zeilen system-gebunden, settings/smtpConfig gebunden
- Falsifizierung durch Rueckbau ausgefuehrt und zurueckgenommen:
  (a) FOR SELECT bei TenderMatch entfernt -> 5 von 253 rot (Insert gelingt,
  cmd ALL); (b) Regel TenderSavedSearch aus der Datei entfernt -> 1 von 245
  rot (Extraktion), lebende DB bleibt bei 34; (c) local=false -> gruen, plus
  Reset entfernt -> 5 rot (Erben sichtbar); (d) Zahl 0 -> 2 rot, Fremddatei
  admin-seed -> 3 rot
- Baseline: 64 Dateien / 1054 Tests, tsc 0, Werkzeug 253

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018N9CD3ebPKm1b32bPpBknY
2026-09-14 11:46:08 +02:00
schalli 3d645674f0 feat(quick-260914-eym): forSystem(), is_system_context(), Systemleseregel auf fuenf Tabellen, DKV-Planer je Mandant — ein Pfad (WINDOWS #21)
- Helfer forSystem(prisma) in prisma-tenant.extension.ts (Array-Form,
  setzt app.system_context='true' und die beiden anderen Variablen
  ausdruecklich leer); forTenant()/withTenantTransaction() setzen
  app.system_context='' als Literal (4 neue Spec-Tests)
- Migration 20260914120000_rls_system_context_read: is_system_context()
  (COALESCE, STABLE) und system_read_policy FOR SELECT auf DkvModuleConfig,
  LdapConfig, LdapFieldMapping, TenderMatch, TenderSavedSearch — lokal
  angewendet (36 Migrationen, pg_proc 1, 5 system_read_policy, 34 Regeln)
- migration-sql.spec.ts: describe-Block fuer die neue Migration (6 Tests)
- rls-scratch-check.mjs: Funktion aus der Migration geschnitten,
  forSystemQuery/buildInlineSystemClient, Reset in forTenantQuery/
  buildInlineExtendedClient, runSystemContextChecks (4 Funktionsfaelle +
  9 Kennungen DkvModuleConfig) -> Alle 216 Pruefungen bestanden
- rls-access-inventory.spec.ts: fuenfte Erkennungsform const X = forSystem(,
  Stand system-gebunden mit Vorrangregel, FORSYSTEM_ALLOWED_CALL_SITES
  (exakte Zahl je Datei, 3 Tests), Proben C/D/E
- DKV: loadActiveConfigsForScheduler() ueber forSystem (findMany isActive,
  CONFIG_SAFE_SELECT, orderBy tenantId); DkvSchedulerService mit Auftrag je
  Mandant dkv-inbox-poll:<tenantId>, activeTenantId ersatzlos entfernt,
  setInterval/stopJob je Mandant, registeredTenantIds(); Controller
  stopJob(tenantId); neue dkv-scheduler.service.spec.ts (7 Tests),
  dkv.service.spec.ts Tests 6/7 umgestellt
- Klassifikation: dkv.service.ts/dkvModuleConfig system-gebunden, Header
  mit fuenfter Erkennungsform und viertem Stand-Wert
- Baseline: 63 Dateien / 1051 Tests, tsc 0, Werkzeug 216

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018N9CD3ebPKm1b32bPpBknY
2026-09-14 11:32:54 +02:00
schalli 02016e19eb docs(quick-260914-eym): Plan fuer Etappe 3c, Systemkontext fuer die Hintergrunddienste (WINDOWS #21, #30)
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018N9CD3ebPKm1b32bPpBknY
2026-09-14 11:15:13 +02:00