Deleting a target blanks its name on every historical delivery in the event log #211
Reference in New Issue
Block a user
Delete Branch "%!s()"
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?
Deletes are soft (
internal/database/base_model.go:16,deleteChildResourceatinternal/handlers/source_management.go:1295-1298) and deliveries carry no FK to the target row, so deleting a target correctly preserves all its delivery history — verified, the rows survive intact.But
loadTargetMap(source_management.go:800-820) queries under GORM's default scope, so the soft-deleted target is excluded andtargetMap[TargetID]yields a zeroTargetView.templates/source_logs.html:26-30then renders{{.Target.Name}}: {{.Status}}as:Verified before and after: the target name disappeared from the log page while its delivery rows remained. The history survives; its label does not.
This is the practical cost of having no target edit form (#127) — changing a destination URL means delete and recreate, and that silently unlabels everything the old target ever did.
Definition of done:
loadTargetMapincludes soft-deleted targets (Unscoped(), or a dedicated lookup) so historical deliveries keep their nameecho-sink (deleted)Not milestoned to 1.0.0: it is a display defect on an already-degraded path, and #127 plus the replay work may reshape it.
clawbot referenced this issue2026-08-20 05:56:52 +02:00
Plan:
loadTargetMap(internal/handlers/source_management.go) already loadsUnscoped()for the redactor half and then discards soft-deleted rows before building the view half. Build the view half from every loaded row instead, so a historical delivery resolves to a named view.delivery.TargetViewgains aDeletedflag set fromDeletedAt.Valid, plus aDisplayName()that rendersname (deleted). Views keep coming fromNewTargetViews, so config masking stays a single chokepoint and a deleted target is masked by exactly the same code as a live one.templates/source_logs.htmlrendersDisplayNameat both places a delivery's target is named.loadTargetMapfeeds onlyDeliveryView.Targeton the event log page. The target list on the source detail page has its own scoped query, and the replay path resolves its target separately and already refuses a deleted one. No delivery-engine code is touched.Tests: a delivery from a since-deleted target renders its name with the marker, and a credential stored in a deleted target's config does not appear in the rendered page.
Built in #266 (branch
issue-211-deleted-target-name, basenext).loadTargetMapnow builds its view half from the soft-deleted rows it was already loadingUnscoped()for the redactor half, anddelivery.TargetViewrendersname (deleted)through a newDisplayName()thattemplates/source_logs.htmluses at both places a delivery's target is named.Verified: both new handler tests fail on unmodified
next(page renders: deliveredand an empty name span) and pass on the branch. On a running instance, with the same script against a build ofnextand a build of the branch — real event delivered through a target namedNAMED-TARGET-211, then deleted through the UI —nextshows zero occurrences of the name afterwards and the branch showsNAMED-TARGET-211 (deleted): delivered, while the source detail target list still shows nothing. A credential stored in a deleted target's config stays masked, asserted by a test.make checkgreen withGOFLAGS=-count=1, lint run uncached in Docker.The PR body records what else consumes the widened lookup and what stays scoped.