Files

29 KiB

quick_id, slug, date, status, relates_to, phase, plan, type, wave, depends_on, files_modified, autonomous, requirements, estimate, must_haves
quick_id slug date status relates_to phase plan type wave depends_on files_modified autonomous requirements estimate must_haves
260907-fgv tessera-logo-und-favicon-fest-einbauen-b 2026-09-07 planned 01-foundation-portal-shell quick-260907-fgv 01 execute 1
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
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
false
QUICK-260907-FGV
tokens raw_tokens tasks confidence
55000 55000 3 low
truths artifacts key_links
Der Browser-Tab zeigt die Bildmarke statt des Standard-Globus — in hellem und in dunklem Erscheinungsbild.
Kopfleiste, Seitenleisten-Schublade, Anmeldeseite (breite und schmale Ansicht) und beide Passwort-Seiten zeigen dieselbe Bildmarke aus derselben Komponente.
Der Schriftzug bleibt in beiden Erscheinungsbildern lesbar, weil er echter HTML-Text in der Vordergrundfarbe der Oberflaeche ist und kein eingebetteter Text mit fest eingebackener Farbe.
Die dunkle Platte der Bildmarke hebt sich im dunklen Erscheinungsbild vom Hintergrund ab, weil sie dort eine helle Haarlinie als Kontur bekommt; im hellen Erscheinungsbild ist die Kontur unsichtbar.
Auf dem gelben Anmelde-Panel bleibt die Bildmarke ohne Kontur, weil dieses Panel unabhaengig vom Erscheinungsbild immer eine helle Flaeche ist.
Der Gelbwert der Marke ist im gesamten Web-Quellcode genau einmal notiert; Anmelde-Panel und Bildmarke lesen ihn aus dieser einen Konstante.
Das gelieferte Doppel favicon.svg / tessera-logo.svg wird nur einmal in das Repository uebernommen — der Byte-Vergleich hat beide als identisch nachgewiesen.
Es entsteht keine Hochlade-Maske, kein Einstellungsfeld, keine Datenbankspalte und keine Mandantenabfrage fuer das Logo.
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
BRAND_YELLOW in brand.ts -> Signalkachel der Bildmarke UND Hintergrund des Anmelde-Panels UND Vorgabewert der persoenlichen Akzentfarbe: eine Konstante, drei Nutzer
TesseraLogo -> header.tsx, sidebar.tsx, login/page.tsx (zweimal), reset-password/page.tsx, reset-password/[token]/page.tsx: die eine Stelle, an der eine spaetere Mandanten-Marke ansetzt
common.brand.logoAlt in de.json UND en.json -> aria-label der Bildmarke; fehlt der Schluessel in einer Sprache, liest ein Screenreader den Schluesselnamen vor
apps/web/src/app/icon.svg -> dateibasierte Metadaten von Next.js: die Datei MUSS unter src/app/ liegen, in public/ waere sie wirkungslos, weil layout.tsx kein icons-Feld setzt
Das gelieferte Tessera-Logo und das Favicon fest in die Oberflaeche einbauen — und zwar so, dass die spaetere Wunschfunktion "Administrator gestaltet das Erscheinungsbild je Mandant" genau eine Datei anfassen muss.

Purpose: Die Plattform traegt bis heute an jeder Marken-Stelle nur das Wort "Tessera" als Text, dazu auf der Anmeldeseite ein handgezeichnetes Vier-Quadrate-Platzhalter-Icon. Das gelieferte Logo ersetzt beides.

Output: Eine zentrale Komponente TesseraLogo, eine Farbkonstanten-Datei, zwei Icon-Dateien fuer den Browser-Tab, sechs umgestellte Verwendungsstellen.

Die gelieferten Dateien und was mit ihnen geschieht

Der Ordner user-files/logo/ ist ueber .gitignore:32 vom Repository ausgeschlossen. Nichts darf von dort aus referenziert werden — was gebraucht wird, wird kopiert.

