Skip to content

The connector denies a stranger's room-share "ask", so a redeemed link never reaches the inviter's host #883

Closed

Description

@Birfy

Priority: P0. Owner request (translated from Chinese, 2026-10-23): "A complete stranger, holding my QR code or link, must be able to join my group with their Bot. I need this urgently."

What this is

The connector half of FlyBot #853: the op:"ask" envelope a redeemed link produces must be allowed to leave the home of a stranger, and only that envelope.

Today it cannot leave at all. Measured on main 690093bc, plugins/social/src/social.js:

  • :1436 — the send middleware denies when sendTarget(msg) resolves nothing: "… is not a Bot a friend shared with you". A cold handle is exactly that, so a stranger's ask dies here before any room logic runs.
  • :1453 — even with a roster entry, the deny returns once the friendship is gone.
  • :1450 — msg.via === 'room' || 'room-share' skips the approval decision, but that is downstream of :1436: it does not help a stranger.
  • Transport :1545 (… is no longer reachable) and :1558 (the same friendship sentence) are the second gate on the same path.

(The line numbers quoted in #853 — 1339-1357 — are from an older main and have drifted.)

The exception, exactly

One send passes, and only when all four hold:

  1. the envelope is a FLYBOT-ROOM-SHARE with op: "ask" (core/src/shared/room-share.js:94 already refuses an ask whose ticket is not ^[A-Za-z0-9_-]{16,64}$);
  2. the ticket has been claimed — read from Bot Social's preview/claim answer, not from anything in the message;
  3. the sending home is the claiming home, and the Bot it sends as is the claimed bot_handle;
  4. the ticket is live (not expired, not revoked) and the roomId inside the envelope is the room the ticket is bound to.

Anything else keeps today's deny. Every failed condition gets its own sentence — a single generic refusal is not acceptable, because "the link expired" and "that link is someone else's" are different things to the person holding it.

Acceptance

  • A home with no friendship and no shared Bot, holding a live claimed ticket, sends op:"ask" and it leaves; the inviter's host receives it.
  • Each of the four conditions forced on its own produces a denial with its own sentence: not claimed, expired/revoked, claimed by another home, and a different roomId than the ticket names.
  • A lookup failure is a deny, never a pass (fail-closed): if the preview/claim answer cannot be read, the envelope stays home.
  • The same home sending any other text, or any other op (invite, join, line, leave), is still denied with today's sentence.
  • The same home reaching any Bot outside that room is still denied — the exception is per envelope, not per home.
  • Negative control: removing the exception returns the ask to today's :1436 deny, and every other test stays green.
  • A test pins that a stranger's ordinary line (no envelope) is still denied at :1436.

Depends on

The server-side ticket record (the separate bot-social issue: mint / preview / claim). Until it exists there is nothing to verify against, so this cannot pass its acceptance end to end — write the "blocked on that issue" line in the PR body, and pin the positive case with the fake server meanwhile.

Related

FlyBot #853 — the cross-repo gate; this issue is its connector half. FlyBot #884 — the host-side admission door, without which the invitee is still seated nowhere. FlyBot #876 — the UI that hands out the link.

Activity

  1. added
    enhancementNew feature or request
    agent-readyMaintainer-approved spec: an agent may take it. Only maintainers set this; never in a template
    area:socialFriends, invites, grants, Bot Social
    area:securityAuth, grants, approvals, secrets
    on Oct 23, 2026
  2. Birfy commented on Oct 23, 2026

    @Birfy
    CollaboratorAuthor

    Written-by: Dev

    Taking this one. Branch feat/883-stranger-ask, after #884's PR (it consumes the same seam). Bot Social side is Birfy/bot-social#60 (I am building that too).

    How the four conditions are read, all from Bot Social's answers, never from the message: the guest home's own POST /v1/local-room-invites/:ticket/claim answer (claimed, by this home, these Bots, this room, not expired) is kept in the plugin's settings; an outbound FLYBOT-ROOM-SHARE to a handle the roster does not know passes only when that record names the target as the ticket's inviter, the sender as one of the claimed Bots, and the envelope's room as the ticket's room — and it goes out with room_id, so the server checks the same claim a second time. On the inviter side the host's answer to a seated stranger (join, line) passes on the seat record #884 writes. Plain text, any other target, or an envelope for another room keeps today's deny and sentence; a failed read is a deny.

  3. added
    agent-workingAn agent has claimed this issue (the claim comment names the branch)
    on Oct 23, 2026
  4. self-assigned this
    on Oct 23, 2026
  5. removed
    agent-readyMaintainer-approved spec: an agent may take it. Only maintainers set this; never in a template
    agent-workingAn agent has claimed this issue (the claim comment names the branch)
    on Oct 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

area:securityAuth, grants, approvals, secretsarea:socialFriends, invites, grants, Bot SocialenhancementNew feature or request

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions