@oxy.so/core 1.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 (673) hide show
  1. package/LICENSE +202 -0
  2. package/NOTICE +16 -0
  3. package/README.md +221 -0
  4. package/dist/cjs/.tsbuildinfo +1 -0
  5. package/dist/cjs/HttpService.js +1270 -0
  6. package/dist/cjs/OxyServices.base.js +390 -0
  7. package/dist/cjs/OxyServices.errors.js +95 -0
  8. package/dist/cjs/OxyServices.js +72 -0
  9. package/dist/cjs/boot/sessionColdBoot.js +395 -0
  10. package/dist/cjs/constants/version.js +16 -0
  11. package/dist/cjs/crypto/aead.js +79 -0
  12. package/dist/cjs/crypto/ecdh.js +35 -0
  13. package/dist/cjs/crypto/identityMarker.js +255 -0
  14. package/dist/cjs/crypto/kdf.js +39 -0
  15. package/dist/cjs/crypto/keyManager.js +2234 -0
  16. package/dist/cjs/crypto/polyfill.js +131 -0
  17. package/dist/cjs/crypto/recoveryPhrase.js +242 -0
  18. package/dist/cjs/crypto/signatureService.js +273 -0
  19. package/dist/cjs/i18n/accountCategoryLabels.js +44 -0
  20. package/dist/cjs/i18n/accountRoleLabels.js +27 -0
  21. package/dist/cjs/i18n/index.js +90 -0
  22. package/dist/cjs/i18n/locales/ar-SA.json +282 -0
  23. package/dist/cjs/i18n/locales/ca-ES.json +282 -0
  24. package/dist/cjs/i18n/locales/de-DE.json +282 -0
  25. package/dist/cjs/i18n/locales/en-US.json +2161 -0
  26. package/dist/cjs/i18n/locales/es-ES.json +2161 -0
  27. package/dist/cjs/i18n/locales/fr-FR.json +282 -0
  28. package/dist/cjs/i18n/locales/it-IT.json +282 -0
  29. package/dist/cjs/i18n/locales/ja-JP.json +282 -0
  30. package/dist/cjs/i18n/locales/ko-KR.json +282 -0
  31. package/dist/cjs/i18n/locales/locales/ar-SA.json +282 -0
  32. package/dist/cjs/i18n/locales/locales/ca-ES.json +282 -0
  33. package/dist/cjs/i18n/locales/locales/de-DE.json +282 -0
  34. package/dist/cjs/i18n/locales/locales/en-US.json +2161 -0
  35. package/dist/cjs/i18n/locales/locales/es-ES.json +2161 -0
  36. package/dist/cjs/i18n/locales/locales/fr-FR.json +282 -0
  37. package/dist/cjs/i18n/locales/locales/it-IT.json +282 -0
  38. package/dist/cjs/i18n/locales/locales/ja-JP.json +282 -0
  39. package/dist/cjs/i18n/locales/locales/ko-KR.json +282 -0
  40. package/dist/cjs/i18n/locales/locales/pt-PT.json +282 -0
  41. package/dist/cjs/i18n/locales/locales/zh-CN.json +282 -0
  42. package/dist/cjs/i18n/locales/pt-PT.json +282 -0
  43. package/dist/cjs/i18n/locales/zh-CN.json +282 -0
  44. package/dist/cjs/i18n/reputationCategoryLabels.js +20 -0
  45. package/dist/cjs/i18n/trustTierLabels.js +19 -0
  46. package/dist/cjs/index.js +498 -0
  47. package/dist/cjs/inference/OxyInferenceClient.js +544 -0
  48. package/dist/cjs/logger/index.js +149 -0
  49. package/dist/cjs/mixins/OxyServices.accounts.js +555 -0
  50. package/dist/cjs/mixins/OxyServices.analytics.js +49 -0
  51. package/dist/cjs/mixins/OxyServices.appData.js +108 -0
  52. package/dist/cjs/mixins/OxyServices.assets.js +764 -0
  53. package/dist/cjs/mixins/OxyServices.auth.js +1254 -0
  54. package/dist/cjs/mixins/OxyServices.chains.js +73 -0
  55. package/dist/cjs/mixins/OxyServices.civic.js +611 -0
  56. package/dist/cjs/mixins/OxyServices.connectedApps.js +78 -0
  57. package/dist/cjs/mixins/OxyServices.contacts.js +50 -0
  58. package/dist/cjs/mixins/OxyServices.deviceBoot.js +191 -0
  59. package/dist/cjs/mixins/OxyServices.deviceTransfer.js +314 -0
  60. package/dist/cjs/mixins/OxyServices.devices.js +116 -0
  61. package/dist/cjs/mixins/OxyServices.features.js +335 -0
  62. package/dist/cjs/mixins/OxyServices.followGraph.js +221 -0
  63. package/dist/cjs/mixins/OxyServices.identity.js +461 -0
  64. package/dist/cjs/mixins/OxyServices.identityBackup.js +172 -0
  65. package/dist/cjs/mixins/OxyServices.inference.js +59 -0
  66. package/dist/cjs/mixins/OxyServices.language.js +125 -0
  67. package/dist/cjs/mixins/OxyServices.links.js +72 -0
  68. package/dist/cjs/mixins/OxyServices.location.js +43 -0
  69. package/dist/cjs/mixins/OxyServices.nodes.js +175 -0
  70. package/dist/cjs/mixins/OxyServices.notifications.js +63 -0
  71. package/dist/cjs/mixins/OxyServices.payment.js +158 -0
  72. package/dist/cjs/mixins/OxyServices.privacy.js +199 -0
  73. package/dist/cjs/mixins/OxyServices.reputation.js +289 -0
  74. package/dist/cjs/mixins/OxyServices.security.js +89 -0
  75. package/dist/cjs/mixins/OxyServices.store.js +266 -0
  76. package/dist/cjs/mixins/OxyServices.topics.js +137 -0
  77. package/dist/cjs/mixins/OxyServices.user.js +902 -0
  78. package/dist/cjs/mixins/OxyServices.utility.js +1098 -0
  79. package/dist/cjs/mixins/index.js +135 -0
  80. package/dist/cjs/mixins/mixinHelpers.js +53 -0
  81. package/dist/cjs/models/Topic.js +16 -0
  82. package/dist/cjs/models/interfaces.js +20 -0
  83. package/dist/cjs/models/session.js +2 -0
  84. package/dist/cjs/server/auth.js +167 -0
  85. package/dist/cjs/server/capabilityTicket.js +192 -0
  86. package/dist/cjs/server/cors.js +225 -0
  87. package/dist/cjs/server/index.js +97 -0
  88. package/dist/cjs/server/rateLimit.js +207 -0
  89. package/dist/cjs/server/safeFetch.js +458 -0
  90. package/dist/cjs/server/securityHeaders.js +377 -0
  91. package/dist/cjs/server/userInvalidation.js +156 -0
  92. package/dist/cjs/server/verifySecret.js +50 -0
  93. package/dist/cjs/session/SessionClient.js +865 -0
  94. package/dist/cjs/session/accountDelegationAccess.js +48 -0
  95. package/dist/cjs/session/accountDialogController.js +1131 -0
  96. package/dist/cjs/session/accountSwitchTargets.js +81 -0
  97. package/dist/cjs/session/authStateStore.js +404 -0
  98. package/dist/cjs/session/createSessionClient.js +32 -0
  99. package/dist/cjs/session/deviceDirectory.js +143 -0
  100. package/dist/cjs/session/deviceSwitcherRows.js +76 -0
  101. package/dist/cjs/session/identityPin.js +256 -0
  102. package/dist/cjs/session/identitySession.js +135 -0
  103. package/dist/cjs/session/projectSessionState.js +121 -0
  104. package/dist/cjs/session/refresh.js +398 -0
  105. package/dist/cjs/session/sessionClientHost.js +34 -0
  106. package/dist/cjs/session/sharedDeviceCredential.js +247 -0
  107. package/dist/cjs/session/socketLoader.js +55 -0
  108. package/dist/cjs/shared/utils/colorUtils.js +153 -0
  109. package/dist/cjs/shared/utils/errorUtils.js +183 -0
  110. package/dist/cjs/shared/utils/index.js +49 -0
  111. package/dist/cjs/shared/utils/networkUtils.js +183 -0
  112. package/dist/cjs/shared/utils/themeUtils.js +106 -0
  113. package/dist/cjs/utils/accountCacheSweep.js +80 -0
  114. package/dist/cjs/utils/accountUtils.js +140 -0
  115. package/dist/cjs/utils/activityId.js +6 -0
  116. package/dist/cjs/utils/apiUtils.js +91 -0
  117. package/dist/cjs/utils/asyncUtils.js +222 -0
  118. package/dist/cjs/utils/authHelpers.js +120 -0
  119. package/dist/cjs/utils/authWebUrl.js +19 -0
  120. package/dist/cjs/utils/avatarUtils.js +29 -0
  121. package/dist/cjs/utils/cache.js +235 -0
  122. package/dist/cjs/utils/cacheKey.js +85 -0
  123. package/dist/cjs/utils/coldBoot.js +122 -0
  124. package/dist/cjs/utils/commonsApproval.js +31 -0
  125. package/dist/cjs/utils/commonsDelivery.js +59 -0
  126. package/dist/cjs/utils/deviceManager.js +174 -0
  127. package/dist/cjs/utils/displayNamePolicyRanges.generated.js +60 -0
  128. package/dist/cjs/utils/edgeRegion.js +6 -0
  129. package/dist/cjs/utils/errorUtils.js +243 -0
  130. package/dist/cjs/utils/identityCacheSweep.js +97 -0
  131. package/dist/cjs/utils/languageUtils.js +224 -0
  132. package/dist/cjs/utils/oauthPkce.js +311 -0
  133. package/dist/cjs/utils/officialOrigins.js +64 -0
  134. package/dist/cjs/utils/oxyServiceEnvironment.js +19 -0
  135. package/dist/cjs/utils/platform.js +119 -0
  136. package/dist/cjs/utils/profileLinks.js +63 -0
  137. package/dist/cjs/utils/redactUrl.js +29 -0
  138. package/dist/cjs/utils/registrableApex.js +45 -0
  139. package/dist/cjs/utils/requestUtils.js +209 -0
  140. package/dist/cjs/utils/sessionUtils.js +181 -0
  141. package/dist/cjs/utils/textNormalization.js +158 -0
  142. package/dist/cjs/utils/userHandle.js +37 -0
  143. package/dist/cjs/utils/userIdentity.js +50 -0
  144. package/dist/cjs/utils/validationUtils.js +370 -0
  145. package/dist/cjs/utils/webauthnOrigin.js +51 -0
  146. package/dist/esm/.tsbuildinfo +1 -0
  147. package/dist/esm/HttpService.js +1266 -0
  148. package/dist/esm/OxyServices.base.js +386 -0
  149. package/dist/esm/OxyServices.errors.js +88 -0
  150. package/dist/esm/OxyServices.js +66 -0
  151. package/dist/esm/boot/sessionColdBoot.js +392 -0
  152. package/dist/esm/constants/version.js +13 -0
  153. package/dist/esm/crypto/aead.js +74 -0
  154. package/dist/esm/crypto/ecdh.js +32 -0
  155. package/dist/esm/crypto/identityMarker.js +248 -0
  156. package/dist/esm/crypto/kdf.js +36 -0
  157. package/dist/esm/crypto/keyManager.js +2227 -0
  158. package/dist/esm/crypto/polyfill.js +129 -0
  159. package/dist/esm/crypto/recoveryPhrase.js +238 -0
  160. package/dist/esm/crypto/signatureService.js +269 -0
  161. package/dist/esm/i18n/accountCategoryLabels.js +37 -0
  162. package/dist/esm/i18n/accountRoleLabels.js +20 -0
  163. package/dist/esm/i18n/index.js +83 -0
  164. package/dist/esm/i18n/locales/ar-SA.json +282 -0
  165. package/dist/esm/i18n/locales/ca-ES.json +282 -0
  166. package/dist/esm/i18n/locales/de-DE.json +282 -0
  167. package/dist/esm/i18n/locales/en-US.json +2161 -0
  168. package/dist/esm/i18n/locales/es-ES.json +2161 -0
  169. package/dist/esm/i18n/locales/fr-FR.json +282 -0
  170. package/dist/esm/i18n/locales/it-IT.json +282 -0
  171. package/dist/esm/i18n/locales/ja-JP.json +282 -0
  172. package/dist/esm/i18n/locales/ko-KR.json +282 -0
  173. package/dist/esm/i18n/locales/locales/ar-SA.json +282 -0
  174. package/dist/esm/i18n/locales/locales/ca-ES.json +282 -0
  175. package/dist/esm/i18n/locales/locales/de-DE.json +282 -0
  176. package/dist/esm/i18n/locales/locales/en-US.json +2161 -0
  177. package/dist/esm/i18n/locales/locales/es-ES.json +2161 -0
  178. package/dist/esm/i18n/locales/locales/fr-FR.json +282 -0
  179. package/dist/esm/i18n/locales/locales/it-IT.json +282 -0
  180. package/dist/esm/i18n/locales/locales/ja-JP.json +282 -0
  181. package/dist/esm/i18n/locales/locales/ko-KR.json +282 -0
  182. package/dist/esm/i18n/locales/locales/pt-PT.json +282 -0
  183. package/dist/esm/i18n/locales/locales/zh-CN.json +282 -0
  184. package/dist/esm/i18n/locales/pt-PT.json +282 -0
  185. package/dist/esm/i18n/locales/zh-CN.json +282 -0
  186. package/dist/esm/i18n/reputationCategoryLabels.js +13 -0
  187. package/dist/esm/i18n/trustTierLabels.js +12 -0
  188. package/dist/esm/index.js +254 -0
  189. package/dist/esm/inference/OxyInferenceClient.js +538 -0
  190. package/dist/esm/logger/index.js +140 -0
  191. package/dist/esm/mixins/OxyServices.accounts.js +543 -0
  192. package/dist/esm/mixins/OxyServices.analytics.js +46 -0
  193. package/dist/esm/mixins/OxyServices.appData.js +103 -0
  194. package/dist/esm/mixins/OxyServices.assets.js +761 -0
  195. package/dist/esm/mixins/OxyServices.auth.js +1247 -0
  196. package/dist/esm/mixins/OxyServices.chains.js +70 -0
  197. package/dist/esm/mixins/OxyServices.civic.js +605 -0
  198. package/dist/esm/mixins/OxyServices.connectedApps.js +75 -0
  199. package/dist/esm/mixins/OxyServices.contacts.js +47 -0
  200. package/dist/esm/mixins/OxyServices.deviceBoot.js +186 -0
  201. package/dist/esm/mixins/OxyServices.deviceTransfer.js +311 -0
  202. package/dist/esm/mixins/OxyServices.devices.js +113 -0
  203. package/dist/esm/mixins/OxyServices.features.js +332 -0
  204. package/dist/esm/mixins/OxyServices.followGraph.js +218 -0
  205. package/dist/esm/mixins/OxyServices.identity.js +457 -0
  206. package/dist/esm/mixins/OxyServices.identityBackup.js +169 -0
  207. package/dist/esm/mixins/OxyServices.inference.js +56 -0
  208. package/dist/esm/mixins/OxyServices.language.js +122 -0
  209. package/dist/esm/mixins/OxyServices.links.js +69 -0
  210. package/dist/esm/mixins/OxyServices.location.js +40 -0
  211. package/dist/esm/mixins/OxyServices.nodes.js +172 -0
  212. package/dist/esm/mixins/OxyServices.notifications.js +60 -0
  213. package/dist/esm/mixins/OxyServices.payment.js +155 -0
  214. package/dist/esm/mixins/OxyServices.privacy.js +196 -0
  215. package/dist/esm/mixins/OxyServices.reputation.js +286 -0
  216. package/dist/esm/mixins/OxyServices.security.js +86 -0
  217. package/dist/esm/mixins/OxyServices.store.js +263 -0
  218. package/dist/esm/mixins/OxyServices.topics.js +134 -0
  219. package/dist/esm/mixins/OxyServices.user.js +899 -0
  220. package/dist/esm/mixins/OxyServices.utility.js +1095 -0
  221. package/dist/esm/mixins/index.js +132 -0
  222. package/dist/esm/mixins/mixinHelpers.js +48 -0
  223. package/dist/esm/models/Topic.js +13 -0
  224. package/dist/esm/models/interfaces.js +17 -0
  225. package/dist/esm/models/session.js +1 -0
  226. package/dist/esm/server/auth.js +154 -0
  227. package/dist/esm/server/capabilityTicket.js +183 -0
  228. package/dist/esm/server/cors.js +220 -0
  229. package/dist/esm/server/index.js +47 -0
  230. package/dist/esm/server/rateLimit.js +201 -0
  231. package/dist/esm/server/safeFetch.js +447 -0
  232. package/dist/esm/server/securityHeaders.js +364 -0
  233. package/dist/esm/server/userInvalidation.js +152 -0
  234. package/dist/esm/server/verifySecret.js +47 -0
  235. package/dist/esm/session/SessionClient.js +861 -0
  236. package/dist/esm/session/accountDelegationAccess.js +45 -0
  237. package/dist/esm/session/accountDialogController.js +1126 -0
  238. package/dist/esm/session/accountSwitchTargets.js +77 -0
  239. package/dist/esm/session/authStateStore.js +398 -0
  240. package/dist/esm/session/createSessionClient.js +29 -0
  241. package/dist/esm/session/deviceDirectory.js +135 -0
  242. package/dist/esm/session/deviceSwitcherRows.js +72 -0
  243. package/dist/esm/session/identityPin.js +249 -0
  244. package/dist/esm/session/identitySession.js +131 -0
  245. package/dist/esm/session/projectSessionState.js +114 -0
  246. package/dist/esm/session/refresh.js +390 -0
  247. package/dist/esm/session/sessionClientHost.js +31 -0
  248. package/dist/esm/session/sharedDeviceCredential.js +239 -0
  249. package/dist/esm/session/socketLoader.js +19 -0
  250. package/dist/esm/shared/utils/colorUtils.js +143 -0
  251. package/dist/esm/shared/utils/errorUtils.js +170 -0
  252. package/dist/esm/shared/utils/index.js +15 -0
  253. package/dist/esm/shared/utils/networkUtils.js +173 -0
  254. package/dist/esm/shared/utils/themeUtils.js +98 -0
  255. package/dist/esm/utils/accountCacheSweep.js +75 -0
  256. package/dist/esm/utils/accountUtils.js +131 -0
  257. package/dist/esm/utils/activityId.js +2 -0
  258. package/dist/esm/utils/apiUtils.js +84 -0
  259. package/dist/esm/utils/asyncUtils.js +207 -0
  260. package/dist/esm/utils/authHelpers.js +111 -0
  261. package/dist/esm/utils/authWebUrl.js +16 -0
  262. package/dist/esm/utils/avatarUtils.js +26 -0
  263. package/dist/esm/utils/cache.js +227 -0
  264. package/dist/esm/utils/cacheKey.js +80 -0
  265. package/dist/esm/utils/coldBoot.js +119 -0
  266. package/dist/esm/utils/commonsApproval.js +27 -0
  267. package/dist/esm/utils/commonsDelivery.js +54 -0
  268. package/dist/esm/utils/deviceManager.js +170 -0
  269. package/dist/esm/utils/displayNamePolicyRanges.generated.js +57 -0
  270. package/dist/esm/utils/edgeRegion.js +2 -0
  271. package/dist/esm/utils/errorUtils.js +232 -0
  272. package/dist/esm/utils/identityCacheSweep.js +92 -0
  273. package/dist/esm/utils/languageUtils.js +212 -0
  274. package/dist/esm/utils/oauthPkce.js +297 -0
  275. package/dist/esm/utils/officialOrigins.js +59 -0
  276. package/dist/esm/utils/oxyServiceEnvironment.js +16 -0
  277. package/dist/esm/utils/platform.js +110 -0
  278. package/dist/esm/utils/profileLinks.js +60 -0
  279. package/dist/esm/utils/redactUrl.js +26 -0
  280. package/dist/esm/utils/registrableApex.js +42 -0
  281. package/dist/esm/utils/requestUtils.js +203 -0
  282. package/dist/esm/utils/sessionUtils.js +171 -0
  283. package/dist/esm/utils/textNormalization.js +154 -0
  284. package/dist/esm/utils/userHandle.js +33 -0
  285. package/dist/esm/utils/userIdentity.js +45 -0
  286. package/dist/esm/utils/validationUtils.js +350 -0
  287. package/dist/esm/utils/webauthnOrigin.js +48 -0
  288. package/dist/types/.tsbuildinfo +1 -0
  289. package/dist/types/HttpService.d.ts +413 -0
  290. package/dist/types/OxyServices.base.d.ts +187 -0
  291. package/dist/types/OxyServices.d.ts +139 -0
  292. package/dist/types/OxyServices.errors.d.ts +84 -0
  293. package/dist/types/boot/sessionColdBoot.d.ts +140 -0
  294. package/dist/types/constants/version.d.ts +13 -0
  295. package/dist/types/crypto/aead.d.ts +56 -0
  296. package/dist/types/crypto/ecdh.d.ts +29 -0
  297. package/dist/types/crypto/identityMarker.d.ts +94 -0
  298. package/dist/types/crypto/kdf.d.ts +25 -0
  299. package/dist/types/crypto/keyManager.d.ts +582 -0
  300. package/dist/types/crypto/polyfill.d.ts +25 -0
  301. package/dist/types/crypto/recoveryPhrase.d.ts +173 -0
  302. package/dist/types/crypto/signatureService.d.ts +136 -0
  303. package/dist/types/i18n/accountCategoryLabels.d.ts +34 -0
  304. package/dist/types/i18n/accountRoleLabels.d.ts +10 -0
  305. package/dist/types/i18n/index.d.ts +3 -0
  306. package/dist/types/i18n/reputationCategoryLabels.d.ts +10 -0
  307. package/dist/types/i18n/trustTierLabels.d.ts +9 -0
  308. package/dist/types/index.d.ts +145 -0
  309. package/dist/types/inference/OxyInferenceClient.d.ts +342 -0
  310. package/dist/types/logger/index.d.ts +104 -0
  311. package/dist/types/mixins/OxyServices.accounts.d.ts +868 -0
  312. package/dist/types/mixins/OxyServices.analytics.d.ts +72 -0
  313. package/dist/types/mixins/OxyServices.appData.d.ts +108 -0
  314. package/dist/types/mixins/OxyServices.assets.d.ts +329 -0
  315. package/dist/types/mixins/OxyServices.auth.d.ts +908 -0
  316. package/dist/types/mixins/OxyServices.chains.d.ts +156 -0
  317. package/dist/types/mixins/OxyServices.civic.d.ts +510 -0
  318. package/dist/types/mixins/OxyServices.connectedApps.d.ts +169 -0
  319. package/dist/types/mixins/OxyServices.contacts.d.ts +100 -0
  320. package/dist/types/mixins/OxyServices.deviceBoot.d.ts +185 -0
  321. package/dist/types/mixins/OxyServices.deviceTransfer.d.ts +149 -0
  322. package/dist/types/mixins/OxyServices.devices.d.ts +103 -0
  323. package/dist/types/mixins/OxyServices.features.d.ts +250 -0
  324. package/dist/types/mixins/OxyServices.followGraph.d.ts +223 -0
  325. package/dist/types/mixins/OxyServices.identity.d.ts +351 -0
  326. package/dist/types/mixins/OxyServices.identityBackup.d.ts +129 -0
  327. package/dist/types/mixins/OxyServices.inference.d.ts +95 -0
  328. package/dist/types/mixins/OxyServices.language.d.ts +87 -0
  329. package/dist/types/mixins/OxyServices.links.d.ts +104 -0
  330. package/dist/types/mixins/OxyServices.location.d.ts +70 -0
  331. package/dist/types/mixins/OxyServices.nodes.d.ts +198 -0
  332. package/dist/types/mixins/OxyServices.notifications.d.ts +143 -0
  333. package/dist/types/mixins/OxyServices.payment.d.ts +117 -0
  334. package/dist/types/mixins/OxyServices.privacy.d.ts +146 -0
  335. package/dist/types/mixins/OxyServices.reputation.d.ts +202 -0
  336. package/dist/types/mixins/OxyServices.security.d.ts +84 -0
  337. package/dist/types/mixins/OxyServices.store.d.ts +334 -0
  338. package/dist/types/mixins/OxyServices.topics.d.ts +110 -0
  339. package/dist/types/mixins/OxyServices.user.d.ts +558 -0
  340. package/dist/types/mixins/OxyServices.utility.d.ts +393 -0
  341. package/dist/types/mixins/index.d.ts +87 -0
  342. package/dist/types/mixins/mixinHelpers.d.ts +31 -0
  343. package/dist/types/models/Topic.d.ts +42 -0
  344. package/dist/types/models/interfaces.d.ts +675 -0
  345. package/dist/types/models/session.d.ts +51 -0
  346. package/dist/types/server/auth.d.ts +130 -0
  347. package/dist/types/server/capabilityTicket.d.ts +41 -0
  348. package/dist/types/server/cors.d.ts +98 -0
  349. package/dist/types/server/index.d.ts +35 -0
  350. package/dist/types/server/rateLimit.d.ts +40 -0
  351. package/dist/types/server/safeFetch.d.ts +137 -0
  352. package/dist/types/server/securityHeaders.d.ts +221 -0
  353. package/dist/types/server/userInvalidation.d.ts +114 -0
  354. package/dist/types/server/verifySecret.d.ts +29 -0
  355. package/dist/types/session/SessionClient.d.ts +418 -0
  356. package/dist/types/session/accountDelegationAccess.d.ts +40 -0
  357. package/dist/types/session/accountDialogController.d.ts +648 -0
  358. package/dist/types/session/accountSwitchTargets.d.ts +70 -0
  359. package/dist/types/session/authStateStore.d.ts +153 -0
  360. package/dist/types/session/createSessionClient.d.ts +30 -0
  361. package/dist/types/session/deviceDirectory.d.ts +182 -0
  362. package/dist/types/session/deviceSwitcherRows.d.ts +92 -0
  363. package/dist/types/session/identityPin.d.ts +87 -0
  364. package/dist/types/session/identitySession.d.ts +105 -0
  365. package/dist/types/session/projectSessionState.d.ts +74 -0
  366. package/dist/types/session/refresh.d.ts +179 -0
  367. package/dist/types/session/sessionClientHost.d.ts +18 -0
  368. package/dist/types/session/sharedDeviceCredential.d.ts +202 -0
  369. package/dist/types/session/socketLoader.d.ts +11 -0
  370. package/dist/types/shared/utils/colorUtils.d.ts +104 -0
  371. package/dist/types/shared/utils/errorUtils.d.ts +97 -0
  372. package/dist/types/shared/utils/index.d.ts +13 -0
  373. package/dist/types/shared/utils/networkUtils.d.ts +139 -0
  374. package/dist/types/shared/utils/themeUtils.d.ts +90 -0
  375. package/dist/types/utils/accountCacheSweep.d.ts +75 -0
  376. package/dist/types/utils/accountUtils.d.ts +100 -0
  377. package/dist/types/utils/activityId.d.ts +2 -0
  378. package/dist/types/utils/apiUtils.d.ts +95 -0
  379. package/dist/types/utils/asyncUtils.d.ts +62 -0
  380. package/dist/types/utils/authHelpers.d.ts +58 -0
  381. package/dist/types/utils/authWebUrl.d.ts +16 -0
  382. package/dist/types/utils/avatarUtils.d.ts +16 -0
  383. package/dist/types/utils/cache.d.ts +130 -0
  384. package/dist/types/utils/cacheKey.d.ts +66 -0
  385. package/dist/types/utils/coldBoot.d.ts +131 -0
  386. package/dist/types/utils/commonsApproval.d.ts +13 -0
  387. package/dist/types/utils/commonsDelivery.d.ts +105 -0
  388. package/dist/types/utils/deviceManager.d.ts +65 -0
  389. package/dist/types/utils/displayNamePolicyRanges.generated.d.ts +57 -0
  390. package/dist/types/utils/edgeRegion.d.ts +2 -0
  391. package/dist/types/utils/errorUtils.d.ts +125 -0
  392. package/dist/types/utils/identityCacheSweep.d.ts +80 -0
  393. package/dist/types/utils/languageUtils.d.ts +100 -0
  394. package/dist/types/utils/oauthPkce.d.ts +157 -0
  395. package/dist/types/utils/officialOrigins.d.ts +13 -0
  396. package/dist/types/utils/oxyServiceEnvironment.d.ts +17 -0
  397. package/dist/types/utils/platform.d.ts +49 -0
  398. package/dist/types/utils/profileLinks.d.ts +44 -0
  399. package/dist/types/utils/redactUrl.d.ts +17 -0
  400. package/dist/types/utils/registrableApex.d.ts +27 -0
  401. package/dist/types/utils/requestUtils.d.ts +123 -0
  402. package/dist/types/utils/sessionUtils.d.ts +54 -0
  403. package/dist/types/utils/textNormalization.d.ts +103 -0
  404. package/dist/types/utils/userHandle.d.ts +26 -0
  405. package/dist/types/utils/userIdentity.d.ts +21 -0
  406. package/dist/types/utils/validationUtils.d.ts +268 -0
  407. package/dist/types/utils/webauthnOrigin.d.ts +32 -0
  408. package/package.json +168 -0
  409. package/src/HttpService.ts +1553 -0
  410. package/src/OxyServices.base.ts +478 -0
  411. package/src/OxyServices.errors.ts +122 -0
  412. package/src/OxyServices.ts +172 -0
  413. package/src/__tests__/authSocket.test.ts +96 -0
  414. package/src/__tests__/httpServiceActivityId.test.ts +49 -0
  415. package/src/__tests__/httpServiceAuthSelfAwait.test.ts +108 -0
  416. package/src/__tests__/httpServiceCache.test.ts +318 -0
  417. package/src/__tests__/httpServiceCsrf.test.ts +235 -0
  418. package/src/__tests__/httpServiceFormEncoded.test.ts +142 -0
  419. package/src/__tests__/httpServiceQueueDeadlock.test.ts +128 -0
  420. package/src/__tests__/httpServiceUnwrapEnvelope.test.ts +115 -0
  421. package/src/__tests__/inSessionRefresh.test.ts +260 -0
  422. package/src/__tests__/linkedClient.test.ts +370 -0
  423. package/src/__tests__/parseHttpErrorBody.test.ts +116 -0
  424. package/src/__tests__/serverValueImportsDeclared.test.ts +120 -0
  425. package/src/__tests__/userIdentity.test.ts +143 -0
  426. package/src/boot/__tests__/sessionColdBoot.identity.test.ts +393 -0
  427. package/src/boot/__tests__/sessionColdBoot.sharedDevice.test.ts +325 -0
  428. package/src/boot/__tests__/sessionColdBoot.test.ts +570 -0
  429. package/src/boot/sessionColdBoot.ts +529 -0
  430. package/src/constants/version.ts +15 -0
  431. package/src/crypto/__tests__/backupMaterial.test.ts +86 -0
  432. package/src/crypto/__tests__/cryptoPrimitives.test.ts +226 -0
  433. package/src/crypto/__tests__/identityMocks.ts +125 -0
  434. package/src/crypto/__tests__/keyManager.atomicity.test.ts +272 -0
  435. package/src/crypto/__tests__/keyManager.cacheSafety.test.ts +175 -0
  436. package/src/crypto/__tests__/keyManager.identityStatus.test.ts +217 -0
  437. package/src/crypto/__tests__/keyManager.recoveryLadder.test.ts +179 -0
  438. package/src/crypto/__tests__/keyManager.recoveryMnemonic.test.ts +138 -0
  439. package/src/crypto/__tests__/keyManager.storageMigration.test.ts +227 -0
  440. package/src/crypto/__tests__/keyManager.test.ts +329 -0
  441. package/src/crypto/__tests__/polyfill.test.ts +109 -0
  442. package/src/crypto/__tests__/recoveryPhrase.test.ts +61 -0
  443. package/src/crypto/__tests__/scopedSeed.test.ts +126 -0
  444. package/src/crypto/__tests__/signChallengeShared.test.ts +63 -0
  445. package/src/crypto/__tests__/signedRecord.test.ts +230 -0
  446. package/src/crypto/aead.ts +97 -0
  447. package/src/crypto/ecdh.ts +37 -0
  448. package/src/crypto/identityMarker.ts +291 -0
  449. package/src/crypto/kdf.ts +43 -0
  450. package/src/crypto/keyManager.ts +2607 -0
  451. package/src/crypto/polyfill.ts +143 -0
  452. package/src/crypto/recoveryPhrase.ts +337 -0
  453. package/src/crypto/signatureService.ts +350 -0
  454. package/src/i18n/__tests__/accountCategoryLabels.test.ts +62 -0
  455. package/src/i18n/__tests__/accountRoleLabels.test.ts +54 -0
  456. package/src/i18n/__tests__/reputationCategoryLabels.test.ts +56 -0
  457. package/src/i18n/__tests__/trustTierLabels.test.ts +47 -0
  458. package/src/i18n/accountCategoryLabels.ts +44 -0
  459. package/src/i18n/accountRoleLabels.ts +26 -0
  460. package/src/i18n/index.ts +88 -0
  461. package/src/i18n/locales/ar-SA.json +282 -0
  462. package/src/i18n/locales/ca-ES.json +282 -0
  463. package/src/i18n/locales/de-DE.json +282 -0
  464. package/src/i18n/locales/en-US.json +2161 -0
  465. package/src/i18n/locales/es-ES.json +2161 -0
  466. package/src/i18n/locales/fr-FR.json +282 -0
  467. package/src/i18n/locales/it-IT.json +282 -0
  468. package/src/i18n/locales/ja-JP.json +282 -0
  469. package/src/i18n/locales/ko-KR.json +282 -0
  470. package/src/i18n/locales/pt-PT.json +282 -0
  471. package/src/i18n/locales/zh-CN.json +282 -0
  472. package/src/i18n/reputationCategoryLabels.ts +20 -0
  473. package/src/i18n/trustTierLabels.ts +18 -0
  474. package/src/index.ts +881 -0
  475. package/src/inference/OxyInferenceClient.ts +888 -0
  476. package/src/inference/__tests__/OxyInferenceClient.test.ts +834 -0
  477. package/src/logger/__tests__/logger.test.ts +207 -0
  478. package/src/logger/index.ts +217 -0
  479. package/src/mixins/OxyServices.accounts.ts +1330 -0
  480. package/src/mixins/OxyServices.analytics.ts +53 -0
  481. package/src/mixins/OxyServices.appData.ts +158 -0
  482. package/src/mixins/OxyServices.assets.ts +861 -0
  483. package/src/mixins/OxyServices.auth.ts +1858 -0
  484. package/src/mixins/OxyServices.chains.ts +134 -0
  485. package/src/mixins/OxyServices.civic.ts +945 -0
  486. package/src/mixins/OxyServices.connectedApps.ts +174 -0
  487. package/src/mixins/OxyServices.contacts.ts +73 -0
  488. package/src/mixins/OxyServices.deviceBoot.ts +210 -0
  489. package/src/mixins/OxyServices.deviceTransfer.ts +393 -0
  490. package/src/mixins/OxyServices.devices.ts +120 -0
  491. package/src/mixins/OxyServices.features.ts +454 -0
  492. package/src/mixins/OxyServices.followGraph.ts +293 -0
  493. package/src/mixins/OxyServices.identity.ts +705 -0
  494. package/src/mixins/OxyServices.identityBackup.ts +250 -0
  495. package/src/mixins/OxyServices.inference.ts +57 -0
  496. package/src/mixins/OxyServices.language.ts +144 -0
  497. package/src/mixins/OxyServices.links.ts +107 -0
  498. package/src/mixins/OxyServices.location.ts +46 -0
  499. package/src/mixins/OxyServices.nodes.ts +337 -0
  500. package/src/mixins/OxyServices.notifications.ts +142 -0
  501. package/src/mixins/OxyServices.payment.ts +163 -0
  502. package/src/mixins/OxyServices.privacy.ts +219 -0
  503. package/src/mixins/OxyServices.reputation.ts +436 -0
  504. package/src/mixins/OxyServices.security.ts +110 -0
  505. package/src/mixins/OxyServices.store.ts +585 -0
  506. package/src/mixins/OxyServices.topics.ts +169 -0
  507. package/src/mixins/OxyServices.user.ts +1137 -0
  508. package/src/mixins/OxyServices.utility.ts +1370 -0
  509. package/src/mixins/__tests__/OxyServices.civic.test.ts +1095 -0
  510. package/src/mixins/__tests__/OxyServices.deviceBoot.test.ts +124 -0
  511. package/src/mixins/__tests__/OxyServices.deviceTransfer.test.ts +271 -0
  512. package/src/mixins/__tests__/OxyServices.identity.test.ts +376 -0
  513. package/src/mixins/__tests__/OxyServices.links.test.ts +154 -0
  514. package/src/mixins/__tests__/OxyServices.nodes.test.ts +341 -0
  515. package/src/mixins/__tests__/OxyServices.rotateKey.test.ts +276 -0
  516. package/src/mixins/__tests__/OxyServices.serviceAssetMetadata.test.ts +192 -0
  517. package/src/mixins/__tests__/OxyServices.serviceAssetMetadataBySha.test.ts +135 -0
  518. package/src/mixins/__tests__/accounts.test.ts +727 -0
  519. package/src/mixins/__tests__/appData.test.ts +203 -0
  520. package/src/mixins/__tests__/assetCredentials.test.ts +47 -0
  521. package/src/mixins/__tests__/assetUpload.test.ts +191 -0
  522. package/src/mixins/__tests__/backgroundCredential.httpIntegration.test.ts +135 -0
  523. package/src/mixins/__tests__/chains.test.ts +113 -0
  524. package/src/mixins/__tests__/commonsSignIn.test.ts +1144 -0
  525. package/src/mixins/__tests__/connectedApps.test.ts +123 -0
  526. package/src/mixins/__tests__/deviceTokenMintPinned.test.ts +113 -0
  527. package/src/mixins/__tests__/discoveryErrorHandling.test.ts +266 -0
  528. package/src/mixins/__tests__/followCacheInvalidation.test.ts +173 -0
  529. package/src/mixins/__tests__/followGraph.test.ts +147 -0
  530. package/src/mixins/__tests__/followGraphPagination.test.ts +271 -0
  531. package/src/mixins/__tests__/getFileDownloadUrl.test.ts +346 -0
  532. package/src/mixins/__tests__/getFollowStatuses.test.ts +95 -0
  533. package/src/mixins/__tests__/getUsersByIds.test.ts +149 -0
  534. package/src/mixins/__tests__/identityBackup.test.ts +315 -0
  535. package/src/mixins/__tests__/identityWriteCacheInvalidation.test.ts +407 -0
  536. package/src/mixins/__tests__/inferenceFactory.test.ts +58 -0
  537. package/src/mixins/__tests__/onTokensChanged.test.ts +129 -0
  538. package/src/mixins/__tests__/preSessionSkipAuth.test.ts +284 -0
  539. package/src/mixins/__tests__/privacyCacheInvalidation.test.ts +155 -0
  540. package/src/mixins/__tests__/reputation.test.ts +522 -0
  541. package/src/mixins/__tests__/serviceAuth.test.ts +832 -0
  542. package/src/mixins/__tests__/serviceTokenJwks.test.ts +208 -0
  543. package/src/mixins/__tests__/store.test.ts +304 -0
  544. package/src/mixins/__tests__/topics.test.ts +156 -0
  545. package/src/mixins/__tests__/userReadCacheBypass.test.ts +129 -0
  546. package/src/mixins/__tests__/userTokenAuth.test.ts +746 -0
  547. package/src/mixins/__tests__/verifyChallenge.test.ts +130 -0
  548. package/src/mixins/__tests__/verifyServiceActingAs.test.ts +167 -0
  549. package/src/mixins/__tests__/webauthnAuth.test.ts +205 -0
  550. package/src/mixins/index.ts +201 -0
  551. package/src/mixins/mixinHelpers.ts +69 -0
  552. package/src/models/Topic.ts +46 -0
  553. package/src/models/interfaces.ts +786 -0
  554. package/src/models/session.ts +55 -0
  555. package/src/server/__tests__/auth.test.ts +78 -0
  556. package/src/server/__tests__/capabilityTicket.test.ts +111 -0
  557. package/src/server/__tests__/cors.socket.test.ts +225 -0
  558. package/src/server/__tests__/cors.test.ts +158 -0
  559. package/src/server/__tests__/rateLimit.test.ts +257 -0
  560. package/src/server/__tests__/safeFetch.test.ts +232 -0
  561. package/src/server/__tests__/securityHeaders.test.ts +348 -0
  562. package/src/server/__tests__/serviceTokenAttribution.test.ts +396 -0
  563. package/src/server/__tests__/userInvalidation.test.ts +203 -0
  564. package/src/server/__tests__/verifySecret.test.ts +40 -0
  565. package/src/server/auth.ts +271 -0
  566. package/src/server/capabilityTicket.ts +258 -0
  567. package/src/server/cors.ts +277 -0
  568. package/src/server/index.ts +136 -0
  569. package/src/server/rateLimit.ts +313 -0
  570. package/src/server/safeFetch.ts +586 -0
  571. package/src/server/securityHeaders.ts +467 -0
  572. package/src/server/userInvalidation.ts +199 -0
  573. package/src/server/verifySecret.ts +52 -0
  574. package/src/session/SessionClient.ts +1001 -0
  575. package/src/session/__tests__/SessionClient.additive.test.ts +153 -0
  576. package/src/session/__tests__/SessionClient.broadcastChannel.test.ts +114 -0
  577. package/src/session/__tests__/SessionClient.diagnostics.test.ts +91 -0
  578. package/src/session/__tests__/SessionClient.directory.test.ts +688 -0
  579. package/src/session/__tests__/SessionClient.httpIntegration.test.ts +65 -0
  580. package/src/session/__tests__/SessionClient.identityPin.test.ts +175 -0
  581. package/src/session/__tests__/SessionClient.rest.test.ts +119 -0
  582. package/src/session/__tests__/SessionClient.serverEvents.test.ts +72 -0
  583. package/src/session/__tests__/SessionClient.socket.test.ts +202 -0
  584. package/src/session/__tests__/SessionClient.socketFactory.test.ts +81 -0
  585. package/src/session/__tests__/SessionClient.state.test.ts +78 -0
  586. package/src/session/__tests__/SessionClient.switchTokenOrder.test.ts +170 -0
  587. package/src/session/__tests__/accountDelegationAccess.test.ts +104 -0
  588. package/src/session/__tests__/accountDialogController.test.ts +1969 -0
  589. package/src/session/__tests__/accountDialogShape.test.ts +118 -0
  590. package/src/session/__tests__/accountSwitchTargets.test.ts +137 -0
  591. package/src/session/__tests__/authStateStore.test.ts +451 -0
  592. package/src/session/__tests__/deviceDirectory.test.ts +422 -0
  593. package/src/session/__tests__/deviceSwitcherRows.test.ts +223 -0
  594. package/src/session/__tests__/identityPin.test.ts +131 -0
  595. package/src/session/__tests__/identitySession.test.ts +194 -0
  596. package/src/session/__tests__/projectSessionState.test.ts +105 -0
  597. package/src/session/__tests__/refresh.identityPin.test.ts +307 -0
  598. package/src/session/__tests__/refresh.test.ts +443 -0
  599. package/src/session/__tests__/sessionIntegration.test.ts +209 -0
  600. package/src/session/__tests__/sharedDeviceCredential.test.ts +300 -0
  601. package/src/session/accountDelegationAccess.ts +72 -0
  602. package/src/session/accountDialogController.ts +1494 -0
  603. package/src/session/accountSwitchTargets.ts +93 -0
  604. package/src/session/authStateStore.ts +502 -0
  605. package/src/session/createSessionClient.ts +39 -0
  606. package/src/session/deviceDirectory.ts +269 -0
  607. package/src/session/deviceSwitcherRows.ts +145 -0
  608. package/src/session/identityPin.ts +310 -0
  609. package/src/session/identitySession.ts +206 -0
  610. package/src/session/projectSessionState.ts +137 -0
  611. package/src/session/refresh.ts +517 -0
  612. package/src/session/sessionClientHost.ts +39 -0
  613. package/src/session/sharedDeviceCredential.ts +349 -0
  614. package/src/session/socketLoader.ts +30 -0
  615. package/src/shared/utils/colorUtils.ts +155 -0
  616. package/src/shared/utils/errorUtils.ts +181 -0
  617. package/src/shared/utils/index.ts +59 -0
  618. package/src/shared/utils/networkUtils.ts +248 -0
  619. package/src/shared/utils/themeUtils.ts +115 -0
  620. package/src/types/buffer.d.ts +97 -0
  621. package/src/types/expo-crypto.d.ts +16 -0
  622. package/src/types/expo-secure-store.d.ts +17 -0
  623. package/src/utils/__tests__/accountUtils.test.ts +151 -0
  624. package/src/utils/__tests__/activityId.test.ts +45 -0
  625. package/src/utils/__tests__/asyncUtils.test.ts +187 -0
  626. package/src/utils/__tests__/authWebUrl.test.ts +15 -0
  627. package/src/utils/__tests__/cacheKey.test.ts +0 -0
  628. package/src/utils/__tests__/coldBoot.test.ts +496 -0
  629. package/src/utils/__tests__/commonsApproval.test.ts +60 -0
  630. package/src/utils/__tests__/identityCacheSweep.test.ts +151 -0
  631. package/src/utils/__tests__/languageUtils.test.ts +219 -0
  632. package/src/utils/__tests__/oauthPkce.test.ts +272 -0
  633. package/src/utils/__tests__/officialOrigins.test.ts +31 -0
  634. package/src/utils/__tests__/oxyServiceEnvironment.test.ts +7 -0
  635. package/src/utils/__tests__/profileLinks.test.ts +180 -0
  636. package/src/utils/__tests__/redactUrl.test.ts +33 -0
  637. package/src/utils/__tests__/registrableApex.test.ts +62 -0
  638. package/src/utils/__tests__/textNormalization.test.ts +205 -0
  639. package/src/utils/__tests__/validationUtils.test.ts +703 -0
  640. package/src/utils/__tests__/webauthnOrigin.test.ts +83 -0
  641. package/src/utils/accountCacheSweep.ts +93 -0
  642. package/src/utils/accountUtils.ts +194 -0
  643. package/src/utils/activityId.ts +2 -0
  644. package/src/utils/apiUtils.ts +137 -0
  645. package/src/utils/asyncUtils.ts +280 -0
  646. package/src/utils/authHelpers.ts +148 -0
  647. package/src/utils/authWebUrl.ts +17 -0
  648. package/src/utils/avatarUtils.ts +39 -0
  649. package/src/utils/cache.ts +273 -0
  650. package/src/utils/cacheKey.ts +93 -0
  651. package/src/utils/coldBoot.ts +218 -0
  652. package/src/utils/commonsApproval.ts +39 -0
  653. package/src/utils/commonsDelivery.ts +132 -0
  654. package/src/utils/deviceManager.ts +203 -0
  655. package/src/utils/displayNamePolicyRanges.generated.ts +69 -0
  656. package/src/utils/edgeRegion.ts +2 -0
  657. package/src/utils/errorUtils.ts +352 -0
  658. package/src/utils/identityCacheSweep.ts +104 -0
  659. package/src/utils/languageUtils.ts +256 -0
  660. package/src/utils/oauthPkce.ts +392 -0
  661. package/src/utils/officialOrigins.ts +62 -0
  662. package/src/utils/oxyServiceEnvironment.ts +17 -0
  663. package/src/utils/platform.ts +139 -0
  664. package/src/utils/profileLinks.ts +91 -0
  665. package/src/utils/redactUrl.ts +28 -0
  666. package/src/utils/registrableApex.ts +41 -0
  667. package/src/utils/requestUtils.ts +237 -0
  668. package/src/utils/sessionUtils.ts +206 -0
  669. package/src/utils/textNormalization.ts +162 -0
  670. package/src/utils/userHandle.ts +49 -0
  671. package/src/utils/userIdentity.ts +60 -0
  672. package/src/utils/validationUtils.ts +390 -0
  673. package/src/utils/webauthnOrigin.ts +52 -0
