Adds docs/operations/update-runbook.md (obtain, verify by digest, back up, apply, verify, roll back) with the migration behaviour stated explicitly: a failed migration rolls back its own transaction but is recorded in _prisma_migrations and blocks every further migrate deploy (P3009) — including a re-deployed old image — until migrate resolve --rolled-back; semantically irreversible migrations have exactly one way back, the pre-update backup set. No rolling updates on a compose stage. Rehearsed in the isolated environment of #220: regular update to a v2 image set, then a deliberate failed-update (P3018 division by zero, schema change proven rolled back) with image-rollback-alone shown insufficient and the documented recovery executed. Protocol: docs/vs-nfd/98-update-rollback-protokoll.md. ADR 0024 decisions 5+6 recorded as executed; operations handbook and restore runbook updated; plan checkbox P1-3 ticked. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AUtYMxwTCMHG9mVHnwbFg8
4.4 KiB
Update-/Rollback-Protokoll — Probe in der isolierten Umgebung (Issue #221)
Nachweis für Maßnahmenplan P1-3 (ADR 0024): der Update-Pfad inklusive
Migrationen und geprobtem Fehlschlag-Rollback, ausgeführt in derselben
netzisolierten Umgebung wie der Isolationslauf
(97-isolationslauf-protokoll.md — Compose-Projekt dorfteich-isolated,
alle Netze internal: true, kein Egress-Pfad). Belegstufe: live
verifiziert. Die daraus destillierte Prozedur steht in
docs/operations/update-runbook.md.
- Datum: 2026-07-31
- Ausgangsstand („v1"): Images
dorfteich-iso-*:isolated(main@a758c9d, backup mit #288-Fix aus4f6596e), Instanz mit Inhalt aus dem Isolationslauf. - Update-Ziel („v2"): Images
dorfteich-iso-*:isolated-v2, gebaut aus dem Kettenstandccffcaa(#288 + #220) — als Stellvertreter eines regulären Release-Bundles; die Beschaffung/Digest-Prüfung eines echten Bundles ist das Mirror-Verfahren (#218,95-mirror-protokoll.md) und wurde dort bereits nachgewiesen. - Fehlschlag-Kandidat („bad"): api-Image mit einer absichtlich
fehlschlagenden Migration
(
20260731230000_deliberately_failing_update:ALTER TABLE+SELECT 1/0), nur für die Probe gebaut, nie committet.
Phase A — reguläres Update
| Schritt | Ergebnis |
|---|---|
| Pre-Update-Backup | ✅ Set 20260731-150833 über die Admin-API erzeugt und in der Set-Liste bestätigt |
TAG → v2, up -d |
✅ alle vier eigenen Services zusammen ersetzt (Ausfallfenster Sekunden, kein Rolling Update) |
| Migrationen | ✅ migrate-on-start läuft durch (dieses „Release" enthält keine neuen Migrationen) |
/readyz |
✅ vollständig grün |
| Inhalt | ✅ Seite „Isolationstest Seite" unverändert vorhanden |
Phase B — geprobter Fehlschlag + Rollback
- Bad-Update einspielen (
TAG→ bad,up -d): api scheitert beim Boot inmigrate deploy— P3018,ERROR: division by zerobei20260731230000_deliberately_failing_update; Container geht in den Restart-Loop, jeder Folge-Boot meldet P3009 („migrate found failed migrations"). - Datenbank-Zustand geprüft: die Migration steht als
failedin_prisma_migrations(Logs erfasst), aberbroken_columnexistiert nicht — die per-Migration-Transaktion hat den Schema-Eingriff zurückgerollt. Genau das dokumentierte Verhalten. - Image-Rollback allein reicht nicht (bewusst vorgeführt):
TAGzurück auf v2,up -d— der alte Stand scheitert weiter mit P3009 („The 20260731230000_deliberately_failing_update migration started at 2026-07-31 15:10:50 UTC failed"). - Recovery wie im Runbook:
migrate resolve --rolled-back 20260731230000_deliberately_failing_update(im api-Image ausgeführt) → „marked as rolled back" → api-Neustart:/readyzvollständig grün, Inhalt unverändert, Migrations-Row trägtrolled_back_at. - Alternativer Weg zurück (für semantisch irreversible, aber
erfolgreich gelaufene Migrationen): Restore des Pre-Update-Sets — der
Restore-Pfad selbst ist im Isolationslauf verifiziert
(
97-isolationslauf-protokoll.md, Fix #288).
Versions-Skew (Akzeptanzkriterium)
Ein Compose-Stage kennt kein Rolling Update: docker compose up -d
ersetzt web/api/collab/backup zusammen; Mischbetrieb alter und neuer
Versionen ist kein unterstützter Betriebszustand und dauert nur die
Container-Ersetzung selbst (Sekunden). Für VS-Zonen heißt das: Update im
angekündigten Wartungsfenster; die Migrationen wendet ausschließlich der
neue api-Container beim Start an (MIGRATE_ON_START).
Rückfluss
docs/operations/update-runbook.md— die Prozedur (Beschaffen, Prüfen, Sichern, Einspielen, Verifizieren, Rollback) inkl. explizitem Migrationsverhalten; aus dieser Probe destilliert.docs/operations/restore-runbook.md— Querverweis: Restore als einziger Weg zurück nach irreversiblen Migrationen.- #229 — Betriebshandbuch §1 (Airgap) und §2 (Update/Rollback) verweisen auf Runbook und dieses Protokoll.