Ein ehrlicher Audit der dv-civic-Plattform (Stadt- & Veranstaltungsportal-as-a-Service) gegen den gebauten Stand der Plattform — nicht gegen die Doku. Jede Aussage unten ist am realen Stand geprüft. Ergebnis: ein technisch starker Pilot-Release-Candidate, dessen Weg zu General Availability nicht an Code-Qualität hängt, sondern an einer offenen Zahlungs-Integration und drei externen Prüfungen.
Methodik: Prüfung jedes sicherheits- und geldrelevanten Pfads (Mandanten- und Domänenlogik, Berechtigungen, Datenmigrationen, Test- und CI-Gates). Es wurde nichts im Audit ausgeführt — Test- und Coverage-Zahlen stammen aus dem zuletzt dokumentierten CI-Lauf und sind als solche markiert. Vorgänger: ein interner Vor-Audit (Stand vor den letzten Verbesserungen).
| Stand | Version 1.0.0 (Pilot-RC) |
| Umfang | Geprüft: Mandanten- und Domänenlogik, Berechtigungen, Datenmigrationen, Test- und CI-Gates über das gesamte Backend und die End-to-End-Tests. |
| Stack | Etablierter EU-hostbarer Server-Stack mit datenbankseitiger Mandantenisolation, server-gerendertem Portal und Admin-/Redaktions-Framework. |
| Datum | 12. Juni 2026 |
Bewertung gegen die Exit-Kriterien aus der Roadmap. „Fortschritt" misst den technischen Aufbau; ein ✅ heißt nicht automatisch GA-reif, wenn ein externes Gate (Pentest, Audit, KoSIT) oder eine Echtgeld-Integration noch aussteht.
| Phase | Inhalt & Exit-Kriterium | Fortschritt | Status |
|---|---|---|---|
| 0 | Fundament. Projektaufbau, CI/CD, Mandanten-Kern (die Trennung wird auf Datenbankebene erzwungen — zweite Verteidigungslinie, sodass selbst ein App-Fehler kein Cross-Tenant-Leck verursacht), Auth inkl. Passkeys, eigenes Designsystem, Coverage-Gate. Exit: Demo-Mandant über Subdomain + Auto-TLS, Isolations-Tests grün, CI blockt < 85 %. |
100 % | Erfüllt |
| 1 | Content-Core. Artikel/Seiten/Kategorien/Tags, Redaktions-Workflow mit V.i.S.d.P.-Freigabe (§ 18 MStV), Rich-Text-Editor, Admin-/Redaktions-Panel mit Mandanten-Trennung, server-gerendertes Portal mit News, strukturierten SEO-Daten, Sitemap, Volltext-Such-Dienst. Offen: Medien-Pipeline (moderne Bildformate, responsive Auslieferung) bewusst deferred. Performance-Ziel nicht im Audit gemessen. |
95 % | Erfüllt |
| 2 | Verzeichnis & Karten. Gastro-/Business-Modell, Claim-Prozess, Karten-Stack ohne Consent-Banner, Bewertungen, DSA-Moderation (Art. 16 Meldeweg + Mail, Art. 17 Begründung). Offen: Tourismus-Seitentypen (geplant, nicht gebaut). Self-hosted Geocoding nicht im Audit verifiziert. |
90 % | Erfüllt |
| 3 | Events & Ticketing. schema.org-Eventmodell, ICS-Feeds, barrierearmer Checkout mit korrekter Kontingent-Sperrung (kein Oversell), PDF-Tickets mit QR, Ticket-Mail, Einlass-Check-in im Admin-Bereich. Blockiert: Anbindung an den Zahlungsdienstleister (Onboarding + Auszahlung + Erstattung) ist ein Platzhalter (nur Test-/Fake-Anbieter). Offline-fähiger Check-in & Open-Data-API verschoben. |
70 % | Teilweise |
| 4 | SaaS-Schicht. Self-Service-Onboarding, Theming (Token-Editor), Custom-Domain-Flow mit DNS-Verifikation → On-Demand-TLS, Plan-/Feature-Gating, XRechnung-Lauf (Leitweg-ID). Offen: KoSIT-Validierung (extern), Mail-/Newsletter-Versanddienst, Consent-Management, SSO-Spike. SEPA gestrichen (YAGNI). |
65 % | Teilweise |
| 5 | Hardening. Audit der datenbankseitigen Mandantenisolation + automatisierte Angriffspfad-Tests, Onsale-Lasttest mit echten parallelen Käufern, Security-Header, token-geschützter Deep-Health-Check, Backup-/Restore-Tooling + DR-Runbook. Offen: externer Pentest, BITV-/WCAG-2.2-Audit, Content-Security-Policy-Härtung, Statuspage. |
55 % | Teilweise |
| 6 | Pilot & GA. Idempotentes Bestandsdaten-Import-Werkzeug (mit Dry-Run), Go-Live-Preflight-Check, Go-Live-Checkliste, Release-Runbook. Offen: realer Pilotbetrieb, LOI/zahlender Kunde (Roadmap-Gate), Owner-Freigabe. GA nicht erreicht. |
40 % | Teilweise |
Acht Kategorien, gewichtet nach Risiko und Geschäftsrelevanz. Vergleich gegen den Vor-Audit (68/100): Code-Qualität und Sicherheit deutlich hoch, Decke weiter durch Zahlungs-Platzhalter und Außen-Gates begrenzt.
| # | Kategorie | Gewicht | Score | Belegt durch |
|---|---|---|---|---|
| 1 | Tenancy & Isolation | 20 % | 9,5 | Der Mandanten-Kern erzwingt die Trennung auf Datenbankebene als zweite Verteidigungslinie — selbst Raw-Inserts werden mandanten-gestempelt, die App-Rolle kann die Isolation nicht umgehen (auch in CI). Durch automatisierte Angriffspfad-Tests abgedeckt. |
| 2 | Produktions-Runtime | 15 % | 6,5 | Domain-Cache-Bug behoben (Skalar-Array statt Model), eigener Hintergrund-Verarbeitungsdienst, Ticket-Mail asynchron. Gedeckelt: Echtgeld-Ticketing blockiert durch Zahlungs-Platzhalter. |
| 3 | Security / AuthZ / AppSec | 15 % | 8,0 | Rollenbasierte Berechtigungen für alle Admin-Bereiche (Bestellungen/PII + Domains nur Admin, Ticket-Preise nur Admin), TOTP-MFA-Pflicht, Registrierungs-Gate, Security-Header, Rate-Limits, tokengeschützter Domain-Verifikations-Endpunkt mit Cache. Offen: Content-Security-Policy, Stored-XSS-Fläche (Pentest). |
| 4 | Domänenlogik-Korrektheit | 12 % | 9,0 | Die Kauf-, Einlass- und Rechnungslogik arbeitet mit korrekter Sperrung gegen Überverkauf und Doppelscan, mit sauberem Rollback bei Zahlungsfehlern und idempotenter Rechnungserzeugung (Leitweg-ID). Alle getestet. |
| 5 | Payments / Ticketing-Produktionspfad | 10 % | 2,0 | Die Zahlungs-Anbindung ist ein bewusst lautstark scheiternder Platzhalter — keine Anbindung, keine Webhooks, keine Erstattung, kein Onboarding. Die Integration ist noch offen. Nur der Test-/Fake-Anbieter funktioniert. |
| 6 | Backend-Tests & Gates | 10 % | 9,0 | Umfangreiche automatisierte Tests, Coverage-Gate ≥ 85 % (zuletzt 90,6 %), statische Analyse, Code-Style-Gate. CI gated zusätzlich auf Abhängigkeits-Sicherheitsscans und Secret-Scanning. |
| 7 | E2E / a11y / Frontend-Tests | 8 % | 6,5 | End-to-End-Tests der kritischen Flows inkl. Checkout, plus automatisierter Barrierefreiheits-Testlauf, gegen einen geseedeten Stack mit aktiver Hintergrund-Verarbeitung. Komponenten-Tests inkl. Ticket-Checkout. Frontend-Coverage noch dünn. |
| 8 | Compliance-Umsetzung | 10 % | 7,5 | DSA Art. 16 Eingangs-Mail + Art. 17 Begründung (jetzt zuverlässig zustellbar), V.i.S.d.P.-Gate (AI Act/MStV), XRechnung. Offen: externer BITV-Test, Consent-Management, KoSIT. |
| Gewichtet | 100 % | 7,5 | ≈ 75 / 100. Vorher 68/100. Anstieg aus Berechtigungs-, Verarbeitungs-, Cache- und E2E-Arbeit; Decke unverändert durch Zahlungs-Platzhalter und offene Außen-Gates. |
Die zwölf Befunde des Vor-Audits, am aktuellen Stand nachverifiziert. Erfreulich: F1 und F2 (die beiden 🔴-Befunde) waren bereits vor dem Audit-Stand behoben; der Vor-Audit lief gegen einen veralteten Stand. Sieben weitere wurden seither umgesetzt.
| ID | Befund | Status heute | Beleg |
|---|---|---|---|
| F1 | 🔴 Domain-Auflösung cachte ein Datenbank-Objekt — der Prod-Cache verweigert Objekte | behoben | Cache hält nur noch Skalar-Werte; Rehydrierung beim Lesen. Durch Regressionstest abgedeckt. |
| F2 | 🔴 Gequeute (DSA-)Mails ohne Verarbeitungsdienst | behoben | Eigener Hintergrund-Verarbeitungsdienst, auch im CI-E2E-Lauf aktiv. Durch Test abgedeckt. |
| F3 | 🟠 Rollenbasierte Berechtigungen deckten nur einen Teil der Admin-Bereiche | behoben | Berechtigungen für alle Admin-Bereiche; Bestellungen/Domains nur Admin, Ticket-Preise schreiben nur Admin, Content abgestuft (Viewer/Editor/Admin). Durch Test abgedeckt. |
| F4 | 🟠 Offene Registrierung + Self-Service-Mandant ohne Verifikation | behoben | Ein abschaltbares Registrierungs-Gate (Default aus) sperrt Registrierung und Self-Service-Anlage. Durch Test abgedeckt. |
| F5 | 🟡 Bestell-Kennung als einzige Capability für Bestellseite/Ticket-PDF | gehärtet | Rate-Limit + striktes No-Store-Caching auf beiden Routen. Capability-Modell bewusst belassen; F7 entschärft Verlustfall. |
| F6 | 🟡 Lücke zwischen Zahlung und Bestätigung ohne Abgleich | offen | Gehört zur noch offenen Zahlungs-Integration (Webhooks + Abgleich). Mit Fake-Anbieter kein reales Risiko. |
| F7 | 🟡 Keine Ticket-Zustellung per Mail | behoben | Ticket-Mail asynchron, PDF im Hintergrund erzeugt. Durch Test abgedeckt. |
| F8 | 🟡 Domain-Verifikations-Endpunkt ungecacht + Hostnamen-Orakel | behoben | Cache mit kurzer TTL und Invalidierung bei Domain-Änderung + tokengeschützter Endpunkt (ohne Token nicht ansprechbar). |
| F9 | 🟡 Bewertungen gehen ungebremst & unmoderiert live | gehärtet | Honeypot (stille Verwerfung) + Flood-Limit pro Ort/IP/Tag. Publish-on-arrival bleibt (DSA notice-and-action). |
| F10 | 🟡 Keine Content-Security-Policy | offen | Noch zu verdrahtende Content-Security-Policy. Bleibt Pentest-Vorbedingung, im Code ehrlich vermerkt. |
| F11 | ⚪ Stored-XSS-Fläche (Admin-Renderer) | offen | Belastbar nur im Pentest prüfbar; die CSP (F10) wäre der Backstop. |
| F12 | ⚪ Kleinigkeiten (Optional-Hacks, Sitemap-Bound, Ticket-Code-Alphabet) | teilweise | Beide Optional-Fallbacks im Frontend entfernt; No-Store gesetzt. Sitemap-Bound & Code-Alphabet bewusst belassen (begründet). |
| # | Blocker | Art | Was es braucht |
|---|---|---|---|
| 1 | Zahlungs-Integration (Zahlungsdienstleister) | Code | Anbindung, signierte + idempotente Webhooks, Onboarding, Erstattungen, Abgleich (schließt F6). Ohne dies kein Echtgeld-Ticketing. |
| 2 | Content-Security-Policy (F10/F11) | Code | Noch zu verdrahtende CSP als AppSec-Härtung; backstoppt die Stored-XSS-Fläche vor dem Pentest. |
| 3 | Externer Pentest | Extern | Schwerpunkt Mandanten-Isolation; ohne offene High/Critical + bestandener Re-Test (gemäß Pentest-Auftrag). ~8–15 k€. |
| 4 | BITV-/WCAG-2.2-Audit | Extern | Externe Prüfung + Behebung; der automatisierte Barrierefreiheits-Testlauf ist die Vorarbeit, ersetzt aber kein Zertifikat. ~5–10 k€. |
| 5 | KoSIT-Validierung der XRechnung | Extern | Der Rechnungslauf existiert (Leitweg-ID); die KoSIT-Konformität muss validiert werden. |
| 6 | Kommerzielles Gate (Roadmap) | Business | LOI/Vorvertrag eines zahlenden Pilotkunden + Owner-Freigabe. Harte Roadmap-Regel, kein Code. |
| 7 | Vertriebs-/Rechtsdokumente | Recht | AVV, TOMs, SLA, Subprozessorenliste — anwaltlich geprüft. Mail-Versanddienst/Consent-Management/SSO nach Bedarf. |
Aus der Launch-Checkliste. Erledigt = im Code/CI nachweisbar; offen = Außen-Gate oder Integration.