@@ -0,0 +1,93 @@
1
+ /**
2
+ * The two questions an account chooser asks of an account-graph node: is this
3
+ * kind switchable at all, and may THIS caller become it.
4
+ *
5
+ * Pure and I/O-free. They live here rather than beside the surfaces that ask
6
+ * them because there is more than one such surface — the Console's workspace
7
+ * tree, the Accounts app's managed-account rows — and a second enumeration of
8
+ * switch targets is a second place for the rule to go missing, which is
9
+ * precisely how the Console went on offering `channel` rows after the rule
10
+ * learned to drop them.
11
+ *
12
+ * The DEVICE switcher no longer asks anything here: it renders the server's
13
+ * device directory (ADR 0002, `deviceDirectory.ts`), whose `available` field is
14
+ * the server's own authorization verdict. These predicates answer a different
15
+ * question — one about the caller's account GRAPH, which is a list of accounts
16
+ * to manage, not a list of identities the device can become.
17
+ */
18
+
19
+ import { isOperatorSwitchTargetKind } from '@oxy.so/contracts';
20
+ import type {
21
+ AccountRelationship,
22
+ AccountKind,
23
+ AccountMember,
24
+ } from '../mixins/OxyServices.accounts';
25
+
26
+ /**
27
+ * Whether the caller can BECOME this account — the one question every account
28
+ * switcher asks, answered here so no surface has to re-derive it.
29
+ *
30
+ * Two independent grounds, either of which suffices:
31
+ *
32
+ * - **It is already the caller's own identity** (`relationship: 'self'`).
33
+ * `GET /accounts` resolves its caller through `resolveOperatorId`, so `self`
34
+ * is the HUMAN operator's personal account even while they are operating an
35
+ * org — never the operated account. Kind is irrelevant on this ground: the
36
+ * caller IS that account, so returning to it asks the server for nothing.
37
+ * - **The server will mint a session for it** — `isOperatorSwitchTargetKind(kind)`
38
+ * is the exact predicate `POST /accounts/:id/switch` enforces, so a row
39
+ * offered on this ground is never a dead button.
40
+ *
41
+ * `isOperatorSwitchTargetKind` ALONE is not this question, and reaching for it
42
+ * directly is the mistake this function exists to prevent: it is false for
43
+ * `personal` as well as `channel`, so a switcher gated on it alone renders an
44
+ * empty list rather than a filtered one. Equally, `kind !== 'channel'` is not
45
+ * this question either — it silently admits every kind invented after it was
46
+ * written, which is the same trap the kind predicates were introduced to close
47
+ * on the server.
48
+ *
49
+ * And it is the OPERATOR predicate, never `isDelegatedActAsEligibleKind`. The
50
+ * two differ only on `bot`, so the delegated one produces a list that looks
51
+ * right and contains one row too many — a seat inside the identity that exists
52
+ * to act while nobody is present. That is not a hypothetical: it put a live bot
53
+ * session on a person's own device, beside their personal login.
54
+ *
55
+ * Takes a structural subset rather than a whole {@link AccountNode} so a caller
56
+ * holding an already-projected row can ask it too.
57
+ */
58
+ export function isSwitchTargetAccount(
59
+ node: { kind?: AccountKind | null; relationship?: AccountRelationship },
60
+ ): boolean {
61
+ return node.relationship === 'self' || isOperatorSwitchTargetKind(node.kind);
62
+ }
63
+
64
+ /**
65
+ * Whether the caller may switch INTO this account — the server-side
66
+ * `account:act_as` gate plus the structural {@link isSwitchTargetAccount} rule.
67
+ *
68
+ * `relationship: 'self'` always passes (returning to the caller's own personal
69
+ * account). Every other ground requires a switch-eligible kind AND
70
+ * `account:act_as` in the resolved membership permissions. When permissions are
71
+ * absent but the relationship is `owner`, the owner baseline is assumed — the
72
+ * API always resolves effective permissions for owned accounts, but test
73
+ * fixtures and stale rows may omit the membership blob.
74
+ */
75
+ export function canSwitchIntoAccount(
76
+ node: {
77
+ kind?: AccountKind | null;
78
+ relationship?: AccountRelationship;
79
+ callerMembership?: AccountMember | null;
80
+ },
81
+ ): boolean {
82
+ if (node.relationship === 'self') {
83
+ return true;
84
+ }
85
+ if (!isSwitchTargetAccount(node)) {
86
+ return false;
87
+ }
88
+ const permissions = node.callerMembership?.permissions;
89
+ if (permissions) {
90
+ return permissions.includes('account:act_as');
91
+ }
92
+ return node.relationship === 'owner';
93
+ }
@@ -0,0 +1,502 @@
1
+ /**
2
+ * Persisted auth state — ONE shape, web + native.
3
+ *
4
+ * The zero-cookie device transport persists the device credential per ORIGIN so
5
+ * a reload restores the session locally without a redirect: `deviceId` +
6
+ * `deviceSecret` mint a fresh access token via `POST /session/device/token`.
7
+ * This module is the storage seam: a tiny `load / save / clear` interface plus
8
+ * platform factories, so the cold boot (`sessionColdBoot`) and the unified re-mint
9
+ * handler (`refresh.ts`) never touch a platform storage API directly.
10
+ *
11
+ * Platform-agnostic — the native factory takes an INJECTED key/value store
12
+ * (`@oxy.so/services` passes a SecureStore-backed adapter) so `@oxy.so/core`
13
+ * never imports `expo-secure-store`. The web factory is self-contained
14
+ * (`localStorage`) and degrades to in-memory when storage is unavailable
15
+ * (sandboxed iframe `SecurityError`, private-mode quota, SSR).
16
+ *
17
+ * ESM-safe (no `require()`).
18
+ */
19
+
20
+ import { logger } from '../logger';
21
+
22
+ /**
23
+ * The persisted session credential set for a single origin.
24
+ *
25
+ * `sessionId` + `userId` identify the owning device session and active account.
26
+ * `deviceId` + `deviceSecret` are the zero-cookie mint credential: the client
27
+ * presents BOTH at `POST /session/device/token` — the secret is the proof, the
28
+ * deviceId selects the device doc. The secret is rotated in-use: the mint returns
29
+ * `nextDeviceSecret`, which the cold boot / re-mint handler persist BEFORE
30
+ * planting the minted access token (multi-tab anti-loss).
31
+ *
32
+ * `accessToken` + `expiresAt` are OPTIONAL warm-boot fields. Persisting them lets
33
+ * the cold boot plant a still-valid access token on the very first paint WITHOUT
34
+ * a blocking mint round-trip — the proactive scheduler then rotates it in the
35
+ * background. They are a strict optimization: the store is fully functional (via
36
+ * `deviceSecret`) when they are absent or stale, and the access token is
37
+ * short-lived, so persisting it adds no exposure the already-persisted
38
+ * `deviceSecret` does not.
39
+ */
40
+ export interface PersistedAuthState {
41
+ sessionId: string;
42
+ userId: string;
43
+ /**
44
+ * The stable device identifier this session is bound to (zero-cookie
45
+ * transport). Persisted alongside {@link deviceSecret} because the
46
+ * `POST /session/device/token` mint presents BOTH. Sourced from every login
47
+ * lane (password / 2FA / QR claim / challenge verify) via the response's
48
+ * `deviceId`.
49
+ */
50
+ deviceId?: string;
51
+ /**
52
+ * The rotating device secret (zero-cookie transport). Possession of it mints a
53
+ * short access token for the device's active account via
54
+ * `POST /session/device/token`. Rotated in-use.
55
+ */
56
+ deviceSecret?: string;
57
+ /** Optional warm-boot access token (short-lived; see interface docs). */
58
+ accessToken?: string;
59
+ /** Optional warm-boot access-token expiry, ISO-8601. */
60
+ expiresAt?: string;
61
+ }
62
+
63
+ /**
64
+ * The storage seam consumed by the cold boot and the re-mint handler. Async
65
+ * throughout so one interface fits both synchronous web `localStorage` and
66
+ * asynchronous native SecureStore/AsyncStorage. `clear()` (sign-out) wipes the
67
+ * per-sign-in credential blob.
68
+ */
69
+ export interface AuthStateStore {
70
+ load(): Promise<PersistedAuthState | null>;
71
+ /**
72
+ * Persist the credential blob and report whether it durably landed.
73
+ *
74
+ * Resolves `true` when the state is retained consistent with this store's
75
+ * durability guarantee — a durable backing whose read-back matched, or a
76
+ * degraded/in-memory store that held it in memory. Resolves `false` when a
77
+ * DURABLE backing was expected but the write did NOT land (read-back mismatch
78
+ * or a thrown write); the in-memory mirror still keeps the session live for
79
+ * this process, but it will be lost on reload.
80
+ *
81
+ * A lane persisting a ROTATED device secret (the mint's `nextDeviceSecret`)
82
+ * MUST treat `false` as fatal for that mint: it must NOT plant/advertise a
83
+ * session built on a secret that will not survive a reload.
84
+ */
85
+ save(state: PersistedAuthState): Promise<boolean>;
86
+ clear(): Promise<void>;
87
+ }
88
+
89
+ /**
90
+ * The minimal async key/value surface a native store must provide. Matches
91
+ * both `expo-secure-store` (wrapped) and `@react-native-async-storage`.
92
+ */
93
+ export interface NativeKeyValueStorage {
94
+ getItem(key: string): Promise<string | null>;
95
+ setItem(key: string, value: string): Promise<void>;
96
+ removeItem(key: string): Promise<void>;
97
+ }
98
+
99
+ /**
100
+ * Versioned DURABLE storage key. Holds ONLY the small, re-mint-critical fields
101
+ * (`sessionId`, `userId`, `deviceId`, `deviceSecret`) — never the large JWT
102
+ * `accessToken`. Keeping this blob small (<2KB) matters on Android
103
+ * `expo-secure-store`, whose backing store can silently fail to persist an
104
+ * oversize value; bundling the token here previously took the mint credential
105
+ * down with it on every write, losing the session on cold restart.
106
+ *
107
+ * The `.v1` suffix lets a future shape change ship a `.v2` key without reading a
108
+ * stale/incompatible `.v1` blob. Distinct from the `oxy_shared_*` keychain keys
109
+ * in `KeyManager`, so it never collides.
110
+ *
111
+ * BACK-COMPAT: pre-split builds wrote the WHOLE state (including `accessToken` /
112
+ * `expiresAt`) into this single key. `load()` still reads those token fields
113
+ * from here when the warm key ({@link AUTH_STATE_TOKEN_STORAGE_KEY}) is absent,
114
+ * so upgrading users are not signed out; the next `save()` splits them apart.
115
+ */
116
+ export const AUTH_STATE_STORAGE_KEY = 'oxy.auth.v1';
117
+
118
+ /**
119
+ * Versioned BEST-EFFORT warm-token storage key. Holds the short-lived
120
+ * `{ accessToken, expiresAt }` pair only. Its write is genuinely non-fatal — a
121
+ * failure (quota / oversize keychain value) is swallowed because the session is
122
+ * fully re-mintable from the durable `deviceSecret`. Kept separate from
123
+ * {@link AUTH_STATE_STORAGE_KEY} so a failed token write can NEVER abort or
124
+ * corrupt the durable credential write.
125
+ */
126
+ export const AUTH_STATE_TOKEN_STORAGE_KEY = 'oxy.auth.token.v1';
127
+
128
+ /**
129
+ * Parse + shape-validate a stored blob. Returns `null` for anything that is
130
+ * not a well-formed {@link PersistedAuthState} (absent, malformed JSON, wrong
131
+ * types) so a corrupt entry degrades to "signed out" rather than throwing.
132
+ */
133
+ function deserialize(raw: string | null): PersistedAuthState | null {
134
+ if (!raw) {
135
+ return null;
136
+ }
137
+ let parsed: unknown;
138
+ try {
139
+ parsed = JSON.parse(raw);
140
+ } catch {
141
+ return null;
142
+ }
143
+ if (!parsed || typeof parsed !== 'object') {
144
+ return null;
145
+ }
146
+ const candidate = parsed as Record<string, unknown>;
147
+ const hasDeviceCredential =
148
+ typeof candidate.deviceId === 'string' &&
149
+ candidate.deviceId.length > 0 &&
150
+ typeof candidate.deviceSecret === 'string' &&
151
+ candidate.deviceSecret.length > 0;
152
+
153
+ const hasSessionIdentity =
154
+ typeof candidate.sessionId === 'string' &&
155
+ typeof candidate.userId === 'string' &&
156
+ candidate.sessionId.length > 0 &&
157
+ candidate.userId.length > 0;
158
+
159
+ // Device-only bootstrap (post join, pre-sign-in): durable credential without session.
160
+ if (!hasSessionIdentity && !hasDeviceCredential) {
161
+ return null;
162
+ }
163
+
164
+ const state: PersistedAuthState = {
165
+ sessionId: hasSessionIdentity ? (candidate.sessionId as string) : '',
166
+ userId: hasSessionIdentity ? (candidate.userId as string) : '',
167
+ };
168
+ if (typeof candidate.deviceId === 'string' && candidate.deviceId.length > 0) {
169
+ state.deviceId = candidate.deviceId;
170
+ }
171
+ if (typeof candidate.deviceSecret === 'string' && candidate.deviceSecret.length > 0) {
172
+ state.deviceSecret = candidate.deviceSecret;
173
+ }
174
+ if (typeof candidate.accessToken === 'string' && candidate.accessToken.length > 0) {
175
+ state.accessToken = candidate.accessToken;
176
+ }
177
+ if (typeof candidate.expiresAt === 'string' && candidate.expiresAt.length > 0) {
178
+ state.expiresAt = candidate.expiresAt;
179
+ }
180
+ return state;
181
+ }
182
+
183
+ /** The parsed warm-token blob: the short-lived optimization fields only. */
184
+ interface WarmToken {
185
+ accessToken?: string;
186
+ expiresAt?: string;
187
+ }
188
+
189
+ /**
190
+ * Parse the best-effort warm-token blob. Returns `null` for anything not a
191
+ * well-formed object so a corrupt warm entry simply forgoes the warm-boot
192
+ * optimization (the durable credential re-mints a fresh token).
193
+ */
194
+ function parseWarmToken(raw: string | null): WarmToken | null {
195
+ if (!raw) {
196
+ return null;
197
+ }
198
+ let parsed: unknown;
199
+ try {
200
+ parsed = JSON.parse(raw);
201
+ } catch {
202
+ return null;
203
+ }
204
+ if (!parsed || typeof parsed !== 'object') {
205
+ return null;
206
+ }
207
+ const candidate = parsed as Record<string, unknown>;
208
+ const warm: WarmToken = {};
209
+ if (typeof candidate.accessToken === 'string' && candidate.accessToken.length > 0) {
210
+ warm.accessToken = candidate.accessToken;
211
+ }
212
+ if (typeof candidate.expiresAt === 'string' && candidate.expiresAt.length > 0) {
213
+ warm.expiresAt = candidate.expiresAt;
214
+ }
215
+ return warm;
216
+ }
217
+
218
+ /** Serialize ONLY the small, re-mint-critical fields for the durable key. */
219
+ function serializeDurable(state: PersistedAuthState): string {
220
+ const durable: Record<string, string> = {
221
+ sessionId: state.sessionId,
222
+ userId: state.userId,
223
+ };
224
+ if (state.deviceId) {
225
+ durable.deviceId = state.deviceId;
226
+ }
227
+ if (state.deviceSecret) {
228
+ durable.deviceSecret = state.deviceSecret;
229
+ }
230
+ return JSON.stringify(durable);
231
+ }
232
+
233
+ /**
234
+ * Serialize the warm-token blob, or `null` when there is no token to persist
235
+ * (so the caller clears the warm key rather than writing an empty object).
236
+ */
237
+ function serializeWarmToken(state: PersistedAuthState): string | null {
238
+ const warm: WarmToken = {};
239
+ if (state.accessToken) {
240
+ warm.accessToken = state.accessToken;
241
+ }
242
+ if (state.expiresAt) {
243
+ warm.expiresAt = state.expiresAt;
244
+ }
245
+ if (!warm.accessToken && !warm.expiresAt) {
246
+ return null;
247
+ }
248
+ return JSON.stringify(warm);
249
+ }
250
+
251
+ /**
252
+ * Compose the unchanged {@link PersistedAuthState} return shape from the two
253
+ * on-disk keys. `accessToken` / `expiresAt` come from the warm key when it is
254
+ * present; when the warm key is ABSENT the token fields fall back to whatever
255
+ * the durable blob carried — the pre-split combined `oxy.auth.v1` blob (BACK-COMPAT).
256
+ */
257
+ function composeState(durableRaw: string | null, warmRaw: string | null): PersistedAuthState | null {
258
+ const state = deserialize(durableRaw);
259
+ if (!state) {
260
+ return null;
261
+ }
262
+ if (warmRaw !== null) {
263
+ // New split layout: the warm key is authoritative for the token fields.
264
+ // Drop anything the durable blob may have carried, then overlay the warm
265
+ // values (a warm key with no token → the session simply has no warm token).
266
+ delete state.accessToken;
267
+ delete state.expiresAt;
268
+ const warm = parseWarmToken(warmRaw);
269
+ if (warm?.accessToken) {
270
+ state.accessToken = warm.accessToken;
271
+ }
272
+ if (warm?.expiresAt) {
273
+ state.expiresAt = warm.expiresAt;
274
+ }
275
+ }
276
+ // else: BACK-COMPAT — the warm key is absent, so `deserialize` already applied
277
+ // any `accessToken` / `expiresAt` from the old combined blob.
278
+ return state;
279
+ }
280
+
281
+ /**
282
+ * A process-lifetime, in-memory {@link AuthStateStore}. Used directly for
283
+ * tests/SSR and as the degraded fallback of the web store when `localStorage`
284
+ * is unreachable. Not durable across reloads — that is acceptable for the
285
+ * fallback because the alternative (throwing) would break cold boot entirely.
286
+ */
287
+ export function createMemoryAuthStateStore(): AuthStateStore {
288
+ let current: PersistedAuthState | null = null;
289
+ return {
290
+ load: async () => current,
291
+ save: async (state) => {
292
+ // Memory IS this store's durability backing — the write always lands.
293
+ current = state;
294
+ return true;
295
+ },
296
+ clear: async () => {
297
+ current = null;
298
+ },
299
+ };
300
+ }
301
+
302
+ /**
303
+ * Read the ambient `localStorage`, tolerating the case where merely ACCESSING
304
+ * `window.localStorage` throws. In a sandboxed / cross-origin iframe the getter
305
+ * itself raises `SecurityError` (not the method calls), so the access must be
306
+ * inside the try. Returns `null` when storage is unavailable.
307
+ */
308
+ function safeGetLocalStorage(): Storage | null {
309
+ try {
310
+ if (typeof globalThis === 'undefined') {
311
+ return null;
312
+ }
313
+ const store = (globalThis as { localStorage?: Storage }).localStorage;
314
+ return store ?? null;
315
+ } catch {
316
+ return null;
317
+ }
318
+ }
319
+
320
+ /**
321
+ * A `localStorage`-backed {@link AuthStateStore} split across the durable
322
+ * {@link AUTH_STATE_STORAGE_KEY} (mint credential) and the best-effort
323
+ * {@link AUTH_STATE_TOKEN_STORAGE_KEY} (warm access token).
324
+ *
325
+ * Resilience:
326
+ * - If `localStorage` is unreachable (sandboxed-iframe `SecurityError`, SSR),
327
+ * the whole store degrades to an in-memory {@link createMemoryAuthStateStore}
328
+ * for this page's lifetime — never throws on construction.
329
+ * - Individual `getItem`/`setItem`/`removeItem` are each wrapped: a read that
330
+ * throws yields `null`; a write that throws (quota, private mode) is
331
+ * swallowed. The re-mint lane treats a failed persist as "no durable state"
332
+ * rather than crashing.
333
+ */
334
+ export function createWebAuthStateStore(): AuthStateStore {
335
+ const storage = safeGetLocalStorage();
336
+ if (!storage) {
337
+ return createMemoryAuthStateStore();
338
+ }
339
+ // In-memory mirror so a FAILED persist (quota / private mode / locked store)
340
+ // does not silently lose the session for this page's lifetime. `undefined`
341
+ // means "never written this session" → fall back to storage; any set value
342
+ // (including `null` after clear) is authoritative and preferred over storage.
343
+ let sessionMirror: PersistedAuthState | null | undefined;
344
+ return {
345
+ load: async () => {
346
+ if (sessionMirror !== undefined) {
347
+ return sessionMirror;
348
+ }
349
+ try {
350
+ return composeState(
351
+ storage.getItem(AUTH_STATE_STORAGE_KEY),
352
+ storage.getItem(AUTH_STATE_TOKEN_STORAGE_KEY),
353
+ );
354
+ } catch {
355
+ return null;
356
+ }
357
+ },
358
+ save: async (state) => {
359
+ sessionMirror = state; // mirror FIRST — authoritative even if persist fails
360
+ // Durable credential FIRST, then VERIFY it landed. The in-memory mirror
361
+ // keeps the session live for this page, but a failed DURABLE write means
362
+ // the mint credential will NOT survive a reload — surface it, never swallow.
363
+ let durablePersisted = false;
364
+ try {
365
+ const durableJson = serializeDurable(state);
366
+ storage.setItem(AUTH_STATE_STORAGE_KEY, durableJson);
367
+ durablePersisted = storage.getItem(AUTH_STATE_STORAGE_KEY) === durableJson;
368
+ if (!durablePersisted) {
369
+ logger.error(
370
+ '[authStateStore] durable credential read-back mismatch after save — the device credential did not persist; the session survives this process via the in-memory mirror but will be lost on reload',
371
+ undefined,
372
+ { component: 'authStateStore' },
373
+ );
374
+ }
375
+ } catch (error) {
376
+ logger.error(
377
+ '[authStateStore] durable credential persist threw — the device credential did not persist; the session survives this process via the in-memory mirror but will be lost on reload',
378
+ error,
379
+ { component: 'authStateStore' },
380
+ );
381
+ }
382
+ // Warm token AFTER, best-effort. Its failure is genuinely non-fatal (the
383
+ // durable credential re-mints a fresh token) and must never abort or
384
+ // corrupt the durable write above.
385
+ try {
386
+ const warmJson = serializeWarmToken(state);
387
+ if (warmJson) {
388
+ storage.setItem(AUTH_STATE_TOKEN_STORAGE_KEY, warmJson);
389
+ } else {
390
+ storage.removeItem(AUTH_STATE_TOKEN_STORAGE_KEY);
391
+ }
392
+ } catch {
393
+ // Quota / private-mode / disabled storage — non-fatal warm-boot loss only.
394
+ }
395
+ // Report ONLY the durable-credential landing; the warm-token outcome above
396
+ // is intentionally excluded (it is a best-effort optimization).
397
+ return durablePersisted;
398
+ },
399
+ clear: async () => {
400
+ sessionMirror = null;
401
+ try {
402
+ storage.removeItem(AUTH_STATE_STORAGE_KEY);
403
+ } catch {
404
+ // Non-fatal — see save().
405
+ }
406
+ try {
407
+ storage.removeItem(AUTH_STATE_TOKEN_STORAGE_KEY);
408
+ } catch {
409
+ // Non-fatal — see save().
410
+ }
411
+ },
412
+ };
413
+ }
414
+
415
+ /**
416
+ * A native {@link AuthStateStore} over an injected async key/value store.
417
+ *
418
+ * `@oxy.so/core` never imports `expo-secure-store`; `@oxy.so/services` constructs
419
+ * the SecureStore-backed adapter and passes it here. Persistence is split across
420
+ * the durable {@link AUTH_STATE_STORAGE_KEY} (mint credential) and the
421
+ * best-effort {@link AUTH_STATE_TOKEN_STORAGE_KEY} (warm access token) — the
422
+ * durable write is read-back-verified and its failure surfaced (not swallowed),
423
+ * while the warm-token write and all reads degrade gracefully exactly like the
424
+ * web store.
425
+ */
426
+ export function createNativeAuthStateStore(storage: NativeKeyValueStorage): AuthStateStore {
427
+ // Same in-memory mirror as the web store — a locked/failed SecureStore write
428
+ // must not silently lose the session for the app's lifetime.
429
+ let sessionMirror: PersistedAuthState | null | undefined;
430
+ return {
431
+ load: async () => {
432
+ if (sessionMirror !== undefined) {
433
+ return sessionMirror;
434
+ }
435
+ try {
436
+ const [durableRaw, warmRaw] = await Promise.all([
437
+ storage.getItem(AUTH_STATE_STORAGE_KEY),
438
+ storage.getItem(AUTH_STATE_TOKEN_STORAGE_KEY),
439
+ ]);
440
+ return composeState(durableRaw, warmRaw);
441
+ } catch {
442
+ return null;
443
+ }
444
+ },
445
+ save: async (state) => {
446
+ sessionMirror = state;
447
+ // Durable credential FIRST, then VERIFY. On Android SecureStore an
448
+ // oversize/failed write can resolve WITHOUT throwing, so a read-back is the
449
+ // only reliable proof. The mirror keeps the session live for this app run,
450
+ // but a failed DURABLE write means the mint credential will NOT survive a
451
+ // cold restart — surface it, never swallow.
452
+ let durablePersisted = false;
453
+ try {
454
+ const durableJson = serializeDurable(state);
455
+ await storage.setItem(AUTH_STATE_STORAGE_KEY, durableJson);
456
+ durablePersisted = (await storage.getItem(AUTH_STATE_STORAGE_KEY)) === durableJson;
457
+ if (!durablePersisted) {
458
+ logger.error(
459
+ '[authStateStore] durable credential read-back mismatch after save — the device credential did not persist (likely oversize SecureStore value); the session survives this app run via the in-memory mirror but will be lost on cold restart',
460
+ undefined,
461
+ { component: 'authStateStore' },
462
+ );
463
+ }
464
+ } catch (error) {
465
+ logger.error(
466
+ '[authStateStore] durable credential persist threw — the device credential did not persist; the session survives this app run via the in-memory mirror but will be lost on cold restart',
467
+ error,
468
+ { component: 'authStateStore' },
469
+ );
470
+ }
471
+ // Warm token AFTER, best-effort. Its failure is genuinely non-fatal (the
472
+ // durable credential re-mints a fresh token) and must never abort or
473
+ // corrupt the durable write above.
474
+ try {
475
+ const warmJson = serializeWarmToken(state);
476
+ if (warmJson) {
477
+ await storage.setItem(AUTH_STATE_TOKEN_STORAGE_KEY, warmJson);
478
+ } else {
479
+ await storage.removeItem(AUTH_STATE_TOKEN_STORAGE_KEY);
480
+ }
481
+ } catch {
482
+ // Locked / oversize keychain — non-fatal warm-boot loss only.
483
+ }
484
+ // Report ONLY the durable-credential landing; the warm-token outcome above
485
+ // is intentionally excluded (it is a best-effort optimization).
486
+ return durablePersisted;
487
+ },
488
+ clear: async () => {
489
+ sessionMirror = null;
490
+ try {
491
+ await storage.removeItem(AUTH_STATE_STORAGE_KEY);
492
+ } catch {
493
+ // Non-fatal.
494
+ }
495
+ try {
496
+ await storage.removeItem(AUTH_STATE_TOKEN_STORAGE_KEY);
497
+ } catch {
498
+ // Non-fatal.
499
+ }
500
+ },
501
+ };
502
+ }
@@ -0,0 +1,39 @@
1
+ import type { OxyServices } from '../OxyServices';
2
+ import { SessionClient, type TokenTransport } from './SessionClient';
3
+ import type { SocketIOFactory } from './socketLoader';
4
+ import { createSessionClientHost } from './sessionClientHost';
5
+
6
+ /**
7
+ * Wires a `SessionClient` over the given `OxyServices` instance: builds the
8
+ * `SessionClientHost` adapter and passes it through together with a
9
+ * caller-supplied `TokenTransport`.
10
+ *
11
+ * The transport is a required parameter (not constructed here) because it is
12
+ * the one piece of this integration that is NOT platform-agnostic: `services`
13
+ * branches native (shared-keychain sign-in) vs. web (silent sign-in), while
14
+ * `auth-sdk` is web-only. Each consumer builds its own transport and passes
15
+ * it in; this factory only wires the platform-agnostic parts (host + client)
16
+ * so neither consumer re-implements them.
17
+ *
18
+ * The host is returned alongside the client (not just the client) so the
19
+ * caller can call `host.setCurrentAccountId(...)` as the active account
20
+ * changes.
21
+ *
22
+ * `socketFactory` is the statically-injected `socket.io-client` `io` export.
23
+ * Consumers that bundle socket.io-client as a real dependency pass it so
24
+ * realtime sync never depends on core's lazy dynamic import of a bare
25
+ * specifier (bundler-fragile in Metro/Expo-web and Vite against the published
26
+ * dist). When omitted, the client falls back to the lazy loader.
27
+ */
28
+ export function createSessionClient(
29
+ oxyServices: OxyServices,
30
+ transport: TokenTransport,
31
+ socketFactory?: SocketIOFactory,
32
+ ): {
33
+ client: SessionClient;
34
+ host: ReturnType<typeof createSessionClientHost>;
35
+ } {
36
+ const host = createSessionClientHost(oxyServices);
37
+ const client = new SessionClient(host, { transport, socketFactory });
38
+ return { client, host };
39
+ }