relay: accept NIP-32 labels (kind:1985) — pairs with the NIP-11 `self` Buzz already publishes
- Dominant language
- Rust
- Stars
- 32.7k
- Forks
- 4.3k
- Avg merge
- 1d 13h
- Merged PRs (30d)
- 253
Description
*This adds a new event kind, so opening an issue for the prior discussion
CONTRIBUTING asks for. The implementation is already written and linked below as a
PR so the proposal is reviewable rather than abstract — but the direction question
is the one that matters here, and I'd close the PR without complaint if the answer
is no.*
**Motivation**
Buzz refuses kind:1985 (NIP-32 labels) at ingest, because `required_scope_for_kind`
is an allowlist that returns `Err` for unregistered kinds.
This is an interop gap rather than a missing feature: most relays are kind-agnostic
and already carry labels. Querying `{"kinds":[1985]}` returns live events from
nos.lol, relay.primal.net and offchain.pub today — one sample carries
`["L","ISO-639-1"]` / `["l","es","ISO-639-1"]`, i.e. language labelling. Buzz is
currently the one that says no.
The reason it's worth doing in Buzz specifically is the identity half, which Buzz
already has and most relays don't expose:
- Buzz publishes a NIP-11 `self`, which NIP-11 defines as a relay's identity
"independent from its administrator".
- Buzz implements NIP-43, which *requires* it: "This event MUST be signed by the
pubkey specified in the `self` field of the relay's NIP-11 document."
So Buzz already has a relay identity that is **bound to its endpoint** and already
signs events with it. NIP-32 is the general-purpose attestation primitive, and
giving that existing identity the ability to issue labels is a small change with a
disproportionate reach: a reader can then verify *the relay at this address made
this claim*.
That is a stronger statement than what a relay-signed event alone gives you. Live
NIP-29 relays I checked (groups.0xchat.com, relay.groups.nip29.com,
groups.fiatjaf.com — all khatru) sign group metadata with a relay key but do **not**
publish `self`, so the most a reader can conclude there is "some key signed this".
The `self` binding is what upgrades that to an attributable claim, and Buzz has it.
Who runs into this: anyone wanting agent work-receipts, or moderation/reputation
signals that stay meaningful once a third party reads them. Today the options are a
Buzz-specific kind (which no standard client renders — NOSTR.md already flags
40002/40003 that way) or kind:1984 reports, which are a private signal to moderators
and suppressed from fanout. Neither is the right shape for a public, attributable
claim.
**Proposed solution**
Register kind:1985 as an ordinary member write:
- `KIND_LABEL` in `buzz-core/src/kind.rs`, added to `ALL_KINDS`
- `required_scope_for_kind` → `Scope::MessagesWrite` — the same gate as any other
member event, deliberately *not* the moderation routing kind:1984 takes
- advertise `32` in the NIP-11 `supported_nips`
- `#h` scopes a label to a channel, per the existing channel-scoping convention
No new HTTP surface, no migration, no side-effect handler — a label stores and fans
out on the ordinary path, which is the whole point.
**Alternatives considered**
- *A Buzz-specific label kind.* Rejected: interop is the entire reason to want this,
and NOSTR.md already flags Buzz-only kinds as things no standard client renders.
- *Reuse kind:1984 reports.* Wrong semantics — a report is a private complaint to
moderators and is suppressed from fanout; a label is a public claim.
- *Label off-relay with an ordinary user key.* Works, but loses the attribution
property, which is the only part not already achievable elsewhere.
**Additional context**
Searched open issues and PRs for NIP-32 / 1985 / labeling — **none found**.
I have a branch implementing exactly the above: unit tests (including registering
1985 in `ALL_KINDS` so the existing `no_duplicate_kind_values` guard covers it), an
e2e test in `buzz-test-client`, and a NOSTR.md "What Works" row. `just ci` passes.
The e2e test was checked against stock Buzz as a control and fails there with
`restricted: unknown event kind`, so it discriminates rather than passing vacuously.
Implementation: #5127
If relay-issued labels aren't something you want in the kind registry, say so and
I'll close the PR — no hard feelings, and it costs you one comment rather than a
review.
Contributor guide
Research direction
Start with buzz-core/src/kind.rs and the existing kind-registration and scope tests, then inspect the linked implementation in PR #5127 and its buzz-test-client e2e test. Run just ci and verify the NOSTR.md "What Works" entry; done means kind:1985 is accepted, channel scoping works, and the end-to-end test passes.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- backend, networking
- Issue type
- Feature
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Stale
- Clarity
- Clearly specified
- Newbie friendliness
- 25/100