@oxy.so/core 4.5.0-oxy-one.1 → 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 (282) 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 +39 -11
  7. package/dist/cjs/api/auth.js +28 -8
  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 +39 -11
  83. package/dist/esm/api/auth.js +28 -8
  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/crypto/internal.d.ts +1 -1
  161. package/dist/types/index.d.ts +4 -4
  162. package/dist/types/server/index.d.ts +6 -6
  163. package/dist/types/server/workloadIdentity.client.d.ts +5 -1
  164. package/dist/types/server/workloadIdentity.d.ts +26 -0
  165. package/dist/types/session/accountDelegationAccess.d.ts +1 -1
  166. package/dist/types/session/index.d.ts +1 -1
  167. package/dist/types/utils/userIdentity.d.ts +1 -1
  168. package/dist/types/utils/validationUtils.d.ts +4 -5
  169. package/package.json +2 -3
  170. package/src/HttpService.ts +183 -53
  171. package/src/OxyServices.errors.ts +7 -3
  172. package/src/OxyServices.ts +6 -2
  173. package/src/api/accounts.ts +76 -26
  174. package/src/api/agency.ts +24 -9
  175. package/src/api/appData.ts +12 -2
  176. package/src/api/apps.ts +81 -31
  177. package/src/api/assets.ts +113 -43
  178. package/src/api/auth.ts +145 -77
  179. package/src/api/billing.ts +112 -65
  180. package/src/api/civic.ts +61 -19
  181. package/src/api/contacts.ts +4 -1
  182. package/src/api/devices.ts +54 -21
  183. package/src/api/follows.ts +88 -31
  184. package/src/api/identity.ts +101 -33
  185. package/src/api/linkedAccounts.ts +26 -8
  186. package/src/api/nodes.ts +18 -6
  187. package/src/api/notifications.ts +26 -6
  188. package/src/api/privacy.ts +42 -8
  189. package/src/api/reputation.ts +18 -7
  190. package/src/api/session.ts +23 -5
  191. package/src/api/store.ts +81 -31
  192. package/src/api/topics.ts +18 -6
  193. package/src/api/users.ts +98 -35
  194. package/src/boot/sessionColdBoot.ts +60 -19
  195. package/src/civic/payloads.ts +1 -4
  196. package/src/client/context.ts +6 -1
  197. package/src/constants/version.ts +7 -6
  198. package/src/crypto/aead.ts +1 -5
  199. package/src/crypto/ecdh.ts +1 -4
  200. package/src/crypto/identityDerivations.ts +5 -1
  201. package/src/crypto/identityMarker.ts +3 -1
  202. package/src/crypto/identityProof.ts +6 -1
  203. package/src/crypto/index.ts +11 -11
  204. package/src/crypto/internal.ts +6 -1
  205. package/src/crypto/keyManager.ts +348 -98
  206. package/src/crypto/recoveryPhrase.ts +14 -9
  207. package/src/crypto/registrationPow.ts +1 -1
  208. package/src/crypto/signatureService.ts +14 -6
  209. package/src/i18n/accountCategoryLabels.ts +1 -4
  210. package/src/i18n/accountRoleLabels.ts +1 -4
  211. package/src/i18n/index.ts +25 -7
  212. package/src/i18n/locales/ar-SA.ts +375 -366
  213. package/src/i18n/locales/ca-ES.ts +382 -366
  214. package/src/i18n/locales/de-DE.ts +387 -366
  215. package/src/i18n/locales/en-US.ts +2034 -1994
  216. package/src/i18n/locales/es-ES.ts +2043 -1994
  217. package/src/i18n/locales/fr-FR.ts +387 -366
  218. package/src/i18n/locales/it-IT.ts +380 -366
  219. package/src/i18n/locales/ja-JP.ts +380 -366
  220. package/src/i18n/locales/ko-KR.ts +377 -366
  221. package/src/i18n/locales/pt-PT.ts +383 -366
  222. package/src/i18n/locales/zh-CN.ts +373 -366
  223. package/src/i18n/trustTierLabels.ts +1 -4
  224. package/src/index.ts +371 -349
  225. package/src/inference/OxyInferenceClient.ts +784 -780
  226. package/src/models/interfaces.ts +30 -27
  227. package/src/server/OxyServer.ts +227 -68
  228. package/src/server/agentAccount.ts +8 -2
  229. package/src/server/aliaMachineCredential.ts +57 -16
  230. package/src/server/auth.ts +9 -5
  231. package/src/server/capabilityTicket.ts +30 -21
  232. package/src/server/index.ts +29 -6
  233. package/src/server/liveCapabilityTicket.ts +31 -9
  234. package/src/server/middleware.ts +212 -121
  235. package/src/server/namespaces.ts +247 -94
  236. package/src/server/rateLimit.ts +2 -4
  237. package/src/server/requesterAssertion.ts +93 -54
  238. package/src/server/serviceTokenLifetime.ts +9 -4
  239. package/src/server/traffic.ts +117 -23
  240. package/src/server/trafficNodeHttp.ts +61 -14
  241. package/src/server/userInvalidation.ts +1 -4
  242. package/src/server/workloadIdentity.client.ts +12 -1
  243. package/src/server/workloadIdentity.ts +52 -5
  244. package/src/session/SessionClient.ts +170 -49
  245. package/src/session/accountDelegationAccess.ts +24 -31
  246. package/src/session/accountDialogController.ts +59 -14
  247. package/src/session/accountSwitchTargets.ts +10 -15
  248. package/src/session/authStateStore.ts +121 -81
  249. package/src/session/deviceDirectory.ts +1 -3
  250. package/src/session/identityPin.ts +10 -11
  251. package/src/session/identitySession.ts +3 -1
  252. package/src/session/index.ts +87 -82
  253. package/src/session/refresh.ts +138 -44
  254. package/src/session/sessionClientHost.ts +1 -3
  255. package/src/session/sharedDeviceCredential.ts +35 -14
  256. package/src/session/socketLoader.ts +9 -2
  257. package/src/shared/utils/errorUtils.ts +5 -2
  258. package/src/shared/utils/networkUtils.ts +5 -8
  259. package/src/shared/utils/themeUtils.ts +2 -6
  260. package/src/types/buffer.d.ts +66 -21
  261. package/src/types/expo-secure-store.d.ts +5 -1
  262. package/src/utils/accountCacheSweep.ts +4 -5
  263. package/src/utils/accountUtils.ts +107 -108
  264. package/src/utils/apiUtils.ts +3 -3
  265. package/src/utils/asyncUtils.ts +2 -2
  266. package/src/utils/authHelpers.ts +10 -5
  267. package/src/utils/avatarUtils.ts +11 -6
  268. package/src/utils/cache.ts +9 -10
  269. package/src/utils/cacheKey.ts +5 -1
  270. package/src/utils/coldBoot.ts +1 -3
  271. package/src/utils/commonsDelivery.ts +1 -4
  272. package/src/utils/deviceManager.ts +15 -14
  273. package/src/utils/errorUtils.ts +68 -86
  274. package/src/utils/languageUtils.ts +407 -58
  275. package/src/utils/oauthPkce.ts +1 -4
  276. package/src/utils/platform.ts +0 -1
  277. package/src/utils/profileLinks.ts +2 -5
  278. package/src/utils/requestUtils.ts +18 -14
  279. package/src/utils/sessionUtils.ts +34 -33
  280. package/src/utils/userHandle.ts +3 -1
  281. package/src/utils/userIdentity.ts +1 -1
  282. package/src/utils/validationUtils.ts +11 -9
