@oxyhq/services 27.1.3 → 29.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 (387) hide show
  1. package/LICENSE +202 -661
  2. package/NOTICE +16 -0
  3. package/README.md +67 -2
  4. package/android/src/main/java/so/oxy/devicesession/OxyDeviceSessionModule.kt +178 -0
  5. package/android/src/main/java/so/oxy/devicesession/OxyDeviceSessionProvider.kt +99 -0
  6. package/android/src/main/java/so/oxy/devicesession/OxyDeviceSessionStore.kt +115 -0
  7. package/expo-module.config.json +1 -0
  8. package/lib/commonjs/index.js +78 -16
  9. package/lib/commonjs/index.js.map +1 -1
  10. package/lib/commonjs/ui/boot/runProviderColdBoot.js +7 -0
  11. package/lib/commonjs/ui/boot/runProviderColdBoot.js.map +1 -1
  12. package/lib/commonjs/ui/client.js +12 -7
  13. package/lib/commonjs/ui/client.js.map +1 -1
  14. package/lib/commonjs/ui/components/OxyAccountDialogScreen.js +10 -27
  15. package/lib/commonjs/ui/components/OxyAccountDialogScreen.js.map +1 -1
  16. package/lib/commonjs/ui/components/OxyAuthChooser.js +132 -44
  17. package/lib/commonjs/ui/components/OxyAuthChooser.js.map +1 -1
  18. package/lib/commonjs/ui/components/OxyProvider.js +4 -2
  19. package/lib/commonjs/ui/components/OxyProvider.js.map +1 -1
  20. package/lib/commonjs/ui/components/SurfaceScreen.js +31 -3
  21. package/lib/commonjs/ui/components/SurfaceScreen.js.map +1 -1
  22. package/lib/commonjs/ui/components/authChooser/AccountsMenuView.js +209 -84
  23. package/lib/commonjs/ui/components/authChooser/AccountsMenuView.js.map +1 -1
  24. package/lib/commonjs/ui/components/authChooser/SignInEntryView.js +25 -7
  25. package/lib/commonjs/ui/components/authChooser/SignInEntryView.js.map +1 -1
  26. package/lib/commonjs/ui/components/authChooser/primitives.js +35 -22
  27. package/lib/commonjs/ui/components/authChooser/primitives.js.map +1 -1
  28. package/lib/commonjs/ui/components/authChooser/signInProgress.js +5 -0
  29. package/lib/commonjs/ui/components/authChooser/signInProgress.js.map +1 -1
  30. package/lib/commonjs/ui/components/authChooser/types.js +11 -0
  31. package/lib/commonjs/ui/components/authChooser/types.js.map +1 -1
  32. package/lib/commonjs/ui/context/OxyContext.js +257 -306
  33. package/lib/commonjs/ui/context/OxyContext.js.map +1 -1
  34. package/lib/commonjs/ui/context/hooks/useAuthOperations.js +27 -37
  35. package/lib/commonjs/ui/context/hooks/useAuthOperations.js.map +1 -1
  36. package/lib/commonjs/ui/context/oxyContextHelpers.js +0 -29
  37. package/lib/commonjs/ui/context/oxyContextHelpers.js.map +1 -1
  38. package/lib/commonjs/ui/context/useOxyAccountGraph.js +6 -17
  39. package/lib/commonjs/ui/context/useOxyAccountGraph.js.map +1 -1
  40. package/lib/commonjs/ui/hooks/accountDialogSnapshot.js +42 -0
  41. package/lib/commonjs/ui/hooks/accountDialogSnapshot.js.map +1 -0
  42. package/lib/commonjs/ui/hooks/mutations/useAccountMutations.js +0 -19
  43. package/lib/commonjs/ui/hooks/mutations/useAccountMutations.js.map +1 -1
  44. package/lib/commonjs/ui/hooks/useDeviceSwitcher.js +57 -0
  45. package/lib/commonjs/ui/hooks/useDeviceSwitcher.js.map +1 -0
  46. package/lib/commonjs/ui/hooks/useI18n.js +22 -3
  47. package/lib/commonjs/ui/hooks/useI18n.js.map +1 -1
  48. package/lib/commonjs/ui/hooks/useSessionManagement.js +46 -153
  49. package/lib/commonjs/ui/hooks/useSessionManagement.js.map +1 -1
  50. package/lib/commonjs/ui/index.js +12 -7
  51. package/lib/commonjs/ui/index.js.map +1 -1
  52. package/lib/commonjs/ui/navigation/routes.js +85 -73
  53. package/lib/commonjs/ui/navigation/routes.js.map +1 -1
  54. package/lib/commonjs/ui/navigation/surfaces.js +8 -7
  55. package/lib/commonjs/ui/navigation/surfaces.js.map +1 -1
  56. package/lib/commonjs/ui/runtime/createOxyRuntime.js +433 -0
  57. package/lib/commonjs/ui/runtime/createOxyRuntime.js.map +1 -0
  58. package/lib/commonjs/ui/runtime/index.js +63 -0
  59. package/lib/commonjs/ui/runtime/index.js.map +1 -0
  60. package/lib/commonjs/ui/runtime/runtimeContext.js +83 -0
  61. package/lib/commonjs/ui/runtime/runtimeContext.js.map +1 -0
  62. package/lib/commonjs/ui/runtime/types.js +6 -0
  63. package/lib/commonjs/ui/runtime/types.js.map +1 -0
  64. package/lib/commonjs/ui/runtime/useRuntimeSnapshot.js +57 -0
  65. package/lib/commonjs/ui/runtime/useRuntimeSnapshot.js.map +1 -0
  66. package/lib/commonjs/ui/screens/AccountMembersScreen.js +3 -4
  67. package/lib/commonjs/ui/screens/AccountMembersScreen.js.map +1 -1
  68. package/lib/commonjs/ui/screens/CreateAccountScreen.js +3 -12
  69. package/lib/commonjs/ui/screens/CreateAccountScreen.js.map +1 -1
  70. package/lib/commonjs/ui/screens/trust/TrustCenterScreen.js +6 -5
  71. package/lib/commonjs/ui/screens/trust/TrustCenterScreen.js.map +1 -1
  72. package/lib/commonjs/ui/screens/trust/TrustLeaderboardScreen.js +4 -4
  73. package/lib/commonjs/ui/screens/trust/TrustLeaderboardScreen.js.map +1 -1
  74. package/lib/commonjs/ui/screens/trust/TrustRewardsScreen.js +1 -1
  75. package/lib/commonjs/ui/screens/trust/TrustRulesScreen.js +4 -2
  76. package/lib/commonjs/ui/screens/trust/TrustRulesScreen.js.map +1 -1
  77. package/lib/commonjs/ui/server.js +1 -2
  78. package/lib/commonjs/ui/server.js.map +1 -1
  79. package/lib/commonjs/ui/session/authStore.js +45 -9
  80. package/lib/commonjs/ui/session/authStore.js.map +1 -1
  81. package/lib/commonjs/ui/session/sharedDeviceCredentialStore.js +306 -0
  82. package/lib/commonjs/ui/session/sharedDeviceCredentialStore.js.map +1 -0
  83. package/lib/commonjs/ui/stores/authStore.js +154 -55
  84. package/lib/commonjs/ui/stores/authStore.js.map +1 -1
  85. package/lib/commonjs/ui/stores/followTargetStore.js +27 -0
  86. package/lib/commonjs/ui/stores/followTargetStore.js.map +1 -1
  87. package/lib/commonjs/ui/utils/avatarUtils.js +2 -36
  88. package/lib/commonjs/ui/utils/avatarUtils.js.map +1 -1
  89. package/lib/module/index.js +20 -9
  90. package/lib/module/index.js.map +1 -1
  91. package/lib/module/ui/boot/runProviderColdBoot.js +7 -0
  92. package/lib/module/ui/boot/runProviderColdBoot.js.map +1 -1
  93. package/lib/module/ui/client.js +1 -2
  94. package/lib/module/ui/client.js.map +1 -1
  95. package/lib/module/ui/components/OxyAccountDialogScreen.js +10 -27
  96. package/lib/module/ui/components/OxyAccountDialogScreen.js.map +1 -1
  97. package/lib/module/ui/components/OxyAuthChooser.js +134 -44
  98. package/lib/module/ui/components/OxyAuthChooser.js.map +1 -1
  99. package/lib/module/ui/components/OxyProvider.js +5 -3
  100. package/lib/module/ui/components/OxyProvider.js.map +1 -1
  101. package/lib/module/ui/components/SurfaceScreen.js +33 -5
  102. package/lib/module/ui/components/SurfaceScreen.js.map +1 -1
  103. package/lib/module/ui/components/authChooser/AccountsMenuView.js +210 -85
  104. package/lib/module/ui/components/authChooser/AccountsMenuView.js.map +1 -1
  105. package/lib/module/ui/components/authChooser/SignInEntryView.js +25 -7
  106. package/lib/module/ui/components/authChooser/SignInEntryView.js.map +1 -1
  107. package/lib/module/ui/components/authChooser/primitives.js +35 -22
  108. package/lib/module/ui/components/authChooser/primitives.js.map +1 -1
  109. package/lib/module/ui/components/authChooser/signInProgress.js +5 -0
  110. package/lib/module/ui/components/authChooser/signInProgress.js.map +1 -1
  111. package/lib/module/ui/components/authChooser/types.js +11 -0
  112. package/lib/module/ui/components/authChooser/types.js.map +1 -1
  113. package/lib/module/ui/context/OxyContext.js +251 -303
  114. package/lib/module/ui/context/OxyContext.js.map +1 -1
  115. package/lib/module/ui/context/hooks/useAuthOperations.js +27 -37
  116. package/lib/module/ui/context/hooks/useAuthOperations.js.map +1 -1
  117. package/lib/module/ui/context/oxyContextHelpers.js +0 -28
  118. package/lib/module/ui/context/oxyContextHelpers.js.map +1 -1
  119. package/lib/module/ui/context/useOxyAccountGraph.js +6 -17
  120. package/lib/module/ui/context/useOxyAccountGraph.js.map +1 -1
  121. package/lib/module/ui/hooks/accountDialogSnapshot.js +38 -0
  122. package/lib/module/ui/hooks/accountDialogSnapshot.js.map +1 -0
  123. package/lib/module/ui/hooks/mutations/useAccountMutations.js +0 -19
  124. package/lib/module/ui/hooks/mutations/useAccountMutations.js.map +1 -1
  125. package/lib/module/ui/hooks/useDeviceSwitcher.js +53 -0
  126. package/lib/module/ui/hooks/useDeviceSwitcher.js.map +1 -0
  127. package/lib/module/ui/hooks/useI18n.js +24 -4
  128. package/lib/module/ui/hooks/useI18n.js.map +1 -1
  129. package/lib/module/ui/hooks/useSessionManagement.js +47 -155
  130. package/lib/module/ui/hooks/useSessionManagement.js.map +1 -1
  131. package/lib/module/ui/index.js +1 -2
  132. package/lib/module/ui/index.js.map +1 -1
  133. package/lib/module/ui/navigation/routes.js +84 -72
  134. package/lib/module/ui/navigation/routes.js.map +1 -1
  135. package/lib/module/ui/navigation/surfaces.js +6 -6
  136. package/lib/module/ui/navigation/surfaces.js.map +1 -1
  137. package/lib/module/ui/runtime/createOxyRuntime.js +430 -0
  138. package/lib/module/ui/runtime/createOxyRuntime.js.map +1 -0
  139. package/lib/module/ui/runtime/index.js +15 -0
  140. package/lib/module/ui/runtime/index.js.map +1 -0
  141. package/lib/module/ui/runtime/runtimeContext.js +75 -0
  142. package/lib/module/ui/runtime/runtimeContext.js.map +1 -0
  143. package/lib/module/ui/runtime/types.js +4 -0
  144. package/lib/module/ui/runtime/types.js.map +1 -0
  145. package/lib/module/ui/runtime/useRuntimeSnapshot.js +52 -0
  146. package/lib/module/ui/runtime/useRuntimeSnapshot.js.map +1 -0
  147. package/lib/module/ui/screens/AccountMembersScreen.js +4 -5
  148. package/lib/module/ui/screens/AccountMembersScreen.js.map +1 -1
  149. package/lib/module/ui/screens/CreateAccountScreen.js +4 -13
  150. package/lib/module/ui/screens/CreateAccountScreen.js.map +1 -1
  151. package/lib/module/ui/screens/trust/TrustCenterScreen.js +6 -5
  152. package/lib/module/ui/screens/trust/TrustCenterScreen.js.map +1 -1
  153. package/lib/module/ui/screens/trust/TrustLeaderboardScreen.js +5 -5
  154. package/lib/module/ui/screens/trust/TrustLeaderboardScreen.js.map +1 -1
  155. package/lib/module/ui/screens/trust/TrustRewardsScreen.js +1 -1
  156. package/lib/module/ui/screens/trust/TrustRulesScreen.js +4 -2
  157. package/lib/module/ui/screens/trust/TrustRulesScreen.js.map +1 -1
  158. package/lib/module/ui/server.js +0 -1
  159. package/lib/module/ui/server.js.map +1 -1
  160. package/lib/module/ui/session/authStore.js +46 -11
  161. package/lib/module/ui/session/authStore.js.map +1 -1
  162. package/lib/module/ui/session/sharedDeviceCredentialStore.js +302 -0
  163. package/lib/module/ui/session/sharedDeviceCredentialStore.js.map +1 -0
  164. package/lib/module/ui/stores/authStore.js +154 -55
  165. package/lib/module/ui/stores/authStore.js.map +1 -1
  166. package/lib/module/ui/stores/followTargetStore.js +25 -0
  167. package/lib/module/ui/stores/followTargetStore.js.map +1 -1
  168. package/lib/module/ui/utils/avatarUtils.js +2 -35
  169. package/lib/module/ui/utils/avatarUtils.js.map +1 -1
  170. package/lib/typescript/commonjs/index.d.ts +6 -4
  171. package/lib/typescript/commonjs/index.d.ts.map +1 -1
  172. package/lib/typescript/commonjs/ui/boot/runProviderColdBoot.d.ts.map +1 -1
  173. package/lib/typescript/commonjs/ui/client.d.ts +1 -2
  174. package/lib/typescript/commonjs/ui/client.d.ts.map +1 -1
  175. package/lib/typescript/commonjs/ui/components/OxyAccountDialogScreen.d.ts.map +1 -1
  176. package/lib/typescript/commonjs/ui/components/OxyAuthChooser.d.ts.map +1 -1
  177. package/lib/typescript/commonjs/ui/components/OxyProvider.d.ts.map +1 -1
  178. package/lib/typescript/commonjs/ui/components/SurfaceScreen.d.ts.map +1 -1
  179. package/lib/typescript/commonjs/ui/components/authChooser/AccountsMenuView.d.ts +11 -4
  180. package/lib/typescript/commonjs/ui/components/authChooser/AccountsMenuView.d.ts.map +1 -1
  181. package/lib/typescript/commonjs/ui/components/authChooser/SignInEntryView.d.ts +3 -1
  182. package/lib/typescript/commonjs/ui/components/authChooser/SignInEntryView.d.ts.map +1 -1
  183. package/lib/typescript/commonjs/ui/components/authChooser/primitives.d.ts +18 -6
  184. package/lib/typescript/commonjs/ui/components/authChooser/primitives.d.ts.map +1 -1
  185. package/lib/typescript/commonjs/ui/components/authChooser/signInProgress.d.ts.map +1 -1
  186. package/lib/typescript/commonjs/ui/components/authChooser/types.d.ts +33 -1
  187. package/lib/typescript/commonjs/ui/components/authChooser/types.d.ts.map +1 -1
  188. package/lib/typescript/commonjs/ui/context/OxyContext.d.ts +35 -4
  189. package/lib/typescript/commonjs/ui/context/OxyContext.d.ts.map +1 -1
  190. package/lib/typescript/commonjs/ui/context/hooks/useAuthOperations.d.ts +8 -12
  191. package/lib/typescript/commonjs/ui/context/hooks/useAuthOperations.d.ts.map +1 -1
  192. package/lib/typescript/commonjs/ui/context/oxyContextHelpers.d.ts +0 -2
  193. package/lib/typescript/commonjs/ui/context/oxyContextHelpers.d.ts.map +1 -1
  194. package/lib/typescript/commonjs/ui/context/oxyContextTypes.d.ts +9 -1
  195. package/lib/typescript/commonjs/ui/context/oxyContextTypes.d.ts.map +1 -1
  196. package/lib/typescript/commonjs/ui/context/useOxyAccountGraph.d.ts +1 -3
  197. package/lib/typescript/commonjs/ui/context/useOxyAccountGraph.d.ts.map +1 -1
  198. package/lib/typescript/commonjs/ui/hooks/accountDialogSnapshot.d.ts +15 -0
  199. package/lib/typescript/commonjs/ui/hooks/accountDialogSnapshot.d.ts.map +1 -0
  200. package/lib/typescript/commonjs/ui/hooks/mutations/useAccountMutations.d.ts.map +1 -1
  201. package/lib/typescript/commonjs/ui/hooks/useDeviceSwitcher.d.ts +49 -0
  202. package/lib/typescript/commonjs/ui/hooks/useDeviceSwitcher.d.ts.map +1 -0
  203. package/lib/typescript/commonjs/ui/hooks/useI18n.d.ts +13 -0
  204. package/lib/typescript/commonjs/ui/hooks/useI18n.d.ts.map +1 -1
  205. package/lib/typescript/commonjs/ui/hooks/useSessionManagement.d.ts +23 -18
  206. package/lib/typescript/commonjs/ui/hooks/useSessionManagement.d.ts.map +1 -1
  207. package/lib/typescript/commonjs/ui/index.d.ts +1 -2
  208. package/lib/typescript/commonjs/ui/index.d.ts.map +1 -1
  209. package/lib/typescript/commonjs/ui/navigation/routes.d.ts +15 -1
  210. package/lib/typescript/commonjs/ui/navigation/routes.d.ts.map +1 -1
  211. package/lib/typescript/commonjs/ui/navigation/surfaces.d.ts.map +1 -1
  212. package/lib/typescript/commonjs/ui/runtime/createOxyRuntime.d.ts +144 -0
  213. package/lib/typescript/commonjs/ui/runtime/createOxyRuntime.d.ts.map +1 -0
  214. package/lib/typescript/commonjs/ui/runtime/index.d.ts +16 -0
  215. package/lib/typescript/commonjs/ui/runtime/index.d.ts.map +1 -0
  216. package/lib/typescript/commonjs/ui/runtime/runtimeContext.d.ts +43 -0
  217. package/lib/typescript/commonjs/ui/runtime/runtimeContext.d.ts.map +1 -0
  218. package/lib/typescript/commonjs/ui/runtime/types.d.ts +89 -0
  219. package/lib/typescript/commonjs/ui/runtime/types.d.ts.map +1 -0
  220. package/lib/typescript/commonjs/ui/runtime/useRuntimeSnapshot.d.ts +23 -0
  221. package/lib/typescript/commonjs/ui/runtime/useRuntimeSnapshot.d.ts.map +1 -0
  222. package/lib/typescript/commonjs/ui/screens/AccountMembersScreen.d.ts.map +1 -1
  223. package/lib/typescript/commonjs/ui/screens/CreateAccountScreen.d.ts.map +1 -1
  224. package/lib/typescript/commonjs/ui/screens/trust/TrustLeaderboardScreen.d.ts.map +1 -1
  225. package/lib/typescript/commonjs/ui/screens/trust/TrustRulesScreen.d.ts.map +1 -1
  226. package/lib/typescript/commonjs/ui/server.d.ts +0 -1
  227. package/lib/typescript/commonjs/ui/server.d.ts.map +1 -1
  228. package/lib/typescript/commonjs/ui/session/authStore.d.ts +60 -9
  229. package/lib/typescript/commonjs/ui/session/authStore.d.ts.map +1 -1
  230. package/lib/typescript/commonjs/ui/session/sharedDeviceCredentialStore.d.ts +32 -0
  231. package/lib/typescript/commonjs/ui/session/sharedDeviceCredentialStore.d.ts.map +1 -0
  232. package/lib/typescript/commonjs/ui/stores/authStore.d.ts +49 -5
  233. package/lib/typescript/commonjs/ui/stores/authStore.d.ts.map +1 -1
  234. package/lib/typescript/commonjs/ui/stores/followTargetStore.d.ts +8 -1
  235. package/lib/typescript/commonjs/ui/stores/followTargetStore.d.ts.map +1 -1
  236. package/lib/typescript/commonjs/ui/types/navigation.d.ts +26 -0
  237. package/lib/typescript/commonjs/ui/types/navigation.d.ts.map +1 -1
  238. package/lib/typescript/commonjs/ui/utils/avatarUtils.d.ts +2 -10
  239. package/lib/typescript/commonjs/ui/utils/avatarUtils.d.ts.map +1 -1
  240. package/lib/typescript/module/index.d.ts +6 -4
  241. package/lib/typescript/module/index.d.ts.map +1 -1
  242. package/lib/typescript/module/ui/boot/runProviderColdBoot.d.ts.map +1 -1
  243. package/lib/typescript/module/ui/client.d.ts +1 -2
  244. package/lib/typescript/module/ui/client.d.ts.map +1 -1
  245. package/lib/typescript/module/ui/components/OxyAccountDialogScreen.d.ts.map +1 -1
  246. package/lib/typescript/module/ui/components/OxyAuthChooser.d.ts.map +1 -1
  247. package/lib/typescript/module/ui/components/OxyProvider.d.ts.map +1 -1
  248. package/lib/typescript/module/ui/components/SurfaceScreen.d.ts.map +1 -1
  249. package/lib/typescript/module/ui/components/authChooser/AccountsMenuView.d.ts +11 -4
  250. package/lib/typescript/module/ui/components/authChooser/AccountsMenuView.d.ts.map +1 -1
  251. package/lib/typescript/module/ui/components/authChooser/SignInEntryView.d.ts +3 -1
  252. package/lib/typescript/module/ui/components/authChooser/SignInEntryView.d.ts.map +1 -1
  253. package/lib/typescript/module/ui/components/authChooser/primitives.d.ts +18 -6
  254. package/lib/typescript/module/ui/components/authChooser/primitives.d.ts.map +1 -1
  255. package/lib/typescript/module/ui/components/authChooser/signInProgress.d.ts.map +1 -1
  256. package/lib/typescript/module/ui/components/authChooser/types.d.ts +33 -1
  257. package/lib/typescript/module/ui/components/authChooser/types.d.ts.map +1 -1
  258. package/lib/typescript/module/ui/context/OxyContext.d.ts +35 -4
  259. package/lib/typescript/module/ui/context/OxyContext.d.ts.map +1 -1
  260. package/lib/typescript/module/ui/context/hooks/useAuthOperations.d.ts +8 -12
  261. package/lib/typescript/module/ui/context/hooks/useAuthOperations.d.ts.map +1 -1
  262. package/lib/typescript/module/ui/context/oxyContextHelpers.d.ts +0 -2
  263. package/lib/typescript/module/ui/context/oxyContextHelpers.d.ts.map +1 -1
  264. package/lib/typescript/module/ui/context/oxyContextTypes.d.ts +9 -1
  265. package/lib/typescript/module/ui/context/oxyContextTypes.d.ts.map +1 -1
  266. package/lib/typescript/module/ui/context/useOxyAccountGraph.d.ts +1 -3
  267. package/lib/typescript/module/ui/context/useOxyAccountGraph.d.ts.map +1 -1
  268. package/lib/typescript/module/ui/hooks/accountDialogSnapshot.d.ts +15 -0
  269. package/lib/typescript/module/ui/hooks/accountDialogSnapshot.d.ts.map +1 -0
  270. package/lib/typescript/module/ui/hooks/mutations/useAccountMutations.d.ts.map +1 -1
  271. package/lib/typescript/module/ui/hooks/useDeviceSwitcher.d.ts +49 -0
  272. package/lib/typescript/module/ui/hooks/useDeviceSwitcher.d.ts.map +1 -0
  273. package/lib/typescript/module/ui/hooks/useI18n.d.ts +13 -0
  274. package/lib/typescript/module/ui/hooks/useI18n.d.ts.map +1 -1
  275. package/lib/typescript/module/ui/hooks/useSessionManagement.d.ts +23 -18
  276. package/lib/typescript/module/ui/hooks/useSessionManagement.d.ts.map +1 -1
  277. package/lib/typescript/module/ui/index.d.ts +1 -2
  278. package/lib/typescript/module/ui/index.d.ts.map +1 -1
  279. package/lib/typescript/module/ui/navigation/routes.d.ts +15 -1
  280. package/lib/typescript/module/ui/navigation/routes.d.ts.map +1 -1
  281. package/lib/typescript/module/ui/navigation/surfaces.d.ts.map +1 -1
  282. package/lib/typescript/module/ui/runtime/createOxyRuntime.d.ts +144 -0
  283. package/lib/typescript/module/ui/runtime/createOxyRuntime.d.ts.map +1 -0
  284. package/lib/typescript/module/ui/runtime/index.d.ts +16 -0
  285. package/lib/typescript/module/ui/runtime/index.d.ts.map +1 -0
  286. package/lib/typescript/module/ui/runtime/runtimeContext.d.ts +43 -0
  287. package/lib/typescript/module/ui/runtime/runtimeContext.d.ts.map +1 -0
  288. package/lib/typescript/module/ui/runtime/types.d.ts +89 -0
  289. package/lib/typescript/module/ui/runtime/types.d.ts.map +1 -0
  290. package/lib/typescript/module/ui/runtime/useRuntimeSnapshot.d.ts +23 -0
  291. package/lib/typescript/module/ui/runtime/useRuntimeSnapshot.d.ts.map +1 -0
  292. package/lib/typescript/module/ui/screens/AccountMembersScreen.d.ts.map +1 -1
  293. package/lib/typescript/module/ui/screens/CreateAccountScreen.d.ts.map +1 -1
  294. package/lib/typescript/module/ui/screens/trust/TrustLeaderboardScreen.d.ts.map +1 -1
  295. package/lib/typescript/module/ui/screens/trust/TrustRulesScreen.d.ts.map +1 -1
  296. package/lib/typescript/module/ui/server.d.ts +0 -1
  297. package/lib/typescript/module/ui/server.d.ts.map +1 -1
  298. package/lib/typescript/module/ui/session/authStore.d.ts +60 -9
  299. package/lib/typescript/module/ui/session/authStore.d.ts.map +1 -1
  300. package/lib/typescript/module/ui/session/sharedDeviceCredentialStore.d.ts +32 -0
  301. package/lib/typescript/module/ui/session/sharedDeviceCredentialStore.d.ts.map +1 -0
  302. package/lib/typescript/module/ui/stores/authStore.d.ts +49 -5
  303. package/lib/typescript/module/ui/stores/authStore.d.ts.map +1 -1
  304. package/lib/typescript/module/ui/stores/followTargetStore.d.ts +8 -1
  305. package/lib/typescript/module/ui/stores/followTargetStore.d.ts.map +1 -1
  306. package/lib/typescript/module/ui/types/navigation.d.ts +26 -0
  307. package/lib/typescript/module/ui/types/navigation.d.ts.map +1 -1
  308. package/lib/typescript/module/ui/utils/avatarUtils.d.ts +2 -10
  309. package/lib/typescript/module/ui/utils/avatarUtils.d.ts.map +1 -1
  310. package/package.json +8 -8
  311. package/plugins/withSharedDeviceSessionProvider.js +102 -0
  312. package/plugins/withSharedDeviceSessionReader.js +57 -0
  313. package/src/__tests__/esmSourcePurity.test.ts +61 -0
  314. package/src/index.ts +36 -9
  315. package/src/ui/boot/runProviderColdBoot.ts +7 -0
  316. package/src/ui/client.ts +1 -2
  317. package/src/ui/components/OxyAccountDialogScreen.tsx +10 -29
  318. package/src/ui/components/OxyAuthChooser.tsx +149 -50
  319. package/src/ui/components/OxyProvider.tsx +7 -5
  320. package/src/ui/components/SurfaceScreen.tsx +28 -4
  321. package/src/ui/components/__tests__/followTargetButton.test.ts +39 -0
  322. package/src/ui/components/authChooser/AccountsMenuView.tsx +246 -96
  323. package/src/ui/components/authChooser/SignInEntryView.tsx +31 -8
  324. package/src/ui/components/authChooser/primitives.tsx +37 -23
  325. package/src/ui/components/authChooser/signInProgress.ts +4 -0
  326. package/src/ui/components/authChooser/types.ts +34 -1
  327. package/src/ui/context/OxyContext.tsx +269 -324
  328. package/src/ui/context/hooks/useAuthOperations.ts +32 -35
  329. package/src/ui/context/oxyContextHelpers.ts +0 -30
  330. package/src/ui/context/oxyContextTypes.ts +9 -1
  331. package/src/ui/context/useOxyAccountGraph.ts +5 -19
  332. package/src/ui/hooks/accountDialogSnapshot.ts +37 -0
  333. package/src/ui/hooks/mutations/useAccountMutations.ts +0 -19
  334. package/src/ui/hooks/queries/__tests__/userCache.test.ts +12 -1
  335. package/src/ui/hooks/useDeviceSwitcher.ts +110 -0
  336. package/src/ui/hooks/useI18n.ts +23 -3
  337. package/src/ui/hooks/useSessionManagement.ts +62 -211
  338. package/src/ui/index.ts +1 -2
  339. package/src/ui/navigation/routes.ts +85 -75
  340. package/src/ui/navigation/surfaces.ts +6 -9
  341. package/src/ui/runtime/createOxyRuntime.ts +623 -0
  342. package/src/ui/runtime/index.ts +34 -0
  343. package/src/ui/runtime/runtimeContext.tsx +111 -0
  344. package/src/ui/runtime/types.ts +110 -0
  345. package/src/ui/runtime/useRuntimeSnapshot.ts +52 -0
  346. package/src/ui/screens/AccountMembersScreen.tsx +6 -5
  347. package/src/ui/screens/CreateAccountScreen.tsx +3 -16
  348. package/src/ui/screens/trust/TrustCenterScreen.tsx +7 -7
  349. package/src/ui/screens/trust/TrustLeaderboardScreen.tsx +4 -5
  350. package/src/ui/screens/trust/TrustRewardsScreen.tsx +1 -1
  351. package/src/ui/screens/trust/TrustRulesScreen.tsx +3 -2
  352. package/src/ui/server.ts +0 -1
  353. package/src/ui/session/__tests__/authStore.test.ts +90 -0
  354. package/src/ui/session/__tests__/sharedDeviceCredentialStore.test.ts +289 -0
  355. package/src/ui/session/authStore.ts +78 -9
  356. package/src/ui/session/sharedDeviceCredentialStore.ts +318 -0
  357. package/src/ui/stores/authStore.ts +171 -43
  358. package/src/ui/stores/followTargetStore.ts +24 -1
  359. package/src/ui/types/navigation.ts +26 -0
  360. package/src/ui/utils/avatarUtils.ts +2 -37
  361. package/lib/commonjs/ui/hooks/useSwitchableAccounts.js +0 -64
  362. package/lib/commonjs/ui/hooks/useSwitchableAccounts.js.map +0 -1
  363. package/lib/commonjs/ui/screens/trust/trustTier.js +0 -23
  364. package/lib/commonjs/ui/screens/trust/trustTier.js.map +0 -1
  365. package/lib/commonjs/ui/stores/accountStore.js +0 -221
  366. package/lib/commonjs/ui/stores/accountStore.js.map +0 -1
  367. package/lib/module/ui/hooks/useSwitchableAccounts.js +0 -60
  368. package/lib/module/ui/hooks/useSwitchableAccounts.js.map +0 -1
  369. package/lib/module/ui/screens/trust/trustTier.js +0 -19
  370. package/lib/module/ui/screens/trust/trustTier.js.map +0 -1
  371. package/lib/module/ui/stores/accountStore.js +0 -213
  372. package/lib/module/ui/stores/accountStore.js.map +0 -1
  373. package/lib/typescript/commonjs/ui/hooks/useSwitchableAccounts.d.ts +0 -23
  374. package/lib/typescript/commonjs/ui/hooks/useSwitchableAccounts.d.ts.map +0 -1
  375. package/lib/typescript/commonjs/ui/screens/trust/trustTier.d.ts +0 -9
  376. package/lib/typescript/commonjs/ui/screens/trust/trustTier.d.ts.map +0 -1
  377. package/lib/typescript/commonjs/ui/stores/accountStore.d.ts +0 -27
  378. package/lib/typescript/commonjs/ui/stores/accountStore.d.ts.map +0 -1
  379. package/lib/typescript/module/ui/hooks/useSwitchableAccounts.d.ts +0 -23
  380. package/lib/typescript/module/ui/hooks/useSwitchableAccounts.d.ts.map +0 -1
  381. package/lib/typescript/module/ui/screens/trust/trustTier.d.ts +0 -9
  382. package/lib/typescript/module/ui/screens/trust/trustTier.d.ts.map +0 -1
  383. package/lib/typescript/module/ui/stores/accountStore.d.ts +0 -27
  384. package/lib/typescript/module/ui/stores/accountStore.d.ts.map +0 -1
  385. package/src/ui/hooks/useSwitchableAccounts.ts +0 -75
  386. package/src/ui/screens/trust/trustTier.ts +0 -20
  387. package/src/ui/stores/accountStore.ts +0 -264
