Skip to content

Accepting an invite never shows the inviter's Bot to the joiner, and the joiner's Chief lists the inviter in People with access (regression of #178 from #334) #342

Closed

Description

@Birfy

Summary

After B accepts A's per-Bot invite, B never gets A's Bot. B's sidebar shows only B's own Chief, and the Social section stays empty, even after a reload. B's own Chief also gets a grant in People with access: SelfA2018 (@selfa2018.home) [Revoke], although B shared nothing. Both symptoms have one cause, a regression from #334: B's plugin stores the talk-through side of the friendship as B sharing its Chief, and then hides A's Chief because of that grant. This is the same flip as #178, back again.

It blocks every new invite. On main, nobody who accepts an invite gets the shared Bot.

Environment

  • FlyBot main 2c9853d09633f5aadeb4fe97a28357553c64630d (fix(social): never publish the Bot that just joined our invite, even before the grant sync #334 merged). Current main d6203fd has the same plugins/social/src/social.js.
  • dsh 0.2.0-rc.2, Node 24.
  • Fresh A on :3095 (SelfA2018, @selfa2018.home) and fresh B on :3096 (SelfB2018, @selfb2018.home), on one Linux box.
  • Bot Social prod https://47-80-69-220.sslip.io (0b7cabb).
  • Product self-test, 2026-10-18 20:24–20:30 Asia/Shanghai.
  • On the previous self-test (a003044, 16:25 Asia/Shanghai) the same steps worked: B had a remote SelfA1622's Chief chat, and B's Chief had no grants.

Steps

  1. On A, right-click Chief > Copy invite link. The toast says Invite link for Chief copied.
  2. On B, click + > Add friend, paste the link, and click Accept invite.
  3. Wait, then reload B. Search the sidebar for Self.
  4. On B, open Edit Bot (Chief) > Sharing. On A, open Edit Bot (Chief) > Sharing.

Actual

  • On B, a toast flashes and the panel closes. Per the code, the toast text is SelfA2018 shared a Bot with you.: inviterBotName is missing, so it falls back to "a Bot". The sidebar then shows only B's own Chief. Social is empty and searching Self finds nothing, also after a reload. Screenshot: B's sidebar with a single Chief row ("Hi! I'm Chief, your …"), the Chief chat with its first-question card, and nothing under it.
  • Accepting the same link again says This invite was already used. Ask your friend for a new one. Screenshot: the Add friend panel ("You are @selfb2018.home", Copy invite link, the pasted link https://47-8…, Accept invite) with that red line. So the join did happen.
  • On A, People with access shows SelfB2018 (@selfb2018.home) [Revoke]. This is correct.
  • On B, Chief > Sharing > People with access shows SelfA2018 (@selfa2018.home) [Revoke]. This is wrong: B shared nothing.
  • On A, no Bot of B's shows and there is no person row. This is correct.

Evidence (read-only, 20:27–20:35 Asia/Shanghai)

  • Bot Social (owner MCP as each home, read-only): one relationship rel_01M57FJ297A1RRCDW3V40S2MR5 (20:25:06.087 Asia/Shanghai). The server made two grants in the same transaction:
    • grt_01M57FJ29909AH3NJHJ5VFDHZC, created 12:25:06.089Z: A's owner gives B's Chief (@chief.selfb2018.home) access to A's Chief. This is the shared Bot, as invited.
    • grt_01M57FJ29AXZC31ES5W889CWBB, created 12:25:06.090Z: B's owner gives A's Chief access to B's Chief (chat.public, profile.read). This is the talk-through side, which Bot Social creates by design in Platform.activateRelationship (requesterToTarget).
    • B's list_remote_bots does list @chief.selfa2018.home under home @selfa2018.home, with grant_id grt_…29909 and via ["@chief.selfb2018.home"]. So the server side is right.
    • The invite G4ZCIPlYXa3Y for @chief.selfa2018.home has status used, uses 1/1.
  • B's local API:
    • flybot/social/remote-bots {fresh:true} returns home SelfA2018 with bots: [], via ["@chief.selfb2018.home"].
    • social/friends and social/overview friends are [].
    • social/access on B's Chief returns grt_01M57FJ29AXZC31ES5W889CWBB, grantee @selfa2018.home.
  • B's files:
    • state.json grants[B's Chief] contains { id: grt_01M57FJ29AXZC31ES5W889CWBB, grantee: "@chief.selfa2018.home", relationshipId: rel_01M57FJ297A1RRCDW3V40S2MR5 }.
    • flybot/remote is {}: B never got a remote chat record for A's Chief. It was not created and then hidden; it was never created.
    • flybot-social-settings.json has inboundBots: {}.
    • web.log has no warnings.
  • A's files: grants[A's Chief] holds grt_…29909 for grantee @chief.selfb2018.home (correct). A's remote-bots home SelfB2018 has bots: [] (correct, per default-deny).

Cause (confirmed with a unit repro at 2c9853d and at its parent f9aa5c2)

  1. Bot Social's join_invite answers { relationship_id, status, approval_id, inviter, awaiting }, where inviter is the invited Bot itself (publicBot(inviterBot), here @chief.selfa2018.home). There is no bot, inviter.bot or offered_bot. So social/join-invite (social.js L1689) gets offeredHandle = '' and does not mark the shared Bot inbound before the refresh. The Accept invite: 'Talk through' copy implies a Bot is granted back; People with access stays stale; Helper appears ~10 s after the toast #228 test hides this, because its mock returns a bot field that the real server never sends, with a home-level inviter.
  2. Before fix(social): never publish the Bot that just joined our invite, even before the grant sync #334, this did not matter. remoteBots() published the roster before the grant sync, so the shared Bot was in added and got rememberInbound'd (L1700–1701). The later grant sync then saw the talk-through grant as talk-through (isTalkThroughGrant needs inboundBots[grantee]).
  3. With fix(social): never publish the Bot that just joined our invite, even before the grant sync #334 (L861–868), a new Bot that is not in inboundBots waits for syncOutgoingGrants({ roster }) before filtering. With inboundBots empty, isTalkThroughGrant is false, so the talk-through grant grt_…29AX is stored as a core grant on B's Chief (L1080). Then keepGrantedRemote (L771, "outgoing grants win") drops A's Chief, added is empty, and rememberInbound never runs. Nothing heals this later.
  4. Unit repro: the Accept invite: 'Talk through' copy implies a Bot is granted back; People with access stays stale; Helper appears ~10 s after the toast #228 test with the real server's response shape (no bot, inviter = { handle: '@chief.bob.home', … }). After an empty roster was fetched once:

Hunch, not tested: an existing friendship cannot recover either. A new invite from A hits relationship_exists, which only unhides, and inboundBots is still empty. Clicking Revoke on B's bogus row would revoke the server's talk-through grant grt_…29AX, which A's Chief needs to reach B's Chief.

Expected (design)

  • Per-Bot grants. Joining an invite never grants the joiner's Bots back, and nothing is published.
  • On B, A's Chief appears in the main list right away, with its own avatar and the small friend's-Bot marker. The result says SelfA2018 shared Chief with you.
  • B's Chief People with access stays empty. The talk-through grant is never shown or stored as sharing.
  • A still shows nothing of B's, and no person row (a friend with nothing shared stays hidden).
  • Accepting an invite briefly publishes the joiner's (unshared) Bot on the inviter's home: dead 'no longer shared with you' chat opens on load; friend invisible in Social #303 stays fixed: A never gets a chat for B's Chief.
  • Tests use Bot Social's real join_invite response shape. The fix should treat a member-level joined.inviter.handle as the offered Bot, or classify the talk-through grant from the relationship and via instead of inboundBots. Cover both homes of one invite, from an empty roster and from a non-empty one.

Related

#178 (same symptom, fixed before), #228, #303 / #334 (the change that brought it back), #161, #336.

Activity

  1. added 2 commits that reference this issue on Oct 18, 2026
    8318269
    1171376
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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