feat(superadmin): migrate internal docs from docusaurus to guava kb
Some checks failed
linter / quality (push) Has been cancelled
tests / ci (push) Has been cancelled
tests / ui (push) Has been cancelled

This commit is contained in:
Codex Agent
2026-02-07 09:58:39 +01:00
parent 1d2242fb4d
commit fb45d1f6ab
77 changed files with 3813 additions and 18636 deletions

View File

@@ -0,0 +1,78 @@
---
title: Major Incidents & Eskalation
---
Diese Seite beschreibt, wie du bei größeren Störungen (SEV1/SEV2) vorgehst. Sie ergänzt die spezifischen Runbooks (Public API, MedienPipeline, Photobooth) um einen einheitlichen Rahmen.
## 1. Incident-Klassifikation
- **SEV1 (kritisch)**
- Gäste können nicht mehr hochladen ODER keine Events/Galerien mehr öffnen.
- Tenant Admins können sich nicht einloggen oder keine Kernaktionen ausführen (Events verwalten, Medien moderieren).
- Datenverlust oder potenzieller Datenverlust (z.B. Löschjob auf falscher StorageEbene).
- **SEV2 (hoch)**
- Teilweise Degradation (z.B. PhotoboothUploads hängen, PublicAPI stark verlangsamt, eine Region betroffen).
- Kritische BackgroundJobs (Archivierung, AV/EXIFScans, ZahlungsWebhooks) stauen sich, ohne dass Gäste sofort komplett blockiert sind.
- **SEV3 (mittel)**
- Einzelne Features gestört (NotificationCenter, JoinTokenAnalytics, einzelne AdminViews).
- Workaround möglich (z.B. manuelle Nacharbeit durch Support).
> Wichtig: Jede Störung, die einen zahlenden Eventkunden am Tag des Events blockiert, sollte mindestens als SEV2, ggf. als SEV1 eingeordnet werden.
## 2. Erstmaßnahmen (Triage)
1. **Scope bestimmen**
- Welche Benutzer sind betroffen? (Alle Gäste, einzelne Tenants, nur Photobooth, nur Admins?)
- Betrifft es nur eine Umgebung (staging vs. production)?
2. **Schnell-Checks**
- Status von App, Queue, Redis, DB (Docker/DokployÜbersicht prüfen).
- Horizon/Queues: sind relevante Queues leer, wachsend, „stuck“? Gibt es viele Failed Jobs?
- Logs für relevante Kanäle: `storage/logs/laravel.log`, spezielle Channels wie `storage-jobs`, `notifications`, `billing`, Nginx/ProxyLogs.
- Monitoring: externe UptimeChecks / Dashboards (z.B. PublicAPI Latenz, ErrorRate).
3. **Einordnung & Eskalation**
- SEV1/2: OnCall informieren (Pager/Chat), IncidentKanal im Teamchat eröffnen.
- SEV3: Im IssueTracker erfassen, ggf. gebündelt mit anderen Findings.
Nutze bei PublicAPIProblems zusätzlich das `docs/ops/deployment/public-api-incident-playbook.md`.
## 3. Standard-Runbooks nach Bereich
- **Public API / Gast-Zugriff**
- Siehe `docs/ops/deployment/public-api-incident-playbook.md`.
- Typische Auslöser: Peaks, Abuse, externe Integrationen, Ratenlimits.
- **Medien-Pipeline / Uploads**
- Siehe `docs/ops/media-storage-spec.md` und `docs/ops/guest-notification-ops.md`.
- Fälle: Uploads bleiben im Pending, Archivjobs laufen nicht, Speicherkapazität erreicht, Gäste bekommen „Uploads hängen noch…“.
- **Photobooth**
- Siehe `docs/ops/photobooth/ops_playbook.md`.
- Fälle: FTP nicht erreichbar, Ingest nicht laufend, falsche Credentials, SecurityVorfälle.
- **Abrechnung & Billing**
- Siehe `docs/ops/billing-ops.md`.
- Fälle: Lemon Squeezy/RevenueCatWebhookFehler, falsche PaketZustände, doppelte/fehlende Buchungen.
Dieses Dokument verweist immer nur auf die jeweils tieferen Runbooks bei konkreten Problemen gehst du dort in die Details.
## 4. Kommunikation
- **Intern (Team)**
- Eröffne einen dedizierten IncidentThread im Chat (mit Zeitstempel, SEVLevel, Kurzbeschreibung).
- Halte dort Statusupdates fest (z.B. „17:05 UploadQueue entstaut, weitere Beobachtung 30 min“).
- Notiere bewusst Entscheidungen (z.B. „19:10 Feature X temporär deaktiviert“, „19:25 Rollback auf vorheriges Release“).
- **Extern (Kunden)**
- Ab SEV2: Überlege einen kurzen Statushinweis (StatusSeite oder manuelle Kommunikation an direkt betroffene Tenants).
- Bei Incidents während Events: Koordiniere mit Success/Support, um proaktiv auf Tenant Admins zuzugehen.
> TODO: Falls du eine StatusSeite oder automatisierte EMails hast, dokumentiere hier, wie und wann sie ausgelöst werden.
## 5. Nachbereitung (Postmortem)
Nach einem SEV1/2 Incident:
1. **Fakten sammeln** (Timeline, betroffene Tenants/Events, konkrete Auswirkungen).
2. **Ursache** (Root Cause) möglichst präzise identifizieren auch dann, wenn direkt „nur“ Symptome gefixt wurden.
3. **Kurzfristige Maßnahmen** (Hotfixes, KonfigAnpassungen, zusätzliche Checks).
4. **Langfristige Maßnahmen** als bd-Issues festhalten (inkl. Link zum Incident).
5. **Dokumentation aktualisieren**
- Relevante Runbooks (dieses Dokument, PublicAPIRunbook, StorageSpec, BillingOps, etc.) mit neuen Learnings ergänzen.
Ziel ist, dass die TimetoDetect und TimetoResolve für ähnliche Probleme in Zukunft sinkt.

View File

@@ -0,0 +1,93 @@
---
title: Backup & Restore / Disaster Recovery
---
Dieses Dokument beschreibt, was gesichert werden sollte, wie Backups geprüft werden und wie ein Restore im Notfall abläuft.
## 1. Was muss gesichert werden?
- **Datenbank**
- MySQLDatenbank (alle Schemas/Tables des FotospielBackends).
- Enthält Tenants, Events, FotosMetadaten, JoinTokens, Abrechnungsdaten, Logs (soweit in DB).
- **Medienspeicher**
- HotStorage: Pfade unter `storage/app/private` / `storage/app/public` oder konfigurierten „hot“Disks.
- Archivspeicher: Buckets/Disks, in denen `event_media_assets` mit Status `archived` liegen.
- **Konfiguration**
- `.env` Dateien (ohne sie in Git zu speichern), DokployComposeKonfigurationen, Secrets für externe Dienste.
- Optional: HorizonKonfiguration, MonitoringDashboards.
> TODO: Füge hier konkrete Pfade/BucketNamen und die verwendeten BackupTools (z.B. `mysqldump`, S3Snapshots, DokployBackups) ein.
## 2. Backup-Strategie
- **Datenbank-Backups**
- Frequenz: mindestens täglich (idealerweise alle 46 Stunden für ProduktionsDB).
- Aufbewahrung: z.B. 730 Tage, mit OffSiteKopie.
- Prüfschritte:
- Dump/Backupfile auf Plausibilität (Größe, letzte Änderung).
- Regelmäßige TestRestores in eine StagingDB:
- Beispiel (einfacher Dump auf Host Pfade/Passwörter an Umgebung anpassen):
- `mysqldump -h 127.0.0.1 -u fotospiel -p fotospiel > fotospiel-$(date +%F).sql`
- Restore in temporäre DB (z.B. `fotospiel_restore`) und kurze Stichproben:
- `mysql -h 127.0.0.1 -u fotospiel -p fotospiel_restore < fotospiel-YYYY-MM-DD.sql`
- **Medien-Backups**
- HotStorage:
- Snapshot/IncrementalBackup der StorageVolumes oder S3Buckets.
- Archive:
- Sicherstellen, dass ArchivBackups nicht versehentlich durch LifecyclePolicies gelöscht werden, bevor gesetzliche Retention erfüllt ist.
- **Konfig-Backups**
- `.env` und Secrets nur verschlüsselt speichern (z.B. in einem SecretsManager, nicht in KlartextBackups).
- Dokploy/ComposeKonfiguration versionieren (Git) und zusätzlich sicher exportieren.
## 3. Restore-Szenarien
### 3.1 Einzelner Tenant/Event defekt
1. Reproduzieren, ob der Fehler rein logisch (Datenkonsistenz) oder physisch (Fehlender MedienBlob) ist.
2. **DBRestore (punktuell)**:
- Wenn möglich, nur relevante Tabellenbereiche (z.B. `tenants`, `events`, `photos`, `event_media_assets`, `event_packages`) aus Backup in eine temporäre DB laden.
- Differenzanalyse: welche Daten fehlen/fehlerhaft? Manuell oder via Skript zurückspielen.
3. **Medien-Check**
- Fehlende Dateien im Hot/ArchiveStorage identifizieren (z.B. per `event_media_assets` Pfade + `Storage::disk()->exists`).
- Wenn Dateien im Backup vorhanden, gezielt an den richtigen Pfad zurückkopieren.
> Diese Schritte sollten zuerst in einer StagingUmgebung eingeübt werden, bevor sie in Produktion angewendet werden.
### 3.2 Betriebsweite Störung (DB/Storage Verlust)
1. **DB wiederherstellen**
- Leere Datenbank aufsetzen, letztes konsistentes Backup einspielen.
2. **Storage wiederherstellen**
- HotStorageBackup auf Volumes/Buckets zurückspielen (z.B. DockerVolume `app-storage` oder zugeordneten Bucket).
- ArchivBuckets ggf. unverändert lassen, sofern noch intakt.
3. **App & Queues**
- App mit readonly/maintenanceFlag starten, Queues gestoppt lassen.
- Konsistenzprüfungen (z.B. stichprobenartige Tenants, Events, Medien, Abrechnungsdaten).
4. **Queues wieder freigeben**
- Wenn die wichtigsten Funktionen wieder intakt sind, Queues/Horizon graduell zuschalten.
> TODO: Ergänze konkrete Kommandos (Migrationsstatus prüfen, HealthChecks) und definierte RTO/RPOZiele.
## 4. Tests & DR-Übungen
- Mindestens 12 Mal pro Jahr einen vollständigen Restore in einer separaten Umgebung durchspielen:
- DBBackup einspielen.
- MedienBackups anbinden.
- Eine Handvoll Tenants/Events kompletter durchklicken (Upload, Galerie, AdminFunktionen).
- Ergebnisse als bd-Issue dokumentieren (z.B. „DRÜbung 2026Q1“ mit Learnings).
## 5. Verantwortlichkeiten
- **Backup-Ownership**: Wer stellt sicher, dass Backups laufen und testweise wiederhergestellt werden?
- **DR-Ownership**: Wer führt die DRÜbungen durch und wer entscheidet im Ernstfall über Failover/Restore?
Diese Punkte sollten mit konkreten Namen/Rollen befüllt werden, damit im Ernstfall keine Unklarheiten bestehen.
## 6. Ergänzende DR-Playbooks
Spezielle DRSzenarien sind in separaten Runbooks beschrieben:
- `docs/ops/dr-tenant-event-restore.md` Vorgehen bei versehentlich gelöschten oder beschädigten Tenants/Events.
- `docs/ops/dr-storage-issues.md` Vorgehen bei Hot/ArchiveStorageProblemen (voll, hängende Archivierung, fehlende Medien).
Dieses Dokument bleibt die HighLevelÜbersicht für konkrete Fälle solltest du immer auch die entsprechenden Playbooks konsultieren.

