@oxy.so/core 4.5.0-oxy-one.0 → 4.5.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 (285) hide show
  1. package/README.md +1 -1
  2. package/dist/cjs/HttpService.js +63 -19
  3. package/dist/cjs/api/accounts.js +10 -3
  4. package/dist/cjs/api/agency.js +3 -1
  5. package/dist/cjs/api/apps.js +15 -4
  6. package/dist/cjs/api/assets.js +49 -12
  7. package/dist/cjs/api/auth.js +37 -11
  8. package/dist/cjs/api/billing.js +24 -7
  9. package/dist/cjs/api/civic.js +14 -4
  10. package/dist/cjs/api/follows.js +9 -2
  11. package/dist/cjs/api/identity.js +31 -9
  12. package/dist/cjs/api/nodes.js +3 -1
  13. package/dist/cjs/api/privacy.js +8 -2
  14. package/dist/cjs/api/session.js +15 -4
  15. package/dist/cjs/api/store.js +15 -5
  16. package/dist/cjs/api/topics.js +10 -3
  17. package/dist/cjs/api/users.js +16 -4
  18. package/dist/cjs/boot/sessionColdBoot.js +40 -13
  19. package/dist/cjs/constants/version.js +6 -6
  20. package/dist/cjs/crypto/identityMarker.js +3 -1
  21. package/dist/cjs/crypto/identityProof.js +6 -1
  22. package/dist/cjs/crypto/keyManager.js +87 -32
  23. package/dist/cjs/crypto/recoveryPhrase.js +2 -2
  24. package/dist/cjs/crypto/signatureService.js +3 -4
  25. package/dist/cjs/i18n/index.js +16 -3
  26. package/dist/cjs/i18n/locales/ar-SA.js +366 -366
  27. package/dist/cjs/i18n/locales/ca-ES.js +366 -366
  28. package/dist/cjs/i18n/locales/de-DE.js +366 -366
  29. package/dist/cjs/i18n/locales/en-US.js +1994 -1994
  30. package/dist/cjs/i18n/locales/es-ES.js +1994 -1994
  31. package/dist/cjs/i18n/locales/fr-FR.js +366 -366
  32. package/dist/cjs/i18n/locales/it-IT.js +366 -366
  33. package/dist/cjs/i18n/locales/ja-JP.js +366 -366
  34. package/dist/cjs/i18n/locales/ko-KR.js +366 -366
  35. package/dist/cjs/i18n/locales/pt-PT.js +366 -366
  36. package/dist/cjs/i18n/locales/zh-CN.js +366 -366
  37. package/dist/cjs/inference/OxyInferenceClient.js +12 -18
  38. package/dist/cjs/models/interfaces.js +11 -11
  39. package/dist/cjs/server/OxyServer.js +86 -28
  40. package/dist/cjs/server/agentAccount.js +6 -2
  41. package/dist/cjs/server/aliaMachineCredential.js +39 -14
  42. package/dist/cjs/server/auth.js +5 -4
  43. package/dist/cjs/server/capabilityTicket.js +5 -5
  44. package/dist/cjs/server/index.js +2 -1
  45. package/dist/cjs/server/liveCapabilityTicket.js +4 -1
  46. package/dist/cjs/server/middleware.js +61 -42
  47. package/dist/cjs/server/namespaces.js +28 -7
  48. package/dist/cjs/server/requesterAssertion.js +36 -30
  49. package/dist/cjs/server/serviceTokenLifetime.js +7 -4
  50. package/dist/cjs/server/traffic.js +53 -14
  51. package/dist/cjs/server/trafficNodeHttp.js +33 -8
  52. package/dist/cjs/server/workloadIdentity.client.js +4 -0
  53. package/dist/cjs/server/workloadIdentity.js +28 -1
  54. package/dist/cjs/session/SessionClient.js +54 -17
  55. package/dist/cjs/session/accountDelegationAccess.js +4 -6
  56. package/dist/cjs/session/accountDialogController.js +1 -1
  57. package/dist/cjs/session/authStateStore.js +18 -9
  58. package/dist/cjs/session/identityPin.js +6 -2
  59. package/dist/cjs/session/refresh.js +81 -23
  60. package/dist/cjs/session/sharedDeviceCredential.js +28 -15
  61. package/dist/cjs/shared/utils/errorUtils.js +1 -1
  62. package/dist/cjs/shared/utils/networkUtils.js +1 -1
  63. package/dist/cjs/shared/utils/themeUtils.js +1 -1
  64. package/dist/cjs/utils/accountCacheSweep.js +3 -1
  65. package/dist/cjs/utils/accountUtils.js +1 -3
  66. package/dist/cjs/utils/asyncUtils.js +1 -1
  67. package/dist/cjs/utils/authHelpers.js +2 -1
  68. package/dist/cjs/utils/avatarUtils.js +4 -2
  69. package/dist/cjs/utils/cache.js +1 -1
  70. package/dist/cjs/utils/cacheKey.js +3 -1
  71. package/dist/cjs/utils/deviceManager.js +4 -4
  72. package/dist/cjs/utils/errorUtils.js +6 -4
  73. package/dist/cjs/utils/languageUtils.js +404 -57
  74. package/dist/cjs/utils/profileLinks.js +1 -3
  75. package/dist/cjs/utils/requestUtils.js +7 -1
  76. package/dist/cjs/utils/userIdentity.js +1 -1
  77. package/dist/cjs/utils/validationUtils.js +5 -6
  78. package/dist/esm/HttpService.js +64 -20
  79. package/dist/esm/api/accounts.js +11 -4
  80. package/dist/esm/api/agency.js +3 -1
  81. package/dist/esm/api/apps.js +15 -4
  82. package/dist/esm/api/assets.js +49 -12
  83. package/dist/esm/api/auth.js +37 -11
  84. package/dist/esm/api/billing.js +25 -8
  85. package/dist/esm/api/civic.js +14 -4
  86. package/dist/esm/api/follows.js +9 -2
  87. package/dist/esm/api/identity.js +31 -9
  88. package/dist/esm/api/nodes.js +3 -1
  89. package/dist/esm/api/privacy.js +8 -2
  90. package/dist/esm/api/session.js +15 -4
  91. package/dist/esm/api/store.js +15 -5
  92. package/dist/esm/api/topics.js +10 -3
  93. package/dist/esm/api/users.js +16 -4
  94. package/dist/esm/boot/sessionColdBoot.js +41 -14
  95. package/dist/esm/constants/version.js +6 -6
  96. package/dist/esm/crypto/identityMarker.js +3 -1
  97. package/dist/esm/crypto/identityProof.js +6 -1
  98. package/dist/esm/crypto/internal.js +1 -1
  99. package/dist/esm/crypto/keyManager.js +87 -32
  100. package/dist/esm/crypto/recoveryPhrase.js +2 -2
  101. package/dist/esm/crypto/signatureService.js +3 -4
  102. package/dist/esm/i18n/index.js +16 -3
  103. package/dist/esm/i18n/locales/ar-SA.js +366 -366
  104. package/dist/esm/i18n/locales/ca-ES.js +366 -366
  105. package/dist/esm/i18n/locales/de-DE.js +366 -366
  106. package/dist/esm/i18n/locales/en-US.js +1994 -1994
  107. package/dist/esm/i18n/locales/es-ES.js +1994 -1994
  108. package/dist/esm/i18n/locales/fr-FR.js +366 -366
  109. package/dist/esm/i18n/locales/it-IT.js +366 -366
  110. package/dist/esm/i18n/locales/ja-JP.js +366 -366
  111. package/dist/esm/i18n/locales/ko-KR.js +366 -366
  112. package/dist/esm/i18n/locales/pt-PT.js +366 -366
  113. package/dist/esm/i18n/locales/zh-CN.js +366 -366
  114. package/dist/esm/index.js +1 -1
  115. package/dist/esm/inference/OxyInferenceClient.js +13 -19
  116. package/dist/esm/models/interfaces.js +11 -11
  117. package/dist/esm/server/OxyServer.js +87 -29
  118. package/dist/esm/server/agentAccount.js +6 -2
  119. package/dist/esm/server/aliaMachineCredential.js +39 -14
  120. package/dist/esm/server/auth.js +6 -5
  121. package/dist/esm/server/capabilityTicket.js +6 -6
  122. package/dist/esm/server/index.js +5 -5
  123. package/dist/esm/server/liveCapabilityTicket.js +6 -3
  124. package/dist/esm/server/middleware.js +62 -43
  125. package/dist/esm/server/namespaces.js +31 -10
  126. package/dist/esm/server/requesterAssertion.js +36 -30
  127. package/dist/esm/server/serviceTokenLifetime.js +7 -4
  128. package/dist/esm/server/traffic.js +55 -16
  129. package/dist/esm/server/trafficNodeHttp.js +34 -9
  130. package/dist/esm/server/userInvalidation.js +1 -1
  131. package/dist/esm/server/workloadIdentity.client.js +3 -0
  132. package/dist/esm/server/workloadIdentity.js +27 -1
  133. package/dist/esm/session/SessionClient.js +54 -17
  134. package/dist/esm/session/accountDelegationAccess.js +5 -7
  135. package/dist/esm/session/accountDialogController.js +1 -1
  136. package/dist/esm/session/authStateStore.js +18 -9
  137. package/dist/esm/session/identityPin.js +6 -2
  138. package/dist/esm/session/refresh.js +82 -24
  139. package/dist/esm/session/sharedDeviceCredential.js +28 -15
  140. package/dist/esm/shared/utils/errorUtils.js +1 -1
  141. package/dist/esm/shared/utils/networkUtils.js +1 -1
  142. package/dist/esm/shared/utils/themeUtils.js +1 -1
  143. package/dist/esm/utils/accountCacheSweep.js +3 -1
  144. package/dist/esm/utils/accountUtils.js +1 -3
  145. package/dist/esm/utils/asyncUtils.js +1 -1
  146. package/dist/esm/utils/authHelpers.js +2 -1
  147. package/dist/esm/utils/avatarUtils.js +4 -2
  148. package/dist/esm/utils/cache.js +1 -1
  149. package/dist/esm/utils/cacheKey.js +3 -1
  150. package/dist/esm/utils/deviceManager.js +4 -4
  151. package/dist/esm/utils/errorUtils.js +6 -4
  152. package/dist/esm/utils/languageUtils.js +404 -57
  153. package/dist/esm/utils/profileLinks.js +1 -3
  154. package/dist/esm/utils/requestUtils.js +7 -1
  155. package/dist/esm/utils/userIdentity.js +1 -1
  156. package/dist/esm/utils/validationUtils.js +5 -6
  157. package/dist/types/HttpService.d.ts +1 -1
  158. package/dist/types/api/accounts.d.ts +1 -1
  159. package/dist/types/api/apps.d.ts +4 -4
  160. package/dist/types/api/assets.d.ts +2 -0
  161. package/dist/types/api/auth.d.ts +8 -3
  162. package/dist/types/crypto/internal.d.ts +1 -1
  163. package/dist/types/index.d.ts +4 -4
  164. package/dist/types/server/index.d.ts +6 -6
  165. package/dist/types/server/requesterAssertion.d.ts +2 -2
  166. package/dist/types/server/workloadIdentity.client.d.ts +5 -1
  167. package/dist/types/server/workloadIdentity.d.ts +26 -0
  168. package/dist/types/session/accountDelegationAccess.d.ts +1 -1
  169. package/dist/types/session/index.d.ts +1 -1
  170. package/dist/types/utils/userIdentity.d.ts +1 -1
  171. package/dist/types/utils/validationUtils.d.ts +4 -5
  172. package/package.json +2 -3
  173. package/src/HttpService.ts +183 -53
  174. package/src/OxyServices.errors.ts +7 -3
  175. package/src/OxyServices.ts +6 -2
  176. package/src/api/accounts.ts +76 -26
  177. package/src/api/agency.ts +24 -9
  178. package/src/api/appData.ts +12 -2
  179. package/src/api/apps.ts +81 -31
  180. package/src/api/assets.ts +122 -40
  181. package/src/api/auth.ts +154 -79
  182. package/src/api/billing.ts +112 -65
  183. package/src/api/civic.ts +61 -19
  184. package/src/api/contacts.ts +4 -1
  185. package/src/api/devices.ts +54 -21
  186. package/src/api/follows.ts +88 -31
  187. package/src/api/identity.ts +101 -33
  188. package/src/api/linkedAccounts.ts +26 -8
  189. package/src/api/nodes.ts +18 -6
  190. package/src/api/notifications.ts +26 -6
  191. package/src/api/privacy.ts +42 -8
  192. package/src/api/reputation.ts +18 -7
  193. package/src/api/session.ts +23 -5
  194. package/src/api/store.ts +81 -31
  195. package/src/api/topics.ts +18 -6
  196. package/src/api/users.ts +98 -35
  197. package/src/boot/sessionColdBoot.ts +60 -19
  198. package/src/civic/payloads.ts +1 -4
  199. package/src/client/context.ts +6 -1
  200. package/src/constants/version.ts +7 -6
  201. package/src/crypto/aead.ts +1 -5
  202. package/src/crypto/ecdh.ts +1 -4
  203. package/src/crypto/identityDerivations.ts +5 -1
  204. package/src/crypto/identityMarker.ts +3 -1
  205. package/src/crypto/identityProof.ts +6 -1
  206. package/src/crypto/index.ts +11 -11
  207. package/src/crypto/internal.ts +6 -1
  208. package/src/crypto/keyManager.ts +348 -98
  209. package/src/crypto/recoveryPhrase.ts +14 -9
  210. package/src/crypto/registrationPow.ts +1 -1
  211. package/src/crypto/signatureService.ts +14 -6
  212. package/src/i18n/accountCategoryLabels.ts +1 -4
  213. package/src/i18n/accountRoleLabels.ts +1 -4
  214. package/src/i18n/index.ts +25 -7
  215. package/src/i18n/locales/ar-SA.ts +375 -366
  216. package/src/i18n/locales/ca-ES.ts +382 -366
  217. package/src/i18n/locales/de-DE.ts +387 -366
  218. package/src/i18n/locales/en-US.ts +2034 -1994
  219. package/src/i18n/locales/es-ES.ts +2043 -1994
  220. package/src/i18n/locales/fr-FR.ts +387 -366
  221. package/src/i18n/locales/it-IT.ts +380 -366
  222. package/src/i18n/locales/ja-JP.ts +380 -366
  223. package/src/i18n/locales/ko-KR.ts +377 -366
  224. package/src/i18n/locales/pt-PT.ts +383 -366
  225. package/src/i18n/locales/zh-CN.ts +373 -366
  226. package/src/i18n/trustTierLabels.ts +1 -4
  227. package/src/index.ts +371 -349
  228. package/src/inference/OxyInferenceClient.ts +784 -780
  229. package/src/models/interfaces.ts +30 -27
  230. package/src/server/OxyServer.ts +227 -68
  231. package/src/server/agentAccount.ts +8 -2
  232. package/src/server/aliaMachineCredential.ts +57 -16
  233. package/src/server/auth.ts +9 -5
  234. package/src/server/capabilityTicket.ts +30 -21
  235. package/src/server/index.ts +29 -6
  236. package/src/server/liveCapabilityTicket.ts +31 -9
  237. package/src/server/middleware.ts +212 -121
  238. package/src/server/namespaces.ts +247 -94
  239. package/src/server/rateLimit.ts +2 -4
  240. package/src/server/requesterAssertion.ts +93 -54
  241. package/src/server/serviceTokenLifetime.ts +9 -4
  242. package/src/server/traffic.ts +117 -23
  243. package/src/server/trafficNodeHttp.ts +61 -14
  244. package/src/server/userInvalidation.ts +1 -4
  245. package/src/server/workloadIdentity.client.ts +12 -1
  246. package/src/server/workloadIdentity.ts +52 -5
  247. package/src/session/SessionClient.ts +170 -49
  248. package/src/session/accountDelegationAccess.ts +24 -31
  249. package/src/session/accountDialogController.ts +59 -14
  250. package/src/session/accountSwitchTargets.ts +10 -15
  251. package/src/session/authStateStore.ts +121 -81
  252. package/src/session/deviceDirectory.ts +1 -3
  253. package/src/session/identityPin.ts +10 -11
  254. package/src/session/identitySession.ts +3 -1
  255. package/src/session/index.ts +87 -82
  256. package/src/session/refresh.ts +138 -44
  257. package/src/session/sessionClientHost.ts +1 -3
  258. package/src/session/sharedDeviceCredential.ts +35 -14
  259. package/src/session/socketLoader.ts +9 -2
  260. package/src/shared/utils/errorUtils.ts +5 -2
  261. package/src/shared/utils/networkUtils.ts +5 -8
  262. package/src/shared/utils/themeUtils.ts +2 -6
  263. package/src/types/buffer.d.ts +66 -21
  264. package/src/types/expo-secure-store.d.ts +5 -1
  265. package/src/utils/accountCacheSweep.ts +4 -5
  266. package/src/utils/accountUtils.ts +107 -108
  267. package/src/utils/apiUtils.ts +3 -3
  268. package/src/utils/asyncUtils.ts +2 -2
  269. package/src/utils/authHelpers.ts +10 -5
  270. package/src/utils/avatarUtils.ts +11 -6
  271. package/src/utils/cache.ts +9 -10
  272. package/src/utils/cacheKey.ts +5 -1
  273. package/src/utils/coldBoot.ts +1 -3
  274. package/src/utils/commonsDelivery.ts +1 -4
  275. package/src/utils/deviceManager.ts +15 -14
  276. package/src/utils/errorUtils.ts +68 -86
  277. package/src/utils/languageUtils.ts +407 -58
  278. package/src/utils/oauthPkce.ts +1 -4
  279. package/src/utils/platform.ts +0 -1
  280. package/src/utils/profileLinks.ts +2 -5
  281. package/src/utils/requestUtils.ts +18 -14
  282. package/src/utils/sessionUtils.ts +34 -33
  283. package/src/utils/userHandle.ts +3 -1
  284. package/src/utils/userIdentity.ts +1 -1
  285. package/src/utils/validationUtils.ts +11 -9
