Bound a Supply run toggle's session load and CSRF refresh by its deadline (Feature 17)
CI / ci (push) Successful in 4m58s
CI / ci (pull_request) Successful in 4m59s

- loadMe takes an optional abort signal; AuthBootstrap calls it with none.
- Each toggle try loads GET /api/v1/me itself under its deadline when the
  session is not loaded, instead of joining a /me query already in flight
  that may never answer.
- The /me refresh a csrf 403 makes is bounded by the request's signal: a
  request whose signal aborts stops waiting at once and the refresh is no
  longer shared, so the next csrf 403 starts a fresh /me. Requests without
  a signal still share it, and it is aborted only once no request waits.
- Tests: a hung /me and a hung csrf refresh during a toggle exchange, both
  recovered on the next try in order; the client's refresh sharing and abort.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-08 11:27:18 -04:00
co-authored by Claude Opus 5.5
parent 6d45f3ed0d
commit 54b59965ed
5 changed files with 239 additions and 34 deletions
+1 -1
View File
@@ -20,7 +20,7 @@ export const meQueryKey = [ME_PATH] as const
export function AuthBootstrap({ children }: { children: ReactNode }) {
const api = useApi()
const forbidden = useSyncExternalStore(api.subscribe, api.forbidden)
const me = useQuery({ queryKey: meQueryKey, queryFn: api.loadMe, staleTime: Infinity, networkMode: 'always' })
const me = useQuery({ queryKey: meQueryKey, queryFn: () => api.loadMe(), staleTime: Infinity, networkMode: 'always' })
// fetch rejects with a TypeError only when the network fails.
const savedPages = me.isError && me.error instanceof TypeError && api.session.verified()
const { refetch } = me