@oxyhq/services 14.1.0 → 16.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 (292) hide show
  1. package/lib/commonjs/index.js +4 -21
  2. package/lib/commonjs/index.js.map +1 -1
  3. package/lib/commonjs/ui/components/SignInAccountChooser.js +189 -0
  4. package/lib/commonjs/ui/components/SignInAccountChooser.js.map +1 -0
  5. package/lib/commonjs/ui/components/SignInModal.js +350 -131
  6. package/lib/commonjs/ui/components/SignInModal.js.map +1 -1
  7. package/lib/commonjs/ui/context/OxyContext.js +340 -1547
  8. package/lib/commonjs/ui/context/OxyContext.js.map +1 -1
  9. package/lib/commonjs/ui/context/hooks/useAuthOperations.js +61 -64
  10. package/lib/commonjs/ui/context/hooks/useAuthOperations.js.map +1 -1
  11. package/lib/commonjs/ui/hooks/mutations/mutationKeys.js +1 -1
  12. package/lib/commonjs/ui/hooks/mutations/useAccountMutations.js +9 -9
  13. package/lib/commonjs/ui/hooks/mutations/useAccountMutations.js.map +1 -1
  14. package/lib/commonjs/ui/hooks/queries/queryKeys.js +1 -1
  15. package/lib/commonjs/ui/hooks/queries/useAccountQueries.js +7 -8
  16. package/lib/commonjs/ui/hooks/queries/useAccountQueries.js.map +1 -1
  17. package/lib/commonjs/ui/hooks/useAuth.js +14 -33
  18. package/lib/commonjs/ui/hooks/useAuth.js.map +1 -1
  19. package/lib/commonjs/ui/hooks/usePasswordSignIn.js +170 -0
  20. package/lib/commonjs/ui/hooks/usePasswordSignIn.js.map +1 -0
  21. package/lib/commonjs/ui/hooks/useProfileEditing.js +2 -5
  22. package/lib/commonjs/ui/hooks/useProfileEditing.js.map +1 -1
  23. package/lib/commonjs/ui/hooks/useSessionManagement.js +2 -2
  24. package/lib/commonjs/ui/hooks/useSessionManagement.js.map +1 -1
  25. package/lib/commonjs/ui/navigation/routes.js +1 -0
  26. package/lib/commonjs/ui/navigation/routes.js.map +1 -1
  27. package/lib/commonjs/ui/screens/ConnectedAppsScreen.js +17 -18
  28. package/lib/commonjs/ui/screens/ConnectedAppsScreen.js.map +1 -1
  29. package/lib/commonjs/ui/screens/EditProfileFieldScreen.js +93 -68
  30. package/lib/commonjs/ui/screens/EditProfileFieldScreen.js.map +1 -1
  31. package/lib/commonjs/ui/screens/EditProfileScreen.js +187 -0
  32. package/lib/commonjs/ui/screens/EditProfileScreen.js.map +1 -0
  33. package/lib/commonjs/ui/screens/ManageAccountScreen.js +3 -7
  34. package/lib/commonjs/ui/screens/ManageAccountScreen.js.map +1 -1
  35. package/lib/commonjs/ui/screens/OxyAuthScreen.js +231 -95
  36. package/lib/commonjs/ui/screens/OxyAuthScreen.js.map +1 -1
  37. package/lib/commonjs/ui/screens/ProfileScreen.js +15 -2
  38. package/lib/commonjs/ui/screens/ProfileScreen.js.map +1 -1
  39. package/lib/commonjs/ui/screens/linkFormat.js +38 -0
  40. package/lib/commonjs/ui/screens/linkFormat.js.map +1 -0
  41. package/lib/commonjs/ui/session/authStore.js +146 -0
  42. package/lib/commonjs/ui/session/authStore.js.map +1 -0
  43. package/lib/commonjs/ui/session/createSessionClient.js +23 -17
  44. package/lib/commonjs/ui/session/createSessionClient.js.map +1 -1
  45. package/lib/commonjs/ui/session/index.js +13 -7
  46. package/lib/commonjs/ui/session/index.js.map +1 -1
  47. package/lib/commonjs/ui/session/tokenTransport.js +19 -31
  48. package/lib/commonjs/ui/session/tokenTransport.js.map +1 -1
  49. package/lib/commonjs/ui/utils/isWebBrowser.js +13 -0
  50. package/lib/commonjs/ui/utils/isWebBrowser.js.map +1 -0
  51. package/lib/commonjs/utils/deviceFlowSignIn.js +13 -16
  52. package/lib/commonjs/utils/deviceFlowSignIn.js.map +1 -1
  53. package/lib/module/index.js +2 -7
  54. package/lib/module/index.js.map +1 -1
  55. package/lib/module/ui/components/SignInAccountChooser.js +183 -0
  56. package/lib/module/ui/components/SignInAccountChooser.js.map +1 -0
  57. package/lib/module/ui/components/SignInModal.js +352 -134
  58. package/lib/module/ui/components/SignInModal.js.map +1 -1
  59. package/lib/module/ui/context/OxyContext.js +342 -1551
  60. package/lib/module/ui/context/OxyContext.js.map +1 -1
  61. package/lib/module/ui/context/hooks/useAuthOperations.js +60 -63
  62. package/lib/module/ui/context/hooks/useAuthOperations.js.map +1 -1
  63. package/lib/module/ui/hooks/mutations/mutationKeys.js +1 -1
  64. package/lib/module/ui/hooks/mutations/useAccountMutations.js +7 -7
  65. package/lib/module/ui/hooks/mutations/useAccountMutations.js.map +1 -1
  66. package/lib/module/ui/hooks/queries/queryKeys.js +1 -1
  67. package/lib/module/ui/hooks/queries/useAccountQueries.js +5 -6
  68. package/lib/module/ui/hooks/queries/useAccountQueries.js.map +1 -1
  69. package/lib/module/ui/hooks/useAuth.js +14 -33
  70. package/lib/module/ui/hooks/useAuth.js.map +1 -1
  71. package/lib/module/ui/hooks/usePasswordSignIn.js +165 -0
  72. package/lib/module/ui/hooks/usePasswordSignIn.js.map +1 -0
  73. package/lib/module/ui/hooks/useProfileEditing.js +2 -5
  74. package/lib/module/ui/hooks/useProfileEditing.js.map +1 -1
  75. package/lib/module/ui/hooks/useSessionManagement.js +1 -1
  76. package/lib/module/ui/hooks/useSessionManagement.js.map +1 -1
  77. package/lib/module/ui/navigation/routes.js +1 -0
  78. package/lib/module/ui/navigation/routes.js.map +1 -1
  79. package/lib/module/ui/screens/ConnectedAppsScreen.js +19 -20
  80. package/lib/module/ui/screens/ConnectedAppsScreen.js.map +1 -1
  81. package/lib/module/ui/screens/EditProfileFieldScreen.js +91 -66
  82. package/lib/module/ui/screens/EditProfileFieldScreen.js.map +1 -1
  83. package/lib/module/ui/screens/EditProfileScreen.js +182 -0
  84. package/lib/module/ui/screens/EditProfileScreen.js.map +1 -0
  85. package/lib/module/ui/screens/ManageAccountScreen.js +3 -7
  86. package/lib/module/ui/screens/ManageAccountScreen.js.map +1 -1
  87. package/lib/module/ui/screens/OxyAuthScreen.js +233 -97
  88. package/lib/module/ui/screens/OxyAuthScreen.js.map +1 -1
  89. package/lib/module/ui/screens/ProfileScreen.js +15 -2
  90. package/lib/module/ui/screens/ProfileScreen.js.map +1 -1
  91. package/lib/module/ui/screens/linkFormat.js +31 -0
  92. package/lib/module/ui/screens/linkFormat.js.map +1 -0
  93. package/lib/module/ui/session/authStore.js +143 -0
  94. package/lib/module/ui/session/authStore.js.map +1 -0
  95. package/lib/module/ui/session/createSessionClient.js +22 -16
  96. package/lib/module/ui/session/createSessionClient.js.map +1 -1
  97. package/lib/module/ui/session/index.js +9 -9
  98. package/lib/module/ui/session/index.js.map +1 -1
  99. package/lib/module/ui/session/tokenTransport.js +20 -33
  100. package/lib/module/ui/session/tokenTransport.js.map +1 -1
  101. package/lib/module/ui/utils/isWebBrowser.js +11 -0
  102. package/lib/module/ui/utils/isWebBrowser.js.map +1 -0
  103. package/lib/module/utils/deviceFlowSignIn.js +14 -17
  104. package/lib/module/utils/deviceFlowSignIn.js.map +1 -1
  105. package/lib/typescript/commonjs/index.d.ts +2 -3
  106. package/lib/typescript/commonjs/index.d.ts.map +1 -1
  107. package/lib/typescript/commonjs/ui/components/SignInAccountChooser.d.ts +29 -0
  108. package/lib/typescript/commonjs/ui/components/SignInAccountChooser.d.ts.map +1 -0
  109. package/lib/typescript/commonjs/ui/components/SignInModal.d.ts +15 -10
  110. package/lib/typescript/commonjs/ui/components/SignInModal.d.ts.map +1 -1
  111. package/lib/typescript/commonjs/ui/context/OxyContext.d.ts +36 -42
  112. package/lib/typescript/commonjs/ui/context/OxyContext.d.ts.map +1 -1
  113. package/lib/typescript/commonjs/ui/context/hooks/useAuthOperations.d.ts +18 -23
  114. package/lib/typescript/commonjs/ui/context/hooks/useAuthOperations.d.ts.map +1 -1
  115. package/lib/typescript/commonjs/ui/hooks/mutations/useAccountMutations.d.ts +4 -6
  116. package/lib/typescript/commonjs/ui/hooks/mutations/useAccountMutations.d.ts.map +1 -1
  117. package/lib/typescript/commonjs/ui/hooks/queries/useAccountQueries.d.ts +6 -7
  118. package/lib/typescript/commonjs/ui/hooks/queries/useAccountQueries.d.ts.map +1 -1
  119. package/lib/typescript/commonjs/ui/hooks/useAuth.d.ts.map +1 -1
  120. package/lib/typescript/commonjs/ui/hooks/usePasswordSignIn.d.ts +31 -0
  121. package/lib/typescript/commonjs/ui/hooks/usePasswordSignIn.d.ts.map +1 -0
  122. package/lib/typescript/commonjs/ui/hooks/useProfileEditing.d.ts +0 -1
  123. package/lib/typescript/commonjs/ui/hooks/useProfileEditing.d.ts.map +1 -1
  124. package/lib/typescript/commonjs/ui/navigation/routes.d.ts +1 -1
  125. package/lib/typescript/commonjs/ui/navigation/routes.d.ts.map +1 -1
  126. package/lib/typescript/commonjs/ui/screens/ConnectedAppsScreen.d.ts.map +1 -1
  127. package/lib/typescript/commonjs/ui/screens/EditProfileFieldScreen.d.ts.map +1 -1
  128. package/lib/typescript/commonjs/ui/screens/EditProfileScreen.d.ts +14 -0
  129. package/lib/typescript/commonjs/ui/screens/EditProfileScreen.d.ts.map +1 -0
  130. package/lib/typescript/commonjs/ui/screens/ManageAccountScreen.d.ts +1 -1
  131. package/lib/typescript/commonjs/ui/screens/ManageAccountScreen.d.ts.map +1 -1
  132. package/lib/typescript/commonjs/ui/screens/OxyAuthScreen.d.ts +13 -12
  133. package/lib/typescript/commonjs/ui/screens/OxyAuthScreen.d.ts.map +1 -1
  134. package/lib/typescript/commonjs/ui/screens/ProfileScreen.d.ts.map +1 -1
  135. package/lib/typescript/commonjs/ui/screens/linkFormat.d.ts +23 -0
  136. package/lib/typescript/commonjs/ui/screens/linkFormat.d.ts.map +1 -0
  137. package/lib/typescript/commonjs/ui/session/authStore.d.ts +33 -0
  138. package/lib/typescript/commonjs/ui/session/authStore.d.ts.map +1 -0
  139. package/lib/typescript/commonjs/ui/session/createSessionClient.d.ts +19 -15
  140. package/lib/typescript/commonjs/ui/session/createSessionClient.d.ts.map +1 -1
  141. package/lib/typescript/commonjs/ui/session/index.d.ts +9 -9
  142. package/lib/typescript/commonjs/ui/session/index.d.ts.map +1 -1
  143. package/lib/typescript/commonjs/ui/session/tokenTransport.d.ts +13 -19
  144. package/lib/typescript/commonjs/ui/session/tokenTransport.d.ts.map +1 -1
  145. package/lib/typescript/commonjs/ui/utils/isWebBrowser.d.ts +9 -0
  146. package/lib/typescript/commonjs/ui/utils/isWebBrowser.d.ts.map +1 -0
  147. package/lib/typescript/commonjs/ui/utils/storageHelpers.d.ts +7 -7
  148. package/lib/typescript/commonjs/utils/deviceFlowSignIn.d.ts +15 -13
  149. package/lib/typescript/commonjs/utils/deviceFlowSignIn.d.ts.map +1 -1
  150. package/lib/typescript/module/index.d.ts +2 -3
  151. package/lib/typescript/module/index.d.ts.map +1 -1
  152. package/lib/typescript/module/ui/components/SignInAccountChooser.d.ts +29 -0
  153. package/lib/typescript/module/ui/components/SignInAccountChooser.d.ts.map +1 -0
  154. package/lib/typescript/module/ui/components/SignInModal.d.ts +15 -10
  155. package/lib/typescript/module/ui/components/SignInModal.d.ts.map +1 -1
  156. package/lib/typescript/module/ui/context/OxyContext.d.ts +36 -42
  157. package/lib/typescript/module/ui/context/OxyContext.d.ts.map +1 -1
  158. package/lib/typescript/module/ui/context/hooks/useAuthOperations.d.ts +18 -23
  159. package/lib/typescript/module/ui/context/hooks/useAuthOperations.d.ts.map +1 -1
  160. package/lib/typescript/module/ui/hooks/mutations/useAccountMutations.d.ts +4 -6
  161. package/lib/typescript/module/ui/hooks/mutations/useAccountMutations.d.ts.map +1 -1
  162. package/lib/typescript/module/ui/hooks/queries/useAccountQueries.d.ts +6 -7
  163. package/lib/typescript/module/ui/hooks/queries/useAccountQueries.d.ts.map +1 -1
  164. package/lib/typescript/module/ui/hooks/useAuth.d.ts.map +1 -1
  165. package/lib/typescript/module/ui/hooks/usePasswordSignIn.d.ts +31 -0
  166. package/lib/typescript/module/ui/hooks/usePasswordSignIn.d.ts.map +1 -0
  167. package/lib/typescript/module/ui/hooks/useProfileEditing.d.ts +0 -1
  168. package/lib/typescript/module/ui/hooks/useProfileEditing.d.ts.map +1 -1
  169. package/lib/typescript/module/ui/navigation/routes.d.ts +1 -1
  170. package/lib/typescript/module/ui/navigation/routes.d.ts.map +1 -1
  171. package/lib/typescript/module/ui/screens/ConnectedAppsScreen.d.ts.map +1 -1
  172. package/lib/typescript/module/ui/screens/EditProfileFieldScreen.d.ts.map +1 -1
  173. package/lib/typescript/module/ui/screens/EditProfileScreen.d.ts +14 -0
  174. package/lib/typescript/module/ui/screens/EditProfileScreen.d.ts.map +1 -0
  175. package/lib/typescript/module/ui/screens/ManageAccountScreen.d.ts +1 -1
  176. package/lib/typescript/module/ui/screens/ManageAccountScreen.d.ts.map +1 -1
  177. package/lib/typescript/module/ui/screens/OxyAuthScreen.d.ts +13 -12
  178. package/lib/typescript/module/ui/screens/OxyAuthScreen.d.ts.map +1 -1
  179. package/lib/typescript/module/ui/screens/ProfileScreen.d.ts.map +1 -1
  180. package/lib/typescript/module/ui/screens/linkFormat.d.ts +23 -0
  181. package/lib/typescript/module/ui/screens/linkFormat.d.ts.map +1 -0
  182. package/lib/typescript/module/ui/session/authStore.d.ts +33 -0
  183. package/lib/typescript/module/ui/session/authStore.d.ts.map +1 -0
  184. package/lib/typescript/module/ui/session/createSessionClient.d.ts +19 -15
  185. package/lib/typescript/module/ui/session/createSessionClient.d.ts.map +1 -1
  186. package/lib/typescript/module/ui/session/index.d.ts +9 -9
  187. package/lib/typescript/module/ui/session/index.d.ts.map +1 -1
  188. package/lib/typescript/module/ui/session/tokenTransport.d.ts +13 -19
  189. package/lib/typescript/module/ui/session/tokenTransport.d.ts.map +1 -1
  190. package/lib/typescript/module/ui/utils/isWebBrowser.d.ts +9 -0
  191. package/lib/typescript/module/ui/utils/isWebBrowser.d.ts.map +1 -0
  192. package/lib/typescript/module/ui/utils/storageHelpers.d.ts +7 -7
  193. package/lib/typescript/module/utils/deviceFlowSignIn.d.ts +15 -13
  194. package/lib/typescript/module/utils/deviceFlowSignIn.d.ts.map +1 -1
  195. package/package.json +4 -4
  196. package/src/index.ts +2 -6
  197. package/src/ui/components/SignInAccountChooser.tsx +162 -0
  198. package/src/ui/components/SignInModal.tsx +309 -139
  199. package/src/ui/context/OxyContext.tsx +532 -1785
  200. package/src/ui/context/hooks/useAuthOperations.ts +65 -76
  201. package/src/ui/hooks/mutations/mutationKeys.ts +1 -1
  202. package/src/ui/hooks/mutations/useAccountMutations.ts +7 -7
  203. package/src/ui/hooks/queries/queryKeys.ts +1 -1
  204. package/src/ui/hooks/queries/useAccountQueries.ts +8 -9
  205. package/src/ui/hooks/useAuth.ts +14 -35
  206. package/src/ui/hooks/usePasswordSignIn.ts +207 -0
  207. package/src/ui/hooks/useProfileEditing.ts +2 -8
  208. package/src/ui/hooks/useSessionManagement.ts +1 -1
  209. package/src/ui/navigation/routes.ts +3 -1
  210. package/src/ui/screens/ConnectedAppsScreen.tsx +23 -24
  211. package/src/ui/screens/EditProfileFieldScreen.tsx +102 -66
  212. package/src/ui/screens/EditProfileScreen.tsx +155 -0
  213. package/src/ui/screens/ManageAccountScreen.tsx +3 -7
  214. package/src/ui/screens/OxyAuthScreen.tsx +259 -112
  215. package/src/ui/screens/ProfileScreen.tsx +15 -2
  216. package/src/ui/screens/__tests__/linkFormat.test.ts +73 -0
  217. package/src/ui/screens/linkFormat.ts +37 -0
  218. package/src/ui/session/__tests__/createSessionClient.test.ts +22 -7
  219. package/src/ui/session/__tests__/tokenTransport.test.ts +37 -49
  220. package/src/ui/session/authStore.ts +164 -0
  221. package/src/ui/session/createSessionClient.ts +30 -17
  222. package/src/ui/session/index.ts +10 -9
  223. package/src/ui/session/tokenTransport.ts +26 -36
  224. package/src/ui/utils/isWebBrowser.ts +8 -0
  225. package/src/ui/utils/storageHelpers.ts +7 -7
  226. package/src/utils/__tests__/deviceFlowSignIn.test.ts +50 -131
  227. package/src/utils/deviceFlowSignIn.ts +19 -26
  228. package/lib/commonjs/ui/context/inSessionTokenRefresh.js +0 -243
  229. package/lib/commonjs/ui/context/inSessionTokenRefresh.js.map +0 -1
  230. package/lib/commonjs/ui/context/silentSessionRestore.js +0 -56
  231. package/lib/commonjs/ui/context/silentSessionRestore.js.map +0 -1
  232. package/lib/commonjs/ui/hooks/useWebSSO.js +0 -28
  233. package/lib/commonjs/ui/hooks/useWebSSO.js.map +0 -1
  234. package/lib/commonjs/ui/session/projectSessionState.js +0 -86
  235. package/lib/commonjs/ui/session/projectSessionState.js.map +0 -1
  236. package/lib/commonjs/ui/session/sessionClientHost.js +0 -30
  237. package/lib/commonjs/ui/session/sessionClientHost.js.map +0 -1
  238. package/lib/commonjs/ui/utils/activeAuthuser.js +0 -142
  239. package/lib/commonjs/ui/utils/activeAuthuser.js.map +0 -1
  240. package/lib/commonjs/utils/crossApex.js +0 -74
  241. package/lib/commonjs/utils/crossApex.js.map +0 -1
  242. package/lib/module/ui/context/inSessionTokenRefresh.js +0 -238
  243. package/lib/module/ui/context/inSessionTokenRefresh.js.map +0 -1
  244. package/lib/module/ui/context/silentSessionRestore.js +0 -53
  245. package/lib/module/ui/context/silentSessionRestore.js.map +0 -1
  246. package/lib/module/ui/hooks/useWebSSO.js +0 -24
  247. package/lib/module/ui/hooks/useWebSSO.js.map +0 -1
  248. package/lib/module/ui/session/projectSessionState.js +0 -79
  249. package/lib/module/ui/session/projectSessionState.js.map +0 -1
  250. package/lib/module/ui/session/sessionClientHost.js +0 -26
  251. package/lib/module/ui/session/sessionClientHost.js.map +0 -1
  252. package/lib/module/ui/utils/activeAuthuser.js +0 -134
  253. package/lib/module/ui/utils/activeAuthuser.js.map +0 -1
  254. package/lib/module/utils/crossApex.js +0 -69
  255. package/lib/module/utils/crossApex.js.map +0 -1
  256. package/lib/typescript/commonjs/ui/context/inSessionTokenRefresh.d.ts +0 -106
  257. package/lib/typescript/commonjs/ui/context/inSessionTokenRefresh.d.ts.map +0 -1
  258. package/lib/typescript/commonjs/ui/context/silentSessionRestore.d.ts +0 -36
  259. package/lib/typescript/commonjs/ui/context/silentSessionRestore.d.ts.map +0 -1
  260. package/lib/typescript/commonjs/ui/hooks/useWebSSO.d.ts +0 -19
  261. package/lib/typescript/commonjs/ui/hooks/useWebSSO.d.ts.map +0 -1
  262. package/lib/typescript/commonjs/ui/session/projectSessionState.d.ts +0 -45
  263. package/lib/typescript/commonjs/ui/session/projectSessionState.d.ts.map +0 -1
  264. package/lib/typescript/commonjs/ui/session/sessionClientHost.d.ts +0 -14
  265. package/lib/typescript/commonjs/ui/session/sessionClientHost.d.ts.map +0 -1
  266. package/lib/typescript/commonjs/ui/utils/activeAuthuser.d.ts +0 -67
  267. package/lib/typescript/commonjs/ui/utils/activeAuthuser.d.ts.map +0 -1
  268. package/lib/typescript/commonjs/utils/crossApex.d.ts +0 -55
  269. package/lib/typescript/commonjs/utils/crossApex.d.ts.map +0 -1
  270. package/lib/typescript/module/ui/context/inSessionTokenRefresh.d.ts +0 -106
  271. package/lib/typescript/module/ui/context/inSessionTokenRefresh.d.ts.map +0 -1
  272. package/lib/typescript/module/ui/context/silentSessionRestore.d.ts +0 -36
  273. package/lib/typescript/module/ui/context/silentSessionRestore.d.ts.map +0 -1
  274. package/lib/typescript/module/ui/hooks/useWebSSO.d.ts +0 -19
  275. package/lib/typescript/module/ui/hooks/useWebSSO.d.ts.map +0 -1
  276. package/lib/typescript/module/ui/session/projectSessionState.d.ts +0 -45
  277. package/lib/typescript/module/ui/session/projectSessionState.d.ts.map +0 -1
  278. package/lib/typescript/module/ui/session/sessionClientHost.d.ts +0 -14
  279. package/lib/typescript/module/ui/session/sessionClientHost.d.ts.map +0 -1
  280. package/lib/typescript/module/ui/utils/activeAuthuser.d.ts +0 -67
  281. package/lib/typescript/module/ui/utils/activeAuthuser.d.ts.map +0 -1
  282. package/lib/typescript/module/utils/crossApex.d.ts +0 -55
  283. package/lib/typescript/module/utils/crossApex.d.ts.map +0 -1
  284. package/src/ui/context/inSessionTokenRefresh.ts +0 -264
  285. package/src/ui/context/silentSessionRestore.ts +0 -53
  286. package/src/ui/hooks/useWebSSO.ts +0 -23
  287. package/src/ui/session/__tests__/projectSessionState.test.ts +0 -114
  288. package/src/ui/session/__tests__/sessionClientHost.test.ts +0 -43
  289. package/src/ui/session/projectSessionState.ts +0 -85
  290. package/src/ui/session/sessionClientHost.ts +0 -27
  291. package/src/ui/utils/activeAuthuser.ts +0 -142
  292. package/src/utils/crossApex.ts +0 -75