@@ -188,7 +188,7 @@ async function initExpoCrypto() {
188
188
  */
189
189
  function uint8ArrayToHex(bytes) {
190
190
  return Array.from(bytes)
191
- .map(b => b.toString(16).padStart(2, '0'))
191
+ .map((b) => b.toString(16).padStart(2, '0'))
192
192
  .join('');
193
193
  }
194
194
  /** Decode a lowercase hex string to bytes. Inverse of {@link uint8ArrayToHex}. */
@@ -298,7 +298,9 @@ export class KeyManager {
298
298
  }
299
299
  /** Build private-key write options (device-only accessibility) for a given keychain service. */
300
300
  static _privateWriteOpts(store, service) {
301
- const opts = { keychainAccessible: store.WHEN_UNLOCKED_THIS_DEVICE_ONLY };
301
+ const opts = {
302
+ keychainAccessible: store.WHEN_UNLOCKED_THIS_DEVICE_ONLY,
303
+ };
302
304
  if (service) {
303
305
  opts.keychainService = service;
304
306
  }
@@ -610,7 +612,9 @@ export class KeyManager {
610
612
  }
611
613
  try {
612
614
  if (!(await signer.write(privateKey, publicKey))) {
613
- logger.warn(`The identity signer store (${signer.name}) did not confirm the write`, { component: 'KeyManager' });
615
+ logger.warn(`The identity signer store (${signer.name}) did not confirm the write`, {
616
+ component: 'KeyManager',
617
+ });
614
618
  }
615
619
  }
616
620
  catch (error) {
@@ -826,10 +830,14 @@ export class KeyManager {
826
830
  return {
827
831
  primaryPublicKey,
828
832
  sharedPublicKey,
829
- activePublicKey: isAndroid() ? (primaryPublicKey ?? sharedPublicKey) : (sharedPublicKey ?? primaryPublicKey),
833
+ activePublicKey: isAndroid()
834
+ ? (primaryPublicKey ?? sharedPublicKey)
835
+ : (sharedPublicKey ?? primaryPublicKey),
830
836
  // Only a real disagreement is out of sync. A device with just one slot
831
837
  // populated has nothing to contradict.
832
- inSync: primaryPublicKey === null || sharedPublicKey === null || primaryPublicKey === sharedPublicKey,
838
+ inSync: primaryPublicKey === null ||
839
+ sharedPublicKey === null ||
840
+ primaryPublicKey === sharedPublicKey,
833
841
  };
834
842
  }
835
843
  /**
@@ -1082,7 +1090,9 @@ export class KeyManager {
1082
1090
  priorPublic = await store.getItemAsync(layout.primaryPublicKeyName, primaryReadOpts);
1083
1091
  }
1084
1092
  catch (error) {
1085
- logger.error('Failed to read existing primary before persist', error, { component: 'KeyManager' });
1093
+ logger.error('Failed to read existing primary before persist', error, {
1094
+ component: 'KeyManager',
1095
+ });
1086
1096
  throw new IdentityPersistError('Could not read existing identity before writing a new one; refusing to overwrite blind.', error);
1087
1097
  }
1088
1098
  // If we are replacing a DIFFERENT, currently-healthy identity, make sure
@@ -1113,7 +1123,9 @@ export class KeyManager {
1113
1123
  await store.setItemAsync(layout.backupTimestampName, Date.now().toString(), backupPubWriteOpts);
1114
1124
  }
1115
1125
  catch (error) {
1116
- logger.error('Failed to back up existing identity before overwrite', error, { component: 'KeyManager' });
1126
+ logger.error('Failed to back up existing identity before overwrite', error, {
1127
+ component: 'KeyManager',
1128
+ });
1117
1129
  throw new IdentityPersistError('Failed to back up existing identity before overwrite', error);
1118
1130
  }
1119
1131
  }
@@ -1127,7 +1139,9 @@ export class KeyManager {
1127
1139
  await store.setItemAsync(layout.primaryPrivateKeyName, canonicalPrivate, primaryPrivWriteOpts);
1128
1140
  }
1129
1141
  catch (error) {
1130
- logger.error('Failed to write primary identity to secure store', error, { component: 'KeyManager' });
1142
+ logger.error('Failed to write primary identity to secure store', error, {
1143
+ component: 'KeyManager',
1144
+ });
1131
1145
  await KeyManager._rollbackPrimary(store, layout, priorPrivate, priorPublic);
1132
1146
  throw new IdentityPersistError('Failed to write identity to secure store', error);
1133
1147
  }
@@ -1151,7 +1165,9 @@ export class KeyManager {
1151
1165
  // trigger a spurious mismatch.
1152
1166
  if (readBackPrivate?.toLowerCase() !== canonicalPrivate ||
1153
1167
  readBackPublic?.toLowerCase() !== canonicalPublic) {
1154
- logger.error('Identity round-trip mismatch after write', undefined, { component: 'KeyManager' });
1168
+ logger.error('Identity round-trip mismatch after write', undefined, {
1169
+ component: 'KeyManager',
1170
+ });
1155
1171
  await KeyManager._rollbackPrimary(store, layout, priorPrivate, priorPublic);
1156
1172
  throw new IdentityPersistError('Identity write was not persisted correctly (round-trip mismatch).');
1157
1173
  }
@@ -1194,7 +1210,9 @@ export class KeyManager {
1194
1210
  priorBackupTimestamp = await store.getItemAsync(layout.backupTimestampName, backupReadOpts);
1195
1211
  }
1196
1212
  catch (error) {
1197
- logger.error('Failed to snapshot identity backup before refresh', error, { component: 'KeyManager' });
1213
+ logger.error('Failed to snapshot identity backup before refresh', error, {
1214
+ component: 'KeyManager',
1215
+ });
1198
1216
  await KeyManager._rollbackPrimary(store, layout, priorPrivate, priorPublic);
1199
1217
  throw new IdentityPersistError('Failed to snapshot identity backup before refresh', error);
1200
1218
  }
@@ -1204,7 +1222,9 @@ export class KeyManager {
1204
1222
  await store.setItemAsync(layout.backupTimestampName, Date.now().toString(), backupPubWriteOpts);
1205
1223
  }
1206
1224
  catch (error) {
1207
- logger.error('Failed to refresh identity backup after primary write', error, { component: 'KeyManager' });
1225
+ logger.error('Failed to refresh identity backup after primary write', error, {
1226
+ component: 'KeyManager',
1227
+ });
1208
1228
  await KeyManager._rollbackBackup(store, layout, priorBackupPrivate, priorBackupPublic, priorBackupTimestamp);
1209
1229
  await KeyManager._rollbackPrimary(store, layout, priorPrivate, priorPublic);
1210
1230
  throw new IdentityPersistError('Failed to refresh identity backup after primary write', error);
@@ -1254,7 +1274,9 @@ export class KeyManager {
1254
1274
  }
1255
1275
  const sameIdentity = existing?.publicKey === publicKey;
1256
1276
  const keptMnemonic = mnemonic ?? (sameIdentity ? existing?.mnemonic : undefined);
1257
- if (sameIdentity && existing?.privateKey === privateKey && existing?.mnemonic === keptMnemonic) {
1277
+ if (sameIdentity &&
1278
+ existing?.privateKey === privateKey &&
1279
+ existing?.mnemonic === keptMnemonic) {
1258
1280
  return true; // Already current; do not churn the store.
1259
1281
  }
1260
1282
  await store.write(serializeDeviceBackup({
@@ -1301,7 +1323,9 @@ export class KeyManager {
1301
1323
  static async _readHealthyPrimary() {
1302
1324
  try {
1303
1325
  const direct = await KeyManager._readPrimaryDirect();
1304
- if (KeyManager._isHealthyPair(direct.privateKey, direct.publicKey) && direct.privateKey && direct.publicKey) {
1326
+ if (KeyManager._isHealthyPair(direct.privateKey, direct.publicKey) &&
1327
+ direct.privateKey &&
1328
+ direct.publicKey) {
1305
1329
  return {
1306
1330
  privateKey: KeyManager.canonicalPrivateKey(direct.privateKey),
1307
1331
  publicKey: direct.publicKey.toLowerCase(),
@@ -1398,7 +1422,9 @@ export class KeyManager {
1398
1422
  try {
1399
1423
  await store.deleteItemAsync(layout.backupPrivateKeyName, backupReadOpts);
1400
1424
  }
1401
- catch { /* best effort */ }
1425
+ catch {
1426
+ /* best effort */
1427
+ }
1402
1428
  }
1403
1429
  if (priorBackupPublic) {
1404
1430
  await store.setItemAsync(layout.backupPublicKeyName, priorBackupPublic, backupPubWriteOpts);
@@ -1407,7 +1433,9 @@ export class KeyManager {
1407
1433
  try {
1408
1434
  await store.deleteItemAsync(layout.backupPublicKeyName, backupReadOpts);
1409
1435
  }
1410
- catch { /* best effort */ }
1436
+ catch {
1437
+ /* best effort */
1438
+ }
1411
1439
  }
1412
1440
  if (priorBackupTimestamp) {
1413
1441
  await store.setItemAsync(layout.backupTimestampName, priorBackupTimestamp, backupPubWriteOpts);
@@ -1416,11 +1444,15 @@ export class KeyManager {
1416
1444
  try {
1417
1445
  await store.deleteItemAsync(layout.backupTimestampName, backupReadOpts);
1418
1446
  }
1419
- catch { /* best effort */ }
1447
+ catch {
1448
+ /* best effort */
1449
+ }
1420
1450
  }
1421
1451
  }
1422
1452
  catch (rollbackError) {
1423
- logger.error('Failed to roll back identity backup after a failed refresh', rollbackError, { component: 'KeyManager' });
1453
+ logger.error('Failed to roll back identity backup after a failed refresh', rollbackError, {
1454
+ component: 'KeyManager',
1455
+ });
1424
1456
  }
1425
1457
  }
1426
1458
  /**
@@ -1448,15 +1480,21 @@ export class KeyManager {
1448
1480
  try {
1449
1481
  await store.deleteItemAsync(layout.primaryPublicKeyName, primaryReadOpts);
1450
1482
  }
1451
- catch { /* best effort */ }
1483
+ catch {
1484
+ /* best effort */
1485
+ }
1452
1486
  try {
1453
1487
  await store.deleteItemAsync(layout.primaryPrivateKeyName, primaryReadOpts);
1454
1488
  }
