d8e2de48e6
## Summary A customer reported that after **Stop Impersonating**, the sidebar still showed the impersonated user's pinned favorites, the AI chat tab toggle, and the AI chat history — even though the original admin's session was correctly restored. ## Root cause The refactor in #19597 replaced the previous `signOut()`-based stop flow with an in-place token swap, but only cleared Apollo cache + reloaded the user. Several user-scoped client stores were left untouched: - **`metadataStoreState`** is localStorage-backed (`navigationMenuItems`, `agentChatThreads`, `views`, `pageLayouts`, etc.) and only refreshed by `MinimalMetadataLoadEffect`. That effect is gated by `metadataLoadedVersion` + `desiredLoadState`, neither of which flips on a same-workspace token swap, so the effect never re-runs. - **In-memory AI atoms** (`currentAiChatThreadState`, `agentChatInputState`, `hasInitializedAgentChatThreadsState`) keep pointing at the impersonated user's selected thread / input. - **Session localStorage keys** (`agentChatDraftsByThreadIdState`, `lastVisitedObjectMetadataItemIdState`, `lastVisitedViewPerObjectMetadataItemState`, `playgroundApiKeyState`) carry the impersonated user's drafts and navigation state. `clearSession()` (used by logout) avoids this because it calls `applyMockedMetadata()` and flips `desiredLoadState` mocked↔real, which chain-triggers a full metadata reload on next sign-in. ## Fix Extract a `resetUserScopedClientState` helper inside `useImpersonationSession` that: 1. Calls `clearSessionLocalStorageKeys()` to drop user-scoped localStorage keys. 2. Resets the in-memory AI session atoms. 3. Marks `metadataStoreState['agentChatThreads']` as `'empty'`. `useLoadStaleMetadataEntities` does **not** handle this entity key, so without an explicit reset to `'empty'` the `AgentChatThreadInitializationEffect` (which only fires on `'empty'`) would never refetch. 4. Calls `invalidateMetadataStore()` to clear all `currentCollectionHash` values and bump `metadataLoadedVersion`, forcing `MinimalMetadataLoadEffect` to re-run and refetch `navigationMenuItems`, `views`, `pageLayouts`, etc. against the new token. The helper is applied to both `startImpersonating` and `stopImpersonating` — start had the same latent bug; the impersonated user could see the admin's favorites until the cache happened to refresh. ## Test plan - [ ] As an admin user, pin some favorites in the sidebar - [ ] Impersonate a user with different favorites → favorites should switch to the impersonated user's - [ ] Click "Stop Impersonating" → sidebar should immediately show the admin's favorites (not the impersonated user's) - [ ] As an admin **without** AI permission, impersonate a user **with** AI permission, open AI chat, send a message, then stop impersonating → AI chat history should be empty / inaccessible (the AI tab visibility itself is fixed in a separate PR) - [ ] Type a draft in AI chat as the impersonated user → after stop, the draft should be gone - [ ] Verify regular sign-out still works while impersonating - [ ] Verify the impersonation banner still shows / hides correctly 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>