Skip to content

Add SWIP-87: BPS explicit multi-publisher — roster and end of stream over BPS-lite - #114

Open
zelig wants to merge 9 commits into
swip-bps-litefrom
swip-87-bps-multipublisher
Open

zelig wants to merge 9 commits into
swip-bps-litefrom
swip-87-bps-multipublisher

Conversation

@zelig

@zelig zelig commented Oct 13, 2026 •

Copy link
Copy Markdown
Member

SWIP-87: BPS explicit multi-publisher — the admin's roster and end of stream over BPS-lite.

Stacked on SWIP-74 BPS-lite (#111): this PR's base is swip-bps-lite, so the diff is SWIPs/swip-87.md alone.

The admin of a BPS-lite channel names who else may publish by publishing a roster on a feed of its own, and can end the channel with an EOS. It is the roster slice of SWIP-60 (#104), with nothing else of it: two more Kind values (EOS = 3, ROSTER = 4) and one payload message (Roster). No new frame, and no change to Join, Ack or the cohort spec. A cohort is multi-publisher iff its admin ever publishes a roster.

What the SWIP specifies:

  • the roster and EOS feeds: owned by the admin alone, verified end to end, full state rather than deltas;
  • pending streams for rostered addresses, with the roster as the grantee's cue;
  • roles that change only by rejoining;
  • a cursor per publisher and per service kind;
  • publisher streams that receive what the others publish;
  • revocation by roster: the revoked streams are written the roster and closed, and what they send meanwhile is dropped, never punished;
  • the EOS as the one signed, final end;
  • bounds, outcomes, replay rows, the WebSocket bridge, and conformance.

Three rules are to be carried back to SWIP-60: roles change only by rejoining; revocation closes the revoked streams with no grace period and no punishment; and the cursor table is bounded by the roster.

Implementation: ethersphere/bee#5661 (draft, stacked on bee #5626).

Open points are marked (?) in the text.

🤖 Generated with Claude Code

zelig and others added 4 commits October 12, 2026 06:43
…m over BPS-lite

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…cue roster is not sent twice

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…stream and drops its frames unpunished

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…he owner's alone, kind and owner on every delivery

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Copilot AI balanced review requested due to automatic review settings October 13, 2026 08:05

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

It introduces a large, intricate protocol specification with multiple deliberate open design points and cross-SWIP dependencies that warrant final human editorial and technical review.

0 open findings

What changed in this PR

This PR adds SWIP-87, the second step of the Broadcast Pub/Sub (BPS) family, specified as a strict extension of SWIP-74 (BPS-lite). It gives a BPS-lite channel's admin a signed control plane: a roster feed naming additional publishers and an end-of-stream (EOS) feed to close the channel attributably. It is the "roster slice" of SWIP-60, lifted out so it can be implemented and conformance-tested independently. The change is purely a new specification document — no code.

Changes:

  • Adds two Kind values (EOS = 3, ROSTER = 4) and one payload message (Roster) on the existing Broadcast frame, with no change to Join, Ack, or CohortSpec.
  • Defines broker/subscriber rules: pending streams for rostered addresses, per-publisher and per-service-kind cursors, delivery to publisher streams, roster-based revocation (no grace period, dropped-not-punished), and channel end via signed EOS.
  • States three rules to be carried back to SWIP-60 (roles change only by rejoining; revocation closes streams without punishment; cursor table bounded by the roster).
File Description
SWIPs/​swip-87.md New Draft Standards Track SWIP specifying the admin roster and EOS control plane over BPS-lite, including wire format, validation, revocation, bounds, outcomes, WebSocket bridge, and conformance.

🧠 Review effort: Balanced


💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

zelig and others added 5 commits October 16, 2026 08:01
… an EOS ends the cohort, the admin republishes its roster

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… deadline is 5 s

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…back, no lite-only subscribers in a granting cohort

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ocket

Follows SWIP-74 rev 11. A stream with no owner is a spectator no roster can name, which
only listens. In the informative API section the bridge is one socket,
/bps/feeds/subscribe/{principal}/{topic}, with the binding in the path because BPS sits
over the subscriptions; a grant is the text frame granted; only the principal has a
bridge auth deadline, with a close code of its own; a roster naming the principal, or an
address twice, is refused at the socket. The errors are in SWIP-74's tables.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@zelig

zelig commented Nov 5, 2026

Copy link
Copy Markdown
Member Author

Rev 3.2 — follows SWIP-74 rev 11. Revisions 1 to 3.1 are in the header comment of swip-87.md.

Normative:

  • identity is now owner, as in SWIP-74: the owner of a stream's frames, the wallet address signing its feed update SOCs.
  • A stream may declare no owner. It is a spectator within the fan-out bound that no roster can name, so it only listens and can never upgrade, even if the key behind it is on the roster; an AUTH on it is a violation (wrong_stream). To publish, a peer joins with its owner declared.

Informative, the API section:

  • One socket, GET /bps/feeds/subscribe/{principal}/{topic}?broker&owner&cursor&roster&rosterCursor, replaces the publish and subscribe pair. On the wire the declared owner settles what a stream is, and the API now does the same.
  • The binding is in the path, because BPS sits over the SOC subscriptions rather than beside them: mic, moc or gsoc would take the same shape with their own parameters. Only feeds publishes directly, with binary frames on the socket.
  • {principal}, not {owner}: a seat signs its own updates on its own feed, so the path says whose channel the stream joins, and owner who is speaking.
  • The grant is the text frame granted, no JSON. It is needed beside the roster because a seat that passes back its position is not given the broker's re-sent roster.
  • Only the principal has a bridge auth deadline, with a close code of its own, 4005. A seat may just listen.
  • A roster naming the principal, or an address twice, is refused at the socket (4002). A receiver still takes one, and it changes nothing.
  • The challenge message has no type field, and a stream with no owner is not sent one.
  • Errors are in SWIP-74's tables; this SWIP adds 4004 and widens 4002 and 4003.

SWIP-74 rev 11 is merged into this branch, so the diff against the base stays swip-87.md alone. ethersphere/bee#5626 at bfba414e implements this revision.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants