Skip to content

social: a friendship covers only the invited Bot and the Bot that joined - #25

Merged
Birfy merged 1 commit into
ThinkFlowLab:mainfrom
Birfy:scope-friend-to-invited-bot
Oct 14, 2026
Merged

Birfy merged 1 commit into
ThinkFlowLab:mainfrom
Birfy:scope-friend-to-invited-bot

Conversation

@Birfy

@Birfy Birfy commented Oct 14, 2026

Copy link
Copy Markdown
Collaborator

What

A Bot Social friendship now covers only the invited Bot and the Bot that joined, not the joiner's whole home.

  • Join as one Bot. social/join-invite sends the request from one local Bot's member identity: botId, defaulting to the Main Bot. It no longer joins as the home. The Add-friend form has a Join as picker (shown when there is more than one Bot), and the result reports joinedAs.
  • Roster = what the server grants. The plugin shows only the Bots that list_remote_bots returns. It also keeps each friend home's via (the local Bots the friendship covers).
  • Only covered Bots may send. The social middleware refuses a send from a local Bot the friendship does not cover, before anything leaves. The user's own chat with a friend's Bot signs only with a covered Bot.
  • Copy link stays per Bot, with no change.

Server side: Birfy/bot-social 7f9c88e records requester_scope / target_scope on relationships, so an invite made for one member exposes only that member. list_remote_bots, profiles, send_as_member, conversations and messages all enforce this on the server.

Tests

  • Updated the join test: the join goes out from the Main Bot's member, or the chosen Bot, never the home.
  • New test for a scoped friendship: the roster shows only the granted Bot, a send from an uncovered local Bot is denied locally, an unlisted remote Bot is unreachable, and the covered Bot's send goes through.
  • plugins/social: 25/25 pass. Across the whole ds-bot suite, the same 9 client-bundle and UI test files fail with and without this change in my environment. None of those 9 are social tests.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 037a807cff

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

if (msg.target?.remote !== true || (msg.to?.transport ?? 'bot-social') !== 'bot-social') return undefined
const bot = await remoteBot(msg.target.handle)
if (bot === undefined) return { action: 'deny', reason: `${msg.target.handle} is not a Bot of a friend on Bot Social` }
if (home && typeof msg.from === 'string' && !covered(await friendEntry(bot.home), msg.from)) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Keep coverage tied to the target relationship

When two Bot-scoped friendships point at the same friend home (for example, Chief↔Coder and Writer↔Researcher), list_remote_bots can contain relationship entries with different bots/via values. remoteBot() finds the requested Bot, but this home-only lookup then selects the first entry for that home, so Writer is denied access to Researcher while Chief may get a cross-relationship send as far as the server. Preserve the entry containing the target Bot and run covered against that entry.

Useful? React with 👍 / 👎.

if (!bot) throw new Error('Choose which of your Bots joins')
const member = await register(bot)
if (!member) throw new Error(`${bot.name} has no Bot Social identity yet`)
from = { from_bot_id: member.bot_id }

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Include member-scoped joins in the overview

When this selected member's join remains pending_target (a state handled just below), the relationship now belongs to that member, but friendsOverview() still queries list_friends only with home.id; setAutoAccept() already enumerates each member identity because member relationships are not returned by that home query. Consequently the Add-friend panel's refresh or reopen omits this request from pending_outgoing, so users cannot track it while waiting for acceptance; aggregate the member identity overviews too.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-14T12:36:55.428312Z 037a807 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

…t joined

Joining an invite now goes out from one local Bot's member identity (Join as,
default the Main Bot) instead of the whole home, so the inviter sees only that
Bot. The roster keeps the server's per-friend 'via' (the local Bots the
friendship covers): sends from any other local Bot are refused before anything
leaves, and the user's own chat signs with a covered Bot. Only Bots that
list_remote_bots returns are shown or reachable.

Needs the Bot Social server with scoped friendships (requester_scope /
target_scope); against an older server the plugin behaves as before.
@Birfy
Birfy force-pushed the scope-friend-to-invited-bot branch from 037a807 to d09a378 Compare October 14, 2026 12:43
@Birfy
Birfy merged commit ea7d380 into ThinkFlowLab:main Oct 14, 2026
4 checks passed
Birfy added a commit that referenced this pull request Oct 23, 2026
`git fetch origin main:refs/remotes/origin/main` without `+` only updates the
ref as a fast-forward. actions/checkout leaves that ref at the tip it saw, so a
push whose base is not a descendant of it made the step die with
`! [rejected] ... (non-fast-forward)` before lint and the suite ran.

Fetch with an explicit force refspec instead. The fetch still fails loudly when
the base cannot be fetched, and the merge-base and rev-parse checks stay, so the
arch-docs check never runs against an unverified base.

`.github/scripts/fetch-base.test.mjs` reads the real step out of the action and
runs it against a scratch repository: a base older than the checkout ref must not
abort, a base that cannot be fetched must fail, and the refspec must stay forced.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant