docs(quick-260907-fgv): SUMMARY fuer Tasks 1+2, Task 3 (Browser-Abnahme) offen

Dokumentiert die uebernommenen/ausgelassenen Lieferdateien, die Begruendung
fuer Text- statt Bild-Schriftzug, die Konturloesung der dunklen Platte, die
Zusammenfuehrung des Gelbwerts sowie zwei waehrend Task 2 automatisch
behobene Deviationen. Status halted, weil Task 3
(checkpoint:human-verify) absichtlich nicht ausgefuehrt wurde.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01K5jtbGzC5Sf9npJ3JCjKhq
This commit is contained in:
2026-09-07 11:27:35 +02:00
parent c4cc05a942
commit 83e8cedcd4
@@ -0,0 +1,196 @@
---
phase: quick-260907-fgv
plan: 01
subsystem: ui
tags: [branding, nextjs, app-router, next-intl, tailwind, vitest, favicon]
requires: []
provides:
- Zentrale Bildmarken-Komponente TesseraLogo (mark/horizontal/stacked) fuer alle Marken-Stellen der Oberflaeche
- brand.ts als einzige Markenfarben-Quelle im Web-Quellcode (BRAND_YELLOW, BRAND_OLIVE, BRAND_PLATE)
- Dateibasierte Next.js-Icon-Metadaten (icon.svg, apple-icon.png) fuer den Browser-Tab
- common.brand.logoAlt in de.json/en.json mit Schluesselparitaets-Test
affects: [branding, login, reset-password, account-settings, header, sidebar]
actuals:
tokens: 4931
tasks: 2
commits: 2
plan_head_before: 17a8355
tech-stack:
added: []
patterns:
- "Markenfarben ausschliesslich als benannte TypeScript-Konstanten (nicht als CSS-Variable), damit sowohl JSX-Fuellwerte als auch ein <input type=\"color\">-Vorgabewert dieselbe Quelle lesen koennen"
- "Bildmarke als handgesetztes JSX-SVG statt eingebetteter Fremd-Datei -- verhindert jede Form von dangerouslySetInnerHTML fuer Lieferanten-Content (T-FGV-01)"
- "Schriftzug ohne eigene Textfarben-Klasse: er erbt die Vordergrundfarbe ueber normale CSS-Kaskade vom naechsten Vorfahren (body text-foreground im Normalfall, text-gray-900 auf dem gelben Anmelde-Panel) statt uber sich gegenseitig ueberschreibende Tailwind-Utilities gleicher Spezifitaet"
key-files:
created:
- apps/web/src/app/icon.svg
- apps/web/src/app/apple-icon.png
- apps/web/src/components/brand/brand.ts
- apps/web/src/components/brand/tessera-logo.tsx
- apps/web/src/components/brand/tessera-logo.test.tsx
modified:
- apps/web/src/messages/de.json
- apps/web/src/messages/en.json
- apps/web/src/components/layout/header.tsx
- apps/web/src/components/layout/sidebar.tsx
- apps/web/src/components/layout/sidebar.test.tsx
- apps/web/src/app/(auth)/login/page.tsx
- apps/web/src/app/(auth)/reset-password/page.tsx
- apps/web/src/app/(auth)/reset-password/[token]/page.tsx
- apps/web/src/components/settings/account-settings-form.tsx
key-decisions:
- "Von den sechs gelieferten Dateien wurden nur favicon.svg (-> icon.svg) und apple-touch-icon.png (-> apple-icon.png) ins Repository uebernommen. tessera-logo.svg entfaellt, weil cmp sie byteidentisch zu favicon.svg ausweist. tessera-logo-schriftzug.svg entfaellt, weil ihre Textfarbe zweimal fest eingebacken ist (im dunklen Erscheinungsbild unsichtbar) UND weil sie die nicht geladene Schriftart Archivo voraussetzt -- die Anwendung laedt ausschliesslich Inter. favicon-16.png/favicon-32.png entfallen, weil jeder unterstuetzte Browser SVG-Favicons zeigt. tessera-logo-512.png entfaellt, weil kein Web-App-Manifest existiert, das sie braeuchte."
- "Der Schriftzug ist echter HTML-Text aus common.appName, keine Bilddatei -- er erbt automatisch die richtige Farbe, bricht nie um und bleibt uebersetzbar."
- "Die dunkle Grundplatte bekommt im dunklen Erscheinungsbild eine halbtransparente helle Haarlinie (Tailwind dark:stroke-white/25), weil sie sonst mit dem fast identischen dunklen Anwendungshintergrund verschmelzen wuerde. Ueber plateOutline={false} ist die Kontur auf dem immer-gelben Anmelde-Panel abgeschaltet, wo sie falsch waere."
- "Der Gelbwert der Marke steht jetzt an genau einer Stelle (brand.ts:BRAND_YELLOW). Anmelde-Panel und der Vorgabewert der persoenlichen Akzentfarbe lesen ihn von dort. Der Token --primary in globals.css bleibt bewusst unberuehrt -- er ist rechnerisch ein anderer Ton und steuert Schaltflaechen/Fokusringe/Aktivmarkierungen der gesamten Anwendung; ihn auf den Markenwert zu ziehen waere eine Umfaerbung, die nicht Teil dieser Aufgabe ist."
- "Rule 1 (Bugfix waehrend Task 2 entdeckt): TesseraLogo setzte in Task 1 noch eine feste text-foreground-Klasse auf den Schriftzug. Auf dem immer-gelben Anmelde-Panel (Task 2) haette das im dunklen Erscheinungsbild helle Schrift auf Gelb erzeugt -- kaum lesbar. Behoben, indem der Schriftzug gar keine eigene Farb-Klasse mehr setzt und stattdessen per CSS-Vererbung die Farbe des umgebenden Containers uebernimmt (body text-foreground normalerweise, text-gray-900 auf dem Anmelde-Panel)."
requirements-completed: [QUICK-260907-FGV]
coverage:
- id: D1
description: "Icon-Dateien fuer den Browser-Tab (icon.svg, apple-icon.png) byteidentisch zur Lieferung unter src/app/"
requirement: "QUICK-260907-FGV"
verification:
- kind: other
ref: "cmp user-files/logo/favicon.svg apps/web/src/app/icon.svg && cmp user-files/logo/apple-touch-icon.png apps/web/src/app/apple-icon.png"
status: pass
human_judgment: false
- id: D2
description: "brand.ts als einzige Markenfarben-Quelle; Gelbwert kommt im Web-Quellcode genau einmal vor"
requirement: "QUICK-260907-FGV"
verification:
- kind: other
ref: "grep -rl 'ffed00' apps/web/src --include='*.ts' --include='*.tsx' -> nur brand.ts"
status: pass
human_judgment: false
- id: D3
description: "TesseraLogo-Komponente mit drei Varianten (mark/horizontal/stacked), dunkle Kontur nur im dunklen Erscheinungsbild und nur wenn plateOutline nicht deaktiviert ist"
requirement: "QUICK-260907-FGV"
verification:
- kind: unit
ref: "apps/web/src/components/brand/tessera-logo.test.tsx (8 Tests)"
status: pass
human_judgment: false
- id: D4
description: "common.brand.logoAlt in de.json und en.json, Schluesselparitaet abgesichert"
requirement: "QUICK-260907-FGV"
verification:
- kind: unit
ref: "apps/web/src/components/brand/tessera-logo.test.tsx#common.brand i18n namespace — de/en key parity"
status: pass
human_judgment: false
- id: D5
description: "Alle sechs Marken-Stellen (Kopfleiste, Seitenleisten-Schublade, Anmeldeseite breit+schmal, beide Passwort-Seiten) ziehen TesseraLogo; Platzhalter-Icon und Hand-Schriftzug entfernt"
requirement: "QUICK-260907-FGV"
verification:
- kind: other
ref: "grep -q TesseraLogo je Datei + grep font-extrabold in (auth) liefert 0 Treffer"
status: pass
human_judgment: false
- id: D6
description: "Visuelle Abnahme im Browser (Task 3, checkpoint:human-verify) -- beide Erscheinungsbilder, sieben Stellen, plus zwei Gestaltungsfragen (Schriftzugfarbe, Reihenfolge auf dem Anmelde-Panel)"
verification: []
human_judgment: true
rationale: "Kontrast, Kontur-Sichtbarkeit und die zwei zur Freigabe gestellten Gestaltungsaenderungen lassen sich nur visuell beurteilen. Task 3 ist absichtlich noch nicht ausgefuehrt -- der Orchestrator uebernimmt Docker-Neubau und Browser-Pruefung."
duration: 35min
completed: 2026-09-07
status: halted
---
# Phase quick-260907-fgv Plan 01: Tessera-Logo und Favicon fest einbauen — Summary
**TesseraLogo-Komponente und brand.ts eingefuehrt, sechs Marken-Stellen umgestellt, Icon-Dateien byteidentisch uebernommen — Task 3 (Browser-Abnahme) steht noch aus.**
## Performance
- **Duration:** ca. 35 min
- **Tasks:** 2 von 3 (Task 3 ist `checkpoint:human-verify`, bewusst nicht ausgefuehrt)
- **Files modified:** 14 (5 neu, 9 geaendert)
## Accomplishments
- Gelieferte `favicon.svg` und `apple-touch-icon.png` byteidentisch nach `apps/web/src/app/icon.svg` bzw. `apps/web/src/app/apple-icon.png` kopiert; die uebrigen vier gelieferten Dateien bleiben mit dokumentierter Begruendung ausserhalb des Repositories.
- `apps/web/src/components/brand/brand.ts` angelegt: die drei Markenfarben (`BRAND_YELLOW`, `BRAND_OLIVE`, `BRAND_PLATE`) stehen jetzt an genau einer Stelle im Web-Quellcode.
- `TesseraLogo`-Komponente gebaut (Varianten `mark`/`horizontal`/`stacked`), als handgesetztes JSX-SVG ohne `dangerouslySetInnerHTML`, mit schaltbarer dunkler Kontur der Grundplatte (`plateOutline`).
- Alle sechs Marken-Stellen umgestellt: Kopfleiste, Seitenleisten-Schublade, Anmeldeseite (breite und schmale Ansicht), beide Passwort-Seiten. Der handgezeichnete Vier-Quadrate-Platzhalter auf der Anmeldeseite ist entfernt.
- `common.brand.logoAlt` in `de.json` und `en.json` ergaenzt, Schluesselparitaet per Test abgesichert.
- Vollstaendige Web-Testsuite (37 Testdateien, 221 Tests) und Typpruefung sind gruen.
## Warum der Schriftzug Text ist, kein Bild
Zwei unabhaengige Gruende. Erstens die Farbe: `tessera-logo-schriftzug.svg` haelt die Textfarbe zweimal fest als dunklen Ton — im dunklen Erscheinungsbild der Anwendung waere der Schriftzug unsichtbar. Zweitens die Schrift: die Datei verlangt Archivo in Schnitt 900, die Anwendung laedt aber ausschliesslich Inter (`--font-sans` in `globals.css`) — der Browser wuerde eine Ersatzschrift mit anderen Buchstabenbreiten in einen starr fixierten Zeichenbereich zwingen. "Tessera" als normaler HTML-Text aus `common.appName` loest beide Probleme: er erbt die richtige Farbe, bricht nie um, bleibt uebersetzbar.
## Kontur der dunklen Platte
Nachgerechnet: die Plattenfarbe (`#1a1a1a`) und der dunkle Anwendungshintergrund (`oklch(0.23 0.01 260)` = `#1a1d22`) sind praktisch derselbe Ton — ohne Gegenmassnahme wuerde die Platte im dunklen Erscheinungsbild verschwinden und die fuenf Kacheln wuerden frei schweben. Deshalb bekommt die Platte ueber eine `dark:stroke-white/25`-Utility eine halbtransparente helle Haarlinie, die im hellen Erscheinungsbild unsichtbar bleibt (`stroke-transparent`). Auf dem gelben Anmelde-Panel ist die Kontur ueber `plateOutline={false}` abgeschaltet, weil dieses Panel unabhaengig vom Erscheinungsbild immer gelb ist und dort ohnehin maximaler Kontrast besteht.
## Gelbwert: eine Quelle, `--primary` bewusst unberuehrt
`brand.ts:BRAND_YELLOW` ist jetzt die einzige Stelle im Web-Quellcode, an der der Markengelbwert notiert steht. Das Anmelde-Panel (Inline-`style`) und der Vorgabewert der persoenlichen Akzentfarbe (`account-settings-form.tsx:DEFAULT_ACCENT`) lesen ihn von dort. Der bestehende Design-Token `--primary` in `globals.css` bleibt unveraendert — er ist rechnerisch ein leicht anderer Ton und steuert Schaltflaechen, Fokusringe und Aktivmarkierungen der gesamten Anwendung. Ihn auf den Markenwert zu ziehen waere eine Umfaerbung der gesamten Oberflaeche und war nicht Teil dieser Aufgabe.
## Task Commits
1. **Task 1: Markenbausteine — Icon-Dateien, Farbkonstanten, TesseraLogo-Komponente, i18n-Schluessel** — `49d3df4` (feat)
2. **Task 2: Alle sechs Marken-Stellen auf die Komponente umstellen und den Gelbwert zusammenfuehren** — `c4cc05a` (feat)
Task 3 (`checkpoint:human-verify`, Browser-Abnahme in beiden Erscheinungsbildern) ist noch offen — siehe unten.
## Deviations from Plan
### Auto-fixed Issues
**1. [Rule 1 - Bug] Schriftzug-Textfarbe entfernt statt fest gesetzt**
- **Found during:** Task 2 (Einbau auf dem gelben Anmelde-Panel)
- **Issue:** `tessera-logo.tsx` setzte in Task 1 noch `text-foreground` direkt auf den Schriftzug. Auf dem immer-gelben Anmelde-Panel haette das im dunklen Erscheinungsbild helle Schrift auf gelbem Grund erzeugt (kaum lesbar), weil eine explizite Tailwind-Farbklasse nicht zuverlaessig von einer Vorfahren-Klasse gleicher Spezifitaet ueberschrieben werden kann.
- **Fix:** Der Schriftzug setzt keine eigene Textfarben-Klasse mehr und erbt die Farbe stattdessen per normaler CSS-Kaskade vom umgebenden Container. Auf normalen Seiten ist das `text-foreground` von `<body>` (`layout.tsx`), auf dem Anmelde-Panel das explizit gesetzte `text-gray-900` am inneren Container.
- **Files modified:** `apps/web/src/components/brand/tessera-logo.tsx`
- **Commit:** `c4cc05a`
**2. [Rule 1 - Bug] Ungenutzte Variable `tCommon` in sidebar.tsx entfernt**
- **Found during:** Task 2
- **Issue:** Nach dem Ersetzen des Schriftzugs durch `TesseraLogo` war `const tCommon = useTranslations('common');` in `sidebar.tsx` nicht mehr referenziert.
- **Fix:** Zeile entfernt.
- **Files modified:** `apps/web/src/components/layout/sidebar.tsx`
- **Commit:** `c4cc05a`
### Bewusst ausgelassen (per Ausfuehrungs-Anweisung)
Der Docker-Neubau (`docker compose build web && docker compose up -d --force-recreate web`) und der `curl`-Health-Check am Ende des Task-2-Verify-Blocks wurden NICHT ausgefuehrt — die Ausfuehrungs-Anweisung fuer diesen Lauf untersagt es ausdruecklich ("Do NOT rebuild Docker images — the orchestrator does that"). Alle anderen Verify-Schritte (Byte-Vergleich der Icons, vollstaendige Testsuite, Typpruefung, grep-Checks) wurden real ausgefuehrt und sind gruen.
## Known Stubs
Keine.
## Threat Flags
Keine neue, im Plan nicht bereits erfasste Angriffsflaeche. Die drei im Plan gefuehrten Bedrohungen (T-FGV-01 Tampering ueber `tessera-logo.tsx`, T-FGV-02 Information Disclosure ueber `icon.svg`, T-FGV-03 Tampering ueber `user-files/logo/`) sind wie geplant behandelt: kein `dangerouslySetInnerHTML`, keine Laufzeit-Dateilesung, Byte-Vergleich im Verify-Schritt bestanden.
## Ausstehend: Task 3 (Browser-Abnahme)
Task 3 ist ein `checkpoint:human-verify` mit `gate="blocking-human"` und wurde absichtlich nicht ausgefuehrt. Der Orchestrator baut das lokale Web-Abbild neu, startet den Container und fuehrt die Browser-Pruefung durch. Zwei Gestaltungsfragen stehen dabei zur Freigabe oder Zurueckweisung:
1. **Schriftzugfarbe:** "Tessera" ist in Kopfleiste und Schublade jetzt dunkel (bzw. hell im dunklen Erscheinungsbild) statt wie bisher gelb. Passt das, oder soll das bisherige Gelb zurueck?
2. **Reihenfolge auf dem Anmelde-Panel:** Die Bildmarke steht jetzt oben auf dem gelben Panel statt wie bisher unten unter dem Text. Passt diese Reihenfolge, oder soll die Marke wieder unter den Text?
Die Entscheidung zu beiden Fragen ist in dieser SUMMARY noch nicht dokumentiert, weil die Abnahme zum Zeitpunkt der Erstellung noch nicht stattgefunden hat.
## Vermerkter Backlog-Punkt (nicht in diesem Plan gebaut)
"Administrator kann das Erscheinungsbild je Mandant anpassen — eigenes Logo hochladen, Markenfarben setzen." Ansatzpunkt ist `apps/web/src/components/brand/`; die Oberflaeche zieht das Logo bereits ausschliesslich von dort. Dieser Punkt ist vom Orchestrator einzureichen.
## Self-Check: PASSED
- `apps/web/src/app/icon.svg` — FOUND, byteidentisch zu `user-files/logo/favicon.svg`
- `apps/web/src/app/apple-icon.png` — FOUND, byteidentisch zu `user-files/logo/apple-touch-icon.png`
- `apps/web/src/components/brand/brand.ts` — FOUND
- `apps/web/src/components/brand/tessera-logo.tsx` — FOUND
- `apps/web/src/components/brand/tessera-logo.test.tsx` — FOUND
- Commit `49d3df4` — FOUND in `git log`
- Commit `c4cc05a` — FOUND in `git log`