@oxyhq/services 13.2.0 → 14.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 (260) hide show
  1. package/lib/commonjs/index.js +11 -17
  2. package/lib/commonjs/index.js.map +1 -1
  3. package/lib/commonjs/ui/components/AccountMenu.js +103 -65
  4. package/lib/commonjs/ui/components/AccountMenu.js.map +1 -1
  5. package/lib/commonjs/ui/components/AccountSwitcher.js +84 -126
  6. package/lib/commonjs/ui/components/AccountSwitcher.js.map +1 -1
  7. package/lib/commonjs/ui/components/ProfileButton.js +81 -22
  8. package/lib/commonjs/ui/components/ProfileButton.js.map +1 -1
  9. package/lib/commonjs/ui/components/ProfileMenu.js +244 -142
  10. package/lib/commonjs/ui/components/ProfileMenu.js.map +1 -1
  11. package/lib/commonjs/ui/components/SignInModal.js +4 -4
  12. package/lib/commonjs/ui/components/SignInModal.js.map +1 -1
  13. package/lib/commonjs/ui/context/OxyContext.js +506 -466
  14. package/lib/commonjs/ui/context/OxyContext.js.map +1 -1
  15. package/lib/commonjs/ui/context/hooks/useAuthOperations.js +59 -57
  16. package/lib/commonjs/ui/context/hooks/useAuthOperations.js.map +1 -1
  17. package/lib/commonjs/ui/context/inSessionTokenRefresh.js +23 -42
  18. package/lib/commonjs/ui/context/inSessionTokenRefresh.js.map +1 -1
  19. package/lib/commonjs/ui/context/silentSessionRestore.js +12 -21
  20. package/lib/commonjs/ui/context/silentSessionRestore.js.map +1 -1
  21. package/lib/commonjs/ui/hooks/useAuth.js +4 -3
  22. package/lib/commonjs/ui/hooks/useAuth.js.map +1 -1
  23. package/lib/commonjs/ui/hooks/useOxyAuthSession.js +12 -7
  24. package/lib/commonjs/ui/hooks/useOxyAuthSession.js.map +1 -1
  25. package/lib/commonjs/ui/hooks/useSessionManagement.js +17 -65
  26. package/lib/commonjs/ui/hooks/useSessionManagement.js.map +1 -1
  27. package/lib/commonjs/ui/hooks/useSwitchableAccounts.js +288 -0
  28. package/lib/commonjs/ui/hooks/useSwitchableAccounts.js.map +1 -0
  29. package/lib/commonjs/ui/hooks/useWebSSO.js +12 -191
  30. package/lib/commonjs/ui/hooks/useWebSSO.js.map +1 -1
  31. package/lib/commonjs/ui/index.js.map +1 -1
  32. package/lib/commonjs/ui/screens/OxyAuthScreen.js +2 -2
  33. package/lib/commonjs/ui/screens/OxyAuthScreen.js.map +1 -1
  34. package/lib/commonjs/ui/session/createSessionClient.js +28 -0
  35. package/lib/commonjs/ui/session/createSessionClient.js.map +1 -0
  36. package/lib/commonjs/ui/session/index.js +52 -0
  37. package/lib/commonjs/ui/session/index.js.map +1 -0
  38. package/lib/commonjs/ui/session/projectSessionState.js +86 -0
  39. package/lib/commonjs/ui/session/projectSessionState.js.map +1 -0
  40. package/lib/commonjs/ui/session/sessionClientHost.js +30 -0
  41. package/lib/commonjs/ui/session/sessionClientHost.js.map +1 -0
  42. package/lib/commonjs/ui/session/tokenTransport.js +77 -0
  43. package/lib/commonjs/ui/session/tokenTransport.js.map +1 -0
  44. package/lib/commonjs/ui/utils/activeAuthuser.js +35 -79
  45. package/lib/commonjs/ui/utils/activeAuthuser.js.map +1 -1
  46. package/lib/commonjs/ui/utils/sessionHelpers.js +1 -51
  47. package/lib/commonjs/ui/utils/sessionHelpers.js.map +1 -1
  48. package/lib/commonjs/utils/deviceFlowSignIn.js +70 -15
  49. package/lib/commonjs/utils/deviceFlowSignIn.js.map +1 -1
  50. package/lib/module/index.js +5 -5
  51. package/lib/module/index.js.map +1 -1
  52. package/lib/module/ui/components/AccountMenu.js +103 -65
  53. package/lib/module/ui/components/AccountMenu.js.map +1 -1
  54. package/lib/module/ui/components/AccountSwitcher.js +85 -127
  55. package/lib/module/ui/components/AccountSwitcher.js.map +1 -1
  56. package/lib/module/ui/components/ProfileButton.js +82 -23
  57. package/lib/module/ui/components/ProfileButton.js.map +1 -1
  58. package/lib/module/ui/components/ProfileMenu.js +247 -145
  59. package/lib/module/ui/components/ProfileMenu.js.map +1 -1
  60. package/lib/module/ui/components/SignInModal.js +4 -4
  61. package/lib/module/ui/components/SignInModal.js.map +1 -1
  62. package/lib/module/ui/context/OxyContext.js +510 -470
  63. package/lib/module/ui/context/OxyContext.js.map +1 -1
  64. package/lib/module/ui/context/hooks/useAuthOperations.js +61 -60
  65. package/lib/module/ui/context/hooks/useAuthOperations.js.map +1 -1
  66. package/lib/module/ui/context/inSessionTokenRefresh.js +24 -43
  67. package/lib/module/ui/context/inSessionTokenRefresh.js.map +1 -1
  68. package/lib/module/ui/context/silentSessionRestore.js +12 -20
  69. package/lib/module/ui/context/silentSessionRestore.js.map +1 -1
  70. package/lib/module/ui/hooks/useAuth.js +4 -3
  71. package/lib/module/ui/hooks/useAuth.js.map +1 -1
  72. package/lib/module/ui/hooks/useOxyAuthSession.js +12 -7
  73. package/lib/module/ui/hooks/useOxyAuthSession.js.map +1 -1
  74. package/lib/module/ui/hooks/useSessionManagement.js +18 -66
  75. package/lib/module/ui/hooks/useSessionManagement.js.map +1 -1
  76. package/lib/module/ui/hooks/useSwitchableAccounts.js +283 -0
  77. package/lib/module/ui/hooks/useSwitchableAccounts.js.map +1 -0
  78. package/lib/module/ui/hooks/useWebSSO.js +13 -192
  79. package/lib/module/ui/hooks/useWebSSO.js.map +1 -1
  80. package/lib/module/ui/index.js +0 -1
  81. package/lib/module/ui/index.js.map +1 -1
  82. package/lib/module/ui/screens/OxyAuthScreen.js +2 -2
  83. package/lib/module/ui/screens/OxyAuthScreen.js.map +1 -1
  84. package/lib/module/ui/session/createSessionClient.js +25 -0
  85. package/lib/module/ui/session/createSessionClient.js.map +1 -0
  86. package/lib/module/ui/session/index.js +17 -0
  87. package/lib/module/ui/session/index.js.map +1 -0
  88. package/lib/module/ui/session/projectSessionState.js +79 -0
  89. package/lib/module/ui/session/projectSessionState.js.map +1 -0
  90. package/lib/module/ui/session/sessionClientHost.js +26 -0
  91. package/lib/module/ui/session/sessionClientHost.js.map +1 -0
  92. package/lib/module/ui/session/tokenTransport.js +74 -0
  93. package/lib/module/ui/session/tokenTransport.js.map +1 -0
  94. package/lib/module/ui/utils/activeAuthuser.js +34 -76
  95. package/lib/module/ui/utils/activeAuthuser.js.map +1 -1
  96. package/lib/module/ui/utils/sessionHelpers.js +0 -49
  97. package/lib/module/ui/utils/sessionHelpers.js.map +1 -1
  98. package/lib/module/utils/deviceFlowSignIn.js +71 -16
  99. package/lib/module/utils/deviceFlowSignIn.js.map +1 -1
  100. package/lib/typescript/commonjs/index.d.ts +2 -3
  101. package/lib/typescript/commonjs/index.d.ts.map +1 -1
  102. package/lib/typescript/commonjs/ui/components/AccountMenu.d.ts +4 -2
  103. package/lib/typescript/commonjs/ui/components/AccountMenu.d.ts.map +1 -1
  104. package/lib/typescript/commonjs/ui/components/AccountSwitcher.d.ts +7 -8
  105. package/lib/typescript/commonjs/ui/components/AccountSwitcher.d.ts.map +1 -1
  106. package/lib/typescript/commonjs/ui/components/ProfileButton.d.ts +11 -1
  107. package/lib/typescript/commonjs/ui/components/ProfileButton.d.ts.map +1 -1
  108. package/lib/typescript/commonjs/ui/components/ProfileMenu.d.ts +12 -9
  109. package/lib/typescript/commonjs/ui/components/ProfileMenu.d.ts.map +1 -1
  110. package/lib/typescript/commonjs/ui/context/OxyContext.d.ts +16 -13
  111. package/lib/typescript/commonjs/ui/context/OxyContext.d.ts.map +1 -1
  112. package/lib/typescript/commonjs/ui/context/hooks/useAuthOperations.d.ts +27 -3
  113. package/lib/typescript/commonjs/ui/context/hooks/useAuthOperations.d.ts.map +1 -1
  114. package/lib/typescript/commonjs/ui/context/inSessionTokenRefresh.d.ts +22 -17
  115. package/lib/typescript/commonjs/ui/context/inSessionTokenRefresh.d.ts.map +1 -1
  116. package/lib/typescript/commonjs/ui/context/silentSessionRestore.d.ts +12 -18
  117. package/lib/typescript/commonjs/ui/context/silentSessionRestore.d.ts.map +1 -1
  118. package/lib/typescript/commonjs/ui/hooks/mutations/useAccountMutations.d.ts +1 -0
  119. package/lib/typescript/commonjs/ui/hooks/mutations/useAccountMutations.d.ts.map +1 -1
  120. package/lib/typescript/commonjs/ui/hooks/useAuth.d.ts +1 -1
  121. package/lib/typescript/commonjs/ui/hooks/useAuth.d.ts.map +1 -1
  122. package/lib/typescript/commonjs/ui/hooks/useOxyAuthSession.d.ts +2 -2
  123. package/lib/typescript/commonjs/ui/hooks/useOxyAuthSession.d.ts.map +1 -1
  124. package/lib/typescript/commonjs/ui/hooks/useSessionManagement.d.ts.map +1 -1
  125. package/lib/typescript/commonjs/ui/hooks/useSwitchableAccounts.d.ts +162 -0
  126. package/lib/typescript/commonjs/ui/hooks/useSwitchableAccounts.d.ts.map +1 -0
  127. package/lib/typescript/commonjs/ui/hooks/useWebSSO.d.ts +13 -52
  128. package/lib/typescript/commonjs/ui/hooks/useWebSSO.d.ts.map +1 -1
  129. package/lib/typescript/commonjs/ui/index.d.ts.map +1 -1
  130. package/lib/typescript/commonjs/ui/session/createSessionClient.d.ts +15 -0
  131. package/lib/typescript/commonjs/ui/session/createSessionClient.d.ts.map +1 -0
  132. package/lib/typescript/commonjs/ui/session/index.d.ts +15 -0
  133. package/lib/typescript/commonjs/ui/session/index.d.ts.map +1 -0
  134. package/lib/typescript/commonjs/ui/session/projectSessionState.d.ts +45 -0
  135. package/lib/typescript/commonjs/ui/session/projectSessionState.d.ts.map +1 -0
  136. package/lib/typescript/commonjs/ui/session/sessionClientHost.d.ts +14 -0
  137. package/lib/typescript/commonjs/ui/session/sessionClientHost.d.ts.map +1 -0
  138. package/lib/typescript/commonjs/ui/session/tokenTransport.d.ts +24 -0
  139. package/lib/typescript/commonjs/ui/session/tokenTransport.d.ts.map +1 -0
  140. package/lib/typescript/commonjs/ui/utils/activeAuthuser.d.ts +21 -29
  141. package/lib/typescript/commonjs/ui/utils/activeAuthuser.d.ts.map +1 -1
  142. package/lib/typescript/commonjs/ui/utils/sessionHelpers.d.ts +0 -19
  143. package/lib/typescript/commonjs/ui/utils/sessionHelpers.d.ts.map +1 -1
  144. package/lib/typescript/commonjs/utils/deviceFlowSignIn.d.ts +51 -19
  145. package/lib/typescript/commonjs/utils/deviceFlowSignIn.d.ts.map +1 -1
  146. package/lib/typescript/module/index.d.ts +2 -3
  147. package/lib/typescript/module/index.d.ts.map +1 -1
  148. package/lib/typescript/module/ui/components/AccountMenu.d.ts +4 -2
  149. package/lib/typescript/module/ui/components/AccountMenu.d.ts.map +1 -1
  150. package/lib/typescript/module/ui/components/AccountSwitcher.d.ts +7 -8
  151. package/lib/typescript/module/ui/components/AccountSwitcher.d.ts.map +1 -1
  152. package/lib/typescript/module/ui/components/ProfileButton.d.ts +11 -1
  153. package/lib/typescript/module/ui/components/ProfileButton.d.ts.map +1 -1
  154. package/lib/typescript/module/ui/components/ProfileMenu.d.ts +12 -9
  155. package/lib/typescript/module/ui/components/ProfileMenu.d.ts.map +1 -1
  156. package/lib/typescript/module/ui/context/OxyContext.d.ts +16 -13
  157. package/lib/typescript/module/ui/context/OxyContext.d.ts.map +1 -1
  158. package/lib/typescript/module/ui/context/hooks/useAuthOperations.d.ts +27 -3
  159. package/lib/typescript/module/ui/context/hooks/useAuthOperations.d.ts.map +1 -1
  160. package/lib/typescript/module/ui/context/inSessionTokenRefresh.d.ts +22 -17
  161. package/lib/typescript/module/ui/context/inSessionTokenRefresh.d.ts.map +1 -1
  162. package/lib/typescript/module/ui/context/silentSessionRestore.d.ts +12 -18
  163. package/lib/typescript/module/ui/context/silentSessionRestore.d.ts.map +1 -1
  164. package/lib/typescript/module/ui/hooks/mutations/useAccountMutations.d.ts +1 -0
  165. package/lib/typescript/module/ui/hooks/mutations/useAccountMutations.d.ts.map +1 -1
  166. package/lib/typescript/module/ui/hooks/useAuth.d.ts +1 -1
  167. package/lib/typescript/module/ui/hooks/useAuth.d.ts.map +1 -1
  168. package/lib/typescript/module/ui/hooks/useOxyAuthSession.d.ts +2 -2
  169. package/lib/typescript/module/ui/hooks/useOxyAuthSession.d.ts.map +1 -1
  170. package/lib/typescript/module/ui/hooks/useSessionManagement.d.ts.map +1 -1
  171. package/lib/typescript/module/ui/hooks/useSwitchableAccounts.d.ts +162 -0
  172. package/lib/typescript/module/ui/hooks/useSwitchableAccounts.d.ts.map +1 -0
  173. package/lib/typescript/module/ui/hooks/useWebSSO.d.ts +13 -52
  174. package/lib/typescript/module/ui/hooks/useWebSSO.d.ts.map +1 -1
  175. package/lib/typescript/module/ui/index.d.ts.map +1 -1
  176. package/lib/typescript/module/ui/session/createSessionClient.d.ts +15 -0
  177. package/lib/typescript/module/ui/session/createSessionClient.d.ts.map +1 -0
  178. package/lib/typescript/module/ui/session/index.d.ts +15 -0
  179. package/lib/typescript/module/ui/session/index.d.ts.map +1 -0
  180. package/lib/typescript/module/ui/session/projectSessionState.d.ts +45 -0
  181. package/lib/typescript/module/ui/session/projectSessionState.d.ts.map +1 -0
  182. package/lib/typescript/module/ui/session/sessionClientHost.d.ts +14 -0
  183. package/lib/typescript/module/ui/session/sessionClientHost.d.ts.map +1 -0
  184. package/lib/typescript/module/ui/session/tokenTransport.d.ts +24 -0
  185. package/lib/typescript/module/ui/session/tokenTransport.d.ts.map +1 -0
  186. package/lib/typescript/module/ui/utils/activeAuthuser.d.ts +21 -29
  187. package/lib/typescript/module/ui/utils/activeAuthuser.d.ts.map +1 -1
  188. package/lib/typescript/module/ui/utils/sessionHelpers.d.ts +0 -19
  189. package/lib/typescript/module/ui/utils/sessionHelpers.d.ts.map +1 -1
  190. package/lib/typescript/module/utils/deviceFlowSignIn.d.ts +51 -19
  191. package/lib/typescript/module/utils/deviceFlowSignIn.d.ts.map +1 -1
  192. package/package.json +4 -4
  193. package/src/index.ts +9 -9
  194. package/src/ui/components/AccountMenu.tsx +117 -70
  195. package/src/ui/components/AccountSwitcher.tsx +88 -134
  196. package/src/ui/components/ProfileButton.tsx +95 -17
  197. package/src/ui/components/ProfileMenu.tsx +263 -155
  198. package/src/ui/components/SignInModal.tsx +5 -5
  199. package/src/ui/context/OxyContext.tsx +560 -475
  200. package/src/ui/context/hooks/useAuthOperations.ts +72 -63
  201. package/src/ui/context/inSessionTokenRefresh.ts +23 -42
  202. package/src/ui/context/silentSessionRestore.ts +12 -26
  203. package/src/ui/hooks/useAuth.ts +4 -3
  204. package/src/ui/hooks/useOxyAuthSession.ts +13 -8
  205. package/src/ui/hooks/useSessionManagement.ts +16 -87
  206. package/src/ui/hooks/useSwitchableAccounts.ts +397 -0
  207. package/src/ui/hooks/useWebSSO.ts +13 -227
  208. package/src/ui/index.ts +0 -1
  209. package/src/ui/screens/OxyAuthScreen.tsx +2 -2
  210. package/src/ui/session/__tests__/createSessionClient.test.ts +41 -0
  211. package/src/ui/session/__tests__/projectSessionState.test.ts +114 -0
  212. package/src/ui/session/__tests__/sessionClientHost.test.ts +43 -0
  213. package/src/ui/session/__tests__/tokenTransport.test.ts +142 -0
  214. package/src/ui/session/createSessionClient.ts +21 -0
  215. package/src/ui/session/index.ts +19 -0
  216. package/src/ui/session/projectSessionState.ts +85 -0
  217. package/src/ui/session/sessionClientHost.ts +27 -0
  218. package/src/ui/session/tokenTransport.ts +76 -0
  219. package/src/ui/utils/activeAuthuser.ts +34 -76
  220. package/src/ui/utils/sessionHelpers.ts +0 -66
  221. package/src/utils/__tests__/deviceFlowSignIn.test.ts +243 -34
  222. package/src/utils/deviceFlowSignIn.ts +98 -21
  223. package/lib/commonjs/ui/components/accountMenuRows.js +0 -33
  224. package/lib/commonjs/ui/components/accountMenuRows.js.map +0 -1
  225. package/lib/commonjs/ui/hooks/useDeviceAccounts.js +0 -280
  226. package/lib/commonjs/ui/hooks/useDeviceAccounts.js.map +0 -1
  227. package/lib/commonjs/ui/hooks/useSessionSocket.js +0 -203
  228. package/lib/commonjs/ui/hooks/useSessionSocket.js.map +0 -1
  229. package/lib/commonjs/utils/silentGuardKey.js +0 -54
  230. package/lib/commonjs/utils/silentGuardKey.js.map +0 -1
  231. package/lib/module/ui/components/accountMenuRows.js +0 -29
  232. package/lib/module/ui/components/accountMenuRows.js.map +0 -1
  233. package/lib/module/ui/hooks/useDeviceAccounts.js +0 -276
  234. package/lib/module/ui/hooks/useDeviceAccounts.js.map +0 -1
  235. package/lib/module/ui/hooks/useSessionSocket.js +0 -199
  236. package/lib/module/ui/hooks/useSessionSocket.js.map +0 -1
  237. package/lib/module/utils/silentGuardKey.js +0 -49
  238. package/lib/module/utils/silentGuardKey.js.map +0 -1
  239. package/lib/typescript/commonjs/ui/components/accountMenuRows.d.ts +0 -34
  240. package/lib/typescript/commonjs/ui/components/accountMenuRows.d.ts.map +0 -1
  241. package/lib/typescript/commonjs/ui/hooks/useDeviceAccounts.d.ts +0 -133
  242. package/lib/typescript/commonjs/ui/hooks/useDeviceAccounts.d.ts.map +0 -1
  243. package/lib/typescript/commonjs/ui/hooks/useSessionSocket.d.ts +0 -14
  244. package/lib/typescript/commonjs/ui/hooks/useSessionSocket.d.ts.map +0 -1
  245. package/lib/typescript/commonjs/utils/silentGuardKey.d.ts +0 -31
  246. package/lib/typescript/commonjs/utils/silentGuardKey.d.ts.map +0 -1
  247. package/lib/typescript/module/ui/components/accountMenuRows.d.ts +0 -34
  248. package/lib/typescript/module/ui/components/accountMenuRows.d.ts.map +0 -1
  249. package/lib/typescript/module/ui/hooks/useDeviceAccounts.d.ts +0 -133
  250. package/lib/typescript/module/ui/hooks/useDeviceAccounts.d.ts.map +0 -1
  251. package/lib/typescript/module/ui/hooks/useSessionSocket.d.ts +0 -14
  252. package/lib/typescript/module/ui/hooks/useSessionSocket.d.ts.map +0 -1
  253. package/lib/typescript/module/utils/silentGuardKey.d.ts +0 -31
  254. package/lib/typescript/module/utils/silentGuardKey.d.ts.map +0 -1
  255. package/src/ui/components/accountMenuRows.ts +0 -48
  256. package/src/ui/hooks/useDeviceAccounts.ts +0 -344
  257. package/src/ui/hooks/useSessionSocket.ts +0 -233
  258. package/src/ui/utils/__tests__/activeAuthuser.test.ts +0 -75
  259. package/src/utils/__tests__/silentGuardKey.test.ts +0 -82
  260. package/src/utils/silentGuardKey.ts +0 -46
