@oxyhq/services 8.1.2 → 8.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -10,6 +10,7 @@ var _OxyContext = require("../context/OxyContext.js");
10
10
  var _reactQuery = require("@tanstack/react-query");
11
11
  var _bloom = require("@oxyhq/bloom");
12
12
  var _toast = require("@oxyhq/bloom/toast");
13
+ var _core = require("@oxyhq/core");
13
14
  var _FontLoader = require("./FontLoader.js");
14
15
  var _queryClient = require("../hooks/queryClient.js");
15
16
  var _storageHelpers = require("../utils/storageHelpers.js");
@@ -53,7 +54,9 @@ const LazyBottomSheetRouter = /*#__PURE__*/(0, _react.lazy)(() => Promise.resolv
53
54
  default: mod.default
54
55
  }), error => {
55
56
  if (__DEV__) {
56
- console.error('[OxyProvider] Failed to load BottomSheetRouter:', error);
57
+ _core.logger.error('Failed to load BottomSheetRouter', error instanceof Error ? error : new Error(String(error)), {
58
+ component: 'OxyProvider'
59
+ });
57
60
  }
58
61
  return {
59
62
  default: () => null
@@ -118,7 +121,9 @@ const OxyProvider = ({
118
121
  const moduleName = KEYBOARD_CONTROLLER_MODULE;
119
122
  (specifier => new Promise(r => r(`${specifier}`)).then(s => _interopRequireWildcard(require(s))))(moduleName).then(mod => setKBProvider(() => mod.KeyboardProvider)).catch(error => {
120
123
  if (__DEV__) {
121
- console.warn('[OxyProvider] react-native-keyboard-controller not available, skipping keyboard support', error);
124
+ _core.logger.warn('react-native-keyboard-controller not available, skipping keyboard support', {
125
+ component: 'OxyProvider'
126
+ }, error);
122
127
  }
123
128
  });
124
129
  }, []);
@@ -161,7 +166,9 @@ const OxyProvider = ({
161
166
  storage = await (0, _storageHelpers.createPlatformStorage)();
162
167
  } catch (error) {
163
168
  if (__DEV__) {
164
- console.warn('[OxyProvider] Failed to initialize storage for query persistence', error);
169
+ _core.logger.warn('Failed to initialize storage for query persistence', {
170
+ component: 'OxyProvider'
171
+ }, error);
165
172
  }
166
173
  }
167
174
  if (!mounted || queryClientRef.current) return;
@@ -1 +1 @@
1
- {"version":3,"names":["_react","require","_reactNative","_OxyContext","_reactQuery","_bloom","_toast","_FontLoader","_queryClient","_storageHelpers","_jsxRuntime","_interopRequireWildcard","e","t","WeakMap","r","n","__esModule","o","i","f","__proto__","default","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","BOOT_BG_COLOR","bootStyles","StyleSheet","create","bootShell","flex","backgroundColor","setupFonts","isWeb","Platform","OS","KEYBOARD_CONTROLLER_MODULE","LazyBottomSheetRouter","lazy","Promise","resolve","then","mod","error","__DEV__","console","LazySignInModal","OxyProvider","oxyServices","children","onAuthStateChange","storageKeyPrefix","baseURL","authWebUrl","authRedirectUri","queryClient","providedQueryClient","KBProvider","setKBProvider","useState","useEffect","moduleName","specifier","s","KeyboardProvider","catch","warn","KeyboardWrapper","jsx","Fragment","storageRef","useRef","queryClientRef","persistenceUnsubRef","setQueryClient","current","mounted","bootstrap","storage","createPlatformStorage","client","createQueryClient","restored","unsubscribe","attachQueryPersistence","handleVisibilityChange","focusManager","setFocused","document","visibilityState","addEventListener","removeEventListener","subscription","AppState","state","remove","cleanup","setupNetworkMonitoring","onlineManager","setOnline","navigator","onLine","handleOnline","handleOffline","window","NetInfo","fetch","isConnected","View","style","coreContent","QueryClientProvider","BloomDialogProvider","jsxs","OxyContextProvider","Suspense","fallback","ToastOutlet","_default","exports"],"sourceRoot":"../../../../src","sources":["ui/components/OxyProvider.tsx"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["_react","require","_reactNative","_OxyContext","_reactQuery","_bloom","_toast","_core","_FontLoader","_queryClient","_storageHelpers","_jsxRuntime","_interopRequireWildcard","e","t","WeakMap","r","n","__esModule","o","i","f","__proto__","default","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","BOOT_BG_COLOR","bootStyles","StyleSheet","create","bootShell","flex","backgroundColor","setupFonts","isWeb","Platform","OS","KEYBOARD_CONTROLLER_MODULE","LazyBottomSheetRouter","lazy","Promise","resolve","then","mod","error","__DEV__","loggerUtil","Error","String","component","LazySignInModal","OxyProvider","oxyServices","children","onAuthStateChange","storageKeyPrefix","baseURL","authWebUrl","authRedirectUri","queryClient","providedQueryClient","KBProvider","setKBProvider","useState","useEffect","moduleName","specifier","s","KeyboardProvider","catch","warn","KeyboardWrapper","jsx","Fragment","storageRef","useRef","queryClientRef","persistenceUnsubRef","setQueryClient","current","mounted","bootstrap","storage","createPlatformStorage","client","createQueryClient","restored","unsubscribe","attachQueryPersistence","handleVisibilityChange","focusManager","setFocused","document","visibilityState","addEventListener","removeEventListener","subscription","AppState","state","remove","cleanup","setupNetworkMonitoring","onlineManager","setOnline","navigator","onLine","handleOnline","handleOffline","window","NetInfo","fetch","isConnected","View","style","coreContent","QueryClientProvider","BloomDialogProvider","jsxs","OxyContextProvider","Suspense","fallback","ToastOutlet","_default","exports"],"sourceRoot":"../../../../src","sources":["ui/components/OxyProvider.tsx"],"mappings":"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","ignoreList":[]}
@@ -30,6 +30,71 @@ const OxyContext = /*#__PURE__*/(0, _react.createContext)(null);
30
30
  // `../utils/activeAuthuser` so the session-management and auth-operations hooks
31
31
  // can share them without re-importing this 1k-line context file.
32
32
 
33
+ /**
34
+ * Module-level run-once guard for the cold-boot silent SSO steps
35
+ * (`fedcm-silent` and `silent-iframe`).
36
+ *
37
+ * Both steps trigger a one-shot browser credential / iframe handshake that must
38
+ * fire AT MOST ONCE per page load — otherwise a provider remount storm (route
39
+ * churn, StrictMode double-invoke, error-boundary recovery) becomes a credential
40
+ * request storm. A per-instance ref resets on every remount, so the guard must
41
+ * live at module scope. Keyed on `origin|baseURL` so two providers pointed at
42
+ * the same API from the same origin share one attempt; never cleared because
43
+ * only a fresh page load can change the IdP session state, and a fresh page load
44
+ * starts a fresh module scope.
45
+ *
46
+ * This is a NEW, dedicated set — distinct from `useWebSSO`'s `silentSSOAttempted`
47
+ * (which guards the post-boot INTERACTIVE button path) and never a core
48
+ * module-level singleton (that re-evaluates under Metro web bundling and the
49
+ * guard would not hold).
50
+ */
51
+ const servicesSilentAttempted = new Set();
52
+
53
+ /**
54
+ * Build the `origin|baseURL` signature used as the silent-cold-boot guard key.
55
+ */
56
+ function silentColdBootKey(oxyServices) {
57
+ const origin = typeof window !== 'undefined' ? window.location.origin : 'no-origin';
58
+ let baseURL = '';
59
+ try {
60
+ baseURL = oxyServices.getBaseURL?.() ?? '';
61
+ } catch {
62
+ baseURL = '';
63
+ }
64
+ return `${origin}|${baseURL}`;
65
+ }
66
+
67
+ /**
68
+ * Whether `idpOrigin` is a same-site, first-party host of the current page —
69
+ * i.e. it shares the page's registrable apex (last two labels), so a "no
70
+ * session" answer from its `/auth/session-check` iframe is authoritative for
71
+ * THIS app and may force a local sign-out.
72
+ *
73
+ * On a cross-site IdP (or any host whose relationship to the page can't be
74
+ * positively established) this returns `false`, so the visibility-driven check
75
+ * may surface a session-ended toast but MUST NOT clear local state — a
76
+ * third-party / undetermined IdP answer can never force logout. Returns `false`
77
+ * off-browser.
78
+ */
79
+ function isSameSiteIdP(idpOrigin) {
80
+ if (typeof window === 'undefined') return false;
81
+ let idpHostname;
82
+ try {
83
+ idpHostname = new URL(idpOrigin).hostname;
84
+ } catch {
85
+ return false;
86
+ }
87
+ const pageHostname = window.location.hostname;
88
+ if (!idpHostname || !pageHostname) return false;
89
+ if (idpHostname === pageHostname) return true;
90
+ const apexOf = hostname => hostname.split('.').slice(-2).join('.');
91
+ const pageApex = apexOf(pageHostname);
92
+ // Require a real registrable apex (≥2 labels) AND an exact apex match AND that
93
+ // the IdP host is the page apex itself or a subdomain of it.
94
+ if (pageHostname.split('.').length < 2) return false;
95
+ if (apexOf(idpHostname) !== pageApex) return false;
96
+ return idpHostname === pageApex || idpHostname.endsWith(`.${pageApex}`);
97
+ }
33
98
  let cachedUseFollowHook = null;
34
99
  const loadUseFollowHook = () => {
35
100
  if (cachedUseFollowHook) {
@@ -71,9 +136,19 @@ const OxyProvider = ({
71
136
  if (providedOxyServices) {
72
137
  oxyServicesRef.current = providedOxyServices;
73
138
  } else if (baseURL) {
139
+ // Auto-detect the FAPI (IdP) origin from the current browser hostname so
140
+ // a consuming RP (mention.earth, homiio.com, alia.onl, …) targets
141
+ // `auth.<rp-apex>` for FedCM + the silent iframe WITHOUT passing
142
+ // `authWebUrl` explicitly — that is what makes both the FedCM config and
143
+ // the `/auth/silent` iframe first-party with the RP (Safari ITP /
144
+ // Firefox TCP need first-party). An explicit `authWebUrl` prop still
145
+ // wins. On native `autoDetectAuthWebUrl()` returns `undefined`
146
+ // (off-browser), leaving the value unchanged. We only auto-detect on the
147
+ // baseURL-only path — a consumer-provided `OxyServices` instance is
148
+ // never mutated.
74
149
  oxyServicesRef.current = new _core.OxyServices({
75
150
  baseURL,
76
- authWebUrl,
151
+ authWebUrl: authWebUrl ?? (0, _core.autoDetectAuthWebUrl)(),
77
152
  authRedirectUri
78
153
  });
79
154
  } else {
@@ -138,7 +213,9 @@ const OxyProvider = ({
138
213
  }, [oxyServices]);
139
214
  const logger = (0, _react.useCallback)((message, err) => {
140
215
  if (__DEV__) {
141
- console.warn(`[OxyContext] ${message}`, err);
216
+ _core.logger.warn(message, {
217
+ component: 'OxyContext'
218
+ }, err);
142
219
  }
143
220
  }, []);
144
221
  const storageKeys = (0, _react.useMemo)(() => (0, _storageHelpers.getStorageKeys)(storageKeyPrefix), [storageKeyPrefix]);
@@ -357,6 +434,14 @@ const OxyProvider = ({
357
434
  const onAuthStateChangeRef = (0, _react.useRef)(onAuthStateChange);
358
435
  onAuthStateChangeRef.current = onAuthStateChange;
359
436
 
437
+ // `handleWebSSOSession` is declared further down (it depends on values that
438
+ // are only available there). The FedCM/iframe cold-boot steps need to commit
439
+ // a recovered session through it, so we route the call through a ref that is
440
+ // populated once the callback exists. The ref is assigned synchronously on
441
+ // every render before the cold-boot effect can fire (the effect is gated on
442
+ // `storage` + `initialized`, both of which settle after first render).
443
+ const handleWebSSOSessionRef = (0, _react.useRef)(null);
444
+
360
445
  // Cold-boot session restore via the secure refresh cookies (web only).
361
446
  //
362
447
  // Calls `oxyServices.refreshAllSessions()` → `POST /auth/refresh-all` with
@@ -451,90 +536,232 @@ const OxyProvider = ({
451
536
  onAuthStateChangeRef.current?.(fullUser);
452
537
  return true;
453
538
  }, [oxyServices, persistSessionDurably]);
539
+
540
+ // Native (and offline) stored-session restore — the ONLY restore path that
541
+ // runs on React Native, and the web fallback when no cross-domain step won.
542
+ //
543
+ // Verbatim-extracted from the previous `restoreSessionsFromStorage` body: it
544
+ // reads the durable `session_ids` / `active_session_id` slots, validates each
545
+ // stored session in parallel (bearer `validateSession`), and switches to the
546
+ // stored active session via the session-management `switchSession`. This body
547
+ // is platform-agnostic and gated by NO `enabled()` predicate so it runs on
548
+ // every platform — on native it is reached unconditionally (every web-only
549
+ // step ahead of it is disabled by `isWebBrowser()`), so native restore is
550
+ // exactly this and nothing else (no FedCM / iframe / refresh-all /
551
+ // handleAuthCallback).
552
+ const restoreStoredSession = (0, _react.useCallback)(async () => {
553
+ if (!storage) {
554
+ return false;
555
+ }
556
+ const storedSessionIdsJson = await storage.getItem(storageKeys.sessionIds);
557
+ const storedSessionIds = storedSessionIdsJson ? JSON.parse(storedSessionIdsJson) : [];
558
+ const storedActiveSessionId = await storage.getItem(storageKeys.activeSessionId);
559
+ let validSessions = [];
560
+ if (storedSessionIds.length > 0) {
561
+ // Validate all sessions in parallel (with 8s timeout per session) to avoid
562
+ // sequential blocking that freezes the app on startup
563
+ const VALIDATION_TIMEOUT = 8000;
564
+ const results = await Promise.allSettled(storedSessionIds.map(async sessionId => {
565
+ const timeoutPromise = new Promise(resolve => setTimeout(() => resolve(null), VALIDATION_TIMEOUT));
566
+ const validationPromise = oxyServices.validateSession(sessionId, {
567
+ useHeaderValidation: true
568
+ }).catch(validationError => {
569
+ if (!(0, _errorHandlers.isInvalidSessionError)(validationError) && !(0, _errorHandlers.isTimeoutOrNetworkError)(validationError)) {
570
+ logger('Session validation failed during init', validationError);
571
+ } else if (__DEV__ && (0, _errorHandlers.isTimeoutOrNetworkError)(validationError)) {
572
+ _core.logger.debug('Session validation timeout (expected when offline)', {
573
+ component: 'OxyContext',
574
+ method: 'restoreStoredSession'
575
+ }, validationError);
576
+ }
577
+ return null;
578
+ });
579
+ return Promise.race([validationPromise, timeoutPromise]).then(validation => {
580
+ if (validation?.valid && validation.user) {
581
+ const now = new Date();
582
+ return {
583
+ sessionId,
584
+ deviceId: '',
585
+ expiresAt: new Date(now.getTime() + 7 * 24 * 60 * 60 * 1000).toISOString(),
586
+ lastActive: now.toISOString(),
587
+ userId: validation.user.id?.toString() ?? '',
588
+ isCurrent: sessionId === storedActiveSessionId
589
+ };
590
+ }
591
+ return null;
592
+ });
593
+ }));
594
+ validSessions = results.filter(r => r.status === 'fulfilled').map(r => r.value).filter(s => s !== null);
595
+
596
+ // Always persist validated sessions to storage (even empty list)
597
+ // to clear stale/expired session IDs that would cause 401 loops on restart
598
+ updateSessionsRef.current(validSessions, {
599
+ merge: false
600
+ });
601
+ }
602
+ if (storedActiveSessionId) {
603
+ try {
604
+ await switchSessionRef.current(storedActiveSessionId);
605
+ return true;
606
+ } catch (switchError) {
607
+ // Silently handle expected errors (invalid sessions, timeouts, network issues)
608
+ if ((0, _errorHandlers.isInvalidSessionError)(switchError)) {
609
+ await storage.removeItem(storageKeys.activeSessionId);
610
+ updateSessionsRef.current(validSessions.filter(session => session.sessionId !== storedActiveSessionId), {
611
+ merge: false
612
+ });
613
+ // Don't log expected session errors during restoration
614
+ } else if ((0, _errorHandlers.isTimeoutOrNetworkError)(switchError)) {
615
+ // Timeout/network error - non-critical, don't block
616
+ if (__DEV__) {
617
+ _core.logger.debug('Active session validation timeout (expected when offline)', {
618
+ component: 'OxyContext',
619
+ method: 'restoreStoredSession'
620
+ }, switchError);
621
+ }
622
+ } else {
623
+ // Only log unexpected errors
624
+ logger('Active session validation error', switchError);
625
+ }
626
+ }
627
+ }
628
+ return false;
629
+ }, [logger, oxyServices, storage, storageKeys.activeSessionId, storageKeys.sessionIds]);
630
+
631
+ // Cold boot — the single, ordered, short-circuit session-recovery sequence,
632
+ // consuming the SAME `runColdBoot` core primitive as `WebOxyProvider`. The
633
+ // FIRST step that yields a session wins; every later step is skipped. Each
634
+ // web-only step is gated by `isWebBrowser()`, so on native ONLY
635
+ // `stored-session` runs.
636
+ //
637
+ // Order (web): redirect callback → FedCM silent → silent iframe → refresh
638
+ // cookie → stored session. Order (native): stored session only.
454
639
  const restoreSessionsFromStorage = (0, _react.useCallback)(async () => {
455
640
  if (!storage) {
456
641
  return;
457
642
  }
458
643
  setTokenReady(false);
644
+ const commitWebSession = handleWebSSOSessionRef.current;
645
+ const silentKey = silentColdBootKey(oxyServices);
646
+ const fedcmSupported = (0, _useWebSSO.isWebBrowser)() && oxyServices.isFedCMSupported?.() === true;
459
647
  try {
460
- // Web cold-boot fast path: restore the active session from the secure
461
- // httpOnly refresh cookie before the bearer-protected stored-session
462
- // validation (which 401s on a hard reload). On success we are signed in
463
- // from the cookie alone no FedCM needed. On failure we fall through to
464
- // the existing stored-session flow below; nothing is cleared.
465
- if (await restoreViaRefreshCookie()) {
466
- return;
467
- }
468
- const storedSessionIdsJson = await storage.getItem(storageKeys.sessionIds);
469
- const storedSessionIds = storedSessionIdsJson ? JSON.parse(storedSessionIdsJson) : [];
470
- const storedActiveSessionId = await storage.getItem(storageKeys.activeSessionId);
471
- let validSessions = [];
472
- if (storedSessionIds.length > 0) {
473
- // Validate all sessions in parallel (with 8s timeout per session) to avoid
474
- // sequential blocking that freezes the app on startup
475
- const VALIDATION_TIMEOUT = 8000;
476
- const results = await Promise.allSettled(storedSessionIds.map(async sessionId => {
477
- const timeoutPromise = new Promise(resolve => setTimeout(() => resolve(null), VALIDATION_TIMEOUT));
478
- const validationPromise = oxyServices.validateSession(sessionId, {
479
- useHeaderValidation: true
480
- }).catch(validationError => {
481
- if (!(0, _errorHandlers.isInvalidSessionError)(validationError) && !(0, _errorHandlers.isTimeoutOrNetworkError)(validationError)) {
482
- logger('Session validation failed during init', validationError);
483
- } else if (__DEV__ && (0, _errorHandlers.isTimeoutOrNetworkError)(validationError)) {
484
- _core.logger.debug('Session validation timeout (expected when offline)', {
485
- component: 'OxyContext',
486
- method: 'restoreSessionsFromStorage'
487
- }, validationError);
488
- }
489
- return null;
490
- });
491
- return Promise.race([validationPromise, timeoutPromise]).then(validation => {
492
- if (validation?.valid && validation.user) {
493
- const now = new Date();
648
+ const outcome = await (0, _core.runColdBoot)({
649
+ steps: [{
650
+ // 1) Redirect callback wins: a popup/redirect sign-in just landed
651
+ // back on this page with `access_token`/`session_id` query params.
652
+ // `handleAuthCallback` plants the token but returns a PLACEHOLDER
653
+ // user (empty id), so we hydrate the REAL user via `getCurrentUser`
654
+ // and commit through `handleWebSSOSession` before claiming a
655
+ // session — never expose a placeholder user (R4).
656
+ id: 'redirect',
657
+ enabled: () => (0, _useWebSSO.isWebBrowser)(),
658
+ run: async () => {
659
+ const callbackSession = oxyServices.handleAuthCallback?.();
660
+ if (!callbackSession || !commitWebSession) {
494
661
  return {
495
- sessionId,
496
- deviceId: '',
497
- expiresAt: new Date(now.getTime() + 7 * 24 * 60 * 60 * 1000).toISOString(),
498
- lastActive: now.toISOString(),
499
- userId: validation.user.id?.toString() ?? '',
500
- isCurrent: sessionId === storedActiveSessionId
662
+ kind: 'skip'
501
663
  };
502
664
  }
503
- return null;
504
- });
505
- }));
506
- validSessions = results.filter(r => r.status === 'fulfilled').map(r => r.value).filter(s => s !== null);
507
-
508
- // Always persist validated sessions to storage (even empty list)
509
- // to clear stale/expired session IDs that would cause 401 loops on restart
510
- updateSessionsRef.current(validSessions, {
511
- merge: false
512
- });
513
- }
514
- if (storedActiveSessionId) {
515
- try {
516
- await switchSessionRef.current(storedActiveSessionId);
517
- } catch (switchError) {
518
- // Silently handle expected errors (invalid sessions, timeouts, network issues)
519
- if ((0, _errorHandlers.isInvalidSessionError)(switchError)) {
520
- await storage.removeItem(storageKeys.activeSessionId);
521
- updateSessionsRef.current(validSessions.filter(session => session.sessionId !== storedActiveSessionId), {
522
- merge: false
665
+ const fullUser = await oxyServices.getCurrentUser();
666
+ await commitWebSession({
667
+ ...callbackSession,
668
+ user: fullUser
523
669
  });
524
- // Don't log expected session errors during restoration
525
- } else if ((0, _errorHandlers.isTimeoutOrNetworkError)(switchError)) {
526
- // Timeout/network error - non-critical, don't block
527
- if (__DEV__) {
528
- _core.logger.debug('Active session validation timeout (expected when offline)', {
529
- component: 'OxyContext',
530
- method: 'restoreSessionsFromStorage'
531
- }, switchError);
670
+ return {
671
+ kind: 'session',
672
+ session: true
673
+ };
674
+ }
675
+ }, {
676
+ // 2) FedCM silent reauthn (Chrome). `silentSignInWithFedCM` plants
677
+ // the access token internally; we commit the returned session via
678
+ // `handleWebSSOSession`. Guarded so it fires at most once per page
679
+ // load across remounts.
680
+ id: 'fedcm-silent',
681
+ enabled: () => fedcmSupported && !servicesSilentAttempted.has(silentKey),
682
+ run: async () => {
683
+ servicesSilentAttempted.add(silentKey);
684
+ const session = await oxyServices.silentSignInWithFedCM?.();
685
+ if (!session || !commitWebSession) {
686
+ return {
687
+ kind: 'skip'
688
+ };
532
689
  }
533
- } else {
534
- // Only log unexpected errors
535
- logger('Active session validation error', switchError);
690
+ await commitWebSession(session);
691
+ return {
692
+ kind: 'session',
693
+ session: true
694
+ };
695
+ }
696
+ }, {
697
+ // 3) Silent first-party iframe ({authWebUrl}/auth/silent) for
698
+ // browsers without FedCM (Safari / Firefox). After auto-detection
699
+ // `authWebUrl` is `auth.<rp-apex>`, so the iframe + its
700
+ // `fedcm_session` cookie are first-party with the RP. Shares the
701
+ // one-shot guard with the FedCM step.
702
+ id: 'silent-iframe',
703
+ enabled: () => (0, _useWebSSO.isWebBrowser)() && oxyServices.isFedCMSupported?.() !== true && !servicesSilentAttempted.has(silentKey),
704
+ run: async () => {
705
+ servicesSilentAttempted.add(silentKey);
706
+ const session = await oxyServices.silentSignIn?.();
707
+ if (!session || !commitWebSession) {
708
+ return {
709
+ kind: 'skip'
710
+ };
711
+ }
712
+ await commitWebSession(session);
713
+ return {
714
+ kind: 'session',
715
+ session: true
716
+ };
717
+ }
718
+ }, {
719
+ // 4) Refresh-cookie restore (same-site only). On `*.oxy.so` the
720
+ // httpOnly `oxy_rt_${n}` cookies ride along and resurrect every
721
+ // device-local slot. On a cross-domain RP (mention.earth, …) the
722
+ // cookie is `Domain=oxy.so` so it never reaches `api.<apex>` —
723
+ // `refreshAllSessions` returns `{accounts:[]}` and this skips.
724
+ // That is correct; there is deliberately NO `api.<apex>` bridge.
725
+ id: 'cookie-restore',
726
+ enabled: () => (0, _useWebSSO.isWebBrowser)(),
727
+ run: async () => {
728
+ const restored = await restoreViaRefreshCookie();
729
+ return restored ? {
730
+ kind: 'session',
731
+ session: true
732
+ } : {
733
+ kind: 'skip'
734
+ };
735
+ }
736
+ }, {
737
+ // 5) Stored-session bearer restore. NO `enabled` gate — runs on ALL
738
+ // platforms. This is native's ONLY restore path (every web-only
739
+ // step above is disabled off-browser).
740
+ id: 'stored-session',
741
+ run: async () => {
742
+ const restored = await restoreStoredSession();
743
+ return restored ? {
744
+ kind: 'session',
745
+ session: true
746
+ } : {
747
+ kind: 'skip'
748
+ };
749
+ }
750
+ }],
751
+ onStepError: (id, error) => {
752
+ if (__DEV__) {
753
+ _core.logger.debug(`Cold-boot step "${id}" errored (non-fatal, falling through)`, {
754
+ component: 'OxyContext',
755
+ method: 'restoreSessionsFromStorage'
756
+ }, error);
536
757
  }
537
758
  }
759
+ });
760
+ if (__DEV__ && outcome.kind === 'session') {
761
+ _core.logger.debug(`Cold boot recovered a session via "${outcome.via}"`, {
762
+ component: 'OxyContext',
763
+ method: 'restoreSessionsFromStorage'
764
+ });
538
765
  }
539
766
  } catch (error) {
540
767
  if (__DEV__) {
@@ -547,7 +774,7 @@ const OxyProvider = ({
547
774
  } finally {
548
775
  setTokenReady(true);
549
776
  }
550
- }, [logger, oxyServices, storage, storageKeys.activeSessionId, storageKeys.sessionIds, restoreViaRefreshCookie]);
777
+ }, [oxyServices, storage, restoreViaRefreshCookie, restoreStoredSession]);
551
778
  (0, _react.useEffect)(() => {
552
779
  if (!storage || initialized) {
553
780
  return;
@@ -622,7 +849,21 @@ const OxyProvider = ({
622
849
  onAuthStateChange?.(fullUser);
623
850
  }, [oxyServices, updateSessions, setActiveSessionId, loginSuccess, onAuthStateChange, persistSessionDurably]);
624
851
 
625
- // Enable web SSO only after local storage check completes and no user found
852
+ // Expose `handleWebSSOSession` to the cold-boot FedCM/iframe/redirect steps,
853
+ // which reference it through a ref because they are declared above this
854
+ // callback. Assigned synchronously on every render so the ref is populated
855
+ // before the cold-boot effect (gated on `storage`/`initialized`) can fire.
856
+ handleWebSSOSessionRef.current = handleWebSSOSession;
857
+
858
+ // Cross-domain silent SSO is now owned by the `fedcm-silent` / `silent-iframe`
859
+ // cold-boot steps above (the ordered `runColdBoot` sequence). `useWebSSO`
860
+ // remains mounted for its module-level run-once guard and its interactive
861
+ // FedCM helpers, and as a bounded post-boot safety net: it can fire at most
862
+ // once per page load (its own module guard), and only AFTER cold boot has
863
+ // finished (`tokenReady`) with no user recovered. We deliberately keep
864
+ // `shouldTryWebSSO` as `tokenReady && !user && initialized` — it is NOT
865
+ // loosened; cold boot runs while `tokenReady` is false, so this never races
866
+ // the cold-boot silent step.
626
867
  const shouldTryWebSSO = (0, _useWebSSO.isWebBrowser)() && tokenReady && !user && initialized;
627
868
  (0, _useWebSSO.useWebSSO)({
628
869
  oxyServices,
@@ -642,8 +883,16 @@ const OxyProvider = ({
642
883
  // If session is gone (cleared/logged out), clear local session too
643
884
  const lastIdPCheckRef = (0, _react.useRef)(0);
644
885
  const pendingIdPCleanupRef = (0, _react.useRef)(null);
886
+
887
+ // Use the RESOLVED IdP origin (the auto-detected `auth.<rp-apex>` planted on
888
+ // the instance config), not the raw `authWebUrl` prop — on a cross-domain RP
889
+ // the prop is undefined but the instance was constructed with the detected
890
+ // value, so the check must target the same first-party IdP the cold-boot
891
+ // iframe used.
892
+ const resolvedAuthWebUrl = oxyServices.config?.authWebUrl;
645
893
  (0, _react.useEffect)(() => {
646
894
  if (!(0, _useWebSSO.isWebBrowser)() || !user || !initialized) return;
895
+ const idpOrigin = resolvedAuthWebUrl || 'https://auth.oxy.so';
647
896
  const checkIdPSession = () => {
648
897
  // Debounce: check at most once per 30 seconds
649
898
  const now = Date.now();
@@ -656,7 +905,6 @@ const OxyProvider = ({
656
905
  // Load hidden iframe to check IdP session via postMessage
657
906
  const iframe = document.createElement('iframe');
658
907
  iframe.style.cssText = 'display:none;width:0;height:0;border:0';
659
- const idpOrigin = authWebUrl || 'https://auth.oxy.so';
660
908
  iframe.src = `${idpOrigin}/auth/session-check?client_id=${encodeURIComponent(window.location.origin)}`;
661
909
  let cleaned = false;
662
910
  const cleanup = () => {
@@ -670,8 +918,15 @@ const OxyProvider = ({
670
918
  if (event.data?.type !== 'oxy-session-check') return;
671
919
  cleanup();
672
920
  if (!event.data.hasSession) {
673
- _bloom.toast.info('Your session has ended. Please sign in again.');
674
- await clearSessionState();
921
+ // Only a SAME-SITE, first-party IdP answer is authoritative enough to
922
+ // force a local sign-out. On a cross-site / undetermined IdP the
923
+ // "no session" answer must never clear local state (a third-party
924
+ // can't be trusted to end this app's session). Surface the toast in
925
+ // both cases, but gate the destructive `clearSessionState()`.
926
+ if (isSameSiteIdP(idpOrigin)) {
927
+ _bloom.toast.info('Your session has ended. Please sign in again.');
928
+ await clearSessionState();
929
+ }
675
930
  }
676
931
  };
677
932
  window.addEventListener('message', handleMessage);
@@ -690,7 +945,7 @@ const OxyProvider = ({
690
945
  pendingIdPCleanupRef.current?.();
691
946
  pendingIdPCleanupRef.current = null;
692
947
  };
693
- }, [user, initialized, clearSessionState, authWebUrl]);
948
+ }, [user, initialized, clearSessionState, resolvedAuthWebUrl]);
694
949
  const activeSession = activeSessionId ? sessions.find(session => session.sessionId === activeSessionId) : undefined;
695
950
  const currentDeviceId = activeSession?.deviceId ?? null;
696
951
  const userId = user?.id;