View File

@@ -0,0 +1,96 @@
---
title: DR-Playbook Tenant/Event versehentlich gelöscht
---
Dieses Playbook beschreibt, wie du vorgehst, wenn ein Tenant oder Event versehentlich gelöscht oder stark beschädigt wurde. Es baut auf den allgemeinen Hinweisen aus `docs/ops/backup-restore.md` auf.
> Wichtig: Diese Schritte sollten zuerst in einer **Staging-Umgebung** geübt werden. In Produktion nur nach klarer Freigabe und mit sauberer Dokumentation anwenden.
## 1. Schadensbild erfassen
Bevor du irgendetwas wiederherstellst:
- **Was genau ist betroffen?**
- Nur ein Event (z.B. versehentlich im Admin archiviert/gelöscht)?
- Mehrere Events eines Tenants?
- Der komplette Tenant (inkl. Benutzer, Events, Pakete)?
- **Welche Daten fehlen/fehlerhaft?**
- Fehlen nur Metadaten (Events, Fotos, Pakete) oder auch MedienDateien?
- Gibt es noch Spuren im Admin/UI (z.B. leere Übersichten, aber Logs mit Fehlermeldungen)?
- **Zeitfenster eingrenzen**
- Wann wurde der Fehler bemerkt?
- Wann war der Zustand sicher noch korrekt (z.B. vor letztem Deploy / gestern Abend)?
Diese Informationen bestimmen, welches Backup verwendet werden sollte.
## 2. Logische vs. physische Schäden unterscheiden
- **Logischer Schaden**
- Falsche Flags (Status falsch, Event „archiviert“ statt „aktiv“).
- Inkompatible PaketZuweisungen, aber Daten sind noch vorhanden.
- Lösbare Fälle oft ohne Restore durch gezielte Updates / AdminUI.
- **Physischer Schaden**
- Reihen in KernTabellen gelöscht (z.B. `events`, `photos`, `event_media_assets`, `tenants`).
- MedienDateien im Storage gelöscht/überschrieben.
Nur bei physischen Schäden ist ein Restore aus Backup nötig. Logische Schäden sollten möglichst mit minimalinvasiven Korrekturen behoben werden.
## 3. Vorgehen bei einzelnen Events
### 3.1 Datenbank Event-Datensätze identifizieren
1. **Event-IDs ermitteln**
- Aus Logs, alten Links, Metriken oder Backups.
2. **Querverweise prüfen**
- `events` (Basisdaten), `photos`, `event_media_assets`, `event_packages`, ggf. `event_join_tokens`.
3. **Temporäre Restore-DB nutzen**
- Erzeuge eine temporäre Datenbank (z.B. `fotospiel_restore`) und spiele den relevanten BackupDump ein.
- Dort die betroffenen EventDatensätze suchen.
### 3.2 Selektiver Restore von Event-Daten
Empfohlenes Muster:
- In **Restore-DB**:
- Exportiere alle relevanten Zeilen für das Event (z.B. `events`, `photos`, `event_media_assets`) in SQL/CSV.
- In **Produktions-DB**:
- Prüfe, ob IDs kollidieren (z.B. neue Events seit dem Backup).
- Freie IDs und referentielle Integrität beachten; wenn IDs bereits vergeben sind, ist ein reiner Import meist nicht möglich → dann manuelle Rekonstruktion (neues Event + Medien erneut verknüpfen).
> Dieses Playbook beschreibt bewusst kein generisches „SQL-Skript“, weil die tatsächliche Struktur und IDs von der aktuellen Migration abhängen. Ziel ist, die **Vorgehensweise** zu standardisieren, nicht ein unüberlegtes MassenUpdate.
### 3.3 Medien-Dateien
1. In der RestoreUmgebung prüfen, welche Pfade `event_media_assets` für das Event referenzieren.
2. Im BackupStorage nach diesen Pfaden suchen (Hot und ggf. ArchivBucket).
3. Fehlende Dateien in das produktive StorageVolume/Bucket an den erwarteten Pfad kopieren.
Wenn die Medien physisch nicht mehr vorhanden sind, ist nur eine teilweise Rekonstruktion möglich (z.B. Thumbnails ohne Originale) das sollte mit dem Tenant klar kommuniziert werden.
## 4. Vorgehen bei Tenant-weiten Fehlern
Wenn ein kompletter Tenant versehentlich gelöscht wurde (inkl. Benutzer/Events):
1. **Einordnung**
- Handelt es sich um einen isolierten Tenant oder könnten mehrere betroffen sein (z.B. durch fehlerhaftes Skript)?
2. **Restore-Strategie wählen**
- _Variante A: Partial Restore_ nur die Tabellenzeilen zum Tenant aus der BackupDB in die ProduktionsDB zurückführen.
- _Variante B: Backup-Spiegel_ Tenant + zugehörige Medien in eine separate Umgebung wiederherstellen und dem Kunden dort einen temporären Zugang geben.
3. **Risikoabwägung**
- Partial Restore in eine laufende ProduktionsDB trägt höhere Risiken (Kollisionsgefahr mit neuen Daten).
- SpiegelVariante ist operativ aufwändiger, kann aber sicherer sein, wenn viele neue Daten seit dem Backup hinzugekommen sind.
> Welche Variante gewählt wird, sollte von PlatformOps + Produkt gemeinsam entschieden werden.
## 5. Kommunikation & Dokumentation
- **Mit dem betroffenen Tenant**
- Ehrlich kommunizieren, was passiert ist, was wiederherstellbar ist und welches Risiko ein Restore birgt.
- Zeitrahmen und mögliche Einschränkungen klar benennen.
- **Intern**
- Den gesamten Prozess in einem bd-Issue oder im Ticketing festhalten:
- Was, wann, warum schief ging.
- Welche RestoreSchritte durchgeführt wurden.
- Welche Verbesserungen künftig notwendig sind (z.B. bessere Schutzmechanismen, zusätzliche Bestätigungen beim Löschen).
Dieses Playbook ist bewusst höherlevelig gehalten; spezifische SQL oder ToolSnippets sollten ergänzend in einem internen Notizsystem oder als separate Anhänge gepflegt werden, sobald eure BackupPipelines stabil etabliert sind.

View File

@@ -0,0 +1,73 @@
---
title: DR-Playbook Storage-Probleme (Hot/Archive)
---
Dieses Playbook beschreibt, wie du vorgehst, wenn es Probleme mit dem MedienStorage gibt z.B. HotStorage voll, Archivierung bleibt hängen oder viele Assets im Status `failed`.
## 1. Symptome & erste Checks
Typische Symptome:
- Gäste können keine Fotos mehr hochladen (Fehlermeldungen im UploadFlow).
- Tenant Admins sehen „fehlende Medien“ oder sehr langsame Galerien.
- `event_media_assets` enthält viele Einträge mit Status `pending` oder `failed`.
- Logs enthalten Hinweise auf fehlgeschlagene Archivierungen oder fehlende Dateien.
Erste Checks:
- StorageUsage der HotVolumes/Buckets prüfen (DockerVolume, S3Dashboard o.ä.).
- `EventMediaAsset`Status stichprobenartig prüfen (`hot`, `archived`, `pending`, `failed`).
- QueueLängen und Fehler in `media-storage` und `media-security` via Horizon und Logs.
## 2. Hot-Storage voll oder kurz vor Limit
1. **Warnungen bestätigen**
- System/ProviderWarnungen (z.B. 90 % voll) bestätigen.
- Prüfen, ob `storage:monitor` oder ähnliche Kommandos bereits Alerts ausgelöst haben.
2. **Sofortmaßnahmen**
- Archivierung priorisieren: sicherstellen, dass `storage:archive-pending` regelmäßig läuft und die `media-storage`Queue abgearbeitet wird.
- Temporäre Limits erhöhen, falls Provider dies erlaubt (z.B. S3Bucket praktisch „unbegrenzt“ vs. lokaler Disk).
3. **Aufräumen**
- Alte Caches/Thumbnails, die problemlos neu generiert werden können, ggf. gezielt löschen.
- Keine unüberlegten `rm -rf` Aktionen auf dem Storage immer mit klarer Strategie arbeiten.
## 3. Archivierung hängt oder schlägt häufig fehl
1. **Queue-Status prüfen**
- `media-storage` QueueLänge, Failed Jobs in Horizon prüfen.
- LogChannel `storage-jobs` nach Fehlermeldungen durchsuchen.
2. **Fehlerbilder auswerten**
- Typische Ursachen:
- Netzwerk/CredentialProbleme beim Zugriff auf den ArchivBucket.
- Zeitüberschreitungen bei sehr großen Medien.
- Inkonsistente `EventMediaAsset`Einträge (Pfad nicht mehr vorhanden, falscher DiskKey).
3. **Abhilfe**
- Netzwerk/Credentials fixen (z.B. S3Keys, Endpoints, Rechte).
- Problematische Assets gezielt in den Logs identifizieren und manuell nachziehen (Kopie auf ArchiveDisk, Status auf `archived` setzen, FehlerFeld leeren).
- Wenn viele Assets betroffen sind, lieber ein dediziertes Skript/Job bauen als adhoc SQL.
## 4. Fehlende oder beschädigte Medien-Dateien
Wenn `EventMediaAsset`Einträge existieren, die zu nicht mehr vorhandenen Dateien zeigen:
1. **Umfang ermitteln**
- Stichproben auf Basis der Fehlerlogs oder per BatchCheck (z.B. ein ArtisanCommand, das `exists()` prüft).
2. **Backup-Sicht**
- Prüfen, ob die Dateien noch im Backup vorhanden sind (Hot/ArchiveBackups).
3. **Wiederherstellung**
- Fehlende Dateien an den erwarteten Pfad im Storage kopieren (Hot oder Archive).
- `EventMediaAsset`Status und Timestamps ggf. aktualisieren (`hot` vs. `archived`).
Wenn keine Backups existieren, bleibt nur, die betroffenen Assets sauber als „nicht mehr verfügbar“ zu kennzeichnen und die Nutzer entsprechend zu informieren.
## 5. Nach einem Storage-Incident
- **Monitoring schärfen**
- Schwellwerte in `storage-monitor` anpassen (Warnung/Kritisch), Alerts für Queues/Storage erweitern.
- **Kapazitätsplanung**
- Erkenntnisse über Medienwachstum nutzen, um frühzeitig auf größere Volumes/Buckets oder häufigere Archivierung umzusteigen.
- **Dokumentation**
- Incident und Maßnahmen als bd-Issue dokumentieren.
- Dieses Playbook aktualisieren, wenn neue Muster entdeckt wurden.
Dieses Playbook ist eng mit `docs/ops/media-storage-spec.md` und `docs/ops/monitoring-observability.md` verknüpft. Nutze diese Dokumente für Detailinformationen zu Queues, Thresholds und StorageTargets.