@@ -0,0 +1,79 @@
1
+ "use strict";
2
+
3
+ /**
4
+ * Pure projection helpers: `DeviceSessionState` (the device-scoped
5
+ * multi-account session-sync state produced by `@oxyhq/core`'s
6
+ * `SessionClient`) -> the shapes `OxyContext` renders today
7
+ * (`ClientSession[]`, an active session id, an active `User`).
8
+ *
9
+ * No I/O. The caller fetches profiles via
10
+ * `oxyServices.getUsersByIds(accountIdsOf(state))` and builds `usersById`
11
+ * from the result before calling `deviceStateToClientSessions` /
12
+ * `activeUserOf`.
13
+ */
14
+
15
+ /**
16
+ * Maps every `SessionAccount` in `state.accounts` to a `ClientSession`.
17
+ *
18
+ * `DeviceSessionState` carries no per-account `expiresAt` / `lastActive` —
19
+ * both are set to `state.updatedAt` (converted to an ISO-8601 string; the
20
+ * wire value is an epoch-ms number) as a provisional value. Fase 3-B
21
+ * rewrites `ClientSession` to make `expiresAt`/`lastActive` optional (they
22
+ * are not derivable from `DeviceSessionState`).
23
+ *
24
+ * `usersById` is accepted for signature symmetry with `activeUserOf` even
25
+ * though `ClientSession` only stores `userId` — a session is still
26
+ * projected for an account whose id is absent from `usersById` (no
27
+ * placeholder user is fabricated).
28
+ */
29
+ export function deviceStateToClientSessions(state, usersById) {
30
+ const provisionalTimestamp = new Date(state.updatedAt).toISOString();
31
+ return state.accounts.map(account => ({
32
+ sessionId: account.sessionId,
33
+ deviceId: state.deviceId,
34
+ // provisional: Fase 3-B rewrites ClientSession to make expiresAt/lastActive
35
+ // optional (they are not in DeviceSessionState)
36
+ expiresAt: provisionalTimestamp,
37
+ lastActive: provisionalTimestamp,
38
+ userId: account.accountId,
39
+ isCurrent: account.accountId === state.activeAccountId,
40
+ authuser: account.authuser
41
+ }));
42
+ }
43
+
44
+ /**
45
+ * The active account's `sessionId`, or `null` when there is no state or no
46
+ * active account is set.
47
+ */
48
+ export function activeSessionIdOf(state) {
49
+ if (state === null || state.activeAccountId === null) {
50
+ return null;
51
+ }
52
+ const activeAccountId = state.activeAccountId;
53
+ const activeAccount = state.accounts.find(account => account.accountId === activeAccountId);
54
+ return activeAccount?.sessionId ?? null;
55
+ }
56
+
57
+ /**
58
+ * The active account's `User`, resolved from `usersById`. `null` when there
59
+ * is no state, no active account is set, or the active account id is absent
60
+ * from `usersById`.
61
+ */
62
+ export function activeUserOf(state, usersById) {
63
+ if (state === null || state.activeAccountId === null) {
64
+ return null;
65
+ }
66
+ return usersById.get(state.activeAccountId) ?? null;
67
+ }
68
+
69
+ /**
70
+ * All account ids in `state`, suitable for an `oxyServices.getUsersByIds(...)`
71
+ * fetch. `[]` for `null` state.
72
+ */
73
+ export function accountIdsOf(state) {
74
+ if (state === null) {
75
+ return [];
76
+ }
77
+ return state.accounts.map(account => account.accountId);
78
+ }
79
+ //# sourceMappingURL=projectSessionState.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["deviceStateToClientSessions","state","usersById","provisionalTimestamp","Date","updatedAt","toISOString","accounts","map","account","sessionId","deviceId","expiresAt","lastActive","userId","accountId","isCurrent","activeAccountId","authuser","activeSessionIdOf","activeAccount","find","activeUserOf","get","accountIdsOf"],"sourceRoot":"../../../../src","sources":["ui/session/projectSessionState.ts"],"mappings":";;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASA,2BAA2BA,CACzCC,KAAyB,EACzBC,SAA4B,EACX;EACjB,MAAMC,oBAAoB,GAAG,IAAIC,IAAI,CAACH,KAAK,CAACI,SAAS,CAAC,CAACC,WAAW,CAAC,CAAC;EACpE,OAAOL,KAAK,CAACM,QAAQ,CAACC,GAAG,CAAEC,OAAO,KAAM;IACtCC,SAAS,EAAED,OAAO,CAACC,SAAS;IAC5BC,QAAQ,EAAEV,KAAK,CAACU,QAAQ;IACxB;IACA;IACAC,SAAS,EAAET,oBAAoB;IAC/BU,UAAU,EAAEV,oBAAoB;IAChCW,MAAM,EAAEL,OAAO,CAACM,SAAS;IACzBC,SAAS,EAAEP,OAAO,CAACM,SAAS,KAAKd,KAAK,CAACgB,eAAe;IACtDC,QAAQ,EAAET,OAAO,CAACS;EACpB,CAAC,CAAC,CAAC;AACL;;AAEA;AACA;AACA;AACA;AACA,OAAO,SAASC,iBAAiBA,CAAClB,KAAgC,EAAiB;EACjF,IAAIA,KAAK,KAAK,IAAI,IAAIA,KAAK,CAACgB,eAAe,KAAK,IAAI,EAAE;IACpD,OAAO,IAAI;EACb;EACA,MAAMA,eAAe,GAAGhB,KAAK,CAACgB,eAAe;EAC7C,MAAMG,aAAa,GAAGnB,KAAK,CAACM,QAAQ,CAACc,IAAI,CAAEZ,OAAO,IAAKA,OAAO,CAACM,SAAS,KAAKE,eAAe,CAAC;EAC7F,OAAOG,aAAa,EAAEV,SAAS,IAAI,IAAI;AACzC;;AAEA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASY,YAAYA,CAC1BrB,KAAgC,EAChCC,SAA4B,EACf;EACb,IAAID,KAAK,KAAK,IAAI,IAAIA,KAAK,CAACgB,eAAe,KAAK,IAAI,EAAE;IACpD,OAAO,IAAI;EACb;EACA,OAAOf,SAAS,CAACqB,GAAG,CAACtB,KAAK,CAACgB,eAAe,CAAC,IAAI,IAAI;AACrD;;AAEA;AACA;AACA;AACA;AACA,OAAO,SAASO,YAAYA,CAACvB,KAAgC,EAAY;EACvE,IAAIA,KAAK,KAAK,IAAI,EAAE;IAClB,OAAO,EAAE;EACX;EACA,OAAOA,KAAK,CAACM,QAAQ,CAACC,GAAG,CAAEC,OAAO,IAAKA,OAAO,CAACM,SAAS,CAAC;AAC3D","ignoreList":[]}
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+
3
+ /**
4
+ * Thin `SessionClientHost` adapter over an `OxyServices` instance.
5
+ *
6
+ * `SessionClient` (in `@oxyhq/core`) is host-agnostic: it only needs a REST +
7
+ * token surface. `OxyServices` already exposes all of that except
8
+ * `getCurrentAccountId`, which has no direct equivalent — the adapter holds a
9
+ * mutable ref set by the caller (`OxyContext`, in Fase 3-B) via
10
+ * `setCurrentAccountId`.
11
+ */
12
+ export function createSessionClientHost(oxyServices) {
13
+ let currentAccountId = null;
14
+ return {
15
+ makeRequest: (method, url, data, options) => oxyServices.makeRequest(method, url, data, options),
16
+ getBaseURL: () => oxyServices.getBaseURL(),
17
+ getAccessToken: () => oxyServices.getAccessToken(),
18
+ onTokensChanged: listener => oxyServices.onTokensChanged(listener),
19
+ setTokens: accessToken => oxyServices.setTokens(accessToken),
20
+ getCurrentAccountId: () => currentAccountId,
21
+ setCurrentAccountId: id => {
22
+ currentAccountId = id;
23
+ }
24
+ };
25
+ }
26
+ //# sourceMappingURL=sessionClientHost.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["createSessionClientHost","oxyServices","currentAccountId","makeRequest","method","url","data","options","getBaseURL","getAccessToken","onTokensChanged","listener","setTokens","accessToken","getCurrentAccountId","setCurrentAccountId","id"],"sourceRoot":"../../../../src","sources":["ui/session/sessionClientHost.ts"],"mappings":";;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASA,uBAAuBA,CACrCC,WAAwB,EAC8C;EACtE,IAAIC,gBAA+B,GAAG,IAAI;EAC1C,OAAO;IACLC,WAAW,EAAEA,CAACC,MAAM,EAAEC,GAAG,EAAEC,IAAI,EAAEC,OAAO,KAAKN,WAAW,CAACE,WAAW,CAACC,MAAM,EAAEC,GAAG,EAAEC,IAAI,EAAEC,OAAO,CAAC;IAChGC,UAAU,EAAEA,CAAA,KAAMP,WAAW,CAACO,UAAU,CAAC,CAAC;IAC1CC,cAAc,EAAEA,CAAA,KAAMR,WAAW,CAACQ,cAAc,CAAC,CAAC;IAClDC,eAAe,EAAGC,QAAQ,IAAKV,WAAW,CAACS,eAAe,CAACC,QAAQ,CAAC;IACpEC,SAAS,EAAGC,WAAW,IAAKZ,WAAW,CAACW,SAAS,CAACC,WAAW,CAAC;IAC9DC,mBAAmB,EAAEA,CAAA,KAAMZ,gBAAgB;IAC3Ca,mBAAmB,EAAGC,EAAE,IAAK;MAC3Bd,gBAAgB,GAAGc,EAAE;IACvB;EACF,CAAC;AACH","ignoreList":[]}
@@ -0,0 +1,74 @@
1
+ "use strict";
2
+
3
+ import { logger } from '@oxyhq/core';
4
+ import { isWebBrowser } from "../hooks/useWebSSO.js";
5
+
6
+ /**
7
+ * Platform `TokenTransport` for `SessionClient`: mints an access token when
8
+ * none is currently held, reusing the SAME primitives `OxyContext`'s cold
9
+ * boot already relies on (never re-implemented here):
10
+ *
11
+ * - web: `oxyServices.silentSignIn()` (per-apex `/auth/silent` iframe).
12
+ * - native: `oxyServices.signInWithSharedIdentity()` (app-group keychain).
13
+ *
14
+ * Both primitives plant the token internally on success (the "Sign-In Token
15
+ * Planting" rule) — `ensureActiveToken` never calls `setTokens` itself.
16
+ *
17
+ * `ensureActiveToken` treats a PRESENT token as sufficient in this phase; it
18
+ * does not decode/match the token's subject against `state.activeAccountId`
19
+ * (that refinement is Fase 3-B). Account switching itself is server-driven
20
+ * via the `activeToken` carried in the sync envelope — this transport is
21
+ * only the fallback used when the envelope carried no token.
22
+ *
23
+ * A failed mint is logged and swallowed: it must never throw out of
24
+ * `ensureActiveToken`, since that would crash the caller (the SessionClient
25
+ * socket handler in Fase 3-B).
26
+ */
27
+ export function createTokenTransport(oxyServices) {
28
+ // Coalesces concurrent mints: `SessionClient.applyState` can fire
29
+ // `ensureActiveToken` on rapid successive state pushes; a second call while a
30
+ // mint is already in flight must reuse it, not spawn a second silent iframe /
31
+ // shared-key challenge round-trip.
32
+ let inFlightMint = null;
33
+ return {
34
+ async ensureActiveToken(state) {
35
+ // Read the current token defensively: it is an in-memory getter that
36
+ // should never throw, but the documented contract is that this method
37
+ // never throws out — so a surprising throw is logged and treated as "no
38
+ // token" (fall through to mint) rather than rejecting the promise.
39
+ try {
40
+ if (oxyServices.getAccessToken()) {
41
+ return;
42
+ }
43
+ } catch (error) {
44
+ logger.warn('ensureActiveToken: getAccessToken threw', {
45
+ component: 'TokenTransport'
46
+ }, error);
47
+ }
48
+ if (inFlightMint) {
49
+ return inFlightMint;
50
+ }
51
+ inFlightMint = (async () => {
52
+ try {
53
+ const session = isWebBrowser() ? await oxyServices.silentSignIn() : await oxyServices.signInWithSharedIdentity();
54
+ if (!session) {
55
+ logger.debug('ensureActiveToken: platform mint returned no session', {
56
+ component: 'TokenTransport',
57
+ deviceId: state.deviceId
58
+ });
59
+ }
60
+ } catch (error) {
61
+ logger.warn('ensureActiveToken: mint failed', {
62
+ component: 'TokenTransport'
63
+ }, error);
64
+ }
65
+ })();
66
+ try {
67
+ await inFlightMint;
68
+ } finally {
69
+ inFlightMint = null;
70
+ }
71
+ }
72
+ };
73
+ }
74
+ //# sourceMappingURL=tokenTransport.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["logger","isWebBrowser","createTokenTransport","oxyServices","inFlightMint","ensureActiveToken","state","getAccessToken","error","warn","component","session","silentSignIn","signInWithSharedIdentity","debug","deviceId"],"sourceRoot":"../../../../src","sources":["ui/session/tokenTransport.ts"],"mappings":";;AAEA,SAASA,MAAM,QAAQ,aAAa;AACpC,SAASC,YAAY,QAAQ,uBAAoB;;AAEjD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,oBAAoBA,CAACC,WAAwB,EAAkB;EAC7E;EACA;EACA;EACA;EACA,IAAIC,YAAkC,GAAG,IAAI;EAE7C,OAAO;IACL,MAAMC,iBAAiBA,CAACC,KAAyB,EAAiB;MAChE;MACA;MACA;MACA;MACA,IAAI;QACF,IAAIH,WAAW,CAACI,cAAc,CAAC,CAAC,EAAE;UAChC;QACF;MACF,CAAC,CAAC,OAAOC,KAAK,EAAE;QACdR,MAAM,CAACS,IAAI,CAAC,yCAAyC,EAAE;UAAEC,SAAS,EAAE;QAAiB,CAAC,EAAEF,KAAK,CAAC;MAChG;MAEA,IAAIJ,YAAY,EAAE;QAChB,OAAOA,YAAY;MACrB;MAEAA,YAAY,GAAG,CAAC,YAAY;QAC1B,IAAI;UACF,MAAMO,OAAO,GAAGV,YAAY,CAAC,CAAC,GAC1B,MAAME,WAAW,CAACS,YAAY,CAAC,CAAC,GAChC,MAAMT,WAAW,CAACU,wBAAwB,CAAC,CAAC;UAEhD,IAAI,CAACF,OAAO,EAAE;YACZX,MAAM,CAACc,KAAK,CAAC,sDAAsD,EAAE;cACnEJ,SAAS,EAAE,gBAAgB;cAC3BK,QAAQ,EAAET,KAAK,CAACS;YAClB,CAAC,CAAC;UACJ;QACF,CAAC,CAAC,OAAOP,KAAK,EAAE;UACdR,MAAM,CAACS,IAAI,CAAC,gCAAgC,EAAE;YAAEC,SAAS,EAAE;UAAiB,CAAC,EAAEF,KAAK,CAAC;QACvF;MACF,CAAC,EAAE,CAAC;MAEJ,IAAI;QACF,MAAMJ,YAAY;MACpB,CAAC,SAAS;QACRA,YAAY,GAAG,IAAI;MACrB;IACF;EACF,CAAC;AACH","ignoreList":[]}
@@ -1,19 +1,25 @@
1
1
  "use strict";
