fix(cli): dms list must query the relay-emitted kind:39000, not kind:41001 - #9
Open
lodar wants to merge 1 commit into
Open
fix(cli): dms list must query the relay-emitted kind:39000, not kind:41001#9lodar wants to merge 1 commit into
dms list must query the relay-emitted kind:39000, not kind:41001#9lodar wants to merge 1 commit into
Conversation
…d:41001
`dms list` queried `{kinds:[41001], "#p":[me]}`. `KIND_DM_CREATED` (41001) is
declared in buzz-core but no code path in this repo ever emits it, so the verb
returned `[]` for every account on every relay while `channels list`, `channels
members` and `messages get` all saw the same conversation. An empty list rather
than an error is why this reads as "no DMs exist" instead of "my predicate
matched nothing".
The relay-emitted truth is kind:39000 NIP-29 group metadata, which
`emit_group_discovery_events` tags with `t=<channel_type>` plus one `p` tag per
participant for DMs. kind:39000 is absent from `required_scope_for_kind`'s
allowlist, so client ingest rejects it as "restricted: unknown event kind" —
only the relay can author one. `t=dm` is therefore relay-attested channel_type
rather than a client-supplied name/membership heuristic, which matters because
consumers skip the @-mention test on the DM path.
- `dm_list_filter()`: extracted so a regression to a kind nothing emits is a red
test, not a silent empty list.
- `parse_query_events()`: a relay error object is an error, not an empty inbox.
The old `unwrap_or_default()` made a dead relay indistinguishable from no DMs.
- `dms_from_group_metadata()`: keeps only `t=dm` with a non-empty `d` tag that
lists us; a valueless `["t"]` tag no longer masks a later `["t","dm"]`; newest
revision per channel wins; sorted newest first.
- Annotated `KIND_DM_CREATED` as reserved-and-unemitted.
Adds an end-to-end interop arm in buzz-test-client that pins the wire kind, so
the relay and the CLI cannot drift apart again.
Signed-off-by: lodar <markounik@gmail.com>
lodar
force-pushed
the
upstream-pr/dms-list-kind-39000
branch
from
August 26, 2026 03:05
14fc3c1 to
7c9f6ed
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The bug
buzz dms listqueries{kinds:[41001], "#p":[me]}.KIND_DM_CREATED(41001) is declared inbuzz-corebut no code path in this repo ever emits it, so the verb returns[]for everyaccount on every relay — while
channels list,channels membersandmessages getall see thesame conversation. Because it returns an empty list rather than an error, it reads as "no DMs
exist" instead of "my predicate matched nothing".
The fix
Query the kind the relay actually emits: kind:39000 NIP-29 group metadata.
emit_group_discovery_eventstags it witht=<channel_type>plus oneptag per participant forDMs.
kind:39000 is absent from
required_scope_for_kind's allowlist, so client ingest rejects it asrestricted: unknown event kind— only the relay can author one.t=dmis thereforerelay-attested channel_type rather than a client-supplied name/membership heuristic, which matters
because consumers skip the @-mention test on the DM path.
Changes:
dm_list_filter()— extracted, so a regression to a kind nothing emits is a red test rather thana silent empty list.
parse_query_events()— a relay error object is now an error, not an empty inbox. The oldunwrap_or_default()made a dead relay indistinguishable from "no DMs".dms_from_group_metadata()— keeps onlyt=dmwith a non-emptydtag that lists us; a valueless["t"]tag no longer masks a later["t","dm"]; newest revision per channel wins; sorted newestfirst.
KIND_DM_CREATEDannotated as reserved-and-unemitted.Testing
9 new
buzz-cliunit tests plus an end-to-end arm inbuzz-test-client(
e2e_nostr_interop.rs) that pins the wire kind against a live relay, so the relay and the CLIcannot drift apart again.
Graded on the original tree at 358/0
buzz-cli(9 new), 249/0buzz-core, clippy clean, fmt clean;9 mutants all killed (accept any channel_type; drop the participant re-check; accept an empty uuid;
degrade a relay error to
[]; keep the oldest revision; query the old kind; …).