From dcc3204735f74cf2df4bf604a9fcacdbb5fd1050 Mon Sep 17 00:00:00 2001 From: Patrick Mulligan Date: Sun, 16 Nov 2025 22:47:16 +0100 Subject: [PATCH] Fix NIP-09 deletion for parameterized replaceable events (NIP-33) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixed bug where deleting a parameterized replaceable event (e.g., kind 31922) using an 'a' tag would incorrectly delete ALL events of that kind instead of just the specific event with the matching d-tag. **Root Cause:** NostrFilter's 'd' field uses a Pydantic Field alias "#d". When creating a filter with `NostrFilter(d=[value])`, Pydantic ignores it because the parameter name doesn't match the alias. **Fix:** Changed filter creation to use the alias: ```python NostrFilter(authors=[...], kinds=[...], **{"#d": [d_tag]}) ``` **Testing:** - Created two tasks with different d-tags - Deleted only one task - Verified only the specified task was marked as deleted in the database - Confirmed the other task remained unaffected This ensures proper NIP-09 deletion behavior for NIP-33 parameterized replaceable events using 'a' tag format (kind:pubkey:d-identifier). 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- relay/client_connection.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/relay/client_connection.py b/relay/client_connection.py index ed9a84b..a64bccc 100644 --- a/relay/client_connection.py +++ b/relay/client_connection.py @@ -235,15 +235,20 @@ class NostrClientConnection: kind = int(kind_str) # Only delete if the address pubkey matches the deletion event author if addr_pubkey == event.pubkey: + # NOTE: Use "#d" alias, not "d" directly (Pydantic Field alias) nostr_filter = NostrFilter( authors=[addr_pubkey], kinds=[kind], - d=[d_tag] + **{"#d": [d_tag]} # Use alias to set d field ) events_to_delete = await get_events(self.relay_id, nostr_filter, False) ids_to_delete.extend([e.id for e in events_to_delete if not e.is_delete_event]) + else: + logger.warning(f"Deletion request pubkey mismatch: {addr_pubkey} != {event.pubkey}") except ValueError: logger.warning(f"Invalid kind in address: {addr}") + else: + logger.warning(f"Invalid address format (expected kind:pubkey:d-tag): {addr}") # Only mark events as deleted if we found specific IDs if ids_to_delete: