# Kritische Risiken und Refactoring-Gefahren **Stand:** 15. Mai 2026 **Reviewer:** Claude **Bezug:** Hosting-Backoffice v0.1 (vollständiger Basisbestand) Jedes Risiko ist mit Schweregrad, Zeitpunkt und konkreter Empfehlung markiert. **Legende:** - Schweregrad: `LOW` / `MEDIUM` / `HIGH` / `CRITICAL` - Zeitpunkt: `NOW` (vor Codebeginn) / `V1` / `V2` / `V3` / `LATER` --- ## R-01 — Mandantenfähigkeit ist Absichtserklärung, kein Design - **Schweregrad:** `CRITICAL` - **Zeitpunkt:** `NOW` - **Problem:** Die Multi-Tenancy-Strategie listet Ziele, keinen Mechanismus. V1 läuft als Single-Tenant mit zwei ungeklärten ID-Spalten (`tenant_id`, `organisation_id`). Wenn V1 ohne Tenant-Scope-Enforcement deployt wird, ist V2/V3-Reseller-Fähigkeit ein Komplett-Refactor jeder Query, Policy, Job-Payload, Cache-Key und Webhook-Definition. - **Empfehlung:** Tenancy-Modell jetzt entscheiden und in ADR festschreiben. Vorschlag: Shared Database, `tenant_id`-Scope, Postgres Row-Level Security als zweite Verteidigungsschicht. Eloquent Global Scope von Tag 1 auf allen mandantenscoped Modellen. Statische Analyse oder Runtime-Assertion in CI gegen ungescopte Queries. `organisation_id` vs. `tenant_id` mit ER-Modell klären oder eine der beiden Spalten streichen. --- ## R-02 — Anbieterlogik im Core-Datenmodell bricht das eigene Adapter-Pattern - **Schweregrad:** `CRITICAL` - **Zeitpunkt:** `NOW` - **Problem:** `Server.KeyHelp-Referenz` und `Rechnung.externes System` stehen im Core-Datenmodell. Das widerspricht direkt dem Integration-Adapter-Pattern, das „Core kennt keine direkte Anbieterlogik" als Grundprinzip formuliert. Sobald V1 mit dieser Schema-Form deployt wird, ist das Adapter-Pattern in der Praxis tot, und jedes neue Hostingpanel braucht Core-Schema-Änderungen. - **Empfehlung:** Vor dem ersten Migration-File ein generisches External-Reference-Pattern einführen, z. B. Tabelle `external_references(id, owner_type, owner_id, adapter_id, external_id, metadata, last_synced_at)`. Im Core nur diese Tabelle, keine anbieter-spezifischen Felder. --- ## R-03 — Daten im Core, Logik in Modulen (Billing-Anti-Pattern) - **Schweregrad:** `CRITICAL` - **Zeitpunkt:** `NOW` - **Problem:** `Rechnung` und `Zahlung` sind im Core-Datenmodell. Billing-Logik ist als Integrationsmodul gedacht (Lexware, Invoice Ninja). Konsequenz: Module schreiben in Core-Tabellen, kennen das Core-Schema, jede Schema-Änderung im Core bricht potenziell mehrere Module. Genau die Konstruktion, in der „modularer Aufbau" zum erweiterten Monolithen wird. - **Empfehlung:** Billing als eigene Bounded-Context-Domäne (Service-Modul) etablieren. Core kennt höchstens `InvoiceReference` mit Adapter-ID und externer ID, nicht aber `Rechnung.Betrag`. Eigenes Datenmodell pro Modul, Kommunikation per definierten Service-Contract. --- ## R-04 — Modulstruktur und Modul-Dokumente widersprechen sich - **Schweregrad:** `HIGH` - **Zeitpunkt:** `NOW` - **Problem:** `module-structure-v0.1.md` listet weder Billing noch Customer Portal, obwohl beide eigene Modul-Beschreibungen haben. KeyHelp und Registrar sind als Modul-Doks vorhanden – einer ist Integrationsmodul, der andere möglicherweise eine Mischform. Solange diese drei verschiedenen „Wahrheiten" parallel existieren, gibt es kein gemeinsames Architekturverständnis. - **Empfehlung:** Modulstruktur als alleinige Wahrheit etablieren. Jedes Modul-Dokument muss in der Modul-Struktur gelistet sein, oder es existiert nicht. Inkonsistenzen vor Codebeginn beheben. --- ## R-05 — Secrets-Management vollständig undefiniert - **Schweregrad:** `CRITICAL` - **Zeitpunkt:** `NOW` - **Problem:** `Registrar-Account.Zugangsdaten/API-Referenzen` impliziert Credentials im Datenmodell. Im gesamten Bestand findet sich kein Wort zu Vault, Verschlüsselung, Key Rotation, KMS, HSM oder Mandanten-Isolation der Schlüssel. Bei kompromittierter DB hätte ein Angreifer Zugriff auf Registrar-Accounts aller Mandanten – das wäre ein Vorfall mit Branchenrelevanz. - **Empfehlung:** Externes Secret-Management (HashiCorp Vault, AWS Secrets Manager, Bitwarden Secrets Manager) oder mindestens Envelope-Encryption mit pro-Mandant abgeleiteten Schlüsseln und externem KMS. Datenmodell darf keine Credentials enthalten, nur Referenzen in den Vault. Vor V1-Codebeginn entscheiden. --- ## R-06 — Core ist zu groß, Monolith-Pfad voraussehbar - **Schweregrad:** `HIGH` - **Zeitpunkt:** `NOW` - **Problem:** Core enthält 13 Bereiche, davon mindestens 6 mit eigener Geschäftslogik (Domains, Hostingpakete, Server, Dokumente, Notifications, Produkte). Diese Konstellation produziert einen Bounded Context für die gesamte Anwendung und macht den Modul-Ansatz architektonisch wirkungslos. - **Empfehlung:** Core auf Identity, RBAC, Audit, Settings, Module-Registry, Event-Routing, Tenant-Scope reduzieren. Domains, Hostingpakete, Server, Dokumente, Notifications-Channels in eigene Service-Module auslagern. Adapter-Pattern und Modul-Contract als verbindliche Grenze. --- ## R-07 — GoBD-Verantwortlichkeit nicht entschieden - **Schweregrad:** `HIGH` - **Zeitpunkt:** `V1` - **Problem:** `Rechnung.externes System` impliziert, dass Lexware/Invoice Ninja der Beleg-Originalspeicher ist. Die GoBD-Archive-Strategie sagt aber gleichzeitig „PDFs archivieren, Hashes speichern, Audit-Logs schreiben" – das klingt nach lokalem Originalspeicher. Wenn Hosting-Backoffice der Originalspeicher ist, gelten harte GoBD-Anforderungen (unveränderbare Belege, lückenlose Nummernkreise pro Mandant, 10-Jahres-Retention, Z3-Export). Aktuell ist das nicht entschieden. - **Empfehlung:** Klärungs-ADR. Empfehlung: Lexware/Invoice Ninja als Original, Hosting-Backoffice als Referenz-/Spiegel-System mit Archivkopie und Hash. Audit-Logs intern, aber keine GoBD-Originalrolle. --- ## R-08 — DSGVO-Löschung vs. GoBD-Retention nicht modelliert - **Schweregrad:** `HIGH` - **Zeitpunkt:** `V1` - **Problem:** Endkunde verlangt Löschung nach DSGVO Art. 17, gleichzeitig müssen Rechnungsbelege 10 Jahre aufbewahrt werden. Diese Spannung muss technisch abgebildet sein. Im aktuellen Datenmodell gibt es weder Soft-Delete-Modell noch Pseudonymisierungs-Strategie noch Tombstone-Mechanismus. - **Empfehlung:** Tombstone- und Pseudonymisierungs-Modell entwerfen. Pflicht: Trennung von Personen-Stammdaten (löschbar/pseudonymisierbar) und Beleg-Inhalt (retentionspflichtig). Konkrete Felder definieren, was bei „Löschung" mit der Person passiert (z. B. `Anonymized` als Name). --- ## R-09 — API-Auth-Strategie unentschieden - **Schweregrad:** `HIGH` - **Zeitpunkt:** `NOW` - **Problem:** „Tokenbasiert, später OAuth/Sanctum möglich" mischt Konzeptebenen. Das WordPress-Plugin und das Customer Portal können nicht entwickelt werden, bevor entschieden ist, welcher Auth-Mechanismus für welchen Client-Typ gilt. - **Empfehlung:** ADR. Vorschlag für V1: Sanctum Personal Access Tokens (M2M, einfache Clients) plus Sanctum SPA-Mode (eigenes Frontend, falls vorhanden). V2: Passport/OAuth2 für WordPress-Plugin und Drittanbieter-Apps. --- ## R-10 — Datenbankwahl offen - **Schweregrad:** `HIGH` - **Zeitpunkt:** `NOW` - **Problem:** „MariaDB oder PostgreSQL" als Nicht-Entscheidung. Postgres bietet Row-Level Security (relevant für Tenancy als Defense-in-Depth), JSONB mit Indizes, transaktionales DDL, partielle Indizes. MariaDB nicht in gleichem Umfang. „Später entscheiden" ist faktisch eine Festlegung auf den kleinsten gemeinsamen Nenner. - **Empfehlung:** ADR. Vorschlag: PostgreSQL 15+, mit expliziter Begründung an Tenancy-, Audit-, JSON- und Performance-Anforderungen. --- ## R-11 — KI-Modul in V1 birgt DSGVO-Sprengstoff - **Schweregrad:** `HIGH` - **Zeitpunkt:** `NOW` (Scope-Entscheidung) / `V2` (technisch) - **Problem:** KI-Funktionen verarbeiten potenziell personenbezogene Support-Ticket-Inhalte über US-Provider, was Auftragsverarbeitungsvertrag, SCC, Drittlandtransfer-Risikobewertung, Subprozessor-Transparenz und Endkunden-Information erfordert. Für V1 (3–5 Pilotkunden, „Ordnung schaffen") ist das Aufwand ohne Geschäftswert. - **Empfehlung:** KI-Modul aus V1 entfernen, in V2 wieder aufnehmen. Bis dahin: Subprozessor-Strategie, DPA-Vorlage, Datenklassifikation und Mensch-im-Loop-Konzept ausarbeiten. --- ## R-12 — SEPA-Lastschrift ohne SEPA-Modell - **Schweregrad:** `MEDIUM` - **Zeitpunkt:** `V1` - **Problem:** Payment Policy listet Lastschrift als V1-Zahlungsart. SEPA-Lastschrift erfordert Mandate (UMR, Mandatsdatum, Mandatstext), Pre-Notification (mind. 1 Tag), IBAN-Speicherung (personenbezogen + sicherheitsrelevant), Mandatsänderungs-Historie. Davon ist nichts modelliert. - **Empfehlung:** Entweder Lastschrift aus V1 entfernen, oder SEPA-Mandat-Modell vollständig spezifizieren (eigene Tabellen, Statusmaschine, Verschlüsselung der IBAN, Audit-Log). --- ## R-13 — V1-Scope intern widersprüchlich - **Schweregrad:** `HIGH` - **Zeitpunkt:** `NOW` - **Problem:** Mehrere Dokumente erzählen unterschiedliche V1-Geschichten: KI in V1 vs. V2, Customer Portal in V1 vs. nicht in MVP, Kundenzahl 1–500 vs. 1–50. Das macht den V1-Scope unentscheidbar und damit das Erfolgsversprechen unprüfbar. - **Empfehlung:** V1-Scope-Liste als einzelne Quelle der Wahrheit etablieren. Empfehlung: KI raus, Customer Portal raus oder mit reduziertem Umfang, Kundenzahl auf 1–50 festgelegt. Alle Dokumente daran ausrichten. --- ## R-14 — Audit-Log-Unveränderbarkeit als Wunsch, kein Mechanismus - **Schweregrad:** `MEDIUM` - **Zeitpunkt:** `V1` - **Problem:** „Logs dürfen nicht manipulierbar sein" steht als Anforderung, aber kein Mechanismus ist beschrieben. Eine normale DB-Tabelle ist manipulierbar. - **Empfehlung:** Mindestens Append-only-Tabelle ohne UPDATE/DELETE-Berechtigung des App-Users, Hash-Chain der Einträge, regelmäßiger Export in WORM-Storage oder externes Audit-Sink. ADR. --- ## R-15 — Tenant-Offboarding und Datenexport nicht definiert - **Schweregrad:** `HIGH` - **Zeitpunkt:** `V2` - **Problem:** Wenn ein Mandant das System verlässt, muss er DSGVO-konform seine Daten erhalten (Datenportabilität) und der Plattformbetreiber muss löschen. Kein Konzept im Bestand. - **Empfehlung:** Tenant-Lifecycle-Domäne entwerfen. Export-Format: maschinenlesbar (JSON Lines, oder pro-Tenant DB-Dump bei DB-per-Tenant-Modell). Aufbewahrungspflichten der GoBD beachten. --- ## R-16 — Steuer-/MwSt-Logik komplett fehlend - **Schweregrad:** `HIGH` - **Zeitpunkt:** `V1` - **Problem:** Im gesamten Bestand kein Wort zu MwSt-Sätzen, OSS (One-Stop-Shop für EU-B2C), Reverse Charge B2B EU, oder MwSt-Befreiungen. Eine Rechnungs-Software ohne Steuermodell ist nicht produktiv einsetzbar. - **Empfehlung:** Minimal-Modell für V1: deutscher Standardfall (19%/7%/0%), B2B/B2C-Flag pro Kunde, Erweiterbarkeit für OSS in V2. ADR + Daten-Modell-Update. --- ## R-17 — Reseller-Hierarchie V3 ohne V1-Vorbereitung - **Schweregrad:** `HIGH` - **Zeitpunkt:** `NOW` - **Problem:** V3 verspricht „Resellerstrukturen" und „tiefere Mandantenfähigkeit". Das setzt mindestens dreistufige Hierarchie (Plattform → Reseller → Endkunde) voraus. V1 plant zweistufig oder einstufig (siehe R-01). Ohne saubere Hierarchie-Definition heute wird V3 ein Modellbruch. - **Empfehlung:** Hierarchie als Datenmodell-Entscheidung heute festlegen (selbst wenn V1 nur eine Ebene aktiv nutzt). ADR. Tabelle `tenants` mit `parent_tenant_id` als Vorbereitung. --- ## R-18 — Fehlerresilienz für Integrationen nicht entworfen - **Schweregrad:** `MEDIUM` - **Zeitpunkt:** `V1` - **Problem:** Adapter-Anforderungen sagen „Fehlerbehandlung" – aber Retry-Strategie, Backoff, Circuit Breaker, Dead-Letter-Queue, Reconciliation bei inkonsistentem Zustand sind nicht beschrieben. Bei Domain-Renewal kann ein nicht behandelter Adapter-Fehler einen geschäftskritischen Datenverlust bedeuten. - **Empfehlung:** Standardpattern für alle Adapter: Retry mit exponentiellem Backoff, Circuit Breaker, Dead Letter, Reconciliation-Job nightly. Job-Status sichtbar im UI. --- ## R-19 — API-Versionierungsstrategie unvollständig - **Schweregrad:** `MEDIUM` - **Zeitpunkt:** `V1` - **Problem:** Nur Pfad-Versionierung (`/api/v1/`) ohne Deprecation/Sunset/Compatibility-Strategie. Bei API-first-Anspruch zu wenig. - **Empfehlung:** ADR mit klaren Regeln: Breaking Changes nur über neue Major-Version, Minor-Changes additiv, Deprecation-Header (`Deprecation`, `Sunset`), Mindest-Support-Zeitraum für ältere Versionen. --- ## R-20 — Nummernkreise pro Mandant ohne Mechanismus - **Schweregrad:** `HIGH` - **Zeitpunkt:** `V1` - **Problem:** Rechnungsnummern müssen lückenlos sein und pro Mandant separat. Kunden-, Vertrags-, Rechnungsnummern: pro Mandant? Global? Konfigurierbar? Aktuell nicht modelliert. - **Empfehlung:** Dedicate Sequence-Tabelle pro Mandant und pro Nummernkreis. Atomic-Increment mit DB-Lock. Konfigurierbares Format (Präfix, Padding, Reset-Verhalten). Pflicht für GoBD-Konformität. --- ## R-21 — Personen-/Adressmodell als undifferenziertes Bündel - **Schweregrad:** `MEDIUM` - **Zeitpunkt:** `NOW` - **Problem:** `Kunde` enthält „Stammdaten + Ansprechpartner + Kontaktdaten" als monolithisches Objekt. Klassisches Anti-Pattern. Erschwert DSGVO-Auskunft/Löschung, B2B-Modell, Mehrfach-Ansprechpartner, getrennte Rechnungs-/Postanschriften. - **Empfehlung:** Trennung in `Party` (Person oder Organisation) + `Address` (mit Verwendungszweck: Rechnung/Post/Rechtssitz) + `ContactPoint` (Mail/Tel/etc. mit Verwendungszweck). N:M zwischen Customer und Party für Ansprechpartner. --- ## R-22 — WordPress-Plugin als zweite Sicherheitsdomäne - **Schweregrad:** `MEDIUM` - **Zeitpunkt:** `V2` - **Problem:** Plugin ist API-Client mit eigener Session-Domäne, eigenem Update-Lifecycle, eigener Plugin-Ökosystem-Risikofläche. Wenn die WP-Site kompromittiert ist, sind die API-Tokens des Plugins gefährdet. Aktuell ist nicht definiert, welche Scopes das Plugin erhält und wie kompromittierte Tokens rotiert werden. - **Empfehlung:** Plugin nur mit minimal-Scope-Token. Token-Revocation aus Admin-UI. Lifetime begrenzen. Audit-Log bei jeder Plugin-API-Nutzung. Strategie für Sandbox-Tests bei kompromittiertem WP-Setup. --- ## R-23 — Frontend-Strategie offen widerspricht API-first-Anspruch - **Schweregrad:** `MEDIUM` - **Zeitpunkt:** `NOW` - **Problem:** „Blade oder später Vue/Nuxt" lässt eine fundamentale Architekturentscheidung offen. Klassischer Laravel-Monolith mit angeflanschter API ist eine andere Architekturklasse als ein API-first-System mit echtem SPA-Client. - **Empfehlung:** ADR. Entweder Blade-als-API-Konsument (Blade-Views rufen interne API auf, kein direkter DB-Zugriff aus Views) oder Vue-/Nuxt-SPA. Nicht „später". --- ## R-24 — BFSG / Barrierefreiheit für Customer Portal - **Schweregrad:** `MEDIUM` - **Zeitpunkt:** `V1` (falls Portal in V1) / `V2` - **Problem:** Seit 28. Juni 2025 sind in der EU kommerzielle digitale Dienste an Verbraucher barrierefrei zu gestalten (BFSG, Umsetzung der EU-Richtlinie 2019/882). Customer Portal fällt darunter. - **Empfehlung:** UI-Komponenten und Frontend-Stack barrierefrei gestalten (WCAG 2.1 AA als Ziel). Wenn Portal aus V1 raus ist (R-13), entschärft sich das auf V2. --- ## R-25 — Modul-Lifecycle (Deinstallation, Datenreferenzen) ungeklärt - **Schweregrad:** `MEDIUM` - **Zeitpunkt:** `V1` - **Problem:** Module sollen aktivierbar/deaktivierbar sein. Was passiert mit referenzierten Daten in anderen Modulen, wenn ein Modul deinstalliert wird? Was passiert bei Re-Installation? Diese Semantik ist nirgendwo beschrieben. - **Empfehlung:** Modul-Lifecycle definieren: aktivieren / deaktivieren (Daten bleiben) / deinstallieren (Daten archivieren, optional löschen). Dependencies zwischen Modulen explizit deklarieren. Migrations-Strategie bei Re-Installation. --- ## R-26 — Logging-/Audit-Sink-Architektur unspezifiziert - **Schweregrad:** `MEDIUM` - **Zeitpunkt:** `V1` - **Problem:** Logging-Strategie sagt was geloggt werden soll, aber nicht wohin oder wie. App-Logs vs. Audit-Logs sind getrennt, aber Speicherort, Retention, Mandantenscope, Integritätsschutz fehlen. - **Empfehlung:** Drei getrennte Senken: App-Logs (lokal, kurzfristig, optional externer Aggregator wie Loki/Sentry), Audit-Logs (DB-Append-only, langfristig, pro Mandant), Security-Logs (Login, Auth-Fehler, Admin-Aktionen, separat). --- ## R-27 — „Vorbereitende" Felder ohne Verwendung in V1 - **Schweregrad:** `LOW` - **Zeitpunkt:** `NOW` - **Problem:** Mehrfach „… später möglich" als Feld-Anmerkung (Server.Rollen später, Hostingpaket.Ressourcen später, Gebührenregeln später). Erfahrung: solche Felder werden entweder nie genutzt oder mit Bedeutung versehen, die nicht zur ursprünglichen Form passt. - **Empfehlung:** „Später"-Felder aus dem v0.1-Datenmodell entfernen. Wenn ein Feld V1 nicht braucht, wird es V1 nicht migriert. Bei Bedarf später eigene Migration. --- ## R-28 — Mehrere parallele Single Sources of Truth - **Schweregrad:** `LOW` (organisatorisch) / `HIGH` (in Konsequenz) - **Zeitpunkt:** `NOW` - **Problem:** Strategie-Dokumente, Modul-Dokumente, Roadmap und MVP-Liste enthalten sich widersprechende Aussagen (siehe R-04, R-13). Ohne klare Hierarchie zwischen den Dokumenten wird im Code-Schritt jede Person eine andere Variante implementieren. - **Empfehlung:** Dokumenthierarchie festlegen: ADRs > Strategie-Dokumente > Modul-Beschreibungen > Roadmap. Konflikte werden in dieser Reihenfolge aufgelöst. Bei Konflikt: ADR ergänzen oder Strategie-Doc aktualisieren, untere Ebenen nachziehen. --- ## Zusammenfassende Priorisierung **CRITICAL / NOW** (vor Codebeginn unverzichtbar): - R-01 Mandantenfähigkeits-Mechanismus - R-02 Anbieterlogik aus Core entfernen - R-03 Billing aus Core entfernen - R-05 Secrets-Management **HIGH / NOW** (vor Codebeginn entscheiden): - R-04 Modulstruktur als einzige Wahrheit - R-06 Core verkleinern - R-09 API-Auth-Strategie - R-10 Datenbank-Engine - R-11 KI-Scope-Entscheidung - R-13 V1-Scope vereinheitlichen - R-17 Reseller-Hierarchie-Vorbereitung - R-21 Personen-/Adressmodell - R-23 Frontend-Strategie - R-28 Dokumenten-Hierarchie **HIGH / V1** (muss in V1 enthalten sein): - R-07 GoBD-Verantwortlichkeit - R-08 DSGVO-Löschung-Modell - R-16 Steuer-/MwSt-Logik - R-20 Nummernkreise **MEDIUM / V1**: - R-12 SEPA-Modell oder raus - R-14 Audit-Unveränderbarkeit - R-18 Adapter-Fehlerresilienz - R-19 API-Versionierung - R-24 Barrierefreiheit (falls Portal in V1) - R-25 Modul-Lifecycle - R-26 Logging-Architektur **MEDIUM/HIGH / V2-V3**: - R-15 Tenant-Offboarding - R-22 WP-Plugin-Sicherheitsmodell - R-24 Barrierefreiheit (Portal in V2) **LOW / NOW**: - R-27 Spekulative Felder entfernen --- Die Gesamtbotschaft: Die Anzahl der CRITICAL/NOW-Punkte (4) ist überschaubar und alle in 2–4 Wochen entscheidungsreif. Die HIGH/NOW-Punkte (10) sind ADR-Material. Wenn diese 14 Punkte vor Codebeginn entschieden sind, hat das Projekt eine sehr gute Ausgangslage. Werden sie nicht entschieden, ist V1 voraussichtlich produktiv nutzbar, aber V2/V3 wird teurer als V1 selbst.