@@ -1,34 +1,32 @@
1
1
  /**
2
2
  * @jest-environment node
3
3
  *
4
- * Regression coverage for the device-flow sign-in bugs:
4
+ * Regression coverage for the device-flow ("Sign in with Oxy" QR / "Open Oxy
5
+ * Auth") sign-in orchestration:
5
6
  *
6
7
  * BUG 1 (native): tapping "Sign In with Oxy" opens `OxyAuthScreen`, which
7
- * creates a device-flow AuthSession and opens auth.oxy.so/authorize. The
8
- * user signs in successfully, the API authorizes the session and notifies
9
- * the client via the auth-session socket but the screen then called
10
- * `switchSession` DIRECTLY without first claiming the bearer with the
11
- * secret `sessionToken`. The session was authorized server-side but the app
12
- * never became authenticated ("nothing happens").
8
+ * creates a device-flow AuthSession. The user signs in successfully, the API
9
+ * authorizes the session and notifies the client but the screen then called
10
+ * `switchSession` DIRECTLY without first claiming the bearer with the secret
11
+ * `sessionToken`. The session was authorized server-side but the app never
12
+ * became authenticated ("nothing happens").
13
13
  *
14
14
  * BUG 2 (session-sync cutover regression): once claiming was fixed,
15
15
  * `completeDeviceFlowSignIn` still committed the claimed session through
16
- * `switchSession`. After the session-sync cutover, `switchSession` became an
17
- * account-SWITCH between accounts already registered on the device and
18
- * throws `No device account found for session "..."` for a freshly-claimed
19
- * session that was never registered — surfacing as "Authorization
20
- * successful but failed to complete sign in." The fix commits the claimed
21
- * session through `commitSession` (`useOxy().handleWebSession`) instead
22
- * the same path a fresh password sign-in uses to register the account
23
- * into the device's session set.
16
+ * `switchSession`, which after the cutover is an account-SWITCH between
17
+ * accounts already registered on the device and throws `No device account
18
+ * found for session "..."` for a freshly-claimed session. The fix commits the
19
+ * claimed session through `commitSession` (`useOxy().handleWebSession`)
20
+ * instead the SAME path a fresh password sign-in uses to register the
21
+ * account into the device's server-authoritative session set.
24
22
  *
25
- * These tests pin the order (claim before commit), the fail-fast behaviour
26
- * on a claim that returns no usable session, and propagation of a
27
- * `commitSession` failure.
23
+ * These tests pin the order (claim before commit), the fail-fast behaviour on a
24
+ * claim that returns no usable session, propagation of a `commitSession`
25
+ * failure, and (device-first) that the rotating refresh token the claim returns
26
+ * is threaded into `commitSession` so the QR sign-in persists a durable session.
28
27
  */
29
28
 
30
29
  import type { SessionLoginResponse, User } from '@oxyhq/core';
31
- import { ssoStateKey, ssoGuardKey, ssoDestKey } from '@oxyhq/core';
32
30
  import {
33
31
  completeDeviceFlowSignIn,
34
32
  type DeviceFlowClient,
@@ -37,6 +35,7 @@ import {
37
35
  const SESSION_ID = 'session-id-123';
38
36
  const SESSION_TOKEN = 'a'.repeat(32);
39
37
  const ACCESS_TOKEN = 'access-token-abc';
38
+ const REFRESH_TOKEN = 'refresh-token-def';
40
39
  const USER = {
41
40
  id: 'user-1',
42
41
  username: 'nate',
@@ -52,7 +51,6 @@ describe('completeDeviceFlowSignIn', () => {
52
51
  const order: string[] = [];
53
52
 
54
53
  const oxyServices: DeviceFlowClient = {
55
- requestSsoEstablishUrl: jest.fn(async () => ({ establishUrl: 'https://auth.oxy.so/sso/establish' })),
56
54
  claimSessionByToken: jest.fn(async (token: string) => {
57
55
  expect(token).toBe(SESSION_TOKEN);
58
56
  order.push('claim');
@@ -89,9 +87,40 @@ describe('completeDeviceFlowSignIn', () => {
89
87
  expect(user).toBe(USER);
90
88
  });
91
89
 
90
+ it('threads the claim rotating refreshToken into commitSession (durable QR session)', async () => {
91
+ const oxyServices: DeviceFlowClient = {
92
+ claimSessionByToken: jest.fn(async () => ({
93
+ accessToken: ACCESS_TOKEN,
94
+ refreshToken: REFRESH_TOKEN,
95
+ sessionId: SESSION_ID,
96
+ deviceId: 'device-1',
97
+ expiresAt: '2026-01-01T00:00:00.000Z',
98
+ user: USER,
99
+ })),
100
+ };
101
+ const commitSession = jest.fn(async (): Promise<void> => {});
102
+
103
+ await completeDeviceFlowSignIn({
104
+ oxyServices,
105
+ sessionId: SESSION_ID,
106
+ sessionToken: SESSION_TOKEN,
107
+ commitSession,
108
+ });
109
+
110
+ // The rotating refresh family is carried into the commit funnel so it
111
+ // persists a durable session that survives a reload without a redirect.
112
+ expect(commitSession).toHaveBeenCalledWith({
113
+ sessionId: SESSION_ID,
114
+ deviceId: 'device-1',
115
+ expiresAt: '2026-01-01T00:00:00.000Z',
116
+ user: MINIMAL_USER,
117
+ accessToken: ACCESS_TOKEN,
118
+ refreshToken: REFRESH_TOKEN,
119
+ });
120
+ });
121
+
92
122
  it('falls back to the delivered sessionId/deviceId/expiresAt when the claim omits them', async () => {
93
123
  const oxyServices: DeviceFlowClient = {
94
- requestSsoEstablishUrl: jest.fn(async () => ({ establishUrl: 'https://auth.oxy.so/sso/establish' })),
95
124
  claimSessionByToken: jest.fn(async () => ({
96
125
  accessToken: ACCESS_TOKEN,
97
126
  user: USER,
@@ -118,7 +147,6 @@ describe('completeDeviceFlowSignIn', () => {
118
147
  it('does NOT commit the session when the claim fails (the original native regression)', async () => {
119
148
  const claimError = new Error('claim failed (401)');
120
149
  const oxyServices: DeviceFlowClient = {
121
- requestSsoEstablishUrl: jest.fn(async () => ({ establishUrl: 'https://auth.oxy.so/sso/establish' })),
122
150
  claimSessionByToken: jest.fn(async () => {
123
151
  throw claimError;
124
152
  }),
@@ -141,7 +169,6 @@ describe('completeDeviceFlowSignIn', () => {
141
169
 
142
170
  it('throws when the claim returns no accessToken (the session-sync regression guard)', async () => {
143
171
  const oxyServices: DeviceFlowClient = {
144
- requestSsoEstablishUrl: jest.fn(async () => ({ establishUrl: 'https://auth.oxy.so/sso/establish' })),
145
172
  claimSessionByToken: jest.fn(async () => ({ sessionId: SESSION_ID, user: USER })),
146
173
  };
147
174
  const commitSession = jest.fn(async (): Promise<void> => {});
@@ -160,7 +187,6 @@ describe('completeDeviceFlowSignIn', () => {
160
187
 
161
188
  it('throws when the claim returns no user', async () => {
162
189
  const oxyServices: DeviceFlowClient = {
163
- requestSsoEstablishUrl: jest.fn(async () => ({ establishUrl: 'https://auth.oxy.so/sso/establish' })),
164
190
  claimSessionByToken: jest.fn(async () => ({ accessToken: ACCESS_TOKEN, sessionId: SESSION_ID })),
165
191
  };
166
192
  const commitSession = jest.fn(async (): Promise<void> => {});
@@ -180,7 +206,6 @@ describe('completeDeviceFlowSignIn', () => {
180
206
  it('propagates a commitSession failure after a successful claim', async () => {
181
207
  const commitError = new Error('session invalid');
182
208
  const oxyServices: DeviceFlowClient = {
183
- requestSsoEstablishUrl: jest.fn(async () => ({ establishUrl: 'https://auth.oxy.so/sso/establish' })),
184
209
  claimSessionByToken: jest.fn(async () => ({
185
210
  accessToken: ACCESS_TOKEN,
186
211
  sessionId: SESSION_ID,
@@ -203,110 +228,4 @@ describe('completeDeviceFlowSignIn', () => {
203
228
  expect(oxyServices.claimSessionByToken).toHaveBeenCalledTimes(1);
204
229
  expect(commitSession).toHaveBeenCalledTimes(1);
205
230
  });
206
-
207
- describe('web durable-session establish hop', () => {
208
- const RP_ORIGIN = 'https://accounts.oxy.so';
209
- const RP_HREF = 'https://accounts.oxy.so/settings';
210
- const ESTABLISH_URL =
211
- 'https://auth.oxy.so/sso/establish?et=jwt&return_to=https%3A%2F%2Faccounts.oxy.so%2F__oxy%2Fsso-callback&state=state-1';
212
-
213
- function webDeps(overrides: Record<string, unknown> = {}) {
214
- const map = new Map<string, string>();
215
- const navigated: string[] = [];
216
- const deps = {
217
- isWeb: () => true,
218
- storage: {
219
- getItem: (k: string) => (map.has(k) ? (map.get(k) as string) : null),
220
- setItem: (k: string, v: string) => { map.set(k, v); },
221
- },
222
- location: { origin: RP_ORIGIN, href: RP_HREF },
223
- navigate: (url: string) => { navigated.push(url); },
224
- generateState: () => 'state-1',
225
- now: () => 1_700_000_000_000,
226
- ...overrides,
227
- };
228
- return { deps, map, navigated };
229
- }
230
-
231
- function baseClient(
232
- requestSsoEstablishUrl: DeviceFlowClient['requestSsoEstablishUrl'],
233
- ): DeviceFlowClient {
234
- return {
235
- requestSsoEstablishUrl,
236
- claimSessionByToken: jest.fn(async () => ({
237
- accessToken: ACCESS_TOKEN,
238
- sessionId: SESSION_ID,
239
- deviceId: 'device-1',
240
- expiresAt: '2026-01-01T00:00:00.000Z',
241
- user: USER,
242
- })),
243
- };
244
- }
245
-
246
- it('fires the establish hop on web: requests the URL with the RP origin + state and navigates once', async () => {
247
- const requestSsoEstablishUrl = jest.fn(async (origin: string, state: string) => {
248
- expect(origin).toBe(RP_ORIGIN);
249
- expect(state).toBe('state-1');
250
- return { establishUrl: ESTABLISH_URL };
251
- });
252
- const oxyServices = baseClient(requestSsoEstablishUrl);
253
- const { deps, map, navigated } = webDeps();
254
-
255
- const user = await completeDeviceFlowSignIn({
256
- oxyServices,
257
- sessionId: SESSION_ID,
258
- sessionToken: SESSION_TOKEN,
259
- commitSession: jest.fn(async () => {}),
260
- establishDeps: deps,
261
- });
262
-
263
- expect(user).toBe(USER);
264
- expect(requestSsoEstablishUrl).toHaveBeenCalledTimes(1);
265
- expect(navigated).toEqual([ESTABLISH_URL]);
266
- // Bounce state persisted so the post-bounce `sso-return` step validates it.
267
- expect(map.get(ssoStateKey(RP_ORIGIN))).toBe('state-1');
268
- expect(map.get(ssoGuardKey(RP_ORIGIN))).toBe(String(1_700_000_000_000));
269
- expect(map.get(ssoDestKey(RP_ORIGIN))).toBe(RP_HREF);
270
- });
271
-
272
- it('does NOT fire the hop on native (no request, no navigation)', async () => {
273
- const requestSsoEstablishUrl = jest.fn(async () => ({ establishUrl: ESTABLISH_URL }));
274
- const oxyServices = baseClient(requestSsoEstablishUrl);
275
- const { deps, navigated } = webDeps({ isWeb: () => false });
276
-
277
- await completeDeviceFlowSignIn({
278
- oxyServices,
279
- sessionId: SESSION_ID,
280
- sessionToken: SESSION_TOKEN,
281
- commitSession: jest.fn(async () => {}),
282
- establishDeps: deps,
283
- });
284
-
285
- expect(requestSsoEstablishUrl).not.toHaveBeenCalled();
286
- expect(navigated).toEqual([]);
287
- });
288
-
289
- it('completes sign-in even if the establish request fails — exactly one attempt, no navigation', async () => {
290
- const requestSsoEstablishUrl = jest.fn(async () => {
291
- throw new Error('403 unapproved');
292
- });
293
- const oxyServices = baseClient(requestSsoEstablishUrl);
294
- const { deps, map, navigated } = webDeps();
295
-
296
- const user = await completeDeviceFlowSignIn({
297
- oxyServices,
298
- sessionId: SESSION_ID,
299
- sessionToken: SESSION_TOKEN,
300
- commitSession: jest.fn(async () => {}),
301
- establishDeps: deps,
302
- });
303
-
304
- // Sign-in still completed (the primitive is total — never throws).
305
- expect(user).toBe(USER);
306
- expect(requestSsoEstablishUrl).toHaveBeenCalledTimes(1);
307
- expect(navigated).toEqual([]);
308
- // No stale bounce state left behind on failure.
309
- expect(map.size).toBe(0);
310
- });
311
- });
312
231
  });
@@ -33,16 +33,18 @@
33
33
 
34
34
  import {
35
35
  KeyManager,
36
- establishIdpSessionAfterClaim,
37
- type EstablishAfterClaimDeps,
38
36
  type MinimalUserData,
39
37
  type SessionLoginResponse,
40
- type SsoEstablishClient,
41
38
  type User,
42
39
  } from '@oxyhq/core';
43
40
 
44
41
  interface DeviceFlowClaimResult {
45
42
  accessToken?: string;
43
+ /** Rotating refresh-token family head minted by `/auth/session/claim` on the
44
+ * trusted lane. Not on the core method's typed return, so read defensively;
45
+ * threaded into `commitSession` so the QR sign-in persists a durable session
46
+ * that survives a reload without a redirect. */
47
+ refreshToken?: string;
46
48
  sessionId?: string;
47
49
  deviceId?: string;
48
50
  expiresAt?: string;
@@ -55,10 +57,8 @@ interface DeviceFlowClaimResult {
55
57
  * trivially unit-testable with a stub and never pulls the RN/Expo runtime into
56
58
  * a test bundle.
57
59
  *
58
- * Extends {@link SsoEstablishClient} (`requestSsoEstablishUrl`) so the WEB
59
- * post-claim durable-session hop can be driven off the same client.
60
60
  */
61
- export interface DeviceFlowClient extends SsoEstablishClient {
61
+ export interface DeviceFlowClient {
62
62
  /**
63
63
  * Exchange the device-flow `sessionToken` for the first access + refresh
64
64
  * token, planting them on the client. Single-use; replay is rejected by the
@@ -83,15 +83,12 @@ export interface CompleteDeviceFlowSignInOptions {
83
83
  * registers the account into the device's server-authoritative session set,
84
84
  * persists it durably, and hydrates the full user profile. Runs AFTER the
85
85
  * bearer is planted so its bearer-protected calls succeed.
86
+ *
87
+ * The `refreshToken` extra (optional; not on the public `SessionLoginResponse`
88
+ * type) carries the rotating refresh family so the commit funnel persists a
89
+ * durable session.
86
90
  */
87
- commitSession: (session: SessionLoginResponse) => Promise<void>;
88
- /**
89
- * Injectable web seams for the post-claim durable-session establish hop
90
- * ({@link establishIdpSessionAfterClaim}). Omit in production — the defaults
91
- * resolve to `window.*` (and no-op off-web / on native). Tests inject fakes to
92
- * drive the web path deterministically.
93
- */
94
- establishDeps?: EstablishAfterClaimDeps;
91
+ commitSession: (session: SessionLoginResponse & { refreshToken?: string }) => Promise<void>;
95
92
  }
96
93
 
97
94
  /**
@@ -108,7 +105,6 @@ export async function completeDeviceFlowSignIn({
108
105
  sessionId,
109
106
  sessionToken,
110
107
  commitSession,
111
- establishDeps,
112
108
  }: CompleteDeviceFlowSignInOptions): Promise<User> {
113
109
  // 1) Plant the bearer + refresh tokens. The claim response is also persisted
114
110
  // to native shared secure storage so a later cold boot has a bearer before
@@ -135,25 +131,22 @@ export async function completeDeviceFlowSignIn({
135
131
 
136
132
  // 2) Bearer is now planted — commit the session through the same path a
137
133
  // fresh sign-in uses so it is registered into the device's
138
- // server-authoritative session set instead of an account switch.
134
+ // server-authoritative session set instead of an account switch. Thread
135
+ // the rotating refresh token so the commit funnel persists a durable
136
+ // session that survives a reload.
139
137
  await commitSession({
140
138
  sessionId: claimed.sessionId || sessionId,
141
139
  deviceId: claimed.deviceId ?? '',
142
140
  expiresAt: claimed.expiresAt ?? '',
143
141
  user: minimalUser,
144
142
  accessToken: claimed.accessToken,
143
+ ...(claimed.refreshToken ? { refreshToken: claimed.refreshToken } : {}),
145
144
  });
146
145
 
147
- // 3) WEB durable-session hop (no-op on native). A device-flow claim plants
148
- // ONLY in-memory tokens no IdP `fedcm_session` cookie is ever planted, so
149
- // a reload cannot re-mint a token and the session is lost. Now that the
150
- // session is committed AND durably persisted (step 2), plant the per-apex
151
- // IdP cookie via ONE top-level establish hop. Single attempt; total (never
152
- // throws) — an establish failure leaves the committed session as-is. On web
153
- // success it navigates away, so it is the LAST step: the browser tears the
154
- // page down on the next tick, after `claimed.user` is returned to the
155
- // caller's `onSignedIn`.
156
- await establishIdpSessionAfterClaim(oxyServices, establishDeps ?? {});
146
+ // The commit funnel persisted the rotating refresh family and registered the
147
+ // account into the device set, so a reload restores the session locally (web:
148
+ // stored-tokens / same-apex web-session; native: shared keychain) WITHOUT any
149
+ // IdP `fedcm_session` cookie or top-level establish hop.
157
150
 
158
151
  return claimed.user;
159
152
  }
@@ -1,243 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.TOKEN_REFRESH_LEAD_MS = void 0;
7
- exports.createInSessionRefreshHandler = createInSessionRefreshHandler;
8
- exports.startTokenRefreshScheduler = startTokenRefreshScheduler;
9
- var _core = require("@oxyhq/core");
10
- var _reactNative = require("react-native");
11
- var _useWebSSO = require("../hooks/useWebSSO.js");
12
- var _silentSessionRestore = require("./silentSessionRestore.js");
13
- /**
14
- * In-session access-token refresh for the React Native / Expo SDK.
15
- *
16
- * THE GAP THIS CLOSES: the services `OxyContext` owns the session but never
17
- * installed an `authRefreshHandler` on the owner `HttpService`, so
18
- * `HttpService.refreshAccessToken` short-circuited to `null` — there was NO
19
- * in-session token refresh on the RN path at all. A 15-minute access token
20
- * expired with the tab/app open and nothing re-minted one; cross-apex RP feeds
21
- * (mention.earth, …) then 401'd in a loop while `isAuthenticated` stayed `true`
22
- * (a zombie logged-in state), because the `Domain=oxy.so` refresh cookie can't
23
- * reach `api.<apex>`. (`AuthManager`, which installs a refresh handler on the
24
- * web path, is only ever constructed by `WebOxyProvider` in `@oxyhq/auth`.)
25
- *
26
- * THE FIX, two cooperating pieces both wired from `OxyContext`:
27
- *
28
- * 1. {@link createInSessionRefreshHandler} — an `AuthRefreshHandler` installed
29
- * on the owner client. It re-mints a fresh access token WITHOUT a page
30
- * reload by composing the SAME silent-restore primitive cold boot uses
31
- * ({@link mintSessionViaPerApexIframe}) — not a copy. The linked client
32
- * (`createLinkedClient`) inherits the fix for free: its refresh delegates
33
- * back to the owner's `refreshAccessToken`.
34
- *
35
- * 2. {@link startTokenRefreshScheduler} — a proactive scheduler that refreshes
36
- * ~{@link TOKEN_REFRESH_LEAD_MS} before expiry (and on web tab-focus / native
37
- * app-foreground), so the common case never even reaches the reactive
38
- * 401-then-recover flash.
39
- *
40
- * Concurrency/cooldown/dedup are owned by `HttpService.refreshAccessToken`
41
- * (single in-flight `tokenRefreshPromise` + cooldown) — this module does not
42
- * reimplement them, so the timer / foreground / per-request triggers collapse to
43
- * one network attempt (no refresh storm).
44
- *
45
- * NOTE (session-sync cutover, Task 5): the web arm chain used to fall through
46
- * to a same-apex `oxy_rt` refresh-cookie arm (`refreshAllSessions` +
47
- * `selectActiveRefreshAccount`). That arm is DELETED — the device account set
48
- * is now server-authoritative via `SessionClient` (`@oxyhq/core`), which
49
- * `OxyContext` bootstraps/reprojects independently of in-session token
50
- * refresh. `selectActiveRefreshAccount` had no other caller and was deleted
51
- * with it.
52
- */
53
-
54
- /**
55
- * Per-arm fail-fast budget (ms) for the web first-party `/auth/silent` iframe
56
- * arm. Slightly more generous than the cold-boot iframe budget (2.5s) because an
57
- * in-session refresh is NOT in the first-paint critical path — a couple hundred
58
- * ms of extra headroom for the same-origin handshake is worth a higher success
59
- * rate. `silentSignIn` still fail-fasts on `iframe.onerror`, so a hard failure
60
- * returns well before this.
61
- */
62
- const SILENT_IFRAME_REFRESH_TIMEOUT = 4000;
63
-
64
- /**
65
- * Lead time (ms) before access-token expiry at which the proactive scheduler
66
- * refreshes. Mirrors `HttpService`'s per-request `TOKEN_REFRESH_LEAD_SECONDS`
67
- * (60s) so the scheduled refresh and the request-time preflight refresh use the
68
- * same window — the scheduler simply fires it during idle/background instead of
69
- * waiting for the next request.
70
- */
71
- const TOKEN_REFRESH_LEAD_MS = exports.TOKEN_REFRESH_LEAD_MS = 60_000;
72
-
73
- /**
74
- * A single refresh arm: attempts one silent-restore mechanism and resolves to
75
- * the freshly planted access token, or `null` to fall through to the next arm.
76
- */
77
-
78
- /**
79
- * Build the in-session `AuthRefreshHandler` for the owner client.
80
- *
81
- * Arms run in an explicit order; the first to plant a token wins. Each arm
82
- * resolves to the planted token (read back via `getAccessToken()` — the
83
- * underlying SDK call plants it internally) or `null`. A throw in one arm is
84
- * logged and treated as `null` so the chain continues.
85
- *
86
- * NATIVE (Expo): shared cross-app identity key re-mint
87
- * (`signInWithSharedIdentity` → challenge→sign→verify plants the tokens).
88
- * The ONLY silent native arm (mirrors cold boot's `shared-key-signin`); the
89
- * `/auth/silent` web iframe is NEVER attempted on native. Resolves to `null`
90
- * when the device holds no shared identity (e.g. a password-only native
91
- * sign-in) so a genuinely dead session reconciles to logged-out rather than
92
- * staying a zombie.
93
- *
94
- * WEB: Per-apex `/auth/silent` iframe — {@link mintSessionViaPerApexIframe}
95
- * (shared verbatim with cold boot). The durable cross-apex path; also
96
- * covers `*.oxy.so` (the per-apex host IS the central host there). There
97
- * is no FedCM arm — FedCM was removed from the client sign-in/refresh path
98
- * entirely (Chrome-only; see `CrossDomainAuth`'s doc comment in
99
- * `@oxyhq/core` for the production sign-in loop that motivated the
100
- * removal).
101
- *
102
- * NO RECURSION: no arm issues a request through the authed client's
103
- * `refreshAccessToken` path. The iframe transport is postMessage-based; the
104
- * follow-up `/session/user` fetch inside `silentSignIn`
105
- * runs against the just-planted FULL-TTL token (≫ the preflight lead), so it
106
- * never re-enters the refresh path.
107
- */
108
- function createInSessionRefreshHandler(oxyServices) {
109
- const runArm = async (label, reason, arm) => {
110
- try {
111
- return await arm();
112
- } catch (error) {
113
- if (__DEV__) {
114
- _core.logger.debug(`In-session refresh arm "${label}" failed (falling through)`, {
115
- component: 'inSessionTokenRefresh',
116
- method: 'authRefreshHandler',
117
- reason
118
- }, error);
119
- }
120
- return null;
121
- }
122
- };
123
- const webArms = [['silent-iframe', async () => (await (0, _silentSessionRestore.mintSessionViaPerApexIframe)(oxyServices, SILENT_IFRAME_REFRESH_TIMEOUT)) ? oxyServices.getAccessToken() : null]];
124
- return async reason => {
125
- if (!(0, _useWebSSO.isWebBrowser)()) {
126
- return runArm('native-shared-key', reason, async () => (await oxyServices.signInWithSharedIdentity?.()) ? oxyServices.getAccessToken() : null);
127
- }
128
- for (const [label, arm] of webArms) {
129
- const token = await runArm(label, reason, arm);
130
- if (token) {
131
- return token;
132
- }
133
- }
134
- return null;
135
- };
136
- }
137
-
138
- /**
139
- * Handle returned by {@link startTokenRefreshScheduler}; call `dispose()` to tear
140
- * down the timer and the foreground listener.
141
- */
142
-
143
- /**
144
- * Start the proactive in-session refresh scheduler against `oxyServices`.
145
- *
146
- * Schedules a single timer to fire {@link TOKEN_REFRESH_LEAD_MS} before the
147
- * current access token's `exp`, calling `httpService.refreshAccessToken`
148
- * ('preflight') — which runs the installed handler and is deduped + cooldown-
149
- * guarded. After every attempt it reschedules from the (possibly rotated) token.
150
- * It also reschedules whenever the token changes (`onTokensChanged` — so a
151
- * sign-out that clears the token cancels the timer) and, on web tab-focus /
152
- * native app-foreground, refreshes immediately if already inside the lead window
153
- * (a long-hidden tab throttles timers, so the token can be expired on return).
154
- *
155
- * The `exp` is derived directly from the JWT via `getAccessTokenExpiry()`. No-ops
156
- * cleanly when there is no token, an opaque/no-`exp` token, or the host lacks
157
- * `getAccessTokenExpiry` (older stubs) — the reactive 401 path stays the only
158
- * refresh trigger in those cases.
159
- */
160
- function startTokenRefreshScheduler(oxyServices) {
161
- let disposed = false;
162
- let timer = null;
163
- const clearTimer = () => {
164
- if (timer !== null) {
165
- clearTimeout(timer);
166
- timer = null;
167
- }
168
- };
169
- const runRefresh = () => {
170
- // `refreshAccessToken` is deduped + cooldown-guarded internally, so this is
171
- // safe to call from the timer, the foreground listener, and request-time
172
- // preflight concurrently — they collapse to one network attempt.
173
- const refresh = oxyServices.httpService.refreshAccessToken?.('preflight');
174
- if (!refresh) {
175
- return;
176
- }
177
- void refresh.catch(() => null).finally(() => {
178
- if (!disposed) {
179
- schedule();
180
- }
181
- });
182
- };
183
- const schedule = () => {
184
- clearTimer();
185
- if (disposed || !oxyServices.getAccessToken()) {
186
- return;
187
- }
188
- const expSeconds = oxyServices.getAccessTokenExpiry?.() ?? null;
189
- if (expSeconds === null) {
190
- return;
191
- }
192
- const fireInMs = expSeconds * 1000 - Date.now() - TOKEN_REFRESH_LEAD_MS;
193
- timer = setTimeout(runRefresh, Math.max(fireInMs, 0));
194
- };
195
- const onForeground = () => {
196
- if (disposed || !oxyServices.getAccessToken()) {
197
- return;
198
- }
199
- const expSeconds = oxyServices.getAccessTokenExpiry?.() ?? null;
200
- if (expSeconds === null) {
201
- return;
202
- }
203
- const remainingMs = expSeconds * 1000 - Date.now();
204
- if (remainingMs <= TOKEN_REFRESH_LEAD_MS) {
205
- runRefresh();
206
- } else {
207
- schedule();
208
- }
209
- };
210
- const unsubscribeTokens = oxyServices.onTokensChanged(() => {
211
- if (!disposed) {
212
- schedule();
213
- }
214
- });
215
- let removeForeground = null;
216
- if ((0, _useWebSSO.isWebBrowser)() && typeof document !== 'undefined') {
217
- const handler = () => {
218
- if (document.visibilityState === 'visible') {
219
- onForeground();
220
- }
221
- };
222
- document.addEventListener('visibilitychange', handler);
223
- removeForeground = () => document.removeEventListener('visibilitychange', handler);
224
- } else if (!(0, _useWebSSO.isWebBrowser)() && _reactNative.AppState && typeof _reactNative.AppState.addEventListener === 'function') {
225
- const subscription = _reactNative.AppState.addEventListener('change', state => {
226
- if (state === 'active') {
227
- onForeground();
228
- }
229
- });
230
- removeForeground = () => subscription.remove();
231
- }
232
- schedule();
233
- return {
234
- dispose() {
235
- disposed = true;
236
- clearTimer();
237
- unsubscribeTokens();
238
- removeForeground?.();
239
- removeForeground = null;
240
- }
241
- };
242
- }
243
- //# sourceMappingURL=inSessionTokenRefresh.js.map
@@ -1 +0,0 @@
1
- {"version":3,"names":["_core","require","_reactNative","_useWebSSO","_silentSessionRestore","SILENT_IFRAME_REFRESH_TIMEOUT","TOKEN_REFRESH_LEAD_MS","exports","createInSessionRefreshHandler","oxyServices","runArm","label","reason","arm","error","__DEV__","loggerUtil","debug","component","method","webArms","mintSessionViaPerApexIframe","getAccessToken","isWebBrowser","signInWithSharedIdentity","token","startTokenRefreshScheduler","disposed","timer","clearTimer","clearTimeout","runRefresh","refresh","httpService","refreshAccessToken","catch","finally","schedule","expSeconds","getAccessTokenExpiry","fireInMs","Date","now","setTimeout","Math","max","onForeground","remainingMs","unsubscribeTokens","onTokensChanged","removeForeground","document","handler","visibilityState","addEventListener","removeEventListener","AppState","subscription","state","remove","dispose"],"sourceRoot":"../../../../src","sources":["ui/context/inSessionTokenRefresh.ts"],"mappings":"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","ignoreList":[]}
@@ -1,56 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.mintSessionViaPerApexIframe = mintSessionViaPerApexIframe;
7
- var _core = require("@oxyhq/core");
8
- /**
9
- * Silent, no-reload session-restore PRIMITIVE — the single shared
10
- * implementation used by BOTH cold boot (`OxyContext.restoreSessionsFromStorage`)
11
- * and in-session token refresh (`createInSessionRefreshHandler`). Neither caller
12
- * re-implements it; they compose it. Keeping one home avoids the two paths
13
- * drifting on "how do we mint a first-party token without a page reload".
14
- *
15
- * Platform-agnostic at the type level and returns plain data; the callers own
16
- * the side effects that differ between them (cold boot COMMITS the recovered
17
- * session into provider state; refresh only reads the freshly planted bearer).
18
- *
19
- * NOTE (session-sync cutover, Task 5): this file used to also export
20
- * `selectActiveRefreshAccount`, which picked the active account out of a
21
- * `refreshAllSessions` (`oxy_rt` refresh-cookie) snapshot. Deleted — its only
22
- * caller was the in-session refresh handler's now-deleted `refresh-cookie`
23
- * arm. The device account SET is server-authoritative via `SessionClient`
24
- * (`@oxyhq/core`) now.
25
- */
26
-
27
- /**
28
- * Mint a fresh first-party session via the PER-APEX `/auth/silent` iframe — the
29
- * durable cross-domain restore path that works WITHOUT a top-level navigation
30
- * (so it succeeds under Safari ITP / Firefox TCP and in a backgrounded tab).
31
- *
32
- * The instance is configured with the CENTRAL auth URL, so we explicitly point
33
- * the iframe at the per-apex host (`auth.<rp-apex>`) via `autoDetectAuthWebUrl()`
34
- * + `silentSignIn`'s `authWebUrlOverride`. On a `*.oxy.so` app the per-apex host
35
- * IS the central host, so this also covers same-apex. When auto-detection bails
36
- * (localhost / IP / single-label / off-browser) there is no per-apex IdP and we
37
- * return `null`. `silentSignIn` plants the access token internally on success.
38
- *
39
- * @returns the recovered session (token already planted) when complete, else
40
- * `null` (no per-apex IdP, no session, or an incomplete iframe response).
41
- */
42
- async function mintSessionViaPerApexIframe(oxyServices, timeoutMs) {
43
- const perApexAuthUrl = (0, _core.autoDetectAuthWebUrl)();
44
- if (!perApexAuthUrl) {
45
- return null;
46
- }
47
- const session = await oxyServices.silentSignIn?.({
48
- authWebUrlOverride: perApexAuthUrl,
49
- timeout: timeoutMs
50
- });
51
- if (!session?.user || !session.sessionId) {
52
- return null;
53
- }
54
- return session;
55
- }
56
- //# sourceMappingURL=silentSessionRestore.js.map
@@ -1 +0,0 @@
1
- {"version":3,"names":["_core","require","mintSessionViaPerApexIframe","oxyServices","timeoutMs","perApexAuthUrl","autoDetectAuthWebUrl","session","silentSignIn","authWebUrlOverride","timeout","user","sessionId"],"sourceRoot":"../../../../src","sources":["ui/context/silentSessionRestore.ts"],"mappings":";;;;;;AAmBA,IAAAA,KAAA,GAAAC,OAAA;AAnBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,eAAeC,2BAA2BA,CAC/CC,WAAwB,EACxBC,SAAiB,EACqB;EACtC,MAAMC,cAAc,GAAG,IAAAC,0BAAoB,EAAC,CAAC;EAC7C,IAAI,CAACD,cAAc,EAAE;IACnB,OAAO,IAAI;EACb;EACA,MAAME,OAAO,GAAG,MAAMJ,WAAW,CAACK,YAAY,GAAG;IAC/CC,kBAAkB,EAAEJ,cAAc;IAClCK,OAAO,EAAEN;EACX,CAAC,CAAC;EACF,IAAI,CAACG,OAAO,EAAEI,IAAI,IAAI,CAACJ,OAAO,CAACK,SAAS,EAAE;IACxC,OAAO,IAAI;EACb;EACA,OAAOL,OAAO;AAChB","ignoreList":[]}