feat: drive migration & Tier 2 restic deprecation (v0.18.0)

Phase 1: Deprecate restic as Tier 2 method (rsync only), auto-migrate on startup
Phase 2: Enhanced per-app migration with backup awareness, DB dump copy, auto-cleanup
Phase 3: Full drive migration with decommissioned state, rollback support, wizard UI
Phase 4: Hub report includes decommissioned drive state

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-19 21:49:14 +01:00
parent bdbe170a54
commit 99bf3ca7a8
22 changed files with 1725 additions and 402 deletions
+4 -10
View File
@@ -595,7 +595,6 @@ func (r *Router) saveCrossBackupConfig(w http.ResponseWriter, req *http.Request,
var body struct {
Enabled bool `json:"enabled"`
Method string `json:"method"`
DestinationPath string `json:"destination_path"`
Schedule string `json:"schedule"`
}
@@ -604,11 +603,6 @@ func (r *Router) saveCrossBackupConfig(w http.ResponseWriter, req *http.Request,
return
}
// Validate method
if body.Method != "rsync" && body.Method != "restic" {
writeJSON(w, http.StatusBadRequest, apiResponse{OK: false, Error: "method must be 'rsync' or 'restic'"})
return
}
// Validate schedule
if body.Schedule != "daily" && body.Schedule != "weekly" && body.Schedule != "manual" {
writeJSON(w, http.StatusBadRequest, apiResponse{OK: false, Error: "schedule must be 'daily', 'weekly', or 'manual'"})
@@ -640,7 +634,7 @@ func (r *Router) saveCrossBackupConfig(w http.ResponseWriter, req *http.Request,
cfg := &settings.CrossDriveBackup{
Enabled: body.Enabled,
Method: body.Method,
Method: "rsync",
DestinationPath: body.DestinationPath,
Schedule: body.Schedule,
LastRun: lastRun,
@@ -656,8 +650,8 @@ func (r *Router) saveCrossBackupConfig(w http.ResponseWriter, req *http.Request,
return
}
r.logger.Printf("[API] Cross-drive backup config saved for %s: method=%s dest=%s schedule=%s",
name, body.Method, body.DestinationPath, body.Schedule)
r.logger.Printf("[API] Cross-drive backup config saved for %s: dest=%s schedule=%s",
name, body.DestinationPath, body.Schedule)
writeJSON(w, http.StatusOK, apiResponse{OK: true, Message: "Cross-drive backup configuration saved"})
}
@@ -690,7 +684,7 @@ func (r *Router) getCrossBackupStatus(w http.ResponseWriter, _ *http.Request, na
writeJSON(w, http.StatusOK, apiResponse{OK: true, Data: map[string]interface{}{
"configured": true,
"enabled": cfg.Enabled,
"method": cfg.Method,
"method": "rsync",
"schedule": cfg.Schedule,
"running": r.crossDriveRunner != nil && r.crossDriveRunner.IsRunning(name),
"last_run": cfg.LastRun,