@@ -3,7 +3,7 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.useOxy = exports.OxyProvider = exports.OxyContextProvider = void 0;
6
+ exports.useOxy = exports.useOptionalOxy = exports.OxyRuntimeProvider = exports.OxyProviderMissingError = void 0;
7
7
  var _react = require("react");
8
8
  var _reactNative = require("react-native");
9
9
  var _socket = require("socket.io-client");
@@ -17,7 +17,6 @@ var _deliveryPlatform = require("../utils/deliveryPlatform.js");
17
17
  var _runProviderColdBoot = require("../boot/runProviderColdBoot.js");
18
18
  var _deviceCredential = require("../utils/deviceCredential.js");
19
19
  var _authStore = require("../stores/authStore.js");
20
- var _shallow = require("zustand/react/shallow");
21
20
  var _useLanguageManagement = require("../hooks/useLanguageManagement.js");
22
21
  var _useSessionManagement = require("../hooks/useSessionManagement.js");
23
22
  var _useAuthOperations = require("./hooks/useAuthOperations.js");
@@ -28,17 +27,36 @@ var _surfaces = require("../navigation/surfaces.js");
28
27
  var _reactQuery = require("@tanstack/react-query");
29
28
  var _queryClient = require("../hooks/queryClient.js");
30
29
  var _useAvatarPicker = require("../hooks/useAvatarPicker.js");