@@ -138,7 +138,10 @@ export function readLocalDeviceCredential(
138
138
  */
139
139
  export function normalizeSharedDeviceSessionRead(raw: unknown): SharedDeviceCredentialRead {
140
140
  if (!raw || typeof raw !== 'object') {
141
- return { state: 'unavailable', cause: new Error('shared device session bridge returned a non-object') };
141
+ return {
142
+ state: 'unavailable',
143
+ cause: new Error('shared device session bridge returned a non-object'),
144
+ };
142
145
  }
143
146
  const payload = raw as Record<string, unknown>;
144
147
  if (payload.status === 'absent') {
@@ -160,16 +163,23 @@ export function normalizeSharedDeviceSessionRead(raw: unknown): SharedDeviceCred
160
163
  // overwrite whatever is really in there.
161
164
  return {
162
165
  state: 'unavailable',
163
- cause: new Error('shared device session bridge reported `present` with an incomplete credential'),
166
+ cause: new Error(
167
+ 'shared device session bridge reported `present` with an incomplete credential',
168
+ ),
164
169
  };
165
170
  }
166
171
  if (payload.status === 'unavailable') {
167
172
  const reason = typeof payload.reason === 'string' ? payload.reason : 'unknown';
168
- return { state: 'unavailable', cause: new Error(`shared device session slot unavailable: ${reason}`) };
173
+ return {
174
+ state: 'unavailable',
175
+ cause: new Error(`shared device session slot unavailable: ${reason}`),
176
+ };
169
177
  }
170
178
  return {
171
179
  state: 'unavailable',
172
- cause: new Error(`shared device session bridge returned an unrecognised status: ${String(payload.status)}`),
180
+ cause: new Error(
181
+ `shared device session bridge returned an unrecognised status: ${String(payload.status)}`,
182
+ ),
173
183
  };
174
184
  }
175
185
 
@@ -318,15 +328,23 @@ export function createSharedMirroringAuthStateStore(deps: {
318
328
  ...local,
319
329
  load: () => local.load(),
320
330
  clear: () => local.clear(),
321
- ...(local.saveIfCurrent ? {saveIfCurrent: async (state: PersistedAuthState, guard: AuthStateWriteGuard) => {
322
- const committed = await local.saveIfCurrent?.(state, guard);
323
- if (!committed) return false;
324
- const credential = readLocalDeviceCredential(state);
325
- if (credential && guard.isCurrent()) {
326
- try { await publishProvenDeviceCredential({shared, credential}); } catch { /* Local durability already verified. */ }
327
- }
328
- return true;
329
- }} : {}),
331
+ ...(local.saveIfCurrent
332
+ ? {
333
+ saveIfCurrent: async (state: PersistedAuthState, guard: AuthStateWriteGuard) => {
334
+ const committed = await local.saveIfCurrent?.(state, guard);
335
+ if (!committed) return false;
336
+ const credential = readLocalDeviceCredential(state);
337
+ if (credential && guard.isCurrent()) {
338
+ try {
339
+ await publishProvenDeviceCredential({ shared, credential });
340
+ } catch {
341
+ /* Local durability already verified. */
342
+ }
343
+ }
344
+ return true;
345
+ },
346
+ }
347
+ : {}),
330
348
  save: async (state) => {
331
349
  // The durable local write is the contract this store owes its caller —
332
350
  // run it first and report ITS result, unchanged. The mirror is additive.
@@ -344,7 +362,10 @@ export function createSharedMirroringAuthStateStore(deps: {
344
362
  }
345
363
  try {
346
364
  const outcome = await publishProvenDeviceCredential({ shared, credential });
347
- if (outcome.status === 'published' || (outcome.status === 'skipped' && outcome.reason === 'already-current')) {
365
+ if (
366
+ outcome.status === 'published' ||
367
+ (outcome.status === 'skipped' && outcome.reason === 'already-current')
368
+ ) {
348
369
  mirrored = credential;
349
370
  }
350
371
  } catch (error) {
@@ -20,11 +20,18 @@ export async function getSocketIO(): Promise<SocketIOFactory | null> {
20
20
  if (loadAttempted) return null;
21
21
  loadAttempted = true;
22
22
  try {
23
- const mod = (await import('socket.io-client')) as { io?: SocketIOFactory; default?: SocketIOFactory };
23
+ const mod = (await import('socket.io-client')) as {
24
+ io?: SocketIOFactory;
25
+ default?: SocketIOFactory;
26
+ };
24
27
  cachedFactory = mod.io ?? mod.default ?? null;
25
28
  return cachedFactory;
26
29
  } catch (error) {
27
- logger.warn('[SessionClient] socket.io-client import failed; realtime session sync disabled', { component: 'SessionClient' }, error);
30
+ logger.warn(
31
+ '[SessionClient] socket.io-client import failed; realtime session sync disabled',
32
+ { component: 'SessionClient' },
33
+ error,
34
+ );
28
35
  return null;
29
36
  }
30
37
  }
@@ -160,14 +160,17 @@ export const isNetworkError = (error: unknown): boolean => {
160
160
 
161
161
  // Check for common network error indicators
162
162
  if (err.name === 'NetworkError') return true;
163
- if (err.code === 'ENOTFOUND' || err.code === 'ECONNREFUSED' || err.code === 'ETIMEDOUT') return true;
163
+ if (err.code === 'ENOTFOUND' || err.code === 'ECONNREFUSED' || err.code === 'ETIMEDOUT')
164
+ return true;
164
165
 
165
166
  // Axios-style: has request but no response
166
167
  if (err.request && !err.response) return true;
167
168
 
168
169
  // Message-based detection
169
170
  const message = getErrorMessage(error, '').toLowerCase();
170
- return message.includes('network') || message.includes('connection') || message.includes('timeout');
171
+ return (
172
+ message.includes('network') || message.includes('connection') || message.includes('timeout')
173
+ );
171
174
  };
172
175
 
173
176
  /**
@@ -63,7 +63,7 @@ export const DEFAULT_CIRCUIT_BREAKER_CONFIG: Required<CircuitBreakerConfig> = {
63
63
  * ```
64
64
  */
65
65
  export const createCircuitBreakerState = (
66
- config: CircuitBreakerConfig = {}
66
+ config: CircuitBreakerConfig = {},
67
67
  ): CircuitBreakerState => {
68
68
  const { baseInterval, maxInterval, maxFailures } = {
69
69
  ...DEFAULT_CIRCUIT_BREAKER_CONFIG,
@@ -97,10 +97,7 @@ export const calculateBackoffInterval = (state: CircuitBreakerState): number =>
97
97
 
98
98
  if (consecutiveFailures === 0) return baseInterval;
99
99
 
100
- const backoffMultiplier = Math.min(
101
- 2 ** (consecutiveFailures - 1),
102
- maxInterval / baseInterval
103
- );
100
+ const backoffMultiplier = Math.min(2 ** (consecutiveFailures - 1), maxInterval / baseInterval);
104
101
 
105
102
  return Math.min(baseInterval * backoffMultiplier, maxInterval);
106
103
  };
@@ -168,7 +165,7 @@ export const recordSuccess = (state: CircuitBreakerState): CircuitBreakerState =
168
165
  */
169
166
  export const shouldAllowRequest = (
170
167
  state: CircuitBreakerState,
171
- recoveryTimeout: number = DEFAULT_CIRCUIT_BREAKER_CONFIG.recoveryTimeout
168
+ recoveryTimeout: number = DEFAULT_CIRCUIT_BREAKER_CONFIG.recoveryTimeout,
172
169
  ): boolean => {
173
170
  if (!state.isOpen) return true;
174
171
 
@@ -190,7 +187,7 @@ export const shouldAllowRequest = (
190
187
  * ```
191
188
  */
192
189
  export const delay = (ms: number): Promise<void> =>
193
- new Promise(resolve => setTimeout(resolve, ms));
190
+ new Promise((resolve) => setTimeout(resolve, ms));
194
191
 
195
192
  /**
196
193
  * Executes a function with exponential backoff retry.
@@ -216,7 +213,7 @@ export const withRetry = async <T>(
216
213
  maxDelay?: number;
217
214
  shouldRetry?: (error: unknown) => boolean;
218
215
  onRetry?: (error: unknown, attempt: number) => void;
219
- } = {}
216
+ } = {},
220
217
  ): Promise<T> => {
221
218
  const {
222
219
  maxRetries = 3,
@@ -51,10 +51,7 @@ export const normalizeTheme = (theme?: string | null): ThemeValue =>
51
51
  * normalizeColorScheme(undefined, undefined); // 'light'
52
52
  * ```
53
53
  */
54
- export const normalizeColorScheme = (
55
- colorScheme?: string | null,
56
- theme?: string
57
- ): ThemeValue => {
54
+ export const normalizeColorScheme = (colorScheme?: string | null, theme?: string): ThemeValue => {
58
55
  if (colorScheme === 'light' || colorScheme === 'dark') {
59
56
  return colorScheme;
60
57
  }
@@ -111,5 +108,4 @@ export const systemPrefersDarkMode = (): boolean => {
111
108
  * const theme = getSystemColorScheme();
112
109
  * ```
113
110
  */
114
- export const getSystemColorScheme = (): ThemeValue =>
115
- systemPrefersDarkMode() ? 'dark' : 'light';
111
+ export const getSystemColorScheme = (): ThemeValue => (systemPrefersDarkMode() ? 'dark' : 'light');
@@ -6,36 +6,54 @@ declare module 'buffer' {
6
6
  constructor(arrayBuffer: ArrayBuffer);
7
7
  constructor(array: ReadonlyArray<number>);
8
8
  constructor(buffer: Buffer);
9
-
9
+
10
10
  static from(arrayBuffer: ArrayBuffer, byteOffset?: number, length?: number): Buffer;
11
11
  static from(data: Uint8Array | ReadonlyArray<number>): Buffer;
12
12
  static from(str: string, encoding?: BufferEncoding): Buffer;
13
- static from(object: { valueOf(): string | object } | { [Symbol.toPrimitive](hint: 'string'): string }, offsetOrEncoding?: number | string, length?: number): Buffer;
14
-
13
+ static from(
14
+ object: { valueOf(): string | object } | { [Symbol.toPrimitive](hint: 'string'): string },
15
+ offsetOrEncoding?: number | string,
16
+ length?: number,
17
+ ): Buffer;
18
+
15
19
  static alloc(size: number, fill?: string | Buffer | number, encoding?: BufferEncoding): Buffer;
16
20
  static allocUnsafe(size: number): Buffer;
17
21
  static allocUnsafeSlow(size: number): Buffer;
18
-
22
+
19
23
  static isBuffer(obj: unknown): obj is Buffer;
20
24
  static isEncoding(encoding: string): encoding is BufferEncoding;
21
- static byteLength(string: string | Buffer | ArrayBuffer | SharedArrayBuffer, encoding?: BufferEncoding): number;
25
+ static byteLength(
26
+ string: string | Buffer | ArrayBuffer | SharedArrayBuffer,
27
+ encoding?: BufferEncoding,
28
+ ): number;
22
29
  static concat(list: ReadonlyArray<Uint8Array>, totalLength?: number): Buffer;
23
30
  static compare(buf1: Uint8Array, buf2: Uint8Array): number;
24
-
31
+
25
32
  write(string: string, encoding?: BufferEncoding): number;
26
33
  write(string: string, offset: number, encoding?: BufferEncoding): number;
27
34
  write(string: string, offset: number, length: number, encoding?: BufferEncoding): number;
28
-
35
+
29
36
  toString(encoding?: BufferEncoding, start?: number, end?: number): string;
30
37
  toJSON(): { type: 'Buffer'; data: number[] };
31
-
38
+
32
39
  equals(otherBuffer: Uint8Array): boolean;
33
- compare(target: Uint8Array, targetStart?: number, targetEnd?: number, sourceStart?: number, sourceEnd?: number): number;
34
- copy(target: Uint8Array, targetStart?: number, sourceStart?: number, sourceEnd?: number): number;
35
-
40
+ compare(
41
+ target: Uint8Array,
42
+ targetStart?: number,
43
+ targetEnd?: number,
44
+ sourceStart?: number,
45
+ sourceEnd?: number,
46
+ ): number;
47
+ copy(
48
+ target: Uint8Array,
49
+ targetStart?: number,
50
+ sourceStart?: number,
51
+ sourceEnd?: number,
52
+ ): number;
53
+
36
54
  slice(start?: number, end?: number): Buffer;
37
55
  subarray(start?: number, end?: number): Buffer;
38
-
56
+
39
57
  readBigInt64BE(offset?: number): bigint;
40
58
  readBigInt64LE(offset?: number): bigint;
41
59
  readBigUInt64BE(offset?: number): bigint;
@@ -58,11 +76,11 @@ declare module 'buffer' {
58
76
  readUInt32LE(offset?: number): number;
59
77
  readUIntBE(offset: number, byteLength: number): number;
60
78
  readUIntLE(offset: number, byteLength: number): number;
61
-
79
+
62
80
  swap16(): Buffer;
63
81
  swap32(): Buffer;
64
82
  swap64(): Buffer;
65
-
83
+
66
84
  writeBigInt64BE(value: bigint, offset?: number): number;
67
85
  writeBigInt64LE(value: bigint, offset?: number): number;
68
86
  writeBigUInt64BE(value: bigint, offset?: number): number;
@@ -85,13 +103,40 @@ declare module 'buffer' {
85
103
  writeUInt32LE(value: number, offset?: number): number;
86
104
  writeUIntBE(value: number, offset: number, byteLength: number): number;
87
105
  writeUIntLE(value: number, offset: number, byteLength: number): number;
88
-
89
- fill(value: string | Uint8Array | number, offset?: number, end?: number, encoding?: BufferEncoding): this;
90
- indexOf(value: string | number | Uint8Array, byteOffset?: number, encoding?: BufferEncoding): number;
91
- lastIndexOf(value: string | number | Uint8Array, byteOffset?: number, encoding?: BufferEncoding): number;
92
- includes(value: string | number | Buffer, byteOffset?: number, encoding?: BufferEncoding): boolean;
106
+
107
+ fill(
108
+ value: string | Uint8Array | number,
109
+ offset?: number,
110
+ end?: number,
111
+ encoding?: BufferEncoding,
112
+ ): this;
113
+ indexOf(
114
+ value: string | number | Uint8Array,
115
+ byteOffset?: number,
116
+ encoding?: BufferEncoding,
117
+ ): number;
118
+ lastIndexOf(
119
+ value: string | number | Uint8Array,
120
+ byteOffset?: number,
121
+ encoding?: BufferEncoding,
122
+ ): number;
123
+ includes(
124
+ value: string | number | Buffer,
125
+ byteOffset?: number,
126
+ encoding?: BufferEncoding,
127
+ ): boolean;
93
128
  }
94
129
 
95
- type BufferEncoding = 'ascii' | 'utf8' | 'utf-8' | 'utf16le' | 'ucs2' | 'ucs-2' | 'base64' | 'base64url' | 'latin1' | 'binary' | 'hex';
130
+ type BufferEncoding =
131
+ | 'ascii'
132
+ | 'utf8'
133
+ | 'utf-8'
134
+ | 'utf16le'
135
+ | 'ucs2'
136
+ | 'ucs-2'
137
+ | 'base64'
138
+ | 'base64url'
139
+ | 'latin1'
140
+ | 'binary'
141
+ | 'hex';
96
142
  }
97
-
@@ -12,6 +12,10 @@ declare module 'expo-secure-store' {
12
12
  export const AFTER_FIRST_UNLOCK_THIS_DEVICE_ONLY: number;
13
13
 
14
14
  export function getItemAsync(key: string, options?: SecureStoreOptions): Promise<string | null>;
15
- export function setItemAsync(key: string, value: string, options?: SecureStoreOptions): Promise<void>;
15
+ export function setItemAsync(
16
+ key: string,
17
+ value: string,
18
+ options?: SecureStoreOptions,
19
+ ): Promise<void>;
16
20
  export function deleteItemAsync(key: string, options?: SecureStoreOptions): Promise<void>;
17
21
  }
@@ -78,12 +78,11 @@ export function oxyAccountDetailCacheKey(accountId: string): string {
78
78
  * account in it (create, archive, ownership transfer) has no
79
79
  * detail row to name, and clears only the lists.
80
80
  */
81
- export function evictOxyAccountForestCache(
82
- http: OxyAccountCacheEvictor,
83
- accountId?: string,
84
- ): void {
81
+ export function evictOxyAccountForestCache(http: OxyAccountCacheEvictor, accountId?: string): void {
85
82
  http.invalidateCache({
86
- keys: accountId ? [OXY_ACCOUNT_LIST_CACHE_KEY, oxyAccountDetailCacheKey(accountId)] : [OXY_ACCOUNT_LIST_CACHE_KEY],
83
+ keys: accountId
84
+ ? [OXY_ACCOUNT_LIST_CACHE_KEY, oxyAccountDetailCacheKey(accountId)]
85
+ : [OXY_ACCOUNT_LIST_CACHE_KEY],
87
86
  prefixes: [OXY_ACCOUNT_LIST_CACHE_QUERY_PREFIX],
88
87
  });
89
88
  }
@@ -7,39 +7,41 @@ import { translate } from '../i18n';
7
7
  import { getNormalizedUserHandle } from './userHandle';
8
8
 
9
9
  export interface QuickAccount {
10
- sessionId: string;
11
- userId?: string;
12
- username: string;
13
- displayName: string;
14
- avatar?: string;
15
- avatarUrl?: string;
16
- /**
17
- * Device-local account slot index, 0..N-1 (Google-style multi-account).
18
- * Optional so that pre-multi-account QuickAccounts (sessionId-only) remain
19
- * valid; the device session set populates it where available.
20
- */
21
- authuser?: number;
22
- /**
23
- * Account's preferred Bloom color preset (e.g. `"blue"`, `"oxy"`). Drives
24
- * per-account theming in the account chooser. `null` / `undefined` means
25
- * the account has no preference and the base theme should be used.
26
- */
27
- color?: string | null;
10
+ sessionId: string;
11
+ userId?: string;
12
+ username: string;
13
+ displayName: string;
14
+ avatar?: string;
15
+ avatarUrl?: string;
16
+ /**
17
+ * Device-local account slot index, 0..N-1 (Google-style multi-account).
18
+ * Optional so that pre-multi-account QuickAccounts (sessionId-only) remain
19
+ * valid; the device session set populates it where available.
20
+ */
21
+ authuser?: number;
22
+ /**
23
+ * Account's preferred Bloom color preset (e.g. `"blue"`, `"oxy"`). Drives
24
+ * per-account theming in the account chooser. `null` / `undefined` means
25
+ * the account has no preference and the base theme should be used.
26
+ */
27
+ color?: string | null;
28
28
  }
29
29
 
30
30
  /** Minimal user shape accepted by display-name helpers. Avoids importing the full User type. */
31
31
  export interface DisplayNameUserShape {
32
- name?: string | {
32
+ name?:
33
+ | string
34
+ | {
33
35
  displayName?: string;
34
36
  first?: string;
35
37
  last?: string;
36
38
  full?: string;
37
39
  [key: string]: unknown;
38
- };
39
- /** Pre-normalized account-row display name, not the API User DTO field. */
40
- displayName?: string;
41
- username?: string;
42
- publicKey?: string;
40
+ };
41
+ /** Pre-normalized account-row display name, not the API User DTO field. */
42
+ displayName?: string;
43
+ username?: string;
44
+ publicKey?: string;
43
45
  }
44
46
 
45
47
  /**
@@ -47,9 +49,9 @@ export interface DisplayNameUserShape {
47
49
  * Falls back to the raw key if it's too short to truncate.
48
50
  */
49
51
  export const formatPublicKeyHandle = (publicKey: string): string => {
50
- const cleaned = publicKey.startsWith('0x') ? publicKey.slice(2) : publicKey;
51
- if (cleaned.length <= 8) return `0x${cleaned}`;
52
- return `0x${cleaned.slice(0, 8)}…`;
52
+ const cleaned = publicKey.startsWith('0x') ? publicKey.slice(2) : publicKey;
53
+ if (cleaned.length <= 8) return `0x${cleaned}`;
54
+ return `0x${cleaned.slice(0, 8)}…`;
53
55
  };
54
56
 
55
57
  /**
@@ -68,37 +70,37 @@ export const formatPublicKeyHandle = (publicKey: string): string => {
68
70
  * caller does not pass a locale, the default English translation is used.
69
71
  */
70
72
  export const getAccountDisplayName = (
71
- user: DisplayNameUserShape | null | undefined,
72
- locale?: string,
73
+ user: DisplayNameUserShape | null | undefined,
74
+ locale?: string,
73
75
  ): string => {
74
- if (!user) return translate(locale, 'common.unnamed');
75
-
76
- const { name, displayName, username, publicKey } = user;
77
-
78
- if (name && typeof name === 'object') {
79
- if (typeof name.displayName === 'string' && name.displayName.trim()) {
80
- return name.displayName.trim();
81
- }
82
- if (typeof name.full === 'string' && name.full.trim()) return name.full.trim();
83
- const first = typeof name.first === 'string' ? name.first.trim() : '';
84
- const last = typeof name.last === 'string' ? name.last.trim() : '';
85
- const composed = [first, last].filter(Boolean).join(' ').trim();
86
- if (composed) return composed;
87
- } else if (typeof name === 'string' && name.trim()) {
88
- return name.trim();
89
- }
76
+ if (!user) return translate(locale, 'common.unnamed');
90
77
 
91
- if (typeof displayName === 'string' && displayName.trim()) return displayName.trim();
78
+ const { name, displayName, username, publicKey } = user;
92
79
 
93
- if (typeof username === 'string' && username.trim()) return username.trim();
94
-
95
- if (typeof publicKey === 'string' && publicKey.length > 0) {
96
- return translate(locale, 'common.accountFallback', {
97
- handle: formatPublicKeyHandle(publicKey),
98
- });
80
+ if (name && typeof name === 'object') {
81
+ if (typeof name.displayName === 'string' && name.displayName.trim()) {
82
+ return name.displayName.trim();
99
83
  }
100
-
101
- return translate(locale, 'common.unnamed');
84
+ if (typeof name.full === 'string' && name.full.trim()) return name.full.trim();
85
+ const first = typeof name.first === 'string' ? name.first.trim() : '';
86
+ const last = typeof name.last === 'string' ? name.last.trim() : '';
87
+ const composed = [first, last].filter(Boolean).join(' ').trim();
88
+ if (composed) return composed;
89
+ } else if (typeof name === 'string' && name.trim()) {
90
+ return name.trim();
91
+ }
92
+
93
+ if (typeof displayName === 'string' && displayName.trim()) return displayName.trim();
94
+
95
+ if (typeof username === 'string' && username.trim()) return username.trim();
96
+
97
+ if (typeof publicKey === 'string' && publicKey.length > 0) {
98
+ return translate(locale, 'common.accountFallback', {
99
+ handle: formatPublicKeyHandle(publicKey),
100
+ });
101
+ }
102
+
103
+ return translate(locale, 'common.unnamed');
102
104
  };
103
105
 
104
106
  /**
@@ -109,29 +111,29 @@ export const getAccountDisplayName = (
109
111
  * available — callers can decide whether to hide the line entirely.
110
112
  */
111
113
  export const getAccountFallbackHandle = (
112
- user: DisplayNameUserShape | null | undefined,
114
+ user: DisplayNameUserShape | null | undefined,
113
115
  ): string | undefined => {
114
- if (!user) return undefined;
115
- if (typeof user.username === 'string' && user.username.trim()) return user.username.trim();
116
- if (typeof user.publicKey === 'string' && user.publicKey.length > 0) {
117
- return formatPublicKeyHandle(user.publicKey);
118
- }
119
- return undefined;
116
+ if (!user) return undefined;
117
+ if (typeof user.username === 'string' && user.username.trim()) return user.username.trim();
118
+ if (typeof user.publicKey === 'string' && user.publicKey.length > 0) {
119
+ return formatPublicKeyHandle(user.publicKey);
120
+ }
121
+ return undefined;
120
122
  };
121
123
 
122
124
  /**
123
125
  * Build an ordered array of QuickAccounts from a map and order list.
124
126
  */
125
127
  export const buildAccountsArray = (
126
- accounts: Record<string, QuickAccount>,
127
- order: string[]
128
+ accounts: Record<string, QuickAccount>,
129
+ order: string[],
128
130
  ): QuickAccount[] => {
129
- const result: QuickAccount[] = [];
130
- for (const id of order) {
131
- const account = accounts[id];
132
- if (account) result.push(account);
133
- }
134
- return result;
131
+ const result: QuickAccount[] = [];
132
+ for (const id of order) {
133
+ const account = accounts[id];
134
+ if (account) result.push(account);
135
+ }
136
+ return result;
135
137
  };
136
138
 
137
139
  /**
@@ -143,45 +145,42 @@ export const buildAccountsArray = (
143
145
  * @param getFileDownloadUrl - Function to generate avatar download URL from file ID
144
146
  */
145
147
  export const createQuickAccount = (
146
- sessionId: string,
147
- userData: {
148
- name?: string | { displayName?: string; full?: string; first?: string; last?: string };
149
- username?: string;
150
- publicKey?: string;
151
- id?: string;
152
- _id?: { toString(): string } | string;
153
- avatar?: string | null;
154
- },
155
- existingAccount?: QuickAccount,
156
- getFileDownloadUrl?: (fileId: string, variant: string) => string
148
+ sessionId: string,
149
+ userData: {
150
+ name?: string | { displayName?: string; full?: string; first?: string; last?: string };
151
+ username?: string;
152
+ publicKey?: string;
153
+ id?: string;
154
+ _id?: { toString(): string } | string;
155
+ avatar?: string | null;
156
+ },
157
+ existingAccount?: QuickAccount,
158
+ getFileDownloadUrl?: (fileId: string, variant: string) => string,
157
159
  ): QuickAccount => {
158
- const nameObj =
159
- userData.name && typeof userData.name === 'object' ? userData.name : undefined;
160
- const apiDisplayName =
161
- typeof nameObj?.displayName === 'string' ? nameObj.displayName.trim() : '';
162
- const displayName =
163
- apiDisplayName ||
164
- getNormalizedUserHandle(userData) ||
165
- getAccountDisplayName(null);
166
- const userId = userData.id || (typeof userData._id === 'string' ? userData._id : userData._id?.toString());
167
-
168
- // Preserve existing avatarUrl if avatar hasn't changed (prevents image reload)
169
- let avatarUrl: string | undefined;
170
- const avatar = userData.avatar ?? undefined;
171
- if (existingAccount && existingAccount.avatar === avatar && existingAccount.avatarUrl) {
172
- avatarUrl = existingAccount.avatarUrl;
173
- } else if (avatar && getFileDownloadUrl) {
174
- avatarUrl = getFileDownloadUrl(avatar, 'thumb');
175
- }
176
-
177
- return {
178
- sessionId,
179
- userId,
180
- username: userData.username || '',
181
- displayName,
182
- avatar,
183
- avatarUrl,
184
- };
160
+ const nameObj = userData.name && typeof userData.name === 'object' ? userData.name : undefined;
161
+ const apiDisplayName = typeof nameObj?.displayName === 'string' ? nameObj.displayName.trim() : '';
162
+ const displayName =
163
+ apiDisplayName || getNormalizedUserHandle(userData) || getAccountDisplayName(null);
164
+ const userId =
165
+ userData.id || (typeof userData._id === 'string' ? userData._id : userData._id?.toString());
166
+
167
+ // Preserve existing avatarUrl if avatar hasn't changed (prevents image reload)
168
+ let avatarUrl: string | undefined;
169
+ const avatar = userData.avatar ?? undefined;
170
+ if (existingAccount && existingAccount.avatar === avatar && existingAccount.avatarUrl) {
171
+ avatarUrl = existingAccount.avatarUrl;
172
+ } else if (avatar && getFileDownloadUrl) {
173
+ avatarUrl = getFileDownloadUrl(avatar, 'thumb');
174
+ }
175
+
176
+ return {
177
+ sessionId,
178
+ userId,
179
+ username: userData.username || '',
180
+ displayName,
181
+ avatar,
182
+ avatarUrl,
183
+ };
185
184
  };
186
185
 
187
186
  /**
@@ -190,5 +189,5 @@ export const createQuickAccount = (
190
189
  * drive per-account theming without duplicating the nullish-handling.
191
190
  */
192
191
  export const getAccountColor = (account: QuickAccount): string | null => {
193
- return account.color ?? null;
192
+ return account.color ?? null;
194
193
  };
@@ -53,10 +53,10 @@ export function buildSearchParams<T extends object>(params: T): URLSearchParams
53
53
  */
54
54
  export function buildUrl<T extends object>(baseUrl: string, params?: T): string {
55
55
  if (!params) return baseUrl;
56
-
56
+
57
57
  const searchParams = buildSearchParams(params);
58
58
  const queryString = searchParams.toString();
59
-
59
+
60
60
  return queryString ? `${baseUrl}?${queryString}` : baseUrl;
61
61
  }
62
62
 
@@ -134,4 +134,4 @@ export function safeJsonParse<T>(data: unknown, fallback: T): T {
134
134
  }
135
135
  }
136
136
  return data as T;
137
- }
137
+ }