controller v0.69.0: remove dead infra-backup stubs + unused restic-password report field
Controller half of Phase-1 Infra Backup retirement (hub v0.12.0; SPIKE-infra-backup-2026-06-15). Pure dead-code removal, no behaviour change. - Remove Pusher.PushInfraBackup (caller-less; hub endpoint gone). - Remove Notifier.NotifyBackupCompleted / backup_completed event (caller-less since slice 8C; hub deadline check now reads agent host-report PBS snapshots). - Remove report.BackupReport.ResticPassword — builder never sets it post-8C (confirmed in source + live), but it historically leaked the restic password into the hub's plaintext reports store. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,22 @@
|
|||||||
## Changelog
|
## Changelog
|
||||||
|
|
||||||
|
### v0.69.0 — remove dead infra-backup stubs + the unused restic-password report field (2026-06-16)
|
||||||
|
|
||||||
|
Controller half of the Phase-1 Infra Backup retirement (hub v0.12.0; see
|
||||||
|
`felhom.eu/documentation/audits/SPIKE-infra-backup-2026-06-15.md`). Pure dead-code removal — no
|
||||||
|
behaviour change (everything removed was already caller-less).
|
||||||
|
|
||||||
|
- **Removed `report.Pusher.PushInfraBackup`** — pushed the infra-backup payload to the now-removed hub
|
||||||
|
endpoint `POST /api/v1/infra-backup`. Dead since slice 8C; no callers.
|
||||||
|
- **Removed `notify.Notifier.NotifyBackupCompleted`** (the `backup_completed` event) — no callers
|
||||||
|
since whole-guest backup moved to the agent in slice 8C. The hub's backup-deadline check now reads
|
||||||
|
the agent host-report's PBS snapshots instead of this event. `NotifyBackupFailed` and the DB-dump
|
||||||
|
notifiers are untouched and still used.
|
||||||
|
- **Removed `report.BackupReport.ResticPassword`** (`json:"restic_password"`) — the live report
|
||||||
|
builder (`buildBackupReport`) has left it empty since slice 8C, but the field historically leaked
|
||||||
|
the restic password into the hub's plaintext `reports` store. Confirmed via pushed source (builder
|
||||||
|
never sets it) **and** live data (current reports carry no `restic_password`) before removal.
|
||||||
|
|
||||||
### v0.68.3 — fix Beállítások page endless-refresh loop after a migration (2026-06-15)
|
### v0.68.3 — fix Beállítások page endless-refresh loop after a migration (2026-06-15)
|
||||||
|
|
||||||
Found while live-validating the M3 migration: once any data migration finished, the **Beállítások
|
Found while live-validating the M3 migration: once any data migration finished, the **Beállítások
|
||||||
|
|||||||
+11
-3
@@ -963,7 +963,6 @@ The controller pushes structured events to the Hub's `/api/v1/event` endpoint. T
|
|||||||
|
|
||||||
| Event Type | Severity | Trigger |
|
| Event Type | Severity | Trigger |
|
||||||
|------------|----------|---------|
|
|------------|----------|---------|
|
||||||
| `backup_completed` | info | Nightly restic backup succeeds |
|
|
||||||
| `backup_failed` | error | Nightly restic backup fails |
|
| `backup_failed` | error | Nightly restic backup fails |
|
||||||
| `db_dump_completed` | info | Nightly database dumps succeed |
|
| `db_dump_completed` | info | Nightly database dumps succeed |
|
||||||
| `db_dump_failed` | error | Nightly database dumps fail |
|
| `db_dump_failed` | error | Nightly database dumps fail |
|
||||||
@@ -1242,9 +1241,18 @@ Each report push now includes per-app telemetry data:
|
|||||||
- `buildAppTelemetrySection()` calls both, then `buildAppTelemetry()` aggregates by stack — summing container metrics, merging issues, capping at 10 per app. Additionally, `buildControllerTelemetry()` creates a special entry for the controller container itself (`app_name: "felhom-controller"`).
|
- `buildAppTelemetrySection()` calls both, then `buildAppTelemetry()` aggregates by stack — summing container metrics, merging issues, capping at 10 per app. Additionally, `buildControllerTelemetry()` creates a special entry for the controller container itself (`app_name: "felhom-controller"`).
|
||||||
- Results stored as `[]AppTelemetry` in the `Report` struct field `app_telemetry`.
|
- Results stored as `[]AppTelemetry` in the `Report` struct field `app_telemetry`.
|
||||||
|
|
||||||
#### Infrastructure Backup to Hub (`internal/report/infra_backup.go`)
|
#### Infrastructure Backup to Hub — RETIRED (2026-06-16)
|
||||||
|
|
||||||
After each backup cycle (including manual Tier 2 triggers via `OnCrossDriveComplete` callback), the controller pushes a full infrastructure snapshot to the Hub for disaster recovery. This snapshot includes:
|
> **Removed.** The controller no longer pushes any infra-backup to the Hub, and the Hub no longer
|
||||||
|
> accepts or stores one (hub v0.12.0). The builder (`internal/report/infra_backup.go`) and local
|
||||||
|
> mirror (`internal/backup/local_infra.go`) were deleted back in slice 8C; the last caller-less stub
|
||||||
|
> (`Pusher.PushInfraBackup`) and the `backup_completed` event were removed in controller v0.69.0.
|
||||||
|
> DR now rests on the agent's PBS whole-CT snapshot + the Hub-generated controller.yaml. The text
|
||||||
|
> below is **historical** and describes the removed mechanism — much of this section (and the
|
||||||
|
> `local_infra.go` / `setup/scanner.go` / `PullRecovery` / `restore_drives` references elsewhere in
|
||||||
|
> this README) is stale slice-8C debt. See `felhom.eu/documentation/audits/SPIKE-infra-backup-2026-06-15.md`.
|
||||||
|
|
||||||
|
After each backup cycle (including manual Tier 2 triggers via `OnCrossDriveComplete` callback), the controller pushed a full infrastructure snapshot to the Hub for disaster recovery. This snapshot included:
|
||||||
- `controller.yaml` (base64-encoded, full config including secrets)
|
- `controller.yaml` (base64-encoded, full config including secrets)
|
||||||
- `settings.json` (base64-encoded, backup prefs, storage paths, cross-drive configs)
|
- `settings.json` (base64-encoded, backup prefs, storage paths, cross-drive configs)
|
||||||
- Disk layout (UUIDs, labels, mount points, fstab options, bind-mount topology)
|
- Disk layout (UUIDs, labels, mount points, fstab options, bind-mount topology)
|
||||||
|
|||||||
@@ -276,10 +276,10 @@ func (n *Notifier) NotifyBackupFailed(message, errMsg string) {
|
|||||||
n.PushEvent("backup_failed", "error", message, BackupDetails{Error: errMsg})
|
n.PushEvent("backup_failed", "error", message, BackupDetails{Error: errMsg})
|
||||||
}
|
}
|
||||||
|
|
||||||
// NotifyBackupCompleted sends a backup success event.
|
// (NotifyBackupCompleted removed 2026-06-16 — the backup_completed event had no callers
|
||||||
func (n *Notifier) NotifyBackupCompleted(details BackupDetails) {
|
// since slice 8C moved whole-guest backup to the agent. The hub's backup-deadline check
|
||||||
n.PushEvent("backup_completed", "info", "Biztonsági mentés elkészült", details)
|
// now reads the agent host-report's PBS snapshots instead of this event. DB-dump events
|
||||||
}
|
// below are still emitted and consumed.)
|
||||||
|
|
||||||
// NotifyDBDumpFailed sends a DB dump failure event.
|
// NotifyDBDumpFailed sends a DB dump failure event.
|
||||||
func (n *Notifier) NotifyDBDumpFailed(message, errMsg string) {
|
func (n *Notifier) NotifyDBDumpFailed(message, errMsg string) {
|
||||||
|
|||||||
@@ -142,55 +142,8 @@ func (p *Pusher) GetStatus() PushStatus {
|
|||||||
return p.status
|
return p.status
|
||||||
}
|
}
|
||||||
|
|
||||||
// PushInfraBackup sends the infrastructure backup payload to the Hub.
|
// (PushInfraBackup removed 2026-06-16 — the infra-backup mechanism was retired hub-side.
|
||||||
// Uses the same retry logic as Push.
|
// It was dead since slice 8C, had no callers, and pushed plaintext secrets to the hub.)
|
||||||
func (p *Pusher) PushInfraBackup(data []byte) error {
|
|
||||||
if !p.enabled {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
url := p.hubURL + "/api/v1/infra-backup"
|
|
||||||
if p.debug {
|
|
||||||
p.logger.Printf("[DEBUG] [report] PushInfraBackup: url=%s payload=%d bytes", url, len(data))
|
|
||||||
}
|
|
||||||
|
|
||||||
var lastErr error
|
|
||||||
for attempt := 0; attempt < 3; attempt++ {
|
|
||||||
if attempt > 0 {
|
|
||||||
time.Sleep(5 * time.Second)
|
|
||||||
}
|
|
||||||
|
|
||||||
req, err := http.NewRequest(http.MethodPost, url, bytes.NewReader(data))
|
|
||||||
if err != nil {
|
|
||||||
lastErr = err
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
req.Header.Set("Content-Type", "application/json")
|
|
||||||
if p.apiKey != "" {
|
|
||||||
req.Header.Set("Authorization", "Bearer "+p.apiKey)
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := p.httpClient.Do(req)
|
|
||||||
if err != nil {
|
|
||||||
lastErr = err
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
io.Copy(io.Discard, resp.Body)
|
|
||||||
resp.Body.Close()
|
|
||||||
|
|
||||||
if resp.StatusCode >= 200 && resp.StatusCode < 300 {
|
|
||||||
p.logger.Printf("[INFO] [report] Infra backup pushed to Hub (%d bytes)", len(data))
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
lastErr = fmt.Errorf("HTTP %d", resp.StatusCode)
|
|
||||||
if p.debug {
|
|
||||||
p.logger.Printf("[DEBUG] [report] PushInfraBackup: attempt %d failed — HTTP %d", attempt+1, resp.StatusCode)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
p.logger.Printf("[WARN] [report] InfraBackup push failed: %v", lastErr)
|
|
||||||
return fmt.Errorf("infra backup push failed after 3 attempts: %w", lastErr)
|
|
||||||
}
|
|
||||||
|
|
||||||
// PushOnce sends a single report regardless of the enabled flag.
|
// PushOnce sends a single report regardless of the enabled flag.
|
||||||
// Used for one-time notifications (e.g., reporting-disabled on startup).
|
// Used for one-time notifications (e.g., reporting-disabled on startup).
|
||||||
|
|||||||
@@ -82,7 +82,8 @@ type BackupReport struct {
|
|||||||
RepoSizeMB int64 `json:"repo_size_mb"`
|
RepoSizeMB int64 `json:"repo_size_mb"`
|
||||||
LastIntegrityCheck *time.Time `json:"last_integrity_check,omitempty"`
|
LastIntegrityCheck *time.Time `json:"last_integrity_check,omitempty"`
|
||||||
IntegrityOK bool `json:"integrity_ok"`
|
IntegrityOK bool `json:"integrity_ok"`
|
||||||
ResticPassword string `json:"restic_password,omitempty"`
|
// (ResticPassword removed 2026-06-16 — the live builder never set it post-slice-8C;
|
||||||
|
// historically it leaked the restic password into the hub's plaintext report store.)
|
||||||
}
|
}
|
||||||
|
|
||||||
// HealthReport holds the aggregated health status.
|
// HealthReport holds the aggregated health status.
|
||||||
|
|||||||
Reference in New Issue
Block a user