feat(archive): BAK-07 gestaffelte Aufbewahrungsfrist fuer Backup-Snapshots

internal/backup.PruneTiered: reine GFS-Funktion (Tag/Woche/Monat) fuer
Datenbank-Generationen, behaelt strukturell immer die neueste Generation
(Sicherheitsnetz gegen Legal-Hold-Kollision). internal/objectbackup.
PruneTiered: duenner Wrapper um restics native --keep-daily/-weekly/
-monthly-Staffelung. Beide CLIs nutzen die Staffelung, wenn konfiguriert,
bleiben sonst abwaertskompatibel zur flachen "letzte N"-Regel. Real
gegen zeitversetzt erzeugte restic-Snapshots getestet (Fund: restics
--time-Flag erwartet eigenes Format, nicht RFC3339), Pruning-Sicherheit
nach dem Loeschen alter Snapshots ueber vollstaendigen Restore +
restic check --read-data bewiesen. Beide Rotationswege real ueber
systemd auf 131 ausgeloest.
This commit is contained in:
sysops
2026-08-30 00:49:23 +02:00
parent 80b0ca9176
commit 823a14ae12
8 changed files with 546 additions and 0 deletions
+20
View File
@@ -54,3 +54,23 @@ func Rotate(backupDir string, keep int) (removed []string, err error) {
}
return removed, nil
}
// PruneRotate wendet BAK-07s gestaffelte RetentionPolicy (PruneTiered,
// siehe retention.go) tatsächlich an — entfernt alle nicht mehr zu
// behaltenden Generationsverzeichnisse. Automatisierte Löschung nach
// Ablauf der Frist (Akzeptanzkriterium 2), unabhängig von RET-02s
// Dokumenten-Retention.
func PruneRotate(backupDir string, policy RetentionPolicy) (removed []string, err error) {
generations, err := ListGenerations(backupDir)
if err != nil {
return nil, err
}
_, toRemove := PruneTiered(generations, policy)
for _, gen := range toRemove {
if err := os.RemoveAll(filepath.Join(backupDir, gen)); err != nil {
return removed, fmt.Errorf("backup: generation %q entfernen: %w", gen, err)
}
removed = append(removed, gen)
}
return removed, nil
}