31
- var _accountStore = require("../stores/accountStore.js");
32
- var _index = require("../session/index.js");
30
+ var _resetSessionScopedStores = require("../stores/resetSessionScopedStores.js");
31
+ var _useResolvedFileUrls = require("../hooks/useResolvedFileUrls.js");
32
+ var _index = require("../runtime/index.js");
33
+ var _index2 = require("../session/index.js");
33
34
  var _oxyContextHelpers = require("./oxyContextHelpers.js");
35
+ var _useFollow = require("../hooks/useFollow.js");
34
36
  var _commitSessionFlow = require("./commitSessionFlow.js");
35
37
  var _passkeyFlow = require("./passkeyFlow.js");
36
38
  var _passkeyClient = require("../../webauthn/passkeyClient");
37
39
  var _queryKeys = require("../hooks/queries/queryKeys.js");
38
40
  var _useOxyAccountGraph = require("./useOxyAccountGraph.js");
39
41
  var _jsxRuntime = require("react/jsx-runtime");
40
- const OxyContext = /*#__PURE__*/(0, _react.createContext)(null);
41
- const OxyProvider = ({
42
+ // `useFollow` imports this module back, so the binding must only be READ inside
43
+ // the provider body — at render time, once every module has evaluated. It is
44
+ // never dereferenced at module scope here.
45
+
46
+ const OxyRuntimeContext = /*#__PURE__*/(0, _react.createContext)(null);
47
+
48
+ /**
49
+ * The SDK's internal runtime provider — the session/account state machine that
50
+ * backs `useOxy()`.
51
+ *
52
+ * This is NOT the component consumers mount. The one public composition root is
53
+ * `OxyProvider` (`../components/OxyProvider`), which mounts this alongside the
54
+ * QueryClient, Bloom's dialog/surface/toast hosts, safe areas, the gesture root
55
+ * and the keyboard provider. Naming both of them `OxyProvider` (as this file
56
+ * used to) made every error message, stack frame and doc reference ambiguous —
57
+ * see ADR 0004.
58
+ */
59
+ const OxyRuntimeProvider = ({
42
60
  children,
43
61
  oxyServices: providedOxyServices,
44
62
  baseURL,
@@ -50,6 +68,7 @@ const OxyProvider = ({
50
68
  sessionMode = 'account',
51
69
  webAuthMode = 'popup',
52
70
  backgroundSession = false,
71
+ deviceCredentialStorage = 'persistent',
53
72
  onAuthStateChange,
54
73
  onError
55
74
  }) => {
@@ -66,17 +85,24 @@ const OxyProvider = ({
66
85
  authRedirectUri
67
86
  });
68
87
  } else {
69
- throw new Error('Either oxyServices or baseURL must be provided to OxyContextProvider');
88
+ throw new Error('Either oxyServices or baseURL must be provided to OxyProvider');
70
89
  }
71
90
  }
72
91
  const oxyServices = oxyServicesRef.current;
73
92
 
74
- // The device-first persisted auth-state store (per-origin zero-cookie device
75
- // credential on web; SecureStore session blob on native). Built ONCE per
76
- // provider mount.
93
+ // The device-first persisted auth-state store (per-origin device credential on
94
+ // web; SecureStore session blob on native). Built ONCE per provider mount.
95
+ //
96
+ // `deviceCredentialStorage` is mount-time configuration for the same reason
97
+ // `sessionMode` is: it decides where the durable credential lives, and letting
98
+ // it change mid-flight would mean a session that started ephemeral could begin
99
+ // writing one.
77
100
  const authStoreRef = (0, _react.useRef)(null);
78
101
  if (!authStoreRef.current) {
79
- authStoreRef.current = (0, _index.createPlatformAuthStateStore)();
102
+ authStoreRef.current = (0, _index2.createPlatformAuthStateStore)({
103
+ sessionMode,
104
+ storage: deviceCredentialStorage
105
+ });
80
106
  }
81
107
  const authStore = authStoreRef.current;
82
108
 
@@ -92,38 +118,96 @@ const OxyProvider = ({
92
118
  // be downgraded mid-flight into following the device's active account.
93
119
  const identityRef = (0, _react.useRef)(null);
94
120
  if (sessionMode === 'identity' && !identityRef.current) {
95
- identityRef.current = (0, _index.createIdentitySessionBinding)();
121
+ identityRef.current = (0, _index2.createIdentitySessionBinding)();
96
122
  }
97
123
  const identity = identityRef.current;
98
124
  const isIdentityBound = identity !== null;
125
+ const logger = (0, _react.useCallback)((message, err) => {
126
+ if (__DEV__) {
127
+ _core.logger.warn(message, {
128
+ component: 'OxyContext'
129
+ }, err);
130
+ }
131
+ }, []);
132
+
133
+ // Server-authoritative device session client. Built ONCE per `oxyServices`
134
+ // instance. Device-scoped sockets connect with deviceId+deviceSecret when no
135
+ // bearer is planted yet, so cross-origin apps sync via `session_state`.
136
+ const sessionClientPairRef = (0, _react.useRef)(null);
137
+ if (!sessionClientPairRef.current) {
138
+ sessionClientPairRef.current = (0, _index2.createSessionClient)(oxyServices, origin => {
139
+ // Erase the DURABLE device credential only on a `request`-origin verdict
140
+ // (a REST sign-out / revocation). A `push`-origin empty state is a socket
141
+ // broadcast that may be a transient reconnect artifact — clearing the
142
+ // credential on it would strand the user signed out with no way back, so
143
+ // we clear only the local UI session and keep the credential (a dead one
144
+ // re-mints to `no_active_session` and resolves signed-out on next boot).
145
+ if (origin === 'request') {
146
+ (0, _useAuthOperations.clearPersistedAuthSafe)(authStore, logger);
147
+ }
148
+ void clearSessionStateRef.current().catch(clearError => {
149
+ logger('Failed to clear local state on remote sign-out', clearError);
150
+ });
151
+ },
152
+ // `null` for every account-mode provider — identical to omitting the
153
+ // option — and the pinned account id once an identity-bound provider has
154
+ // resolved its pin. Read through the ref so the resolver stays stable for
155
+ // the client's lifetime while still seeing later resolutions.
156
+ () => identityRef.current?.getPinnedAccountId() ?? null);
157
+ }
99
158
  const {
100
- user,
101
- isAuthenticated,
159
+ client: sessionClient,
160
+ host: sessionClientHost
161
+ } = sessionClientPairRef.current;
162
+
163
+ // ── The runtime ──────────────────────────────────────────────────────────
164
+ // One owner for the session facts (ADR 0004), built ONCE and never rebuilt,
165
+ // so the context value below can hand out a reference that never changes.
166
+ //
167
+ // Its three callbacks reach forward through refs because the collaborators
168
+ // they need — the storage-backed teardown, the account-graph refresh — are
169
+ // hooks declared after it. Latching the runtime here rather than after them
170
+ // is deliberate: a runtime rebuilt mid-flight would drop its `SessionClient`
171
+ // subscription and every subscriber with it.
172
+ const clearSessionStateRef = (0, _react.useRef)(() => Promise.resolve());
173
+ const saveSessionIdsRef = (0, _react.useRef)(() => undefined);
174
+ const subjectChangeRef = (0, _react.useRef)(() => undefined);
175
+ const reestablishRef = (0, _react.useRef)(() => undefined);
176
+ const runtimeRef = (0, _react.useRef)(null);
177
+ if (!runtimeRef.current) {
178
+ runtimeRef.current = (0, _index.createOxyRuntime)({
179
+ oxyServices,
180
+ sessionClient,
181
+ sessionClientHost,
182
+ identity,
183
+ onSubjectChange: transition => subjectChangeRef.current(transition),
184
+ onDeviceEmpty: () => clearSessionStateRef.current(),
185
+ onSessionsProjected: sessionIds => saveSessionIdsRef.current(sessionIds),
186
+ onIdentityUnbound: (binding, revision) => reestablishRef.current(binding, revision),
187
+ logger
188
+ });
189
+ }
190
+ const runtime = runtimeRef.current;
191
+ const snapshot = (0, _index.useRuntimeSnapshot)(runtime);
192
+ const {
193
+ account: user,
194
+ sessions,
195
+ activeSessionId,
102
196
  isLoading,
103
- error,
104
- loginSuccess,
105
- loginFailure,
106
- logoutStore
107
- } = (0, _authStore.useAuthStore)((0, _shallow.useShallow)(state => ({
108
- user: state.user,
109
- isAuthenticated: state.isAuthenticated,
110
- isLoading: state.isLoading,
111
- error: state.error,
112
- loginSuccess: state.loginSuccess,
113
- loginFailure: state.loginFailure,
114
- logoutStore: state.logout
115
- })));
116
- const [tokenReady, setTokenReady] = (0, _react.useState)(true);
117
- const [hasAccessToken, setHasAccessToken] = (0, _react.useState)(() => Boolean(oxyServices.getAccessToken()));
118
- const [authResolved, setAuthResolved] = (0, _react.useState)(false);
119
- const authResolvedRef = (0, _react.useRef)(false);
120
- const userRef = (0, _react.useRef)(user);
121
- const isAuthenticatedRef = (0, _react.useRef)(isAuthenticated);
122
- userRef.current = user;
123
- isAuthenticatedRef.current = isAuthenticated;
197
+ tokenReady,
198
+ hasAccessToken,
199
+ authResolved
200
+ } = snapshot;
201
+ const isAuthenticated = user !== null;
202
+ const error = snapshot.error?.message ?? null;
124
203
  const [initialized, setInitialized] = (0, _react.useState)(false);
125
204
  const [accountDialogOpen, setAccountDialogOpen] = (0, _react.useState)(false);
126
- const setAuthState = _authStore.useAuthStore.setState;
205
+
206
+ // Project the runtime onto `useAuthStore`, which a dozen out-of-band callers
207
+ // (mutation success handlers, cache helpers, the Commons app) still read the
208
+ // signed-in user through. It is a projection, not a second store.
209
+ (0, _react.useEffect)(() => (0, _authStore.bindAuthStoreToRuntime)(runtime), [runtime]);
210
+ (0, _react.useEffect)(() => runtime.start(), [runtime]);
127
211
 
128
212
  // Keep the shared `oxyClient` singleton's token store in lockstep with the
129
213
  // session owned by THIS provider's instance (many apps build API clients
@@ -143,13 +227,6 @@ const OxyProvider = ({
143
227
  applyToSingleton(oxyServices.getAccessToken());
144
228
  return oxyServices.onTokensChanged(applyToSingleton);
145
229
  }, [oxyServices]);
146
- const logger = (0, _react.useCallback)((message, err) => {
147
- if (__DEV__) {
148
- _core.logger.warn(message, {
149
- component: 'OxyContext'
150
- }, err);
151
- }
152
- }, []);
153
230
  const storageKeys = (0, _react.useMemo)(() => (0, _storageHelpers.getStorageKeys)(storageKeyPrefix), [storageKeyPrefix]);
154
231
  const clientId = (0, _react.useMemo)(() => {
155
232
  const trimmed = clientIdProp?.trim();
@@ -183,6 +260,7 @@ const OxyProvider = ({
183
260
  storageReady.resolve(storageInstance);
184
261
  if (mounted) {
185
262
  setStorage(storageInstance);
263
+ runtime.setStorageReady(true);
186
264
  }
187
265
  }).catch(err => {
188
266
  if (mounted) {
@@ -197,7 +275,7 @@ const OxyProvider = ({
197
275
  return () => {
198
276
  mounted = false;
199
277
  };
200
- }, [logger, onError, storageReady]);
278
+ }, [logger, onError, runtime, storageReady]);
201
279
  const {
202
280
  currentLanguage,
203
281
  languages: currentLanguages,
@@ -214,85 +292,36 @@ const OxyProvider = ({
214
292
  });
215
293
  const queryClient = (0, _reactQuery.useQueryClient)();
216
294
  const {
217
- sessions,
218
- activeSessionId,
219
- setActiveSessionId,
220
- updateSessions,
295
+ saveSessionIds,
221
296
  switchSession,
222
297
  clearSessionState,
223
298
  saveActiveSessionId
224
299
  } = (0, _useSessionManagement.useSessionManagement)({
225
300
  oxyServices,
301
+ runtime,
226
302
  storage,
227
303
  storageKeyPrefix,
228
- loginSuccess,
229
- logoutStore,
230
304
  onAuthStateChange,
231
305
  onError,
232
- setAuthError: message => setAuthState({
233
- error: message
234
- }),
306
+ setAuthError: message => runtime.setError(message),
235
307
  logger,
236
- setTokenReady,
237
308
  queryClient
238
309
  });
239
-
240
- // Refs so callbacks below can invoke the latest session-management functions
241
- // without widening dependency arrays.
242
- const switchSessionRef = (0, _react.useRef)(switchSession);
243
- switchSessionRef.current = switchSession;
244
- const clearSessionStateRef = (0, _react.useRef)(clearSessionState);
245
310
  clearSessionStateRef.current = clearSessionState;
246
- const setActiveSessionIdRef = (0, _react.useRef)(setActiveSessionId);
247
- setActiveSessionIdRef.current = setActiveSessionId;
248
- const loginSuccessRef = (0, _react.useRef)(loginSuccess);
249
- loginSuccessRef.current = loginSuccess;
311
+ saveSessionIdsRef.current = saveSessionIds;
250
312
  const onAuthStateChangeRef = (0, _react.useRef)(onAuthStateChange);
251
313
  onAuthStateChangeRef.current = onAuthStateChange;
252
314
 
253
- // Flip the auth-resolution gate (`authResolved` + `tokenReady`) the moment a
254
- // session commits or the boot concludes signed out. Idempotent + monotonic.
315
+ // Flip the auth-resolution gate the moment a session commits or the boot
316
+ // concludes signed out. Idempotent + monotonic, enforced by the runtime.
255
317
  const markAuthResolved = (0, _react.useCallback)(() => {
256
- if (authResolvedRef.current) {
257
- return;
258
- }
259
- authResolvedRef.current = true;
260
- setTokenReady(true);
261
- setAuthResolved(true);
262
- }, []);
318
+ runtime.markAuthResolved();
319
+ }, [runtime]);
263
320
  const markAuthResolvedRef = (0, _react.useRef)(markAuthResolved);
264
321
  markAuthResolvedRef.current = markAuthResolved;
265
-
266
- // Server-authoritative device session client. Built ONCE per `oxyServices`
267
- // instance. Device-scoped sockets connect with deviceId+deviceSecret when no
268
- // bearer is planted yet, so cross-origin apps sync via `session_state` after
269
- // the one-shot join redirect.
270
- const sessionClientPairRef = (0, _react.useRef)(null);
271
- if (!sessionClientPairRef.current) {
272
- sessionClientPairRef.current = (0, _index.createSessionClient)(oxyServices, origin => {
273
- // Erase the DURABLE device credential only on a `request`-origin verdict
274
- // (a REST sign-out / revocation). A `push`-origin empty state is a socket
275
- // broadcast that may be a transient reconnect artifact — clearing the
276
- // credential on it would strand the user signed out with no way back, so
277
- // we clear only the local UI session and keep the credential (a dead one
278
- // re-mints to `no_active_session` and resolves signed-out on next boot).
279
- if (origin === 'request') {
280
- (0, _useAuthOperations.clearPersistedAuthSafe)(authStore, logger);
281
- }
282
- void clearSessionStateRef.current().catch(clearError => {
283
- logger('Failed to clear local state on remote sign-out', clearError);
284
- });
285
- },
286
- // `null` for every account-mode provider — identical to omitting the
287
- // option — and the pinned account id once an identity-bound provider has
288
- // resolved its pin. Read through the ref so the resolver stays stable for
289
- // the client's lifetime while still seeing later resolutions.
290
- () => identityRef.current?.getPinnedAccountId() ?? null);
291
- }
292
- const {
293
- client: sessionClient,
294
- host: sessionClientHost
295
- } = sessionClientPairRef.current;
322
+ const setTokenReady = (0, _react.useCallback)(ready => {
323
+ runtime.setTokenReady(ready);
324
+ }, [runtime]);
296
325
 
297
326
  // Re-establishment lane for an identity-bound provider whose pin is missing or
298
327
  // whose pinned account is no longer part of this device's session set (another
@@ -337,78 +366,22 @@ const OxyProvider = ({
337
366
  tracker.inFlight = false;
338
367
  });
339
368
  }, [oxyServices, authStore, sessionClient, logger]);
369
+ reestablishRef.current = reestablishIdentitySession;
340
370
 
341
- // Projects `client.getState()` onto the exposed `sessions`/`activeSessionId`/
342
- // `user`. Sole authority for both locally-initiated mutations (switch/logout)
343
- // AND remotely-pushed `session_state` over the `device:<deviceId>` socket.
344
- const syncFromClient = (0, _react.useCallback)(async () => {
345
- const state = sessionClient.getState();
346
- if (state === null) {
347
- return;
348
- }
349
- if (state.accounts.length === 0) {
350
- // Clear the LOCAL UI session on any applied empty state, but NEVER the
351
- // durable device credential here: `syncFromClient` runs for socket-pushed
352
- // (possibly transient) states too, and wiping the credential on one would
353
- // strand the user signed out. The credential wipe is gated on a
354
- // `request`-origin verdict in `onUnauthenticated` above.
355
- sessionClientHost.setCurrentAccountId(null);
356
- await clearSessionState();
357
- return;
358
- }
359
- // Last-write-wins guard: capture the revision this projection is for, then
360
- // after the async profile fetch bail if a fresher state has landed.
361
- const capturedRevision = state.revision;
362
- // Resolve the pin BEFORE the profile fetch (memoised: one storage + keychain
363
- // read per boot) so every projection below is bound on the FIRST pass over a
364
- // freshly applied state. Deferring it would let a sibling app's switch render
365
- // once as this client's user before the pin corrected it. `null` for every
366
- // account-mode provider, where each projection falls back to the device's
367
- // active account exactly as before.
368
- const pinnedAccountId = identity ? await identity.ensurePinnedAccountId() : null;
369
- const ids = (0, _index.accountIdsOf)(state);
370
- let users = [];
371
- try {
372
- users = ids.length > 0 ? await oxyServices.getUsersByIds(ids) : [];
373
- } catch (fetchError) {
374
- logger('Failed to resolve account profiles during syncFromClient', fetchError);
375
- return;
376
- }
377
- const latest = sessionClient.getState();
378
- if (!latest || latest.revision !== capturedRevision) {
379
- return;
380
- }
381
- if (identity && (pinnedAccountId === null || (0, _index.activeSessionIdOf)(latest, pinnedAccountId) === null)) {
382
- // Either no verified pin, or the pinned account left this device's session
383
- // set. Projecting anything here would mean projecting SOMEBODY ELSE's
384
- // account, so leave the current projection untouched and re-derive the
385
- // session from the local identity key instead.
386
- reestablishIdentitySession(identity, latest.revision);
387
- return;
388
- }
389
- const usersById = new Map(users.map(resolvedUser => [resolvedUser.id, resolvedUser]));
390
- updateSessions((0, _index.deviceStateToClientSessions)(latest, usersById, pinnedAccountId));
391
- setActiveSessionId((0, _index.activeSessionIdOf)(latest, pinnedAccountId));
392
- const activeUser = (0, _index.activeUserOf)(latest, usersById, pinnedAccountId);
393
- if (activeUser) {
394
- loginSuccess(activeUser);
395
- }
396
- // The host's current account feeds the socket handshake and the bearer's
397
- // token-account comparisons, so it tracks the PIN — never the account another
398
- // app switched the device to.
399
- sessionClientHost.setCurrentAccountId(pinnedAccountId ?? latest.activeAccountId);
400
- }, [identity, oxyServices, reestablishIdentitySession, sessionClient, sessionClientHost, updateSessions, setActiveSessionId, loginSuccess, clearSessionState, logger]);
371
+ /**
372
+ * Project the server-authoritative device state onto the runtime.
373
+ *
374
+ * The projection itself lives in the runtime; this is the awaitable handle
375
+ * the commit/logout/reconnect paths already had. It is stable, because the
376
+ * runtime is.
377
+ */
378
+ const syncFromClient = (0, _react.useCallback)(() => runtime.reconcileFromClient(), [runtime]);
401
379
  const syncFromClientRef = (0, _react.useRef)(syncFromClient);
402
380
  syncFromClientRef.current = syncFromClient;
403
381
  const syncDeviceCredentialToHost = (0, _react.useCallback)(async () => {
404
382
  const cred = await (0, _deviceCredential.loadPersistedDeviceCredential)(authStore);
405
383
  sessionClientHost.setDeviceCredential(cred);
406
384
  }, [authStore, sessionClientHost]);
407
- (0, _react.useEffect)(() => {
408
- return sessionClient.subscribe(() => {
409
- void syncFromClient();
410
- });
411
- }, [sessionClient, syncFromClient]);
412
385
  const {
413
386
  signIn,
414
387
  logout,
@@ -417,9 +390,7 @@ const OxyProvider = ({
417
390
  oxyServices,
418
391
  store: authStore,
419
392
  storage,
420
- activeSessionId,
421
- setActiveSessionId,
422
- updateSessions,
393
+ runtime,
423
394
  saveActiveSessionId,
424
395
  clearSessionState,
425
396
  switchSession,
@@ -427,10 +398,6 @@ const OxyProvider = ({
427
398
  syncFromClient,
428
399
  onAuthStateChange,
429
400
  onError,
430
- loginSuccess,
431
- loginFailure,
432
- logoutStore,
433
- setAuthState,
434
401
  logger,
435
402
  ...(identity ? {
436
403
  identityBinding: identity.binding,
@@ -459,7 +426,6 @@ const OxyProvider = ({
459
426
  // Explicit FULL wipe: also drop the persisted device credential so a reload
460
427
  // finds nothing to restore.
461
428
  await authStore.clear();
462
- _accountStore.useAccountStore.getState().reset();
463
429
  oxyServices.clearCache();
464
430
  }, [queryClient, storage, clearSessionState, authStore, logger, oxyServices]);
465
431
  const {
@@ -473,7 +439,6 @@ const OxyProvider = ({
473
439
  clearSessionState,
474
440
  logger
475
441
  });
476
- const useFollowHook = (0, _oxyContextHelpers.loadUseFollowHook)();
477
442
 
478
443
  // Token-change side effects: an invalidated bearer (HttpService clears tokens
479
444
  // on an unrecoverable 401 and emits `null`) must locally sign out an
@@ -484,16 +449,16 @@ const OxyProvider = ({
484
449
  const clearingInvalidTokenRef = (0, _react.useRef)(false);
485
450
  (0, _react.useEffect)(() => {
486
451
  const handleTokenChange = accessToken => {
487
- setHasAccessToken(Boolean(accessToken));
452
+ runtime.setHasAccessToken(Boolean(accessToken));
488
453
  if (accessToken) {
489
- setTokenReady(true);
454
+ runtime.setTokenReady(true);
490
455
  if (sessionClient.getState()?.accounts.length) {
491
456
  void syncFromClientRef.current();
492
457
  }
493
458
  return;
494
459
  }
495
- if (userRef.current || isAuthenticatedRef.current) {
496
- setTokenReady(false);
460
+ if (runtime.getSnapshot().account !== null) {
461
+ runtime.setTokenReady(false);
497
462
  if (clearingInvalidTokenRef.current) {
498
463
  return;
499
464
  }
@@ -502,19 +467,19 @@ const OxyProvider = ({
502
467
  logger('Failed to clear invalidated auth session', clearError);
503
468
  }).finally(() => {
504
469
  clearingInvalidTokenRef.current = false;
505
- if (authResolvedRef.current) {
506
- setTokenReady(true);
470
+ if (runtime.getSnapshot().authResolved) {
471
+ runtime.setTokenReady(true);
507
472
  }
508
473
  });
509
474
  return;
510
475
  }
511
- if (authResolvedRef.current) {
512
- setTokenReady(true);
476
+ if (runtime.getSnapshot().authResolved) {
477
+ runtime.setTokenReady(true);
513
478
  }
514
479
  };
515
480
  handleTokenChange(oxyServices.getAccessToken());
516
481
  return oxyServices.onTokensChanged(handleTokenChange);
517
- }, [logger, oxyServices, sessionClient]);
482
+ }, [logger, oxyServices, runtime, sessionClient]);
518
483
 
519
484
  // Unified in-session refresh (SDK-owned; every RP inherits it). Installs the
520
485
  // ONE core refresh handler (re-mint from the persisted zero-cookie device
@@ -577,20 +542,25 @@ const OxyProvider = ({
577
542
  }
578
543
 
579
544
  // Fast local mirror so the UI updates before the server round-trip; the
580
- // SessionClient projection below overwrites it with server truth.
545
+ // SessionClient projection below overwrites it with server truth. Batched
546
+ // so the mirror and the active id land in ONE transition — unbatched, a
547
+ // subscriber woken between them would see the new session list still
548
+ // pointing at the previous active id.
581
549
  if (input.userId) {
582
550
  const now = new Date();
583
- updateSessions([{
584
- sessionId: input.sessionId,
585
- deviceId: input.deviceId ?? '',
586
- expiresAt: input.expiresAt || new Date(now.getTime() + _oxyContextHelpers.DEFAULT_SESSION_VALIDITY_MS).toISOString(),
587
- lastActive: now.toISOString(),
588
- userId: input.userId,
589
- isCurrent: true
590
- }], {
591
- merge: true
551
+ runtime.batch(() => {
552
+ runtime.mergeSessions([{
553
+ sessionId: input.sessionId,
554
+ deviceId: input.deviceId ?? '',
555
+ expiresAt: input.expiresAt || new Date(now.getTime() + _oxyContextHelpers.DEFAULT_SESSION_VALIDITY_MS).toISOString(),
556
+ lastActive: now.toISOString(),
557
+ userId: input.userId,
558
+ isCurrent: true
559
+ }], {
560
+ merge: true
561
+ });
562
+ runtime.setActiveSessionId(input.sessionId);
592
563
  });
593
- setActiveSessionId(input.sessionId);
594
564
  }
595
565
 
596
566
  // Register into the device set, hydrate the full user, and flip the
@@ -610,11 +580,11 @@ const OxyProvider = ({
610
580
  startSocket: () => sessionClient.start(),
611
581
  syncFromClient,
612
582
  getCurrentUser: () => oxyServices.getCurrentUser(),
613
- loginSuccess,
583
+ loginSuccess: fullUser => runtime.setAccount(fullUser),
614
584
  onAuthStateChange: onAuthStateChangeRef.current,
615
585
  markAuthResolved: markAuthResolvedRef.current
616
586
  });
617
- }, [oxyServices, authStore, updateSessions, setActiveSessionId, sessionClient, sessionClientHost, syncFromClient, loginSuccess, logger]);
587
+ }, [oxyServices, authStore, runtime, sessionClient, sessionClientHost, syncFromClient, logger]);
618
588
  const commitSessionRef = (0, _react.useRef)(commitSession);
619
589
  commitSessionRef.current = commitSession;
620
590
 
@@ -637,27 +607,6 @@ const OxyProvider = ({
637
607
  });
638
608
  }, [commitSession]);
639
609
 
640
- // Commit a minted graph-SWITCH session through the same funnel as
641
- // `handleWebSession`. Nothing extra to do IN-PLACE: the switch already
642
- // propagates across tabs/apps via the server's `session_state` socket
643
- // broadcast.
644
- const commitSwitchedSession = (0, _react.useCallback)(async session => {
645
- if (!session?.user || !session?.sessionId || !session.accessToken) {
646
- throw new Error('Session response did not include a usable session');
647
- }
648
- await commitSession({
649
- sessionId: session.sessionId,
650
- accessToken: session.accessToken,
651
- deviceSecret: session.deviceSecret,
652
- deviceId: session.deviceId,
653
- expiresAt: session.expiresAt,
654
- userId: session.user.id,
655
- user: session.user
656
- }, {
657
- activate: true
658
- });
659
- }, [commitSession]);
660
-
661
610
  // ── Web third-party OAuth sign-in ──────────────────────────────────────────
662
611
  // The shared operation `OxySignInButton` (and any RP-owned button) delegates
663
612
  // to, so no consumer ever writes popup listeners or a token exchange. The
@@ -677,13 +626,11 @@ const OxyProvider = ({
677
626
  // ── Unified account dialog ─────────────────────────────────────────────────
678
627
  // The single account-chooser + sign-in surface. Built ONCE per provider mount
679
628
  // and bound to the live `oxyServices` + `sessionClient` + this provider's
680
- // commit funnels. Both funnels are threaded through refs so the controller
681
- // keeps STABLE commit callbacks (rebuilding the controller on every
682
- // commit-identity change would drop its subscription + state).
629
+ // sign-in commit funnel, threaded through a ref so the controller keeps a
630
+ // STABLE commit callback (rebuilding the controller on every commit-identity
631
+ // change would drop its subscription + state).
683
632
  const handleWebSessionRef = (0, _react.useRef)(handleWebSession);
684
633
  handleWebSessionRef.current = handleWebSession;
685
- const commitSwitchedSessionRef = (0, _react.useRef)(commitSwitchedSession);
686
- commitSwitchedSessionRef.current = commitSwitchedSession;
687
634
 
688
635
  // The live AccountDialog surface (a stacked Bloom surface), while open — the
689
636
  // SINGLE source of truth for "is the account dialog open". Held so
@@ -726,12 +673,10 @@ const OxyProvider = ({
726
673
  oxyServices,
727
674
  sessionClient,
728
675
  clientId,
729
- locale: currentLanguage,
730
676
  // Same statically-injected `io` as the SessionClient: gives the QR flow an
731
677
  // instant `/auth-session` `auth_update` wake instead of a slow poll.
732
678
  socketFactory: _socket.io,
733
679
  commitSession: session => handleWebSessionRef.current(session),
734
- commitSwitchedSession: session => commitSwitchedSessionRef.current(session),
735
680
  onSignedIn: () => {
736
681
  // Close the dialog: pop the morphed frame back to its host surface, or
737
682
  // dismiss the detached surface (whose settle flips `accountDialogOpen`).
@@ -950,7 +895,7 @@ const OxyProvider = ({
950
895
  if (identity) {
951
896
  await identity.refreshPinnedAccountId();
952
897
  }
953
- }, [oxyServices, authStore, clientIdProp, authRedirectUri, sessionMode, identity, syncDeviceCredentialToHost, sessionClient]);
898
+ }, [oxyServices, authStore, clientIdProp, authRedirectUri, sessionMode, identity, syncDeviceCredentialToHost, sessionClient, setTokenReady]);
954
899
  (0, _react.useEffect)(() => {
955
900
  if (initialized) {
956
901
  return;
@@ -1041,7 +986,7 @@ const OxyProvider = ({
1041
986
  // `switchToAccount`, so leaving it live would be a bypass around the same rule.
1042
987
  const switchSessionForContext = (0, _react.useCallback)(async sessionId => {
1043
988
  if (isIdentityBound) {
1044
- throw new _index.IdentityBoundSessionError('switchSession');
989
+ throw new _index2.IdentityBoundSessionError('switchSession');
1045
990
  }
1046
991
  const targetAccountId = sessionClient.getState()?.accounts.find(account => account.sessionId === sessionId)?.accountId;
1047
992
  if (!targetAccountId) {
@@ -1049,12 +994,12 @@ const OxyProvider = ({
1049
994
  }
1050
995
  await sessionClient.switchAccount(targetAccountId);
1051
996
  await syncFromClient();
1052
- const activeUser = _authStore.useAuthStore.getState().user;
997
+ const activeUser = runtime.getSnapshot().account;
1053
998
  if (!activeUser) {
1054
999
  throw new Error('Active account profile could not be resolved after switch');
1055
1000
  }
1056
1001
  return activeUser;
1057
- }, [isIdentityBound, sessionClient, syncFromClient]);
1002
+ }, [isIdentityBound, runtime, sessionClient, syncFromClient]);
1058
1003
 
1059
1004
  // Thin passthroughs to the platform-agnostic KeyManager. NOTE: both now THROW
1060
1005
  // `IdentityUnavailableError` (from `@oxyhq/core`) when identity storage is
@@ -1090,10 +1035,44 @@ const OxyProvider = ({
1090
1035
  sessionClient,
1091
1036
  syncFromClient,
1092
1037
  commitSession,
1093
- queryClient,
1094
1038
  accountDialogControllerRef,
1095
1039
  clearSessionStateRef
1096
1040
  });
1041
+
1042
+ // The account-scoped cache reset, run by the runtime BETWEEN committing the
1043
+ // new subject's bearer and waking anybody (ADR 0002). It used to trail the two
1044
+ // branches of `switchToAccount`, which meant a switch pushed over the socket
1045
+ // by another app on this device got none of it: the follow stores, the scoped
1046
+ // media URLs and every warm query stayed on the previous subject until
1047
+ // something happened to refetch.
1048
+ //
1049
+ // An initial sign-in is deliberately exempt. There is nothing account-scoped
1050
+ // cached before the first account, so invalidating everything there would only
1051
+ // buy a refetch storm at first paint.
1052
+ const handleSubjectChange = (0, _react.useCallback)(({
1053
+ previous,
1054
+ next
1055
+ }) => {
1056
+ if (previous === null) {
1057
+ return;
1058
+ }
1059
+ (0, _resetSessionScopedStores.resetSessionScopedStores)();
1060
+ if (next === null) {
1061
+ // A sign-out: `clearSessionState` owns the rest of the teardown, and
1062
+ // invalidating a cache we are about to clear would only refetch as the
1063
+ // bearer disappears.
1064
+ return;
1065
+ }
1066
+ // Scoped media tokens are per-viewer — drop any cached URLs immediately so
1067
+ // `keepPreviousData`-style placeholders cannot flash the prior account's
1068
+ // private thumbnails while the new bearer mint lands.
1069
+ queryClient.removeQueries({
1070
+ queryKey: [_useResolvedFileUrls.ASSET_DOWNLOAD_URLS_QUERY_KEY]
1071
+ });
1072
+ queryClient.invalidateQueries();
1073
+ void refreshAccounts();
1074
+ }, [queryClient, refreshAccounts]);
1075
+ subjectChangeRef.current = handleSubjectChange;
1097
1076
  const canUsePrivateApi = authResolved && isAuthenticated && tokenReady && hasAccessToken;
1098
1077
  const isPrivateApiPending = !authResolved || isAuthenticated && (!tokenReady || !hasAccessToken);
1099
1078
 
@@ -1102,7 +1081,7 @@ const OxyProvider = ({
1102
1081
  // unless the app opted in. Placed AFTER `canUsePrivateApi` because provisioning
1103
1082
  // needs a bearer, and keyed on the signed-in account so a sign-out or an
1104
1083
  // account switch revokes the credential before anything else happens.
1105
- (0, _index.useBackgroundSessionSync)({
1084
+ (0, _index2.useBackgroundSessionSync)({
1106
1085
  enabled: backgroundSession,
1107
1086
  oxyServices,
1108
1087
  userId: user?.id ?? null,
@@ -1119,7 +1098,7 @@ const OxyProvider = ({
1119
1098
  canUsePrivateApi,
1120
1099
  isPrivateApiPending,
1121
1100
  isAuthResolved: authResolved,
1122
- isStorageReady: storage !== null,
1101
+ isStorageReady: snapshot.storageReady,
1123
1102
  sessionMode: isIdentityBound ? 'identity' : 'account',
1124
1103
  webAuthMode,
1125
1104
  error,
@@ -1153,7 +1132,7 @@ const OxyProvider = ({
1153
1132
  clientId,
1154
1133
  oxyServices,
1155
1134
  sessionClient,
1156
- useFollow: useFollowHook,
1135
+ useFollow: _useFollow.useFollow,
1157
1136
  showBottomSheet: showBottomSheetForContext,
1158
1137
  openAvatarPicker,
1159
1138
  accountDialogController,
@@ -1164,85 +1143,57 @@ const OxyProvider = ({
1164
1143
  switchToAccount,
1165
1144
  refreshAccounts,
1166
1145
  createAccount: createAccountFn
1167
- }), [user, sessions, activeSessionId, isAuthenticated, isLoading, tokenReady, hasAccessToken, canUsePrivateApi, isPrivateApiPending, authResolved, storage, isIdentityBound, webAuthMode, error, currentLanguage, currentLanguages, currentLanguageMetadata, currentLanguageName, currentNativeLanguageName, hasIdentity, getPublicKey, signIn, signInWithPasskey, registerWithPasskey, addPasskey, removePasskey, revokeSuspiciousSignIn, handleWebSession, startWebOAuthSignInForContext, logout, logoutAll, switchSessionForContext, refreshSessionsForContext, setLanguage, getDeviceSessions, logoutAllDeviceSessions, updateDeviceName, clearSessionState, clearAllAccountData, storageKeyPrefix, clientId, oxyServices, sessionClient, useFollowHook, showBottomSheetForContext, openAvatarPicker, accountDialogController, accountDialogOpen, openAccountDialog, closeAccountDialog, accounts, switchToAccount, refreshAccounts, createAccountFn]);
1168
- return /*#__PURE__*/(0, _jsxRuntime.jsx)(OxyContext.Provider, {
1169
- value: contextValue,
1170
- children: children
1146
+ }), [user, sessions, activeSessionId, isAuthenticated, isLoading, tokenReady, hasAccessToken, canUsePrivateApi, isPrivateApiPending, authResolved, snapshot.storageReady, isIdentityBound, webAuthMode, error, currentLanguage, currentLanguages, currentLanguageMetadata, currentLanguageName, currentNativeLanguageName, hasIdentity, getPublicKey, signIn, signInWithPasskey, registerWithPasskey, addPasskey, removePasskey, revokeSuspiciousSignIn, handleWebSession, startWebOAuthSignInForContext, logout, logoutAll, switchSessionForContext, refreshSessionsForContext, setLanguage, getDeviceSessions, logoutAllDeviceSessions, updateDeviceName, clearSessionState, clearAllAccountData, storageKeyPrefix, clientId, oxyServices, sessionClient, showBottomSheetForContext, openAvatarPicker, accountDialogController, accountDialogOpen, openAccountDialog, closeAccountDialog, accounts, switchToAccount, refreshAccounts, createAccountFn]);
1147
+
1148
+ // Two contexts, deliberately. The inner one carries the wide compatibility
1149
+ // value every `useOxy()` consumer reads, rebuilt whenever any of its members
1150
+ // moves. The outer one carries the runtime reference, which never changes
1151
+ // identity — so `useActiveAccount()` and friends re-render on the fact they
1152
+ // selected and nothing else. Phase 8 retires the inner one.
1153
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_index.OxyRuntimeHandleProvider, {
1154
+ value: runtime,
1155
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(OxyRuntimeContext.Provider, {
1156
+ value: contextValue,
1157
+ children: children
1158
+ })
1171
1159
  });
1172
1160
  };
1173
- exports.OxyProvider = OxyProvider;
1174
- const OxyContextProvider = exports.OxyContextProvider = OxyProvider;
1161
+ exports.OxyRuntimeProvider = OxyRuntimeProvider;
1162
+ const PROVIDER_MISSING_ERROR_MESSAGE = 'useOxy() was called outside <OxyProvider>. Mount <OxyProvider clientId="…"> above this component, ' + 'or use useOptionalOxy() if this component legitimately renders both inside and outside the provider.';
1163
+ class OxyProviderMissingError extends Error {
1164
+ code = 'oxy_provider_missing';
1165
+ constructor() {
1166
+ super(PROVIDER_MISSING_ERROR_MESSAGE);
1167
+ this.name = 'OxyProviderMissingError';
1168
+ }
1169
+ }
1175
1170
 
1176
1171
  /**
1177
- * Loading-state stub used when `useOxy()` is called outside an OxyProvider.
1178
- * All async methods reject with a clear error so misuse is caught early.
1172
+ * The base runtime hook. THROWS when no `<OxyProvider>` is mounted.
1173
+ *
1174
+ * It used to return a fabricated forever-loading runtime — `isLoading: true`,
1175
+ * `isPrivateApiPending: true`, every method a rejecting no-op — which turned a
1176
+ * missing provider into a UI that spins forever with nothing in the console.
1177
+ * Failing here names the mistake at the exact component that made it (ADR 0004).
1178
+ *
1179
+ * A component that legitimately renders both inside and outside the provider
1180
+ * uses {@link useOptionalOxy} instead.
1179
1181
  */
1180
- const PROVIDER_MISSING_ERROR_MESSAGE = 'OxyProvider is not mounted. Wrap your app in <OxyProvider> before calling useOxy() methods.';
1181
- const rejectMissingProvider = () => Promise.reject(new Error(PROVIDER_MISSING_ERROR_MESSAGE));
1182
- const LOADING_STATE_OXY_SERVICES = new _core.OxyServices({
1183
- baseURL: 'about:blank'
1184
- });
1185
- const LOADING_STATE = {
1186
- user: null,
1187
- sessions: [],
1188
- activeSessionId: null,
1189
- isAuthenticated: false,
1190
- isLoading: true,
1191
- isTokenReady: false,
1192
- hasAccessToken: false,
1193
- canUsePrivateApi: false,
1194
- isPrivateApiPending: true,
1195
- isAuthResolved: false,
1196
- isStorageReady: false,
1197
- sessionMode: 'account',
1198
- webAuthMode: 'popup',
1199
- error: null,
1200
- currentLanguage: 'en-US',
1201
- currentLanguages: [],
1202
- currentLanguageMetadata: null,
1203
- currentLanguageName: 'English (United States)',
1204
- currentNativeLanguageName: 'English (United States)',
1205
- hasIdentity: () => Promise.resolve(false),
1206
- getPublicKey: () => Promise.resolve(null),
1207
- signIn: () => rejectMissingProvider(),
1208
- signInWithPasskey: () => rejectMissingProvider(),
1209
- registerWithPasskey: () => rejectMissingProvider(),
1210
- addPasskey: () => rejectMissingProvider(),
1211
- removePasskey: () => rejectMissingProvider(),
1212
- revokeSuspiciousSignIn: () => rejectMissingProvider(),
1213
- handleWebSession: () => rejectMissingProvider(),
1214
- startWebOAuthSignIn: () => rejectMissingProvider(),
1215
- logout: () => rejectMissingProvider(),
1216
- logoutAll: () => rejectMissingProvider(),
1217
- switchSession: () => rejectMissingProvider(),
1218
- removeSession: () => rejectMissingProvider(),
1219
- refreshSessions: () => rejectMissingProvider(),
1220
- setLanguage: () => rejectMissingProvider(),
1221
- getDeviceSessions: () => Promise.resolve([]),
1222
- logoutAllDeviceSessions: () => rejectMissingProvider(),
1223
- updateDeviceName: () => rejectMissingProvider(),
1224
- clearSessionState: () => rejectMissingProvider(),
1225
- clearAllAccountData: () => rejectMissingProvider(),
1226
- storageKeyPrefix: 'oxy_session',
1227
- clientId: null,
1228
- oxyServices: LOADING_STATE_OXY_SERVICES,
1229
- sessionClient: null,
1230
- openAvatarPicker: () => {},
1231
- accountDialogController: null,
1232
- isAccountDialogOpen: false,
1233
- openAccountDialog: () => {},
1234
- closeAccountDialog: () => {},
1235
- accounts: [],
1236
- switchToAccount: () => rejectMissingProvider(),
1237
- refreshAccounts: () => rejectMissingProvider(),
1238
- createAccount: () => rejectMissingProvider()
1239
- };
1182
+ exports.OxyProviderMissingError = OxyProviderMissingError;
1240
1183
  const useOxy = () => {
1241
- const context = (0, _react.useContext)(OxyContext);
1184
+ const context = (0, _react.useContext)(OxyRuntimeContext);
1242
1185
  if (!context) {
1243
- return LOADING_STATE;
1186
+ throw new OxyProviderMissingError();
1244
1187
  }
1245
1188
  return context;
1246
1189
  };
1190
+
1191
+ /**
1192
+ * `useOxy()` for the rare component that renders both inside and outside the
1193
+ * provider — returns `null` instead of throwing. Callers must handle `null`;
1194
+ * there is no fabricated runtime to fall back on.
1195
+ */
1247
1196
  exports.useOxy = useOxy;
1197
+ const useOptionalOxy = () => (0, _react.useContext)(OxyRuntimeContext);
1198
+ exports.useOptionalOxy = useOptionalOxy;
1248
1199
  //# sourceMappingURL=OxyContext.js.map