From e848dbca97b8d53c930f5ca1c05f19ae36a894d7 Mon Sep 17 00:00:00 2001 From: DanConwayDev Date: Thu, 15 Jan 2026 07:50:12 +0000 Subject: [PATCH] issue: create fc4d - investigate rust-nostr deletion request broadcast behavior --- ...-rust-nostr-deletion-broadcast-behavior.md | 211 ++++++++++++++++++ 1 file changed, 211 insertions(+) create mode 100644 fc4d-rust-nostr-deletion-broadcast-behavior.md diff --git a/fc4d-rust-nostr-deletion-broadcast-behavior.md b/fc4d-rust-nostr-deletion-broadcast-behavior.md new file mode 100644 index 0000000..c9a10a4 --- /dev/null +++ b/fc4d-rust-nostr-deletion-broadcast-behavior.md @@ -0,0 +1,211 @@ +# rust-nostr: Deletion Request Broadcast Behavior Investigation + +**ID:** fc4d + +**Status:** Investigation Needed +**Priority:** Low (Non-Urgent) +**Complexity:** Medium (requires rust-nostr codebase investigation) +**Type:** Potential Upstream PR + +## Problem Statement + +When ngit-grasp runs in "deletion request disrespector" mode (`deletion_request_disrespector = true`), it accepts kind 5 (NIP-09 deletion request) events but intentionally does NOT process them. The events should be: + +1. **Stored in the database** (for historical record) +2. **Broadcast to active WebSocket subscribers** with matching filters (standard relay behavior) + +**Current uncertainty:** We need to verify that rust-nostr's `nostr-relay-builder` actually broadcasts kind 5 events to active subscribers when `WritePolicyResult::Accept` is returned from the WritePolicy. + +### Why This Matters + +**Archive relay use case:** +- Archive relays preserve deleted content (prevent "left-pad" scenarios) +- Deletion requests are legitimate events that clients may want to track +- Clients with filters matching kind 5 should receive these events +- This is standard relay behavior: accepted events → saved + broadcast + +**Current implementation:** +```rust +// src/nostr/builder.rs:759-766 +DeletionResult::AcceptIgnore => { + tracing::debug!( + event_id = %event_id_str, + author = %event.pubkey, + "Accepted deletion request but ignoring (disrespector mode)" + ); + WritePolicyResult::Accept // ← Does this trigger broadcast? +} +``` + +## Investigation Tasks + +### Phase 1: Verify Current Behavior + +- [ ] **Test current ngit-grasp behavior:** + - [ ] Start relay in disrespector mode + - [ ] Connect WebSocket client with filter: `{"kinds": [5]}` + - [ ] Submit kind 5 deletion request + - [ ] Verify: Is event broadcast to subscriber? + - [ ] Verify: Is event stored in database? + +- [ ] **Document findings:** + - [ ] If YES (broadcasts): Document that current behavior is correct + - [ ] If NO (doesn't broadcast): Document the gap + +### Phase 2: Investigate rust-nostr Source Code + +- [ ] **Examine nostr-relay-builder event flow:** + - [ ] Trace `WritePolicyResult::Accept` through relay code + - [ ] Find where events are saved to database + - [ ] Find where events are broadcast to subscribers + - [ ] Determine if kind 5 has special handling that bypasses broadcast + +- [ ] **Check for automatic NIP-09 processing:** + - [ ] Verify if relay layer (not just database layer) filters kind 5 + - [ ] Check if there's a "don't broadcast deletion requests" policy + - [ ] Document any hardcoded NIP-09 behavior + +### Phase 3: Determine If PR Is Needed + +Based on investigation findings: + +**Scenario A: Current behavior is correct (broadcasts kind 5)** +- [ ] Document that no PR is needed +- [ ] Update ngit-grasp docs to confirm broadcast behavior +- [ ] Close this issue as "working as designed" + +**Scenario B: rust-nostr doesn't broadcast kind 5 events** +- [ ] Determine root cause (intentional vs bug) +- [ ] Design PR proposal (see below) +- [ ] Discuss with rust-nostr maintainers +- [ ] Implement and submit PR + +## Proposed PR (If Needed) + +### Option 1: Fix Bug (if it's unintentional) + +If rust-nostr is accidentally not broadcasting kind 5 events when `WritePolicyResult::Accept` is returned: + +**Change:** Ensure kind 5 events follow standard event flow (save + broadcast) + +**Rationale:** +- NIP-09 says relays "MAY" honor deletions, not "MUST" +- Accepting but not processing is legitimate (archive relays) +- Accepted events should always be broadcast to matching subscribers +- This is standard relay behavior regardless of event kind + +### Option 2: Add Configuration (if it's intentional) + +If rust-nostr intentionally doesn't broadcast kind 5 events: + +**Change:** Add configuration option to control kind 5 broadcast behavior + +```rust +pub struct RelayOptions { + // ... existing fields ... + + /// Broadcast deletion requests (kind 5) to subscribers + /// When false, kind 5 events are saved but not broadcast + /// Default: true (standard relay behavior) + pub broadcast_deletion_requests: bool, +} +``` + +**Rationale:** +- Some relays may want to suppress deletion request broadcasts +- Archive relays need full transparency (broadcast everything) +- Configuration provides flexibility for different relay policies + +### Option 3: No Change Needed (if configurable) + +If rust-nostr already has a way to control this behavior: + +- [ ] Document the configuration option +- [ ] Update ngit-grasp to use it correctly +- [ ] No upstream PR needed + +## NIP-09 Specification Context + +**From NIP-09:** +> Relays **MAY** choose to honor deletion requests or not. + +**Implications:** +1. Accepting kind 5 without processing is **legitimate** +2. Clients should be able to **see** deletion requests (for transparency) +3. Broadcast behavior should be **consistent** with other event kinds +4. Archive relays need **full event history** including deletion requests + +**Use cases for seeing deletion requests:** +- Audit trails (who deleted what, when) +- Research and analysis (deletion patterns) +- Client-side deletion handling (some clients may honor deletions locally) +- Transparency (users can see what was requested to be deleted) + +## Related Work + +**ngit-grasp implementation:** +- Issue: `b905-deletion-request-support.md` +- Implementation: Phase 1-4 complete (holding database, recovery, graph algorithm) +- Disrespector mode: Working (stores events, doesn't process deletions) +- Question: Are stored events being broadcast? + +**rust-nostr investigation:** +- Previous finding: Database layer automatically processes kind 5 (deletes events) +- Workaround: WritePolicy intercepts before database layer +- New question: Does relay layer broadcast accepted kind 5 events? + +## Success Criteria + +1. ✅ **Verified behavior:** We know whether kind 5 events are broadcast in disrespector mode +2. ✅ **Documented findings:** Clear documentation of rust-nostr behavior +3. ✅ **Decision made:** PR needed vs no PR needed +4. ✅ **If PR needed:** Proposal written and discussed with maintainers + +## Timeline + +**Priority:** Low (non-urgent) +- Not blocking ngit-grasp Phase 4-7 implementation +- Can be investigated after deletion support is complete +- Good candidate for post-implementation cleanup + +**Suggested timing:** +- After Phase 7 (ngit-grasp deletion support complete) +- When we have working disrespector mode to test against +- Before announcing archive relay capabilities publicly + +## Progress + +### 2026-01-15 [Session 10:00] +- **Created issue:** Based on user question about deletion request broadcast behavior +- **Context:** User correctly identified that "deletion request" implies optional processing +- **Question raised:** Are kind 5 events broadcast to WebSocket subscribers in disrespector mode? +- **Pattern:** ngit-grasp directly saves events to database, which triggers broadcast elsewhere +- **Uncertainty:** Need to verify this pattern applies to kind 5 events +- **Next:** Investigate current behavior with test client, then examine rust-nostr source + +## Notes + +**Key insight from user:** +> "The clue is in the name 'request'" - NIP-09 deletion requests are optional, not mandatory + +**Standard relay pattern:** +``` +Event arrives → WritePolicy.admit_event() → WritePolicyResult::Accept + ↓ + Database.save_event() → Broadcast to subscribers +``` + +**Question:** Does this pattern apply to kind 5 events, or do they have special handling? + +**Why this matters:** +- Archive relays need transparency (show all events including deletion requests) +- Clients may want to track deletion requests for audit/analysis +- Standard relay behavior: accepted events are broadcast +- Consistency: kind 5 shouldn't be special-cased unless necessary + +## References + +- **NIP-09 Spec:** `/persistent/dcdev/clones/nips/09.md` +- **ngit-grasp deletion support:** `b905-deletion-request-support.md` +- **rust-nostr investigation:** Previous findings in b905 Phase 6 notes +- **nostr-relay-builder:** `~/.cargo/git/.../nostr-relay-builder/`