Schriften ins Repository, Anleitung fuer neue Websites, Schutzkopfzeilen
CMS quality / php (8.2) (push) Canceled after 0s
CMS quality / php (8.4) (push) Canceled after 0s
CMS quality / browser (push) Canceled after 0s
CMS quality / mysql (push) Canceled after 0s

Die Lato-Dateien liegen jetzt unter public/assets/fonts/ samt OFL-Text
und einer Lizenznotiz: auf einem frischen Server fehlt nichts, und es
wird nie versehentlich von Google geladen.

docs/NEUE-WEBSITE.md beschreibt, wie eine neue Kundenwebsite entsteht -
Reihenfolge, Dokumentformat, Bilder, SEO, Pruefungen - und nennt am
Ende die fuenf Fehler, die hier immer wieder passiert sind.

Permissions-Policy ergaenzt (Kamera, Mikrofon, Standort, Sensoren aus),
X-Powered-By entfernt: der Server nannte in jeder Antwort seine genaue
PHP-Fassung. Die Browserpruefung misst die Kopfzeilen jetzt.

Behoben: der Editor kannte Schema v17, der Validator v18 - die
Beitragsnavigation liess sich in keinem aktuellen Dokument einfuegen.
Ein Test bindet die Zahl des Editors an die des Validators.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
kantarciandClaude Opus 5 committed 2026-09-13 15:28:31 +02:00
1 parent 7c6b2a9ec8
commit a2dfd0f796
20 files changed
+401 -3

No files matched your search

+23
View File
@@ -879,6 +879,29 @@ final class CmsTest extends TestCase
self::assertStringContainsString('Nächstes Projekt', $rand);
}
public function testEveryPublicAnswerCarriesItsProtectiveHeaders(): void
{
// Diese Kopfzeilen fehlen lautlos, wenn jemand eine Antwort an der Stelle vorbeibaut, die
// sie setzt. Ein Test ist billiger als die Entdeckung im Betrieb.
$this->pages->publish('page-1', $this->pages->saveDraft('page-1', DemoContent::starter('Startseite'), 0), 1);
foreach (['/', '/gibt-es-nicht'] as $adresse) {
$antwort = $this->request($adresse);
$csp = (string) $antwort->headers->get('Content-Security-Policy');
self::assertStringContainsString("default-src 'self'", $csp, $adresse);
self::assertStringContainsString("object-src 'none'", $csp, $adresse);
// Ein eingeschleustes <base> würde jeden Verweis der Seite umlenken.
self::assertStringContainsString("base-uri 'none'", $csp, $adresse);
self::assertStringContainsString("frame-ancestors 'none'", $csp, $adresse);
self::assertSame('nosniff', $antwort->headers->get('X-Content-Type-Options'), $adresse);
self::assertStringContainsString('camera=()', (string) $antwort->headers->get('Permissions-Policy'), $adresse);
}
// Und der Vordereingang verrät nicht, welche PHP-Fassung hier läuft.
$index = (string) file_get_contents(__DIR__.'/../public/index.php');
self::assertStringContainsString("header_remove('X-Powered-By')", $index);
self::assertStringContainsString('Header always unset X-Powered-By', (string) file_get_contents(__DIR__.'/../public/.htaccess'));
}
public function testABackgroundPictureShrinksForSmallScreensEvenWhenSetOnce(): void
{
// Gemessen auf der nachgebauten Startseite: das Telefon lud das Hintergrundbild mit 1920