Scope Channels (bluebird) browser tabs to the signed-in user#3164
Scope Channels (bluebird) browser tabs to the signed-in user#3164adamleithp wants to merge 2 commits into
Conversation
Tab strips were stored machine-wide, so every account on a machine shared one set of tabs and logout left the previous user's tabs behind. Persist them per (cloudRegion, accountKey) instead: each login restores that user's tabs, switching accounts swaps snapshots, and signed-out sessions are memory-only so no account's saved tabs get overwritten. Pre-account rows are adopted by the first login so existing users keep their tabs. Generated-By: PostHog Code Task-Id: b06ce1b6-aef9-4164-8274-0ae6374ca8c1
|
Merging to
After your PR is submitted to the merge queue, this comment will be automatically updated with its status. If the PR fails, failure details will also be posted here |
|
React Doctor found no issues in the changed files. 🎉 Reviewed by React Doctor for commit |
|
| @@ -0,0 +1,2 @@ | |||
| ALTER TABLE `browser_windows` ADD `account_scope` text;--> statement-breakpoint | |||
| CREATE INDEX `browser_windows_account_scope_idx` ON `browser_windows` (`account_scope`); No newline at end of file | |||
There was a problem hiding this comment.
The file is missing a trailing newline, which can cause issues with some SQL tools and shows as a diff noise marker (
\ No newline at end of file) in git diff.
| CREATE INDEX `browser_windows_account_scope_idx` ON `browser_windows` (`account_scope`); | |
| CREATE INDEX `browser_windows_account_scope_idx` ON `browser_windows` (`account_scope`); |
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
Fixes from review of the initial per-user scoping: - AuthService now tracks a session epoch: a background session restore that finishes after a logout (or after a newer login) is discarded instead of resurrecting the old session — previously it would re-apply the logged-out user's tab scope and could clobber a fresh login. - The tabs service treats "scope not determined yet" (app boot before auth resolves, offline restore, failed identity fetch) as a distinct state from "signed out": tabs opened during that window are adopted into the account's snapshot when the scope arrives, instead of being silently discarded with the swap. - setActiveTab ignores tab ids not present in the window, so stale renderer state (router history from a previous account) can't leave a dangling activeTabId. - browser_windows now scopes by (account_key, cloud_region) columns, matching the auth_preferences convention, instead of a combined string; migration 0017 regenerated (unshipped). - save() relies on the window FK cascade instead of an extra subquery DELETE per mutation; repository mock extracted per convention. Generated-By: PostHog Code Task-Id: b06ce1b6-aef9-4164-8274-0ae6374ca8c1
Problem
Channels/canvas browser tabs are persisted machine-wide, not per user. Everyone who logs into the app on the same machine shares one tab strip: logging out leaves the previous user's tabs behind, and switching accounts doesn't restore that user's own tabs.
Why
Tabs should follow the login, not the install — logging into an account should bring back that account's tabs, and switching users should restore theirs (raised for PostHog Code / project bluebird).
Changes
browser_windowsrows now carry an owning account (account_key+cloud_region, the same convention asauth_preferences; migration 0017); tabs inherit scope through their window FK. Load/save inBrowserTabsRepositoryonly touch the active account's rows.BrowserTabsServicegetssetAccountScope()with a three-state scope: undetermined (app boot before auth resolves, session restoring, identity fetch not yet succeeded — tabs opened then are adopted into the account's snapshot once the scope arrives, so nothing is lost to the swap), signed out (memory-only blank strip by design), and scoped (login loads that account's persisted snapshot and fans it out to all windows).AuthStateexposesaccountKey, with agetAccountScope()helper encoding the three-way scope; the Electron main process wires auth state changes to the tabs service.AuthServicegains a session-epoch staleness guard: a background session restore that completes after a logout (or after a newer login) is discarded instead of resurrecting the old session's state and tab scope.setActiveTabignores tab ids not present in the window, so stale renderer state (router history stamped under a previous account's snapshot) can't leave a danglingactiveTabId.How did you test this?
browser-tabs-repository.test.ts(scope isolation across accounts and regions, round-trip, FK-cascade replace, legacy-row adoption),service.test.ts(per-account restore on user switch, adoption of pre-scope tabs with dedupe and focus, signed-out isolation, setActiveTab guard),authIdentity.test.ts(three-way scope resolution), and newauth.test.tsraces (restore completing after logout, stale restore vs newer login) — 82 tests passing across the touched suites.pnpm typecheckclean across all 22 packages; Biome clean on changed files.Automatic notifications
Created with PostHog Code