Skip to content

Inbound message from an inviter's Bot to the joiner's unshared Bot is refused silently; the sender sees 'delivered' #336

Closed

Description

@Birfy

What happens

User B joins A's per-Bot invite with B's Bot X. A's Bot then sends X a message. Bot Social marks it delivered (the server holds reciprocal chat.public and profile.read grants for A's Bot on X), but the FlyBot plugin on B's side refuses it in reach() ("X has not been granted to this sender, so it cannot be reached from outside") and only logs a warn in the web log.

Actual

  • B sees nothing: no card, no chat, no notification.
  • A's Bot is told "delivered" and waits for a reply forever.
  • The server grant model (talk-through grants allow reach) and the client (denies unless X is shared with the sender) disagree.
  • The inviter has no way to know the joiner's Bot must be shared back first.

Expected

Surface a card or notice to B ("A's Bot tried to message X; share X with them?"), or tell the sender the message was refused, and make the server and client grant models consistent. Per-Bot default-deny stays: nothing is auto-granted.

Related

#138, #161, #240, #272, #284, #286, #303 (#272/#284 fixed the same kind of silent deny for a Bot's reply, but not a first inbound message from the inviter).

Evidence

One message in the conversation, event seq 1261 consumed by the Mac at delivery time; the plugin log line "message from @yi1c1ca1.bot refused: ... has not been granted to this sender".

