163 lines
4.3 KiB
Markdown
163 lines
4.3 KiB
Markdown
# 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
|