Datei Verwendung
favicon.svg wird nach apps/web/src/app/icon.svg kopiert (Browser-Tab)
tessera-logo.svg wird NICHT kopiert — diff weist sie als byteweise identisch zu favicon.svg aus
apple-touch-icon.png wird nach apps/web/src/app/apple-icon.png kopiert
tessera-logo-schriftzug.svg wird NICHT kopiert — Begruendung unten
favicon-16.png, favicon-32.png werden NICHT kopiert — jeder von Tessera unterstuetzte Browser zeigt SVG-Favicons
tessera-logo-512.png wird NICHT kopiert — es gibt keine Web-App-Manifest-Datei, die sie braeuchte

Vier Entscheidungen, die vorab getroffen wurden

1. Der Schriftzug wird nicht als Bild ausgeliefert, sondern als echter Text neben der Bildmarke gesetzt. Zwei unabhaengige Gruende. Erstens die Farbe: in tessera-logo-schriftzug.svg steht die Textfarbe zweimal fest eingebacken als dunkler Ton; auf dem dunklen Erscheinungsbild der Anwendung waere der Schriftzug unsichtbar. Zweitens die Schrift: die Datei verlangt die Schriftart Archivo in Schnitt 900 — die Anwendung laedt ueber --font-sans in globals.css:33 ausschliesslich Inter, Archivo ist nirgends eingebunden. Der Browser wuerde also ohnehin eine andere Schrift einsetzen, mit anderen Buchstabenbreiten, in einem starr auf 420x100 festgelegten Zeichenbereich — der Schriftzug wuerde je nach Rechner ueberlaufen oder verloren in der Flaeche stehen. Beides faellt weg, wenn "Tessera" normaler HTML-Text in der Hausschrift ist: er erbt die Vordergrundfarbe, er bricht nie, und er kommt aus common.appName, ist also uebersetzbar. Die Alternative — je eine helle und eine dunkle Variante der Bilddatei ausliefern — waere zwei Dateien, ein Theme-Hook und ein Umschaltflackern beim Seitenaufbau; sie loest das Schriftproblem ausserdem gar nicht.

2. Die dunkle Platte der Bildmarke bekommt im dunklen Erscheinungsbild eine Kontur. Nachgerechnet, nicht vermutet: die Platte der Marke ist ein sehr dunkles Grau, der dunkle Anwendungshintergrund oklch(0.23 0.01 260) entspricht #1a1d22, die dunkle Seitenleiste oklch(0.20 0.01 260) entspricht #13161b. Platte und Hintergrund sind damit praktisch derselbe Ton — die Platte verschwindet, die fuenf Kacheln wuerden frei schweben. Die Marke selbst bleibt trotzdem unangetastet: die Platte erhaelt lediglich ueber eine dark:-Utility-Klasse eine halbtransparente helle Haarlinie als Kontur. Im hellen Erscheinungsbild ist die Kontur durchsichtig, dort aendert sich also nichts. Das ist dieselbe Behandlung, die die Anwendung ohnehin fuer dunkle Flaechen auf dunklem Grund verwendet. Auf dem gelben Anmelde-Panel wird die Kontur per Eigenschaft abgeschaltet, weil dieses Panel unabhaengig vom gewaehlten Erscheinungsbild gelb bleibt und die Platte dort von sich aus maximalen Kontrast hat. Fuer die Icon-Datei im Browser-Tab bleibt die Platte ohne Kontur: die Tab-Leiste ist keine Flaeche dieser Anwendung, und die Wiedererkennung traegt dort ohnehin die helle Signalkachel.

3. Der Gelbwert steht kuenftig genau einmal im Quellcode. Er kommt heute dreimal vor: als Hintergrund-Utility des Anmelde-Panels, im Kopfkommentar derselben Datei und als Vorgabewert der persoenlichen Akzentfarbe in account-settings-form.tsx:14. Kuenftig steht er nur noch in apps/web/src/components/brand/brand.ts; die drei Stellen lesen ihn von dort. Bewusst KEINE neue CSS-Variable in globals.css: die Auswahl der Akzentfarbe laeuft ueber ein <input type="color">, das zwingend einen echten Farbwert braucht und mit einer CSS-Variablen nichts anfangen kann. Eine TypeScript-Konstante bedient alle drei Stellen, eine CSS-Variable koennte es nicht. Der vorhandene Token --primary bleibt unberuehrt: er ist ein rechnerisch leicht abweichender Ton (#fbe405 gegen den Gelbwert der Marke) und steuert Schaltflaechen, Fokusringe und Aktivmarkierungen — ihn auf den Markenwert zu ziehen waere eine Umfaerbung der gesamten Anwendung und ist nicht Teil dieser Aufgabe.

4. Der Browser-Tab wird ueber dateibasierte Metadaten verdrahtet, nicht ueber metadata.icons. Next.js liegt hier in Version 15.5.19 mit App Router vor; eine Datei src/app/icon.svg erzeugt den <link rel="icon">-Eintrag von selbst. Damit bleibt layout.tsx unberuehrt — weniger Code, weniger Fehlerquellen. Das leere Verzeichnis apps/web/public/ bleibt leer; dort abgelegte Icons wuerden ohne zusaetzlichen Eintrag in layout.tsx nicht gefunden.

Zwei sichtbare Aenderungen, die ueber "Logo einbauen" hinausgehen und deshalb ausdruecklich zur Abnahme gestellt werden

  • Der Schriftzug ist kuenftig nicht mehr gelb. Kopfleiste und Seitenleiste setzen "Tessera" heute in der Primaerfarbe, also Gelb auf weissem Grund — schwer lesbar. Das gelieferte Logo setzt den Schriftzug dunkel. Die Komponente folgt dem Logo und nutzt die Vordergrundfarbe der Oberflaeche.
  • Auf dem gelben Anmelde-Panel steht die Bildmarke kuenftig OBEN. Heute steht dort Schriftzug, Zeile darunter, Platzhalter-Icon ganz unten. Das gelieferte Logo ist als Bildmarke-zuerst aufgebaut; die Komponente uebernimmt diese Reihenfolge. Der bestehende Werbesatz bleibt unveraendert darunter stehen.

Beides steht im Abnahmeschritt und kann dort zurueckgewiesen werden.

Was ausdruecklich NICHT passiert

Keine Hochlade-Maske, keine Einstellungsseite, kein Datenbankfeld, keine Mandantenabfrage fuer das Logo. Der Wunsch "ein Administrator soll das Erscheinungsbild je Mandant anpassen koennen" wird als eigener Backlog-Punkt festgehalten und vom Orchestrator eingereicht — nicht in diesem Plan gebaut.

<execution_context> @/.claude/gsd-core/workflows/execute-plan.md @/.claude/gsd-core/templates/summary.md </execution_context>

@CLAUDE.md @.planning/STATE.md @apps/web/src/app/layout.tsx @apps/web/src/app/globals.css @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/components/settings/account-settings-form.tsx @apps/web/src/messages/de.json Task 1: Markenbausteine — Icon-Dateien, Farbkonstanten, TesseraLogo-Komponente, i18n-Schluessel 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, apps/web/src/messages/de.json, apps/web/src/messages/en.json - Variante `mark`: es entsteht ein Element mit der Rolle `img`, dessen zugaenglicher Name aus dem Uebersetzungsschluessel `common.brand.logoAlt` stammt. Ein sichtbarer Schriftzug ist NICHT vorhanden. - Variante `horizontal`: Rolle `img` vorhanden UND der Schriftzug aus `common.appName` ist als Text sichtbar. - Variante `stacked`: Rolle `img` vorhanden UND der Schriftzug ist sichtbar. - Die Platte traegt bei Vorgabewerten eine Klasse, die die Kontur nur im dunklen Erscheinungsbild einschaltet; mit `plateOutline={false}` fehlt diese Klasse. - Die Grundflaeche der Bildmarke enthaelt fuenf Kacheln, davon genau eine mit dem Gelbwert der Marke und genau eine mit einer Drehung. - Sowohl `de.json` als auch `en.json` definieren `common.brand.logoAlt` — der Test liest beide Dateien und vergleicht die Schluesselmenge unterhalb von `common.brand`, damit keine Sprache spaeter allein ergaenzt werden kann. Kopiere `user-files/logo/favicon.svg` unveraendert nach `apps/web/src/app/icon.svg` und `user-files/logo/apple-touch-icon.png` unveraendert nach `apps/web/src/app/apple-icon.png`. Nur diese beiden Dateien — die uebrigen gelieferten Dateien bleiben ausserhalb des Repositories, `tessera-logo.svg` ist nachweislich byteweise identisch zu `favicon.svg` und wuerde eine zweite Kopie desselben Inhalts erzeugen. Beide Zieldateien MUESSEN unter `src/app/` liegen, damit Next.js sie als dateibasierte Metadaten erkennt; `layout.tsx` wird nicht angefasst.

Lege apps/web/src/components/brand/brand.ts an. Die Datei exportiert drei benannte Konstanten fuer die drei Farben der Marke: den Gelbwert der gedrehten Signalkachel als BRAND_YELLOW, den Olivton der vier uebrigen Kacheln als BRAND_OLIVE und die Farbe der abgerundeten Grundplatte als BRAND_PLATE. Die Werte werden NICHT aus dieser Beschreibung abgeschrieben, sondern beim Umsetzen direkt aus user-files/logo/favicon.svg uebernommen — dort steht die Plattenfarbe am rect mit rx="14", der Olivton an den vier achsenparallelen Kacheln und der Gelbwert an der Kachel mit transform="rotate(...)". Ein kurzer Dateikommentar haelt fest, dass dies die einzige Stelle im Web-Quellcode ist, an der eine Markenfarbe notiert wird, und dass eine spaetere mandantenspezifische Gestaltung hier ansetzt. Schreibe in diesen Kommentar keinen weiteren Farbwert hinein — die Konstanten tragen die Werte, der Kommentar beschreibt nur ihren Zweck.

Lege apps/web/src/components/brand/tessera-logo.tsx an, als 'use client'-Komponente, weil sie useTranslations aus next-intl benutzt. Exportiere TesseraLogo mit den Eigenschaften variant ('mark' | 'horizontal' | 'stacked', Vorgabe 'horizontal'), size (Kantenlaenge der Bildmarke in Pixeln, Vorgabe 32), plateOutline (Vorgabe true), className und wordmarkClassName.

Die Bildmarke wird als JSX-SVG von Hand gesetzt: viewBox="0 0 72 72", width/height aus size, role="img" und aria-label aus t('brand.logoAlt') bei useTranslations('common'). Geometrie und Reihenfolge der sechs Rechtecke werden 1:1 aus user-files/logo/favicon.svg uebernommen — Position, Groesse, Eckenradius und die Drehung der Signalkachel unveraendert. Die Fuellfarben kommen aus den drei Konstanten, nicht als Zahlenwerte im JSX. Setze das SVG als echte JSX-Elemente zusammen; verwende ausdruecklich NICHT dangerouslySetInnerHTML und lies die Datei auch nicht zur Laufzeit ein.

Die Grundplatte erhaelt zusaetzlich strokeWidth={2} und, sofern plateOutline wahr ist, eine Klassenkombination, die die Kontur im hellen Erscheinungsbild durchsichtig laesst und im dunklen auf eine halbtransparente weisse Linie schaltet (Tailwind-Utilities stroke-transparent und die zugehoerige dark:-Variante, etwa mit rund 25 Prozent Deckung). Ist plateOutline falsch, bleibt es bei der durchsichtigen Kontur ohne dark:-Variante. So bleibt die Umschaltung reines CSS — kein Theme-Hook, kein Flackern beim Seitenaufbau.

Die Variante mark liefert nur das SVG. horizontal liefert einen inline-flex-Container mit Bildmarke und daneben dem Schriftzug aus t('appName'), gesetzt in halbfett, leicht negativer Laufweite und in der Vordergrundfarbe der Oberflaeche (nicht in der Primaerfarbe); wordmarkClassName wird an das Schriftzug-Element angehaengt, damit aufrufende Stellen die Farbe ueberschreiben koennen. stacked liefert dieselben beiden Bausteine als zentrierte Spalte, Bildmarke oben, Schriftzug darunter deutlich groesser. inline-flex ist Absicht: die aufrufenden Seiten zentrieren ueber text-center des Elternelements, ein Block-Element wuerde dort links kleben.

Ergaenze in de.json und en.json unterhalb von common das Objekt brand mit dem Schluessel logoAlt ("Tessera Logo" beziehungsweise "Tessera logo"). Beide Dateien bekommen exakt denselben Schluesselbaum.

Schreibe apps/web/src/components/brand/tessera-logo.test.tsx nach dem Muster von sidebar.test.tsx: useTranslations aus next-intl per vi.mock ersetzen, Rueckgabe ueber eine flache Zuordnung mit appName und 'brand.logoAlt'. Decke die unter behavior genannten Faelle ab und lies fuer die Sprachparitaet de.json und en.json direkt als Modul ein, so wie es src/messages/tenderRadar-parity.spec.ts vormacht. 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 && pnpm --filter @tessera/web exec vitest run src/components/brand && pnpm --filter @tessera/web type-check Die beiden Icon-Dateien liegen byteidentisch zur Lieferung unter src/app/. TesseraLogo rendert in allen drei Varianten, der Test ist gruen, beide Sprachdateien tragen den neuen Schluessel, die Typpruefung ist sauber.

Task 2: Alle sechs Marken-Stellen auf die Komponente umstellen und den Gelbwert zusammenfuehren 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 - `sidebar.test.tsx` bleibt gruen: die Uebersetzungs-Attrappe kennt zusaetzlich den Schluessel `brand.logoAlt` im Bereich `common`, sodass die Bildmarke in der mobilen Schublade einen echten zugaenglichen Namen traegt statt des Schluesselnamens. - Die vorhandenen Aussagen von `sidebar.test.tsx` werden nicht abgeschwaecht und keine geloescht. Ersetze in `header.tsx` das Schriftzug-Element neben der Menue-Schaltflaeche durch ``. Der umgebende Flex-Container mit `gap-3` bleibt unveraendert.

Ersetze in sidebar.tsx das Schriftzug-Element in der Kopfzeile der mobilen Schublade durch <TesseraLogo variant="horizontal" size={28} />. Die Schliessen-Schaltflaeche rechts daneben bleibt unveraendert. In sidebar.test.tsx ergaenze die Uebersetzungs-Attrappe im Bereich common um den Eintrag 'brand.logoAlt' mit einem sprechenden Wert; die Attrappe arbeitet bereits mit punktierten Schluesseln.

Baue in login/page.tsx die linke, gelbe Spalte um. Der Gelbwert steht dort heute als Hintergrund-Utility in eckigen Klammern und ein zweites Mal im Kopfkommentar der Datei. Beide Vorkommen verschwinden: das Utility wird durch ein Inline-style mit backgroundColor: BRAND_YELLOW ersetzt (Import aus @/components/brand/brand), alle uebrigen Klassen der Spalte bleiben stehen; der Kopfkommentar wird ohne Nennung eines Farbwerts neu formuliert und verweist stattdessen auf die Konstante. Setze auf derselben Spalte zusaetzlich className="text-gray-900" an den inneren, zentrierten Container, damit der Schriftzug die dunkle Schrift des Panels erbt.

Innerhalb der gelben Spalte entfaellt die Schriftzug-Ueberschrift ersatzlos, und ebenso ersatzlos entfaellt der handgezeichnete Platzhalter — das ist der <svg>-Block mit den vier gleich grossen Rechtecken im 24er-Koordinatensystem samt seinem mt-4-Wrapper. An ihre Stelle tritt, als erstes Element der Spalte, <TesseraLogo variant="stacked" size={112} plateOutline={false} />. plateOutline={false} ist hier Pflicht: das Panel ist unabhaengig vom Erscheinungsbild immer gelb, eine helle Kontur waere dort falsch. Der bestehende Absatz mit t('branding.tagline') bleibt unveraendert darunter stehen.

In der nur auf schmalen Fenstern sichtbaren Marken-Gruppe derselben Datei entfaellt die Schriftzug-Ueberschrift ebenfalls ersatzlos; an ihre Stelle tritt <TesseraLogo variant="horizontal" size={32} />. Der Container traegt bereits text-center, die Komponente zentriert sich dadurch von selbst. Der Absatz mit dem Werbesatz bleibt.

Ersetze in reset-password/page.tsx und in reset-password/[token]/page.tsx jeweils die Schriftzug-Ueberschrift ueber der Seitenueberschrift durch <TesseraLogo variant="horizontal" size={32} />. Die jeweils folgende <h2> mit dem Seitentitel bleibt unveraendert — sie ist die eigentliche Ueberschrift der Seite und darf nicht mitentfernt werden.

Ersetze in account-settings-form.tsx den Rumpf der lokalen Konstante DEFAULT_ACCENT durch den aus @/components/brand/brand importierten BRAND_YELLOW. Der Name DEFAULT_ACCENT bleibt bestehen, damit die drei bestehenden Verwendungsstellen unveraendert bleiben; nur der Wert kommt jetzt aus der Markendatei. set -e; test "$(grep -rl 'ffed00' apps/web/src --include='.ts' --include='.tsx')" = 'apps/web/src/components/brand/brand.ts'; test "$(grep -rl 'font-extrabold' 'apps/web/src/app/(auth)' --include='*.tsx' | wc -l)" -eq 0; test "$(grep -c 'width="7" height="7"' 'apps/web/src/app/(auth)/login/page.tsx' || true)" -eq 0; for f in apps/web/src/components/layout/header.tsx apps/web/src/components/layout/sidebar.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'; do grep -q 'TesseraLogo' "$f"; done; pnpm --filter @tessera/web exec vitest run; pnpm --filter @tessera/web type-check; docker compose build web && docker compose up -d --force-recreate web; for i in $(seq 1 30); do curl -sf -o /dev/null http://localhost:3000/login && break || sleep 2; done; curl -sf -o /dev/null http://localhost:3000/login Der Gelbwert der Marke steht im gesamten Web-Quellcode nur noch in brand.ts. In den Anmelde- und Passwort-Seiten steht kein von Hand gesetzter Schriftzug mehr und kein Platzhalter-Icon. Alle fuenf Verwendungsstellen ziehen TesseraLogo. Die vollstaendige Web-Testsuite und die Typpruefung sind gruen. Das LOKALE Web-Abbild ist neu gebaut, der Container laeuft mit dem neuen Stand und die Anmeldeseite antwortet — die Abnahme in Task 3 sieht damit garantiert den neuen Code. Der Testserver alpha.tessera.ctl.de wird dabei NICHT angefasst.

Task 3: Abnahme im Browser — beide Erscheinungsbilder, sieben Stellen Das gelieferte Tessera-Logo ist an sechs Stellen der Oberflaeche fest eingebaut und die Icon-Dateien fuer den Browser-Tab liegen im Repository. Alle Stellen ziehen aus einer einzigen Komponente `apps/web/src/components/brand/tessera-logo.tsx`; die Markenfarben stehen ausschliesslich in `apps/web/src/components/brand/brand.ts`. Der handgezeichnete Vier-Quadrate-Platzhalter auf der Anmeldeseite ist entfernt. Der Schriftzug wird als echter Text in der Hausschrift gesetzt, nicht als Bilddatei, damit er in beiden Erscheinungsbildern lesbar bleibt. Task 2 hat das lokale Web-Abbild bereits neu gebaut und den Container ersetzt — unter `http://localhost:3000` laeuft der neue Stand. Der Testserver alpha.tessera.ctl.de wurde nicht angefasst. `http://localhost:3000` oeffnen. Anmeldung mit `admin` / `admin123`; fuer die Nutzersicht stehen `nutzer1` / `Test1234!` und `nutzer2` / `Test1234!` bereit. Das Erscheinungsbild wird ueber den Umschalter rechts in der Kopfleiste gewechselt.

Sollte die Oberflaeche wider Erwarten noch den alten Stand zeigen, hilft docker compose build web && docker compose up -d --force-recreate web — ein blosses up baut nicht neu.

Jeder der folgenden sieben Punkte ist EINMAL im hellen und EINMAL im dunklen Erscheinungsbild anzusehen:

  1. Browser-Tab — im Tab steht die dunkle abgerundete Kachel-Marke, nicht mehr das leere Standard-Blatt. Bei hartnaeckigem alten Symbol den Tab neu laden mit geleertem Zwischenspeicher.
  2. Kopfleiste — Bildmarke links neben dem Schriftzug "Tessera", in einer Zeile, senkrecht mittig zur Zeilenhoehe, nicht abgeschnitten.
  3. Seitenleisten-Schublade — Browserfenster schmal ziehen, bis das Menue-Symbol erscheint, Schublade oeffnen: dieselbe Marke in der Kopfzeile der Schublade, die Schliessen-Schaltflaeche daneben unveraendert erreichbar.
  4. Anmeldeseite, breite Ansicht — abmelden, http://localhost:3000/login, Fenster breit: das gelbe Panel links zeigt oben die Bildmarke, darunter "Tessera", darunter den bekannten Werbesatz. Das handgezeichnete Vier-Quadrate-Symbol ist verschwunden. Das Gelb des Panels ist unveraendert dasselbe wie vorher.
  5. Anmeldeseite, schmale Ansicht — Fenster schmal ziehen: das gelbe Panel entfaellt wie bisher, ueber dem Anmeldeformular steht die Marke einzeilig und mittig.
  6. Passwort-vergessen-Seite — http://localhost:3000/reset-password: Marke oben, darunter unveraendert die Seitenueberschrift und das E-Mail-Feld.
  7. Passwort-neu-setzen-Seite — http://localhost:3000/reset-password/test123 (irgendein Zeichenkettenwert genuegt, die Seite rendert vor der Pruefung): Marke oben, darunter unveraendert Ueberschrift und beide Passwortfelder.

Beim Durchgang im DUNKLEN Erscheinungsbild zusaetzlich pruefen: die dunkle Platte der Bildmarke hebt sich in Kopfleiste, Schublade und auf den Passwort-Seiten durch eine feine helle Kontur vom Hintergrund ab und verschwimmt nicht mit ihm. Auf dem gelben Anmelde- Panel darf diese Kontur NICHT zu sehen sein.

Zwei Aenderungen ausdruecklich zur Freigabe oder Zurueckweisung:

  • Der Schriftzug "Tessera" ist in Kopfleiste und Schublade jetzt dunkel (beziehungsweise hell im dunklen Erscheinungsbild) statt wie bisher gelb. Passt das, oder soll das bisherige Gelb zurueck?
  • Auf dem gelben Anmelde-Panel steht die Bildmarke jetzt oben statt unten. Passt diese Reihenfolge, oder soll die Marke wieder unter den Text? "passt" — wenn alle sieben Punkte in beiden Erscheinungsbildern stimmen und beide Gestaltungsfragen freigegeben sind.

Andernfalls die abweichende Stelle benennen (welcher Punkt, welches Erscheinungsbild, was ist zu sehen) beziehungsweise die gewuenschte Antwort auf die zwei Gestaltungsfragen geben. Beides wird noch in diesem Plan nachgezogen und nicht vertagt.

<threat_model>

Trust Boundaries

Boundary Description
Lieferant -> Repository Die Logo-Dateien stammen von aussen und werden ins Repository uebernommen
Browser -> ausgelieferte Icon-Route Next.js liefert icon.svg unter einer oeffentlichen Route aus, ohne Anmeldung

STRIDE Threat Register

Threat ID Category Component Severity Disposition Mitigation Plan
T-FGV-01 Tampering tessera-logo.tsx medium mitigate Eine fremde SVG-Datei als Zeichenkette in die Seite zu geben waere ein Einfallstor fuer eingebettete Skripte. Task 1 verbietet dangerouslySetInnerHTML und jedes Einlesen der Datei zur Laufzeit ausdruecklich: die Bildmarke wird als JSX von Hand gesetzt, React entwertet dabei jeden Inhalt.
T-FGV-02 Information Disclosure apps/web/src/app/icon.svg low accept Das Icon wird ohne Anmeldung ausgeliefert. Es ist eine Bildmarke ohne jeden Bezug zu Mandanten oder Nutzern — genau das ist der Zweck eines Favicons. Bewusst getragen.
T-FGV-03 Tampering user-files/logo/ low mitigate Die Lieferung liegt in einem vom Repository ausgeschlossenen Ordner und koennte unbemerkt ausgetauscht werden. Der Verify-Schritt von Task 1 vergleicht die kopierten Dateien byteweise gegen die Lieferung, sodass Kopie und Quelle nachweislich uebereinstimmen; ab dem Commit ist die Repository-Fassung die massgebliche.
T-FGV-SC Tampering npm/pip/cargo installs n/a n/a Dieser Plan installiert kein Paket — keine neue Abhaengigkeit, kein Legitimitaets-Tor noetig.
</threat_model>
- `pnpm --filter @tessera/web exec vitest run` ist vollstaendig gruen (der bestehende Bestand plus der neue Komponententest). - `pnpm --filter @tessera/web type-check` ist sauber. - Der Gelbwert der Marke kommt im Web-Quellcode genau einmal vor, in `brand.ts`. - `apps/web/src/app/icon.svg` und `apps/web/src/app/apple-icon.png` sind byteidentisch zu den gelieferten Dateien. - In `apps/web/src/app/(auth)/` steht kein von Hand gesetzter Marken-Schriftzug mehr. - Die Abnahme aus Task 3 ist in beiden Erscheinungsbildern durchlaufen.

<success_criteria>

  • Browser-Tab, Kopfleiste, Seitenleisten-Schublade, Anmeldeseite in breiter und schmaler Ansicht sowie beide Passwort-Seiten zeigen das gelieferte Logo.
  • Schriftzug und Bildmarke bleiben in hellem UND dunklem Erscheinungsbild lesbar; die dunkle Platte verschwimmt im dunklen Erscheinungsbild nicht mit dem Hintergrund.
  • Es existiert genau eine Datei, die eine spaetere mandantenspezifische Gestaltung anfassen muss: apps/web/src/components/brand/ mit der Farbkonstanten-Datei und der Logo-Komponente.
  • Von der Lieferung wurde nichts doppelt uebernommen; die nicht uebernommenen Dateien sind mit Grund benannt.
  • Es wurde keinerlei Hochlade-, Einstellungs- oder Mandanten-Funktion fuer das Logo gebaut. </success_criteria>
Create `.planning/quick/260907-fgv-tessera-logo-und-favicon-fest-einbauen-b/260907-fgv-SUMMARY.md` when done.

Die SUMMARY muss festhalten:

  • welche gelieferten Dateien uebernommen wurden und welche mit welcher Begruendung nicht,
  • warum der Schriftzug als Text und nicht als Bilddatei ausgeliefert wird (Farbe fest eingebacken UND Schriftart Archivo nicht geladen),
  • wie die Kontur der Platte im dunklen Erscheinungsbild geloest ist und warum sie auf dem gelben Anmelde-Panel abgeschaltet ist,
  • dass der Gelbwert jetzt an genau einer Stelle steht und --primary bewusst unberuehrt blieb,
  • wie der Benutzer die beiden zur Freigabe gestellten Gestaltungsfragen entschieden hat.

Ausserdem als Backlog-Punkt zu vermerken (vom Orchestrator einzureichen, in diesem Plan NICHT zu bauen): "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."