block / block/buzz

feat(relay): channel-scoped guest read/write access for public support

Open
#2,475 2 comments 0 reactions 0 assignees View on GitHub
Dominant language
Rust
Stars
32.7k
Forks
4.3k
Avg merge
1d 13h
Merged PRs (30d)
253

Description

## Use case

We run a membership-gated Buzz community containing internal channels and agents. We want to put a **Get support** link on our public website that lets any external user open Buzz and ask for help in one configured `#support` channel. Our existing members and agents should see and answer those messages in the same community and data plane.

The external user must not become a normal relay member and must not be able to read or write any other channel, create channels, use repositories or workflows, administer membership, or publish/query unrelated global state. A separate support community can share physical infrastructure, but it splits the logical data and agent sessions, which is the part we are trying to avoid.

## Current gap

`BUZZ_REQUIRE_RELAY_MEMBERSHIP` is process-wide. When enabled, a non-member is rejected before channel authorization; when disabled, any successfully authenticated Nostr identity receives ordinary open-relay access. Channel `visibility=open` controls channel membership after relay admission, so it cannot express “this non-member may use exactly one channel.” Existing relay invites also turn the claimant into an ordinary relay member.

The current public-access proposals are deliberately read-only:

- #920 adds an explicit public-readable channel allowlist, but grants no write, membership, upload, presence, or admin capability.
- #896 demonstrated read-only scopes plus `AuthContext.channel_ids`, then was superseded by #920’s direct public-read policy.
- #274 proposed a public read-only WebSocket endpoint for website feeds and embeds.

## Requested authorization model

Writes should remain authenticated: the guest proves control of a Nostr key through NIP-42/NIP-98, but does not acquire general relay membership. A guest session would receive only the minimum scopes needed to read and post messages, with `channel_ids` restricted to an explicit per-community support-channel allowlist.

The security contract should be:

- Accept channel-scoped `REQ`, `COUNT`, and message `EVENT` operations only when exactly one `#h` UUID is present and allowlisted.
- Deny global/unscoped reads and writes, other channel UUIDs, channel creation or mutation, membership/admin commands, DMs, repositories, workflows, jobs, and other privileged surfaces.
- Resolve configured channels against live, non-deleted channel records and fail closed on malformed configuration or database errors.
- Preserve existing behavior for ordinary relay members and channel members.
- Apply the existing ban, moderation, replay, and rate-limit controls to guests.
- Keep an initial version text-only if media uploads cannot yet be safely bound to channel provenance.
- Allow agents that are explicit members of `#support` to receive and answer guest posts through the normal channel path.

The website/client flow should have a stable URL or deep link carrying the relay and target channel: open or install Buzz, establish the guest identity, open `#support`, and post. It should not grant broader relay membership as a side effect.

## Design question

Would upstream accept a channel-scoped guest-writer capability that combines #920’s explicit public-channel policy with the scoped `AuthContext` pattern from #896? The exact grant surface could be operator configuration, a signed channel-bound invite, or another mechanism; the invariant we need is authenticated read/write access to one channel and no authority elsewhere.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.