@oxyhq/services 22.12.4 → 22.12.7

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 (639) hide show
  1. package/README.md +16 -46
  2. package/lib/commonjs/index.js +84 -10
  3. package/lib/commonjs/index.js.map +1 -1
  4. package/lib/commonjs/notifications/deviceNotifications.js +380 -0
  5. package/lib/commonjs/notifications/deviceNotifications.js.map +1 -0
  6. package/lib/commonjs/ui/boot/runProviderColdBoot.js +51 -9
  7. package/lib/commonjs/ui/boot/runProviderColdBoot.js.map +1 -1
  8. package/lib/commonjs/ui/client.js +0 -13
  9. package/lib/commonjs/ui/client.js.map +1 -1
  10. package/lib/commonjs/ui/components/AvatarCameraBadge.js +3 -2
  11. package/lib/commonjs/ui/components/AvatarCameraBadge.js.map +1 -1
  12. package/lib/commonjs/ui/components/OxyAccountDialogScreen.js +14 -3
  13. package/lib/commonjs/ui/components/OxyAccountDialogScreen.js.map +1 -1
  14. package/lib/commonjs/ui/components/OxyAuthChooser.js +70 -1121
  15. package/lib/commonjs/ui/components/OxyAuthChooser.js.map +1 -1
  16. package/lib/commonjs/ui/components/OxyConsentScreen.js +50 -12
  17. package/lib/commonjs/ui/components/OxyConsentScreen.js.map +1 -1
  18. package/lib/commonjs/ui/components/OxyProvider.js +4 -4
  19. package/lib/commonjs/ui/components/OxyProvider.js.map +1 -1
  20. package/lib/commonjs/ui/components/OxySignInButton.js +74 -40
  21. package/lib/commonjs/ui/components/OxySignInButton.js.map +1 -1
  22. package/lib/commonjs/ui/components/OxySignInRequestSurface.js +147 -0
  23. package/lib/commonjs/ui/components/OxySignInRequestSurface.js.map +1 -0
  24. package/lib/commonjs/ui/components/ProfileButton.js +4 -3
  25. package/lib/commonjs/ui/components/ProfileButton.js.map +1 -1
  26. package/lib/commonjs/ui/components/SettingsIcon.js +3 -2
  27. package/lib/commonjs/ui/components/SettingsIcon.js.map +1 -1
  28. package/lib/commonjs/ui/components/authChooser/AccountsMenuView.js +527 -0
  29. package/lib/commonjs/ui/components/authChooser/AccountsMenuView.js.map +1 -0
  30. package/lib/commonjs/ui/components/authChooser/SignInEntryView.js +90 -0
  31. package/lib/commonjs/ui/components/authChooser/SignInEntryView.js.map +1 -0
  32. package/lib/commonjs/ui/components/authChooser/SignInRequestView.js +106 -0
  33. package/lib/commonjs/ui/components/authChooser/SignInRequestView.js.map +1 -0
  34. package/lib/commonjs/ui/components/authChooser/SignUpView.js +188 -0
  35. package/lib/commonjs/ui/components/authChooser/SignUpView.js.map +1 -0
  36. package/lib/commonjs/ui/components/authChooser/TroubleDisclosure.js +61 -0
  37. package/lib/commonjs/ui/components/authChooser/TroubleDisclosure.js.map +1 -0
  38. package/lib/commonjs/ui/components/authChooser/primitives.js +170 -0
  39. package/lib/commonjs/ui/components/authChooser/primitives.js.map +1 -0
  40. package/lib/commonjs/ui/components/authChooser/requestSurfaces.js +153 -0
  41. package/lib/commonjs/ui/components/authChooser/requestSurfaces.js.map +1 -0
  42. package/lib/commonjs/ui/components/authChooser/signInProgress.js +54 -0
  43. package/lib/commonjs/ui/components/authChooser/signInProgress.js.map +1 -0
  44. package/lib/commonjs/ui/components/{oxyAuthChooserStyles.js → authChooser/styles.js} +19 -1
  45. package/lib/commonjs/ui/components/authChooser/styles.js.map +1 -0
  46. package/lib/commonjs/ui/components/authChooser/types.js +70 -0
  47. package/lib/commonjs/ui/components/authChooser/types.js.map +1 -0
  48. package/lib/commonjs/ui/components/authChooser/useUsernameAvailability.js +50 -0
  49. package/lib/commonjs/ui/components/authChooser/useUsernameAvailability.js.map +1 -0
  50. package/lib/commonjs/ui/components/fileManagement/AnimatedButton.js +3 -2
  51. package/lib/commonjs/ui/components/fileManagement/AnimatedButton.js.map +1 -1
  52. package/lib/commonjs/ui/components/fileManagement/FileDetailsModal.js +3 -2
  53. package/lib/commonjs/ui/components/fileManagement/FileDetailsModal.js.map +1 -1
  54. package/lib/commonjs/ui/components/fileManagement/FileViewer.js +15 -14
  55. package/lib/commonjs/ui/components/fileManagement/FileViewer.js.map +1 -1
  56. package/lib/commonjs/ui/components/fileManagement/UploadPreview.js +6 -5
  57. package/lib/commonjs/ui/components/fileManagement/UploadPreview.js.map +1 -1
  58. package/lib/commonjs/ui/components/modals/DeleteAccountModal.js +3 -2
  59. package/lib/commonjs/ui/components/modals/DeleteAccountModal.js.map +1 -1
  60. package/lib/commonjs/ui/components/payment/PaymentDetailsStep.js +6 -6
  61. package/lib/commonjs/ui/components/payment/PaymentDetailsStep.js.map +1 -1
  62. package/lib/commonjs/ui/components/payment/PaymentMethodStep.js +5 -5
  63. package/lib/commonjs/ui/components/payment/PaymentMethodStep.js.map +1 -1
  64. package/lib/commonjs/ui/components/payment/PaymentReviewStep.js +10 -9
  65. package/lib/commonjs/ui/components/payment/PaymentReviewStep.js.map +1 -1
  66. package/lib/commonjs/ui/components/payment/PaymentSuccessStep.js +4 -3
  67. package/lib/commonjs/ui/components/payment/PaymentSuccessStep.js.map +1 -1
  68. package/lib/commonjs/ui/components/payment/PaymentSummaryStep.js +6 -5
  69. package/lib/commonjs/ui/components/payment/PaymentSummaryStep.js.map +1 -1
  70. package/lib/commonjs/ui/context/OxyContext.js +200 -29
  71. package/lib/commonjs/ui/context/OxyContext.js.map +1 -1
  72. package/lib/commonjs/ui/context/commitSessionFlow.js +43 -0
  73. package/lib/commonjs/ui/context/commitSessionFlow.js.map +1 -1
  74. package/lib/commonjs/ui/context/useOxyAccountGraph.js +13 -5
  75. package/lib/commonjs/ui/context/useOxyAccountGraph.js.map +1 -1
  76. package/lib/commonjs/ui/hooks/useSwitchableAccounts.js +6 -1
  77. package/lib/commonjs/ui/hooks/useSwitchableAccounts.js.map +1 -1
  78. package/lib/commonjs/ui/index.js +0 -13
  79. package/lib/commonjs/ui/index.js.map +1 -1
  80. package/lib/commonjs/ui/oauth/browserAuthTransport.js +168 -0
  81. package/lib/commonjs/ui/oauth/browserAuthTransport.js.map +1 -0
  82. package/lib/commonjs/ui/oauth/completeOAuthCode.js +78 -0
  83. package/lib/commonjs/ui/oauth/completeOAuthCode.js.map +1 -0
  84. package/lib/commonjs/ui/oauth/legacyRedirectLanes.js +48 -0
  85. package/lib/commonjs/ui/oauth/legacyRedirectLanes.js.map +1 -0
  86. package/lib/commonjs/ui/oauth/oauthHandshake.js +53 -0
  87. package/lib/commonjs/ui/oauth/oauthHandshake.js.map +1 -0
  88. package/lib/commonjs/ui/oauth/oauthPopup.js +229 -0
  89. package/lib/commonjs/ui/oauth/oauthPopup.js.map +1 -0
  90. package/lib/commonjs/ui/oauth/oauthPopupMessages.js +141 -0
  91. package/lib/commonjs/ui/oauth/oauthPopupMessages.js.map +1 -0
  92. package/lib/commonjs/ui/oauth/types.js +2 -0
  93. package/lib/commonjs/ui/oauth/types.js.map +1 -0
  94. package/lib/commonjs/ui/screens/AccountMembersScreen.js +4 -3
  95. package/lib/commonjs/ui/screens/AccountMembersScreen.js.map +1 -1
  96. package/lib/commonjs/ui/screens/CreateAccountScreen.js +7 -6
  97. package/lib/commonjs/ui/screens/CreateAccountScreen.js.map +1 -1
  98. package/lib/commonjs/ui/screens/EditProfileFieldScreen.js +4 -3
  99. package/lib/commonjs/ui/screens/EditProfileFieldScreen.js.map +1 -1
  100. package/lib/commonjs/ui/screens/FAQScreen.js +3 -2
  101. package/lib/commonjs/ui/screens/FAQScreen.js.map +1 -1
  102. package/lib/commonjs/ui/screens/FeedbackScreen.js +11 -10
  103. package/lib/commonjs/ui/screens/FeedbackScreen.js.map +1 -1
  104. package/lib/commonjs/ui/screens/FileManagementScreen.js +19 -18
  105. package/lib/commonjs/ui/screens/FileManagementScreen.js.map +1 -1
  106. package/lib/commonjs/ui/screens/LanguageSelectorScreen.js +4 -3
  107. package/lib/commonjs/ui/screens/LanguageSelectorScreen.js.map +1 -1
  108. package/lib/commonjs/ui/screens/ManageAccountScreen.js +2 -2
  109. package/lib/commonjs/ui/screens/ManageAccountScreen.js.map +1 -1
  110. package/lib/commonjs/ui/screens/PaymentGatewayScreen.js +3 -3
  111. package/lib/commonjs/ui/screens/PaymentGatewayScreen.js.map +1 -1
  112. package/lib/commonjs/ui/screens/PremiumSubscriptionScreen.js +9 -8
  113. package/lib/commonjs/ui/screens/PremiumSubscriptionScreen.js.map +1 -1
  114. package/lib/commonjs/ui/screens/ProfileScreen.js +10 -10
  115. package/lib/commonjs/ui/screens/ProfileScreen.js.map +1 -1
  116. package/lib/commonjs/ui/screens/UserListScreen.js +3 -3
  117. package/lib/commonjs/ui/screens/UserListScreen.js.map +1 -1
  118. package/lib/commonjs/ui/screens/WelcomeNewUserScreen.js +3 -2
  119. package/lib/commonjs/ui/screens/WelcomeNewUserScreen.js.map +1 -1
  120. package/lib/commonjs/ui/screens/fileManagement/FileLibraryError.js +4 -3
  121. package/lib/commonjs/ui/screens/fileManagement/FileLibraryError.js.map +1 -1
  122. package/lib/commonjs/ui/screens/fileManagement/FileListSection.js +4 -3
  123. package/lib/commonjs/ui/screens/fileManagement/FileListSection.js.map +1 -1
  124. package/lib/commonjs/ui/screens/fileManagement/PhotoPickerSection.js +4 -3
  125. package/lib/commonjs/ui/screens/fileManagement/PhotoPickerSection.js.map +1 -1
  126. package/lib/commonjs/ui/screens/fileManagement/UploadBar.js +3 -2
  127. package/lib/commonjs/ui/screens/fileManagement/UploadBar.js.map +1 -1
  128. package/lib/commonjs/ui/screens/trust/TrustCenterScreen.js +3 -2
  129. package/lib/commonjs/ui/screens/trust/TrustCenterScreen.js.map +1 -1
  130. package/lib/commonjs/ui/screens/trust/TrustLeaderboardScreen.js +4 -3
  131. package/lib/commonjs/ui/screens/trust/TrustLeaderboardScreen.js.map +1 -1
  132. package/lib/commonjs/ui/screens/trust/TrustRewardsScreen.js +4 -3
  133. package/lib/commonjs/ui/screens/trust/TrustRewardsScreen.js.map +1 -1
  134. package/lib/commonjs/ui/server.js +2 -5
  135. package/lib/commonjs/ui/server.js.map +1 -1
  136. package/lib/commonjs/ui/session/authStore.js +6 -75
  137. package/lib/commonjs/ui/session/authStore.js.map +1 -1
  138. package/lib/commonjs/ui/session/createSessionClient.js +11 -3
  139. package/lib/commonjs/ui/session/createSessionClient.js.map +1 -1
  140. package/lib/commonjs/ui/session/identityBinding.js +95 -0
  141. package/lib/commonjs/ui/session/identityBinding.js.map +1 -0
  142. package/lib/commonjs/ui/session/index.js +13 -0
  143. package/lib/commonjs/ui/session/index.js.map +1 -1
  144. package/lib/commonjs/ui/session/nativeSecureStorage.js +90 -0
  145. package/lib/commonjs/ui/session/nativeSecureStorage.js.map +1 -0
  146. package/lib/commonjs/ui/session/tokenTransport.js +11 -1
  147. package/lib/commonjs/ui/session/tokenTransport.js.map +1 -1
  148. package/lib/commonjs/ui/utils/crossOriginRestore.js +3 -2
  149. package/lib/commonjs/ui/utils/crossOriginRestore.js.map +1 -1
  150. package/lib/commonjs/ui/utils/deliveryPlatform.js +58 -0
  151. package/lib/commonjs/ui/utils/deliveryPlatform.js.map +1 -0
  152. package/lib/commonjs/ui/utils/oauthReturn.js +70 -46
  153. package/lib/commonjs/ui/utils/oauthReturn.js.map +1 -1
  154. package/lib/module/index.js +27 -4
  155. package/lib/module/index.js.map +1 -1
  156. package/lib/module/notifications/deviceNotifications.js +371 -0
  157. package/lib/module/notifications/deviceNotifications.js.map +1 -0
  158. package/lib/module/ui/boot/runProviderColdBoot.js +51 -9
  159. package/lib/module/ui/boot/runProviderColdBoot.js.map +1 -1
  160. package/lib/module/ui/client.js +0 -1
  161. package/lib/module/ui/client.js.map +1 -1
  162. package/lib/module/ui/components/AvatarCameraBadge.js +1 -1
  163. package/lib/module/ui/components/AvatarCameraBadge.js.map +1 -1
  164. package/lib/module/ui/components/OxyAccountDialogScreen.js +14 -3
  165. package/lib/module/ui/components/OxyAccountDialogScreen.js.map +1 -1
  166. package/lib/module/ui/components/OxyAuthChooser.js +74 -1126
  167. package/lib/module/ui/components/OxyAuthChooser.js.map +1 -1
  168. package/lib/module/ui/components/OxyConsentScreen.js +50 -12
  169. package/lib/module/ui/components/OxyConsentScreen.js.map +1 -1
  170. package/lib/module/ui/components/OxyProvider.js +4 -4
  171. package/lib/module/ui/components/OxyProvider.js.map +1 -1
  172. package/lib/module/ui/components/OxySignInButton.js +76 -42
  173. package/lib/module/ui/components/OxySignInButton.js.map +1 -1
  174. package/lib/module/ui/components/OxySignInRequestSurface.js +141 -0
  175. package/lib/module/ui/components/OxySignInRequestSurface.js.map +1 -0
  176. package/lib/module/ui/components/ProfileButton.js +1 -1
  177. package/lib/module/ui/components/ProfileButton.js.map +1 -1
  178. package/lib/module/ui/components/SettingsIcon.js +1 -1
  179. package/lib/module/ui/components/SettingsIcon.js.map +1 -1
  180. package/lib/module/ui/components/authChooser/AccountsMenuView.js +523 -0
  181. package/lib/module/ui/components/authChooser/AccountsMenuView.js.map +1 -0
  182. package/lib/module/ui/components/authChooser/SignInEntryView.js +85 -0
  183. package/lib/module/ui/components/authChooser/SignInEntryView.js.map +1 -0
  184. package/lib/module/ui/components/authChooser/SignInRequestView.js +101 -0
  185. package/lib/module/ui/components/authChooser/SignInRequestView.js.map +1 -0
  186. package/lib/module/ui/components/authChooser/SignUpView.js +184 -0
  187. package/lib/module/ui/components/authChooser/SignUpView.js.map +1 -0
  188. package/lib/module/ui/components/authChooser/TroubleDisclosure.js +57 -0
  189. package/lib/module/ui/components/authChooser/TroubleDisclosure.js.map +1 -0
  190. package/lib/module/ui/components/authChooser/primitives.js +163 -0
  191. package/lib/module/ui/components/authChooser/primitives.js.map +1 -0
  192. package/lib/module/ui/components/authChooser/requestSurfaces.js +143 -0
  193. package/lib/module/ui/components/authChooser/requestSurfaces.js.map +1 -0
  194. package/lib/module/ui/components/authChooser/signInProgress.js +50 -0
  195. package/lib/module/ui/components/authChooser/signInProgress.js.map +1 -0
  196. package/lib/module/ui/components/{oxyAuthChooserStyles.js → authChooser/styles.js} +19 -1
  197. package/lib/module/ui/components/authChooser/styles.js.map +1 -0
  198. package/lib/module/ui/components/authChooser/types.js +66 -0
  199. package/lib/module/ui/components/authChooser/types.js.map +1 -0
  200. package/lib/module/ui/components/authChooser/useUsernameAvailability.js +46 -0
  201. package/lib/module/ui/components/authChooser/useUsernameAvailability.js.map +1 -0
  202. package/lib/module/ui/components/fileManagement/AnimatedButton.js +1 -1
  203. package/lib/module/ui/components/fileManagement/AnimatedButton.js.map +1 -1
  204. package/lib/module/ui/components/fileManagement/FileDetailsModal.js +1 -1
  205. package/lib/module/ui/components/fileManagement/FileDetailsModal.js.map +1 -1
  206. package/lib/module/ui/components/fileManagement/FileViewer.js +1 -1
  207. package/lib/module/ui/components/fileManagement/FileViewer.js.map +1 -1
  208. package/lib/module/ui/components/fileManagement/UploadPreview.js +1 -1
  209. package/lib/module/ui/components/fileManagement/UploadPreview.js.map +1 -1
  210. package/lib/module/ui/components/modals/DeleteAccountModal.js +1 -1
  211. package/lib/module/ui/components/modals/DeleteAccountModal.js.map +1 -1
  212. package/lib/module/ui/components/payment/PaymentDetailsStep.js +1 -1
  213. package/lib/module/ui/components/payment/PaymentDetailsStep.js.map +1 -1
  214. package/lib/module/ui/components/payment/PaymentMethodStep.js +1 -1
  215. package/lib/module/ui/components/payment/PaymentMethodStep.js.map +1 -1
  216. package/lib/module/ui/components/payment/PaymentReviewStep.js +1 -1
  217. package/lib/module/ui/components/payment/PaymentReviewStep.js.map +1 -1
  218. package/lib/module/ui/components/payment/PaymentSuccessStep.js +1 -1
  219. package/lib/module/ui/components/payment/PaymentSuccessStep.js.map +1 -1
  220. package/lib/module/ui/components/payment/PaymentSummaryStep.js +1 -1
  221. package/lib/module/ui/components/payment/PaymentSummaryStep.js.map +1 -1
  222. package/lib/module/ui/context/OxyContext.js +203 -32
  223. package/lib/module/ui/context/OxyContext.js.map +1 -1
  224. package/lib/module/ui/context/commitSessionFlow.js +42 -0
  225. package/lib/module/ui/context/commitSessionFlow.js.map +1 -1
  226. package/lib/module/ui/context/useOxyAccountGraph.js +13 -5
  227. package/lib/module/ui/context/useOxyAccountGraph.js.map +1 -1
  228. package/lib/module/ui/hooks/useSwitchableAccounts.js +6 -1
  229. package/lib/module/ui/hooks/useSwitchableAccounts.js.map +1 -1
  230. package/lib/module/ui/index.js +0 -1
  231. package/lib/module/ui/index.js.map +1 -1
  232. package/lib/module/ui/oauth/browserAuthTransport.js +165 -0
  233. package/lib/module/ui/oauth/browserAuthTransport.js.map +1 -0
  234. package/lib/module/ui/oauth/completeOAuthCode.js +75 -0
  235. package/lib/module/ui/oauth/completeOAuthCode.js.map +1 -0
  236. package/lib/module/ui/oauth/legacyRedirectLanes.js +44 -0
  237. package/lib/module/ui/oauth/legacyRedirectLanes.js.map +1 -0
  238. package/lib/module/ui/oauth/oauthHandshake.js +50 -0
  239. package/lib/module/ui/oauth/oauthHandshake.js.map +1 -0
  240. package/lib/module/ui/oauth/oauthPopup.js +221 -0
  241. package/lib/module/ui/oauth/oauthPopup.js.map +1 -0
  242. package/lib/module/ui/oauth/oauthPopupMessages.js +135 -0
  243. package/lib/module/ui/oauth/oauthPopupMessages.js.map +1 -0
  244. package/lib/module/ui/oauth/types.js +2 -0
  245. package/lib/module/ui/oauth/types.js.map +1 -0
  246. package/lib/module/ui/screens/AccountMembersScreen.js +1 -1
  247. package/lib/module/ui/screens/AccountMembersScreen.js.map +1 -1
  248. package/lib/module/ui/screens/CreateAccountScreen.js +1 -1
  249. package/lib/module/ui/screens/CreateAccountScreen.js.map +1 -1
  250. package/lib/module/ui/screens/EditProfileFieldScreen.js +1 -1
  251. package/lib/module/ui/screens/EditProfileFieldScreen.js.map +1 -1
  252. package/lib/module/ui/screens/FAQScreen.js +1 -1
  253. package/lib/module/ui/screens/FAQScreen.js.map +1 -1
  254. package/lib/module/ui/screens/FeedbackScreen.js +1 -1
  255. package/lib/module/ui/screens/FeedbackScreen.js.map +1 -1
  256. package/lib/module/ui/screens/FileManagementScreen.js +2 -1
  257. package/lib/module/ui/screens/FileManagementScreen.js.map +1 -1
  258. package/lib/module/ui/screens/LanguageSelectorScreen.js +1 -1
  259. package/lib/module/ui/screens/LanguageSelectorScreen.js.map +1 -1
  260. package/lib/module/ui/screens/ManageAccountScreen.js +1 -1
  261. package/lib/module/ui/screens/ManageAccountScreen.js.map +1 -1
  262. package/lib/module/ui/screens/PaymentGatewayScreen.js +1 -1
  263. package/lib/module/ui/screens/PaymentGatewayScreen.js.map +1 -1
  264. package/lib/module/ui/screens/PremiumSubscriptionScreen.js +1 -1
  265. package/lib/module/ui/screens/PremiumSubscriptionScreen.js.map +1 -1
  266. package/lib/module/ui/screens/ProfileScreen.js +1 -1
  267. package/lib/module/ui/screens/ProfileScreen.js.map +1 -1
  268. package/lib/module/ui/screens/UserListScreen.js +1 -1
  269. package/lib/module/ui/screens/UserListScreen.js.map +1 -1
  270. package/lib/module/ui/screens/WelcomeNewUserScreen.js +1 -1
  271. package/lib/module/ui/screens/WelcomeNewUserScreen.js.map +1 -1
  272. package/lib/module/ui/screens/fileManagement/FileLibraryError.js +1 -1
  273. package/lib/module/ui/screens/fileManagement/FileLibraryError.js.map +1 -1
  274. package/lib/module/ui/screens/fileManagement/FileListSection.js +1 -1
  275. package/lib/module/ui/screens/fileManagement/FileListSection.js.map +1 -1
  276. package/lib/module/ui/screens/fileManagement/PhotoPickerSection.js +2 -1
  277. package/lib/module/ui/screens/fileManagement/PhotoPickerSection.js.map +1 -1
  278. package/lib/module/ui/screens/fileManagement/UploadBar.js +1 -1
  279. package/lib/module/ui/screens/fileManagement/UploadBar.js.map +1 -1
  280. package/lib/module/ui/screens/trust/TrustCenterScreen.js +1 -1
  281. package/lib/module/ui/screens/trust/TrustCenterScreen.js.map +1 -1
  282. package/lib/module/ui/screens/trust/TrustLeaderboardScreen.js +1 -1
  283. package/lib/module/ui/screens/trust/TrustLeaderboardScreen.js.map +1 -1
  284. package/lib/module/ui/screens/trust/TrustRewardsScreen.js +1 -1
  285. package/lib/module/ui/screens/trust/TrustRewardsScreen.js.map +1 -1
  286. package/lib/module/ui/server.js +0 -2
  287. package/lib/module/ui/server.js.map +1 -1
  288. package/lib/module/ui/session/authStore.js +5 -75
  289. package/lib/module/ui/session/authStore.js.map +1 -1
  290. package/lib/module/ui/session/createSessionClient.js +11 -3
  291. package/lib/module/ui/session/createSessionClient.js.map +1 -1
  292. package/lib/module/ui/session/identityBinding.js +89 -0
  293. package/lib/module/ui/session/identityBinding.js.map +1 -0
  294. package/lib/module/ui/session/index.js +5 -2
  295. package/lib/module/ui/session/index.js.map +1 -1
  296. package/lib/module/ui/session/nativeSecureStorage.js +88 -0
  297. package/lib/module/ui/session/nativeSecureStorage.js.map +1 -0
  298. package/lib/module/ui/session/tokenTransport.js +11 -1
  299. package/lib/module/ui/session/tokenTransport.js.map +1 -1
  300. package/lib/module/ui/utils/crossOriginRestore.js +4 -3
  301. package/lib/module/ui/utils/crossOriginRestore.js.map +1 -1
  302. package/lib/module/ui/utils/deliveryPlatform.js +55 -0
  303. package/lib/module/ui/utils/deliveryPlatform.js.map +1 -0
  304. package/lib/module/ui/utils/oauthReturn.js +70 -46
  305. package/lib/module/ui/utils/oauthReturn.js.map +1 -1
  306. package/lib/typescript/commonjs/index.d.ts +9 -1
  307. package/lib/typescript/commonjs/index.d.ts.map +1 -1
  308. package/lib/typescript/commonjs/notifications/deviceNotifications.d.ts +141 -0
  309. package/lib/typescript/commonjs/notifications/deviceNotifications.d.ts.map +1 -0
  310. package/lib/typescript/commonjs/ui/boot/runProviderColdBoot.d.ts +34 -2
  311. package/lib/typescript/commonjs/ui/boot/runProviderColdBoot.d.ts.map +1 -1
  312. package/lib/typescript/commonjs/ui/client.d.ts +0 -1
  313. package/lib/typescript/commonjs/ui/client.d.ts.map +1 -1
  314. package/lib/typescript/commonjs/ui/components/OxyAccountDialogScreen.d.ts.map +1 -1
  315. package/lib/typescript/commonjs/ui/components/OxyAuthChooser.d.ts +16 -29
  316. package/lib/typescript/commonjs/ui/components/OxyAuthChooser.d.ts.map +1 -1
  317. package/lib/typescript/commonjs/ui/components/OxyConsentScreen.d.ts.map +1 -1
  318. package/lib/typescript/commonjs/ui/components/OxyProvider.d.ts.map +1 -1
  319. package/lib/typescript/commonjs/ui/components/OxySignInButton.d.ts +17 -12
  320. package/lib/typescript/commonjs/ui/components/OxySignInButton.d.ts.map +1 -1
  321. package/lib/typescript/commonjs/ui/components/OxySignInRequestSurface.d.ts +108 -0
  322. package/lib/typescript/commonjs/ui/components/OxySignInRequestSurface.d.ts.map +1 -0
  323. package/lib/typescript/commonjs/ui/components/SettingsIcon.d.ts +1 -1
  324. package/lib/typescript/commonjs/ui/components/SettingsIcon.d.ts.map +1 -1
  325. package/lib/typescript/commonjs/ui/components/authChooser/AccountsMenuView.d.ts +38 -0
  326. package/lib/typescript/commonjs/ui/components/authChooser/AccountsMenuView.d.ts.map +1 -0
  327. package/lib/typescript/commonjs/ui/components/authChooser/SignInEntryView.d.ts +32 -0
  328. package/lib/typescript/commonjs/ui/components/authChooser/SignInEntryView.d.ts.map +1 -0
  329. package/lib/typescript/commonjs/ui/components/authChooser/SignInRequestView.d.ts +34 -0
  330. package/lib/typescript/commonjs/ui/components/authChooser/SignInRequestView.d.ts.map +1 -0
  331. package/lib/typescript/commonjs/ui/components/authChooser/SignUpView.d.ts +34 -0
  332. package/lib/typescript/commonjs/ui/components/authChooser/SignUpView.d.ts.map +1 -0
  333. package/lib/typescript/commonjs/ui/components/authChooser/TroubleDisclosure.d.ts +36 -0
  334. package/lib/typescript/commonjs/ui/components/authChooser/TroubleDisclosure.d.ts.map +1 -0
  335. package/lib/typescript/commonjs/ui/components/authChooser/primitives.d.ts +55 -0
  336. package/lib/typescript/commonjs/ui/components/authChooser/primitives.d.ts.map +1 -0
  337. package/lib/typescript/commonjs/ui/components/authChooser/requestSurfaces.d.ts +58 -0
  338. package/lib/typescript/commonjs/ui/components/authChooser/requestSurfaces.d.ts.map +1 -0
  339. package/lib/typescript/commonjs/ui/components/authChooser/signInProgress.d.ts +26 -0
  340. package/lib/typescript/commonjs/ui/components/authChooser/signInProgress.d.ts.map +1 -0
  341. package/lib/typescript/{module/ui/components/oxyAuthChooserStyles.d.ts → commonjs/ui/components/authChooser/styles.d.ts} +19 -1
  342. package/lib/typescript/commonjs/ui/components/authChooser/styles.d.ts.map +1 -0
  343. package/lib/typescript/commonjs/ui/components/authChooser/types.d.ts +103 -0
  344. package/lib/typescript/commonjs/ui/components/authChooser/types.d.ts.map +1 -0
  345. package/lib/typescript/commonjs/ui/components/authChooser/useUsernameAvailability.d.ts +16 -0
  346. package/lib/typescript/commonjs/ui/components/authChooser/useUsernameAvailability.d.ts.map +1 -0
  347. package/lib/typescript/commonjs/ui/components/payment/types.d.ts +1 -1
  348. package/lib/typescript/commonjs/ui/components/payment/types.d.ts.map +1 -1
  349. package/lib/typescript/commonjs/ui/context/OxyContext.d.ts.map +1 -1
  350. package/lib/typescript/commonjs/ui/context/commitSessionFlow.d.ts +40 -0
  351. package/lib/typescript/commonjs/ui/context/commitSessionFlow.d.ts.map +1 -1
  352. package/lib/typescript/commonjs/ui/context/oxyContextTypes.d.ts +44 -1
  353. package/lib/typescript/commonjs/ui/context/oxyContextTypes.d.ts.map +1 -1
  354. package/lib/typescript/commonjs/ui/context/useOxyAccountGraph.d.ts +7 -1
  355. package/lib/typescript/commonjs/ui/context/useOxyAccountGraph.d.ts.map +1 -1
  356. package/lib/typescript/commonjs/ui/hooks/useSwitchableAccounts.d.ts.map +1 -1
  357. package/lib/typescript/commonjs/ui/index.d.ts +0 -1
  358. package/lib/typescript/commonjs/ui/index.d.ts.map +1 -1
  359. package/lib/typescript/commonjs/ui/oauth/browserAuthTransport.d.ts +56 -0
  360. package/lib/typescript/commonjs/ui/oauth/browserAuthTransport.d.ts.map +1 -0
  361. package/lib/typescript/commonjs/ui/oauth/completeOAuthCode.d.ts +49 -0
  362. package/lib/typescript/commonjs/ui/oauth/completeOAuthCode.d.ts.map +1 -0
  363. package/lib/typescript/commonjs/ui/oauth/legacyRedirectLanes.d.ts +40 -0
  364. package/lib/typescript/commonjs/ui/oauth/legacyRedirectLanes.d.ts.map +1 -0
  365. package/lib/typescript/commonjs/ui/oauth/oauthHandshake.d.ts +50 -0
  366. package/lib/typescript/commonjs/ui/oauth/oauthHandshake.d.ts.map +1 -0
  367. package/lib/typescript/commonjs/ui/oauth/oauthPopup.d.ts +77 -0
  368. package/lib/typescript/commonjs/ui/oauth/oauthPopup.d.ts.map +1 -0
  369. package/lib/typescript/commonjs/ui/oauth/oauthPopupMessages.d.ts +67 -0
  370. package/lib/typescript/commonjs/ui/oauth/oauthPopupMessages.d.ts.map +1 -0
  371. package/lib/typescript/commonjs/ui/oauth/types.d.ts +176 -0
  372. package/lib/typescript/commonjs/ui/oauth/types.d.ts.map +1 -0
  373. package/lib/typescript/commonjs/ui/screens/FeedbackScreen.d.ts.map +1 -1
  374. package/lib/typescript/commonjs/ui/screens/FileManagementScreen.d.ts.map +1 -1
  375. package/lib/typescript/commonjs/ui/screens/fileManagement/PhotoPickerSection.d.ts.map +1 -1
  376. package/lib/typescript/commonjs/ui/server.d.ts +0 -2
  377. package/lib/typescript/commonjs/ui/server.d.ts.map +1 -1
  378. package/lib/typescript/commonjs/ui/session/authStore.d.ts +3 -7
  379. package/lib/typescript/commonjs/ui/session/authStore.d.ts.map +1 -1
  380. package/lib/typescript/commonjs/ui/session/createSessionClient.d.ts +8 -1
  381. package/lib/typescript/commonjs/ui/session/createSessionClient.d.ts.map +1 -1
  382. package/lib/typescript/commonjs/ui/session/identityBinding.d.ts +66 -0
  383. package/lib/typescript/commonjs/ui/session/identityBinding.d.ts.map +1 -0
  384. package/lib/typescript/commonjs/ui/session/index.d.ts +6 -2
  385. package/lib/typescript/commonjs/ui/session/index.d.ts.map +1 -1
  386. package/lib/typescript/commonjs/ui/session/nativeSecureStorage.d.ts +25 -0
  387. package/lib/typescript/commonjs/ui/session/nativeSecureStorage.d.ts.map +1 -0
  388. package/lib/typescript/commonjs/ui/session/tokenTransport.d.ts +8 -1
  389. package/lib/typescript/commonjs/ui/session/tokenTransport.d.ts.map +1 -1
  390. package/lib/typescript/commonjs/ui/types/navigation.d.ts +44 -0
  391. package/lib/typescript/commonjs/ui/types/navigation.d.ts.map +1 -1
  392. package/lib/typescript/commonjs/ui/utils/crossOriginRestore.d.ts.map +1 -1
  393. package/lib/typescript/commonjs/ui/utils/deliveryPlatform.d.ts +33 -0
  394. package/lib/typescript/commonjs/ui/utils/deliveryPlatform.d.ts.map +1 -0
  395. package/lib/typescript/commonjs/ui/utils/fileManagement.d.ts +1 -1
  396. package/lib/typescript/commonjs/ui/utils/fileManagement.d.ts.map +1 -1
  397. package/lib/typescript/commonjs/ui/utils/oauthReturn.d.ts +30 -16
  398. package/lib/typescript/commonjs/ui/utils/oauthReturn.d.ts.map +1 -1
  399. package/lib/typescript/module/index.d.ts +9 -1
  400. package/lib/typescript/module/index.d.ts.map +1 -1
  401. package/lib/typescript/module/notifications/deviceNotifications.d.ts +141 -0
  402. package/lib/typescript/module/notifications/deviceNotifications.d.ts.map +1 -0
  403. package/lib/typescript/module/ui/boot/runProviderColdBoot.d.ts +34 -2
  404. package/lib/typescript/module/ui/boot/runProviderColdBoot.d.ts.map +1 -1
  405. package/lib/typescript/module/ui/client.d.ts +0 -1
  406. package/lib/typescript/module/ui/client.d.ts.map +1 -1
  407. package/lib/typescript/module/ui/components/OxyAccountDialogScreen.d.ts.map +1 -1
  408. package/lib/typescript/module/ui/components/OxyAuthChooser.d.ts +16 -29
  409. package/lib/typescript/module/ui/components/OxyAuthChooser.d.ts.map +1 -1
  410. package/lib/typescript/module/ui/components/OxyConsentScreen.d.ts.map +1 -1
  411. package/lib/typescript/module/ui/components/OxyProvider.d.ts.map +1 -1
  412. package/lib/typescript/module/ui/components/OxySignInButton.d.ts +17 -12
  413. package/lib/typescript/module/ui/components/OxySignInButton.d.ts.map +1 -1
  414. package/lib/typescript/module/ui/components/OxySignInRequestSurface.d.ts +108 -0
  415. package/lib/typescript/module/ui/components/OxySignInRequestSurface.d.ts.map +1 -0
  416. package/lib/typescript/module/ui/components/SettingsIcon.d.ts +1 -1
  417. package/lib/typescript/module/ui/components/SettingsIcon.d.ts.map +1 -1
  418. package/lib/typescript/module/ui/components/authChooser/AccountsMenuView.d.ts +38 -0
  419. package/lib/typescript/module/ui/components/authChooser/AccountsMenuView.d.ts.map +1 -0
  420. package/lib/typescript/module/ui/components/authChooser/SignInEntryView.d.ts +32 -0
  421. package/lib/typescript/module/ui/components/authChooser/SignInEntryView.d.ts.map +1 -0
  422. package/lib/typescript/module/ui/components/authChooser/SignInRequestView.d.ts +34 -0
  423. package/lib/typescript/module/ui/components/authChooser/SignInRequestView.d.ts.map +1 -0
  424. package/lib/typescript/module/ui/components/authChooser/SignUpView.d.ts +34 -0
  425. package/lib/typescript/module/ui/components/authChooser/SignUpView.d.ts.map +1 -0
  426. package/lib/typescript/module/ui/components/authChooser/TroubleDisclosure.d.ts +36 -0
  427. package/lib/typescript/module/ui/components/authChooser/TroubleDisclosure.d.ts.map +1 -0
  428. package/lib/typescript/module/ui/components/authChooser/primitives.d.ts +55 -0
  429. package/lib/typescript/module/ui/components/authChooser/primitives.d.ts.map +1 -0
  430. package/lib/typescript/module/ui/components/authChooser/requestSurfaces.d.ts +58 -0
  431. package/lib/typescript/module/ui/components/authChooser/requestSurfaces.d.ts.map +1 -0
  432. package/lib/typescript/module/ui/components/authChooser/signInProgress.d.ts +26 -0
  433. package/lib/typescript/module/ui/components/authChooser/signInProgress.d.ts.map +1 -0
  434. package/lib/typescript/{commonjs/ui/components/oxyAuthChooserStyles.d.ts → module/ui/components/authChooser/styles.d.ts} +19 -1
  435. package/lib/typescript/module/ui/components/authChooser/styles.d.ts.map +1 -0
  436. package/lib/typescript/module/ui/components/authChooser/types.d.ts +103 -0
  437. package/lib/typescript/module/ui/components/authChooser/types.d.ts.map +1 -0
  438. package/lib/typescript/module/ui/components/authChooser/useUsernameAvailability.d.ts +16 -0
  439. package/lib/typescript/module/ui/components/authChooser/useUsernameAvailability.d.ts.map +1 -0
  440. package/lib/typescript/module/ui/components/payment/types.d.ts +1 -1
  441. package/lib/typescript/module/ui/components/payment/types.d.ts.map +1 -1
  442. package/lib/typescript/module/ui/context/OxyContext.d.ts.map +1 -1
  443. package/lib/typescript/module/ui/context/commitSessionFlow.d.ts +40 -0
  444. package/lib/typescript/module/ui/context/commitSessionFlow.d.ts.map +1 -1
  445. package/lib/typescript/module/ui/context/oxyContextTypes.d.ts +44 -1
  446. package/lib/typescript/module/ui/context/oxyContextTypes.d.ts.map +1 -1
  447. package/lib/typescript/module/ui/context/useOxyAccountGraph.d.ts +7 -1
  448. package/lib/typescript/module/ui/context/useOxyAccountGraph.d.ts.map +1 -1
  449. package/lib/typescript/module/ui/hooks/useSwitchableAccounts.d.ts.map +1 -1
  450. package/lib/typescript/module/ui/index.d.ts +0 -1
  451. package/lib/typescript/module/ui/index.d.ts.map +1 -1
  452. package/lib/typescript/module/ui/oauth/browserAuthTransport.d.ts +56 -0
  453. package/lib/typescript/module/ui/oauth/browserAuthTransport.d.ts.map +1 -0
  454. package/lib/typescript/module/ui/oauth/completeOAuthCode.d.ts +49 -0
  455. package/lib/typescript/module/ui/oauth/completeOAuthCode.d.ts.map +1 -0
  456. package/lib/typescript/module/ui/oauth/legacyRedirectLanes.d.ts +40 -0
  457. package/lib/typescript/module/ui/oauth/legacyRedirectLanes.d.ts.map +1 -0
  458. package/lib/typescript/module/ui/oauth/oauthHandshake.d.ts +50 -0
  459. package/lib/typescript/module/ui/oauth/oauthHandshake.d.ts.map +1 -0
  460. package/lib/typescript/module/ui/oauth/oauthPopup.d.ts +77 -0
  461. package/lib/typescript/module/ui/oauth/oauthPopup.d.ts.map +1 -0
  462. package/lib/typescript/module/ui/oauth/oauthPopupMessages.d.ts +67 -0
  463. package/lib/typescript/module/ui/oauth/oauthPopupMessages.d.ts.map +1 -0
  464. package/lib/typescript/module/ui/oauth/types.d.ts +176 -0
  465. package/lib/typescript/module/ui/oauth/types.d.ts.map +1 -0
  466. package/lib/typescript/module/ui/screens/FeedbackScreen.d.ts.map +1 -1
  467. package/lib/typescript/module/ui/screens/FileManagementScreen.d.ts.map +1 -1
  468. package/lib/typescript/module/ui/screens/fileManagement/PhotoPickerSection.d.ts.map +1 -1
  469. package/lib/typescript/module/ui/server.d.ts +0 -2
  470. package/lib/typescript/module/ui/server.d.ts.map +1 -1
  471. package/lib/typescript/module/ui/session/authStore.d.ts +3 -7
  472. package/lib/typescript/module/ui/session/authStore.d.ts.map +1 -1
  473. package/lib/typescript/module/ui/session/createSessionClient.d.ts +8 -1
  474. package/lib/typescript/module/ui/session/createSessionClient.d.ts.map +1 -1
  475. package/lib/typescript/module/ui/session/identityBinding.d.ts +66 -0
  476. package/lib/typescript/module/ui/session/identityBinding.d.ts.map +1 -0
  477. package/lib/typescript/module/ui/session/index.d.ts +6 -2
  478. package/lib/typescript/module/ui/session/index.d.ts.map +1 -1
  479. package/lib/typescript/module/ui/session/nativeSecureStorage.d.ts +25 -0
  480. package/lib/typescript/module/ui/session/nativeSecureStorage.d.ts.map +1 -0
  481. package/lib/typescript/module/ui/session/tokenTransport.d.ts +8 -1
  482. package/lib/typescript/module/ui/session/tokenTransport.d.ts.map +1 -1
  483. package/lib/typescript/module/ui/types/navigation.d.ts +44 -0
  484. package/lib/typescript/module/ui/types/navigation.d.ts.map +1 -1
  485. package/lib/typescript/module/ui/utils/crossOriginRestore.d.ts.map +1 -1
  486. package/lib/typescript/module/ui/utils/deliveryPlatform.d.ts +33 -0
  487. package/lib/typescript/module/ui/utils/deliveryPlatform.d.ts.map +1 -0
  488. package/lib/typescript/module/ui/utils/fileManagement.d.ts +1 -1
  489. package/lib/typescript/module/ui/utils/fileManagement.d.ts.map +1 -1
  490. package/lib/typescript/module/ui/utils/oauthReturn.d.ts +30 -16
  491. package/lib/typescript/module/ui/utils/oauthReturn.d.ts.map +1 -1
  492. package/package.json +15 -7
  493. package/src/index.ts +50 -5
  494. package/src/notifications/deviceNotifications.ts +395 -0
  495. package/src/ui/boot/__tests__/coldBootWebAuthMode.test.ts +281 -0
  496. package/src/ui/boot/runProviderColdBoot.ts +83 -13
  497. package/src/ui/client.ts +0 -1
  498. package/src/ui/components/AvatarCameraBadge.tsx +1 -1
  499. package/src/ui/components/OxyAccountDialogScreen.tsx +20 -3
  500. package/src/ui/components/OxyAuthChooser.tsx +91 -1230
  501. package/src/ui/components/OxyConsentScreen.tsx +56 -13
  502. package/src/ui/components/OxyProvider.tsx +4 -4
  503. package/src/ui/components/OxySignInButton.tsx +119 -78
  504. package/src/ui/components/OxySignInRequestSurface.tsx +202 -0
  505. package/src/ui/components/ProfileButton.tsx +1 -1
  506. package/src/ui/components/SettingsIcon.tsx +1 -1
  507. package/src/ui/components/__tests__/OxyConsentScreen.test.tsx +27 -0
  508. package/src/ui/components/authChooser/AccountsMenuView.tsx +569 -0
  509. package/src/ui/components/authChooser/SignInEntryView.tsx +121 -0
  510. package/src/ui/components/authChooser/SignInRequestView.tsx +130 -0
  511. package/src/ui/components/authChooser/SignUpView.tsx +174 -0
  512. package/src/ui/components/authChooser/TroubleDisclosure.tsx +73 -0
  513. package/src/ui/components/authChooser/primitives.tsx +144 -0
  514. package/src/ui/components/authChooser/requestSurfaces.tsx +120 -0
  515. package/src/ui/components/authChooser/signInProgress.ts +54 -0
  516. package/src/ui/components/{oxyAuthChooserStyles.ts → authChooser/styles.ts} +18 -0
  517. package/src/ui/components/authChooser/types.ts +120 -0
  518. package/src/ui/components/authChooser/useUsernameAvailability.ts +60 -0
  519. package/src/ui/components/fileManagement/AnimatedButton.tsx +1 -1
  520. package/src/ui/components/fileManagement/FileDetailsModal.tsx +1 -1
  521. package/src/ui/components/fileManagement/FileViewer.tsx +1 -1
  522. package/src/ui/components/fileManagement/UploadPreview.tsx +1 -1
  523. package/src/ui/components/modals/DeleteAccountModal.tsx +1 -1
  524. package/src/ui/components/payment/PaymentDetailsStep.tsx +1 -1
  525. package/src/ui/components/payment/PaymentMethodStep.tsx +1 -1
  526. package/src/ui/components/payment/PaymentReviewStep.tsx +1 -1
  527. package/src/ui/components/payment/PaymentSuccessStep.tsx +1 -1
  528. package/src/ui/components/payment/PaymentSummaryStep.tsx +1 -1
  529. package/src/ui/components/payment/types.ts +1 -1
  530. package/src/ui/context/OxyContext.tsx +220 -24
  531. package/src/ui/context/__tests__/commitSessionFlow.test.ts +89 -0
  532. package/src/ui/context/commitSessionFlow.ts +61 -0
  533. package/src/ui/context/oxyContextTypes.ts +45 -1
  534. package/src/ui/context/useOxyAccountGraph.ts +19 -5
  535. package/src/ui/hooks/useSwitchableAccounts.ts +12 -1
  536. package/src/ui/index.ts +0 -1
  537. package/src/ui/oauth/__tests__/browserAuthTransport.test.ts +335 -0
  538. package/src/ui/oauth/__tests__/completeOAuthCode.test.ts +142 -0
  539. package/src/ui/oauth/__tests__/oauthPopup.test.ts +326 -0
  540. package/src/ui/oauth/__tests__/oauthPopupMessages.test.ts +189 -0
  541. package/src/ui/oauth/__tests__/sharedCompletionPath.test.ts +174 -0
  542. package/src/ui/oauth/browserAuthTransport.ts +187 -0
  543. package/src/ui/oauth/completeOAuthCode.ts +93 -0
  544. package/src/ui/oauth/legacyRedirectLanes.ts +43 -0
  545. package/src/ui/oauth/oauthHandshake.ts +74 -0
  546. package/src/ui/oauth/oauthPopup.ts +219 -0
  547. package/src/ui/oauth/oauthPopupMessages.ts +136 -0
  548. package/src/ui/oauth/types.ts +150 -0
  549. package/src/ui/screens/AccountMembersScreen.tsx +1 -1
  550. package/src/ui/screens/CreateAccountScreen.tsx +1 -1
  551. package/src/ui/screens/EditProfileFieldScreen.tsx +1 -1
  552. package/src/ui/screens/FAQScreen.tsx +1 -1
  553. package/src/ui/screens/FeedbackScreen.tsx +2 -1
  554. package/src/ui/screens/FileManagementScreen.tsx +2 -1
  555. package/src/ui/screens/LanguageSelectorScreen.tsx +1 -1
  556. package/src/ui/screens/ManageAccountScreen.tsx +1 -1
  557. package/src/ui/screens/PaymentGatewayScreen.tsx +1 -1
  558. package/src/ui/screens/PremiumSubscriptionScreen.tsx +1 -1
  559. package/src/ui/screens/ProfileScreen.tsx +1 -1
  560. package/src/ui/screens/UserListScreen.tsx +1 -1
  561. package/src/ui/screens/WelcomeNewUserScreen.tsx +1 -1
  562. package/src/ui/screens/fileManagement/FileLibraryError.tsx +1 -1
  563. package/src/ui/screens/fileManagement/FileListSection.tsx +1 -1
  564. package/src/ui/screens/fileManagement/PhotoPickerSection.tsx +2 -1
  565. package/src/ui/screens/fileManagement/UploadBar.tsx +1 -1
  566. package/src/ui/screens/trust/TrustCenterScreen.tsx +1 -1
  567. package/src/ui/screens/trust/TrustLeaderboardScreen.tsx +1 -1
  568. package/src/ui/screens/trust/TrustRewardsScreen.tsx +1 -1
  569. package/src/ui/server.ts +0 -2
  570. package/src/ui/session/__tests__/createSessionClient.test.ts +26 -0
  571. package/src/ui/session/__tests__/tokenTransport.test.ts +34 -0
  572. package/src/ui/session/authStore.ts +5 -89
  573. package/src/ui/session/createSessionClient.ts +15 -2
  574. package/src/ui/session/identityBinding.ts +116 -0
  575. package/src/ui/session/index.ts +6 -2
  576. package/src/ui/session/nativeSecureStorage.ts +98 -0
  577. package/src/ui/session/tokenTransport.ts +14 -1
  578. package/src/ui/types/navigation.ts +44 -1
  579. package/src/ui/utils/crossOriginRestore.ts +4 -7
  580. package/src/ui/utils/deliveryPlatform.ts +65 -0
  581. package/src/ui/utils/fileManagement.ts +1 -1
  582. package/src/ui/utils/oauthReturn.ts +74 -65
  583. package/lib/commonjs/assets/assets/fonts/Inter/Inter_18pt-Black.ttf +0 -0
  584. package/lib/commonjs/assets/assets/fonts/Inter/Inter_18pt-Bold.ttf +0 -0
  585. package/lib/commonjs/assets/assets/fonts/Inter/Inter_18pt-ExtraBold.ttf +0 -0
  586. package/lib/commonjs/assets/assets/fonts/Inter/Inter_18pt-Light.ttf +0 -0
  587. package/lib/commonjs/assets/assets/fonts/Inter/Inter_18pt-Medium.ttf +0 -0
  588. package/lib/commonjs/assets/assets/fonts/Inter/Inter_18pt-Regular.ttf +0 -0
  589. package/lib/commonjs/assets/assets/fonts/Inter/Inter_18pt-SemiBold.ttf +0 -0
  590. package/lib/commonjs/assets/fonts/Inter/Inter_18pt-Black.ttf +0 -0
  591. package/lib/commonjs/assets/fonts/Inter/Inter_18pt-Bold.ttf +0 -0
  592. package/lib/commonjs/assets/fonts/Inter/Inter_18pt-ExtraBold.ttf +0 -0
  593. package/lib/commonjs/assets/fonts/Inter/Inter_18pt-Light.ttf +0 -0
  594. package/lib/commonjs/assets/fonts/Inter/Inter_18pt-Medium.ttf +0 -0
  595. package/lib/commonjs/assets/fonts/Inter/Inter_18pt-Regular.ttf +0 -0
  596. package/lib/commonjs/assets/fonts/Inter/Inter_18pt-SemiBold.ttf +0 -0
  597. package/lib/commonjs/ui/components/FontLoader.js +0 -35
  598. package/lib/commonjs/ui/components/FontLoader.js.map +0 -1
  599. package/lib/commonjs/ui/components/FontLoader.native.js +0 -88
  600. package/lib/commonjs/ui/components/FontLoader.native.js.map +0 -1
  601. package/lib/commonjs/ui/components/oxyAuthChooserStyles.js.map +0 -1
  602. package/lib/module/assets/assets/fonts/Inter/Inter_18pt-Black.ttf +0 -0
  603. package/lib/module/assets/assets/fonts/Inter/Inter_18pt-Bold.ttf +0 -0
  604. package/lib/module/assets/assets/fonts/Inter/Inter_18pt-ExtraBold.ttf +0 -0
  605. package/lib/module/assets/assets/fonts/Inter/Inter_18pt-Light.ttf +0 -0
  606. package/lib/module/assets/assets/fonts/Inter/Inter_18pt-Medium.ttf +0 -0
  607. package/lib/module/assets/assets/fonts/Inter/Inter_18pt-Regular.ttf +0 -0
  608. package/lib/module/assets/assets/fonts/Inter/Inter_18pt-SemiBold.ttf +0 -0
  609. package/lib/module/assets/fonts/Inter/Inter_18pt-Black.ttf +0 -0
  610. package/lib/module/assets/fonts/Inter/Inter_18pt-Bold.ttf +0 -0
  611. package/lib/module/assets/fonts/Inter/Inter_18pt-ExtraBold.ttf +0 -0
  612. package/lib/module/assets/fonts/Inter/Inter_18pt-Light.ttf +0 -0
  613. package/lib/module/assets/fonts/Inter/Inter_18pt-Medium.ttf +0 -0
  614. package/lib/module/assets/fonts/Inter/Inter_18pt-Regular.ttf +0 -0
  615. package/lib/module/assets/fonts/Inter/Inter_18pt-SemiBold.ttf +0 -0
  616. package/lib/module/ui/components/FontLoader.js +0 -29
  617. package/lib/module/ui/components/FontLoader.js.map +0 -1
  618. package/lib/module/ui/components/FontLoader.native.js +0 -83
  619. package/lib/module/ui/components/FontLoader.native.js.map +0 -1
  620. package/lib/module/ui/components/oxyAuthChooserStyles.js.map +0 -1
  621. package/lib/typescript/commonjs/ui/components/FontLoader.d.ts +0 -24
  622. package/lib/typescript/commonjs/ui/components/FontLoader.d.ts.map +0 -1
  623. package/lib/typescript/commonjs/ui/components/FontLoader.native.d.ts +0 -13
  624. package/lib/typescript/commonjs/ui/components/FontLoader.native.d.ts.map +0 -1
  625. package/lib/typescript/commonjs/ui/components/oxyAuthChooserStyles.d.ts.map +0 -1
  626. package/lib/typescript/module/ui/components/FontLoader.d.ts +0 -24
  627. package/lib/typescript/module/ui/components/FontLoader.d.ts.map +0 -1
  628. package/lib/typescript/module/ui/components/FontLoader.native.d.ts +0 -13
  629. package/lib/typescript/module/ui/components/FontLoader.native.d.ts.map +0 -1
  630. package/lib/typescript/module/ui/components/oxyAuthChooserStyles.d.ts.map +0 -1
  631. package/src/assets/fonts/Inter/Inter_18pt-Black.ttf +0 -0
  632. package/src/assets/fonts/Inter/Inter_18pt-Bold.ttf +0 -0
  633. package/src/assets/fonts/Inter/Inter_18pt-ExtraBold.ttf +0 -0
  634. package/src/assets/fonts/Inter/Inter_18pt-Light.ttf +0 -0
  635. package/src/assets/fonts/Inter/Inter_18pt-Medium.ttf +0 -0
  636. package/src/assets/fonts/Inter/Inter_18pt-Regular.ttf +0 -0
  637. package/src/assets/fonts/Inter/Inter_18pt-SemiBold.ttf +0 -0
  638. package/src/ui/components/FontLoader.native.tsx +0 -88
  639. package/src/ui/components/FontLoader.tsx +0 -27
