Repository navigation
feat(rooms): seat a stranger's Bots through a link Bot Social records (#884, #878) - #889
Merged
Merged
Conversation
Collaborator
Author
|
Verdict: PASS at d5fac4f Fresh pass at the PR head, read cold against origin/main d0cafd5 (21 files: room-membership.js, reach.js, channel.js, authz.js, roster.js, hooks.js, room-share.js, the two test files, two subsystem docs, the regenerated patches). Ran:
Findings, no blocking ones:
This report is a Verifier result, not merge authority on its own; the merge follows AGENTS.md step 6. |
HugoXK
pushed a commit
to HugoXK/FlyBot
that referenced
this pull request
Oct 23, 2026
… room (ThinkFlowLab#883) (ThinkFlowLab#890) Written-by: Dev Tip SHA: `ca8f82268d4c6eb05216762fd604e23f40276b0e` Fixes ThinkFlowLab#883 Refs ThinkFlowLab#852, ThinkFlowLab#884, ThinkFlowLab#878, ThinkFlowLab#876 This is the social plugin's half of the stranger link. ThinkFlowLab#889 (merged as 924b175) seats a home that is not a friend through a link Bot Social records. This PR registers that host seam with the plugin and lets the room's shares reach exactly that seat, under that room, without making the stranger a friend. ## Reproduce On `924b175` with the plugin loaded: - `rt.roomInviteServer` stays undefined, because no plugin calls `flybot.rooms.serveInvites`. Every mint falls back to the friend-only local ticket, and a stranger can never be seated. - A room share to a seated stranger's Bot is denied by the social send middleware's roster check (the handle is not a friend), or it is held for approval. - Live two-home pre-check on this box (two local FlyBot instances plus a local Bot Social at master b748167): - A fresh home's lead Bot has no Bot Social identity, so `room-invite-mint` answers `This machine has no Bot Social identity yet`. A room-only identity is not polled, so the room's lines would not arrive either. - Withdrawing a link (Bot Social answers `DELETE … 204`) killed the inviting FlyBot process: `TypeError: Response constructor: Invalid response status code 204` was thrown inside `socialFetch`'s `end` handler, where nothing catches it. - The guest's room read "Shared room from You": the host's own label for its owner leaked into `sharedFrom.inviterName`. ## What changed - **The seam** (`social.js`): `flybot.rooms.serveInvites` is registered as follows: - `identify` gives a link's own Bots a full identity with `register(bot, { forInvite: true })`, which is polled and signs its sends; - `mint` is gated on the `local_room_invites` feature in `/v1/platform`, and answers `undefined` on an older server; - `preview`, `claim` and `verify` read the minting or claiming owner's view; - `revoke`. The REST calls live in `face-rooms.js` `localInvites`. - **Exactly the seat** (`ticketPair`): - A room share whose pair `{from, to, scope}` is one of `flybot.rooms.ticketPeers()` skips the roster deny and the hold. - `sendTicketShare` sends it as `send_as_member` with `room_id: scope`, so Bot Social uses that room's reach. - Nothing else is opened: another Bot of the same home, another room, or a plain DM is still refused. - **204 is an answer** (`mcp-client.js` `socialFetch`): - A 101/204/205/304 Response is built with no body. - A Response that still throws now rejects the call, so it can no longer end the process. - **Inviter name** (`room-membership.js` `shareInviter`): a human participant named "You" (this home's own label) yields to the Bot Social owner name. - **Docs**: `docs/subsystems/social.md`. Changelog fragments `changelog.d/883-stranger-room-share.added.md` and `changelog.d/883-link-live-fixes.fixed.md`. ## Tests - `social.test.js` "ThinkFlowLab#883: …": a SEATED room's share goes to the seat as `send_as_member` with `room_id`. A non-pair is still refused. - `face-rooms.test.js` "ThinkFlowLab#884: local room invite calls": each REST shape. - `connector-scope.test.js` "a 204 answer …": a real HTTP server answers 204. Without the fix this test fails with `Invalid response status code 204`. - `room-ticket-seat.test.js`: the host's human is "You", and the guest must read "Alice". This fails without the fix. ## What I ran - `TZ=UTC npm run verify` at this tree (Node 24.21.0) → pass. The tree is identical to 0c4c7e0, checked with `git diff 0c4c7e0 ca8f822` = empty. Counts: core 1322, social 389, tree 125, timeline 125, .github scripts 332, interop 37, live-e2e 16. `ds-bot-patches check` ok. - Live pre-check, two non-friend homes on this box: - A minted a link (the lead got its identity on demand); - B previewed it ("Trip plan", Chief, Ann) and joined with one Bot; - A seated `@scoutb.ben.home` with `admittedBy: 'ticket'`, and B projected the room; - A crashed on the 204 right after. That crash is fixed here, and the full two-way run is repeated after merge. ## Risk The plugin's send path for room shares changes, but only for a pair that `ticketPeers()` lists, under its own scope. Every other send takes the same path as before. --------- Co-authored-by: Birfy <15378933+Birfy@users.noreply.github.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.
Written-by: Dev
Tip SHA:
a2ed01420cbb3aa8ad64fb45aed180364472dadeFixes #884
Fixes #878
Refs #852, #883, #876
A room that lives in one FlyBot can now seat a home that is not a friend, with the Bots it brings, through a link Bot Social records (Bot Social #60, merged as b748167). This is the host half: the ticket list, the server seam, the read-back on accept, the seat, and the room traffic to and from it. The social plugin's half (registering the seam, the connector exception for room shares to a seat) is #883 and the next PR; the UI is #876.
Reproduce
On
d0cafd5:rt.mintRoomInvite('war')twice: the first link stops answering (room.localInviteis a single field), so two people cannot each get one (One local-room ticket admits one Bot: a friend and their Bot need two links, and minting a second link kills the first #878).assertAddable(Only a Bot granted to you may join a shared room), so an accepting knock from a stranger always endsnot-addable(assertAddable refuses a remote Bot that a verified ticket admitted, so the invited stranger is seated nowhere #884).op: 'line'from a remote member addressed to a room that lives here falls throughinboundOfand projects a second, phantominbound-shareroom of the same id instead of landing in the room.What changed
room-membership.js):room.localInvites, several open at once;rt.localInvitesOf/rt.localInviteOf(newest);rt.revokeRoomInvite(roomId, ticket?)withdraws one link, or every unused one; the old single field is moved into the list on first read.rt.roomInviteServer(registered by a plugin through the newflybot.rooms.serveInvites), a mint goes to Bot Social (server: true). A failing server refuses the mint (never a silent local fallback); a server withoutlocal_room_invitesanswersundefinedand the friend-only local ticket stays.room-invite-askwithaccept: trueandbotsclaims the ticket for those Bots (all or none, the actor's own only), then the first of them knocks with{ op: 'ask', ticket, accept, roomId, bots }.room-invite-previewreads the server's public record. Server refusals map to one reason each (expired,revoked,claimed-elsewhere,own-invite,busy,lookup-failed).seatByTicket): the knock is a request only. The claim is read back with this home's own credential and seats exactly the claim's Bots, from the claiming home, for this room, or nobody:unclaimed/claimed-elsewhere/wrong-room/lookup-failed/expired/revoked/not-addable. A seat is{ admittedBy: 'ticket', ticket, hostBotId }: not published, nothing in the sidebar, named from the server's claim.notifyRoomShare/fanoutRoomLinereach a seat fromhostBotIdonly, withmeta.scope(the room id) for the transport to send under. Lines and leaves a remote seat sends to a room of this home land in it (ingestSeatShare), fan out to the other seats but not back, and call local Bots throughstartInboundTurn; alinefor a room of mine from a non-seat is dropped (not-seated).mayShareRoomthere (reach.js openedByLink). A room with an ungranted Specialist can be shared by link; without a link nothing changes.unseatTicket), removal or the guest leaving (the ticket is spent and revoked at the server once its last seat is gone), and room delete (rt.dropRoomInvites, called fromdeleteRoom).inbound-shareroom for every Bot a ticket seated (sharedFrom.ticket); eachjoinadds or revives only the Bot it names; a seated Bot's line goes from that Bot under the inviter's room id; the last one leaving gives the claim back.docs/subsystems/core-host.md.changelog.d/884-ticket-seats.added.md.What I ran
On
a2ed01420cbb3aa8ad64fb45aed180364472dade(Node 24.21.0):TZ=UTC npm run verify→ pass: core 1321/1321, plugins/social 386/386, tree 125/125, timeline 125/125, .github scripts 332/332, interop 37/37, live-e2e 16/16; build-client check, ds-bot-patches check, lint and arch-docs ok.core/test/room-ticket-seat.test.js(new, 5 tests): two homes in one process, a stand-in for Bot Social's ticket record and reach rule, and a transport that delivers only where that reach lets it through.Red without the source change
openedByLinkinmayShareRoomnot-addable)ownSeatOf→ingestSeatSharebranchunseatTicketon withdrawNot run (and why)
Risk
mayShareRoomnow passes the minting owner's Bots in a room with an open or seated Bot Social link; that also lets them share that room with a friend's Bot in it. Owner-scoped, and it ends with the link.core/client.jsunchanged; patches regenerated,0001/0003keep main's generated text.