2
2
 
3
3
  /**
4
- * Web-only persistence of the active multi-account slot index.
4
+ * Web-only helpers around the retired `oxy_rt_${authuser}` multi-slot
5
+ * refresh-cookie scheme, PLUS the (unrelated, still load-bearing) deliberate
6
+ * sign-out / SSO-bounce gates.
5
7
  *
6
- * Google-style multi-account sign-in stores ONE refresh cookie per device
7
- * slot (`oxy_rt_${authuser}`, where `authuser` is an integer 0..N). The
8
- * server's `/auth/refresh-all` returns one entry per valid cookie; the
9
- * client must remember WHICH slot is currently active across reloads so
10
- * that the cold-boot snapshot resolves to the user's last selection
11
- * rather than always defaulting to slot 0.
12
- *
13
- * The persisted value is JUST the slot INDEX (a small integer) — never an
14
- * access token, refresh token, session id, or any user-identifying secret.
15
- * It is read by both `OxyContext` (cold-boot active selection) and the
16
- * session-management / auth-operations hooks (switch / logout).
8
+ * NOTE (session-sync cutover, Task 5): the device account SET is now
9
+ * server-authoritative via `SessionClient` (`@oxyhq/core`) nothing in
10
+ * `@oxyhq/services` writes the persisted active-`authuser`-slot key anymore
11
+ * (`writeActiveAuthuser`/`clearActiveAuthuser` were deleted; their only
12
+ * callers were the deleted `establishDeviceRefreshSlot` sign-in registration
13
+ * and the deleted `switchToAccount`/`switchSession` slot bookkeeping).
14
+ * {@link readActiveAuthuser} is KEPT purely as an OPTIONAL restore hint:
15
+ * `OxyContext`'s `restoreStoredSession` cold-boot step reads it only to
16
+ * backfill `clientSession.authuser` for the active session when a legacy value
17
+ * happens to be present. It NO LONGER gates whether restore is attempted the
18
+ * old guard that also required this marker made every web reload with a lapsed
19
+ * local bearer bail before any network validation (P0), and was replaced by a
20
+ * "bail only when there is nothing to restore" guard plus a valid-session
21
+ * election. Since nothing writes the key anymore, the backfill is dormant on
22
+ * fresh installs; it stays for legacy installs and costs nothing.
17
23
  *
18
24
  * Native (React Native) has no equivalent of these device-local cookies
19
25
  * and uses bearer-protected session ids directly, so these helpers no-op
@@ -22,23 +28,8 @@
22
28
 
23
29
  import { ssoAttemptedKey, ssoNoSessionKey, ssoGuardKey, ssoStateKey, ssoDestKey, ssoSignedOutKey, silentRestoreSuppressed } from '@oxyhq/core';
24
30
  const ACTIVE_AUTHUSER_KEY = 'oxy_active_authuser';
25
-
26
- /**
27
- * Safely resolve `window.localStorage`, returning `null` when it is
28
- * unavailable. The PROPERTY ACCESS itself (`window.localStorage`) can throw a
29
- * `SecurityError` synchronously in opaque-origin / sandboxed iframes or when
30
- * storage is disabled — even `typeof window.localStorage` evaluates the getter
31
- * and throws. Every read/write in this module routes through here so the getter
32
- * throw is caught once, at the source, and callers stay clean. Returns `null`
33
- * off-web and on any access failure (fail safe).
34
- */
35
- function getLocalStorage() {
36
- if (typeof window === 'undefined') return null;
37
- try {
38
- return window.localStorage ?? null;
39
- } catch {
40
- return null;
41
- }
31
+ function hasLocalStorage() {
32
+ return typeof window !== 'undefined' && typeof window.localStorage !== 'undefined';
42
33
  }
43
34
  function getSessionStorage() {
44
35
  if (typeof window === 'undefined') return null;
@@ -57,12 +48,11 @@ function getSessionStorage() {
57
48
  * fall back to deterministic selection (lowest authuser).
58
49
  */
59
50
  export function readActiveAuthuser() {
60
- const storage = getLocalStorage();
61
- if (!storage) {
51
+ if (!hasLocalStorage()) {
62
52
  return null;
63
53
  }
64
54
  try {
65
- const raw = storage.getItem(ACTIVE_AUTHUSER_KEY);
55
+ const raw = window.localStorage.getItem(ACTIVE_AUTHUSER_KEY);
66
56
  if (raw === null) return null;
67
57
  const parsed = Number.parseInt(raw, 10);
68
58
  if (!Number.isFinite(parsed) || parsed < 0) return null;
@@ -72,50 +62,18 @@ export function readActiveAuthuser() {
72
62
  }
73
63
  }
74
64
 
75
- /**
76
- * Persist the active `authuser` slot index. No-ops on native and on any
77
- * storage failure (e.g. Safari private mode). Callers MUST NOT depend on
78
- * this succeeding — it is best-effort UX persistence, not authoritative.
79
- */
80
- export function writeActiveAuthuser(authuser) {
81
- if (!Number.isFinite(authuser) || authuser < 0) return;
82
- const storage = getLocalStorage();
83
- if (!storage) return;
84
- try {
85
- storage.setItem(ACTIVE_AUTHUSER_KEY, String(authuser));
86
- } catch {
87
- // Best-effort persistence; swallow QuotaExceededError / SecurityError.
88
- }
89
- }
90
-
91
- /**
92
- * Clear the persisted active `authuser` slot index. Called on full sign-out
93
- * (logoutAll) so that the next cold boot doesn't try to resurrect a
94
- * cleared slot.
95
- */
96
- export function clearActiveAuthuser() {
97
- const storage = getLocalStorage();
98
- if (!storage) return;
99
- try {
100
- storage.removeItem(ACTIVE_AUTHUSER_KEY);
101
- } catch {
102
- // Best-effort.
103
- }
104
- }
105
-
106
65
  /**
107
66
  * Mark this origin as DELIBERATELY signed out (durable `localStorage`, via the
108
67
  * core {@link ssoSignedOutKey}). Called ONLY on EXPLICIT full sign-out so that
109
68
  * the next cold boot does NOT silently re-mint a session from a still-live IdP
110
- * session (`fedcm-silent` / per-apex `/auth/silent` iframe). Cleared by any
69
+ * session (the per-apex `/auth/silent` iframe cold-boot step). Cleared by any
111
70
  * deliberate sign-in (see {@link clearSignedOut}). No-ops on native / storage
112
71
  * failure (best-effort).
113
72
  */
114
73
  export function markSignedOut() {
115
- const storage = getLocalStorage();
116
- if (!storage) return;
74
+ if (!hasLocalStorage()) return;
117
75
  try {
118
- storage.setItem(ssoSignedOutKey(window.location.origin), '1');
76
+ window.localStorage.setItem(ssoSignedOutKey(window.location.origin), '1');
119
77
  } catch {
120
78
  // Best-effort; swallow QuotaExceededError / SecurityError (private mode).
121
79
  }
@@ -123,15 +81,14 @@ export function markSignedOut() {
123
81
 
124
82
  /**
125
83
  * Clear the durable deliberately-signed-out flag. Called on ANY deliberate
126
- * sign-in (password, FedCM, account switch, device claim) so a real sign-in
84
+ * sign-in (password, account switch, device claim) so a real sign-in
127
85
  * fully re-enables automatic silent restore — there is no "stuck signed out"
128
86
  * state. No-ops on native / storage failure.
129
87
  */
130
88
  export function clearSignedOut() {
131
- const storage = getLocalStorage();
132
- if (!storage) return;
89
+ if (!hasLocalStorage()) return;
133
90
  try {
134
- storage.removeItem(ssoSignedOutKey(window.location.origin));
91
+ window.localStorage.removeItem(ssoSignedOutKey(window.location.origin));
135
92
  } catch {
136
93
  // Best-effort.
137
94
  }
@@ -142,12 +99,14 @@ export function clearSignedOut() {
142
99
  * the user deliberately signed out. Reads the durable flag through the core
143
100
  * {@link silentRestoreSuppressed} predicate. Returns `false` off-web and on any
144
101
  * storage failure (fail safe toward normal restore). Used to gate the
145
- * `fedcm-silent` and `silent-iframe` cold-boot steps.
102
+ * `silent-iframe` cold-boot step.
146
103
  */
147
104
  export function isSilentRestoreSuppressed() {
148
- const storage = getLocalStorage();
149
- if (!storage) return false;
150
- return silentRestoreSuppressed(storage, window.location.origin);
105
+ // Unlike its try/catch-wrapped siblings this reads `window.location.origin`
106
+ // directly, so guard it: an RN polyfill can expose `localStorage` without a
107
+ // `location`, which would throw here. Fail safe toward normal restore.
108
+ if (!hasLocalStorage() || typeof window.location === 'undefined') return false;
109
+ return silentRestoreSuppressed(window.localStorage, window.location.origin);
151
110
  }
152
111
 
153
112
  /**
@@ -172,5 +131,4 @@ export function clearSsoBounceState() {
172
131
  // Best-effort; swallow SecurityError (e.g. Safari private mode).
173
132
  }
174
133
  }
175
- export { ACTIVE_AUTHUSER_KEY };
176
134
  //# sourceMappingURL=activeAuthuser.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["ssoAttemptedKey","ssoNoSessionKey","ssoGuardKey","ssoStateKey","ssoDestKey","ssoSignedOutKey","silentRestoreSuppressed","ACTIVE_AUTHUSER_KEY","getLocalStorage","window","localStorage","getSessionStorage","sessionStorage","readActiveAuthuser","storage","raw","getItem","parsed","Number","parseInt","isFinite","writeActiveAuthuser","authuser","setItem","String","clearActiveAuthuser","removeItem","markSignedOut","location","origin","clearSignedOut","isSilentRestoreSuppressed","clearSsoBounceState"],"sourceRoot":"../../../../src","sources":["ui/utils/activeAuthuser.ts"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["ssoAttemptedKey","ssoNoSessionKey","ssoGuardKey","ssoStateKey","ssoDestKey","ssoSignedOutKey","silentRestoreSuppressed","ACTIVE_AUTHUSER_KEY","hasLocalStorage","window","localStorage","getSessionStorage","sessionStorage","readActiveAuthuser","raw","getItem","parsed","Number","parseInt","isFinite","markSignedOut","setItem","location","origin","clearSignedOut","removeItem","isSilentRestoreSuppressed","clearSsoBounceState","storage"],"sourceRoot":"../../../../src","sources":["ui/utils/activeAuthuser.ts"],"mappings":"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","ignoreList":[]}
@@ -52,53 +52,4 @@ export const fetchSessionsWithFallback = async (oxyServices, sessionId, {
52
52
  return mapSessionsToClient(userSessions, fallbackDeviceId, fallbackUserId);
53
53
  }
54
54
  };
55
-
56
- /**
57
- * Validate multiple sessions concurrently with configurable concurrency.
58
- *
59
- * @param oxyServices - Oxy service instance
60
- * @param sessionIds - Session identifiers to validate
61
- * @param options - Validation options
62
- */
63
- export const validateSessionBatch = async (oxyServices, sessionIds, {
64
- useHeaderValidation = true,
65
- maxConcurrency = 5
66
- } = {}) => {
67
- if (!sessionIds.length) {
68
- return [];
69
- }
70
- const uniqueSessionIds = Array.from(new Set(sessionIds));
71
- const safeConcurrency = Math.max(1, Math.min(maxConcurrency, uniqueSessionIds.length));
72
- const results = [];
73
- let index = 0;
74
- const worker = async () => {
75
- while (index < uniqueSessionIds.length) {
76
- const currentIndex = index;
77
- index += 1;
78
- const sessionId = uniqueSessionIds[currentIndex];
79
- try {
80
- const validation = await oxyServices.validateSession(sessionId, {
81
- useHeaderValidation
82
- });
83
- const valid = Boolean(validation?.valid);
84
- results.push({
85
- sessionId,
86
- valid,
87
- user: validation?.user,
88
- raw: validation
89
- });
90
- } catch (error) {
91
- results.push({
92
- sessionId,
93
- valid: false,
94
- error
95
- });
96
- }
97
- }
98
- };
99
- await Promise.all(Array.from({
100
- length: safeConcurrency
101
- }, worker));
102
- return results;
103
- };
104
55
  //# sourceMappingURL=sessionHelpers.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["mapSessionsToClient","sessions","fallbackDeviceId","fallbackUserId","now","Date","map","session","sessionId","deviceId","expiresAt","getTime","toISOString","lastActive","userId","user","id","_id","toString","undefined","isCurrent","Boolean","fetchSessionsWithFallback","oxyServices","logger","deviceSessions","getDeviceSessions","error","__DEV__","userSessions","getSessionsBySessionId","validateSessionBatch","sessionIds","useHeaderValidation","maxConcurrency","length","uniqueSessionIds","Array","from","Set","safeConcurrency","Math","max","min","results","index","worker","currentIndex","validation","validateSession","valid","push","raw","Promise","all"],"sourceRoot":"../../../../src","sources":["ui/utils/sessionHelpers.ts"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["mapSessionsToClient","sessions","fallbackDeviceId","fallbackUserId","now","Date","map","session","sessionId","deviceId","expiresAt","getTime","toISOString","lastActive","userId","user","id","_id","toString","undefined","isCurrent","Boolean","fetchSessionsWithFallback","oxyServices","logger","deviceSessions","getDeviceSessions","error","__DEV__","userSessions","getSessionsBySessionId"],"sourceRoot":"../../../../src","sources":["ui/utils/sessionHelpers.ts"],"mappings":";;AAaA;AACA;AACA;AACA;AACA;AACA;AACA;;AASA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,MAAMA,mBAAmB,GAAGA,CACjCC,QAAyB,EACzBC,gBAAyB,EACzBC,cAAuB,KACH;EACpB,MAAMC,GAAG,GAAG,IAAIC,IAAI,CAAC,CAAC;EAEtB,OAAOJ,QAAQ,CAACK,GAAG,CAAEC,OAAO,KAAM;IAChCC,SAAS,EAAED,OAAO,CAACC,SAAS;IAC5BC,QAAQ,EAAEF,OAAO,CAACE,QAAQ,IAAIP,gBAAgB,IAAI,EAAE;IACpDQ,SAAS,EAAEH,OAAO,CAACG,SAAS,IAAI,IAAIL,IAAI,CAACD,GAAG,CAACO,OAAO,CAAC,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAACC,WAAW,CAAC,CAAC;IAC/FC,UAAU,EAAEN,OAAO,CAACM,UAAU,IAAIT,GAAG,CAACQ,WAAW,CAAC,CAAC;IACnDE,MAAM,EACJP,OAAO,CAACQ,IAAI,EAAEC,EAAE,IAChBT,OAAO,CAACO,MAAM,KACbP,OAAO,CAACQ,IAAI,EAAEE,GAAG,GAAGV,OAAO,CAACQ,IAAI,CAACE,GAAG,CAACC,QAAQ,CAAC,CAAC,GAAGC,SAAS,CAAC,IAC7DhB,cAAc,IACd,EAAE;IACJiB,SAAS,EAAEC,OAAO,CAACd,OAAO,CAACa,SAAS;EACtC,CAAC,CAAC,CAAC;AACL,CAAC;;AAED;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,MAAME,yBAAyB,GAAG,MAAAA,CACvCC,WAA2B,EAC3Bf,SAAiB,EACjB;EACEN,gBAAgB;EAChBC,cAAc;EACdqB;AACgC,CAAC,GAAG,CAAC,CAAC,KACX;EAC7B,IAAI;IACF,MAAMC,cAAc,GAAG,MAAMF,WAAW,CAACG,iBAAiB,CAAClB,SAAS,CAAC;IACrE,OAAOR,mBAAmB,CAACyB,cAAc,EAAEvB,gBAAgB,EAAEC,cAAc,CAAC;EAC9E,CAAC,CAAC,OAAOwB,KAAK,EAAE;IACd,IAAIC,OAAO,IAAIJ,MAAM,EAAE;MACrBA,MAAM,CAAC,8DAA8D,EAAEG,KAAK,CAAC;IAC/E;IAEA,MAAME,YAAY,GAAG,MAAMN,WAAW,CAACO,sBAAsB,CAACtB,SAAS,CAAC;IACxE,OAAOR,mBAAmB,CAAC6B,YAAY,EAAE3B,gBAAgB,EAAEC,cAAc,CAAC;EAC5E;AACF,CAAC","ignoreList":[]}
@@ -4,41 +4,62 @@
4
4
  * Shared, pure orchestration for completing the cross-app device-flow sign-in
5
5
  * (the QR-code / "Open Oxy Auth" path used on native and web).
6
6
  *
7
- * THE BUG THIS FIXES (native): once another authenticated device approves the
8
- * pending AuthSession, the originating client is notified (socket / poll /
9
- * deep-link) with the authorized `sessionId`. Before any session-management
10
- * code can use it, the client MUST exchange the secret 128-bit `sessionToken`
11
- * (held only by this client, generated for THIS flow) for the first access
12
- * token via `claimSessionByToken` — the device-flow equivalent of OAuth's
13
- * code-for-token exchange (RFC 8628 §3.4).
7
+ * THE FIRST BUG THIS FIXES (native): once another authenticated device
8
+ * approves the pending AuthSession, the originating client is notified
9
+ * (socket / poll / deep-link) with the authorized `sessionId`. Before any
10
+ * session-management code can use it, the client MUST exchange the secret
11
+ * 128-bit `sessionToken` (held only by this client, generated for THIS flow)
12
+ * for the first access token via `claimSessionByToken` — the device-flow
13
+ * equivalent of OAuth's code-for-token exchange (RFC 8628 §3.4).
14
+ *
15
+ * THE SECOND BUG THIS FIXES (session-sync cutover regression): the
16
+ * freshly-claimed session is NOT yet registered in the device's
17
+ * server-authoritative session set — nothing has run
18
+ * `sessionClient.addCurrentAccount()` for it — so it must NOT be committed
19
+ * through `switchSession`. That path is now an account-SWITCH between
20
+ * accounts already registered on this device (`OxyContext`'s
21
+ * `switchSessionForContext`), and throws `No device account found for
22
+ * session "..."` for anything else, surfacing as "Authorization successful
23
+ * but failed to complete sign in." Instead the claimed session must be
24
+ * committed through the SAME path a fresh password sign-in uses —
25
+ * `useOxy().handleWebSession` (`OxyContext`'s `handleWebSSOSession`) — which
26
+ * registers the account into the device set, persists it durably, and
27
+ * hydrates the full user profile.
14
28
  *
15
29
  * Skipping the claim leaves the SDK with NO bearer token: the session is
16
30
  * authorized server-side but the app never becomes authenticated and the UI
17
- * sits "Waiting for authorization..." forever. Consolidating the claim→switch
18
- * sequence here keeps native and web identical and unit-testable.
31
+ * sits "Waiting for authorization..." forever. Consolidating the
32
+ * claim->commit sequence here keeps native and web identical and
33
+ * unit-testable.
19
34
  */
20
35
 
21
- import { KeyManager } from '@oxyhq/core';
36
+ import { KeyManager, establishIdpSessionAfterClaim } from '@oxyhq/core';
22
37
 
23
38
  /**
24
39
  * The minimal `OxyServices` surface this orchestration needs. Kept as a
25
40
  * structural type (rather than importing the full client) so the helper is
26
41
  * trivially unit-testable with a stub and never pulls the RN/Expo runtime into
27
42
  * a test bundle.
43
+ *
44
+ * Extends {@link SsoEstablishClient} (`requestSsoEstablishUrl`) so the WEB
45
+ * post-claim durable-session hop can be driven off the same client.
28
46
  */
29
47
 
30
48
  /**
31
49
  * Complete a device-flow sign-in: claim the first access token with the secret
32
- * `sessionToken` (planting the bearer), then hydrate the session via
33
- * `switchSession`. Returns the authenticated user.
50
+ * `sessionToken` (planting the bearer), then commit the resulting session via
51
+ * `commitSession` (registers it into the device's server-authoritative session
52
+ * set and hydrates the full user). Returns the authenticated user.
34
53
  *
35
- * Throws if either the claim or the switch fails; callers surface a retry UI.
54
+ * Throws if the claim did not return a usable session, or if either the claim
55
+ * or the commit fails; callers surface a retry UI.
36
56
  */
37
57
  export async function completeDeviceFlowSignIn({
38
58
  oxyServices,
39
59
  sessionId,
40
60
  sessionToken,
41
- switchSession
61
+ commitSession,
62
+ establishDeps
42
63
  }) {
43
64
  // 1) Plant the bearer + refresh tokens. The claim response is also persisted
44
65
  // to native shared secure storage so a later cold boot has a bearer before
@@ -47,8 +68,42 @@ export async function completeDeviceFlowSignIn({
47
68
  if (claimed?.accessToken) {
48
69
  await KeyManager.storeSharedSession(claimed.sessionId || sessionId, claimed.accessToken);
49
70
  }
71
+ if (!claimed?.accessToken || !claimed.user) {
72
+ throw new Error('Device-flow claim did not return a usable session');
73
+ }
74
+
75
+ // `SessionLoginResponse.user` is the minimal session-carried shape (avatar
76
+ // is `string | undefined`); the claim response returns the full `User`
77
+ // (avatar is `string | null | undefined`). Normalize rather than widening
78
+ // `SessionLoginResponse.user` to accept `null`.
79
+ const minimalUser = {
80
+ id: claimed.user.id,
81
+ username: claimed.user.username,
82
+ name: claimed.user.name,
83
+ avatar: claimed.user.avatar ?? undefined
84
+ };
85
+
86
+ // 2) Bearer is now planted — commit the session through the same path a
87
+ // fresh sign-in uses so it is registered into the device's
88
+ // server-authoritative session set instead of an account switch.
89
+ await commitSession({
90
+ sessionId: claimed.sessionId || sessionId,
91
+ deviceId: claimed.deviceId ?? '',
92
+ expiresAt: claimed.expiresAt ?? '',
93
+ user: minimalUser,
94
+ accessToken: claimed.accessToken
95
+ });
50
96
 
51
- // 2) Bearer is now planted hydrate the session through the normal path.
52
- return switchSession(sessionId);
97
+ // 3) WEB durable-session hop (no-op on native). A device-flow claim plants
98
+ // ONLY in-memory tokens — no IdP `fedcm_session` cookie is ever planted, so
99
+ // a reload cannot re-mint a token and the session is lost. Now that the
100
+ // session is committed AND durably persisted (step 2), plant the per-apex
101
+ // IdP cookie via ONE top-level establish hop. Single attempt; total (never
102
+ // throws) — an establish failure leaves the committed session as-is. On web
103
+ // success it navigates away, so it is the LAST step: the browser tears the
104
+ // page down on the next tick, after `claimed.user` is returned to the
105
+ // caller's `onSignedIn`.
106
+ await establishIdpSessionAfterClaim(oxyServices, establishDeps ?? {});
107
+ return claimed.user;
53
108
  }
54
109
  //# sourceMappingURL=deviceFlowSignIn.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["KeyManager","completeDeviceFlowSignIn","oxyServices","sessionId","sessionToken","switchSession","claimed","claimSessionByToken","accessToken","storeSharedSession"],"sourceRoot":"../../../src","sources":["utils/deviceFlowSignIn.ts"],"mappings":";;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,SAASA,UAAU,QAAmB,aAAa;;AAOnD;AACA;AACA;AACA;AACA;AACA;;AA4BA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,eAAeC,wBAAwBA,CAAC;EAC7CC,WAAW;EACXC,SAAS;EACTC,YAAY;EACZC;AAC+B,CAAC,EAAiB;EACjD;EACA;EACA;EACA,MAAMC,OAAO,GAAG,MAAMJ,WAAW,CAACK,mBAAmB,CAACH,YAAY,CAAC;EACnE,IAAIE,OAAO,EAAEE,WAAW,EAAE;IACxB,MAAMR,UAAU,CAACS,kBAAkB,CAACH,OAAO,CAACH,SAAS,IAAIA,SAAS,EAAEG,OAAO,CAACE,WAAW,CAAC;EAC1F;;EAEA;EACA,OAAOH,aAAa,CAACF,SAAS,CAAC;AACjC","ignoreList":[]}
1
+ {"version":3,"names":["KeyManager","establishIdpSessionAfterClaim","completeDeviceFlowSignIn","oxyServices","sessionId","sessionToken","commitSession","establishDeps","claimed","claimSessionByToken","accessToken","storeSharedSession","user","Error","minimalUser","id","username","name","avatar","undefined","deviceId","expiresAt"],"sourceRoot":"../../../src","sources":["utils/deviceFlowSignIn.ts"],"mappings":";;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,SACEA,UAAU,EACVC,6BAA6B,QAMxB,aAAa;;AAUpB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAqCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,eAAeC,wBAAwBA,CAAC;EAC7CC,WAAW;EACXC,SAAS;EACTC,YAAY;EACZC,aAAa;EACbC;AAC+B,CAAC,EAAiB;EACjD;EACA;EACA;EACA,MAAMC,OAAO,GAAG,MAAML,WAAW,CAACM,mBAAmB,CAACJ,YAAY,CAAC;EACnE,IAAIG,OAAO,EAAEE,WAAW,EAAE;IACxB,MAAMV,UAAU,CAACW,kBAAkB,CAACH,OAAO,CAACJ,SAAS,IAAIA,SAAS,EAAEI,OAAO,CAACE,WAAW,CAAC;EAC1F;EAEA,IAAI,CAACF,OAAO,EAAEE,WAAW,IAAI,CAACF,OAAO,CAACI,IAAI,EAAE;IAC1C,MAAM,IAAIC,KAAK,CAAC,mDAAmD,CAAC;EACtE;;EAEA;EACA;EACA;EACA;EACA,MAAMC,WAA4B,GAAG;IACnCC,EAAE,EAAEP,OAAO,CAACI,IAAI,CAACG,EAAE;IACnBC,QAAQ,EAAER,OAAO,CAACI,IAAI,CAACI,QAAQ;IAC/BC,IAAI,EAAET,OAAO,CAACI,IAAI,CAACK,IAAI;IACvBC,MAAM,EAAEV,OAAO,CAACI,IAAI,CAACM,MAAM,IAAIC;EACjC,CAAC;;EAED;EACA;EACA;EACA,MAAMb,aAAa,CAAC;IAClBF,SAAS,EAAEI,OAAO,CAACJ,SAAS,IAAIA,SAAS;IACzCgB,QAAQ,EAAEZ,OAAO,CAACY,QAAQ,IAAI,EAAE;IAChCC,SAAS,EAAEb,OAAO,CAACa,SAAS,IAAI,EAAE;IAClCT,IAAI,EAAEE,WAAW;IACjBJ,WAAW,EAAEF,OAAO,CAACE;EACvB,CAAC,CAAC;;EAEF;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA,MAAMT,6BAA6B,CAACE,WAAW,EAAEI,aAAa,IAAI,CAAC,CAAC,CAAC;EAErE,OAAOC,OAAO,CAACI,IAAI;AACrB","ignoreList":[]}
@@ -28,7 +28,6 @@ export type { AuthState, AuthActions, UseAuthReturn } from './ui/hooks/useAuth';
28
28
  export { FontLoader } from './ui/components/FontLoader';
29
29
  export { useAuthStore } from './ui/stores/authStore';
30
30
  export { useAssetStore, useAssets as useAssetsStore, useAsset, useUploadProgress, useAssetLoading, useAssetErrors, useAssetsByApp, useAssetsByEntity, useAssetUsageCount, useIsAssetLinked, } from './ui/stores/assetStore';
31
- export { useSessionSocket } from './ui/hooks/useSessionSocket';
32
31
  export { useAssets, setOxyAssetInstance } from './ui/hooks/useAssets';
33
32
  export { useFileDownloadUrl } from './ui/hooks/useFileDownloadUrl';
34
33
  export { useFollow, useFollowerCounts } from './ui/hooks/useFollow';
@@ -71,8 +70,8 @@ export { default as ProfileMenu } from './ui/components/ProfileMenu';
71
70
  export type { ProfileMenuProps, ProfileMenuAnchor } from './ui/components/ProfileMenu';
72
71
  export { default as AccountSwitcher, AccountSwitcherView } from './ui/components/AccountSwitcher';
73
72
  export type { AccountSwitcherProps, AccountSwitcherActions } from './ui/components/AccountSwitcher';
74
- export { useDeviceAccounts } from './ui/hooks/useDeviceAccounts';
75
- export type { DeviceAccount, DeviceAccountUser, UseDeviceAccountsResult, } from './ui/hooks/useDeviceAccounts';
73
+ export { useSwitchableAccounts } from './ui/hooks/useSwitchableAccounts';
74
+ export type { SwitchableAccount, SwitchableAccountUser, UseSwitchableAccountsResult, } from './ui/hooks/useSwitchableAccounts';
76
75
  export { default as ManageAccountScreen } from './ui/screens/ManageAccountScreen';
77
76
  export { default as NotificationsScreen } from './ui/screens/NotificationsScreen';
78
77
  export { default as PreferencesScreen } from './ui/screens/PreferencesScreen';