block / block/buzz

feat(relay): per-channel write policy for announcement / read-only channels

Open
#2,497 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. We want an `#announcements`
channel that every member can read and react to, but where only the
channel owner and admins can post. This is the standard announcements
or broadcast pattern from Slack and Discord: one low-noise, high-signal
feed that members trust precisely because replies do not dilute it.

Today the only ways to keep such a channel clean are social convention,
or a moderation agent that deletes non-owner posts after the fact. The
latter is reactive and visibly flashes the post before removing it.

## Current gap

Per-channel access is membership-binary: if a principal is a member of a
channel they can both read and write it, so there is no concept of a
member who can only read. `channel_members.member_role`
(Owner / Admin / Member / Guest / Bot) exists but is not consulted in the
message-write path. PR #896 states this directly: `guest` was rejected
because "message writes are membership-binary today and guest would
silently fall through to write behavior." Issue #2475 confirms the same
invariant.

So there is currently no way to express "everyone may read, only Owner
or Admin may post" for a channel whose members are ordinary relay members.

## Relation to existing work

This is the complementary axis to the current public-access cluster, not
a duplicate of it:

- #920 (public-readable channel reads) and #2475 (channel-scoped guest
read/write) expand access outward to non-members and the public.
- This request restricts write access inward, by role, within a single
channel.

Both ride the same enforcement seams, so the mechanism should feel familiar.

## Requested model

A per-channel write policy, for example a channel setting
`post_policy: everyone | admins` (default `everyone`, behaviour unchanged).
When a channel is set to `admins`:

- Message-write EVENTs bearing that channel's `#h` are accepted only from
principals whose channel role is Owner or Admin.
- All members keep read, search, live subscription and reactions for the
channel.
- Non-admin writes fail closed with a clear relay message.
- Every other channel, and open relays, are unaffected.

Suggested mechanism, reusing the seams PR #896 already proved out: gate the
message-write scope for that channel's `#h` on channel role at ingest
(`required_scope_for_kind` and the `*:write` scope check in `ingest.rs`),
rather than introducing a new membership model. #896 showed read-only can
be expressed as scopes fixed at auth time; this applies the same idea
per-channel, per-role, for writes.

## Design question

Would upstream accept a per-channel write policy (an announcement or
read-only channel) that gates message-write on channel role, reusing the
scope-based enforcement from #896 and per-channel policy storage along the
lines of #920? Happy to align the config surface (channel setting vs relay
config vs a signed channel-policy event) with whatever fits the roadmap.

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.