Add AI workspace reviews

This commit is contained in:
2026-05-18 04:37:23 +00:00
commit 7ac1371aff
106 changed files with 5378 additions and 0 deletions
@@ -0,0 +1,472 @@
## 1. Zusammenfassung
Claude benennt valide Architektur-Risiken. Für das Projekt werden daraus keine neuen Produktziele abgeleitet, sondern konkrete Korrekturen an Datenmodell, Security-Dokumentation, ADRs und Betriebsregeln.
Kernentscheidungen:
- `tenant_id` wird der einzige technische Mandanten-Isolationsschlüssel.
- `organisation_id` wird nicht mehr für Tenant-Isolation verwendet.
- Multi-Tenancy wird nicht „halb vorbereitet“, sondern technisch sauber in V1 angelegt.
- Secrets werden nicht im Domainmodell gespeichert, sondern nur referenziert.
- Audit-Hash-Chain wird nicht als manipulationssichere Security-Maßnahme verkauft.
- DLQ, Dokumente, Rollen und Reconciliation erhalten konkrete Regeln.
- Bounded Contexts werden als Modul-/Schema-Grenzen dokumentiert, keine Microservice-Aufspaltung.
---
## 2. Übernommene Punkte
### Tenant-Isolation
Übernehmen.
Änderung:
- `tenant_id` ist Pflichtfeld auf allen mandantenbezogenen Tabellen.
- `organisation_id` wird aus der technischen Isolation entfernt.
- Falls Organisation benötigt wird, dann nur fachlich, z. B. als `customer_organisation_id`.
- PostgreSQL Row-Level-Security wird vorgesehen.
- Tenant-Kontext wird pro Request/Job explizit gesetzt.
- Queries ohne Tenant-Kontext müssen fehlschlagen.
Konkrete Modellregel:
```text
tenant_id UUID NOT NULL REFERENCES tenants(id)
```
Für mandantenbezogene Relationen:
```text
FOREIGN KEY (tenant_id, customer_id)
REFERENCES customers(tenant_id, id)
```
---
### Secrets-Management
Übernehmen.
Änderung:
- Keine API-Keys, Passwörter oder Tokens in Fachentitäten.
- Domainmodelle speichern nur `secret_ref`.
- Secret-Service wird als technischer Baustein dokumentiert.
- Encryption-at-rest wird verpflichtend für Secret-Storage.
- Zugriff auf Secrets nur über Service-Layer, nicht über direkte DB-Reads.
Beispiel:
```text
registrar_accounts.secret_ref
```
statt:
```text
registrar_accounts.api_key
registrar_accounts.password
```
---
### Audit-Log
Teilweise übernehmen.
Änderung:
- Hash-Chain wird nicht als Schutz gegen DB-Admin-Manipulation beschrieben.
- Audit-Log bleibt append-only auf Anwendungsebene.
- Integritätsprüfung wird klar abgegrenzt.
- Optional: periodischer Export/Checkpoint in externes System.
ADR 0014 muss entsprechend korrigiert werden.
---
### Dead Letter Queue
Übernehmen.
Änderung:
- DLQ erhält Retention-Regeln.
- PII in Fehlerpayloads wird vermieden oder redaktiert.
- Maximale Aufbewahrung wird festgelegt.
- Reprocessing und Löschung werden beschrieben.
Vorschlag:
```text
DLQ default retention: 30 Tage
DLQ max retention: 90 Tage
PII payloads: nicht speichern oder redaktieren
```
---
### Bounded Contexts
Übernehmen, aber pragmatisch.
Änderung:
- Keine sofortige Service-Aufteilung.
- Einführung klarer Modulgrenzen im Monolithen.
- Datenmodell wird nach fachlichen Bereichen gegliedert.
Kontexte:
- Identity & Access
- CRM
- Billing
- Provisioning
- Registry
- Support
- Documents
- Audit
---
### Reconciliation
Teilweise übernehmen.
Änderung:
- Kein vollständiges Event-Sourcing für V1.
- Stattdessen Operation-/Job-Historie und Status-Snapshots.
- Reconciliation basiert auf:
- gewünschtem Zustand
- aktuellem externem Zustand
- letzter Operation
- Fehlerhistorie
Benötigte Tabellen/Modelle:
```text
provisioning_operations
external_resource_snapshots
job_runs
job_attempts
```
---
### Rollen und Scopes
Übernehmen.
Änderung:
- Rollen werden nicht nur benannt, sondern mit konkreten Berechtigungen dokumentiert.
- Zugriff auf Secrets, Rechnungen, Serverdaten und Kundendaten wird explizit geregelt.
Beispielrollen:
- Owner
- Admin
- Billing
- Support
- Provisioning Operator
- Read-only Auditor
---
### Dokument-Storage
Übernehmen.
Änderung:
- Dokumente speichern keine Datei direkt im Datenmodell.
- Dokumente referenzieren Object Storage.
- Tenant-Isolation über Bucket/Prefix plus DB-Zugriffskontrolle.
- Löschung, Archivierung und Legal Hold werden dokumentiert.
Beispiel:
```text
documents.object_key
documents.storage_provider
documents.checksum_sha256
documents.retention_until
documents.legal_hold
documents.deleted_at
```
---
## 3. Abgelehnte oder verschobene Punkte
### Vollständiges Event-Sourcing
Verschoben.
Begründung:
- Für V1 nicht erforderlich.
- Reconciliation kann über Operation-Historie, Job-Historie und Snapshots umgesetzt werden.
---
### Microservice-Aufteilung nach Bounded Contexts
Abgelehnt für V1.
Begründung:
- Zu hoher Betriebs- und Integrationsaufwand.
- Modulgrenzen im Monolithen reichen aktuell aus.
---
### Audit-Hash-Chain als Manipulationsschutz
Abgelehnt.
Änderung:
- Hash-Chain darf maximal als Integritätsindikator beschrieben werden.
- Kein Sicherheitsversprechen gegen privilegierte DB-Manipulation.
---
### Parallele Nutzung von `organisation_id` und `tenant_id`
Abgelehnt.
Änderung:
- Nur `tenant_id` ist technischer Scope.
- Organisation ist, falls benötigt, ein CRM-/Kundenkonzept.
---
### Single-Tenant V1 ohne Tenant-Schutz
Abgelehnt.
Änderung:
- V1 darf fachlich nur einen aktiven Tenant haben.
- Technisch wird Tenant-Isolation trotzdem sauber eingebaut.
---
## 4. Neue/geänderte Dateien
### Geändert
#### `docs/data-model-v0.2.md`
Änderungen:
- `organisation_id` aus technischer Mandanten-Isolation entfernen.
- `tenant_id` als verbindlichen Scope definieren.
- Tenant-FK-Regeln ergänzen.
- Tabellen nach Bounded Contexts gruppieren.
- Secret-Felder durch `secret_ref` ersetzen.
- Dokumentmodell um Storage-Metadaten erweitern.
- Operation-/Job-Historie ergänzen.
---
#### `docs/security.md`
Änderungen:
- Tenant-Isolation konkretisieren.
- Secrets-Management konkretisieren.
- RBAC/Scopes verlinken.
- RLS und Tenant-Kontext als Pflichtmechanismus aufnehmen.
---
#### `docs/adr/0014-audit-log.md`
Änderungen:
- Hash-Chain nicht mehr als manipulationssicher beschreiben.
- Algorithmus konkretisieren, falls beibehalten.
- Optionalen externen Checkpoint/Export dokumentieren.
- Grenzen des Mechanismus explizit nennen.
---
#### `docs/adr/0017-jobs-reconciliation-dlq.md`
Änderungen:
- DLQ-Retention ergänzen.
- PII-Regeln ergänzen.
- Reprocessing-Regeln ergänzen.
- Reconciliation-Datenbasis ergänzen.
---
### Neu
#### `docs/architecture/tenant-isolation.md`
Inhalt:
- `tenant_id` als einziger technischer Mandantenschlüssel
- Request-/Job-Tenant-Kontext
- Fail-closed-Verhalten
- RLS-Grundregeln
- Cross-Tenant-Zugriffe verboten
- Composite FK-Regeln
---
#### `docs/architecture/bounded-contexts.md`
Inhalt:
- Modulgrenzen
- erlaubte Abhängigkeiten
- Besitz von Tabellen/Entitäten
- keine direkten Fremdzugriffe zwischen Kontexten ohne definierte Schnittstelle
---
#### `docs/security/secrets-management.md`
Inhalt:
- Secret-Service-Konzept
- `secret_ref`
- keine Klartext-Secrets in DB
- Rotation
- Zugriffskontrolle
- Auditierung von Secret-Zugriffen
---
#### `docs/security/rbac-matrix.md`
Inhalt:
| Bereich | Owner | Admin | Billing | Support | Provisioning | Auditor |
|---|---:|---:|---:|---:|---:|---:|
| Kunden lesen | ja | ja | ja | ja | ja | ja |
| Kunden ändern | ja | ja | nein | eingeschränkt | nein | nein |
| Rechnungen lesen | ja | ja | ja | nein | nein | ja |
| Rechnungen ändern | ja | ja | ja | nein | nein | nein |
| Serverdaten lesen | ja | ja | nein | eingeschränkt | ja | ja |
| Server ändern | ja | ja | nein | nein | ja | nein |
| Secrets lesen | nein | nein | nein | nein | nein | nein |
| Secret nutzen | ja | ja | nein | nein | system | nein |
---
#### `docs/storage/document-storage.md`
Inhalt:
- Object-Storage-Strategie
- Tenant-Isolation per Prefix/Bucket
- Checksums
- Archivierung
- Löschanfragen
- Legal Hold
- Zugriffskontrolle
---
#### `docs/operations/dlq-retention.md`
Inhalt:
- DLQ-Retention
- PII-Regeln
- Reprocessing
- manuelle Freigabe
- endgültige Löschung
- Monitoring
---
#### `docs/operations/reconciliation.md`
Inhalt:
- gewünschter Zustand
- externer Ist-Zustand
- Operation-Historie
- Snapshot-Modell
- Konfliktbehandlung
- Retry-Strategie
---
#### `db/policies/tenant_rls.sql`
Inhalt:
- PostgreSQL RLS-Grundstruktur
- Policy pro mandantenbezogener Tabelle
- Nutzung von `current_setting('app.tenant_id')`
- Fail-closed bei fehlendem Tenant-Kontext
Beispiel:
```sql
ALTER TABLE customers ENABLE ROW LEVEL SECURITY;
CREATE POLICY tenant_isolation_customers
ON customers
USING (
tenant_id = current_setting('app.tenant_id')::uuid
);
```
---
#### `db/migrations/xxxx_add_tenant_scope.sql`
Inhalt:
- `tenants`-Tabelle
- `tenant_id` auf mandantenbezogenen Tabellen
- NOT NULL Constraints
- Composite Foreign Keys
- Indizes auf `(tenant_id, id)`
---
## 5. Konkrete nächste Schritte
1. `docs/data-model-v0.2.md` anpassen:
- `tenant_id` festlegen
- `organisation_id` aus Isolation entfernen
- Secret-Felder durch `secret_ref` ersetzen
2. `docs/architecture/tenant-isolation.md` neu erstellen.
3. `db/migrations/xxxx_add_tenant_scope.sql` vorbereiten:
- `tenants`
- `tenant_id`
- Constraints
- Indizes
4. `db/policies/tenant_rls.sql` erstellen.
5. `docs/security/secrets-management.md` erstellen.
6. `docs/security/rbac-matrix.md` erstellen.
7. ADR 0014 überarbeiten:
- keine falsche Sicherheitsbehauptung zur Hash-Chain
8. ADR 0017 überarbeiten:
- DLQ-Retention
- PII-Regeln
- Reconciliation-Datenbasis
9. `docs/storage/document-storage.md` erstellen.
10. `docs/architecture/bounded-contexts.md` erstellen und Datenmodell danach gruppieren.