issue: create fc4d - investigate rust-nostr deletion request broadcast behavior

This commit is contained in:
DanConwayDev
2026-01-15 07:50:12 +00:00
parent a19325a6c7
commit e848dbca97
@@ -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/`