fix(relay): NIP-09 a-tag deletion soft-deletes addressable rows (#714)#716
Closed
tlongwell-block wants to merge 1 commit into
Closed
fix(relay): NIP-09 a-tag deletion soft-deletes addressable rows (#714)#716tlongwell-block wants to merge 1 commit into
tlongwell-block wants to merge 1 commit into
Conversation
`handle_a_tag_deletion` in `crates/sprout-relay/src/handlers/side_effects.rs` previously only had a side-effect branch for `KIND_WORKFLOW_DEF`. Every other addressable kind — including kind:30023 (NIP-23 long-form) — fell through to the `_ =>` arm which only emitted a debug log. The kind:5 deletion event was accepted and stored, but the target row was never soft-deleted, so subsequent REQs still returned it. This was discovered while building `sprout notes` (CLI for NIP-23 long-form content): the semantically correct way to delete a parameterized-replaceable note is by `a` coordinate, but until this fix the relay silently no-op'd. The CLI shipped a dual-tag workaround (`["e", id]` + `["a", coord]`); once this lands, the a-tag becomes load-bearing. Changes: - `sprout_db::event::soft_delete_by_coordinate(pool, kind, pubkey, d_tag)`: new helper mirroring `soft_delete_event`. WHERE clause matches the NIP-33 replacement key used by `replace_parameterized_event` exactly — `channel_id` is intentionally not in the key (NIP-33 replacement is global per the spec; `channel_id` is for query scoping, not identity). - `Db::soft_delete_by_coordinate` wrapper for caller ergonomics. - `handle_a_tag_deletion`: new arm `k if is_parameterized_replaceable(k) =>` between the existing workflow branch and `_ =>`. Workflow keeps its bespoke deletion (`delete_workflow` only touches `workflows`; the underlying kind:30620 row in `events` is left alive by design — out of scope for this fix). For every other NIP-33 kind the new helper runs and the row is soft-deleted. `_ =>` is now correctly scoped to "non-NIP-33 kind" only. - `e2e_long_form.rs::test_long_form_a_tag_deletion`: full round-trip regression test (publish → verify queryable → a-tag kind:5 → verify REQ returns 0). `#[ignore]`'d like the rest of that file (needs a running relay). Read-path filtering in `req.rs` already gates on `deleted_at IS NULL`, so once the side-effect path soft-deletes the row, REQs hide it automatically. No filter changes needed. Verified locally: - `cargo build -p sprout-db -p sprout-relay -p sprout-test-client` - `cargo test -p sprout-db --lib` → 64/64 - `cargo test -p sprout-relay --lib` → 192/192 - `cargo clippy -p sprout-db -p sprout-relay -p sprout-test-client --all-targets -- -D warnings` - `cargo fmt --check` - New e2e test compiles cleanly; runs against a live relay via CI. Signed-off-by: tlongwell-block <109685178+tlongwell-block@users.noreply.github.com> Co-authored-by: Dawn (sprout agent) <c6237ef84fa537c78dcee78efd2d4e59f728859c7f194da42ac51ededfa0be05@sprout-oss.stage.blox.sqprod.co>
This was referenced May 21, 2026
Collaborator
Author
|
Superseded by #719 (combined into one PR per Tyler). Relay a-tag fix carried over verbatim. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #714.
What
handle_a_tag_deletioninsprout-relaypreviously only handledKIND_WORKFLOW_DEF. Every other addressable kind — including kind:30023 (NIP-23 long-form) — fell through to a debug-only_ =>arm. The kind:5 event was accepted and stored, but the target row was never soft-deleted, so REQs kept returning it.This PR generalises the side-effect path to soft-delete any parameterized-replaceable row by coordinate.
How
sprout_db::event::soft_delete_by_coordinate(pool, kind, pubkey, d_tag) -> Result<bool>— new helper mirroringsoft_delete_event. WHERE clause is lifted fromreplace_parameterized_event(the NIP-33 replacement path) so coordinate semantics stay consistent:channel_idis intentionally not in the key. Wrapped onDbfor caller ergonomics.handle_a_tag_deletion— new armk if is_parameterized_replaceable(k) =>between the workflow branch and_ =>. Workflow's bespoke deletion keeps its precedence (delete_workflowonly touches theworkflowstable by design — the underlying kind:30620 row ineventsis left alive, see Note below). For every other NIP-33 kind, the new helper runs.e2e_long_form.rs::test_long_form_a_tag_deletion— full round-trip: publish kind:30023 → verify queryable → emit kind:5 with["a", "30023:pubkey:d-tag"]→ verify REQ returns 0.#[ignore]'d, matching the rest of that file.Read-path filtering in
req.rsalready gates ondeleted_at IS NULL, so once the soft-delete fires, REQs hide the row automatically. No filter changes needed.Note on workflow
delete_workflow(workflow's existing branch) only deletes fromworkflows; the underlying kind:30620 row ineventsstays alive. Same bug shape as #714 for a different kind, but fixing it could change workflow lifecycle assumptions. Scoped narrowly here — my new arm fires for all NIP-33 kinds except workflow. Happy to file a separate issue if anyone agrees that's a gap worth closing.Verified
cargo build -p sprout-db -p sprout-relay -p sprout-test-clientcargo test -p sprout-db --lib→ 64/64 (0 failures, 10 ignored as before)cargo test -p sprout-relay --lib→ 192/192cargo clippy -p sprout-db -p sprout-relay -p sprout-test-client --all-targets -- -D warningscargo fmt --checkThe new e2e case (
test_long_form_a_tag_deletion) needs a live relay; CI will exercise it.