Add live roster / presence to A2ABus (announce + roster)#40
Merged
Conversation
Who is on a channel right now, gated by the same scopes as the messages: - announce(principal, channel) heartbeats a live seat; roster(channel, within=) lists subjects seen in the window, sorted. announce needs the channel's post scope (asserting presence is a write, so a read-only principal can't claim a seat); roster needs the read scope; denial stays opaque (who-is-here doesn't leak channel existence). - Presence is soft state: a subject that stops heartbeating ages off, and a roster seat is never a grant, so it can't smuggle access past the gate. An orchestrator can dispatch only to workers that are up and notice a dark one. - Backed by a per-channel presence table on the existing bus connection. 301 tests (+9), mypy --strict, ruff, catalog freshness all green. v1.7.0. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Live roster / presence (
A2ABus.announce/A2ABus.roster)Who is on a channel right now. The bus already answers "who may post/read here"; this adds "who is here", gated the same way:
announce(principal, channel)heartbeats a live seat and returns the timestamp — call it on a timer to stay live.roster(principal, channel, within=30.0)returns the subjects seen within the window, sorted.It reuses the auth core, it doesn't bolt on a side channel:
announceneeds the channel's post scope — asserting presence is a write, so a read-only watcher can't claim a seat it couldn't post from.rosterneeds the read scope, and denial stays opaque (an unknown channel and a declared-but-unauthorized one fail identically — who-is-here leaks channel existence no more than the messages do).That lets an orchestrator dispatch only to workers that are actually up, and notice when one goes dark — without a second identity system.
Backed by a per-channel
a2a_presencetable on the bus's existing connection.Verification
tests/test_presence.py— 9 tests: on-roster after announce, sorted+deduped, announce needs post scope, roster needs read scope, opaque denial, stale ages off, re-announce refreshes the heartbeat, per-channel isolation, decisions audited.mypy --strict,ruff, catalog freshness all green.Additive. Advances the "A2A depth: presence/live-roster" roadmap item.