Name a deleted target on its historical deliveries (closes #211) #266
Reference in New Issue
Block a user
Delete Branch "issue-211-deleted-target-name"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Closes #211.
Deleting a target soft deletes its row while its deliveries survive in the per-webhook database, so the event log kept the history and lost the label.
Change
loadTargetMap(internal/handlers/source_management.go) already loaded soft-deleted rowsUnscoped()for the redactor half, then discarded them before building the view half. It now builds both halves from every loaded row.delivery.TargetViewgainsDeleted(fromDeletedAt.Valid) andDisplayName(), which rendersname (deleted). The bare name is not restored: an operator debugging an old delivery needs to know the target is gone, not just what it was called.Namestays the stored name.templates/source_logs.htmlrendersDisplayNameat both places a delivery's target is named (the collapsed status line and the deliveries block heading).Masking is unchanged
Views still come from
NewTargetViews, so a deleted target's configuration is masked by exactly the code that masks a live one's —TargetViewhas no raw config field, and nothing else was widened.TestHandleSourceLogs_MasksDeletedTargetConfigstores a Slack webhook URL on a target, deletes the target through the real delete handler, and asserts neither the credential path norwebhookUrlappears in the rendered page while the name does.Scope of the widening — what I audited
The map is historical display only. Its view half reaches nothing but
DeliveryView.Targeton the event log page. Everything that could deliver to or re-activate a target resolves its own targets and is untouched:loadActiveTargets(internal/handlers/webhook.go), scoped andactive = true.loadTargetMap(internal/delivery/engine.go): scoped. No file underinternal/deliveryother than the display projectiontarget_config_view.gois touched, so nothing here anticipates #107.replayTarget(internal/handlers/delivery_replay.go) does its ownUnscoped()lookup and still refuses a deleted target with its own banner.source_management.go:452) and the target edit form (ownedTarget): scoped, so a deleted target stays off both. Confirmed live below.Other views that show a target name against historical data
Searched every template and handler.
templates/source_logs.htmlis the only place a name renders against delivery history, and both of its occurrences are fixed.target_edit.htmlrenders a live target only. The replay and resubmit banners name no target. There is no JSON/API surface that projects a target name. Atarget_idnaming no row at all — deleted or otherwise — still renders blank, but no code path hard deletes a target, so that state is not reachable through the app.Verification
make checkgreen,GOFLAGS=-count=1, lint ran uncached in Docker ([lint 3/3] RUN golangci-lint run—0 issues, 48s, notCACHED); all 20 packagesok.Both new handler tests were confirmed failing on unmodified
nextfirst: the rendered page contained: deliveredand<span class="text-sm text-gray-700"></span>.Live before/after on a running instance, same script against a build of unmodified
nextand a build of this branch: create alogtarget namedNAMED-TARGET-211, POST a real event through the entrypoint, view the event log, delete the target through the UI, view it again.Unmodified
next, after the delete:This branch, after the same delete:
and on the source detail page after the delete,
occurrences of NAMED-TARGET-211 on detail page: 0— the deleted target does not come back into the live target list.Tests added:
TestHandleSourceLogs_NamesDeletedTarget(before/after control on one source, deleting through the real handler),TestHandleSourceLogs_MasksDeletedTargetConfig,TestNewTargetViews_DeletedTarget, plus live-targetDeleted/DisplayNameassertions folded intoTestNewTargetViews_Slackso the marker cannot reach a name that still exists.TODO.mddeliberately untouched per #112.PASS.
Checked by execution from a clean clone: the blanking reproduces on the parent commit and is fixed at both render sites (marker appears exactly twice, matching the live control); no credential (Slack webhook URL, HTTP destination URL,
Authorization: Bearerheader) reaches the event log or the source detail page for a deleted target, and its masked rendering is identical to a live target's; the redactor half is unchanged and still redacts a deleted target's stored response body and error; the deleted target stays refused by the source detail list, the edit form (404), toggle, replay (?replay=target-deleted, no new delivery queued) and both fan-outs; a delete mid-retry rendersname (deleted)withretryingand does not panic; both new handler tests fail on the parent. CI green on2729155;make checkgreen withGOFLAGS=-count=1(88s, 20/20 packagesok, zero(cached), lint uncached in Docker,0 issues); mergeable withnext.Two points worth recording rather than confirming:
deleteWebhookResourcessoft-deletes targets while destroying the whole per-webhook event database, so no delivery survives to be orphaned; and theDELETE FROM targetsininternal/database/event_db_isolation.goclears a stray legacy table inside the event database, not the config database. Unreachable as claimed.templates/source_logs.htmlreads only.Target.DisplayName, so the widened view'sConfignever reaches a template at all. TheUnscoped()load itself was already present on the parent, so the query was not widened — only which loaded rows get projected.Disclosures: no live HTTP instance was stood up; the harness drove the real handlers and real templates in-process, which is the same rendering path. Anomaly, not a defect: the landing commit is authored
sneak <sneak@sneak.berlin>where neighbouring commits areclawbot.