Repository navigation
fix(social): accepting an invite shows the shared Bot at once and never grants ours back; live People with access (#228) - #240
Conversation
…grants ours back; live People with access (ThinkFlowLab#228) - social/join-invite marks the offered Bot inbound before its first roster refresh. The grant sync that refresh starts saw the talk-through grant on our Bot before the Bot was inbound, stored it as a core grant on our Bot for the inviter's Bot, and its re-filter could drop the shared Bot until a later refresh (the late row after the toast). - A grant re-filter of an older roster fetch never overwrites a newer one (fetch counter instead of a millisecond timestamp). - Talk through shows only with more than one Bot; its tooltip says that Bot is not shared. - An open People with access re-reads social/access every 5 s while visible; social/access syncs only that Bot's grants.
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 1cde0bc7a7
ℹ️ 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".
| // Mark the shared Bot inbound before the first refresh: the grant sync that refresh starts | ||
| // must already see the talk-through grant on our Bot as talk-through, or it stores it as us | ||
| // sharing that Bot back and the re-filter drops the shared Bot until the next refresh (#228). | ||
| if (offeredHandle) rememberInbound(offeredHandle) |
There was a problem hiding this comment.
Drain older grant syncs before returning from join
When a remoteBots or social/access grant sync is already in flight while the user accepts an invite, setting only inboundBots here is insufficient: isTalkThroughGrant also requires the new relationship to be present in remote.homes, which is not updated until the fresh roster call below. If that older list_bot_grants finishes after the server creates the relationship but before the roster applies, it writes the shared Bot as a real core grant on the joiner's Bot; the new sync is fire-and-forget, so a failure there can leave that grant passing the reach gate beyond the success toast. Version or serialize grant writes, or await a post-roster sync before returning.
Useful? React with 👍 / 👎.
| useEffect(() => { | ||
| void load() | ||
| if (typeof setInterval !== 'function') return undefined | ||
| const timer = setInterval(() => { if (typeof document === 'undefined' || !document.hidden) void load() }, ACCESS_POLL_MS) |
There was a problem hiding this comment.
Keep access polls from overlapping
When a social/access request takes longer than 5 seconds (the MCP timeout is 30 seconds), every interval tick starts another load while the prior request is pending. Each backend handler performs syncOutgoingGrants({ only }) and writes flybot.grants, so responses that finish out of order can overwrite a newer accept/revoke snapshot and then regress this component through setView; an outage can also accumulate six concurrent requests. Use a single-flight guard or schedule the next poll only after the previous load settles.
Useful? React with 👍 / 👎.
| useEffect(() => { | ||
| void load() | ||
| if (typeof setInterval !== 'function') return undefined | ||
| const timer = setInterval(() => { if (typeof document === 'undefined' || !document.hidden) void load() }, ACCESS_POLL_MS) |
There was a problem hiding this comment.
Avoid saving team state on every access poll
While People with access is open with no changes, this 5-second tick still calls social/access; its syncOutgoingGrants unconditionally calls flybot.grants.set, and core's setGrants calls rt.save() even when grantsEqual is true. save() increments the team revision and rewrites state.json, so merely viewing this panel produces a full state write and global UI revision about 12 times per minute despite the setView equality check. Skip the core set when the grant list is unchanged or poll through a side-effect-free query.
Useful? React with 👍 / 👎.
Fixes #228
Accepting a Bot invite had three problems: the Talk through tooltip implied a Bot is granted back, the inviter's open People with access stayed stale, and the shared Bot showed up ~10 s after the success toast.
What
social.jssocial/join-invite): the offered Bot is marked inbound before the first roster refresh. Before, the grant sync started by that refresh saw Bot Social's talk-through grant on the joiner's Chief (grantee = the shared Bot) before the Bot was inbound, soisTalkThroughGrantmissed it: it was stored as a core grant on the joiner's Chief for the inviter's Bot (the Granted friend Bot never shows for the grantee: the talk-through grant hides it (regression from the #161 fix) #178 class: a usable grant, until a later sync dropped it), and the re-filter could drop the shared Bot until the next refresh, which is the late row.client.js): Talk through shows only when the joiner has more than one Bot. Its tooltip says plainly: "Talks for you. Not shared: your friend can't use it unless you invite them to it."social/accessevery 5 s while the page is visible (only re-renders on a change).social/accessnow syncs only that Bot's grants (syncOutgoingGrants({ only })), so the poll costs onelist_bot_grantscall.list_bot_grants). FlyBot filters it on both sides (Regression of #138: joining a friend's invite still puts the joiner's Chief on the inviter's main list #161, Granted friend Bot never shows for the grantee: the talk-through grant hides it (regression from the #161 fix) #178), and changing that needs a Bot Social change.Tests
#228: accepting an invite … never grants our talk-through Bot backfails at base (core grant on Chief for@helper.bob.home) and passes at tip. It also checks the shared Bot is listed when the join returns and after the background sync, and that Chief's People with access is empty.#228: an open People with access shows a friend who accepts, without reopeningfails at base (no poll).#136 / #181(no picker with one Bot, tooltip copy) and#138(copy).ARCH_DOCS_BASE=upstream/main npm run verifygreen locally (TZ=UTC). The social suite passed 6/6 repeated runs. One unrelated core test (an untagged hold stamps the latest working task…) failed once and passed on rerun. Docs:social.md. Fragment228-accept-invite-grant.fixed.md.