## 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.