Add a dedicated cleanup path for incomplete snapshots instead of letting
retention prune them implicitly. The retention plan now exposes a guarded
form that requires host and delete-count confirmation before removing
.incomplete snapshot directories and their SQL records.
Keep scheduled/manual retention behavior unchanged, add path safety checks,
and cover cleanup success, confirmation failures, max-delete limits, and
unexpected paths in tests.
Refs #10
Replace remaining model-name based configuration errors with labels that
match the Django-first operating model.
Add coverage for missing global config and host configuration errors so
operator-facing messages stay readable.
Record planned delete counts, max-delete settings, base protection, and
ignored incomplete snapshots in retention apply results.
Surface those details on run detail pages so scheduled and manual prune
outcomes are understandable without reading the raw JSON payload.
Show keep/delete reasons in the retention plan, surface scheduled prune
limit warnings, and explain base snapshot protection before retention is
applied.
Also surface incomplete snapshots from the retention views without deleting
them automatically, so interrupted backups are visible on the dashboard,
host detail, and retention plan.
Make SQL retention delete the snapshot root when records point at the
snapshot data directory, matching how backup metadata is stored on disk.
Before removing a snapshot tree, temporarily add user write permission to
directories inside that snapshot so rsync-preserved source permissions do
not block cleanup.
Add a regression test for pruning snapshots whose data directory mirrors a
read-only remote root.