feat: infra backup GFS retention + version history

New infra_backup_versions table with GFS pruning (~14 versions per
customer). Recovery endpoint supports ?version=ID. New /versions API.
Dashboard shows collapsible backup history with app names and disk count.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-26 14:47:48 +01:00
parent f82fa9be2c
commit f1212e6ba8
5 changed files with 341 additions and 30 deletions
@@ -313,7 +313,34 @@
<span class="label">Disks</span>
<span class="value">{{.InfraBackup.DiskCount}}</span>
</div>
<div class="info-item">
<span class="label">Versions</span>
<span class="value">{{.InfraBackup.VersionCount}}</span>
</div>
</div>
{{if .InfraBackupVersions}}
<details style="margin-top: 0.75rem;">
<summary style="cursor: pointer; color: var(--text-secondary, #94a3b8); font-size: 0.85em;">Backup History ({{len .InfraBackupVersions}} versions)</summary>
<table style="width: 100%; margin-top: 0.5rem; font-size: 0.85em;">
<thead>
<tr>
<th style="text-align: left; padding: 0.25rem 0.5rem;">Date</th>
<th style="text-align: left; padding: 0.25rem 0.5rem;">Apps</th>
<th style="text-align: right; padding: 0.25rem 0.5rem;">Disks</th>
</tr>
</thead>
<tbody>
{{range .InfraBackupVersions}}
<tr>
<td style="padding: 0.25rem 0.5rem;">{{.CreatedAt.Format "2006-01-02 15:04"}}</td>
<td style="padding: 0.25rem 0.5rem;">{{.StackCount}}{{if .StackNames}}: {{range $i, $n := .StackNames}}{{if $i}}, {{end}}{{$n}}{{end}}{{end}}</td>
<td style="text-align: right; padding: 0.25rem 0.5rem;">{{.DiskCount}}</td>
</tr>
{{end}}
</tbody>
</table>
</details>
{{end}}
{{else}}
<p style="color: #facc15">No infra backup received yet</p>
{{end}}