@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.
- package/README.md +1 -1
- package/dist/cjs/HttpService.js +63 -19
- package/dist/cjs/api/accounts.js +10 -3
- package/dist/cjs/api/agency.js +3 -1
- package/dist/cjs/api/apps.js +15 -4
- package/dist/cjs/api/assets.js +49 -12
- package/dist/cjs/api/auth.js +37 -11
- package/dist/cjs/api/billing.js +24 -7
- package/dist/cjs/api/civic.js +14 -4
- package/dist/cjs/api/follows.js +9 -2
- package/dist/cjs/api/identity.js +31 -9
- package/dist/cjs/api/nodes.js +3 -1
- package/dist/cjs/api/privacy.js +8 -2
- package/dist/cjs/api/session.js +15 -4
- package/dist/cjs/api/store.js +15 -5
- package/dist/cjs/api/topics.js +10 -3
- package/dist/cjs/api/users.js +16 -4
- package/dist/cjs/boot/sessionColdBoot.js +40 -13
- package/dist/cjs/constants/version.js +6 -6
- package/dist/cjs/crypto/identityMarker.js +3 -1
- package/dist/cjs/crypto/identityProof.js +6 -1
- package/dist/cjs/crypto/keyManager.js +87 -32
- package/dist/cjs/crypto/recoveryPhrase.js +2 -2
- package/dist/cjs/crypto/signatureService.js +3 -4
- package/dist/cjs/i18n/index.js +16 -3
- package/dist/cjs/i18n/locales/ar-SA.js +366 -366
- package/dist/cjs/i18n/locales/ca-ES.js +366 -366
- package/dist/cjs/i18n/locales/de-DE.js +366 -366
- package/dist/cjs/i18n/locales/en-US.js +1994 -1994
- package/dist/cjs/i18n/locales/es-ES.js +1994 -1994
- package/dist/cjs/i18n/locales/fr-FR.js +366 -366
- package/dist/cjs/i18n/locales/it-IT.js +366 -366
- package/dist/cjs/i18n/locales/ja-JP.js +366 -366
- package/dist/cjs/i18n/locales/ko-KR.js +366 -366
- package/dist/cjs/i18n/locales/pt-PT.js +366 -366
- package/dist/cjs/i18n/locales/zh-CN.js +366 -366
- package/dist/cjs/inference/OxyInferenceClient.js +12 -18
- package/dist/cjs/models/interfaces.js +11 -11
- package/dist/cjs/server/OxyServer.js +86 -28
- package/dist/cjs/server/agentAccount.js +6 -2
- package/dist/cjs/server/aliaMachineCredential.js +39 -14
- package/dist/cjs/server/auth.js +5 -4
- package/dist/cjs/server/capabilityTicket.js +5 -5
- package/dist/cjs/server/index.js +2 -1
- package/dist/cjs/server/liveCapabilityTicket.js +4 -1
- package/dist/cjs/server/middleware.js +61 -42
- package/dist/cjs/server/namespaces.js +28 -7
- package/dist/cjs/server/requesterAssertion.js +36 -30
- package/dist/cjs/server/serviceTokenLifetime.js +7 -4
- package/dist/cjs/server/traffic.js +53 -14
- package/dist/cjs/server/trafficNodeHttp.js +33 -8
- package/dist/cjs/server/workloadIdentity.client.js +4 -0
- package/dist/cjs/server/workloadIdentity.js +28 -1
- package/dist/cjs/session/SessionClient.js +54 -17
- package/dist/cjs/session/accountDelegationAccess.js +4 -6
- package/dist/cjs/session/accountDialogController.js +1 -1
- package/dist/cjs/session/authStateStore.js +18 -9
- package/dist/cjs/session/identityPin.js +6 -2
- package/dist/cjs/session/refresh.js +81 -23
- package/dist/cjs/session/sharedDeviceCredential.js +28 -15
- package/dist/cjs/shared/utils/errorUtils.js +1 -1
- package/dist/cjs/shared/utils/networkUtils.js +1 -1
- package/dist/cjs/shared/utils/themeUtils.js +1 -1
- package/dist/cjs/utils/accountCacheSweep.js +3 -1
- package/dist/cjs/utils/accountUtils.js +1 -3
- package/dist/cjs/utils/asyncUtils.js +1 -1
- package/dist/cjs/utils/authHelpers.js +2 -1
- package/dist/cjs/utils/avatarUtils.js +4 -2
- package/dist/cjs/utils/cache.js +1 -1
- package/dist/cjs/utils/cacheKey.js +3 -1
- package/dist/cjs/utils/deviceManager.js +4 -4
- package/dist/cjs/utils/errorUtils.js +6 -4
- package/dist/cjs/utils/languageUtils.js +404 -57
- package/dist/cjs/utils/profileLinks.js +1 -3
- package/dist/cjs/utils/requestUtils.js +7 -1
- package/dist/cjs/utils/userIdentity.js +1 -1
- package/dist/cjs/utils/validationUtils.js +5 -6
- package/dist/esm/HttpService.js +64 -20
- package/dist/esm/api/accounts.js +11 -4
- package/dist/esm/api/agency.js +3 -1
- package/dist/esm/api/apps.js +15 -4
- package/dist/esm/api/assets.js +49 -12
- package/dist/esm/api/auth.js +37 -11
- package/dist/esm/api/billing.js +25 -8
- package/dist/esm/api/civic.js +14 -4
- package/dist/esm/api/follows.js +9 -2
- package/dist/esm/api/identity.js +31 -9
- package/dist/esm/api/nodes.js +3 -1
- package/dist/esm/api/privacy.js +8 -2
- package/dist/esm/api/session.js +15 -4
- package/dist/esm/api/store.js +15 -5
- package/dist/esm/api/topics.js +10 -3
- package/dist/esm/api/users.js +16 -4
- package/dist/esm/boot/sessionColdBoot.js +41 -14
- package/dist/esm/constants/version.js +6 -6
- package/dist/esm/crypto/identityMarker.js +3 -1
- package/dist/esm/crypto/identityProof.js +6 -1
- package/dist/esm/crypto/internal.js +1 -1
- package/dist/esm/crypto/keyManager.js +87 -32
- package/dist/esm/crypto/recoveryPhrase.js +2 -2
- package/dist/esm/crypto/signatureService.js +3 -4
- package/dist/esm/i18n/index.js +16 -3
- package/dist/esm/i18n/locales/ar-SA.js +366 -366
- package/dist/esm/i18n/locales/ca-ES.js +366 -366
- package/dist/esm/i18n/locales/de-DE.js +366 -366
- package/dist/esm/i18n/locales/en-US.js +1994 -1994
- package/dist/esm/i18n/locales/es-ES.js +1994 -1994
- package/dist/esm/i18n/locales/fr-FR.js +366 -366
- package/dist/esm/i18n/locales/it-IT.js +366 -366
- package/dist/esm/i18n/locales/ja-JP.js +366 -366
- package/dist/esm/i18n/locales/ko-KR.js +366 -366
- package/dist/esm/i18n/locales/pt-PT.js +366 -366
- package/dist/esm/i18n/locales/zh-CN.js +366 -366
- package/dist/esm/index.js +1 -1
- package/dist/esm/inference/OxyInferenceClient.js +13 -19
- package/dist/esm/models/interfaces.js +11 -11
- package/dist/esm/server/OxyServer.js +87 -29
- package/dist/esm/server/agentAccount.js +6 -2
- package/dist/esm/server/aliaMachineCredential.js +39 -14
- package/dist/esm/server/auth.js +6 -5
- package/dist/esm/server/capabilityTicket.js +6 -6
- package/dist/esm/server/index.js +5 -5
- package/dist/esm/server/liveCapabilityTicket.js +6 -3
- package/dist/esm/server/middleware.js +62 -43
- package/dist/esm/server/namespaces.js +31 -10
- package/dist/esm/server/requesterAssertion.js +36 -30
- package/dist/esm/server/serviceTokenLifetime.js +7 -4
- package/dist/esm/server/traffic.js +55 -16
- package/dist/esm/server/trafficNodeHttp.js +34 -9
- package/dist/esm/server/userInvalidation.js +1 -1
- package/dist/esm/server/workloadIdentity.client.js +3 -0
- package/dist/esm/server/workloadIdentity.js +27 -1
- package/dist/esm/session/SessionClient.js +54 -17
- package/dist/esm/session/accountDelegationAccess.js +5 -7
- package/dist/esm/session/accountDialogController.js +1 -1
- package/dist/esm/session/authStateStore.js +18 -9
- package/dist/esm/session/identityPin.js +6 -2
- package/dist/esm/session/refresh.js +82 -24
- package/dist/esm/session/sharedDeviceCredential.js +28 -15
- package/dist/esm/shared/utils/errorUtils.js +1 -1
- package/dist/esm/shared/utils/networkUtils.js +1 -1
- package/dist/esm/shared/utils/themeUtils.js +1 -1
- package/dist/esm/utils/accountCacheSweep.js +3 -1
- package/dist/esm/utils/accountUtils.js +1 -3
- package/dist/esm/utils/asyncUtils.js +1 -1
- package/dist/esm/utils/authHelpers.js +2 -1
- package/dist/esm/utils/avatarUtils.js +4 -2
- package/dist/esm/utils/cache.js +1 -1
- package/dist/esm/utils/cacheKey.js +3 -1
- package/dist/esm/utils/deviceManager.js +4 -4
- package/dist/esm/utils/errorUtils.js +6 -4
- package/dist/esm/utils/languageUtils.js +404 -57
- package/dist/esm/utils/profileLinks.js +1 -3
- package/dist/esm/utils/requestUtils.js +7 -1
- package/dist/esm/utils/userIdentity.js +1 -1
- package/dist/esm/utils/validationUtils.js +5 -6
- package/dist/types/HttpService.d.ts +1 -1
- package/dist/types/api/accounts.d.ts +1 -1
- package/dist/types/api/apps.d.ts +4 -4
- package/dist/types/api/assets.d.ts +2 -0
- package/dist/types/api/auth.d.ts +8 -3
- package/dist/types/crypto/internal.d.ts +1 -1
- package/dist/types/index.d.ts +4 -4
- package/dist/types/server/index.d.ts +6 -6
- package/dist/types/server/requesterAssertion.d.ts +2 -2
- package/dist/types/server/workloadIdentity.client.d.ts +5 -1
- package/dist/types/server/workloadIdentity.d.ts +26 -0
- package/dist/types/session/accountDelegationAccess.d.ts +1 -1
- package/dist/types/session/index.d.ts +1 -1
- package/dist/types/utils/userIdentity.d.ts +1 -1
- package/dist/types/utils/validationUtils.d.ts +4 -5
- package/package.json +2 -3
- package/src/HttpService.ts +183 -53
- package/src/OxyServices.errors.ts +7 -3
- package/src/OxyServices.ts +6 -2
- package/src/api/accounts.ts +76 -26
- package/src/api/agency.ts +24 -9
- package/src/api/appData.ts +12 -2
- package/src/api/apps.ts +81 -31
- package/src/api/assets.ts +122 -40
- package/src/api/auth.ts +154 -79
- package/src/api/billing.ts +112 -65
- package/src/api/civic.ts +61 -19
- package/src/api/contacts.ts +4 -1
- package/src/api/devices.ts +54 -21
- package/src/api/follows.ts +88 -31
- package/src/api/identity.ts +101 -33
- package/src/api/linkedAccounts.ts +26 -8
- package/src/api/nodes.ts +18 -6
- package/src/api/notifications.ts +26 -6
- package/src/api/privacy.ts +42 -8
- package/src/api/reputation.ts +18 -7
- package/src/api/session.ts +23 -5
- package/src/api/store.ts +81 -31
- package/src/api/topics.ts +18 -6
- package/src/api/users.ts +98 -35
- package/src/boot/sessionColdBoot.ts +60 -19
- package/src/civic/payloads.ts +1 -4
- package/src/client/context.ts +6 -1
- package/src/constants/version.ts +7 -6
- package/src/crypto/aead.ts +1 -5
- package/src/crypto/ecdh.ts +1 -4
- package/src/crypto/identityDerivations.ts +5 -1
- package/src/crypto/identityMarker.ts +3 -1
- package/src/crypto/identityProof.ts +6 -1
- package/src/crypto/index.ts +11 -11
- package/src/crypto/internal.ts +6 -1
- package/src/crypto/keyManager.ts +348 -98
- package/src/crypto/recoveryPhrase.ts +14 -9
- package/src/crypto/registrationPow.ts +1 -1
- package/src/crypto/signatureService.ts +14 -6
- package/src/i18n/accountCategoryLabels.ts +1 -4
- package/src/i18n/accountRoleLabels.ts +1 -4
- package/src/i18n/index.ts +25 -7
- package/src/i18n/locales/ar-SA.ts +375 -366
- package/src/i18n/locales/ca-ES.ts +382 -366
- package/src/i18n/locales/de-DE.ts +387 -366
- package/src/i18n/locales/en-US.ts +2034 -1994
- package/src/i18n/locales/es-ES.ts +2043 -1994
- package/src/i18n/locales/fr-FR.ts +387 -366
- package/src/i18n/locales/it-IT.ts +380 -366
- package/src/i18n/locales/ja-JP.ts +380 -366
- package/src/i18n/locales/ko-KR.ts +377 -366
- package/src/i18n/locales/pt-PT.ts +383 -366
- package/src/i18n/locales/zh-CN.ts +373 -366
- package/src/i18n/trustTierLabels.ts +1 -4
- package/src/index.ts +371 -349
- package/src/inference/OxyInferenceClient.ts +784 -780
- package/src/models/interfaces.ts +30 -27
- package/src/server/OxyServer.ts +227 -68
- package/src/server/agentAccount.ts +8 -2
- package/src/server/aliaMachineCredential.ts +57 -16
- package/src/server/auth.ts +9 -5
- package/src/server/capabilityTicket.ts +30 -21
- package/src/server/index.ts +29 -6
- package/src/server/liveCapabilityTicket.ts +31 -9
- package/src/server/middleware.ts +212 -121
- package/src/server/namespaces.ts +247 -94
- package/src/server/rateLimit.ts +2 -4
- package/src/server/requesterAssertion.ts +93 -54
- package/src/server/serviceTokenLifetime.ts +9 -4
- package/src/server/traffic.ts +117 -23
- package/src/server/trafficNodeHttp.ts +61 -14
- package/src/server/userInvalidation.ts +1 -4
- package/src/server/workloadIdentity.client.ts +12 -1
- package/src/server/workloadIdentity.ts +52 -5
- package/src/session/SessionClient.ts +170 -49
- package/src/session/accountDelegationAccess.ts +24 -31
- package/src/session/accountDialogController.ts +59 -14
- package/src/session/accountSwitchTargets.ts +10 -15
- package/src/session/authStateStore.ts +121 -81
- package/src/session/deviceDirectory.ts +1 -3
- package/src/session/identityPin.ts +10 -11
- package/src/session/identitySession.ts +3 -1
- package/src/session/index.ts +87 -82
- package/src/session/refresh.ts +138 -44
- package/src/session/sessionClientHost.ts +1 -3
- package/src/session/sharedDeviceCredential.ts +35 -14
- package/src/session/socketLoader.ts +9 -2
- package/src/shared/utils/errorUtils.ts +5 -2
- package/src/shared/utils/networkUtils.ts +5 -8
- package/src/shared/utils/themeUtils.ts +2 -6
- package/src/types/buffer.d.ts +66 -21
- package/src/types/expo-secure-store.d.ts +5 -1
- package/src/utils/accountCacheSweep.ts +4 -5
- package/src/utils/accountUtils.ts +107 -108
- package/src/utils/apiUtils.ts +3 -3
- package/src/utils/asyncUtils.ts +2 -2
- package/src/utils/authHelpers.ts +10 -5
- package/src/utils/avatarUtils.ts +11 -6
- package/src/utils/cache.ts +9 -10
- package/src/utils/cacheKey.ts +5 -1
- package/src/utils/coldBoot.ts +1 -3
- package/src/utils/commonsDelivery.ts +1 -4
- package/src/utils/deviceManager.ts +15 -14
- package/src/utils/errorUtils.ts +68 -86
- package/src/utils/languageUtils.ts +407 -58
- package/src/utils/oauthPkce.ts +1 -4
- package/src/utils/platform.ts +0 -1
- package/src/utils/profileLinks.ts +2 -5
- package/src/utils/requestUtils.ts +18 -14
- package/src/utils/sessionUtils.ts +34 -33
- package/src/utils/userHandle.ts +3 -1
- package/src/utils/userIdentity.ts +1 -1
- 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 = {
|
|
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`, {
|
|
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()
|
|
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 ||
|
|
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, {
|
|
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, {
|
|
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, {
|
|
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, {
|
|
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, {
|
|
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, {
|
|
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 &&
|
|
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) &&
|
|
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 {
|
|
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 {
|
|
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 {
|
|
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, {
|
|
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 {
|
|
1483
|
+
catch {
|
|
1484
|
+
/* best effort */
|
|
1485
|
+
}
|
|
1452
1486
|
try {
|
|
1453
1487
|
await store.deleteItemAsync(layout.primaryPrivateKeyName, primaryReadOpts);
|
|
1454
1488
|
}
|
|
1455
|
-
catch {
|
|
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, {
|
|
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, {
|
|
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', {
|
|
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', {
|
|
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, {
|
|
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) ||
|
|
2120
|
-
|
|
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', {
|
|
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, {
|
|
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 &&
|
|
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, {
|
|
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
|
|
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);
|
package/dist/esm/i18n/index.js
CHANGED
|
@@ -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',
|
|
24
|
-
|
|
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
|
|
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);
|