feat(nip11): advertise NIP-62 unless deletion disrespector

NIP-62 (request to vanish) support was honoured (kind-62 handler in
builder.rs) but never advertised in the NIP-11 supported_nips list.
Advertise NIP-62 (62) alongside NIP-09 (9), gated on the same
deletion_request_disrespector flag: a disrespector/archival relay omits
both so clients can discover it does not honour deletion requests.

- nip11: push 62 into supported_nips when disrespector is false.
- tests: extend the unit tests and the TestRelay-driven e2e
  nip11_advertisement_reflects_deletion_support to assert NIP-62
  presence/absence mirrors NIP-09.
- docs/config/nix/.env: document NIP-62 in the conditional NIP-11
  advertisement across all four config sources.

Note: disrespector still only short-circuits NIP-09 *processing*; the
kind-62 vanish handler is unchanged. The advertisement now reflects the
relay's deletion stance for both NIPs.
This commit is contained in:
DanConwayDev
2026-06-17 08:28:57 +00:00
parent 90ad63691d
commit 98ed855ce7
6 changed files with 50 additions and 27 deletions
+4 -2
View File
@@ -247,13 +247,15 @@
# When enabled, incoming NIP-09 (kind 5) deletion requests are STORED but NOT
# acted upon: targeted events remain fully accessible. This makes the relay an
# archival server, preserving content and preventing "left-pad" scenarios.
# NIP-11 supported_nips will NOT advertise NIP-09 (deletion) in this mode.
# NIP-11 supported_nips will NOT advertise NIP-09 (deletion) or NIP-62
# (request to vanish) in this mode.
#
# This ONLY affects NIP-09 user-initiated deletions. It does NOT prevent
# blacklist-triggered deletions (operator moderation: spam/malware/abuse).
#
# When disabled (default), deletion requests are honoured: targeted events are
# deleted and re-submission stays rejected. NIP-09 is advertised in NIP-11.
# deleted and re-submission stays rejected. NIP-09 and NIP-62 are advertised in
# NIP-11.
#
# See: docs/explanation/deletion-requests.md
#
+7 -5
View File
@@ -79,10 +79,12 @@ tombstone; cascade = walk the references of a recorded deletion).
therefore stored in the main DB so clients get an OK), but it is **not** acted
upon: no purgatory eviction, no main-DB deletion, and no tombstone is recorded.
Targeted events stay fully accessible, making the relay an archival server.
This only affects NIP-09 (kind 5); NIP-62 vanish handling is unchanged.
NIP-11 advertisement reflects the mode: NIP-09 (`9`) is included in
The short-circuit only affects NIP-09 (kind 5) *processing*; NIP-62 vanish
*handling* is unchanged. NIP-11 advertisement, however, reflects the mode for
both deletion NIPs: NIP-09 (`9`) and NIP-62 (`62`) are included in
`supported_nips` only when disrespector is `false`
([`src/http/nip11.rs`](../../src/http/nip11.rs)).
([`src/http/nip11.rs`](../../src/http/nip11.rs)), so clients can discover that
an archival relay does not honour deletion requests.
---
@@ -516,8 +518,8 @@ How long to retain archived events and git data before permanent deletion. Provi
Deletion support is **conditionally advertised** in NIP-11 relay information
(implemented in [`src/http/nip11.rs`](../../src/http/nip11.rs)):
- **When `deletion_request_disrespector = false`:** include `9` (`"deletion"`) in the supported NIPs array
- **When `deletion_request_disrespector = true`:** do NOT include `9` (archival mode doesn't honor deletions)
- **When `deletion_request_disrespector = false`:** include `9` (`"deletion"`) and `62` (`"request to vanish"`) in the supported NIPs array
- **When `deletion_request_disrespector = true`:** do NOT include `9` or `62` (archival mode doesn't honor deletions)
This allows clients to discover whether a relay respects deletion requests.
+3 -3
View File
@@ -1055,14 +1055,14 @@ Event blacklist does **not** affect NIP-11 metadata:
hard-deleted from the relay, matching purgatory entries are evicted, and a
persistent tombstone is recorded so re-submission of the deleted event stays
rejected across restarts.
- NIP-11 `supported_nips` includes `9` (deletion).
- NIP-11 `supported_nips` includes `9` (deletion) and `62` (request to vanish).
- When `true`:
- Incoming NIP-09 deletion requests are still **stored** (the client receives
an OK), but they are **not acted upon**. Targeted events remain fully
accessible. This makes the relay an archival server, preserving content and
preventing "left-pad" scenarios.
- NIP-11 `supported_nips` does **not** include `9`, so clients can discover
that this relay does not honour deletions.
- NIP-11 `supported_nips` does **not** include `9` or `62`, so clients can
discover that this relay does not honour deletions.
**IMPORTANT:** This setting ONLY affects NIP-09 user-initiated deletions. It does
**NOT** prevent blacklist-triggered deletions, which are an operator moderation
+4 -3
View File
@@ -266,13 +266,14 @@ let
When enabled, incoming NIP-09 (kind 5) deletion requests are stored
but NOT acted upon: targeted events remain fully accessible. This
preserves content and prevents "left-pad" scenarios. NIP-11
supported_nips will NOT advertise NIP-09 (deletion).
supported_nips will NOT advertise NIP-09 (deletion) or NIP-62
(request to vanish).
This ONLY affects NIP-09 user-initiated deletions. It does NOT prevent
blacklist-triggered deletions (operator moderation).
When disabled (default), deletion requests are honoured and NIP-09 is
advertised in NIP-11.
When disabled (default), deletion requests are honoured and NIP-09 and
NIP-62 are advertised in NIP-11.
See: docs/explanation/deletion-requests.md
'';
+16 -9
View File
@@ -112,13 +112,15 @@ impl RelayInformationDocument {
34, // NIP-34: Git repository announcements
77, // NIP-77: Negentropy sync (reconciliation protocol)
];
// NIP-09 (deletion) is honoured only when not running as an
// archival "disrespector" relay. When disrespector mode is on
// the relay stores but ignores deletion requests, so we must not
// advertise NIP-09 support — clients can then discover that this
// relay does not honour deletions.
// NIP-09 (deletion) and NIP-62 (request to vanish) are honoured
// only when not running as an archival "disrespector" relay. When
// disrespector mode is on the relay stores but ignores deletion /
// vanish requests, so we must not advertise NIP-09 or NIP-62
// support — clients can then discover that this relay does not
// honour deletions.
if !config.deletion_request_disrespector {
nips.push(9); // NIP-09: Event deletion requests
nips.push(62); // NIP-62: Request to vanish
nips.sort_unstable();
}
nips
@@ -170,8 +172,10 @@ mod tests {
assert!(doc.supported_nips.contains(&11));
assert!(doc.supported_nips.contains(&34));
assert!(doc.supported_nips.contains(&77));
// NIP-09 (deletion) advertised by default (disrespector off).
// NIP-09 (deletion) and NIP-62 (vanish) advertised by default
// (disrespector off).
assert!(doc.supported_nips.contains(&9));
assert!(doc.supported_nips.contains(&62));
// Without archive mode, only GRASP-01 and GRASP-02
assert_eq!(doc.supported_grasps, vec!["GRASP-01", "GRASP-02"]);
assert!(doc.repo_acceptance_criteria.contains("None"));
@@ -329,8 +333,10 @@ mod tests {
let config = Config::for_testing();
let doc = RelayInformationDocument::from_config(&config);
// NIP-09 (deletion) is honoured (and advertised) by default.
// NIP-09 (deletion) and NIP-62 (vanish) are honoured (and advertised)
// by default.
assert!(doc.supported_nips.contains(&9));
assert!(doc.supported_nips.contains(&62));
}
#[test]
@@ -340,9 +346,10 @@ mod tests {
let doc = RelayInformationDocument::from_config(&config);
// Archival relays do not honour deletions, so NIP-09 must not be
// advertised.
// Archival relays do not honour deletions, so NIP-09 and NIP-62 must
// not be advertised.
assert!(!doc.supported_nips.contains(&9));
assert!(!doc.supported_nips.contains(&62));
// Other NIPs are unaffected.
assert!(doc.supported_nips.contains(&1));
assert!(doc.supported_nips.contains(&34));
+16 -5
View File
@@ -13,8 +13,8 @@
//! `OK`, yet the targeted announcement remains queryable afterwards.
//! 2. **Normal mode honours deletion** — the same flow against a default relay
//! removes the target.
//! 3. **NIP-11 advertisement** — a disrespector relay omits `9` from
//! `supported_nips`; a normal relay advertises it.
//! 3. **NIP-11 advertisement** — a disrespector relay omits `9` and `62` from
//! `supported_nips`; a normal relay advertises both.
//!
//! # Running
//!
@@ -330,10 +330,11 @@ async fn fetch_supported_nips(relay: &TestRelay) -> Vec<u64> {
.expect("NIP-11 document must contain a supported_nips array")
}
/// NIP-11 advertisement: disrespector omits NIP-09, normal mode advertises it.
/// NIP-11 advertisement: disrespector omits NIP-09/NIP-62, normal mode
/// advertises both.
#[tokio::test]
async fn nip11_advertisement_reflects_deletion_support() {
// Disrespector relay: NIP-09 (9) MUST be absent.
// Disrespector relay: NIP-09 (9) and NIP-62 (62) MUST be absent.
let disrespector = TestRelay::start_with_deletion_disrespector().await;
let supported = fetch_supported_nips(&disrespector).await;
disrespector.stop().await;
@@ -343,8 +344,13 @@ async fn nip11_advertisement_reflects_deletion_support() {
"disrespector relay must NOT advertise NIP-09; supported_nips = {:?}",
supported
);
assert!(
!supported.contains(&62),
"disrespector relay must NOT advertise NIP-62; supported_nips = {:?}",
supported
);
// Normal relay: NIP-09 (9) MUST be present.
// Normal relay: NIP-09 (9) and NIP-62 (62) MUST be present.
let normal = TestRelay::start().await;
let supported = fetch_supported_nips(&normal).await;
normal.stop().await;
@@ -354,4 +360,9 @@ async fn nip11_advertisement_reflects_deletion_support() {
"normal relay must advertise NIP-09; supported_nips = {:?}",
supported
);
assert!(
supported.contains(&62),
"normal relay must advertise NIP-62; supported_nips = {:?}",
supported
);
}