Files
tibi-docs/src/content/docs/projekt/audit-backup.md
T
apairon 6aabd842e9 Ton: Fehlerabschnitte von Fuersorge-Sprache auf Handbuch-Sprache umgestellt
- AGENTS.md: neue Pflichtregel 'Ton in Fehlerabschnitten' (Tabelle Meldung|Bedeutung|Vorgehen; verbotene Muster + Ersatzformen)
- anwender/*: 12 Seiten umgeschrieben - 'Wenn etwas schiefgeht'/'Wenn nicht alles klappt' -> 'Fehler'-Tabellen; 'bitte deine Betreuung/Teamleitung' -> konkrete Instanz mit Link; 'Zeichen fuer Zeichen', 'hoechstens drei Versuche', 'statt weiter zu raten' entfernt
- hilfe.md komplett neu: Fehleruebersicht + Zustaendigkeiten als Tabellen (Titel 'Hilfe bei Stoerungen')
- admin/ki-funktionen: Produkt-Zitat als solches belassen; projekt/audit-backup, sammlungen-anlegen, llm-nutzen entbelehrt
- Belege nachgezogen: upload.maxBodySize/allowedMimeTypes, Konflikt = Unique-Index (409/500), Passwort-Reset in der Benutzerverwaltung
- Build 71 Seiten gruen, 0 tote Links/Tabellen
2026-10-17 13:19:20 +00:00

13 KiB

title, description
title description
Änderungen und Sicherung Audit-Log lesen, Snapshots nutzen, Backup und Restore ausführen.

import { Aside, Steps, Card, CardGrid } from '@astrojs/starlight/components';

Wer hat was geändert — und wie kommst du zurück? Drei Ebenen: Das Audit-Log protokolliert Änderungen, Snapshots frieren Datenstände ein, Backups sichern alles für den Ernstfall. Suchbegriffe: Änderungshistorie, Verlauf, Wiederherstellen, Snapshot, Datensicherung.

Protokolliert Änderungen — wer, wann, vorher/nachher. Frieren Datenstände im Ordner `snapshotPath` ein. Voll-Export als ZIP für Umzug und Ernstfall.

Audit einschalten und lesen

Audit ist zweistufig: Es läuft nur, wenn Server und Projekt es erlauben.

audit:
  enabled: true
Ebene Schalter Standard
Server audit.enabled, TTL audit.defaultTTL: 720h (30 Tage, "0" = ewig) Betreiber-Sache
Projekt audit.enabled: true Starter: an
Sammlung audit: { enabled, actions: [create, update, delete] } Standard-Aktionen: anlegen, ändern, löschen
Action audit: { enabled, actions: [get, post] } Nur was du einschaltest
  1. Etwas ändern (z. B. Seitentitel per PUT).
  2. Im tibi-admin die Änderungshistorie des Eintrags öffnen — wer, wann, vorher/nachher.
  3. Alte Fassung per Wiederherstellen zurückschreiben (erst an Testdaten üben).
  4. Per API lesen geht mit GET /api/v1/audit (Recht audit.read nötig).

Verlauf im Admin

Du musst nicht per API lesen: Der Admin zeigt den Verlauf pro Eintrag (letzte 50 Änderungen mit Vorher/Nachher-Vergleich und Wiederherstellen einzelner Felder) sowie global als Audit-Log. Details zur Bedienung — Verlaufspanel, Diff-Ansicht, Wiederherstellen-Dialog, Seitenleiste — stehen unter Eintrags-Editor.

Snapshots

Snapshots sind eingefrorene Datenstände im Ordner snapshotPath (../snapshots im Starter):

snapshotPath: ../snapshots
snapshots:
  - name: daily          # 12:00 Uhr, redaktionelle Daten + Medien, 14 Stück
    schedule: "0 12 * * *"
    collections: [content, navigation, tags, medialib, ssr]
    includeMedia: true
    retention: { maxCount: 14 }
  - name: full-daily
    schedule: "0 3 * * *"    # 03:00 Uhr, alles + Medien, 14 Stück
    includeMedia: true
    retention: { maxCount: 14 }
  - name: full-weekly    # sonntags 05:00 Uhr, 12 Stück
    schedule: "0 5 * * 0"
    collections: []      # leer = alle Sammlungen
    includeMedia: true
    retention: { maxCount: 12 }
  - name: full-monthly   # monatlich, Langzeitarchiv, 12 Stück
    schedule: "0 6 1 * *"
    collections: []
    includeMedia: true
    retention: { maxCount: 12 }
Regel Bedeutung
collections: [] (leer) Alle Sammlungen sichern
Liste mit Namen Nur diese sichern (Medien nur mit includeMedia: true, per Hardlink)
retention.maxCount Älteste fliegen automatisch raus
Speicherung json (BSON-Extended-JSON auf Platte, Standard); db/both sind Zukunft

Snapshot-Config-Felder

Alle Felder aus snapshot_config.go:11-58 — nur diese Namen verwenden:

Feld YAML-Name Bedeutung
Name name Eindeutige Profil-Kennung (Pflicht, sonst snapshot config: name is required)
Beschreibung description Freitext, optional
Sammlungen collections [] = alle; String-Kurzform "content" = include; Objektform {name, mode} (include oder exclude) — gemischt include + exclude ist ein Validierungsfehler
Medien includeMedia Datei-Felder per Hardlink sichern (Standard: true)
Deduplizierung collectionDedup SHA256-Dedup identischer Collection-Exporte über .store/collections/ per Hardlink — nur für große, selten geänderte Sammlungen
Modus mode ""/json = Platte (Standard, implementiert); db/both = MongoDB-$out-Kopie (Zukunft) — Medien immer Hardlink, egal welcher Modus
Aufbewahrung retention: { maxCount, maxAge, maxSizeBytes } Auto-Prune-Regeln, alle optional
Zeitplan schedule Cron-Ausdruck; leer = nur manuell per Trigger-API
Team-Rechte permissions Liste reiner Berechtigungsnamen — Phase 2, aktuell gilt AllowSnapshots
An/Aus enabled false = Scheduler überspringt das Profil; manueller Trigger geht trotzdem
snapshots:
  - name: redaktionell
    description: "Täglich, ohne Systemdaten"
    collections:
      - content            # Kurzform = include
      - name: ssr           # Objektform
        mode: exclude
    includeMedia: true
    collectionDedup: false
    mode: json
    retention: { maxCount: 14, maxAge: "336h", maxSizeBytes: 10737418240 }
    schedule: "0 12 * * *"
    permissions: []
    enabled: true

Snapshot-Routen

Alle Routen aus setup.go:436-495 (GET liest, POST löst aus, DELETE löscht):

Methode Pfad (hinter /api/v1/_/:project/_/admin) Zweck
GET /snapshots/configs Alle Profile aus der Projekt-YAML lesen (AdminSnapshotConfigs)
POST /snapshots/configs/:name/trigger Profil manuell auslösen — geht auch bei enabled: false
GET /snapshots Alle Einträge auflisten (Scannt das entries-Verzeichnis)
GET /snapshots/download/:file Datei-Download (vor :id registriert, damit download kein :id matcht)
GET /snapshots/:id Einzelnen Eintrag ansehen
DELETE /snapshots/:id Eintrag löschen
POST /snapshots/:id/restore?merge=1&collections=a,b Zurückspielen (merge=1 = zusammenführen; collections = Auswahl)
GET /snapshots/:id/download Eintrag als ZIP laden
GET /snapshots/stats Belegung prüfen
POST /snapshots/prune Retention-Aufräumen manuell anstoßen

Im tibi-admin (/projects/:id/snapshots, drei Tabs):

Tab Was du tust
Configs Profile ansehen
Entries Auslösen (mit Fortschritt), herunterladen (ZIP), zurückspielen, löschen, aufräumen
Stats Belegung prüfen

Zum Zurückspielen braucht dein Token allowSnapshots: true. Übe das Zurückspielen nur mit Testdaten — es überschreibt den Live-Stand.

Backup-Routen

Alle Routen aus setup.go:398-432:

Methode Pfad (hinter /api/v1/_/:project/_/admin) Zweck
GET /backup/analyze-download?collections=a,b Schätzung (Dokument-/Medien-Zahlen) ohne Voll-Export — vor dem Download prüfen
GET /backup Voll-ZIP erzeugen und laden (?collections= schränkt ein, ?sse=1 streamt)
GET /backup/download/:file Fertiges Temp-ZIP aus dem SSE-Modus laden (One-Time-Use: zweiter Request = 404)
POST /backup?sse=1 ZIP hochladen und analysieren → antwortet mit restoreToken
POST /backup/:restoreToken?collections=…&merge=true&sse=1 Restore aus dem analysierten Temp-Verzeichnis ausführen
DELETE /backup/:restoreToken Temp-Daten zum Token manuell aufräumen

Restore-Token-Lebenszyklus

POST /backup erzeugt Token plus Temp-Verzeichnis (admin_backup.go:204-234), POST /backup/:restoreToken verbraucht es, DELETE räumt auf.

  1. Analyse: ZIP per POST /backup hochladen — Antwort enthält restoreToken, sourceNamespace, createdAt, expiresAt (admin_backup.go:378-384). Mit ?sse=1 kommt der Fortschritt als Stream (init → done, jeweils mit restoreToken).
  2. Prüfen: collections-Analyse in der Antwort lesen (Quelle gegen Ziel abgleichen, ggf. ?collections= für Teil-Restore vormerken).
  3. Restore: POST /backup/:restoreToken ausführen — bei Erfolg landet restoredCollections/totalDocuments/mediaFiles in der Antwort, alles wird als Audit-Action backup/restore protokolliert. Danach ist das Token verbraucht (Eintrag wird vor dem Restore aus dem Store entfernt).
  4. Cleanup: Läuft der Restore ohne sse, löscht der Server das Temp-Verzeichnis selbst (os.RemoveAll). Bei Abbruch oder abgelaufenem Token per DELETE /backup/:restoreToken aufräumen — Antwort 404 restore token not found or already cleaned up heißt: schon weg. Abgelaufene Tokens räumt zusätzlich ein Hintergrund-Job weg.

Rechte und Auth-Reihenfolge

Ebene Schalter Beleg
Server-Token Scope project.backup / project.snapshot (scope.go:53-55) X-Admin-Token oder Authorization: Bearer
Projekt-Token allowBackup / allowSnapshots in der Projekt-Config (project.go:118-120) Nur mit passendem Flag
JWT-Login Rolle AdminRole plus Scope-Check (EnforceScope) Persönliche Tokens bleiben durch ihre Scopes begrenzt

Der Check läuft in admin_auth.go:20-74 immer in dieser Reihenfolge:

  1. Server-Token mit passendem Scope (config.GetAdminTokenInfo).
  2. Projekt-Token mit passendem Flag (AllowBackup / AllowSnapshots per ConstantTimeCompare).
  3. JWT-Login mit Admin-Rolle plus Scope-Prüfung — sonst 403 permission denied.

Backup und Restore

Backups sind der Voll-Export für Umzug und Desaster-Fall — im Admin unter /projects/:id/backup:

  1. Export-Tab: Sammlungen wählen (Kopf-Kästchen = alle), „Start backup“ klicken, Fortschritt abwarten, Datei mit Größenangabe laden.
  2. Bricht der Download ab: erst Analyse (backup/analyze-download), dann neu laden.
  3. Import-Tab: ZIP in die Zone ziehen, Analyse lesen, Restore bestätigen.
  4. Danach: Reload und SSR-Cache prüfen, Seite anonym aufrufen.
Unterschied Snapshot Backup
Wofür Schneller Rücksprung im Alltag Umzug, Desaster, Weitergabe
Wo snapshotPath auf dem Server ZIP-Datei bei dir
Recht allowSnapshots Projekt-Admin plus AllowBackup
Fortschritt Ja (Stream) Ja (SSE-Stream)

Fehler

Fehlerbild Ursache Lösung
Audit bleibt leer audit.enabled im Projekt fehlt oder Server-Flag aus Beide Schalter prüfen, Änderung erneut auslösen
Alte Einträge verschwinden TTL (720h) abgelaufen Wichtige Stände als Snapshot sichern, TTL ggf. auf "0"
Snapshot-Button fehlt Token ohne allowSnapshots Flag allowSnapshots am Projekt-Token setzen (siehe Rechte und Auth-Reihenfolge)
Backup-Button fehlt Kein Projekt-Admin oder AllowBackup fehlt Projekt-Admin-Rolle bzw. Flag AllowBackup am Projekt-Token prüfen (siehe Rechte und Auth-Reihenfolge)
400 missing restoreToken Restore ohne Token aufgerufen Erst POST /backup (Analyse), Token aus der Antwort nehmen
404 restore token not found or expired Token verbraucht, aufgeräumt oder TTL abgelaufen Analyse erneut hochladen, neues Token holen
403 invalid entry id / 404 snapshot not found Snapshot-Restore mit falscher/gelöschter ID ID aus GET /snapshots neu lesen
snapshot config: name is required Profil ohne name name in der YAML ergänzen
Restore zeigt keine Wirkung Cache alt Reload plus ?clear=1 (siehe Veröffentlichen)

Wie ein Redakteur eine Sicherung einspielt: Backup einspielen.

Verifiziert am e3f92eb 2026-10-17 (tibi-svelte-starter, config.yml audit- und snapshots-Blöcke), am 68b4278 2026-10-17 (tibi-server, audit-, backup- und snapshot-docs), am 2b091d8 2026-10-17 (tibi-admin-nova, test-pläne 43 und 44, AuditView, AuditHistoryPanel, AuditDiff, AuditRestoreDialog, AuditSidebarHistory)