@oxyhq/core 5.4.3 → 6.0.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.
Files changed (186) hide show
  1. package/dist/cjs/.tsbuildinfo +1 -1
  2. package/dist/cjs/HttpService.js +6 -3
  3. package/dist/cjs/OxyServices.base.js +7 -102
  4. package/dist/cjs/boot/coldBootV2.js +350 -0
  5. package/dist/cjs/boot/deviceBootReturn.js +152 -0
  6. package/dist/cjs/crypto/keyManager.js +95 -0
  7. package/dist/cjs/i18n/locales/en-US.json +13 -1
  8. package/dist/cjs/i18n/locales/es-ES.json +13 -1
  9. package/dist/cjs/i18n/locales/locales/en-US.json +13 -1
  10. package/dist/cjs/i18n/locales/locales/es-ES.json +13 -1
  11. package/dist/cjs/index.js +47 -43
  12. package/dist/cjs/mixins/OxyServices.accounts.js +6 -13
  13. package/dist/cjs/mixins/OxyServices.auth.js +66 -201
  14. package/dist/cjs/mixins/OxyServices.authorizedApps.js +38 -0
  15. package/dist/cjs/mixins/OxyServices.deviceBoot.js +119 -0
  16. package/dist/cjs/mixins/index.js +13 -17
  17. package/dist/cjs/session/SessionClient.js +44 -2
  18. package/dist/cjs/session/authStateStore.js +284 -0
  19. package/dist/cjs/session/createSessionClient.js +8 -2
  20. package/dist/cjs/session/refresh.js +264 -0
  21. package/dist/cjs/utils/accountUtils.js +1 -55
  22. package/dist/cjs/utils/authWebUrl.js +6 -15
  23. package/dist/cjs/utils/fapiAutoDetect.js +16 -64
  24. package/dist/cjs/utils/platform.js +19 -0
  25. package/dist/cjs/utils/ssoBounce.js +15 -340
  26. package/dist/cjs/utils/validationUtils.js +57 -0
  27. package/dist/esm/.tsbuildinfo +1 -1
  28. package/dist/esm/HttpService.js +6 -3
  29. package/dist/esm/OxyServices.base.js +7 -102
  30. package/dist/esm/boot/coldBootV2.js +344 -0
  31. package/dist/esm/boot/deviceBootReturn.js +146 -0
  32. package/dist/esm/crypto/keyManager.js +95 -0
  33. package/dist/esm/i18n/locales/en-US.json +13 -1
  34. package/dist/esm/i18n/locales/es-ES.json +13 -1
  35. package/dist/esm/i18n/locales/locales/en-US.json +13 -1
  36. package/dist/esm/i18n/locales/locales/es-ES.json +13 -1
  37. package/dist/esm/index.js +28 -18
  38. package/dist/esm/mixins/OxyServices.accounts.js +6 -13
  39. package/dist/esm/mixins/OxyServices.auth.js +66 -201
  40. package/dist/esm/mixins/OxyServices.authorizedApps.js +35 -0
  41. package/dist/esm/mixins/OxyServices.deviceBoot.js +116 -0
  42. package/dist/esm/mixins/index.js +13 -17
  43. package/dist/esm/session/SessionClient.js +44 -2
  44. package/dist/esm/session/authStateStore.js +278 -0
  45. package/dist/esm/session/createSessionClient.js +8 -2
  46. package/dist/esm/session/refresh.js +257 -0
  47. package/dist/esm/utils/accountUtils.js +0 -53
  48. package/dist/esm/utils/authWebUrl.js +6 -14
  49. package/dist/esm/utils/fapiAutoDetect.js +16 -63
  50. package/dist/esm/utils/platform.js +18 -0
  51. package/dist/esm/utils/ssoBounce.js +14 -324
  52. package/dist/esm/utils/validationUtils.js +56 -0
  53. package/dist/types/.tsbuildinfo +1 -1
  54. package/dist/types/HttpService.d.ts +13 -0
  55. package/dist/types/OxyServices.base.d.ts +0 -52
  56. package/dist/types/OxyServices.d.ts +0 -25
  57. package/dist/types/boot/coldBootV2.d.ts +76 -0
  58. package/dist/types/boot/deviceBootReturn.d.ts +83 -0
  59. package/dist/types/crypto/keyManager.d.ts +21 -0
  60. package/dist/types/index.d.ts +16 -21
  61. package/dist/types/mixins/OxyServices.accounts.d.ts +0 -2
  62. package/dist/types/mixins/OxyServices.analytics.d.ts +0 -2
  63. package/dist/types/mixins/OxyServices.appData.d.ts +0 -2
  64. package/dist/types/mixins/OxyServices.assets.d.ts +0 -2
  65. package/dist/types/mixins/OxyServices.auth.d.ts +35 -77
  66. package/dist/types/mixins/{OxyServices.redirect.d.ts → OxyServices.authorizedApps.d.ts} +35 -33
  67. package/dist/types/mixins/OxyServices.civic.d.ts +0 -2
  68. package/dist/types/mixins/OxyServices.connectedApps.d.ts +0 -2
  69. package/dist/types/mixins/OxyServices.contacts.d.ts +0 -2
  70. package/dist/types/mixins/OxyServices.deviceBoot.d.ts +110 -0
  71. package/dist/types/mixins/OxyServices.devices.d.ts +0 -2
  72. package/dist/types/mixins/OxyServices.features.d.ts +0 -2
  73. package/dist/types/mixins/OxyServices.identity.d.ts +0 -2
  74. package/dist/types/mixins/OxyServices.language.d.ts +0 -2
  75. package/dist/types/mixins/OxyServices.links.d.ts +0 -2
  76. package/dist/types/mixins/OxyServices.location.d.ts +0 -2
  77. package/dist/types/mixins/OxyServices.nodes.d.ts +0 -2
  78. package/dist/types/mixins/OxyServices.payment.d.ts +0 -2
  79. package/dist/types/mixins/OxyServices.privacy.d.ts +0 -2
  80. package/dist/types/mixins/OxyServices.reputation.d.ts +0 -2
  81. package/dist/types/mixins/OxyServices.security.d.ts +0 -2
  82. package/dist/types/mixins/OxyServices.topics.d.ts +0 -2
  83. package/dist/types/mixins/OxyServices.user.d.ts +0 -2
  84. package/dist/types/mixins/OxyServices.utility.d.ts +0 -2
  85. package/dist/types/mixins/index.d.ts +6 -9
  86. package/dist/types/models/interfaces.d.ts +0 -67
  87. package/dist/types/session/SessionClient.d.ts +38 -1
  88. package/dist/types/session/authStateStore.d.ts +119 -0
  89. package/dist/types/session/createSessionClient.d.ts +8 -1
  90. package/dist/types/session/refresh.d.ts +93 -0
  91. package/dist/types/utils/accountUtils.d.ts +0 -14
  92. package/dist/types/utils/authWebUrl.d.ts +6 -12
  93. package/dist/types/utils/fapiAutoDetect.d.ts +15 -38
  94. package/dist/types/utils/platform.d.ts +14 -0
  95. package/dist/types/utils/ssoBounce.d.ts +14 -262
  96. package/dist/types/utils/validationUtils.d.ts +15 -0
  97. package/package.json +2 -2
  98. package/src/HttpService.ts +19 -3
  99. package/src/OxyServices.base.ts +7 -112
  100. package/src/OxyServices.ts +0 -38
  101. package/src/boot/__tests__/coldBootV2.test.ts +317 -0
  102. package/src/boot/__tests__/deviceBootReturn.test.ts +158 -0
  103. package/src/boot/coldBootV2.ts +426 -0
  104. package/src/boot/deviceBootReturn.ts +195 -0
  105. package/src/crypto/__tests__/sharedDeviceToken.test.ts +24 -0
  106. package/src/crypto/keyManager.ts +101 -0
  107. package/src/i18n/locales/en-US.json +13 -1
  108. package/src/i18n/locales/es-ES.json +13 -1
  109. package/src/index.ts +78 -64
  110. package/src/mixins/OxyServices.accounts.ts +6 -13
  111. package/src/mixins/OxyServices.auth.ts +78 -253
  112. package/src/mixins/OxyServices.authorizedApps.ts +75 -0
  113. package/src/mixins/OxyServices.deviceBoot.ts +146 -0
  114. package/src/mixins/__tests__/OxyServices.deviceBoot.test.ts +107 -0
  115. package/src/mixins/__tests__/accounts.test.ts +17 -44
  116. package/src/mixins/__tests__/authorizedApps.test.ts +63 -0
  117. package/src/mixins/__tests__/passwordSignIn.test.ts +91 -0
  118. package/src/mixins/index.ts +16 -22
  119. package/src/models/interfaces.ts +0 -79
  120. package/src/session/SessionClient.ts +69 -3
  121. package/src/session/__tests__/SessionClient.additive.test.ts +92 -0
  122. package/src/session/__tests__/SessionClient.rest.test.ts +25 -0
  123. package/src/session/__tests__/SessionClient.socketFactory.test.ts +79 -0
  124. package/src/session/__tests__/SessionClient.state.test.ts +18 -5
  125. package/src/session/__tests__/authStateStore.test.ts +209 -0
  126. package/src/session/__tests__/refresh.test.ts +256 -0
  127. package/src/session/authStateStore.ts +335 -0
  128. package/src/session/createSessionClient.ts +9 -1
  129. package/src/session/refresh.ts +334 -0
  130. package/src/utils/__tests__/authWebUrl.test.ts +5 -29
  131. package/src/utils/__tests__/fapiAutoDetect.test.ts +5 -126
  132. package/src/utils/__tests__/validationUtils.test.ts +30 -0
  133. package/src/utils/accountUtils.ts +0 -62
  134. package/src/utils/authWebUrl.ts +6 -15
  135. package/src/utils/fapiAutoDetect.ts +16 -60
  136. package/src/utils/platform.ts +21 -0
  137. package/src/utils/ssoBounce.ts +14 -371
  138. package/src/utils/validationUtils.ts +62 -0
  139. package/dist/cjs/AuthManager.js +0 -1110
  140. package/dist/cjs/AuthManagerTypes.js +0 -13
  141. package/dist/cjs/CrossDomainAuth.js +0 -206
  142. package/dist/cjs/mixins/OxyServices.fedcm.js +0 -823
  143. package/dist/cjs/mixins/OxyServices.redirect.js +0 -95
  144. package/dist/cjs/mixins/OxyServices.silent.js +0 -204
  145. package/dist/cjs/mixins/OxyServices.sso.js +0 -208
  146. package/dist/cjs/utils/ssoEstablish.js +0 -110
  147. package/dist/cjs/utils/ssoReturn.js +0 -267
  148. package/dist/esm/AuthManager.js +0 -1105
  149. package/dist/esm/AuthManagerTypes.js +0 -12
  150. package/dist/esm/CrossDomainAuth.js +0 -201
  151. package/dist/esm/mixins/OxyServices.fedcm.js +0 -821
  152. package/dist/esm/mixins/OxyServices.redirect.js +0 -92
  153. package/dist/esm/mixins/OxyServices.silent.js +0 -202
  154. package/dist/esm/mixins/OxyServices.sso.js +0 -204
  155. package/dist/esm/utils/ssoEstablish.js +0 -107
  156. package/dist/esm/utils/ssoReturn.js +0 -263
  157. package/dist/types/AuthManager.d.ts +0 -380
  158. package/dist/types/AuthManagerTypes.d.ts +0 -81
  159. package/dist/types/CrossDomainAuth.d.ts +0 -164
  160. package/dist/types/mixins/OxyServices.fedcm.d.ts +0 -331
  161. package/dist/types/mixins/OxyServices.silent.d.ts +0 -132
  162. package/dist/types/mixins/OxyServices.sso.d.ts +0 -138
  163. package/dist/types/utils/ssoEstablish.d.ts +0 -85
  164. package/dist/types/utils/ssoReturn.d.ts +0 -146
  165. package/src/AuthManager.ts +0 -1269
  166. package/src/AuthManagerTypes.ts +0 -86
  167. package/src/CrossDomainAuth.ts +0 -243
  168. package/src/__tests__/authManager.cookiePath.test.ts +0 -390
  169. package/src/__tests__/authManager.security.test.ts +0 -377
  170. package/src/__tests__/crossDomainAuth.test.ts +0 -116
  171. package/src/__tests__/establishDeviceRefreshSlot.test.ts +0 -221
  172. package/src/mixins/OxyServices.fedcm.ts +0 -1026
  173. package/src/mixins/OxyServices.redirect.ts +0 -122
  174. package/src/mixins/OxyServices.silent.ts +0 -272
  175. package/src/mixins/OxyServices.sso.ts +0 -261
  176. package/src/mixins/__tests__/constructorAuthWebUrl.test.ts +0 -85
  177. package/src/mixins/__tests__/fedcm.test.ts +0 -667
  178. package/src/mixins/__tests__/sessionBaseUrl.test.ts +0 -61
  179. package/src/mixins/__tests__/silent.test.ts +0 -102
  180. package/src/mixins/__tests__/sso.test.ts +0 -228
  181. package/src/utils/__tests__/consumeSsoReturn.test.ts +0 -816
  182. package/src/utils/__tests__/ssoBounce.test.ts +0 -219
  183. package/src/utils/__tests__/ssoEstablish.test.ts +0 -204
  184. package/src/utils/__tests__/ssoReturn.test.ts +0 -251
  185. package/src/utils/ssoEstablish.ts +0 -174
  186. package/src/utils/ssoReturn.ts +0 -372
