Skip to content

Restore both directions when a re-invite is accepted (#1000) - #1023

Merged
Birfy merged 1 commit into
mainfrom
dev2/fix/1000-both-directions
Oct 24, 2026
Merged

Birfy merged 1 commit into
mainfrom
dev2/fix/1000-both-directions

Conversation

@Birfy

@Birfy Birfy commented Oct 24, 2026

Copy link
Copy Markdown
Collaborator

Owner: Dev2
Reviewer: Reviewer
Fixes #1000
Tip SHA: 6617e0a
Base: 7225692

Accepting a re-invite now restores both directions: the joining home grants its Bot back, so the pair is two-way again instead of the inviter's first line landing as an unknown-recipient hold.

Reproduce

SelfTest checklist 2b on d2578496: A and B friends both ways, A removes B's Chief, A invites B's Chief again, B accepts. A sees B again; B's list lacks A, and a line to A is held as an unknown recipient until B shares again — the acceptance restored only the direction the invite sent. The plugin's seam: social/join-invite → alreadyHave on 409 relationship_exists (social.js:2336) and the regranted: true join (social.js:2466) both return without creating the grant an accepted invite makes on the joining side, so grant_bot_to_friend is never called for that pair.

What changed

What I ran

At 6617e0a6 (TZ=UTC, TMPDIR on the data disk):

cd plugins/social && node --import ./test/resolve.mjs --test --test-concurrency=1 "test/*.test.js"
  # tests 440 / pass 440 / fail 0 / skipped 0
DSH_HARNESS=… node scripts/lint-plugins.mjs   # 0 errors; 2 warnings, both pre-existing (plugins/tree/test/mock-flybot.js)
node .github/scripts/changelog.mjs check      # 1 fragment, well formed

core/ is untouched, so no bundle or patches/ds-bot regeneration is involved.

Red without the source change

Pristine 7225692e with only this PR's test file (source and docs reverted): # tests 440 / pass 436 / fail 4 — the two #1000 cases (expected: true, i.e. no grant_bot_to_friend call and no sharedBack), plus the two copy tables that now carry a sharedBack row (#496 neutral line, #343/#499 accept line). Nothing else moves: the tolerance case (an older server that cannot grant back never fails the accept) is green on both trees, so it is a negative control, not a second red.

Not run

  • No bench run and no live Bot Social: the two re-accept shapes are modelled from Bot Social's documented answers (409 relationship_exists, regranted: true), and the grant uses the same call the Share panel already drives (Share a Bot with an existing friend without an invite link #500). Which of the two shapes the live server picks for this scenario is not observed here — both are covered so the fix does not depend on it.
  • plugins/tree and core suites: not touched by this diff (plugin lint covers the file set).

Risk

  • The new call shares the joining Bot with the inviter's Bot. It is scoped to a re-accept (a relationship that already exists) and is the half the invite already asks for (requested_capabilities: ['chat.public'] on our own invites), so it restores what a fresh accept would have created — but it is a sharing action on the security surface, and the owner/Reviewer should read it as such: a first-time accept still shares nothing back.
  • On a server that grants back but fails the roster refresh, the line still says shared back while the list catches up on the next poll (same as the existing share flow).

An accepted invite is where the two-way friendship comes from, but Bot Social
applies neither half of the invite again when the relationship already exists
(a `relationship_exists` 409, or a `regranted` join): the joining home's Bot
stayed ungranted, so the inviter's first line to it was held as an unknown
recipient until that side shared again.

The re-accept path now asks for the grant an accepted invite would have made
(`grant_bot_to_friend`, chat.public, best effort on a server without the tool),
and the Add friend line says the Bot is shared back instead of only "You
already have ...".
@Birfy Birfy added the agent-pr Pull request opened by an agent label Oct 24, 2026
@Birfy Birfy self-assigned this Oct 24, 2026
@Birfy

Birfy commented Oct 24, 2026

Copy link
Copy Markdown
Collaborator Author

Verdict: PASS at 6617e0a
Written-by: Reviewer

5 个文件 +152/−4,和正文一致。这段的关键不是代码形状,而是“这个 grant 用到的 id 服务端到底给不给”:inviter.bot_id 不是新编的字段——base 7225692e 上 #496 的两条测试(plugins/social/test/social.test.js 里 inviter: { bot_id: 'x1', … },一条走公开 invite info、一条走 regranted join)早就按真实回答钉住了它;grant_bot_to_friend 也是 #500 那条现成的路(plugins/social/src/mcp-client.js:466,friend_bot_id 就是 list_friends 的 peer bot_id,#592)。两条重接受路径拿到的都是服务端真给的 id。

按新 tip 重跑:plugins/social 440/440;7225692e 只换这版测试 → 436/440,红的正好是两条 #1000 加两条文案表(#496 面板、#343/#499 接受成功那句)。

刀四把(每把都 cmp 核对并还原):

  • 拿掉 409 分支里的 restoreAcceptedInviteGrant(social.js:2355)→ 只掉 #1000 第一条;
  • 关掉 regranted 那条(:2468)→ 只掉第二条;
  • 把 grant 的 botId 从 member.bot_id 换成 bot.id(:2409)→ 第一条红在 “the joining Bot, never the home”,授的是 Bot 身份不是本地 id;
  • 拿掉 syncOutgoingGrants(:2411)→ 全套仍绿(见非阻断 2)。

范围核过:首次 join 不进这两条路(regranted === true && status === 'active' 才走,409 那条只有关系已存在才到),#138/#161/#342 的默认拒绝用例在 440 里全绿;social/join-invite 只有 Add friend 表单一个调用点(client.js:2887),没有自动接受也没有 agent 调用,外发一定跟着人点“接受”走。changelog.mjs check 通过(1 条片段,fixed);social.md 的 #496 句补上了 #1000 的边界(best effort、旧服务器 sharedBack 缺席)。

Ran:

$ node api.mjs /repos/ThinkFlowLab/FlyBot/commits/6617e0a6a4510a02a5b161733a29320bb38bcdcd/check-runs
# 除 enqueue-guard 外全 success;enqueue-guard 的失败是在等这条 PASS
$ node --import ./test/resolve.mjs --test "test/*.test.js"   (plugins/social, 6617e0a6)
# 440 / 440
$ 7225692e 树 + 这版 test/social.test.js → 同一套件
# 436 / 440:两条 #1000 + 两条文案表
$ node --test --test-name-pattern="1000" (四把刀,逐把)
# 刀 A/B/C 各掉自己那条;刀 D(去掉 :2411 的 sync)全绿
$ node .github/scripts/changelog.mjs check
# 1 fragment(s) in changelog.d/ are well formed

非阻断(不挡这张):

  1. friendHome 兜底到不了服务端:mcp-client.js:477 写明服务端只收那两个 id,REST body 里也确实没有 friend_home。invite info 不带 bot_id 时这条兜底会静默失败(接受仍成功、sharedBack 缺席)。要么按 list_friends 补 bot_id,要么去掉兜底,别留一条走不通的路。
  2. social.js:2411 那次 sync 没有测试钉住:拿掉它全套仍 440/440,因为 social/access 自己会再同步一次。要留,就加一条不经过 social/access 的断言;否则正文里别说它是“列表立刻可见”的证据。
  3. 两家主 Bot 都叫 Chief 时,提示读成 “You already have Chief (SelfA1233). Chief is shared back…”,两个 Chief 指两个 Bot;带上 handle 更清楚。
  4. alreadyHave 在返回答复前 await 这次 grant(客户端 30 s 死线);Bot Social 卡住时接受结果要等,最终仍成功但面板会像没反应。

@github-actions github-actions Bot added the pass label Oct 24, 2026
@Birfy
Birfy added this pull request to the merge queue Oct 24, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Oct 24, 2026
@Birfy
Birfy added this pull request to the merge queue Oct 24, 2026
Merged via the queue into main with commit db56b81 Oct 24, 2026
11 of 13 checks passed
@Birfy
Birfy deleted the dev2/fix/1000-both-directions branch October 24, 2026 19:37
@Birfy Birfy removed the agent-pr Pull request opened by an agent label Oct 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Accepting a re-invite restores only the direction that sent it; the other side is silently absent

1 participant