Das Logo war nie kaputt — der Proxy hat es umgeleitet
Some checks failed
CI / Migrationen auf leerer Datenbank (push) Has been cancelled
CI / Lint, Typen, Tests, Build (push) Has been cancelled

`curl -sI` auf /brand/manner-logo.png antwortete mit **307**. Die Datei lag
die ganze Zeit da, ausgeliefert wurde sie nie: der Abgleich in proxy.ts
nimmt alles ausser _next/static, _next/image und favicon.ico, und public/
stand nicht darin. Eine Anfrage nach dem Logo lief also in den Gate, fand
keine Sitzung und bekam eine Umleitung nach /login. Auf ein <img> antwortet
der Server damit mit HTML, und der Browser zeigt den Ersatztext.

Das erklaert auch, warum es so sprunghaft aussah. Auffallen konnte es nur an
einer einzigen Stelle: die Anmeldeseite ist die einzige Seite, die jemand
ohne Sitzung zu sehen bekommt — und ausgerechnet dort steht das Logo.
Ueberall sonst ist man angemeldet, der Gate laesst das Bild durch. Einmal so
geladen liegt es im Zwischenspeicher und erscheint auf /login weiter, bis
jemand hart neu laedt.

Und es erklaert, warum keine der Aenderungen am Bild geholfen hat: weder das
Ausmisten des SVG noch der Wechsel auf ein PNG konnte etwas ausrichten, weil
die Datei den Browser gar nicht erreichte. Dass es „seit 8016d31" auftrat,
war eine Verwechslung von Ursache und Gelegenheit — dort bekam die
Anmeldeseite ihre rosa Flaeche und damit ueberhaupt erst ein sichtbares Logo
an einer Stelle ohne Sitzung.

Aufgenommen wird jetzt, was eine nicht angemeldete Person auf der
Anmeldeseite braucht: brand/ sowie icon.svg, apple-icon.png und
manifest.webmanifest, die der Browser von sich aus holt. Einzeln aufgezaehlt
und nicht als Regel ueber Dateiendungen — „alles mit einem Punkt darin"
haette auch Routen durchgelassen, die keine Datei sind. In public/ liegt
nichts Personenbezogenes und darf auch nie etwas liegen; alles, was Daten
fuehrt, geht durch withUser() und die Policies.

Fuenf Tests auf den Abgleich selbst. Die vorhandenen rufen proxy()
unmittelbar auf und gehen damit am matcher vorbei — ein Fehler dort war von
ihnen nicht zu sehen. Geprueft wird beides: dass die Dateien vorbeikommen,
und dass sonst nichts aufgeht, auch nicht ueber einen aehnlich aussehenden
Pfad wie /brandneu.

Lint, Typen, Schemaabgleich, 567 Tests und der Build sind sauber.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-15 21:39:58 +02:00
parent b23ee17608
commit a0811d75f4
2 changed files with 86 additions and 1 deletions

View File

@@ -78,6 +78,41 @@ export async function proxy(...args: Parameters<Awaited<typeof gate>>) {
return (await gate)(...args);
}
// ═══ Was der Proxy gar nicht erst sieht ═══
//
// Der Abgleich ist eine Verneinung: alles ausser dem hier Aufgezaehlten laeuft
// durch den Gate. Das ist die richtige Richtung — eine vergessene Route ist
// dann geschuetzt und nicht offen.
//
// Es fehlten allerdings die statischen Dateien aus public/. Eine Anfrage nach
// /brand/manner-logo.png lief damit in den Gate, fand keine Sitzung und
// bekam eine Umleitung nach /login. Der Browser bekommt auf ein <img> also
// HTML statt eines Bildes und zeigt den Ersatztext.
//
// Aufgefallen ist es nur an einer Stelle, und zwar an der einzigen, an der es
// auffallen konnte: die Anmeldeseite ist die einzige Seite, die jemand ohne
// Sitzung zu sehen bekommt — und ausgerechnet dort steht das Logo. Ueberall
// sonst ist man angemeldet, der Gate laesst das Bild durch, und es erscheint.
// Daher auch das Sprunghafte: einmal angemeldet geladen, liegt es im
// Zwischenspeicher des Browsers und erscheint auf /login weiter, bis jemand
// hart neu laedt.
//
// Aufgenommen wird nur, was eine nicht angemeldete Person auf der
// Anmeldeseite braucht, und jeder Eintrag einzeln statt einer Regel ueber
// Dateiendungen: „alles mit einem Punkt darin" haette auch Routen
// durchgelassen, die keine Datei sind.
//
// _next/static, _next/image die Ausgabe des Bauwerkzeugs
// favicon.ico, icon.svg, die Symbole, die der Browser von sich aus holt
// apple-icon.png
// manifest.webmanifest dito, fuer die Installation als App
// brand/ Logo und App-Symbole aus public/brand
//
// In public/ liegt sonst nichts; personenbezogen ist dort nichts und darf
// dort auch nie etwas liegen — alles, was Daten fuehrt, geht durch withUser()
// und die Policies.
export const config = {
matcher: ["/((?!_next/static|_next/image|favicon.ico).*)"],
matcher: [
"/((?!_next/static|_next/image|favicon\\.ico|icon\\.svg|apple-icon\\.png|manifest\\.webmanifest|brand/).*)",
],
};