(feature) Require delete count confirmation for retention apply

Make manual retention application more explicit by requiring operators to
confirm both the host name and the current number of planned deletions.

This reduces the risk of applying a stale or misunderstood retention plan
when the delete set changes between review and confirmation.
This commit is contained in:
2026-05-21 01:19:08 +02:00
parent 90e293facd
commit f76b6cad14
4 changed files with 74 additions and 2 deletions

View File

@@ -542,10 +542,12 @@ def host_retention_plan(request, host: str):
"scheduled_prune_exceeded": scheduled_prune_limit is not None and delete_count > scheduled_prune_limit,
"apply_form": RetentionApplyForm(
host_name=host_config.host,
expected_delete_count=delete_count,
initial={
"kind": kind,
"protect_bases": protect_bases,
"max_delete": delete_count,
"confirm_delete_count": delete_count,
},
),
}
@@ -556,7 +558,26 @@ def host_retention_plan(request, host: str):
@require_POST
def apply_host_retention(request, host: str):
host_config = get_object_or_404(HostConfig, host=host)
form = RetentionApplyForm(request.POST, host_name=host_config.host)
raw_kind = request.POST.get("kind", "scheduled")
raw_protect_bases = request.POST.get("protect_bases") in {"1", "true", "on", "yes"}
expected_delete_count = None
if raw_kind in {"scheduled", "manual", "all"}:
try:
plan = run_sql_retention_plan(
host=host_config.host,
kind=raw_kind,
protect_bases=raw_protect_bases,
)
except PobsyncError as exc:
messages.error(request, str(exc))
return redirect("host_retention_plan", host=host_config.host)
expected_delete_count = len(plan.get("delete") or [])
form = RetentionApplyForm(
request.POST,
host_name=host_config.host,
expected_delete_count=expected_delete_count,
)
if not form.is_valid():
messages.error(request, "Retention apply confirmation is invalid.")
return redirect("host_retention_plan", host=host_config.host)