block / block/buzz

relay: NIP-09 a-tag deletion is a no-op for kind:30023 (and all non-workflow addressables)

Open
#714 1 comment 0 reactions 0 assignees View on GitHub
Dominant language
Rust
Stars
32.7k
Forks
4.3k
Avg merge
1d 13h
Merged PRs (30d)
253

Description

## Summary

`handle_a_tag_deletion` in `crates/sprout-relay/src/handlers/side_effects.rs` (≈line 1330) only implements a side-effect branch for `KIND_WORKFLOW_DEF`. All other addressable kinds — including kind:30023 (NIP-23 long-form) — fall through to the `_ =>` arm which only emits a debug log. The kind:5 deletion event is accepted and stored, but the targeted addressable row is never soft-deleted, so subsequent REQs still return it.

## Why this matters

`sprout-cli` is gaining `notes rm` for the team knowledge-base workflow (NIP-23 editable notes). The semantically correct NIP-09 deletion of a parameterized-replaceable note targets its `a` coordinate (`30023::`), not just the event id — otherwise a future re-`set` of the same slug could be shadowed by a stale tombstone or cause confusion about which event id is authoritative.

The CLI's v1 workaround is to include **both** an `e`-tag (current event id, which works via the existing soft-delete path) and an `a`-tag (forward-compatible, currently a no-op). Once this relay-side gap is closed, `rm` becomes more robust without any CLI change.

## Code pointers

- `crates/sprout-relay/src/handlers/side_effects.rs:1330` — `handle_a_tag_deletion`; the `_ =>` branch is the gap.
- `crates/sprout-db/src/event.rs` — `soft_delete_event(event_id)` exists; no `soft_delete_by_coordinate` analogue.
- Read-path filtering in `crates/sprout-relay/src/handlers/req.rs` already gates on `deleted_at IS NULL`, so once the side-effect path soft-deletes the row, REQs hide it automatically.

## Proposed fix (sketch, non-binding)

1. Add `sprout_db::event::soft_delete_addressable(pool, kind, pubkey, d_tag) -> Result` that updates `deleted_at` on the row matching `(kind, pubkey, d_tag)`. The `d_tag` column already exists and is indexed for NIP-33 kinds.
2. In `handle_a_tag_deletion`, replace the unconditional `_ =>` debug log with a call to that helper for *any* parameterized-replaceable kind (or a documented allowlist if we want to be cautious). Workflow-specific logic stays where it is.

## Validation already done

- e-tag deletion path works fully for kind:30023 (`deleted_at` set; REQs hide it).
- a-tag kind:5 events are accepted by validation (`validate_standard_deletion_event` correctly checks author ownership via pubkey-in-coordinate), but have no DB-level effect.

## Scope

Out of scope: rebroadcast / discovery of the deletion event to other relays. This issue is purely about the local read-path consistency.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.