@@ -91,6 +91,11 @@ const STORAGE_KEYS = {
91
91
  SHARED_PUBLIC_KEY: 'oxy_shared_identity_public_key',
92
92
  SHARED_SESSION_TOKEN: 'oxy_shared_session_token',
93
93
  SHARED_SESSION_ID: 'oxy_shared_session_id',
94
+ // Opaque device-attribution token, shared across all Oxy apps on one device
95
+ // so they all resolve to a SINGLE server-side DeviceSession (device-first
96
+ // session model). Add-only: it never carries session state, only attributes
97
+ // a newly-credentialed session to the shared device set.
98
+ SHARED_DEVICE_TOKEN: 'oxy_shared_device_token',
94
99
  } as const;
95
100
 
96
101
  /**
@@ -643,6 +648,102 @@ export class KeyManager {
643
648
  }
644
649
  }
645
650
 
651
+ /**
652
+ * Store the opaque device-attribution token in the SHARED keychain so every
653
+ * Oxy app on this device reads the SAME token and therefore resolves to one
654
+ * server-side DeviceSession.
655
+ *
656
+ * Mirrors the shared-session storage options exactly (iOS keychain access
657
+ * group `group.so.oxy.shared`; Android shared secure store). Native-only —
658
+ * a no-op on web (the shared keychain does not exist there; web persists its
659
+ * deviceToken in the per-origin {@link AuthStateStore} instead).
660
+ */
661
+ static async setSharedDeviceToken(deviceToken: string): Promise<void> {
662
+ if (isWebPlatform()) {
663
+ return; // Not supported on web
664
+ }
665
+
666
+ try {
667
+ const store = await initSecureStore();
668
+
669
+ if (isIOS()) {
670
+ const opts: OxySecureStoreOptions = {
671
+ keychainAccessible: store.WHEN_UNLOCKED,
672
+ keychainAccessGroup: IOS_KEYCHAIN_GROUP,
673
+ };
674
+ await store.setItemAsync(STORAGE_KEYS.SHARED_DEVICE_TOKEN, deviceToken, opts);
675
+ } else if (isAndroid()) {
676
+ await store.setItemAsync(STORAGE_KEYS.SHARED_DEVICE_TOKEN, deviceToken);
677
+ }
678
+
679
+ if (isDev()) {
680
+ logger.debug('Shared device token stored successfully', { component: 'KeyManager' });
681
+ }
682
+ } catch (error) {
683
+ if (isDev()) {
684
+ logger.error('Failed to store shared device token', error, { component: 'KeyManager' });
685
+ }
686
+ throw error;
687
+ }
688
+ }
689
+
690
+ /**
691
+ * Read the shared device-attribution token, or `null` when none is set (or
692
+ * on web). Mirrors {@link getSharedSession}'s keychain-access-group read.
693
+ */
694
+ static async getSharedDeviceToken(): Promise<string | null> {
695
+ if (isWebPlatform()) {
696
+ return null;
697
+ }
698
+
699
+ try {
700
+ const store = await initSecureStore();
701
+
702
+ if (isIOS()) {
703
+ const opts: OxySecureStoreOptions = { keychainAccessGroup: IOS_KEYCHAIN_GROUP };
704
+ return await store.getItemAsync(STORAGE_KEYS.SHARED_DEVICE_TOKEN, opts);
705
+ }
706
+ if (isAndroid()) {
707
+ return await store.getItemAsync(STORAGE_KEYS.SHARED_DEVICE_TOKEN);
708
+ }
709
+ return null;
710
+ } catch (error) {
711
+ if (isDev()) {
712
+ logger.warn('Failed to get shared device token', { component: 'KeyManager' }, error);
713
+ }
714
+ return null;
715
+ }
716
+ }
717
+
718
+ /**
719
+ * Delete the shared device-attribution token (device signout-all). Best-effort:
720
+ * a keychain failure is logged, not thrown, so it cannot block a sign-out.
721
+ */
722
+ static async clearSharedDeviceToken(): Promise<void> {
723
+ if (isWebPlatform()) {
724
+ return;
725
+ }
726
+
727
+ try {
728
+ const store = await initSecureStore();
729
+
730
+ if (isIOS()) {
731
+ const opts: OxySecureStoreOptions = { keychainAccessGroup: IOS_KEYCHAIN_GROUP };
732
+ await store.deleteItemAsync(STORAGE_KEYS.SHARED_DEVICE_TOKEN, opts);
733
+ } else if (isAndroid()) {
734
+ await store.deleteItemAsync(STORAGE_KEYS.SHARED_DEVICE_TOKEN);
735
+ }
736
+
737
+ if (isDev()) {
738
+ logger.debug('Shared device token cleared successfully', { component: 'KeyManager' });
739
+ }
740
+ } catch (error) {
741
+ if (isDev()) {
742
+ logger.error('Failed to clear shared device token', error, { component: 'KeyManager' });
743
+ }
744
+ }
745
+ }
746
+
646
747
  // ==================== END SHARED IDENTITY METHODS ====================
647
748
 
648
749
  /**
@@ -2,6 +2,13 @@
2
2
  "signin": {
3
3
  "title": "Sign In",
4
4
  "subtitle": "Sign in to continue your journey",
5
+ "chooser": {
6
+ "title": "Choose an account",
7
+ "subtitle": "Continue as an account below, or use another.",
8
+ "signedIn": "Signed in",
9
+ "useAnother": "Use another account",
10
+ "continueAs": "Continue as {{name}}"
11
+ },
5
12
  "addAccountTitle": "Add Another Account",
6
13
  "addAccountSubtitle": "Sign in with another account",
7
14
  "username": {
@@ -602,6 +609,7 @@
602
609
  "editProfile": {
603
610
  "title": "Edit Profile",
604
611
  "subtitle": "Manage your profile and preferences",
612
+ "notSet": "Not set",
605
613
  "sections": {
606
614
  "profilePicture": "Profile Picture",
607
615
  "basicInfo": "Basic Information",
@@ -610,6 +618,9 @@
610
618
  "security": "Security"
611
619
  },
612
620
  "items": {
621
+ "avatar": {
622
+ "subtitle": "Update your profile photo"
623
+ },
613
624
  "displayName": {
614
625
  "title": "Display Name",
615
626
  "subtitle": "This is how your name will appear to others",
@@ -617,7 +628,8 @@
617
628
  "firstName": "First Name",
618
629
  "firstNamePlaceholder": "Enter first name",
619
630
  "lastName": "Last Name",
620
- "lastNamePlaceholder": "Enter last name (optional)"
631
+ "lastNamePlaceholder": "Enter last name (optional)",
632
+ "invalidChars": "Use letters and spaces only"
621
633
  },
622
634
  "username": {
623
635
  "title": "Username",
@@ -2,6 +2,13 @@
2
2
  "signin": {
3
3
  "title": "Iniciar sesión",
4
4
  "subtitle": "Inicia sesión para continuar",
5
+ "chooser": {
6
+ "title": "Elige una cuenta",
7
+ "subtitle": "Continúa con una de tus cuentas o usa otra.",
8
+ "signedIn": "Sesión activa",
9
+ "useAnother": "Usar otra cuenta",
10
+ "continueAs": "Continuar como {{name}}"
11
+ },
5
12
  "addAccountTitle": "Agregar otra cuenta",
6
13
  "addAccountSubtitle": "Inicia sesión con otra cuenta",
7
14
  "username": {
@@ -152,6 +159,7 @@
152
159
  "editProfile": {
153
160
  "title": "Editar perfil",
154
161
  "subtitle": "Gestiona tu perfil y preferencias",
162
+ "notSet": "Sin definir",
155
163
  "sections": {
156
164
  "profilePicture": "Foto de perfil",
157
165
  "basicInfo": "Información básica",
@@ -160,6 +168,9 @@
160
168
  "security": "Seguridad"
161
169
  },
162
170
  "items": {
171
+ "avatar": {
172
+ "subtitle": "Actualiza tu foto de perfil"
173
+ },
163
174
  "displayName": {
164
175
  "title": "Nombre para mostrar",
165
176
  "subtitle": "Así aparecerá tu nombre para los demás",
@@ -167,7 +178,8 @@
167
178
  "firstName": "Nombre",
168
179
  "firstNamePlaceholder": "Introduce tu nombre",
169
180
  "lastName": "Apellido",
170
- "lastNamePlaceholder": "Introduce tu apellido (opcional)"
181
+ "lastNamePlaceholder": "Introduce tu apellido (opcional)",
182
+ "invalidChars": "Usa solo letras y espacios"
171
183
  },
172
184
  "username": {
173
185
  "title": "Usuario",
package/src/index.ts CHANGED
@@ -34,25 +34,9 @@ export type { AuthRefreshReason, AuthRefreshHandler } from './HttpService';
34
34
  // ---------------------------------------------------------------------------
35
35
  // Authentication
36
36
  // ---------------------------------------------------------------------------
37
- export { AuthManager, createAuthManager } from './AuthManager';
38
- export type {
39
- StorageAdapter,
40
- AuthStateChangeCallback,
41
- AuthMethod,
42
- AuthManagerConfig,
43
- } from './AuthManager';
44
- export type {
45
- AuthManagerAccount,
46
- RestoreFromCookiesResult,
47
- RestoreFromCookiesOptions,
48
- SwitchAuthuserResult,
49
- } from './AuthManagerTypes';
50
-
51
- export { CrossDomainAuth, createCrossDomainAuth } from './CrossDomainAuth';
52
- export type { CrossDomainAuthOptions } from './CrossDomainAuth';
53
- export type { FedCMAuthOptions, FedCMConfig, AuthorizedApp } from './mixins/OxyServices.fedcm';
54
- export type { SilentAuthOptions } from './mixins/OxyServices.silent';
55
- export type { RedirectAuthOptions } from './mixins/OxyServices.redirect';
37
+ // Legacy "Connected apps" management surface (list/revoke FedCM authorization
38
+ // grants). The FedCM sign-in machinery was removed in the device-first cutover.
39
+ export type { AuthorizedApp } from './mixins/OxyServices.authorizedApps';
56
40
  export { ServiceCredentialMismatchError } from './mixins/OxyServices.auth';
57
41
  export type { ServiceTokenResponse } from './mixins/OxyServices.auth';
58
42
  // "Sign in with Oxy" — handoff (Workstream C)
@@ -245,16 +229,6 @@ export type {
245
229
  SessionLoginResponse,
246
230
  } from './models/session';
247
231
 
248
- // ---------------------------------------------------------------------------
249
- // Multi-account refresh-all (Google-style)
250
- // ---------------------------------------------------------------------------
251
- export type {
252
- RefreshAllResponse,
253
- RefreshAllAccount,
254
- RefreshAllAccountUser,
255
- RefreshCookieResponse,
256
- } from './models/interfaces';
257
-
258
232
  // ---------------------------------------------------------------------------
259
233
  // Crypto / identity
260
234
  // ---------------------------------------------------------------------------
@@ -367,6 +341,7 @@ export {
367
341
  isNative,
368
342
  isIOS,
369
343
  isAndroid,
344
+ isWebBrowser,
370
345
  } from './utils/platform';
371
346
  export type { PlatformOS } from './utils/platform';
372
347
 
@@ -468,6 +443,7 @@ export {
468
443
  isValidEmail,
469
444
  isValidUsername,
470
445
  isValidPassword,
446
+ isValidDisplayName,
471
447
  isRequiredString,
472
448
  isRequiredNumber,
473
449
  isRequiredBoolean,
@@ -514,47 +490,23 @@ export {
514
490
  getAccountDisplayName,
515
491
  getAccountFallbackHandle,
516
492
  formatPublicKeyHandle,
517
- mergeAccountsFromRefreshAll,
518
493
  getAccountColor,
519
494
  } from './utils/accountUtils';
520
495
  export type { QuickAccount, DisplayNameUserShape } from './utils/accountUtils';
521
496
 
522
497
  // ---------------------------------------------------------------------------
523
- // Cross-domain SSO infrastructure
498
+ // Registrable-domain + central-IdP-apex helpers.
499
+ //
500
+ // The client SSO-bounce / silent-iframe / FedCM machinery was removed in the
501
+ // device-first cutover. These three symbols survive because the api SSO surface
502
+ // and the IdP (both lista B, gated on the ecosystem bump) still import them:
503
+ // `registrableApex` (eTLD+1), `CENTRAL_IDP_APEX`, and the `SSO_CALLBACK_PATH`
504
+ // constant. `@oxyhq/core/server` re-exports `registrableApex` + `SSO_CALLBACK_PATH`
505
+ // for the api; the IdP imports all three from here.
524
506
  // ---------------------------------------------------------------------------
525
- export { autoDetectAuthWebUrl, registrableApex } from './utils/fapiAutoDetect';
526
-
527
- // Central cross-domain SSO (opaque single-use code bounce via auth.oxy.so)
528
- export { CENTRAL_AUTH_URL, CENTRAL_IDP_APEX, resolveCentralAuthUrl } from './utils/authWebUrl';
529
- export { parseSsoReturnFragment, consumeSsoReturn } from './utils/ssoReturn';
530
- export type { SsoReturnKind, SsoReturnResult, ConsumeSsoReturnDeps } from './utils/ssoReturn';
531
- export { generateSsoState } from './mixins/OxyServices.sso';
532
-
533
- // Post-claim durable-session establish hop (web device-flow / QR sign-in).
534
- export { establishIdpSessionAfterClaim } from './utils/ssoEstablish';
535
- export type { SsoEstablishClient, EstablishAfterClaimDeps } from './utils/ssoEstablish';
536
-
537
- // SSO bounce — per-origin sessionStorage keys, bounce URL builder, predicates
538
- export {
539
- SSO_CALLBACK_PATH,
540
- SSO_GUARD_TTL_MS,
541
- ssoStateKey,
542
- ssoGuardKey,
543
- ssoDestKey,
544
- ssoNoSessionKey,
545
- ssoAttemptedKey,
546
- ssoPriorSessionKey,
547
- ssoSignedOutKey,
548
- ssoCallbackBootstrapKey,
549
- ssoNavigate,
550
- getSsoCallbackBootstrapScript,
551
- buildSsoBounceUrl,
552
- isCentralIdPOrigin,
553
- guardActive,
554
- silentRestoreSuppressed,
555
- allowSsoBounce,
556
- } from './utils/ssoBounce';
557
- export type { SsoBounceGate } from './utils/ssoBounce';
507
+ export { registrableApex } from './utils/fapiAutoDetect';
508
+ export { CENTRAL_AUTH_URL, CENTRAL_IDP_APEX } from './utils/authWebUrl';
509
+ export { SSO_CALLBACK_PATH } from './utils/ssoBounce';
558
510
 
559
511
  export { runColdBoot } from './utils/coldBoot';
560
512
  export type {
@@ -571,6 +523,10 @@ export type {
571
523
  // ---------------------------------------------------------------------------
572
524
  export { SessionClient } from './session/SessionClient';
573
525
  export type { TokenTransport, SessionClientHost, SessionClientOptions } from './session/SessionClient';
526
+ // The injectable socket factory type: consumers that bundle socket.io-client
527
+ // (services/auth-sdk) pass its `io` export as `socketFactory` so realtime sync
528
+ // never relies on core's lazy dynamic import of a bare specifier.
529
+ export type { SocketIOFactory, MinimalSocket } from './session/socketLoader';
574
530
 
575
531
  // Shared SessionClient integration layer: the host adapter, the pure
576
532
  // DeviceSessionState projection helpers, and the client factory are defined
@@ -586,6 +542,64 @@ export {
586
542
  accountIdsOf,
587
543
  } from './session/projectSessionState';
588
544
 
545
+ // ---------------------------------------------------------------------------
546
+ // Device-first session machinery (auth centralization, wave 1) — additive.
547
+ // Persisted auth-state store, the unified refresh handler + scheduler, the
548
+ // cold-boot v2 runner, and the device-boot return-fragment consumer. Built ON
549
+ // the existing `runColdBoot` primitive + `SessionClient`; the legacy
550
+ // FedCM/SSO/CrossDomainAuth surface is untouched (cutover happens in F4).
551
+ // ---------------------------------------------------------------------------
552
+ export {
553
+ createWebAuthStateStore,
554
+ createNativeAuthStateStore,
555
+ createMemoryAuthStateStore,
556
+ AUTH_STATE_STORAGE_KEY,
557
+ DEVICE_TOKEN_STORAGE_KEY,
558
+ } from './session/authStateStore';
559
+ export type {
560
+ PersistedAuthState,
561
+ AuthStateStore,
562
+ NativeKeyValueStorage,
563
+ } from './session/authStateStore';
564
+
565
+ export {
566
+ refreshPersistedSession,
567
+ createAuthRefreshHandler,
568
+ installAuthRefreshHandler,
569
+ startTokenRefreshScheduler,
570
+ TOKEN_REFRESH_LEAD_MS,
571
+ } from './session/refresh';
572
+ export type { RefreshDeps, TokenRefreshSchedulerHandle } from './session/refresh';
573
+
574
+ export {
575
+ runSessionColdBoot,
576
+ createBrowserColdBootDom,
577
+ isSameApex,
578
+ BOOT_ATTEMPTED_KEY,
579
+ } from './boot/coldBootV2';
580
+ export type {
581
+ RunSessionColdBootOptions,
582
+ ColdBootDom,
583
+ SignedOutReason,
584
+ } from './boot/coldBootV2';
585
+
586
+ export {
587
+ consumeDeviceBootReturn,
588
+ parseDeviceBootFragment,
589
+ hashHasBootFragment,
590
+ BOOT_FRAGMENT_PARAM,
591
+ BOOT_STATE_SESSION_KEY,
592
+ } from './boot/deviceBootReturn';
593
+ export type {
594
+ DeviceBootSession,
595
+ DeviceBootReturnOutcome,
596
+ ConsumeDeviceBootReturnDeps,
597
+ } from './boot/deviceBootReturn';
598
+
599
+ // The web-session result contract (`WebSessionResult`) is owned by
600
+ // `@oxyhq/contracts` — import it directly from there; `@oxyhq/core` does not
601
+ // re-export contract types.
602
+
589
603
  // API response contracts (request/response Zod schemas + inferred types) live in
590
604
  // `@oxyhq/contracts` — the single source of truth shared by the backend and every
591
605
  // client SDK. Import them directly from `@oxyhq/contracts`; `@oxyhq/core` does NOT
@@ -555,23 +555,16 @@ export function OxyServicesAccountsMixin<T extends typeof OxyServicesBase>(Base:
555
555
 
556
556
  // Plant the freshly minted session as the ACTIVE session, mirroring
557
557
  // `claimSessionByToken` / `verifyChallenge`: the response body carries
558
- // the first access token. The device refresh cookie is established below.
558
+ // the first access token.
559
559
  if (res?.accessToken) {
560
560
  this.setTokens(res.accessToken);
561
561
  }
562
562
 
563
- // Register the switched session in the device's multi-account set by
564
- // establishing its first-party refresh cookie. This MUST be a separate
565
- // call to `POST /auth/session` (the shared `establishDeviceRefreshSlot`
566
- // primitive): the switch route is at `/accounts/*`, outside the
567
- // `oxy_rt_<authuser>` cookie's `Path=/auth` scope, so it can never read
568
- // the device's existing slots and would overwrite slot 0 (destroying the
569
- // operator's own session). `/auth/session` runs where the cookies ARE
570
- // visible, so the server allocates a NEW slot that coexists with the
571
- // operator's and returns its `authuser`. Web-only; best-effort (the helper
572
- // re-plants the rotated access token and returns `null` on native/failure).
573
- const establishedAuthuser = await this.establishDeviceRefreshSlot();
574
- const authuser = establishedAuthuser ?? res.authuser;
563
+ // The switch route now registers the switched session in the device's
564
+ // server-side DeviceSession set directly (device-first), so there is no
565
+ // client-side refresh-cookie slot to establish the `authuser` comes
566
+ // from the switch response (optional-chained to match `res?.accessToken`).
567
+ const authuser = res?.authuser;
575
568
 
576
569
  // Identity changed → drop the entire GET response cache so no entry
577
570
  // personalised for the previous identity is reused. Cache keys are