diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index 0a89a04..e3f0e8a 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -1,6 +1,14 @@ # Architekturentscheidungen -Stand: 09.10.2026. Arbeitstitel KantSites; Produktname offen. +Stand: 12.10.2026. Arbeitstitel KantSites; Produktname offen. + +## ADR 114 – Die Umschreibregel fängt index.php selbst ab (12.10.2026) + +Anlass: huefner-gartenbau.de bei IONOS (PHP 8.4.26) antwortete auf `/`, `/install` und `/assets/` mit einem weißen 500er von Apache. Die Notfallschicht (ADR 113) griff nicht, weil PHP gar nicht erreicht wurde. `/index.php/install` lieferte dagegen 200, auch mit der `.htaccess` – die Datei wurde also gelesen, der Fehler lag in der Umschreibregel. Vermutete Ursache: `RewriteCond %{REQUEST_FILENAME} !-f` erkennt dort die bereits umgeschriebene `index.php` nicht als Datei, die Regel greift erneut, Apache bricht nach zehn internen Umleitungen ab. + +**Entscheidung.** `public/.htaccess` setzt `RewriteBase /` und beendet die Umschreibung für `index.php` selbst (`RewriteRule ^index\.php$ - [L]`), wie die `.htaccess` von WordPress. Auf dem Hosting von Umut mit beiden Zeilen bestätigt; welche der beiden allein genügt hätte, ist nicht geprüft. `CmsTest` sichert die Zeilen ab. + +**Folgen.** `RewriteBase /` setzt voraus, dass die Domain auf `public/` zeigt – das war schon Bedingung, eine Installation in einem Unterordner einer Domain ist nicht vorgesehen. Bestehende Installationen bekommen die Zeilen mit dem nächsten Archivupdate, weil der Updater die `.htaccess` des Releases übernimmt (nur eingeschaltete HTTPS-/HSTS-Zeilen werden erhalten). `Options -Indexes -MultiViews` verträgt IONOS: auf huefner-gartenbau.de wieder eingeschaltet, die Seite lädt weiter. Ausgeliefert mit 1.28.1. ## ADR 113 – Kein leerer 500er mehr, Update mit einem Klick nach reiseSoft (09.10.2026) diff --git a/docs/STATUS.md b/docs/STATUS.md index f9bb821..e24bc2c 100644 --- a/docs/STATUS.md +++ b/docs/STATUS.md @@ -1,5 +1,17 @@ # Projektstatus +## Fassung 1.28.1: weißer 500er bei IONOS durch die Umschreibregel (12.10.2026) + +**Anlass:** huefner-gartenbau.de bei IONOS zeigte nach der Einrichtung auf jeder Adresse einen weißen 500er. + +**Ursache und Änderung (ADR 114):** PHP 8.4.26 lief (`test.php`), `/index.php/install` lieferte 200, nur umgeschriebene Adressen scheiterten – Umschreibschleife in `public/.htaccess`. Neu im Kern: `RewriteBase /` und `RewriteRule ^index\.php$ - [L]` vor der `!-f`-Regel; Test in `CmsTest::testEveryPublicAnswerCarriesItsProtectiveHeaders`. + +**Geprüft:** Umut hat beide Zeilen auf IONOS eingetragen, danach lädt `/install`; auch mit eingeschalteter `Options`-Zeile. PHPUnit vollständig: 643 Tests grün, eine Warnung aus `UpdaterTest` (fehlende `.env` im Testordner, unabhängig von dieser Änderung); php-cs-fixer sauber. + +**Offen:** Der Installer auf huefner-gartenbau.de war bis zum Abschluss der Einrichtung öffentlich erreichbar. + +**Nächster Schritt:** Bestehende IONOS-Installationen auf 1.28.1 aktualisieren. + ## Fassung 1.28.0: Notfallseite, Fehlerprotokoll und Update mit einem Klick (09.10.2026) **Anlass:** kantarci-reisen.de zeigt nach einer per FTP ersetzten Datenbank auf jeder Adresse eine leere 500-Seite. Umut: „Fang mit 1 und 2 an und verbessere den Update-Prozess … mach es wie bei reiseSoft.“ diff --git a/public/.htaccess b/public/.htaccess index 15a87a6..f80abb1 100644 --- a/public/.htaccess +++ b/public/.htaccess @@ -2,7 +2,14 @@ DirectoryIndex index.php Options -Indexes -MultiViews # Alles, was keine Datei ist, beantwortet PHP. +# +# Die Zeile fuer index.php selbst ist kein Zierrat: Bei IONOS erkennt !-f die bereits +# umgeschriebene index.php nicht als Datei, die Regel greift wieder und wieder, und Apache bricht +# nach zehn Runden mit einem weissen 500er ab (huefner-gartenbau.de, 12.10.2026). Dieselbe +# Absicherung steht in der .htaccess von WordPress. RewriteEngine On +RewriteBase / +RewriteRule ^index\.php$ - [L] RewriteCond %{REQUEST_FILENAME} !-f RewriteRule ^ index.php [L] diff --git a/tests/CmsTest.php b/tests/CmsTest.php index 085af9d..ec1cf86 100644 --- a/tests/CmsTest.php +++ b/tests/CmsTest.php @@ -1618,7 +1618,10 @@ final class CmsTest extends TestCase // 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')); + $htaccess = (string) file_get_contents(__DIR__.'/../public/.htaccess'); + self::assertStringContainsString('Header always unset X-Powered-By', $htaccess); + // Ohne diese Zeile schreibt IONOS index.php endlos auf sich selbst um: weißer 500er (ADR 114). + self::assertStringContainsString("RewriteBase /\nRewriteRule ^index\\.php$ - [L]\nRewriteCond %{REQUEST_FILENAME} !-f", $htaccess); } public function testABackgroundPictureShrinksForSmallScreensEvenWhenSetOnce(): void