You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix(queries): close React Query key/fetch-arg drift cache collisions
Several query hooks fetched with an identifier that was absent from their
queryKey, so distinct fetch args shared one cache entry. Thread the missing
args into the key factories and update all callsites/invalidations.
- organization: useOrganization always fetched the ACTIVE org via
getFullOrganization() while caching under detail(orgId). Pass orgId through
to the better-auth call (query.organizationId); active-org behavior unchanged.
- logs: logKeys.detail now keys on (workspaceId, logId) to prevent cross-
workspace collision; updated useLogDetail, useLogByExecutionId, prefetchLogDetail,
useCancelExecution optimistic path, and external callsites.
- inbox: inboxKeys.taskList now includes cursor/limit (pagination args were sent
but omitted from the key); keepPreviousData pagination UX preserved.
- a2a: narrow create/update byWorkflows() invalidation to byWorkflow(ws, wf)
since their responses reliably carry both ids; delete/publish stay broad.
Not bugs (verified, left unchanged):
- kb/connectors update/delete invalidate knowledgeKeys.detail(kbId), which is a
prefix of connectorKeys.all(kbId) — connector list/detail are invalidated
transitively by React Query prefix matching.
Harness: add a key-fetch-arg-drift check to check-react-query-patterns.ts that
flags a camelCase identifier the queryFn forwards into the fetch but is absent
from the queryKey (excludes the requestJson contract arg, PascalCase/SCREAMING
constants, and signal/pageParam machinery). Document the rule in sim-queries.md.
tables.useTable annotated rq-lint-allow (tableId globally unique; workspaceId is
only an authz scope).
Copy file name to clipboardExpand all lines: .claude/rules/sim-queries.md
+3-1Lines changed: 3 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -25,6 +25,8 @@ export const entityKeys = {
25
25
26
26
Never use inline query keys — always use the factory.
27
27
28
+
**Every identifier the `queryFn` uses MUST appear in the `queryKey`.** If the fetch is scoped by `workspaceId`, `cursor`, `limit`, an org id, etc., those values must be part of the key — otherwise distinct fetch args share one cache entry (a cross-tenant / per-param cache collision). The lone exception is a globally-unique id used as the key while a second fetch arg is only an authz scope that cannot collide; annotate those with `// rq-lint-allow: <reason>`. Enforced by the `key-fetch-arg-drift` check in `scripts/check-react-query-patterns.ts`.
`scripts/check-react-query-patterns.ts` (`bun run check:react-query`, run in CI) statically enforces these conventions: every `useQuery`/`useInfiniteQuery`/`useSuspenseQuery` declares an explicit `staleTime`, inline `queryFn`s destructure `signal`, `queryKey`s reference a colocated factory rather than an inline literal, and every `*Keys` factory in `hooks/queries/**` exposes an `all` root key. `hooks/queries/**` is a zero-tolerance zone; the rest of `apps/sim/**` is ratcheted against `scripts/check-react-query-patterns.baseline.json`. For a genuine exception, put `// rq-lint-allow: <reason>` on the line directly above the flagged construct.
147
+
`scripts/check-react-query-patterns.ts` (`bun run check:react-query`, run in CI) statically enforces these conventions: every `useQuery`/`useInfiniteQuery`/`useSuspenseQuery` declares an explicit `staleTime`, inline `queryFn`s destructure `signal`, `queryKey`s reference a colocated factory rather than an inline literal, every `*Keys` factory in `hooks/queries/**` exposes an `all` root key, and every identifier the `queryFn` forwards into the fetch also appears in the `queryKey` (`key-fetch-arg-drift`). `hooks/queries/**` is a zero-tolerance zone; the rest of `apps/sim/**` is ratcheted against `scripts/check-react-query-patterns.baseline.json`. For a genuine exception, put `// rq-lint-allow: <reason>` on the line directly above the flagged construct.
Copy file name to clipboardExpand all lines: apps/sim/app/workspace/[workspaceId]/home/components/mothership-view/components/resource-registry/resource-registry.tsx
0 commit comments