7.3 KiB
M2 Technisches Fundament
Stand: 2026-07-13
M2 führt die technischen Grundbausteine für den SaaS-Umbau ein, ohne das Legacy-Verhalten oder das bestehende Design zu verändern.
Status: abgeschlossen für den M2-Scope. Bewusst ausgelagerte Themen sind unten als Grenzen und M3-/M6-Übergabe dokumentiert.
Ziel
- Versionierte Datenbankmigrationen statt loser Schema-Ausführung.
- Zentrales Bootstrap für Umgebung, Session und CSRF-Helper.
- Bestehende Legacy-Seiten bleiben kompatibel.
- Layout-Trennung wird vorbereitet, aber noch nicht in bestehende Seiten hineingezogen.
Umgesetzte Bausteine
Bootstrap
app/bootstrap.phpdefiniert zentrale Helfer:app_env()app_is_dev()app_start_session()app_csrf_token()app_csrf_field()app_verify_csrf()app_require_csrf()
config.phplädt den Bootstrap und startet die Session mit sicheren Cookie-Optionen.- Sessions werden standardmäßig unter
var/sessionsabgelegt, weil die lokale PHP-Umgebung keinen beschreibbaren Systempfad garantiert.var/ist von Git ignoriert. Der Pfad kann überAPP_SESSION_PATHüberschrieben werden. - CSRF ist bewusst noch nicht global erzwungen. Die vorhandenen POST-Seiten werden später einzeln umgestellt, damit keine Formulare oder Spezialflows brechen.
CSRF-Rollout
Erste Legacy-POST-Seiten sind opt-in abgesichert:
hinweise.php: Hinweis anlegen und Hinweis löschen. Der bisherige GET-Löschlink wurde durch ein POST-Formular mit CSRF-Token ersetzt.mitarbeiterverwalten.php: Mitglied anlegen, Bearbeitungsformular öffnen, Mitglied speichern, aktivieren und deaktivieren.namenanpassen.php: Anzeigenamen aktualisieren.index.php: eigene Web-Striche eintragen.stricheintragen.php: Sammelerfassung von Strichen.einzahlung.php: Sammelerfassung von Einzahlungen.letzteneintraege.php: letzte Einzahlungen und Strich-Einträge löschen.csvupload.php: CSV-Zahlungsimport.
Noch offen:
- Spezialprozesse:
mailversenden.php,jahresauswertung.php.
CSV-Upload-Härtung
csvupload.phpnutzt jetzt CSRF.- Uploads werden unter
var/uploadsgespeichert und nach der Verarbeitung gelöscht. Damit liegen importierte Dateien nicht mehr im Webroot. - Dateiendung, Dateigröße und MIME-Typ werden vor der Verarbeitung geprüft.
- Hochgeladene Dateien bekommen serverseitig erzeugte Zufallsnamen.
- CSV-Auswertungswerte werden HTML-escaped ausgegeben.
- Die PayPal-Namenssuche nutzt
Nameundpaypalnamemit expliziter Parameterbindung.
Offen für M6:
- Importvorschau vor dem Schreiben.
- Import-Batch/Audit-Log.
- Saubere Fehlerberichte je CSV-Zeile.
Migrationen
database/migrations/0001_legacy_mysql_baseline.sqlbildet die bisherige MySQL-Dev-Baseline als erste versionierte Migration ab.scripts/dev-db.phpverwaltetschema_migrationsund führt neue Migrationen idempotent aus.scripts/migrate.phpist der direkte Runner für Migrationen.scripts/init-mysql-dev.phpnutzt ab jetzt ebenfalls die Migrationslogik.
Layout
header.phpundfooter.phpbleiben vorerst Legacy-Wrapper.- Die spätere Trennung in Public-Layout und App-Layout wird erst umgesetzt, wenn die neue Route-/View-Struktur steht.
- Die bestehende HTML5-UP-Struktur, Sidebar und Assets bleiben unverändert.
Ausführung
Mit normaler PHP-CLI:
php scripts/migrate.php
php scripts/init-mysql-dev.php
php scripts/check-golden-master.php
php scripts/http-smoke.php
In der aktuellen lokalen Umgebung:
LD_LIBRARY_PATH="$PWD/.local/php/usr/lib/x86_64-linux-gnu:$PWD/.local/php/usr/lib/x86_64-linux-gnu/sasl2" \
"$PWD/.local/php/usr/bin/php8.3" \
-c "$PWD/.local/php-dev.ini" \
scripts/migrate.php
Die Skripte erwarten die bekannten Dev-Umgebungsvariablen DB_HOST, DB_NAME,
DB_USER und DB_PASS. scripts/init-mysql-dev.php braucht zusätzlich
DEV_AUTH_EMAIL.
Aktueller Prüfstatus
- Migration
0001_legacy_mysql_baseline.sqlerfolgreich angewendet. - Zweiter Migrationslauf meldet: Datenbank ist aktuell.
- PHP-Syntax für Bootstrap, Migrationen, Init-Skript und Config ist sauber.
- Session-Start läuft in der lokalen Dev-Umgebung ohne PHP-Warnings über
var/sessions. - CSRF negative Tests:
hinweise.php,mitarbeiterverwalten.phpundnamenanpassen.phpliefern bei POST ohne Token HTTP 419. - CSRF positive Tests: gültige Token funktionieren für Hinweis-Anlage, Mitglieder-Bearbeitungsformular und Namensanpassung. Der temporäre Testhinweis wurde wieder entfernt.
- CSRF negative Tests für Buchungsflows:
index.php,stricheintragen.phpundeinzahlung.phpliefern bei POST ohne Token HTTP 419. - CSRF positive Tests für Buchungsflows: gültige Token funktionieren für eigene Web-Striche, Sammelstriche und Sammeleinzahlungen. Die temporären Testbuchungen wurden wieder entfernt.
- CSRF negative Tests für Korrektur-/Löschflows:
letzteneintraege.phpliefert bei POST ohne Token HTTP 419. - CSRF positive Tests für Korrektur-/Löschflows: gültige Token funktionieren für das Löschen temporärer Einzahlungs- und Strich-Testeinträge.
- CSRF negative Test für CSV-Upload: POST ohne Token liefert HTTP 419.
- CSV-Upload positive Tests: gültiges Token verarbeitet eine CSV-Datei, erkennt
eine PayPal-Alias-Dublette und hinterlässt keine Datei in
var/uploads. - CSV-Upload negative Tests: Nicht-CSV-Dateien werden abgewiesen.
- Golden Master weiterhin grün mit 104 Assertions.
- HTTP-Smoke weiterhin grün mit 23 sicheren Seiten inklusive Landingpage, Login, Registrierung, Passwort-Reset, E-Mail-Verifikation und geschützter Mandant-Einstellungen, geschützter Mandantenauswahl sowie Ledger-Preview.
Bewusste Grenzen
- Keine Tenant-/User-/Rollen-Tabellen in M2. Diese gehören zu M3.
- Keine globale CSRF-Erzwingung für Spezialprozesse.
mailversenden.phpundjahresauswertung.phpwerden in M6 als Jobs mit Dry-Run, Audit und Versandlog neu betrachtet. - Kein Layout-Umbau in M2. Die visuelle Struktur bleibt stabil; Public-/App- Layouts werden mit der M3-/M7-Struktur vorbereitet.
- PDF-/Mail-/Jahresprozesse bleiben als M6-Themen offen.
Abschlusskriterien
- Migrationsrunner ist vorhanden und idempotent.
- Bootstrap, Session und CSRF-Helper sind zentral verfügbar.
- Die relevanten Legacy-Schreibseiten sind CSRF-geschützt.
- CSV-Uploads liegen nicht mehr im Webroot.
- Bestehende Legacy-Seiten bleiben per HTTP-Smoke erreichbar.
- Golden-Master-Fachwerte bleiben unverändert.
Übergabe an M3
M3 startet mit additiven SaaS-Tabellen und einer Default-Tenant-Abbildung. Die Legacy-Seiten sollen dabei weiterhin über die bestehenden Tabellen laufen, bis der fachliche Kern in M4/M5 schrittweise auf das Zielmodell umgestellt wird.
M3 wurde inzwischen gestartet. Umgesetzte Details stehen in
docs/m3-saas-basis-vorbereitung.md. Der ursprüngliche Startpunkt war:
tenants,tenant_settings,users,tenant_membershipsundparticipantsals neue Migration anlegen.- Einen Default-Tenant für die bestehende Kaffeeliste definieren.
- Bestehende
kl_Mitarbeiterinparticipantsspiegeln, inklusivelegacy_mitarbeiter_id. - Admins aus
kl_Mitarbeiter.adminalstenant_memberships.role = 'admin'beziehungsweise für den ersten Hauptnutzer alsownerabbilden. - Erst danach Login/Registrierung und Public-/App-Routen anschließen.