@oxyhq/services 27.1.3 → 29.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (387) hide show
  1. package/LICENSE +202 -661
  2. package/NOTICE +16 -0
  3. package/README.md +67 -2
  4. package/android/src/main/java/so/oxy/devicesession/OxyDeviceSessionModule.kt +178 -0
  5. package/android/src/main/java/so/oxy/devicesession/OxyDeviceSessionProvider.kt +99 -0
  6. package/android/src/main/java/so/oxy/devicesession/OxyDeviceSessionStore.kt +115 -0
  7. package/expo-module.config.json +1 -0
  8. package/lib/commonjs/index.js +78 -16
  9. package/lib/commonjs/index.js.map +1 -1
  10. package/lib/commonjs/ui/boot/runProviderColdBoot.js +7 -0
  11. package/lib/commonjs/ui/boot/runProviderColdBoot.js.map +1 -1
  12. package/lib/commonjs/ui/client.js +12 -7
  13. package/lib/commonjs/ui/client.js.map +1 -1
  14. package/lib/commonjs/ui/components/OxyAccountDialogScreen.js +10 -27
  15. package/lib/commonjs/ui/components/OxyAccountDialogScreen.js.map +1 -1
  16. package/lib/commonjs/ui/components/OxyAuthChooser.js +132 -44
  17. package/lib/commonjs/ui/components/OxyAuthChooser.js.map +1 -1
  18. package/lib/commonjs/ui/components/OxyProvider.js +4 -2
  19. package/lib/commonjs/ui/components/OxyProvider.js.map +1 -1
  20. package/lib/commonjs/ui/components/SurfaceScreen.js +31 -3
  21. package/lib/commonjs/ui/components/SurfaceScreen.js.map +1 -1
  22. package/lib/commonjs/ui/components/authChooser/AccountsMenuView.js +209 -84
  23. package/lib/commonjs/ui/components/authChooser/AccountsMenuView.js.map +1 -1
  24. package/lib/commonjs/ui/components/authChooser/SignInEntryView.js +25 -7
  25. package/lib/commonjs/ui/components/authChooser/SignInEntryView.js.map +1 -1
  26. package/lib/commonjs/ui/components/authChooser/primitives.js +35 -22
  27. package/lib/commonjs/ui/components/authChooser/primitives.js.map +1 -1
  28. package/lib/commonjs/ui/components/authChooser/signInProgress.js +5 -0
  29. package/lib/commonjs/ui/components/authChooser/signInProgress.js.map +1 -1
  30. package/lib/commonjs/ui/components/authChooser/types.js +11 -0
  31. package/lib/commonjs/ui/components/authChooser/types.js.map +1 -1
  32. package/lib/commonjs/ui/context/OxyContext.js +257 -306
  33. package/lib/commonjs/ui/context/OxyContext.js.map +1 -1
  34. package/lib/commonjs/ui/context/hooks/useAuthOperations.js +27 -37
  35. package/lib/commonjs/ui/context/hooks/useAuthOperations.js.map +1 -1
  36. package/lib/commonjs/ui/context/oxyContextHelpers.js +0 -29
  37. package/lib/commonjs/ui/context/oxyContextHelpers.js.map +1 -1
  38. package/lib/commonjs/ui/context/useOxyAccountGraph.js +6 -17
  39. package/lib/commonjs/ui/context/useOxyAccountGraph.js.map +1 -1
  40. package/lib/commonjs/ui/hooks/accountDialogSnapshot.js +42 -0
  41. package/lib/commonjs/ui/hooks/accountDialogSnapshot.js.map +1 -0
  42. package/lib/commonjs/ui/hooks/mutations/useAccountMutations.js +0 -19
  43. package/lib/commonjs/ui/hooks/mutations/useAccountMutations.js.map +1 -1
  44. package/lib/commonjs/ui/hooks/useDeviceSwitcher.js +57 -0
  45. package/lib/commonjs/ui/hooks/useDeviceSwitcher.js.map +1 -0
  46. package/lib/commonjs/ui/hooks/useI18n.js +22 -3
  47. package/lib/commonjs/ui/hooks/useI18n.js.map +1 -1
  48. package/lib/commonjs/ui/hooks/useSessionManagement.js +46 -153
  49. package/lib/commonjs/ui/hooks/useSessionManagement.js.map +1 -1
  50. package/lib/commonjs/ui/index.js +12 -7
  51. package/lib/commonjs/ui/index.js.map +1 -1
  52. package/lib/commonjs/ui/navigation/routes.js +85 -73
  53. package/lib/commonjs/ui/navigation/routes.js.map +1 -1
  54. package/lib/commonjs/ui/navigation/surfaces.js +8 -7
  55. package/lib/commonjs/ui/navigation/surfaces.js.map +1 -1
  56. package/lib/commonjs/ui/runtime/createOxyRuntime.js +433 -0
  57. package/lib/commonjs/ui/runtime/createOxyRuntime.js.map +1 -0
  58. package/lib/commonjs/ui/runtime/index.js +63 -0
  59. package/lib/commonjs/ui/runtime/index.js.map +1 -0
  60. package/lib/commonjs/ui/runtime/runtimeContext.js +83 -0
  61. package/lib/commonjs/ui/runtime/runtimeContext.js.map +1 -0
  62. package/lib/commonjs/ui/runtime/types.js +6 -0
  63. package/lib/commonjs/ui/runtime/types.js.map +1 -0
  64. package/lib/commonjs/ui/runtime/useRuntimeSnapshot.js +57 -0
  65. package/lib/commonjs/ui/runtime/useRuntimeSnapshot.js.map +1 -0
  66. package/lib/commonjs/ui/screens/AccountMembersScreen.js +3 -4
  67. package/lib/commonjs/ui/screens/AccountMembersScreen.js.map +1 -1
  68. package/lib/commonjs/ui/screens/CreateAccountScreen.js +3 -12
  69. package/lib/commonjs/ui/screens/CreateAccountScreen.js.map +1 -1
  70. package/lib/commonjs/ui/screens/trust/TrustCenterScreen.js +6 -5
  71. package/lib/commonjs/ui/screens/trust/TrustCenterScreen.js.map +1 -1
  72. package/lib/commonjs/ui/screens/trust/TrustLeaderboardScreen.js +4 -4
  73. package/lib/commonjs/ui/screens/trust/TrustLeaderboardScreen.js.map +1 -1
  74. package/lib/commonjs/ui/screens/trust/TrustRewardsScreen.js +1 -1
  75. package/lib/commonjs/ui/screens/trust/TrustRulesScreen.js +4 -2
  76. package/lib/commonjs/ui/screens/trust/TrustRulesScreen.js.map +1 -1
  77. package/lib/commonjs/ui/server.js +1 -2
  78. package/lib/commonjs/ui/server.js.map +1 -1
  79. package/lib/commonjs/ui/session/authStore.js +45 -9
  80. package/lib/commonjs/ui/session/authStore.js.map +1 -1
  81. package/lib/commonjs/ui/session/sharedDeviceCredentialStore.js +306 -0
  82. package/lib/commonjs/ui/session/sharedDeviceCredentialStore.js.map +1 -0
  83. package/lib/commonjs/ui/stores/authStore.js +154 -55
  84. package/lib/commonjs/ui/stores/authStore.js.map +1 -1
  85. package/lib/commonjs/ui/stores/followTargetStore.js +27 -0
  86. package/lib/commonjs/ui/stores/followTargetStore.js.map +1 -1
  87. package/lib/commonjs/ui/utils/avatarUtils.js +2 -36
  88. package/lib/commonjs/ui/utils/avatarUtils.js.map +1 -1
  89. package/lib/module/index.js +20 -9
  90. package/lib/module/index.js.map +1 -1
  91. package/lib/module/ui/boot/runProviderColdBoot.js +7 -0
  92. package/lib/module/ui/boot/runProviderColdBoot.js.map +1 -1
  93. package/lib/module/ui/client.js +1 -2
  94. package/lib/module/ui/client.js.map +1 -1
  95. package/lib/module/ui/components/OxyAccountDialogScreen.js +10 -27
  96. package/lib/module/ui/components/OxyAccountDialogScreen.js.map +1 -1
  97. package/lib/module/ui/components/OxyAuthChooser.js +134 -44
  98. package/lib/module/ui/components/OxyAuthChooser.js.map +1 -1
  99. package/lib/module/ui/components/OxyProvider.js +5 -3
  100. package/lib/module/ui/components/OxyProvider.js.map +1 -1
  101. package/lib/module/ui/components/SurfaceScreen.js +33 -5
  102. package/lib/module/ui/components/SurfaceScreen.js.map +1 -1
  103. package/lib/module/ui/components/authChooser/AccountsMenuView.js +210 -85
  104. package/lib/module/ui/components/authChooser/AccountsMenuView.js.map +1 -1
  105. package/lib/module/ui/components/authChooser/SignInEntryView.js +25 -7
  106. package/lib/module/ui/components/authChooser/SignInEntryView.js.map +1 -1
  107. package/lib/module/ui/components/authChooser/primitives.js +35 -22
  108. package/lib/module/ui/components/authChooser/primitives.js.map +1 -1
  109. package/lib/module/ui/components/authChooser/signInProgress.js +5 -0
  110. package/lib/module/ui/components/authChooser/signInProgress.js.map +1 -1
  111. package/lib/module/ui/components/authChooser/types.js +11 -0
  112. package/lib/module/ui/components/authChooser/types.js.map +1 -1
  113. package/lib/module/ui/context/OxyContext.js +251 -303
  114. package/lib/module/ui/context/OxyContext.js.map +1 -1
  115. package/lib/module/ui/context/hooks/useAuthOperations.js +27 -37
  116. package/lib/module/ui/context/hooks/useAuthOperations.js.map +1 -1
  117. package/lib/module/ui/context/oxyContextHelpers.js +0 -28
  118. package/lib/module/ui/context/oxyContextHelpers.js.map +1 -1
  119. package/lib/module/ui/context/useOxyAccountGraph.js +6 -17
  120. package/lib/module/ui/context/useOxyAccountGraph.js.map +1 -1
  121. package/lib/module/ui/hooks/accountDialogSnapshot.js +38 -0
  122. package/lib/module/ui/hooks/accountDialogSnapshot.js.map +1 -0
  123. package/lib/module/ui/hooks/mutations/useAccountMutations.js +0 -19
  124. package/lib/module/ui/hooks/mutations/useAccountMutations.js.map +1 -1
  125. package/lib/module/ui/hooks/useDeviceSwitcher.js +53 -0
  126. package/lib/module/ui/hooks/useDeviceSwitcher.js.map +1 -0
  127. package/lib/module/ui/hooks/useI18n.js +24 -4
  128. package/lib/module/ui/hooks/useI18n.js.map +1 -1
  129. package/lib/module/ui/hooks/useSessionManagement.js +47 -155
  130. package/lib/module/ui/hooks/useSessionManagement.js.map +1 -1
  131. package/lib/module/ui/index.js +1 -2
  132. package/lib/module/ui/index.js.map +1 -1
  133. package/lib/module/ui/navigation/routes.js +84 -72
  134. package/lib/module/ui/navigation/routes.js.map +1 -1
  135. package/lib/module/ui/navigation/surfaces.js +6 -6
  136. package/lib/module/ui/navigation/surfaces.js.map +1 -1
  137. package/lib/module/ui/runtime/createOxyRuntime.js +430 -0
  138. package/lib/module/ui/runtime/createOxyRuntime.js.map +1 -0
  139. package/lib/module/ui/runtime/index.js +15 -0
  140. package/lib/module/ui/runtime/index.js.map +1 -0
  141. package/lib/module/ui/runtime/runtimeContext.js +75 -0
  142. package/lib/module/ui/runtime/runtimeContext.js.map +1 -0
  143. package/lib/module/ui/runtime/types.js +4 -0
  144. package/lib/module/ui/runtime/types.js.map +1 -0
  145. package/lib/module/ui/runtime/useRuntimeSnapshot.js +52 -0
  146. package/lib/module/ui/runtime/useRuntimeSnapshot.js.map +1 -0
  147. package/lib/module/ui/screens/AccountMembersScreen.js +4 -5
  148. package/lib/module/ui/screens/AccountMembersScreen.js.map +1 -1
  149. package/lib/module/ui/screens/CreateAccountScreen.js +4 -13
  150. package/lib/module/ui/screens/CreateAccountScreen.js.map +1 -1
  151. package/lib/module/ui/screens/trust/TrustCenterScreen.js +6 -5
  152. package/lib/module/ui/screens/trust/TrustCenterScreen.js.map +1 -1
  153. package/lib/module/ui/screens/trust/TrustLeaderboardScreen.js +5 -5
  154. package/lib/module/ui/screens/trust/TrustLeaderboardScreen.js.map +1 -1
  155. package/lib/module/ui/screens/trust/TrustRewardsScreen.js +1 -1
  156. package/lib/module/ui/screens/trust/TrustRulesScreen.js +4 -2
  157. package/lib/module/ui/screens/trust/TrustRulesScreen.js.map +1 -1
  158. package/lib/module/ui/server.js +0 -1
  159. package/lib/module/ui/server.js.map +1 -1
  160. package/lib/module/ui/session/authStore.js +46 -11
  161. package/lib/module/ui/session/authStore.js.map +1 -1
  162. package/lib/module/ui/session/sharedDeviceCredentialStore.js +302 -0
  163. package/lib/module/ui/session/sharedDeviceCredentialStore.js.map +1 -0
  164. package/lib/module/ui/stores/authStore.js +154 -55
  165. package/lib/module/ui/stores/authStore.js.map +1 -1
  166. package/lib/module/ui/stores/followTargetStore.js +25 -0
  167. package/lib/module/ui/stores/followTargetStore.js.map +1 -1
  168. package/lib/module/ui/utils/avatarUtils.js +2 -35
  169. package/lib/module/ui/utils/avatarUtils.js.map +1 -1
  170. package/lib/typescript/commonjs/index.d.ts +6 -4
  171. package/lib/typescript/commonjs/index.d.ts.map +1 -1
  172. package/lib/typescript/commonjs/ui/boot/runProviderColdBoot.d.ts.map +1 -1
  173. package/lib/typescript/commonjs/ui/client.d.ts +1 -2
  174. package/lib/typescript/commonjs/ui/client.d.ts.map +1 -1
  175. package/lib/typescript/commonjs/ui/components/OxyAccountDialogScreen.d.ts.map +1 -1
  176. package/lib/typescript/commonjs/ui/components/OxyAuthChooser.d.ts.map +1 -1
  177. package/lib/typescript/commonjs/ui/components/OxyProvider.d.ts.map +1 -1
  178. package/lib/typescript/commonjs/ui/components/SurfaceScreen.d.ts.map +1 -1
  179. package/lib/typescript/commonjs/ui/components/authChooser/AccountsMenuView.d.ts +11 -4
  180. package/lib/typescript/commonjs/ui/components/authChooser/AccountsMenuView.d.ts.map +1 -1
  181. package/lib/typescript/commonjs/ui/components/authChooser/SignInEntryView.d.ts +3 -1
  182. package/lib/typescript/commonjs/ui/components/authChooser/SignInEntryView.d.ts.map +1 -1
  183. package/lib/typescript/commonjs/ui/components/authChooser/primitives.d.ts +18 -6
  184. package/lib/typescript/commonjs/ui/components/authChooser/primitives.d.ts.map +1 -1
  185. package/lib/typescript/commonjs/ui/components/authChooser/signInProgress.d.ts.map +1 -1
  186. package/lib/typescript/commonjs/ui/components/authChooser/types.d.ts +33 -1
  187. package/lib/typescript/commonjs/ui/components/authChooser/types.d.ts.map +1 -1
  188. package/lib/typescript/commonjs/ui/context/OxyContext.d.ts +35 -4
  189. package/lib/typescript/commonjs/ui/context/OxyContext.d.ts.map +1 -1
  190. package/lib/typescript/commonjs/ui/context/hooks/useAuthOperations.d.ts +8 -12
  191. package/lib/typescript/commonjs/ui/context/hooks/useAuthOperations.d.ts.map +1 -1
  192. package/lib/typescript/commonjs/ui/context/oxyContextHelpers.d.ts +0 -2
  193. package/lib/typescript/commonjs/ui/context/oxyContextHelpers.d.ts.map +1 -1
  194. package/lib/typescript/commonjs/ui/context/oxyContextTypes.d.ts +9 -1
  195. package/lib/typescript/commonjs/ui/context/oxyContextTypes.d.ts.map +1 -1
  196. package/lib/typescript/commonjs/ui/context/useOxyAccountGraph.d.ts +1 -3
  197. package/lib/typescript/commonjs/ui/context/useOxyAccountGraph.d.ts.map +1 -1
  198. package/lib/typescript/commonjs/ui/hooks/accountDialogSnapshot.d.ts +15 -0
  199. package/lib/typescript/commonjs/ui/hooks/accountDialogSnapshot.d.ts.map +1 -0
  200. package/lib/typescript/commonjs/ui/hooks/mutations/useAccountMutations.d.ts.map +1 -1
  201. package/lib/typescript/commonjs/ui/hooks/useDeviceSwitcher.d.ts +49 -0
  202. package/lib/typescript/commonjs/ui/hooks/useDeviceSwitcher.d.ts.map +1 -0
  203. package/lib/typescript/commonjs/ui/hooks/useI18n.d.ts +13 -0
  204. package/lib/typescript/commonjs/ui/hooks/useI18n.d.ts.map +1 -1
  205. package/lib/typescript/commonjs/ui/hooks/useSessionManagement.d.ts +23 -18
  206. package/lib/typescript/commonjs/ui/hooks/useSessionManagement.d.ts.map +1 -1
  207. package/lib/typescript/commonjs/ui/index.d.ts +1 -2
  208. package/lib/typescript/commonjs/ui/index.d.ts.map +1 -1
  209. package/lib/typescript/commonjs/ui/navigation/routes.d.ts +15 -1
  210. package/lib/typescript/commonjs/ui/navigation/routes.d.ts.map +1 -1
  211. package/lib/typescript/commonjs/ui/navigation/surfaces.d.ts.map +1 -1
  212. package/lib/typescript/commonjs/ui/runtime/createOxyRuntime.d.ts +144 -0
  213. package/lib/typescript/commonjs/ui/runtime/createOxyRuntime.d.ts.map +1 -0
  214. package/lib/typescript/commonjs/ui/runtime/index.d.ts +16 -0
  215. package/lib/typescript/commonjs/ui/runtime/index.d.ts.map +1 -0
  216. package/lib/typescript/commonjs/ui/runtime/runtimeContext.d.ts +43 -0
  217. package/lib/typescript/commonjs/ui/runtime/runtimeContext.d.ts.map +1 -0
  218. package/lib/typescript/commonjs/ui/runtime/types.d.ts +89 -0
  219. package/lib/typescript/commonjs/ui/runtime/types.d.ts.map +1 -0
  220. package/lib/typescript/commonjs/ui/runtime/useRuntimeSnapshot.d.ts +23 -0
  221. package/lib/typescript/commonjs/ui/runtime/useRuntimeSnapshot.d.ts.map +1 -0
  222. package/lib/typescript/commonjs/ui/screens/AccountMembersScreen.d.ts.map +1 -1
  223. package/lib/typescript/commonjs/ui/screens/CreateAccountScreen.d.ts.map +1 -1
  224. package/lib/typescript/commonjs/ui/screens/trust/TrustLeaderboardScreen.d.ts.map +1 -1
  225. package/lib/typescript/commonjs/ui/screens/trust/TrustRulesScreen.d.ts.map +1 -1
  226. package/lib/typescript/commonjs/ui/server.d.ts +0 -1
  227. package/lib/typescript/commonjs/ui/server.d.ts.map +1 -1
  228. package/lib/typescript/commonjs/ui/session/authStore.d.ts +60 -9
  229. package/lib/typescript/commonjs/ui/session/authStore.d.ts.map +1 -1
  230. package/lib/typescript/commonjs/ui/session/sharedDeviceCredentialStore.d.ts +32 -0
  231. package/lib/typescript/commonjs/ui/session/sharedDeviceCredentialStore.d.ts.map +1 -0
  232. package/lib/typescript/commonjs/ui/stores/authStore.d.ts +49 -5
  233. package/lib/typescript/commonjs/ui/stores/authStore.d.ts.map +1 -1
  234. package/lib/typescript/commonjs/ui/stores/followTargetStore.d.ts +8 -1
  235. package/lib/typescript/commonjs/ui/stores/followTargetStore.d.ts.map +1 -1
  236. package/lib/typescript/commonjs/ui/types/navigation.d.ts +26 -0
  237. package/lib/typescript/commonjs/ui/types/navigation.d.ts.map +1 -1
  238. package/lib/typescript/commonjs/ui/utils/avatarUtils.d.ts +2 -10
  239. package/lib/typescript/commonjs/ui/utils/avatarUtils.d.ts.map +1 -1
  240. package/lib/typescript/module/index.d.ts +6 -4
  241. package/lib/typescript/module/index.d.ts.map +1 -1
  242. package/lib/typescript/module/ui/boot/runProviderColdBoot.d.ts.map +1 -1
  243. package/lib/typescript/module/ui/client.d.ts +1 -2
  244. package/lib/typescript/module/ui/client.d.ts.map +1 -1
  245. package/lib/typescript/module/ui/components/OxyAccountDialogScreen.d.ts.map +1 -1
  246. package/lib/typescript/module/ui/components/OxyAuthChooser.d.ts.map +1 -1
  247. package/lib/typescript/module/ui/components/OxyProvider.d.ts.map +1 -1
  248. package/lib/typescript/module/ui/components/SurfaceScreen.d.ts.map +1 -1
  249. package/lib/typescript/module/ui/components/authChooser/AccountsMenuView.d.ts +11 -4
  250. package/lib/typescript/module/ui/components/authChooser/AccountsMenuView.d.ts.map +1 -1
  251. package/lib/typescript/module/ui/components/authChooser/SignInEntryView.d.ts +3 -1
  252. package/lib/typescript/module/ui/components/authChooser/SignInEntryView.d.ts.map +1 -1
  253. package/lib/typescript/module/ui/components/authChooser/primitives.d.ts +18 -6
  254. package/lib/typescript/module/ui/components/authChooser/primitives.d.ts.map +1 -1
  255. package/lib/typescript/module/ui/components/authChooser/signInProgress.d.ts.map +1 -1
  256. package/lib/typescript/module/ui/components/authChooser/types.d.ts +33 -1
  257. package/lib/typescript/module/ui/components/authChooser/types.d.ts.map +1 -1
  258. package/lib/typescript/module/ui/context/OxyContext.d.ts +35 -4
  259. package/lib/typescript/module/ui/context/OxyContext.d.ts.map +1 -1
  260. package/lib/typescript/module/ui/context/hooks/useAuthOperations.d.ts +8 -12
  261. package/lib/typescript/module/ui/context/hooks/useAuthOperations.d.ts.map +1 -1
  262. package/lib/typescript/module/ui/context/oxyContextHelpers.d.ts +0 -2
  263. package/lib/typescript/module/ui/context/oxyContextHelpers.d.ts.map +1 -1
  264. package/lib/typescript/module/ui/context/oxyContextTypes.d.ts +9 -1
  265. package/lib/typescript/module/ui/context/oxyContextTypes.d.ts.map +1 -1
  266. package/lib/typescript/module/ui/context/useOxyAccountGraph.d.ts +1 -3
  267. package/lib/typescript/module/ui/context/useOxyAccountGraph.d.ts.map +1 -1
  268. package/lib/typescript/module/ui/hooks/accountDialogSnapshot.d.ts +15 -0
  269. package/lib/typescript/module/ui/hooks/accountDialogSnapshot.d.ts.map +1 -0
  270. package/lib/typescript/module/ui/hooks/mutations/useAccountMutations.d.ts.map +1 -1
  271. package/lib/typescript/module/ui/hooks/useDeviceSwitcher.d.ts +49 -0
  272. package/lib/typescript/module/ui/hooks/useDeviceSwitcher.d.ts.map +1 -0
  273. package/lib/typescript/module/ui/hooks/useI18n.d.ts +13 -0
  274. package/lib/typescript/module/ui/hooks/useI18n.d.ts.map +1 -1
  275. package/lib/typescript/module/ui/hooks/useSessionManagement.d.ts +23 -18
  276. package/lib/typescript/module/ui/hooks/useSessionManagement.d.ts.map +1 -1
  277. package/lib/typescript/module/ui/index.d.ts +1 -2
  278. package/lib/typescript/module/ui/index.d.ts.map +1 -1
  279. package/lib/typescript/module/ui/navigation/routes.d.ts +15 -1
  280. package/lib/typescript/module/ui/navigation/routes.d.ts.map +1 -1
  281. package/lib/typescript/module/ui/navigation/surfaces.d.ts.map +1 -1
  282. package/lib/typescript/module/ui/runtime/createOxyRuntime.d.ts +144 -0
  283. package/lib/typescript/module/ui/runtime/createOxyRuntime.d.ts.map +1 -0
  284. package/lib/typescript/module/ui/runtime/index.d.ts +16 -0
  285. package/lib/typescript/module/ui/runtime/index.d.ts.map +1 -0
  286. package/lib/typescript/module/ui/runtime/runtimeContext.d.ts +43 -0
  287. package/lib/typescript/module/ui/runtime/runtimeContext.d.ts.map +1 -0
  288. package/lib/typescript/module/ui/runtime/types.d.ts +89 -0
  289. package/lib/typescript/module/ui/runtime/types.d.ts.map +1 -0
  290. package/lib/typescript/module/ui/runtime/useRuntimeSnapshot.d.ts +23 -0
  291. package/lib/typescript/module/ui/runtime/useRuntimeSnapshot.d.ts.map +1 -0
  292. package/lib/typescript/module/ui/screens/AccountMembersScreen.d.ts.map +1 -1
  293. package/lib/typescript/module/ui/screens/CreateAccountScreen.d.ts.map +1 -1
  294. package/lib/typescript/module/ui/screens/trust/TrustLeaderboardScreen.d.ts.map +1 -1
  295. package/lib/typescript/module/ui/screens/trust/TrustRulesScreen.d.ts.map +1 -1
  296. package/lib/typescript/module/ui/server.d.ts +0 -1
  297. package/lib/typescript/module/ui/server.d.ts.map +1 -1
  298. package/lib/typescript/module/ui/session/authStore.d.ts +60 -9
  299. package/lib/typescript/module/ui/session/authStore.d.ts.map +1 -1
  300. package/lib/typescript/module/ui/session/sharedDeviceCredentialStore.d.ts +32 -0
  301. package/lib/typescript/module/ui/session/sharedDeviceCredentialStore.d.ts.map +1 -0
  302. package/lib/typescript/module/ui/stores/authStore.d.ts +49 -5
  303. package/lib/typescript/module/ui/stores/authStore.d.ts.map +1 -1
  304. package/lib/typescript/module/ui/stores/followTargetStore.d.ts +8 -1
  305. package/lib/typescript/module/ui/stores/followTargetStore.d.ts.map +1 -1
  306. package/lib/typescript/module/ui/types/navigation.d.ts +26 -0
  307. package/lib/typescript/module/ui/types/navigation.d.ts.map +1 -1
  308. package/lib/typescript/module/ui/utils/avatarUtils.d.ts +2 -10
  309. package/lib/typescript/module/ui/utils/avatarUtils.d.ts.map +1 -1
  310. package/package.json +8 -8
  311. package/plugins/withSharedDeviceSessionProvider.js +102 -0
  312. package/plugins/withSharedDeviceSessionReader.js +57 -0
  313. package/src/__tests__/esmSourcePurity.test.ts +61 -0
  314. package/src/index.ts +36 -9
  315. package/src/ui/boot/runProviderColdBoot.ts +7 -0
  316. package/src/ui/client.ts +1 -2
  317. package/src/ui/components/OxyAccountDialogScreen.tsx +10 -29
  318. package/src/ui/components/OxyAuthChooser.tsx +149 -50
  319. package/src/ui/components/OxyProvider.tsx +7 -5
  320. package/src/ui/components/SurfaceScreen.tsx +28 -4
  321. package/src/ui/components/__tests__/followTargetButton.test.ts +39 -0
  322. package/src/ui/components/authChooser/AccountsMenuView.tsx +246 -96
  323. package/src/ui/components/authChooser/SignInEntryView.tsx +31 -8
  324. package/src/ui/components/authChooser/primitives.tsx +37 -23
  325. package/src/ui/components/authChooser/signInProgress.ts +4 -0
  326. package/src/ui/components/authChooser/types.ts +34 -1
  327. package/src/ui/context/OxyContext.tsx +269 -324
  328. package/src/ui/context/hooks/useAuthOperations.ts +32 -35
  329. package/src/ui/context/oxyContextHelpers.ts +0 -30
  330. package/src/ui/context/oxyContextTypes.ts +9 -1
  331. package/src/ui/context/useOxyAccountGraph.ts +5 -19
  332. package/src/ui/hooks/accountDialogSnapshot.ts +37 -0
  333. package/src/ui/hooks/mutations/useAccountMutations.ts +0 -19
  334. package/src/ui/hooks/queries/__tests__/userCache.test.ts +12 -1
  335. package/src/ui/hooks/useDeviceSwitcher.ts +110 -0
  336. package/src/ui/hooks/useI18n.ts +23 -3
  337. package/src/ui/hooks/useSessionManagement.ts +62 -211
  338. package/src/ui/index.ts +1 -2
  339. package/src/ui/navigation/routes.ts +85 -75
  340. package/src/ui/navigation/surfaces.ts +6 -9
  341. package/src/ui/runtime/createOxyRuntime.ts +623 -0
  342. package/src/ui/runtime/index.ts +34 -0
  343. package/src/ui/runtime/runtimeContext.tsx +111 -0
  344. package/src/ui/runtime/types.ts +110 -0
  345. package/src/ui/runtime/useRuntimeSnapshot.ts +52 -0
  346. package/src/ui/screens/AccountMembersScreen.tsx +6 -5
  347. package/src/ui/screens/CreateAccountScreen.tsx +3 -16
  348. package/src/ui/screens/trust/TrustCenterScreen.tsx +7 -7
  349. package/src/ui/screens/trust/TrustLeaderboardScreen.tsx +4 -5
  350. package/src/ui/screens/trust/TrustRewardsScreen.tsx +1 -1
  351. package/src/ui/screens/trust/TrustRulesScreen.tsx +3 -2
  352. package/src/ui/server.ts +0 -1
  353. package/src/ui/session/__tests__/authStore.test.ts +90 -0
  354. package/src/ui/session/__tests__/sharedDeviceCredentialStore.test.ts +289 -0
  355. package/src/ui/session/authStore.ts +78 -9
  356. package/src/ui/session/sharedDeviceCredentialStore.ts +318 -0
  357. package/src/ui/stores/authStore.ts +171 -43
  358. package/src/ui/stores/followTargetStore.ts +24 -1
  359. package/src/ui/types/navigation.ts +26 -0
  360. package/src/ui/utils/avatarUtils.ts +2 -37
  361. package/lib/commonjs/ui/hooks/useSwitchableAccounts.js +0 -64
  362. package/lib/commonjs/ui/hooks/useSwitchableAccounts.js.map +0 -1
  363. package/lib/commonjs/ui/screens/trust/trustTier.js +0 -23
  364. package/lib/commonjs/ui/screens/trust/trustTier.js.map +0 -1
  365. package/lib/commonjs/ui/stores/accountStore.js +0 -221
  366. package/lib/commonjs/ui/stores/accountStore.js.map +0 -1
  367. package/lib/module/ui/hooks/useSwitchableAccounts.js +0 -60
  368. package/lib/module/ui/hooks/useSwitchableAccounts.js.map +0 -1
  369. package/lib/module/ui/screens/trust/trustTier.js +0 -19
  370. package/lib/module/ui/screens/trust/trustTier.js.map +0 -1
  371. package/lib/module/ui/stores/accountStore.js +0 -213
  372. package/lib/module/ui/stores/accountStore.js.map +0 -1
  373. package/lib/typescript/commonjs/ui/hooks/useSwitchableAccounts.d.ts +0 -23
  374. package/lib/typescript/commonjs/ui/hooks/useSwitchableAccounts.d.ts.map +0 -1
  375. package/lib/typescript/commonjs/ui/screens/trust/trustTier.d.ts +0 -9
  376. package/lib/typescript/commonjs/ui/screens/trust/trustTier.d.ts.map +0 -1
  377. package/lib/typescript/commonjs/ui/stores/accountStore.d.ts +0 -27
  378. package/lib/typescript/commonjs/ui/stores/accountStore.d.ts.map +0 -1
  379. package/lib/typescript/module/ui/hooks/useSwitchableAccounts.d.ts +0 -23
  380. package/lib/typescript/module/ui/hooks/useSwitchableAccounts.d.ts.map +0 -1
  381. package/lib/typescript/module/ui/screens/trust/trustTier.d.ts +0 -9
  382. package/lib/typescript/module/ui/screens/trust/trustTier.d.ts.map +0 -1
  383. package/lib/typescript/module/ui/stores/accountStore.d.ts +0 -27
  384. package/lib/typescript/module/ui/stores/accountStore.d.ts.map +0 -1
  385. package/src/ui/hooks/useSwitchableAccounts.ts +0 -75
  386. package/src/ui/screens/trust/trustTier.ts +0 -20
  387. package/src/ui/stores/accountStore.ts +0 -264
