From 37972fc413a1aeb2a6aa789d129d7b3d922fe6d7 Mon Sep 17 00:00:00 2001 From: clawbot <35+clawbot@noreply.example.org> Date: Fri, 2 Oct 2026 16:30:44 +0000 Subject: [PATCH] Name the reaper's hard delete in the event body comments (closes #455) The comments on eventBodyQuery and on its reaped-event test credited the deleted_at predicate with refusing a reaped event. The retention reaper deletes event rows outright, so a reaped event is simply gone; nothing soft-deletes an event, so the predicate excludes nothing today and the test's soft-delete case only pins it. Model: opus-5-5 --- internal/handlers/event_body.go | 10 ++++++---- internal/handlers/event_body_test.go | 9 +++++---- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/internal/handlers/event_body.go b/internal/handlers/event_body.go index cf2452f..e0b242c 100644 --- a/internal/handlers/event_body.go +++ b/internal/handlers/event_body.go @@ -15,10 +15,12 @@ import ( // eventBodyQuery reads one event's stored body as bytes. The cast // to blob is what makes the driver hand back the stored bytes // rather than a string conversion, so Content-Length taken from -// the result matches what goes on the wire. The soft-delete -// predicate is spelled out because Raw bypasses GORM's default -// scope, and it is what stops a reaped event still being -// downloadable. +// the result matches what goes on the wire. The retention reaper +// deletes event rows outright, so a reaped event is simply gone +// and the query finds no row. The deleted_at predicate repeats +// the soft-delete scope GORM adds to its own queries, which Raw +// bypasses; nothing soft-deletes an event, so today it excludes +// nothing. const eventBodyQuery = "SELECT cast(body as blob) " + "FROM events WHERE id = ? AND webhook_id = ? AND deleted_at IS NULL" diff --git a/internal/handlers/event_body_test.go b/internal/handlers/event_body_test.go index e758635..0ab4692 100644 --- a/internal/handlers/event_body_test.go +++ b/internal/handlers/event_body_test.go @@ -405,10 +405,11 @@ func TestHandleEventBodyDownload_UnknownEvent404s(t *testing.T) { // route. The body is read in one query before any header is // written, so a reaped event cannot produce a partial download: // it is a clean 404 with no Content-Length and no -// Content-Disposition. Both removals the codebase performs are -// covered — the reaper hard-deletes, and a soft-deleted row is -// excluded by the query's own deleted_at predicate rather than -// by GORM's default scope, which Raw bypasses. +// Content-Disposition. The reaper deletes event rows outright, +// which is the "hard deleted" case. The "soft deleted" case +// covers a row no code produces today: it only pins the query's +// own deleted_at predicate, the soft-delete condition Raw would +// otherwise skip. func TestHandleEventBodyDownload_ReapedEvent404s(t *testing.T) { t.Parallel() -- 2.54.0