Zum Inhalt

Test-Daten-Cleanup (TODO-UX-02)

Operator-Tool, um akkumulierte E2E-/Bench-Test-Daten aus der Live-kora-platform-DB zu entfernen. Nutzt scripts/cleanup-test-data.sh. Wird manuell ausgeführt — keine CI-Automatisierung, kein Pytest-Hook (Pytest-Hook-Variante wäre der saubere Endzustand, ist aber bewusst out-of-scope von TODO-UX-02).

Wann brauche ich das?

  • Vor jedem AVS-Demo-Zugang. Nach längeren E2E-Test-Phasen sammelt die DB Test-Tenants (e2e-conflict-*, e2e-happy-*, e2e-bulk-*, e2e-mod-*) und Test-Templates (e2e-conf-*, e2e-tpl-*) an, die in der Operator-UI sichtbar sind.
  • Vor v1.0.0-GA. Spätestens.
  • Wenn in der Operator-UI-Tenants-Liste mehr als ein paar Dutzend Einträge stehen und du die Demo-/Live-Trennung schärfen willst.

Aufruf

Default — Dry-Run, nur e2e-*

set -a && source .env.platform && set +a   # POSTGRES_USER/_DB lesen
make cleanup-test-data

Output zeigt:

  • Zu löschende Tenants- und Template-Anzahl
  • CASCADE-FK-Effekte (informativ — werden vom DELETE automatisch mitgenommen): tenant_packages, tenant_branding, chatbots, credentials, tenant_modules
  • Pre-Flight NO-ACTION-FK-Sicherheits-Check: alle müssen 0 sein, sonst Abbruch (siehe „Edge-Cases" unten)

Kein DB-Touch.

Apply — mit Confirm-Prompt

make cleanup-test-data-apply

Zeigt erst denselben Plan wie der Dry-Run, dann fragt: [yes/NO]:. Nur die exakte Eingabe yes führt das Lösch-DELETE aus. Lösch- Operation läuft in einer Transaktion — bei jedem Fehler vollständiger Rollback.

Apply — Bench-Tenants mit einbeziehen

bench-tenant-a + bench-tenant-b werden vom Default-Pattern bewusst nicht angefasst (sie dienen als Demo-Daten und werden von gen-test-tokens.sh reconciled). Für eine vollständige Säuberung explizit opt-in:

make cleanup-test-data-apply args=--include-bench

⚠️ Falls du das tust, läuft gen-test-tokens.sh beim nächsten E2E-Lauf erneut und legt sie wieder an — also nur sinnvoll, wenn für eine Demo wirklich kein Test-Tenant in der UI auftauchen soll.

Apply — Auth-Test-Pollution (op-vendor-*) mit einbeziehen

op-vendor-write-<hash> (und ähnliche Slugs) entstehen aus Auth-Test-Token-Generator-Runs. Default-Cleanup übersieht sie. Für eine zusätzliche Klasse:

# Convenience-Targets:
make cleanup-test-data-include-test         # Dry-Run
make cleanup-test-data-include-test-apply   # Apply mit Confirm

# Oder via args= an die generischen Targets:
make cleanup-test-data-apply args=--include-test
make cleanup-test-data-apply args="--include-bench --include-test"  # alle drei Klassen

Pattern erweiterbar: das Skript nutzt op-vendor-% und kann durch einen weiteren if [[ "$INCLUDE_TEST" == 1 ]]; then ...-Block um weitere Auth-/Service-Test-Klassen erweitert werden, ohne neuen Flag einzuführen.

CI / Skript-Modus (kein Confirm)

scripts/cleanup-test-data.sh --apply --yes

Nur für Maschinen-Aufrufe; in interaktiven Umgebungen lieber das Confirm-Prompt nutzen.

Was wird gelöscht?

Tabelle Pattern Mechanismus
tenants slug LIKE 'e2e-%' (+ 'bench-%' mit --include-bench, + 'op-vendor-%' mit --include-test) direkter DELETE
chatbot_templates id LIKE 'e2e-%' (+ 'bench-%', + 'op-vendor-%' analog) direkter DELETE
tenant_packages per Tenant CASCADE-FK
tenant_branding per Tenant CASCADE-FK
chatbots per Tenant CASCADE-FK
credentials per Tenant CASCADE-FK
tenant_modules per Tenant CASCADE-FK
evaluation_questions per Template CASCADE-FK

Was wird NICHT gelöscht?

Was Warum
platform_audit_log Audit-History bleibt vollständig erhalten — auch von gelöschten Tenants. Audit-Zeilen referenzieren den Tenant-UUID weiter über die entity_id-Spalte (string). Die tenant_id-FK-Spalte ist nullable und im Discovery-Befund (TODO-UX-02 Phase 1) leer für e2e/bench
Keycloak-User Out-of-Scope — separater Cleanup-Pfad, falls je nötig
Bench-Tenants ohne --include-bench Demo-Daten, opt-in
op-vendor-*-Tenants ohne --include-test Auth-Test-Token-Generator-Pollution, opt-in
chatbots mit template_id aus zu löschenden Templates NO-ACTION-FK; Pre-Flight bricht ab, falls solche Chatbots existieren — du musst sie erst manuell auflösen

Edge-Cases

NO-ACTION-FK-Pre-Flight scheitert

Beispiel-Fehlermeldung:

Pre-Flight NO-ACTION-FKs (müssen 0 sein, sonst Abbruch):
  platform_audit_log.tenant_id             0
  chatbot_sources                          5    ← non-zero
  ...
ABBRUCH: NO-ACTION-FK-Pre-Flight scheiterte — 1 Tabelle(n)
        haben referenzierte Rows. DELETE würde mit Foreign-Key-Violation abbrechen.

Bedeutet: ein zu löschender Tenant hat „echte" Daten (Source-Konnektor, Chat-Session, …), die nicht via CASCADE mitgenommen werden. Cleanup fasst diese Tabellen per Scope-Boundary nicht an. Manuelle Untersuchung mit psql (z.B. SELECT * FROM chatbot_sources WHERE tenant_id IN (SELECT id FROM tenants WHERE slug LIKE 'e2e-%')) und Entscheidung, ob das wirklich ein Test-Tenant ist (dann manuell löschen oder den Tenant umbenennen, damit er nicht mehr ins Pattern fällt).

DB-Connection-Fehler

ERROR: DB-Container 'kora-platform-postgres' läuft nicht.

Stack starten mit make dev-platform. Oder DB_CONTAINER-Env setzen, falls in einer anderen Umgebung gearbeitet wird.

ERROR: DB-Connection fehlgeschlagen (User=kora_platform, DB=kora_platform).
       Source .env.platform: 'set -a && source .env.platform && set +a'

.env.platform nicht in der Shell — vorher sourcen.

Apply ohne Confirm abgebrochen

Beim Confirm-Prompt etwas anderes als yes eingegeben:

Tatsächlich löschen? [yes/NO]: n
Abgebrochen — keine Änderungen.

Idempotent — kein DB-Touch.

Idempotenz nach erfolgreichem Apply

Keine Test-Daten gefunden — nichts zu tun.

Ist der Erfolgs-Marker für „der Stack ist sauber".

Verifikation nach Apply

# 1. Skript erneut → Idempotenz-Bestätigung
make cleanup-test-data
# Erwartet: "Keine Test-Daten gefunden"

# 2. Direkte DB-Abfrage
docker exec -i kora-platform-postgres psql -U "$POSTGRES_USER" -d "$POSTGRES_DB" -t -A \
  -c "SELECT COUNT(*) FROM tenants WHERE slug LIKE 'e2e-%' OR slug LIKE 'bench-%';"
# Erwartet: 0 (mit --include-bench) oder 2 (ohne, bench-tenant-a/-b verbleiben)

# 3. Operator-UI Tenants-Liste neu laden — keine e2e-* mehr sichtbar.
# 4. Audit-Log unter /admin/operator/audit weiterhin vollständig sichtbar
#    (entity_type=tenant, entity_id=<UUID des gelöschten Tenants>).

Was nach v1.0.0?

Saubere Lösung wäre ein Pytest-Hook, der nach jedem E2E-Lauf die erzeugten Items wieder abräumt — e2e-*-Pollution würde dann gar nicht erst entstehen. Dieser Pfad ist out-of-scope von TODO-UX-02 (Workflow-Eingriff in alle Test-Suites), könnte aber in einem späteren Block (z.B. parallel zu Block 14 CI-Roll-Out) ergänzt werden.

Bis dahin: dieser Cleanup ist der Manual-Operator-Knopf vor jedem externen Demo-Zugang.

Letzte Aktualisierung

00ee4a48ff481c0d016e5ede298320ff5342c95c (TODO-UX-02-Merge), 2026-04-27.