Skip to content

fix: clear user collections and queries on sign out (@fehmer) - #8569

Draft
fehmer wants to merge 1 commit into
masterfrom
clear-user-collections-signout
Draft

fehmer wants to merge 1 commit into
masterfrom
clear-user-collections-signout

Conversation

@fehmer

@fehmer fehmer commented Nov 12, 2026 •

Copy link
Copy Markdown
Member

TL;DR

Signing out reset the ["user", …] queries but never cleared the queryCollectionOptions collections, so the next signed-in user kept the previous user's rows in every user-bound collection (custom themes, presets, tags, results, inbox, connections, ape keys, result filter presets) until their own download happened to replace them.

QueryClient.resetQueries / removeQueries cannot clear a collection: the collection keeps its rows in its own normalized state, and the query↔collection sync only applies successful fetch results — resetting or removing the query never touches the rows (reproduced in the regression spec below).

What this does

  • New leaf module collections/utils/session-collection.ts with the session collections registry and the sign in / sign out cleanup. It only imports libraries (queryClient is passed to the clear as a parameter, so it never imports the app's queries module — no import cycle), and:
    • clearSessionCollections sweeps every row of each registered collection — the keys come from the collection's own getKeyFromItem, deletes run inside a no-op transaction (the collections have no onDelete handler, and locally written rows the query does not own would survive the sync anyway) — then empties the backing query with setQueryData(rootKey, []), which the sync applies, dropping the query's ownership and the cache copy;
    • refetchSessionCollections calls collection.utils.refetch() for each registered collection. Collections keep enabled: isAuthenticated, so the refetch is a no-op for collections whose query never started; startSync'd collections need it because their query is created at module load, before the auth state resolves, and never re-evaluates enabled on its own. A refetch never double-downloads: it joins the in-flight initial download.
  • The auth effect in queries/index.ts drives the registry: on sign out it runs resetQueries({ queryKey: ["user"] }) (for the plain user queries, as before) first, then the collection clears, so the clears' setQueryData([]) wins as each query's final state.
  • friendsList gets enabled: isAuthenticated — the friends page is auth-gated, so the sign-out reset must not refetch it into a 401.
  • Each collection module registers itself at module load with just { collection, queryKey }; no cleanup logic lives in the collection modules.

Repro before the fix

  1. Sign in → custom themes load into the customThemes collection.
  2. Sign out → the collection keeps all of the previous user's rows (the query is reset; the collection is not).
  3. Sign in again → the next user's UI renders the previous user's rows.

Testing

  • frontend/__tests__/collections/utils/session-collection.spec.ts covers the registry in isolation with a collection created in the test (none of the app's modules): the download lands, clearSessionCollections empties the collection and the query without calling the collection's onDelete handler (the ambient transaction bypasses it — the guarantee that clearing never syncs deletes to the backend), and refetchSessionCollections restarts the download.
  • Full frontend suite: 106 files / 1776 tests pass.
  • oxlint --type-aware --type-check clean; madge reports no circular dependencies; production build passes.
  • Browser check on the dev server: sign in → themes render in the test widget in the header; sign out → widget shows ready with zero rows, and the network log shows no user-endpoint writes or 401s; sign in again → themes re-download and render.

@monkeytypegeorge monkeytypegeorge added the frontend User interface or web stuff label Nov 12, 2026
@fehmer
fehmer force-pushed the clear-user-collections-signout branch 3 times, most recently from a49ff94 to 7e17585 Compare November 12, 2026 21:04
queryClient.resetQueries on sign out never cleared the queryCollectionOptions collections: their rows live in the collection's normalized state, which resetting/removing the query never touches (the sync only applies successful fetches), so the previous user's themes/presets/tags/etc. stayed visible to the next user.

Each user collection now registers { clear, refetch } in a new leaf registry (queries/user-scoped.ts):

- clear (sign out): sweep all rows in a transaction (the collections have no onDelete handler), then empty the backing query with setQueryData([]), which the sync applies, dropping query ownership and the cache copy.
- refetch (sign in): collection.utils.refetch(), replacing the per-module createRoot sign-in effects with one central effect in queries/index.ts (resetQueries stays for plain user queries like friendsList, which gains enabled: isAuthenticated to avoid refetching into a 401 after sign out).

Verified in the browser: fresh load downloads and shows the themes, sign out empties the collection (status stays ready), sign in re-downloads. No duplicate fetches; no circular imports; full suite, typecheck and build green.
@fehmer
fehmer force-pushed the clear-user-collections-signout branch from 7e17585 to fbea5fe Compare November 12, 2026 21:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

frontend User interface or web stuff

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants