Summary
AuditAction::EventDeleted is defined but has no production call site anywhere in the codebase. Neither of the two paths that delete/tombstone an event (the standard NIP-09 soft-delete, or the hard-delete-on-supersede path for parameterized-replaceable events) ever writes an audit log entry. This relay currently cannot produce an audit trail for any event deletion.
Where
-
crates/buzz-audit/src/action.rs (~lines 8-31) defines AuditAction with 11 variants including EventDeleted (event_deleted in storage). Searching the whole tree, it appears in exactly two places: the enum definition itself, and one #[cfg(test)] unit test (crates/buzz-audit/src/service.rs, verify_detects_tampering_within_a_community) that uses it only as a generic sample action to exercise hash-chain tamper detection — not a real deletion code path.
-
NIP-09 deletion dispatch is in crates/buzz-relay/src/handlers/side_effects.rs:
handle_delete_event_side_effect (standard e-tag deletion) calls soft_delete_event_and_update_thread.
- The
a-tag (addressable/parameterized-replaceable) NIP-09 deletion path also calls soft_delete_event_and_update_thread.
Neither call path touches buzz_audit — there's no audit_tx.send(...) anywhere near either handler. Contrast with the two paths that do audit correctly on the same pattern:
crates/buzz-relay/src/handlers/event.rs (enqueue_event_created_audit) sends AuditAction::EventCreated after every successful event write.
crates/buzz-relay/src/api/media.rs sends AuditAction::MediaUploaded after a successful Blossom upload (explicitly commented as following "the same pattern as event audit").
No equivalent enqueue_event_deleted_audit exists.
-
Both deletion mechanisms confirmed:
- Soft delete / tombstone (the normal user-facing NIP-09 delete, both
e-tag and a-tag): soft_delete_event_and_update_thread and the lower-level delete_event/delete_by_kind_pubkey_dtag in crates/buzz-db/src/event.rs do UPDATE events SET deleted_at = NOW() WHERE ... AND deleted_at IS NULL. There is no DELETE FROM events anywhere in that file.
- Hard delete for parameterized-replaceable event supersession, gated behind a
hard_delete_superseded flag: replace_parameterized_event in crates/buzz-db/src/lib.rs issues DELETE FROM events WHERE community_id = $1 AND kind = $2 AND pubkey = $3 AND d_tag = $4 AND deleted_at IS NULL plus a companion DELETE FROM event_mentions.
Neither path calls into buzz_audit anywhere in crates/buzz-db or in the crates/buzz-relay/src/handlers/side_effects.rs caller.
Reproduction
A regression test reproducing this against real Postgres (standard_deletion_writes_no_audit_entry, crates/buzz-relay) is here, passing in CI: frodoHost#1
Related doc gap
ARCHITECTURE.md (~line 503) lists only 10 audit actions and omits MediaUploaded (which does exist and is wired up correctly) — worth fixing alongside this, and worth noting there that EventDeleted is defined-but-dead.
Summary
AuditAction::EventDeletedis defined but has no production call site anywhere in the codebase. Neither of the two paths that delete/tombstone an event (the standard NIP-09 soft-delete, or the hard-delete-on-supersede path for parameterized-replaceable events) ever writes an audit log entry. This relay currently cannot produce an audit trail for any event deletion.Where
crates/buzz-audit/src/action.rs(~lines 8-31) definesAuditActionwith 11 variants includingEventDeleted(event_deletedin storage). Searching the whole tree, it appears in exactly two places: the enum definition itself, and one#[cfg(test)]unit test (crates/buzz-audit/src/service.rs,verify_detects_tampering_within_a_community) that uses it only as a generic sample action to exercise hash-chain tamper detection — not a real deletion code path.NIP-09 deletion dispatch is in
crates/buzz-relay/src/handlers/side_effects.rs:handle_delete_event_side_effect(standarde-tag deletion) callssoft_delete_event_and_update_thread.a-tag (addressable/parameterized-replaceable) NIP-09 deletion path also callssoft_delete_event_and_update_thread.Neither call path touches
buzz_audit— there's noaudit_tx.send(...)anywhere near either handler. Contrast with the two paths that do audit correctly on the same pattern:crates/buzz-relay/src/handlers/event.rs(enqueue_event_created_audit) sendsAuditAction::EventCreatedafter every successful event write.crates/buzz-relay/src/api/media.rssendsAuditAction::MediaUploadedafter a successful Blossom upload (explicitly commented as following "the same pattern as event audit").No equivalent
enqueue_event_deleted_auditexists.Both deletion mechanisms confirmed:
e-tag anda-tag):soft_delete_event_and_update_threadand the lower-leveldelete_event/delete_by_kind_pubkey_dtagincrates/buzz-db/src/event.rsdoUPDATE events SET deleted_at = NOW() WHERE ... AND deleted_at IS NULL. There is noDELETE FROM eventsanywhere in that file.hard_delete_supersededflag:replace_parameterized_eventincrates/buzz-db/src/lib.rsissuesDELETE FROM events WHERE community_id = $1 AND kind = $2 AND pubkey = $3 AND d_tag = $4 AND deleted_at IS NULLplus a companionDELETE FROM event_mentions.Neither path calls into
buzz_auditanywhere incrates/buzz-dbor in thecrates/buzz-relay/src/handlers/side_effects.rscaller.Reproduction
A regression test reproducing this against real Postgres (
standard_deletion_writes_no_audit_entry,crates/buzz-relay) is here, passing in CI: frodoHost#1Related doc gap
ARCHITECTURE.md(~line 503) lists only 10 audit actions and omitsMediaUploaded(which does exist and is wired up correctly) — worth fixing alongside this, and worth noting there thatEventDeletedis defined-but-dead.