1455
- catch { /* best effort */ }
1489
+ catch {
1490
+ /* best effort */
1491
+ }
1456
1492
  }
1457
1493
  }
1458
1494
  catch (rollbackError) {
1459
- logger.error('Failed to roll back primary identity after a failed write', rollbackError, { component: 'KeyManager' });
1495
+ logger.error('Failed to roll back primary identity after a failed write', rollbackError, {
1496
+ component: 'KeyManager',
1497
+ });
1460
1498
  }
1461
1499
  finally {
1462
1500
  // Whatever happened, the cached verdict is no longer trustworthy.
@@ -1762,7 +1800,9 @@ export class KeyManager {
1762
1800
  // fetch before the device is unlocked). Do NOT cache; throw a TYPED error
1763
1801
  // so callers distinguish "temporarily unavailable" from "genuinely absent"
1764
1802
  // instead of silently treating a locked keystore as a blank device.
1765
- logger.error('Failed to read identity from secure storage', error, { component: 'KeyManager' });
1803
+ logger.error('Failed to read identity from secure storage', error, {
1804
+ component: 'KeyManager',
1805
+ });
1766
1806
  throw new IdentityUnavailableError('Failed to read identity from secure storage.', error);
1767
1807
  }
1768
1808
  // Storage succeeded. Now classify the result. From here onward, any
@@ -1789,7 +1829,9 @@ export class KeyManager {
1789
1829
  }
1790
1830
  }