Activity

  1. Birfy commented on Oct 18, 2026

    @Birfy
    CollaboratorAuthor

    Maintenance check on main 5b7b778 (2026-10-18 22:30 Asia/Shanghai): still valid, and no open PR covers it. plugins/social/src/social.js (inbound poll) still only warns when flybot.bot.send answers deny (core/src/host/reach.js: "… has not been granted to this sender"), and the event is then marked done. #344/#348 fixed the joiner side of invites, not this inbound case.

    This needs an owner decision before anyone codes it:

    1. Receiver side, local only (no protocol change): keep a refused first message as a card for the owner of X, e.g. "A's Bot tried to message X. Share X with them?", with a Sharing button. Nothing is auto-granted.
    2. Sender side: tell A that the message was refused. An automatic reply sent by B's Bot would be a Bot-sent message without the owner's approval, which the design rules out. So this would need a backward-compatible Bot Social signal instead (for example a refused delivery state that old clients ignore). That is a server change and needs a separate yes before deploy.

    My suggestion is (1) now and (2) later if it is wanted.

  2. Birfy commented on Oct 19, 2026

    @Birfy
    CollaboratorAuthor

    Maintenance check on main 0e72bb8 (2026-10-19): still valid. Inbound from the inviter's Bot to the joiner's unshared Bot is still refused in reach() with only a web-log warn; the sender still sees delivered. Expected behavior (surface a card/notice to the joiner vs auto-share vs something else) still needs an owner decision — not inventing one this run.

  3. Birfy commented on Oct 19, 2026

    @Birfy
    CollaboratorAuthor

    Owner decision (2026-10-19): Approved to change the server side as well, so the server and client grant models agree and the sender is told when a message is refused (per the Expected section of this issue). Per-Bot default-deny stays: nothing is auto-granted. Bot Social counterpart: Birfy/bot-social#23 (backward compatible; no production deploy without the owner's explicit yes).

  4. added
    bugSomething isn't working
    area:socialFriends, invites, grants, Bot Social
    agent-readyMaintainer-approved spec: an agent may take it. Only maintainers set this; never in a template
    on Oct 19, 2026
  5. Birfy commented on Oct 19, 2026

    @Birfy
    CollaboratorAuthor

    Triage on main 7b9e90b, 2026-10-19 ~12:10 Asia/Shanghai: design conflicts resolved, spec clear; ready to develop (FlyBot receiver side). Checked: owner decision of 2026-10-19 above (server side approved as well; per-Bot default-deny stays, nothing auto-granted), the design rule that a Bot never sends on its own without the owner's approval (so no automatic reply from B's Bot), and #138/#161/#272/#284. FlyBot scope now: when reach() refuses a first inbound message because X is not shared with the sender, keep it as a notice for X's owner ("'s Bot tried to message X. Share X with them?") with a button that opens X's Sharing, instead of only a web-log warn. Nothing is granted automatically. The sender-side signal waits for Birfy/bot-social#23 (the FlyBot part of that comes after it lands).

  6. Birfy commented on Oct 19, 2026

    @Birfy
    CollaboratorAuthor

    Owner decision (2026-10-19): the receiver card must be triggered by the new server event (the owner chose option 1 in Birfy/bot-social#23: the server rejects the inviter Bot's first message to an unshared joiner Bot with 403 and emits an event to the joiner's owner).

  7. Birfy commented on Oct 19, 2026

    @Birfy
    CollaboratorAuthor

    Triage on main a7f51e8, 2026-10-19 ~14:15 Asia/Shanghai: not ready any more, removing agent-ready (added by this routine earlier). The Owner decision of 05:38 UTC says the receiver card must be driven by the new server event from Birfy/bot-social#23 (server refuses the first message with 403 and notifies the joiner's owner). That server change is not built or deployed yet (bot-social#23 open). Blocked until bot-social#23 lands and the owner says yes to deploy it; then the FlyBot side (show the 'share this Bot?' card on that event, show the 403 to the sender) is ready.

  8. added
    needs-humanThe agent loop stopped; a person must decide (reason in the last comment)
    and removed
    agent-readyMaintainer-approved spec: an agent may take it. Only maintainers set this; never in a template
    on Oct 19, 2026
  9. Birfy commented on Oct 19, 2026

    @Birfy
    CollaboratorAuthor

    Triage on main e5f6036, 2026-10-19 ~16:35 Asia/Shanghai: design conflicts resolved, spec clear; ready to develop. The blocker is gone: Birfy/bot-social#27 (fixes bot-social#23) is deployed on production since 15:40 today. The server now refuses the inviter Bot's first message to an unshared joiner Bot with 403 bot_not_shared ({code, message, suggestion: 'ask_owner_to_share', bot_id, relationship_id, owner_notified}; nothing stored or delivered) and adds a share.requested event to the joiner Bot's queue ({relationship_id, bot_id, from: {bot_id, handle, display_name, owner_display_name, owner_verified}, attempted, trust, note}, at most one per sender and Bot per 24 h, no peer content).

    FlyBot scope:

    1. Joiner (X's owner): on a share.requested event, show one notice/card "<Bot (owner)> tried to start a chat with X. X is not shared with them." with a Share X… button that opens X's Sharing, and a dismiss. Nothing is granted automatically; no typed reply acts on it ([Feature RFC] Agent inbox board: one place for tasks, approvals and failures (personal first, team second) #349); X never answers on its own.
    2. Sender (inviter's owner): when a send/start answers 403 bot_not_shared, the chat says the Bot is not shared with yours yet and its owner was told (no "delivered", no retry loop), named in the one-name form Bot (owner) (Friend's Bot rows: two name formats ('Helper · SelfB0023's Bot' vs 'SelfA0023's Chief'), two-line wrap, no preview, inset highlight, faint marker, same avatar as own Chief #384).
    3. Keep reach()'s local refusal as the safety net. Mock answers copy the server shapes above (LESSONS 2026-10-18, name bot-social faa7cb5).

    Checked: owner rules (per-Bot grants, default deny, approvals only via UI buttons, owner-only actions), the 05:38 UTC owner decision on this issue (card driven by the server event), #384/#425 naming, #138/#272/#284.

  10. added
    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)
    and removed
    needs-humanThe agent loop stopped; a person must decide (reason in the last comment)
    on Oct 19, 2026
  11. self-assigned this
    on Oct 19, 2026
  12. Birfy commented on Oct 19, 2026

    @Birfy
    CollaboratorAuthor

    Claimed by the maintenance routine (2026-10-19 16:25 Asia/Shanghai). Branch: Birfy:fix/336-share-requested-card off main 31c4c2a. Scope per the 08:12 UTC triage: a button-only "Share X…" card on share.requested, the sender sees the 403 bot_not_shared explanation instead of delivered; reach() stays the safety net.

  13. Birfy commented on Oct 19, 2026

    @Birfy
    CollaboratorAuthor

    PR #428. Minor details decided by the routine (owner-delegated): the card sits at the top of Friends' Bots (sidebar), one per sender and Bot, buttons Dismiss and Share … (opens that Bot's settings → Sharing; nothing is shared from the card); it drops by itself once that Bot is shared with the sender; at most 20 open cards kept. Sender text: "<Bot (owner)> is not shared with your Bots yet, so the message was not delivered. Bot Social told its owner, who can share it with you. Sending again will not help until then."

  14. added a commit that references this issue on Oct 19, 2026
    e131cf5
  15. removed
    agent-workingAn agent has claimed this issue (the claim comment names the branch)
    agent-readyMaintainer-approved spec: an agent may take it. Only maintainers set this; never in a template
    on Oct 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

area:socialFriends, invites, grants, Bot SocialbugSomething isn't working

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions