mirror of
https://github.com/block/buzz.git
synced 2026-10-29 13:31:44 +00:00
Join every new community member into the channels a relay owner or admin flagged with `channels.auto_join` (R1, d65bf983a), at the moment they become a member. This is the behaviour half (R2) of default channels: clients see the flagged channels in their sidebar, unread state and push with no client work, because the relay runs the kind:9021 body for them. - `join_channel_as_self` is kind:9021's body extracted from `handle_join_request` and returns `Joined | AlreadyMember`: open and unarchived checks, skip-if-member, then `put_member(.., None, None)` so the channel's `join_role` applies, cache invalidation, the `member_joined` kind:40099, 39000/39002 and the kind:44100. The handler keeps its exact external behaviour; the archived guard is new in the shared body because only the 9021 validator held it before. - `auto_join_default_channels` iterates `Db::list_auto_join_channels` (effective channels only) and calls the body per channel, best effort: a failure is logged and counted (`buzz_auto_join_failures_total`), a join counted (`buzz_auto_join_channels_total`), and the caller never fails, because the relay membership has already committed. No retry after that commit: re-running at any later point would resurrect kind:9022 leaves, and the kind:39000 `auto_join` tag is the record a client reconciles against. This is an accepted Review-Proven Rule 1 deviation, documented in NOSTR.md. - Called inline right after `publish_nip43_member_added` at the three user-facing join sites: the v2 invite claim `Joined` arm, the v1 claim `was_inserted` branch, and kind:9030 when the roster row was inserted. Never at login or reconnect. Inline means the kind:39002 roster already lists the member when the claim response returns. - `buzz-admin add-member` is unchanged except for help text noting it writes the roster row only; it has no `AppState` to sign 39002/44100. Tests: `claim_auto_joins_default_channels_once` (Postgres lane) covers a v2 claim against a flagged, an archived-after-flagging, a private-after-flagging and an unflagged channel: membership and 39002 in the flagged one only, one 44100 and one `member_joined` 40099, then a kind:9022 leave and re-claim that stays `already_member` without re-adding; the v1 token path; and the shared body's archived refusal directly. `adding_a_member_auto_joins_default_channels` is the first Postgres test for kind:9030 add, with the same leave-then-repeat step. Deleting the call at any of the three sites fails the matching test (verified by mutation). `test_invite_claim_auto_joins_default_channel` is the e2e smoke, run against a local relay: the claimer receives the kind:44100 and is on the kind:39002 roster. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Signed-off-by: Matt Toohey <contact@matttoohey.com>