Skip to content

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

Description

@imikerussell

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:

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions