# ADR 0004 — Tenancy-Modell ## Status Accepted ## Kurz erklärt Tenancy bedeutet Mandantenfähigkeit. Ein Mandant ist z. B. ein Anbieter, eine Agentur oder später ein Reseller, der seine eigenen Kunden, Verträge, Domains und Rechnungen verwaltet. Das Tenancy-Modell legt fest, wie Daten verschiedener Mandanten technisch voneinander getrennt werden. ## Kontext Hosting-Backoffice soll zunächst einfach nutzbar sein, später aber mandantenfähig und ggf. resellerfähig erweitert werden können. Die bisherige Planung enthielt die Begriffe `tenant_id` und `organisation_id`, ohne deren Verhältnis eindeutig zu definieren. Das wurde im Architekturreview als kritisches Risiko bewertet, da eine nachträgliche Mandantenfähigkeit sehr teuer und fehleranfällig wäre. ## Entscheidung Hosting-Backoffice verwendet von Beginn an ein mandantenfähiges Datenmodell mit: - `tenant_id` als zentrale Mandantenreferenz - Shared Database Modell - PostgreSQL als bevorzugte Datenbank - Tenant Scope auf Anwendungsebene - Row Level Security als spätere zusätzliche Sicherheitsschicht `organisation_id` wird vorerst nicht als separates Standardfeld verwendet. Falls später eine Organisationshierarchie benötigt wird, wird diese über das Tenant-Modell abgebildet. ## Gewähltes Modell ```text Platform └── Tenant └── Kunde └── Verträge └── Domains └── Hostingpakete └── Tickets └── Dokumente ``` Später möglich: ```text Platform └── Tenant └── Reseller-Tenant └── Kunden ``` Dafür kann später ein Feld wie `parent_tenant_id` in der Tenant-Struktur ergänzt oder vorbereitet werden. ## Begründung Ein Shared-Database-Modell mit `tenant_id` ist für den Start sinnvoll, weil: - V1 klein bleiben soll - alle Daten zentral verwaltbar bleiben - Migrationen einfacher sind - Betrieb und Backups weniger komplex sind - spätere Mandantenfähigkeit vorbereitet wird - Resellerstrukturen später möglich bleiben PostgreSQL wird bevorzugt, weil es Row Level Security unterstützt. Row Level Security bedeutet: ```text Die Datenbank selbst kann verhindern, dass Mandant A Datensätze von Mandant B sieht. ``` Das ist eine zusätzliche Sicherheitsschicht neben der Anwendung. ## Konsequenzen ### Positiv - Mandantenfähigkeit wird nicht später „angeklebt“ - bessere Grundlage für spätere SaaS-/Resellerfähigkeit - klare Datenisolation - bessere Sicherheitsarchitektur - weniger Refactoring-Risiko ### Negativ - jede mandantenbezogene Tabelle braucht `tenant_id` - alle Abfragen müssen tenant-aware sein - Entwickler müssen von Anfang an sauber mit Tenant-Kontext arbeiten - Tests müssen Mandantenisolation prüfen ## Technische Leitlinien Alle mandantenbezogenen Tabellen erhalten: ```text tenant_id ``` Beispiele: ```text customers.tenant_id contracts.tenant_id domains.tenant_id hosting_packages.tenant_id tickets.tenant_id documents.tenant_id ``` Nicht mandantenbezogene Tabellen können global sein, z. B.: ```text system_settings module_registry global_permissions ``` ## Anwendungsebene Laravel soll sicherstellen, dass mandantenbezogene Daten nur im aktuellen Tenant-Kontext geladen werden. Dafür vorgesehen: - Tenant Context - Eloquent Global Scopes - Policies - Tests gegen Tenant-Leaks Tenant-Leak bedeutet: ```text Ein Benutzer oder Prozess sieht versehentlich Daten eines anderen Mandanten. ``` ## Datenbankebene PostgreSQL Row Level Security soll als spätere zweite Schutzschicht vorbereitet werden. V1 kann zunächst mit sauberem Tenant Scope in Laravel starten. RLS sollte jedoch nicht durch Datenmodellentscheidungen blockiert werden. ## Offene Punkte Noch zu klären: - genaue Tenant-Tabelle - ob `parent_tenant_id` sofort angelegt wird - ob V1 technisch bereits echtes Multi-Tenant-Login erlaubt - wie Plattform-Admins mandantenübergreifend arbeiten dürfen - wie Tenant-Offboarding später funktioniert ## Nicht entschieden Diese ADR entscheidet noch nicht: - ob Hosting-Backoffice später SaaS oder nur self-hosted wird - ob einzelne Mandanten später eigene Datenbanken erhalten können - ob Resellerstrukturen bereits in V1 aktiv sichtbar sind ## Verwandte ADRs - ADR 0005 — Datenbankwahl - ADR 0006 — Auth-Strategie - ADR 0009 — Core-Grenzen - ADR 0011 — GoBD-Verantwortlichkeit