@@ -1,8 +1,10 @@
1
1
  import type { ReactNode } from 'react';
2
- import type { OxyServices, User, SessionLoginResponse, AccountNode, CreateAccountInput, ClientSession, AccountDialogController, AccountDialogView, ApiError, SessionClient } from '@oxyhq/core';
2
+ import type { OxyServices, User, SessionLoginResponse, AccountNode, CreateAccountInput, ClientSession, AccountDialogController, AccountDialogView, ApiError, SessionClient, SessionMode } from '@oxyhq/core';
3
3
  import type { UseFollowHook } from '../hooks/useFollow.types';
4
4
  import type { useLanguageManagement } from '../hooks/useLanguageManagement';
5
5
  import type { RouteName } from '../navigation/routes';
6
+ import type { StartWebOAuthSignInOptions } from '../oauth/browserAuthTransport';
7
+ import type { WebAuthMode, WebOAuthSignInResult } from '../oauth/types';
6
8
 
7
9
  export interface OxyContextState {
8
10
  user: User | null;
@@ -26,6 +28,19 @@ export interface OxyContextState {
26
28
  */
27
29
  isAuthResolved: boolean;
28
30
  isStorageReady: boolean;
31
+ /**
32
+ * Who owns this provider's session (see `OxyProviderProps.sessionMode`).
33
+ *
34
+ * `'account'` — the device's active account; any app on the device can switch
35
+ * it and this client follows. `'identity'` — the owner of the local primary
36
+ * identity key, permanently: a sibling app's account switch never changes this
37
+ * client's user or bearer, and every account-graph mutation
38
+ * (`switchToAccount` / `switchSession`) rejects with `IdentityBoundSessionError`
39
+ * while `accounts` stays empty and the account dialog never opens.
40
+ */
41
+ sessionMode: SessionMode;
42
+ /** How web third-party sign-in reaches the IdP (see `OxyProviderProps.webAuthMode`). */
43
+ webAuthMode: WebAuthMode;
29
44
  error: string | null;
30
45
  /** Active UI locale (`language-REGION`): the account's primary locale when signed in, else the guest/device locale. */
31
46
  currentLanguage: string;
@@ -79,6 +94,24 @@ export interface OxyContextState {
79
94
  revokeSuspiciousSignIn: () => Promise<void>;
80
95
  handleWebSession: (session: SessionLoginResponse) => Promise<void>;
81
96
 
97
+ /**
98
+ * Run a WEB third-party OAuth sign-in (authorization code + PKCE) end to end
99
+ * using this provider's `webAuthMode`, and commit the resulting session.
100
+ *
101
+ * This is the shared operation `OxySignInButton` delegates to; RPs that ship
102
+ * their own button call it directly and never implement popup listeners, a
103
+ * token exchange, or `state` validation themselves. Returns a typed result —
104
+ * closing the popup and running out of time are values, not exceptions.
105
+ *
106
+ * In popup mode the window MUST be opened during the user's click: either
107
+ * call this synchronously from the press handler (it opens one itself), or
108
+ * call `openOAuthPopup()` there and pass the handle as `popup`.
109
+ *
110
+ * No-op outside a browser and in `sessionMode: 'identity'`, both of which
111
+ * resolve to `{ status: 'unsupported' }`.
112
+ */
113
+ startWebOAuthSignIn: (options: StartWebOAuthSignInOptions) => Promise<WebOAuthSignInResult>;
114
+
82
115
  logout: (targetSessionId?: string) => Promise<void>;
83
116
  logoutAll: () => Promise<void>;
84
117
  switchSession: (sessionId: string) => Promise<User>;
@@ -133,6 +166,17 @@ export interface OxyContextProviderProps {
133
166
  authorizeBaseUrl?: string;
134
167
  storageKeyPrefix?: string;
135
168
  clientId?: string;
169
+ /**
170
+ * Who owns this provider's session. See `OxyProviderProps.sessionMode` for the
171
+ * full contract.
172
+ * @default 'account'
173
+ */
174
+ sessionMode?: SessionMode;
175
+ /**
176
+ * Transport for WEB third-party sign-in. See `OxyProviderProps.webAuthMode`.
177
+ * @default 'redirect'
178
+ */
179
+ webAuthMode?: WebAuthMode;
136
180
  /** Sync device credentials to auth.oxy.so after interactive sign-in. @default true */
137
181
  hubSync?: boolean;
138
182
  onAuthStateChange?: (user: User | null) => void;
@@ -6,12 +6,19 @@ import { useAuthStore } from '../stores/authStore';
6
6
  import { isUnauthorizedStatus } from './oxyContextHelpers';
7
7
  import { resetSessionScopedStores } from '../stores/resetSessionScopedStores';
8
8
  import { ASSET_DOWNLOAD_URLS_QUERY_KEY } from '../hooks/useResolvedFileUrls';
9
+ import { IdentityBoundSessionError } from '../session';
9
10
  import type { CommitInput } from './oxyContextTypes';
10
11
 
11
12
  interface UseOxyAccountGraphParams {
12
13
  isAuthenticated: boolean;
13
14
  tokenReady: boolean;
14
15
  initialized: boolean;
16
+ /**
17
+ * `sessionMode: 'identity'`. The account graph is a switcher surface, and an
18
+ * identity-bound client authenticates as the owner of the local identity key —
19
+ * permanently. The graph is therefore never fetched and every switch rejects.
20
+ */
21
+ identityBound: boolean;
15
22
  oxyServices: OxyServices;
16
23
  sessionClient: SessionClient;
17
24
  syncFromClient: () => Promise<void>;
@@ -25,6 +32,7 @@ export function useOxyAccountGraph({
25
32
  isAuthenticated,
26
33
  tokenReady,
27
34
  initialized,
35
+ identityBound,
28
36
  oxyServices,
29
37
  sessionClient,
30
38
  syncFromClient,
@@ -36,7 +44,7 @@ export function useOxyAccountGraph({
36
44
  const [accounts, setAccounts] = useState<AccountNode[]>([]);
37
45
 
38
46
  const refreshAccounts = useCallback(async (): Promise<void> => {
39
- if (!isAuthenticated || !tokenReady || !oxyServices.getAccessToken()) {
47
+ if (identityBound || !isAuthenticated || !tokenReady || !oxyServices.getAccessToken()) {
40
48
  setAccounts([]);
41
49
  return;
42
50
  }
@@ -53,14 +61,14 @@ export function useOxyAccountGraph({
53
61
  loggerUtil.debug('Failed to load accounts', { component: 'OxyContext' }, err as unknown);
54
62
  }
55
63
  }
56
- }, [isAuthenticated, oxyServices, tokenReady, clearSessionStateRef]);
64
+ }, [identityBound, isAuthenticated, oxyServices, tokenReady, clearSessionStateRef]);
57
65
 
58
66
  useEffect(() => {
59
- if (isAuthenticated && initialized && tokenReady) {
67
+ if (!identityBound && isAuthenticated && initialized && tokenReady) {
60
68
  refreshAccounts();
61
69
  void accountDialogControllerRef.current?.refresh();
62
70
  }
63
- }, [isAuthenticated, initialized, tokenReady, refreshAccounts, accountDialogControllerRef]);
71
+ }, [identityBound, isAuthenticated, initialized, tokenReady, refreshAccounts, accountDialogControllerRef]);
64
72
 
65
73
  const runPostAccountSwitchSideEffects = useCallback(async (): Promise<void> => {
66
74
  resetSessionScopedStores();
@@ -74,6 +82,12 @@ export function useOxyAccountGraph({
74
82
 
75
83
  const switchToAccount = useCallback(
76
84
  async (accountId: string): Promise<void> => {
85
+ if (identityBound) {
86
+ // Loud rejection, never a silent no-op: a resolved promise here would
87
+ // read to the caller as a completed switch that simply left the user
88
+ // unchanged, which is exactly the confusion this mode must avoid.
89
+ throw new IdentityBoundSessionError('switchToAccount');
90
+ }
77
91
  const deviceState = sessionClient.getState();
78
92
  if (deviceState?.accounts.some((account) => account.accountId === accountId)) {
79
93
  await sessionClient.switchAccount(accountId);
@@ -102,7 +116,7 @@ export function useOxyAccountGraph({
102
116
  );
103
117
  await runPostAccountSwitchSideEffects();
104
118
  },
105
- [oxyServices, sessionClient, syncFromClient, commitSession, runPostAccountSwitchSideEffects],
119
+ [identityBound, oxyServices, sessionClient, syncFromClient, commitSession, runPostAccountSwitchSideEffects],
106
120
  );
107
121
 
108
122
  const createAccount = useCallback(
@@ -22,7 +22,18 @@ const EMPTY_SNAPSHOT: AccountDialogSnapshot = {
22
22
  loading: false,
23
23
  error: null,
24
24
  switchingAccountId: null,
25
- signIn: { phase: 'idle', authorizeCode: null, qrPayload: null, expiresAt: null, error: null },
25
+ signIn: {
26
+ phase: 'idle',
27
+ authorizeCode: null,
28
+ qrPayload: null,
29
+ expiresAt: null,
30
+ error: null,
31
+ route: null,
32
+ routeFailed: false,
33
+ pushSentAt: null,
34
+ openedAt: null,
35
+ progress: 'idle',
36
+ },
26
37
  commonsAvailability: 'unknown',
27
38
  };
28
39
 
package/src/ui/index.ts CHANGED
@@ -26,7 +26,6 @@ export { RequireOxyAuth } from './components/RequireOxyAuth';
26
26
  export type { RequireOxyAuthProps, RequireOxyAuthPrompt } from './components/RequireOxyAuth';
27
27
  export { default as FollowButton } from './components/FollowButton';
28
28
  export { default as OxyPayButton } from './components/OxyPayButton';
29
- export { FontLoader, setupFonts } from './components/FontLoader';
30
29
  export { default as ProfileButton } from './components/ProfileButton';
31
30
 
32
31
  // Context + hooks
@@ -0,0 +1,335 @@
1
+ // The platform redirect is spied on so no real navigation happens and the
2
+ // authorize URL each lane hands to the browser can be asserted.
3
+ jest.mock('../../components/oauthNavigation', () => ({
4
+ redirectToAuthorize: jest.fn(),
5
+ }));
6
+
7
+ import type { OxyServices } from '@oxyhq/core';
8
+ import {
9
+ computeCodeChallenge,
10
+ OXY_OAUTH_CODE_VERIFIER_STORAGE_KEY,
11
+ OXY_OAUTH_STATE_STORAGE_KEY,
12
+ } from '@oxyhq/core';
13
+ import { redirectToAuthorize } from '../../components/oauthNavigation';
14
+ import {
15
+ startWebOAuthSignIn,
16
+ type WebOAuthTransportContext,
17
+ } from '../browserAuthTransport';
18
+ import { OXY_OAUTH_CODE_MESSAGE_TYPE, OXY_OAUTH_ERROR_MESSAGE_TYPE } from '../oauthPopupMessages';
19
+ import type { OAuthPopupHandle } from '../types';
20
+
21
+ const mockRedirect = redirectToAuthorize as jest.Mock;
22
+
23
+ const CLIENT_ID = 'oxy_dk_test';
24
+ const REDIRECT_URI = 'https://mention.earth';
25
+ const AUTHORIZE_BASE_URL = 'https://auth.oxy.so/authorize';
26
+ const IDP_ORIGIN = 'https://auth.oxy.so';
27
+
28
+ const SESSION = {
29
+ sessionId: 'sess-1',
30
+ deviceId: 'dev-1',
31
+ deviceSecret: 'secret-1',
32
+ accessToken: 'token-1',
33
+ expiresAt: '2099-01-01T00:00:00.000Z',
34
+ user: { id: 'user-1', username: 'nate' },
35
+ };
36
+
37
+ interface ControllablePopup extends OAuthPopupHandle {
38
+ close: jest.Mock;
39
+ }
40
+
41
+ function fakePopup(): ControllablePopup {
42
+ let closed = false;
43
+ return {
44
+ get closed() {
45
+ return closed;
46
+ },
47
+ close: jest.fn(() => {
48
+ closed = true;
49
+ }),
50
+ location: { href: '' },
51
+ };
52
+ }
53
+
54
+ function makeContext(
55
+ overrides: Partial<WebOAuthTransportContext> = {},
56
+ ): WebOAuthTransportContext & { exchangeOAuthCode: jest.Mock; commitSession: jest.Mock } {
57
+ const exchangeOAuthCode = jest.fn().mockResolvedValue(SESSION);
58
+ const commitSession = jest.fn().mockResolvedValue(undefined);
59
+ const base: WebOAuthTransportContext = {
60
+ mode: 'popup',
61
+ oxyServices: { exchangeOAuthCode } as unknown as OxyServices,
62
+ clientId: CLIENT_ID,
63
+ authorizeBaseUrl: AUTHORIZE_BASE_URL,
64
+ identityBound: false,
65
+ commitSession,
66
+ };
67
+ return { ...base, ...overrides, exchangeOAuthCode, commitSession };
68
+ }
69
+
70
+ /** Wait for the transport to finish preparing PKCE and navigate the popup. */
71
+ async function waitForAuthorizeUrl(popup: OAuthPopupHandle): Promise<URL> {
72
+ for (let attempt = 0; attempt < 100; attempt += 1) {
73
+ if (popup.location.href) return new URL(popup.location.href);
74
+ await new Promise((resolve) => {
75
+ setTimeout(resolve, 5);
76
+ });
77
+ }
78
+ throw new Error('the popup was never navigated to the authorize URL');
79
+ }
80
+
81
+ function dispatchFromPopup(data: unknown, source: unknown, origin = IDP_ORIGIN): void {
82
+ const event = new Event('message');
83
+ Object.assign(event, { data, origin, source });
84
+ window.dispatchEvent(event);
85
+ }
86
+
87
+ describe('startWebOAuthSignIn', () => {
88
+ beforeEach(() => {
89
+ mockRedirect.mockClear();
90
+ globalThis.sessionStorage?.clear();
91
+ });
92
+
93
+ afterEach(() => {
94
+ jest.restoreAllMocks();
95
+ });
96
+
97
+ describe('popup mode', () => {
98
+ it('signs in without navigating the relying party', async () => {
99
+ const context = makeContext();
100
+ const popup = fakePopup();
101
+
102
+ const pending = startWebOAuthSignIn(context, { redirectUri: REDIRECT_URI, popup });
103
+ const authorizeUrl = await waitForAuthorizeUrl(popup);
104
+
105
+ // The IdP is asked for the popup channel, with the standard PKCE binding.
106
+ expect(authorizeUrl.origin).toBe(IDP_ORIGIN);
107
+ expect(authorizeUrl.searchParams.get('response_mode')).toBe('web_message');
108
+ expect(authorizeUrl.searchParams.get('client_id')).toBe(CLIENT_ID);
109
+ expect(authorizeUrl.searchParams.get('redirect_uri')).toBe(REDIRECT_URI);
110
+ expect(authorizeUrl.searchParams.get('code_challenge_method')).toBe('S256');
111
+
112
+ const state = authorizeUrl.searchParams.get('state');
113
+ dispatchFromPopup(
114
+ { type: OXY_OAUTH_CODE_MESSAGE_TYPE, code: 'code-1', state },
115
+ popup,
116
+ );
117
+
118
+ await expect(pending).resolves.toEqual({ status: 'signed-in' });
119
+ expect(mockRedirect).not.toHaveBeenCalled();
120
+
121
+ // The verifier the main window replays is the one behind the challenge it
122
+ // sent — the popup never saw either.
123
+ const exchangeArgs = context.exchangeOAuthCode.mock.calls[0][0];
124
+ expect(exchangeArgs.code).toBe('code-1');
125
+ expect(exchangeArgs.redirectUri).toBe(REDIRECT_URI);
126
+ await expect(computeCodeChallenge(exchangeArgs.codeVerifier)).resolves.toBe(
127
+ authorizeUrl.searchParams.get('code_challenge'),
128
+ );
129
+
130
+ expect(context.commitSession).toHaveBeenCalledTimes(1);
131
+ // Nothing about the popup handshake is left in storage.
132
+ expect(sessionStorage.getItem(OXY_OAUTH_CODE_VERIFIER_STORAGE_KEY)).toBeNull();
133
+ expect(sessionStorage.getItem(OXY_OAUTH_STATE_STORAGE_KEY)).toBeNull();
134
+ });
135
+
136
+ it('opens the window itself when the caller did not pre-open one', async () => {
137
+ const context = makeContext();
138
+ const popup = fakePopup();
139
+ const openSpy = jest.spyOn(window, 'open').mockReturnValue(popup as unknown as Window);
140
+
141
+ const pending = startWebOAuthSignIn(context, { redirectUri: REDIRECT_URI });
142
+ const authorizeUrl = await waitForAuthorizeUrl(popup);
143
+ dispatchFromPopup(
144
+ {
145
+ type: OXY_OAUTH_CODE_MESSAGE_TYPE,
146
+ code: 'code-1',
147
+ state: authorizeUrl.searchParams.get('state'),
148
+ },
149
+ popup,
150
+ );
151
+
152
+ await expect(pending).resolves.toEqual({ status: 'signed-in' });
153
+ expect(openSpy).toHaveBeenCalledTimes(1);
154
+ });
155
+
156
+ it('falls back to a full-page redirect when the popup was blocked', async () => {
157
+ const context = makeContext();
158
+
159
+ const result = await startWebOAuthSignIn(context, {
160
+ redirectUri: REDIRECT_URI,
161
+ popup: null,
162
+ });
163
+
164
+ expect(result).toEqual({ status: 'redirecting', via: 'popup-blocked' });
165
+ expect(mockRedirect).toHaveBeenCalledTimes(1);
166
+ // The fallback is a plain redirect request — no popup channel.
167
+ const url = new URL(mockRedirect.mock.calls[0][0]);
168
+ expect(url.searchParams.get('response_mode')).toBeNull();
169
+ // …and its handshake survives the navigation.
170
+ expect(sessionStorage.getItem(OXY_OAUTH_STATE_STORAGE_KEY)).toBe(
171
+ url.searchParams.get('state'),
172
+ );
173
+ expect(sessionStorage.getItem(OXY_OAUTH_CODE_VERIFIER_STORAGE_KEY)).toBeTruthy();
174
+ expect(context.exchangeOAuthCode).not.toHaveBeenCalled();
175
+ });
176
+
177
+ it('falls back to a full-page redirect when the popup cannot be navigated', async () => {
178
+ const context = makeContext();
179
+ const deadPopup: OAuthPopupHandle = {
180
+ closed: false,
181
+ close: jest.fn(),
182
+ get location(): { href: string } {
183
+ throw new Error('window closed');
184
+ },
185
+ };
186
+
187
+ const result = await startWebOAuthSignIn(context, {
188
+ redirectUri: REDIRECT_URI,
189
+ popup: deadPopup,
190
+ });
191
+
192
+ expect(result).toEqual({ status: 'redirecting', via: 'popup-navigation-failed' });
193
+ expect(mockRedirect).toHaveBeenCalledTimes(1);
194
+ });
195
+
196
+ it('surfaces a typed IdP error and closes the window', async () => {
197
+ const context = makeContext();
198
+ const popup = fakePopup();
199
+
200
+ const pending = startWebOAuthSignIn(context, { redirectUri: REDIRECT_URI, popup });
201
+ const authorizeUrl = await waitForAuthorizeUrl(popup);
202
+ dispatchFromPopup(
203
+ {
204
+ type: OXY_OAUTH_ERROR_MESSAGE_TYPE,
205
+ error: 'access_denied',
206
+ errorDescription: 'user declined',
207
+ state: authorizeUrl.searchParams.get('state'),
208
+ },
209
+ popup,
210
+ );
211
+
212
+ await expect(pending).resolves.toEqual({
213
+ status: 'failed',
214
+ reason: 'idp-error',
215
+ description: 'user declined',
216
+ });
217
+ expect(context.exchangeOAuthCode).not.toHaveBeenCalled();
218
+ expect(popup.close).toHaveBeenCalled();
219
+ });
220
+
221
+ it('refuses a result carrying the wrong state', async () => {
222
+ const context = makeContext();
223
+ const popup = fakePopup();
224
+
225
+ const pending = startWebOAuthSignIn(context, { redirectUri: REDIRECT_URI, popup });
226
+ await waitForAuthorizeUrl(popup);
227
+ dispatchFromPopup(
228
+ { type: OXY_OAUTH_CODE_MESSAGE_TYPE, code: 'code-1', state: 'forged-state' },
229
+ popup,
230
+ );
231
+
232
+ await expect(pending).resolves.toEqual({ status: 'failed', reason: 'state-mismatch' });
233
+ expect(context.exchangeOAuthCode).not.toHaveBeenCalled();
234
+ expect(context.commitSession).not.toHaveBeenCalled();
235
+ });
236
+
237
+ it('reports a timeout when the popup never answers', async () => {
238
+ const context = makeContext();
239
+ const popup = fakePopup();
240
+
241
+ const result = await startWebOAuthSignIn(context, {
242
+ redirectUri: REDIRECT_URI,
243
+ popup,
244
+ timeoutMs: 20,
245
+ });
246
+
247
+ expect(result).toEqual({ status: 'timed-out' });
248
+ expect(popup.close).toHaveBeenCalled();
249
+ expect(context.exchangeOAuthCode).not.toHaveBeenCalled();
250
+ });
251
+
252
+ it('reports a failed exchange', async () => {
253
+ const context = makeContext();
254
+ context.exchangeOAuthCode.mockRejectedValue(new Error('invalid_grant'));
255
+ const popup = fakePopup();
256
+
257
+ const pending = startWebOAuthSignIn(context, { redirectUri: REDIRECT_URI, popup });
258
+ const authorizeUrl = await waitForAuthorizeUrl(popup);
259
+ dispatchFromPopup(
260
+ {
261
+ type: OXY_OAUTH_CODE_MESSAGE_TYPE,
262
+ code: 'code-1',
263
+ state: authorizeUrl.searchParams.get('state'),
264
+ },
265
+ popup,
266
+ );
267
+
268
+ await expect(pending).resolves.toEqual({ status: 'failed', reason: 'exchange-failed' });
269
+ expect(context.commitSession).not.toHaveBeenCalled();
270
+ });
271
+ });
272
+
273
+ describe('redirect mode', () => {
274
+ it('hands the top-level document to the IdP and persists the handshake', async () => {
275
+ const context = makeContext({ mode: 'redirect' });
276
+
277
+ const result = await startWebOAuthSignIn(context, { redirectUri: REDIRECT_URI });
278
+
279
+ expect(result).toEqual({ status: 'redirecting', via: 'redirect-mode' });
280
+ expect(mockRedirect).toHaveBeenCalledTimes(1);
281
+ const url = new URL(mockRedirect.mock.calls[0][0]);
282
+ expect(url.searchParams.get('response_mode')).toBeNull();
283
+ expect(url.searchParams.get('client_id')).toBe(CLIENT_ID);
284
+ expect(sessionStorage.getItem(OXY_OAUTH_STATE_STORAGE_KEY)).toBe(
285
+ url.searchParams.get('state'),
286
+ );
287
+ });
288
+
289
+ it('never opens a window, even if one was handed to it', async () => {
290
+ const context = makeContext({ mode: 'redirect' });
291
+ const popup = fakePopup();
292
+ const openSpy = jest.spyOn(window, 'open');
293
+
294
+ await startWebOAuthSignIn(context, { redirectUri: REDIRECT_URI, popup });
295
+
296
+ expect(openSpy).not.toHaveBeenCalled();
297
+ expect(popup.close).toHaveBeenCalledTimes(1);
298
+ expect(popup.location.href).toBe('');
299
+ });
300
+
301
+ it('aborts instead of redirecting when the handshake cannot be persisted', async () => {
302
+ const context = makeContext({ mode: 'redirect' });
303
+ jest.spyOn(Storage.prototype, 'setItem').mockImplementation(() => {
304
+ throw new Error('storage is disabled');
305
+ });
306
+
307
+ const result = await startWebOAuthSignIn(context, { redirectUri: REDIRECT_URI });
308
+
309
+ expect(result).toEqual({ status: 'failed', reason: 'handshake-storage' });
310
+ expect(mockRedirect).not.toHaveBeenCalled();
311
+ });
312
+ });
313
+
314
+ describe('inapplicable configurations', () => {
315
+ it('refuses an identity-bound provider and closes any popup it was given', async () => {
316
+ const context = makeContext({ identityBound: true });
317
+ const popup = fakePopup();
318
+
319
+ const result = await startWebOAuthSignIn(context, { redirectUri: REDIRECT_URI, popup });
320
+
321
+ expect(result).toEqual({ status: 'unsupported', reason: 'identity-bound' });
322
+ expect(popup.close).toHaveBeenCalledTimes(1);
323
+ expect(mockRedirect).not.toHaveBeenCalled();
324
+ });
325
+
326
+ it('refuses a provider with no clientId', async () => {
327
+ const context = makeContext({ clientId: null });
328
+
329
+ const result = await startWebOAuthSignIn(context, { redirectUri: REDIRECT_URI });
330
+
331
+ expect(result).toEqual({ status: 'unsupported', reason: 'missing-client-id' });
332
+ expect(mockRedirect).not.toHaveBeenCalled();
333
+ });
334
+ });
335
+ });
@@ -0,0 +1,142 @@
1
+ import type { OxyServices } from '@oxyhq/core';
2
+ import { completeOAuthCode } from '../completeOAuthCode';
3
+ import type { OAuthSessionCommitInput } from '../types';
4
+
5
+ const HANDSHAKE = { state: 'state-abc', codeVerifier: 'verifier-xyz' };
6
+ const REDIRECT_URI = 'https://mention.earth';
7
+
8
+ const SESSION = {
9
+ sessionId: 'sess-1',
10
+ deviceId: 'dev-1',
11
+ deviceSecret: 'secret-1',
12
+ accessToken: 'token-1',
13
+ expiresAt: '2099-01-01T00:00:00.000Z',
14
+ user: { id: 'user-1', username: 'nate', avatar: 'a1' },
15
+ };
16
+
17
+ function makeOxyServices(exchange: jest.Mock): OxyServices {
18
+ return { exchangeOAuthCode: exchange } as unknown as OxyServices;
19
+ }
20
+
21
+ describe('completeOAuthCode', () => {
22
+ it('exchanges the code and commits the session it returns', async () => {
23
+ const exchange = jest.fn().mockResolvedValue(SESSION);
24
+ const committed: OAuthSessionCommitInput[] = [];
25
+
26
+ const result = await completeOAuthCode({
27
+ oxyServices: makeOxyServices(exchange),
28
+ clientId: 'oxy_dk_test',
29
+ code: 'code-1',
30
+ returnedState: HANDSHAKE.state,
31
+ handshake: HANDSHAKE,
32
+ redirectUri: REDIRECT_URI,
33
+ commitSession: async (input) => {
34
+ committed.push(input);
35
+ },
36
+ });
37
+
38
+ expect(result).toEqual({ ok: true });
39
+ expect(exchange).toHaveBeenCalledWith({
40
+ code: 'code-1',
41
+ clientId: 'oxy_dk_test',
42
+ redirectUri: REDIRECT_URI,
43
+ codeVerifier: HANDSHAKE.codeVerifier,
44
+ });
45
+ expect(committed).toEqual([
46
+ {
47
+ sessionId: 'sess-1',
48
+ accessToken: 'token-1',
49
+ deviceId: 'dev-1',
50
+ deviceSecret: 'secret-1',
51
+ userId: 'user-1',
52
+ expiresAt: '2099-01-01T00:00:00.000Z',
53
+ user: SESSION.user,
54
+ },
55
+ ]);
56
+ });
57
+
58
+ it('cleans up BEFORE committing, so a stale code cannot re-enter the exchange', async () => {
59
+ const order: string[] = [];
60
+ const result = await completeOAuthCode({
61
+ oxyServices: makeOxyServices(jest.fn().mockResolvedValue(SESSION)),
62
+ clientId: 'oxy_dk_test',
63
+ code: 'code-1',
64
+ returnedState: HANDSHAKE.state,
65
+ handshake: HANDSHAKE,
66
+ redirectUri: REDIRECT_URI,
67
+ commitSession: async () => {
68
+ order.push('commit');
69
+ },
70
+ cleanup: () => {
71
+ order.push('cleanup');
72
+ },
73
+ });
74
+
75
+ expect(result).toEqual({ ok: true });
76
+ expect(order).toEqual(['cleanup', 'commit']);
77
+ });
78
+
79
+ it.each([
80
+ ['a mismatched state', 'someone-elses-state', HANDSHAKE],
81
+ ['no returned state', null, HANDSHAKE],
82
+ ['no stored handshake', HANDSHAKE.state, null],
83
+ ])('refuses to exchange the code with %s', async (_label, returnedState, handshake) => {
84
+ const exchange = jest.fn();
85
+ const commitSession = jest.fn();
86
+ const cleanup = jest.fn();
87
+
88
+ const result = await completeOAuthCode({
89
+ oxyServices: makeOxyServices(exchange),
90
+ clientId: 'oxy_dk_test',
91
+ code: 'code-1',
92
+ returnedState,
93
+ handshake,
94
+ redirectUri: REDIRECT_URI,
95
+ commitSession,
96
+ cleanup,
97
+ });
98
+
99
+ expect(result).toEqual({ ok: false, reason: 'state-mismatch' });
100
+ expect(exchange).not.toHaveBeenCalled();
101
+ expect(commitSession).not.toHaveBeenCalled();
102
+ expect(cleanup).toHaveBeenCalledTimes(1);
103
+ });
104
+
105
+ it('reports a failed exchange without throwing, and still cleans up', async () => {
106
+ const cleanup = jest.fn();
107
+ const commitSession = jest.fn();
108
+
109
+ const result = await completeOAuthCode({
110
+ oxyServices: makeOxyServices(jest.fn().mockRejectedValue(new Error('invalid_grant'))),
111
+ clientId: 'oxy_dk_test',
112
+ code: 'code-1',
113
+ returnedState: HANDSHAKE.state,
114
+ handshake: HANDSHAKE,
115
+ redirectUri: REDIRECT_URI,
116
+ commitSession,
117
+ cleanup,
118
+ });
119
+
120
+ expect(result).toEqual({ ok: false, reason: 'exchange-failed' });
121
+ expect(commitSession).not.toHaveBeenCalled();
122
+ expect(cleanup).toHaveBeenCalledTimes(1);
123
+ });
124
+
125
+ it('reports a failed commit without throwing, and cleans up exactly once', async () => {
126
+ const cleanup = jest.fn();
127
+
128
+ const result = await completeOAuthCode({
129
+ oxyServices: makeOxyServices(jest.fn().mockResolvedValue(SESSION)),
130
+ clientId: 'oxy_dk_test',
131
+ code: 'code-1',
132
+ returnedState: HANDSHAKE.state,
133
+ handshake: HANDSHAKE,
134
+ redirectUri: REDIRECT_URI,
135
+ commitSession: jest.fn().mockRejectedValue(new Error('commit blew up')),
136
+ cleanup,
137
+ });
138
+
139
+ expect(result).toEqual({ ok: false, reason: 'exchange-failed' });
140
+ expect(cleanup).toHaveBeenCalledTimes(1);
141
+ });
142
+ });