feat(auth): detect session expiry live and offer re-login in place
Every response already funnels through runtimeFetch, so a classifier there spots 401s, confirms them against /auth/session (a proxied provider 401 must not read as a logout), and flips a small auth-session store. The web and hosted surfaces show a frosted banner under the header whose Log in button hands off to the session gate's existing unlock flow; sends are paused while expired, the session-load error screen explains the auth case and retries itself after login, and returning to a long-idle window revalidates once via visibility/focus. Native mobile feeds the same signal into its connection re-probe instead of showing the banner; VS Code is exempt.
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import { getActiveRelayTunnel } from './relay/runtime-tunnel';
|
||||
import { TUNNEL_PARSE_BASE } from './relay/tunnel-payloads';
|
||||
import { buildRuntimeAuthHeaders } from './runtime-auth';
|
||||
import { observeRuntimeAuthResponse } from './runtime-auth-expiry';
|
||||
import { getRuntimeUrlResolver, type RuntimeUrlQuery } from './runtime-url';
|
||||
|
||||
export interface RuntimeFetchOptions extends RequestInit {
|
||||
@@ -294,6 +295,14 @@ export const runtimeFetch = async (input: string | URL | Request, init: RuntimeF
|
||||
).toUpperCase();
|
||||
}
|
||||
|
||||
// Session-expiry classification rides on responses that already flow
|
||||
// through here; only the status is read, never the body.
|
||||
const rawFetch = doFetch;
|
||||
doFetch = () => rawFetch().then((response) => {
|
||||
observeRuntimeAuthResponse(url, response.status);
|
||||
return response;
|
||||
});
|
||||
|
||||
// A Request always carries a (possibly default) signal; treat any Request, or
|
||||
// an explicit init.signal, as "has signal" and skip coalescing for safety.
|
||||
const hasSignal = requestInit.signal != null || input instanceof Request;
|
||||
|
||||
Reference in New Issue
Block a user