Acknowledge persisted webhook deletion to the destination editor

Return the explicit success boolean the existing editor requires after durable and live removal, while retaining the legacy status field. Pin the response contract so a successful deletion is not displayed as failed and does not encourage blind retries.

Change-source: pulse-maintainer
This commit is contained in:
pulse-triage[bot]
2026-10-24 16:21:39 +01:00
parent 5c6811f93d
commit 94a50e75b0
6 changed files with 40 additions and 1 deletions
@@ -1687,6 +1687,11 @@ token-free command. No copy receipt establishes installed removal or a release.
## Shared Boundaries
Webhook DELETE acknowledges committed destination removal with `success: true`
and the retained legacy status. It does not acknowledge agent removal, revoke an
agent credential or change an already admitted agent/update job. Notification
queue destination-ID revocation remains with the notification owner.
Proxmox helper operation v2 carries the shared `ProxmoxLXCInventory` completeness and bounded omitted-VMID contract. V1 stays strict complete-only. The collector tries v1 only after an explicit unsupported-v2 response, under one unchanged operation deadline; transport, authorization and provider failures never select a broader fallback.
The shared monitor constructor also composes notification bootstrap: it loads
@@ -21,6 +21,18 @@
## Purpose
### Webhook deletion has an explicit committed acknowledgement
`DELETE /api/notifications/webhooks/{id}` returns `success: true` after saved and
live inventories both remove that ID. The legacy `status: "success"` field remains
for existing clients. The destination editor already requires the boolean before
accepting deletion; the acknowledgement must not leave a successfully removed
row shown as failed. Missing destinations, failed persistence and failed live
publication retain their existing error and rollback paths, not a success body.
The handler's deletion assertion pins both fields; persistence-failure controls
continue to require no live removal. This changes no route, scope, credential,
retention or admitted-delivery snapshot contract.
### Typed MCP fleet filters survive HTTP projection
GET/DELETE capability projection preserves public string and boolean query
@@ -39,6 +39,14 @@ operator retry, cancellation, audit/receipt readback and new-alert delivery.
This is synthetic source proof, not evidence of prior exposure, installed-provider
recovery or resolution of a reported notification outage.
The DELETE acknowledgement includes `success: true` only after durable and live
removal complete, retaining the legacy `status: "success"` field. The existing
editor requires that explicit boolean before removing the visible destination;
a successful mutation must not be displayed as failed or encourage a blind retry.
Persistence/live-publication failures retain their existing refusal/rollback
behaviour. `TestNotificationHandlers/DeleteWebhook` pins both success fields;
its failure controls still prove that a rejected save never removes live state.
### Approved addresses share a bounded connection budget
Webhook and HTTP Apprise transports pass their validated numeric destinations
@@ -775,6 +775,11 @@ Compact Coverage age cells use the existing metadata-size text and reclaim numer
## Shared Boundaries
Webhook DELETE's explicit success acknowledges saved/live destination removal,
not deletion of its retained queue configuration or failed-attempt history.
Queue records still follow the existing cancellation/retention policy; no
storage schema, backup, restore or data-removal acknowledgement is added.
### Operator storage vocabulary without identity changes
Storage topology names preserve Proxmox plugin vocabulary, including LVM-Thin,
+3 -1
View File
@@ -750,7 +750,9 @@ func (h *NotificationHandlers) DeleteWebhook(w http.ResponseWriter, r *http.Requ
return
}
if err := utils.WriteJSONResponse(w, map[string]string{"status": "success"}); err != nil {
// The destination editor accepts a mutation only after success is explicit.
// Keep status for existing clients; acknowledge only after durable/live removal.
if err := utils.WriteJSONResponse(w, map[string]interface{}{"success": true, "status": "success"}); err != nil {
log.Error().Err(err).Str("webhookID", webhookID).Msg("Failed to write webhook deletion response")
}
}
@@ -718,6 +718,13 @@ func TestNotificationHandlers(t *testing.T) {
h.DeleteWebhook(w, req)
assert.Equal(t, 200, w.Code)
var result struct {
Success bool `json:"success"`
Status string `json:"status"`
}
assert.NoError(t, json.Unmarshal(w.Body.Bytes(), &result))
assert.True(t, result.Success, "the destination editor must be able to accept the persisted deletion")
assert.Equal(t, "success", result.Status, "retain the legacy acknowledgement")
})
t.Run("GetWebhookTemplates", func(t *testing.T) {