@@ -0,0 +1,111 @@
1
+ import { createContext, useContext } from 'react';
2
+ import type { DeviceDirectory } from '@oxyhq/contracts';
3
+ import type { DeviceContext, User } from '@oxyhq/core';
4
+ import type { OxyRuntime } from './createOxyRuntime';
5
+ import type { OxyRuntimeStatus } from './types';
6
+ import { useRuntimeSelector, useRuntimeSnapshot } from './useRuntimeSnapshot';
7
+
8
+ /**
9
+ * The runtime reference itself, as a context value that NEVER changes identity
10
+ * (ADR 0004).
11
+ *
12
+ * It is deliberately a second context beside the big `OxyContextState` one.
13
+ * That value is rebuilt whenever any of its fifty-odd members moves — a locale,
14
+ * a dialog opening — and every hook reading it re-renders with it. Hooks
15
+ * hanging off this one subscribe to the runtime with a selector instead, so
16
+ * only a change to what they actually selected wakes them. Retiring the wide
17
+ * context is Phase 8; this is what its replacements are built on.
18
+ */
19
+ const OxyRuntimeHandleContext = createContext<OxyRuntime | null>(null);
20
+
21
+ export const OxyRuntimeHandleProvider = OxyRuntimeHandleContext.Provider;
22
+
23
+ const RUNTIME_MISSING_MESSAGE =
24
+ 'useOxyRuntime() was called outside <OxyProvider>. Mount <OxyProvider clientId="…"> above this component.';
25
+
26
+ export class OxyRuntimeMissingError extends Error {
27
+ readonly code = 'oxy_runtime_missing';
28
+
29
+ constructor() {
30
+ super(RUNTIME_MISSING_MESSAGE);
31
+ this.name = 'OxyRuntimeMissingError';
32
+ }
33
+ }
34
+
35
+ /** The runtime this provider owns. THROWS when no `<OxyProvider>` is mounted. */
36
+ export function useOxyRuntime(): OxyRuntime {
37
+ const runtime = useContext(OxyRuntimeHandleContext);
38
+ if (runtime === null) {
39
+ throw new OxyRuntimeMissingError();
40
+ }
41
+ return runtime;
42
+ }
43
+
44
+ export interface ActiveAccount {
45
+ /**
46
+ * The human whose authentication backs the session — the audit actor. Equal
47
+ * to {@link ActiveAccount.account} unless a delegated context is active.
48
+ */
49
+ principal: User | null;
50
+ /** The account the session acts AS — what a profile header renders. */
51
+ account: User | null;
52
+ /** The resolved `principal acting as account` pair, when a directory is held. */
53
+ context: DeviceContext | null;
54
+ /** Whether the actor and the subject are different accounts. */
55
+ isDelegated: boolean;
56
+ status: OxyRuntimeStatus;
57
+ }
58
+
59
+ function selectActiveAccount(snapshot: {
60
+ principal: User | null;
61
+ account: User | null;
62
+ activeContext: DeviceContext | null;
63
+ status: OxyRuntimeStatus;
64
+ }): ActiveAccount {
65
+ return {
66
+ principal: snapshot.principal,
67
+ account: snapshot.account,
68
+ context: snapshot.activeContext,
69
+ isDelegated: snapshot.activeContext?.isDelegated ?? false,
70
+ status: snapshot.status,
71
+ };
72
+ }
73
+
74
+ function activeAccountsEqual(a: ActiveAccount, b: ActiveAccount): boolean {
75
+ return (
76
+ a.principal === b.principal &&
77
+ a.account === b.account &&
78
+ a.context === b.context &&
79
+ a.isDelegated === b.isDelegated &&
80
+ a.status === b.status
81
+ );
82
+ }
83
+
84
+ /**
85
+ * Who this app is running as, with the actor and the subject kept apart.
86
+ *
87
+ * Unlike `useOxy()`, this re-renders only when one of those five facts moves —
88
+ * a locale change, a dialog opening or a session-list refresh does not reach it.
89
+ */
90
+ export function useActiveAccount(): ActiveAccount {
91
+ return useRuntimeSelector(useOxyRuntime(), selectActiveAccount, activeAccountsEqual);
92
+ }
93
+
94
+ const selectDirectory = (snapshot: { device: DeviceDirectory | null }): DeviceDirectory | null =>
95
+ snapshot.device;
96
+
97
+ /**
98
+ * The device directory — every principal on this device and the contexts each
99
+ * may act as (ADR 0002).
100
+ *
101
+ * `null` until something calls `runtime.refreshDirectory()`. A client that
102
+ * never asks for one never pays for the round trip.
103
+ */
104
+ export function useDeviceDirectory(): DeviceDirectory | null {
105
+ return useRuntimeSelector(useOxyRuntime(), selectDirectory);
106
+ }
107
+
108
+ /** The whole runtime snapshot. Prefer a narrower hook where one exists. */
109
+ export function useOxySnapshot(): ReturnType<OxyRuntime['getSnapshot']> {
110
+ return useRuntimeSnapshot(useOxyRuntime());
111
+ }
@@ -0,0 +1,110 @@
1
+ import type { DeviceDirectory, DeviceSessionState } from '@oxyhq/contracts';
2
+ import type { ClientSession, DeviceContext, User } from '@oxyhq/core';
3
+
4
+ /**
5
+ * The runtime's coarse verdict about this device's session.
6
+ *
7
+ * `'booting'` is NOT "signed out but we are still looking": it is the honest
8
+ * "undetermined" that every readiness gate in the SDK exists to express, and it
9
+ * ends exactly once at the first cold-boot resolution. `'error'` is reserved for
10
+ * a resolved boot that produced no account AND recorded a failure — a failed
11
+ * sign-in against a signed-out device is `'signed_out'` with an `error`, because
12
+ * the device really is signed out.
13
+ */
14
+ export type OxyRuntimeStatus = 'booting' | 'authenticated' | 'signed_out' | 'error';
15
+
16
+ /**
17
+ * Whether a bearer usable for private calls is planted right now.
18
+ *
19
+ * `'refreshing'` covers both halves of the gap the SDK already tracked with two
20
+ * separate booleans: a bearer that is present but whose readiness gate is shut
21
+ * (a commit in flight), and an authenticated account whose bearer has been
22
+ * invalidated and is being re-minted. Both mean the same thing to a caller —
23
+ * wait, do not treat this as signed out.
24
+ */
25
+ export type OxyTokenStatus = 'missing' | 'refreshing' | 'ready' | 'error';
26
+
27
+ export interface OxyRuntimeError {
28
+ message: string;
29
+ code: string;
30
+ }
31
+
32
+ /**
33
+ * The ONE observable state of an `OxyRuntime` (ADR 0004).
34
+ *
35
+ * Frozen and referentially stable: a new object is published only when
36
+ * something actually changed, so `useSyncExternalStore` can compare by identity
37
+ * and a selector over an unchanged field never re-renders.
38
+ *
39
+ * Every field is either a fact the runtime owns or a pure derivation of one.
40
+ * There is no second writable store: `sessions`, `activeSessionId`, `status`
41
+ * and `tokenStatus` are computed by the one snapshot builder, so two of them can
42
+ * never disagree about the same device.
43
+ */
44
+ export interface OxyRuntimeSnapshot {
45
+ status: OxyRuntimeStatus;
46
+
47
+ /**
48
+ * The device DIRECTORY (ADR 0002) — principals and the contexts each may act
49
+ * as. `null` until something asks for one; the flat lane never pays for it.
50
+ */
51
+ device: DeviceDirectory | null;
52
+
53
+ /**
54
+ * The flat, server-authoritative device state. Kept beside {@link device}
55
+ * because it is what the compatibility projections below are derived from,
56
+ * and because the two describe the same device at the same `revision`.
57
+ */
58
+ deviceState: DeviceSessionState | null;
59
+
60
+ /** The active `principal acting as account` pair, when a directory is held. */
61
+ activeContext: DeviceContext | null;
62
+
63
+ /**
64
+ * The human whose authentication backs the session — the audit actor.
65
+ *
66
+ * Equal to {@link account} on a device with no directory and on any
67
+ * non-delegated context: the flat lane cannot tell the two apart, and saying
68
+ * so by making them the same object is more honest than leaving this `null`.
69
+ */
70
+ principal: User | null;
71
+
72
+ /** The account the session acts AS — what a profile header renders. */
73
+ account: User | null;
74
+
75
+ tokenStatus: OxyTokenStatus;
76
+
77
+ /**
78
+ * Whether the first cold boot has concluded. Monotonic: once `true` it never
79
+ * reverts, so a later transient signed-out state is never mistaken for
80
+ * "still booting".
81
+ */
82
+ authResolved: boolean;
83
+
84
+ /** A context activation / account switch is in flight. */
85
+ switching: boolean;
86
+
87
+ error: OxyRuntimeError | null;
88
+
89
+ // ── Compatibility projections ────────────────────────────────────────────
90
+ // Derived, never separately written. They exist because every app still
91
+ // renders the flat session list; Phase 7 moves them onto the directory.
92
+
93
+ sessions: ClientSession[];
94
+ activeSessionId: string | null;
95
+
96
+ /** A sign-in / sign-out operation is in flight. */
97
+ isLoading: boolean;
98
+
99
+ /** The local display/bookkeeping storage has resolved. */
100
+ storageReady: boolean;
101
+
102
+ /** A bearer is planted on the client instance right now. */
103
+ hasAccessToken: boolean;
104
+
105
+ /**
106
+ * The commit gate. Shut while a session commit is mid-flight so a consumer
107
+ * cannot fire a private call between the token landing and the projection.
108
+ */
109
+ tokenReady: boolean;
110
+ }
@@ -0,0 +1,52 @@
1
+ import { useCallback, useRef, useSyncExternalStore } from 'react';
2
+ import type { OxyRuntime } from './createOxyRuntime';
3
+ import type { OxyRuntimeSnapshot } from './types';
4
+
5
+ /**
6
+ * Subscribe to the whole runtime snapshot.
7
+ *
8
+ * The runtime publishes a frozen object only when a fact actually changed, so
9
+ * identity comparison is exact: a locale change, a dialog opening or an
10
+ * unrelated query settling does not wake anything subscribed here.
11
+ */
12
+ export function useRuntimeSnapshot(runtime: OxyRuntime): OxyRuntimeSnapshot {
13
+ return useSyncExternalStore(runtime.subscribe, runtime.getSnapshot, runtime.getSnapshot);
14
+ }
15
+
16
+ /**
17
+ * Subscribe to one derived value of the runtime snapshot.
18
+ *
19
+ * The selection is cached against the snapshot it was computed from, which is
20
+ * what makes a selector returning a fresh object (`{user, isAuthenticated}`)
21
+ * safe here: `useSyncExternalStore` calls `getSnapshot` several times per
22
+ * commit and would otherwise see a new object every call and loop.
23
+ *
24
+ * `selector` must be stable — hoist it to module scope or wrap it in
25
+ * `useCallback`. An inline arrow re-subscribes on every render.
26
+ */
27
+ export function useRuntimeSelector<T>(
28
+ runtime: OxyRuntime,
29
+ selector: (snapshot: OxyRuntimeSnapshot) => T,
30
+ isEqual?: (a: T, b: T) => boolean,
31
+ ): T {
32
+ const cache = useRef<{ snapshot: OxyRuntimeSnapshot; value: T } | null>(null);
33
+
34
+ const getSelection = useCallback((): T => {
35
+ const snapshot = runtime.getSnapshot();
36
+ const cached = cache.current;
37
+ if (cached !== null && cached.snapshot === snapshot) {
38
+ return cached.value;
39
+ }
40
+ const value = selector(snapshot);
41
+ if (cached !== null && isEqual?.(cached.value, value) === true) {
42
+ // Same value under the caller's equality: keep the PREVIOUS reference so a
43
+ // structurally-equal recomputation does not read as a change.
44
+ cache.current = { snapshot, value: cached.value };
45
+ return cached.value;
46
+ }
47
+ cache.current = { snapshot, value };
48
+ return value;
49
+ }, [runtime, selector, isEqual]);
50
+
51
+ return useSyncExternalStore(runtime.subscribe, getSelection, getSelection);
52
+ }
@@ -15,7 +15,7 @@ import { Button } from '@oxyhq/bloom/button';
15
15
  import { TextField, TextFieldInput } from '@oxyhq/bloom/text-field';