1791
1831
  else {
1792
- logger.warn('KeyManager.hasIdentity: stored key material is malformed', { component: 'KeyManager' });
1832
+ logger.warn('KeyManager.hasIdentity: stored key material is malformed', {
1833
+ component: 'KeyManager',
1834
+ });
1793
1835
  }
1794
1836
  }
1795
1837
  // Cache result. Storage succeeded, so this verdict is stable:
@@ -1914,7 +1956,9 @@ export class KeyManager {
1914
1956
  try {
1915
1957
  const backupSuccess = await KeyManager.backupIdentity();
1916
1958
  if (!backupSuccess && isDev()) {
1917
- logger.warn('Failed to backup identity before deletion - proceeding anyway', { component: 'KeyManager' });
1959
+ logger.warn('Failed to backup identity before deletion - proceeding anyway', {
1960
+ component: 'KeyManager',
1961
+ });
1918
1962
  }
1919
1963
  }
1920
1964
  catch (backupError) {
@@ -2042,7 +2086,9 @@ export class KeyManager {
2042
2086
  const probeHash = '0'.repeat(64);
2043
2087
  const signature = signSecp256k1Digest(canonicalPrivateKey, probeHash);
2044
2088
  if (!verifySecp256k1Digest(publicKey, probeHash, signature)) {
2045
- logger.error('Identity sign/verify probe failed during integrity check', undefined, { component: 'KeyManager' });
2089
+ logger.error('Identity sign/verify probe failed during integrity check', undefined, {
2090
+ component: 'KeyManager',
2091
+ });
2046
2092
  return false;
2047
2093
  }
2048
2094
  return true;
@@ -2116,8 +2162,11 @@ export class KeyManager {
2116
2162
  if (!backupPrivateKey || !backupPublicKey) {
2117
2163
  return false; // No backup available
2118
2164
  }
2119
- if (!KeyManager.isValidPrivateKey(backupPrivateKey) || !KeyManager.isValidPublicKey(backupPublicKey)) {
2120
- logger.warn('Backup identity is malformed; refusing to restore', { component: 'KeyManager' });
2165
+ if (!KeyManager.isValidPrivateKey(backupPrivateKey) ||
2166
+ !KeyManager.isValidPublicKey(backupPublicKey)) {
2167
+ logger.warn('Backup identity is malformed; refusing to restore', {
2168
+ component: 'KeyManager',
2169
+ });
2121
2170
  return false;
2122
2171
  }
2123
2172
  // Verify backup keys derive consistently. Hex is case-insensitive so
@@ -2125,7 +2174,9 @@ export class KeyManager {
2125
2174
  // be considered valid.
2126
2175
  const derivedPublicKey = KeyManager.derivePublicKey(backupPrivateKey);
2127
2176
  if (derivedPublicKey.toLowerCase() !== backupPublicKey.toLowerCase()) {
2128
- logger.warn('Backup public key does not match derived; refusing to restore', { component: 'KeyManager' });
2177
+ logger.warn('Backup public key does not match derived; refusing to restore', {
2178
+ component: 'KeyManager',
2179
+ });
2129
2180
  return false;
2130
2181
  }
2131
2182
  // Guard 3: if ANY primary key material is still present and identifies a
@@ -2134,8 +2185,7 @@ export class KeyManager {
2134
2185
  // the user. We check the private key too (not just the public): a
2135
2186
  // present private key that derives to a non-backup public means a real,
2136
2187
  // different identity is sitting in the primary slot.
2137
- if (primaryPublic &&
2138
- primaryPublic.toLowerCase() !== backupPublicKey.toLowerCase()) {
2188
+ if (primaryPublic && primaryPublic.toLowerCase() !== backupPublicKey.toLowerCase()) {
2139
2189
  logger.error('Primary public key is present, corrupt-or-mismatched, AND differs from the backup. Refusing to restore to avoid switching accounts.', undefined, { component: 'KeyManager' });
2140
2190
  return false;
2141
2191
  }
@@ -2151,7 +2201,9 @@ export class KeyManager {
2151
2201
  await KeyManager._persistIdentityAtomic(backupPrivateKey, backupPublicKey, 'restore');
2152
2202
  }
2153
2203
  catch (error) {
2154
- logger.error('Failed to persist identity restored from backup', error, { component: 'KeyManager' });
2204
+ logger.error('Failed to persist identity restored from backup', error, {
2205
+ component: 'KeyManager',
2206
+ });
2155
2207
  return false;
2156
2208
  }
2157
2209
  await store.setItemAsync(layout.backupTimestampName, Date.now().toString(), backupReadOpts);
@@ -2289,7 +2341,8 @@ export class KeyManager {
2289
2341
  if (!(await KeyManager._commitRecovery(record.privateKey, record.publicKey))) {
2290
2342
  return false;
2291
2343
  }
2292
- if (record.mnemonic && (await KeyManager._phraseDerivesPublicKey(record.mnemonic, record.publicKey))) {
2344
+ if (record.mnemonic &&
2345
+ (await KeyManager._phraseDerivesPublicKey(record.mnemonic, record.publicKey))) {
2293
2346
  try {
2294
2347
  await KeyManager.storeRecoveryMnemonic(record.mnemonic);
2295
2348
  }
@@ -2357,7 +2410,9 @@ export class KeyManager {
2357
2410
  return true;
2358
2411
  }
2359
2412
  catch (error) {
2360
- logger.error('Recovery: failed to persist recovered identity', error, { component: 'KeyManager' });
2413
+ logger.error('Recovery: failed to persist recovered identity', error, {
2414
+ component: 'KeyManager',
2415
+ });
2361
2416
  return false;
2362
2417
  }
2363
2418
  }
@@ -24,7 +24,7 @@ function toHex(data) {
24
24
  // Convert to array of numbers if needed
25
25
  const bytes = data instanceof Uint8Array ? data : new Uint8Array(data);
26
26
  return Array.from(bytes)
27
- .map(b => b.toString(16).padStart(2, '0'))
27
+ .map((b) => b.toString(16).padStart(2, '0'))
28
28
  .join('');
29
29
  }
30
30
  /** UTF-8 encode an ASCII label to bytes (for HKDF salt/info). */
@@ -233,7 +233,7 @@ export class RecoveryPhraseService {
233
233
  * Convert a word array to a phrase string
234
234
  */
235
235
  static wordsToPhrase(words) {
236
- return words.map(w => w.toLowerCase().trim()).join(' ');
236
+ return words.map((w) => w.toLowerCase().trim()).join(' ');
237
237
  }
238
238
  }
239
239
  export default RecoveryPhraseService;
@@ -39,7 +39,7 @@ export class SignatureService {
39
39
  const bytes = new Uint8Array(32);
40
40
  globalThis.crypto.getRandomValues(bytes);
41
41
  return Array.from(bytes)
42
- .map(b => b.toString(16).padStart(2, '0'))
42
+ .map((b) => b.toString(16).padStart(2, '0'))
43
43
  .join('');
44
44
  }
45
45
  /**
@@ -81,8 +81,7 @@ export class SignatureService {
81
81
  * Verify a signed message object
82
82
  * Checks both signature validity and timestamp freshness
83
83
  */
84
- static async verifySignedMessage(signedMessage, maxAgeMs = 5 * 60 * 1000 // 5 minutes default
85
- ) {
84
+ static async verifySignedMessage(signedMessage, maxAgeMs = 5 * 60 * 1000) {
86
85
  const { message, signature, publicKey, timestamp } = signedMessage;
87
86
  // Check timestamp freshness
88
87
  const now = Date.now();
@@ -185,7 +184,7 @@ export class SignatureService {
185
184
  const timestamp = Date.now();
186
185
  // Create canonical string representation
187
186
  const sortedKeys = Object.keys(data).sort();
188
- const canonicalParts = sortedKeys.map(key => `${key}:${JSON.stringify(data[key])}`);
187
+ const canonicalParts = sortedKeys.map((key) => `${key}:${JSON.stringify(data[key])}`);
189
188
  const canonicalString = canonicalParts.join('|');
190
189
  const message = `request:${publicKey}:${timestamp}:${canonicalString}`;
191
190
  const signature = await SignatureService.sign(message);
@@ -20,8 +20,17 @@ const LOADERS = {
20
20
  };
21
21
  /** Base subtag → the dictionary that serves it. */
22
22
  const ALIASES = {
23
- en: 'en-US', es: 'es-ES', ca: 'ca-ES', fr: 'fr-FR', de: 'de-DE', it: 'it-IT',
24
- pt: 'pt-PT', ja: 'ja-JP', ko: 'ko-KR', zh: 'zh-CN', ar: 'ar-SA',
23
+ en: 'en-US',
24
+ es: 'es-ES',
25
+ ca: 'ca-ES',
26
+ fr: 'fr-FR',
27
+ de: 'de-DE',
28
+ it: 'it-IT',
29
+ pt: 'pt-PT',
30
+ ja: 'ja-JP',
31
+ ko: 'ko-KR',
32
+ zh: 'zh-CN',
33
+ ar: 'ar-SA',
25
34
  };
26
35
  const DICTS = { [FALLBACK]: enUS };
27
36
  const pending = new Map();
@@ -96,7 +105,11 @@ function resolveLang(locale) {
96
105
  return FALLBACK;
97
106
  }
98
107
  function getNested(obj, path) {
99
- return path.split('.').reduce((acc, key) => (acc && typeof acc === 'object' && acc[key] != null ? acc[key] : undefined), obj);
108
+ return path
109
+ .split('.')
110
+ .reduce((acc, key) => acc && typeof acc === 'object' && acc[key] != null
111
+ ? acc[key]
112
+ : undefined, obj);
100
113
  }
101
114
  export function translate(locale, key, vars) {
102
115
  const lang = resolveLang(locale);