Die ausgelieferte App muss verifiziert werden, nicht nur die Konvention
Das Dashboard begrenzt Anfragen pro Besucher und erneuert angemeldete Sitzungen serverseitig. Beim Umstieg auf den ausgelieferten Produktiv-Build stellte sich heraus, dass genau diese Schutzfunktion im Test griff, im echten Betrieb aber wirkungslos blieb: Der gebaute Server kannte die zuständige Komponente nicht und führte sie nie aus. Sichtbar wurde das erst beim Test gegen die echte Auslieferung. Lehre: Bei jedem Release prüfen, ob die im Test funktionierende Schutzschicht auch in der tatsächlich ausgelieferten Anwendung aktiv ist, statt sich auf die Konvention zu verlassen.
Interne Inhalte werden vor der Veröffentlichung im Zweifel blockiert
Damit aus internen Repositories nichts versehentlich in öffentliche Texte gelangt, durchläuft jeder generierte Inhalt vor der Freigabe eine eigene Prüfung. Diese Prüfung ist bewusst restriktiv: Im Zweifel oder bei einem Fehler wird der Inhalt blockiert statt durchgewunken. Beim Härten zeigte sich, dass gezielt konstruierte Eingaben die Prüfung in die Länge ziehen konnten. Wir haben deshalb klare Obergrenzen für die zu prüfende Textmenge eingezogen, sodass die Laufzeit auch im Missbrauchsfall planbar bleibt. Lehre: Eine Sicherheitsgrenze, die nur den Normalfall abdeckt, ist keine Grenze. Sie muss auch im Fehler- und Missbrauchsfall geschlossen bleiben.
Die public/internal-Grenze braucht einen blockierenden Anon-Leak-Test
Row Level Security in Postgres ist die Basis der Trennung zwischen freigegebenen und internen Daten, aber eine einzelne falsche Policy oder ein neues Feld kann die Grenze unbemerkt aufweichen. Wir haben deshalb eine eigene Test-Suite, die aus Sicht eines anonymen Betrachters prüft, dass exakt die freigegebenen Projekte sichtbar sind und kein internes Feld in der Antwort auftaucht. Dieser Test ist ein blockierender CI-Gate: schlägt er fehl, kommt der Build nicht durch. So wird die Sicherheitsgrenze bei jedem Schema-Change neu verifiziert statt nur einmal beim Schreiben der Policy.
Static SRI-CSP statt Request-Nonce im Next-16-Standalone-Build
Der naheliegende Weg zu einer strengen Content-Security-Policy ist ein per Request erzeugter Nonce, aber im Next-16-Standalone-Build bricht das die Hydration: das Framework hasht nur externe Chunks, während die inline-Bootstrap-Daten einen Request-Nonce bräuchten, den ein statisch ausgelieferter Build nicht hat. Wir setzen stattdessen auf eine statische CSP mit festen Hashes für die erlaubten Skripte. Der entscheidende Schritt war, das im echten Browser zu verifizieren statt nur im Test, weil der Hydration-Fehler erst dort sichtbar wird.
Ein Projection-Chokepoint, durch den interne Felder strukturell nicht leaken
Beim Mapping von internen Projektdaten auf die öffentliche Ansicht gibt es genau eine Stelle, die jedes Feld explizit per Allowlist freigibt, statt ein Objekt durchzureichen und einzelne Felder zu entfernen. Ein neu hinzugefügtes internes Feld erscheint dadurch per Default nicht in der öffentlichen Projektion, sondern nur, wenn es bewusst in die Allowlist aufgenommen wird. Das verlagert die Sicherheit von nicht vergessen, etwas zu entfernen zu nichts wird gezeigt, was nicht ausdrücklich erlaubt ist. Zusammen mit dem RLS-Gate ergibt das eine doppelte Absicherung der public/internal-Grenze.