16
16
  import { Divider } from '@oxyhq/bloom/divider';
17
17
  import type { AccountMember, AccountRole } from '@oxyhq/core';
18
- import { getNormalizedUserHandle } from '@oxyhq/core';
18
+ import { accountRoleLabel, getNormalizedUserHandle } from '@oxyhq/core';
19
19
  import type { BaseScreenProps } from '../types/navigation';
20
20
  import { useOxy } from '../context/OxyContext';
21
21
  import { useI18n } from '../hooks/useI18n';
@@ -42,7 +42,7 @@ const isUserNotFound = (error: unknown): boolean => {
42
42
  const AccountMembersScreen: React.FC<BaseScreenProps> = ({ onClose, goBack, accountId }) => {
43
43
  const bloomTheme = useTheme();
44
44
  const colors = bloomTheme.colors;
45
- const { t } = useI18n();
45
+ const { t, locale } = useI18n();
46
46
 
47
47
  useSurfaceHeader({
48
48
  title: t('accounts.members.title') || 'Members',
@@ -53,9 +53,10 @@ const AccountMembersScreen: React.FC<BaseScreenProps> = ({ onClose, goBack, acco
53
53
 
54
54
  const id = typeof accountId === 'string' ? accountId : '';
55
55
 
56
- const roleLabel = useCallback((role: AccountRole): string => {
57
- return t(`accounts.roles.${role}.label`) || role.charAt(0).toUpperCase() + role.slice(1);
58
- }, [t]);
56
+ const roleLabel = useCallback(
57
+ (role: AccountRole): string => accountRoleLabel(locale, role),
58
+ [locale],
59
+ );
59
60
 
60
61
  const accountQuery = useQuery({
61
62
  queryKey: ['accounts', 'detail', id],
@@ -3,7 +3,7 @@ import { useState, useCallback, useRef, useEffect } from 'react';
3
3
  import { View, ActivityIndicator } from 'react-native';
4
4
  import Ionicons from '@expo/vector-icons/Ionicons';
5
5
  import type { AccountCategoryId, AccountKind, CreateAccountInput } from '@oxyhq/core';
6
- import { DISPLAY_NAME_INVALID_MESSAGE, isValidDisplayName, MAX_ACCOUNT_CATEGORIES, MAX_DISPLAY_NAME_LENGTH, SELECTABLE_ACCOUNT_CATEGORY_IDS } from '@oxyhq/core';
6
+ import { accountCategoryLabel, DISPLAY_NAME_INVALID_MESSAGE, isValidDisplayName, MAX_ACCOUNT_CATEGORIES, MAX_DISPLAY_NAME_LENGTH, SELECTABLE_ACCOUNT_CATEGORY_IDS } from '@oxyhq/core';
7
7
  import type { BaseScreenProps } from '../types/navigation';
8
8
  import { useI18n } from '../hooks/useI18n';
9
9
  import { useSurfaceHeader } from '../hooks/useSurfaceHeader';
@@ -83,19 +83,6 @@ const kindDescription = (
83
83
  }
84
84
  };
85
85
 
86
- /**
87
- * The visible label for a category id.
88
- *
89
- * A lookup, deliberately not a `switch` with a `default`: a `default` would let
90
- * an id with no translation render as some OTHER category's label, silently and
91
- * only in the languages that are missing it. Falling back to the raw id is ugly
92
- * and correct — it is visibly wrong, and it names the missing key.
93
- */
94
- const accountCategoryLabel = (
95
- t: (key: string, vars?: Record<string, string | number>) => string,
96
- category: AccountCategoryId,
97
- ): string => t(`accounts.accountCategory.${category}`) || category;
98
-
99
86
  /**
100
87
  * Only the SELECTABLE ids are offered. The full `ACCOUNT_CATEGORY_IDS` still
101
88
  * contains withdrawn ones so that accounts already carrying them keep working —
@@ -116,7 +103,7 @@ const CreateAccountScreen: React.FC<BaseScreenProps> = ({
116
103
  }) => {
117
104
  const bloomTheme = useTheme();
118
105
  const { oxyServices, createAccount, switchToAccount } = useOxy();
119
- const { t } = useI18n();
106
+ const { t, locale } = useI18n();
120
107
 
121
108
  useSurfaceHeader({
122
109
  title: t('accounts.create.title') || 'Create account',
@@ -337,7 +324,7 @@ const CreateAccountScreen: React.FC<BaseScreenProps> = ({
337
324
  {ACCOUNT_CATEGORY_OPTIONS.map((option) => {
338
325
  const position = accountCategories.indexOf(option);
339
326
  const selected = position >= 0;
340
- const label = accountCategoryLabel(t, option);
327
+ const label = accountCategoryLabel(locale, option);
341
328
  return (
342
329
  <SettingsListItem
343
330
  key={option}
@@ -13,7 +13,7 @@ import { Loading } from '@oxyhq/bloom/loading';
13
13
  import { useI18n } from '../../hooks/useI18n';
14
14
  import { useSurfaceHeader } from '../../hooks/useSurfaceHeader';
15
15
  import { useOxy } from '../../context/OxyContext';
16
- import { getTrustTierLabel } from './trustTier';
16
+ import { trustTierLabel } from '@oxyhq/core';
17
17
 
18
18
  const TrustCenterScreen: React.FC<BaseScreenProps> = ({
19
19
  navigate,
@@ -21,7 +21,7 @@ const TrustCenterScreen: React.FC<BaseScreenProps> = ({
21
21
  // Reputation/trust is the ACTIVE account's standing (the org/project/bot
22
22
  // when switched, else the personal user).
23
23
  const { user, oxyServices, isAuthenticated } = useOxy();
24
- const { t } = useI18n();
24
+ const { t, locale } = useI18n();
25
25
  const [reputationTotal, setReputationTotal] = useState<number | null>(null);
26
26
  const [trustTier, setTrustTier] = useState<TrustTier | null>(null);
27
27
  const [transactions, setTransactions] = useState<ReputationTransaction[]>([]);
@@ -53,9 +53,9 @@ const TrustCenterScreen: React.FC<BaseScreenProps> = ({
53
53
  .finally(() => setIsLoading(false));
54
54
  }, [user, oxyServices, t]);
55
55
 
56
- const trustTierLabel = useMemo(
57
- () => (trustTier ? getTrustTierLabel(trustTier, t) : null),
58
- [trustTier, t],
56
+ const resolvedTrustTierLabel = useMemo(
57
+ () => (trustTier ? trustTierLabel(locale, trustTier) : null),
58
+ [trustTier, locale],
59
59
  );
60
60
 
61
61
  const title = t('trust.center.title') || 'Trust Center';
@@ -87,7 +87,7 @@ const TrustCenterScreen: React.FC<BaseScreenProps> = ({
87
87
  <Text className="text-text-tertiary text-base mt-space-2 mb-space-12">
88
88
  {t('trust.center.balance') || 'Reputation Balance'}
89
89
  </Text>
90
- {trustTierLabel ? (
90
+ {resolvedTrustTierLabel ? (
91
91
  <Chip
92
92
  variant="soft"
93
93
  color="primary"
@@ -99,7 +99,7 @@ const TrustCenterScreen: React.FC<BaseScreenProps> = ({
99
99
  />
100
100
  }
101
101
  >
102
- {trustTierLabel}
102
+ {resolvedTrustTierLabel}
103
103
  </Chip>
104
104
  ) : null}
105
105
  <Text
@@ -8,7 +8,7 @@ import {
8
8
  TouchableOpacity,
9
9
  } from 'react-native';
10
10
  import type { ReputationLeaderboardEntry } from '@oxyhq/contracts';
11
- import { getNormalizedUserHandle, logger } from '@oxyhq/core';
11
+ import { getNormalizedUserHandle, logger, trustTierLabel } from '@oxyhq/core';
12
12
  import { useTheme } from '@oxyhq/bloom/theme';
13
13
  import { H6, Text } from '@oxyhq/bloom/typography';
14
14
  import { Chip } from '@oxyhq/bloom/chip';
@@ -19,7 +19,6 @@ import { Avatar } from '@oxyhq/bloom/avatar';
19
19
  import { useI18n } from '../../hooks/useI18n';
20
20
  import { useSurfaceHeader } from '../../hooks/useSurfaceHeader';
21
21
  import { useOxy } from '../../context/OxyContext';
22
- import { getTrustTierLabel } from './trustTier';
23
22
 
24
23
  const AVATAR_SIZE = 40;
25
24
  const EMPTY_ICON_SIZE = 64;
@@ -29,7 +28,7 @@ const PODIUM_RANK = 3;
29
28
 
30
29
  const TrustLeaderboardScreen: React.FC<BaseScreenProps> = ({ navigate }) => {
31
30
  const { oxyServices, user: currentUser } = useOxy();
32
- const { t } = useI18n();
31
+ const { t, locale } = useI18n();
33
32
  const bloomTheme = useTheme();
34
33
 
35
34
  const [leaderboard, setLeaderboard] = useState<ReputationLeaderboardEntry[]>([]);
@@ -106,7 +105,7 @@ const TrustLeaderboardScreen: React.FC<BaseScreenProps> = ({ navigate }) => {
106
105
  </Text>
107
106
  <View style={styles.tierRow} className="mt-space-4">
108
107
  <Chip size="small" variant="soft" color={isPodium ? 'primary' : 'default'}>
109
- {getTrustTierLabel(item.trustTier, t)}
108
+ {trustTierLabel(locale, item.trustTier)}
110
109
  </Chip>
111
110
  </View>
112
111
  </View>
@@ -116,7 +115,7 @@ const TrustLeaderboardScreen: React.FC<BaseScreenProps> = ({ navigate }) => {
116
115
  </TouchableOpacity>
117
116
  );
118
117
  },
119
- [oxyServices, currentUserId, handleEntryPress, t],
118
+ [oxyServices, currentUserId, handleEntryPress, locale],
120
119
  );
121
120
 
122
121
  const keyExtractor = useCallback(
@@ -26,7 +26,7 @@ interface Achievement {
26
26
  }
27
27
 
28
28
  /**
29
- * Per-achievement identity tints. Like the trust-tier palette in `trustTier.ts`,
29
+ * Per-achievement identity tints. Like the trust-tier palette in `trustTierLabels`,
30
30
  * these are data, not theme surfaces — they brand each badge regardless of theme.
31
31
  */
32
32
  const ACHIEVEMENT_TINT = {
@@ -4,6 +4,7 @@ import { View, Text } from 'react-native';
4
4
  import { SettingsListGroup, SettingsListItem } from '@oxyhq/bloom/settings-list';
5
5
  import { Chip } from '@oxyhq/bloom/chip';
6
6
  import { useTheme } from '@oxyhq/bloom/theme';
7
+ import { reputationCategoryLabel } from '@oxyhq/core';
7
8
  import type { ReputationRule, ReputationCategory } from '@oxyhq/contracts';
8
9
  import type { BaseScreenProps } from '../../types/navigation';
9
10
  import { useSurfaceHeader } from '../../hooks/useSurfaceHeader';
@@ -24,7 +25,7 @@ const CATEGORY_ORDER: ReputationCategory[] = [
24
25
 
25
26
  const TrustRulesScreen: React.FC<BaseScreenProps> = () => {
26
27
  const { oxyServices } = useOxy();
27
- const { t } = useI18n();
28
+ const { t, locale } = useI18n();
28
29
 
29
30
  useSurfaceHeader({
30
31
  title: t('trust.rules.title') || 'Trust Rules',
@@ -82,7 +83,7 @@ const TrustRulesScreen: React.FC<BaseScreenProps> = () => {
82
83
  {groupedRules.map(({ category, items }) => (
83
84
  <SettingsListGroup
84
85
  key={category}
85
- title={t(`trust.rules.categories.${category}`) || category}
86
+ title={reputationCategoryLabel(locale, category)}
86
87
  >
87
88
  {items.map((rule) => (
88
89
  <SettingsListItem
package/src/ui/server.ts CHANGED
@@ -34,7 +34,6 @@ export const ProfileScreen = noopComponent;
34
34
 
35
35
  // Stores (return empty objects)
36
36
  export const useAuthStore = noopHook;
37
- export const useAccountStore = noopHook;
38
37
 
39
38
  // Toast (noop)
40
39
  export const toast = Object.assign(
@@ -0,0 +1,90 @@
1
+ /**
2
+ * Which apps mirror their device credential into the device-wide shared slot.
3
+ *
4
+ * The mirror is what makes a later-installed official app able to JOIN this
5
+ * device's session instead of asking for the Commons identity key. It runs on
6
+ * native, in `'account'` mode only — the identity vault is excluded so that a
7
+ * background persist inside the vault can never change which session five other
8
+ * apps boot into.
9
+ */
10
+ import type { AuthStateStore } from '@oxyhq/core';
11
+
12
+ const CRED_STATE = { sessionId: 'sess-1', userId: 'user-1', deviceId: 'dev-1', deviceSecret: 'ds-1' };
13
+
14
+ /** Track every credential handed to the shared slot by the store under test. */
15
+ function makeSharedSpy() {
16
+ const published: { deviceId: string; deviceSecret: string }[] = [];
17
+ return {
18
+ published,
19
+ store: {
20
+ read: async () => ({ state: 'absent' as const }),
21
+ publish: async (credential: { deviceId: string; deviceSecret: string }) => {
22
+ published.push(credential);
23
+ return true;
24
+ },
25
+ clear: async () => undefined,
26
+ },
27
+ };
28
+ }
29
+
30
+ /**
31
+ * Build the platform store with the native seams stubbed. `jest.resetModules()`
32
+ * + `require` rather than `jest.isolateModules` for the same reason as
33
+ * `sharedDeviceCredentialStore.test.ts`: a factory registered inside an isolate
34
+ * leaked into the next one.
35
+ */
36
+ function loadAuthStore(
37
+ os: 'ios' | 'android' | 'web',
38
+ sessionMode: 'account' | 'identity',
39
+ shared: ReturnType<typeof makeSharedSpy>,
40
+ ): AuthStateStore {
41
+ jest.resetModules();
42
+ jest.doMock('../sharedDeviceCredentialStore', () => ({
43
+ createPlatformSharedDeviceCredentialStore: () => (os === 'web' ? null : shared.store),
44
+ }));
45
+ const rn = require('react-native') as { Platform: { OS: string } };
46
+ rn.Platform.OS = os;
47
+ // `authStore` selects web-vs-native with `isReactNative()`, which reads
48
+ // `navigator.product` — NOT `Platform.OS`. Setting only the latter leaves it on
49
+ // the web branch, where nothing mirrors and every case passes for the wrong
50
+ // reason.
51
+ Object.defineProperty(globalThis.navigator, 'product', {
52
+ value: os === 'web' ? 'Gecko' : 'ReactNative',
53
+ configurable: true,
54
+ });
55
+ const mod = require('../authStore') as typeof import('../authStore');
56
+ return mod.createPlatformAuthStateStore({ sessionMode });
57
+ }
58
+
59
+ afterEach(() => {
60
+ jest.dontMock('../sharedDeviceCredentialStore');
61
+ Object.defineProperty(globalThis.navigator, 'product', { value: 'Gecko', configurable: true });
62
+ jest.resetModules();
63
+ });
64
+
65
+ describe('createPlatformAuthStateStore', () => {
66
+ test('an ordinary native app publishes its credential to the shared slot', async () => {
67
+ const shared = makeSharedSpy();
68
+ const store = loadAuthStore('android', 'account', shared);
69
+ await store.save(CRED_STATE);
70
+ expect(shared.published).toEqual([{ deviceId: 'dev-1', deviceSecret: 'ds-1' }]);
71
+ });
72
+
73
+ test('the identity vault does NOT publish', async () => {
74
+ // The vault's credential is a perfectly valid device credential, so this is a
75
+ // deliberate abstention, not an impossibility: publishing it would let every
76
+ // ordinary app on the device join the vault's session as a side effect of the
77
+ // vault persisting a token.
78
+ const shared = makeSharedSpy();
79
+ const store = loadAuthStore('android', 'identity', shared);
80
+ await store.save(CRED_STATE);
81
+ expect(shared.published).toEqual([]);
82
+ });
83
+
84
+ test('web has no shared slot to publish into', async () => {
85
+ const shared = makeSharedSpy();
86
+ const store = loadAuthStore('web', 'account', shared);
87
+ await store.save(CRED_STATE);
88
+ expect(shared.published).toEqual([]);
89
+ });
90
+ });