@oxyhq/core 10.1.5 → 11.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/.tsbuildinfo +1 -1
- package/dist/cjs/boot/sessionColdBoot.js +3 -3
- package/dist/cjs/crypto/keyManager.js +68 -69
- package/dist/cjs/crypto/signatureService.js +2 -2
- package/dist/cjs/index.js +13 -21
- package/dist/cjs/logger/index.js +149 -0
- package/dist/cjs/mixins/OxyServices.assets.js +4 -4
- package/dist/cjs/mixins/OxyServices.auth.js +2 -2
- package/dist/cjs/mixins/OxyServices.language.js +3 -5
- package/dist/cjs/mixins/OxyServices.privacy.js +2 -4
- package/dist/cjs/mixins/OxyServices.security.js +7 -11
- package/dist/cjs/mixins/OxyServices.topics.js +25 -15
- package/dist/cjs/mixins/OxyServices.user.js +4 -4
- package/dist/cjs/mixins/OxyServices.utility.js +18 -18
- package/dist/cjs/server/rateLimit.js +100 -6
- package/dist/cjs/session/SessionClient.js +17 -17
- package/dist/cjs/session/accountDialogController.js +12 -12
- package/dist/cjs/session/authStateStore.js +5 -5
- package/dist/cjs/session/refresh.js +4 -4
- package/dist/cjs/session/socketLoader.js +2 -2
- package/dist/cjs/utils/asyncUtils.js +2 -2
- package/dist/cjs/utils/avatarUtils.js +2 -1
- package/dist/cjs/utils/deviceManager.js +7 -5
- package/dist/cjs/utils/errorUtils.js +3 -3
- package/dist/cjs/utils/oauthPkce.js +3 -3
- package/dist/cjs/utils/requestUtils.js +1 -1
- package/dist/esm/.tsbuildinfo +1 -1
- package/dist/esm/boot/sessionColdBoot.js +1 -1
- package/dist/esm/crypto/keyManager.js +1 -2
- package/dist/esm/crypto/signatureService.js +1 -1
- package/dist/esm/index.js +2 -3
- package/dist/esm/logger/index.js +140 -0
- package/dist/esm/mixins/OxyServices.assets.js +2 -2
- package/dist/esm/mixins/OxyServices.auth.js +1 -1
- package/dist/esm/mixins/OxyServices.language.js +3 -5
- package/dist/esm/mixins/OxyServices.privacy.js +2 -4
- package/dist/esm/mixins/OxyServices.security.js +7 -11
- package/dist/esm/mixins/OxyServices.topics.js +25 -15
- package/dist/esm/mixins/OxyServices.user.js +1 -1
- package/dist/esm/mixins/OxyServices.utility.js +1 -1
- package/dist/esm/server/rateLimit.js +100 -6
- package/dist/esm/session/SessionClient.js +1 -1
- package/dist/esm/session/accountDialogController.js +1 -1
- package/dist/esm/session/authStateStore.js +1 -1
- package/dist/esm/session/refresh.js +1 -1
- package/dist/esm/session/socketLoader.js +1 -1
- package/dist/esm/utils/asyncUtils.js +1 -1
- package/dist/esm/utils/avatarUtils.js +2 -1
- package/dist/esm/utils/deviceManager.js +7 -5
- package/dist/esm/utils/errorUtils.js +1 -1
- package/dist/esm/utils/oauthPkce.js +1 -1
- package/dist/esm/utils/requestUtils.js +1 -1
- package/dist/types/.tsbuildinfo +1 -1
- package/dist/types/index.d.ts +3 -4
- package/dist/types/logger/index.d.ts +104 -0
- package/dist/types/mixins/OxyServices.topics.d.ts +3 -3
- package/dist/types/models/Topic.d.ts +10 -0
- package/dist/types/utils/requestUtils.d.ts +1 -1
- package/package.json +16 -1
- package/src/boot/sessionColdBoot.ts +1 -1
- package/src/crypto/keyManager.ts +1 -2
- package/src/crypto/signatureService.ts +1 -1
- package/src/index.ts +17 -19
- package/src/logger/__tests__/logger.test.ts +207 -0
- package/src/logger/index.ts +217 -0
- package/src/mixins/OxyServices.assets.ts +3 -3
- package/src/mixins/OxyServices.auth.ts +1 -1
- package/src/mixins/OxyServices.language.ts +3 -5
- package/src/mixins/OxyServices.privacy.ts +2 -4
- package/src/mixins/OxyServices.security.ts +7 -11
- package/src/mixins/OxyServices.topics.ts +47 -17
- package/src/mixins/OxyServices.user.ts +1 -1
- package/src/mixins/OxyServices.utility.ts +1 -1
- package/src/mixins/__tests__/discoveryErrorHandling.test.ts +1 -1
- package/src/mixins/__tests__/topics.test.ts +156 -0
- package/src/models/Topic.ts +11 -0
- package/src/server/__tests__/rateLimit.test.ts +98 -4
- package/src/server/rateLimit.ts +105 -6
- package/src/session/SessionClient.ts +1 -1
- package/src/session/__tests__/SessionClient.diagnostics.test.ts +1 -1
- package/src/session/__tests__/accountDialogController.test.ts +1 -1
- package/src/session/accountDialogController.ts +1 -1
- package/src/session/authStateStore.ts +1 -1
- package/src/session/refresh.ts +1 -1
- package/src/session/socketLoader.ts +1 -1
- package/src/utils/asyncUtils.ts +1 -1
- package/src/utils/avatarUtils.ts +3 -1
- package/src/utils/deviceManager.ts +8 -5
- package/src/utils/errorUtils.ts +1 -1
- package/src/utils/oauthPkce.ts +1 -1
- package/src/utils/requestUtils.ts +1 -1
- package/dist/cjs/shared/utils/debugUtils.js +0 -80
- package/dist/cjs/utils/loggerUtils.js +0 -126
- package/dist/esm/shared/utils/debugUtils.js +0 -72
- package/dist/esm/utils/loggerUtils.js +0 -115
- package/dist/types/shared/utils/debugUtils.d.ts +0 -48
- package/dist/types/utils/loggerUtils.d.ts +0 -48
- package/src/shared/utils/__tests__/debugUtils.test.ts +0 -55
- package/src/shared/utils/debugUtils.ts +0 -78
- package/src/utils/loggerUtils.ts +0 -153
|
@@ -25,7 +25,7 @@ exports.runSessionColdBoot = runSessionColdBoot;
|
|
|
25
25
|
*/
|
|
26
26
|
const coldBoot_1 = require("../utils/coldBoot");
|
|
27
27
|
const platform_1 = require("../utils/platform");
|
|
28
|
-
const
|
|
28
|
+
const logger_1 = require("../logger");
|
|
29
29
|
const refresh_1 = require("../session/refresh");
|
|
30
30
|
/**
|
|
31
31
|
* Run the device-first cold boot. Resolves to the `runColdBoot` outcome and, as
|
|
@@ -119,11 +119,11 @@ async function runSessionColdBoot(opts) {
|
|
|
119
119
|
// The mint rotated the secret but it could not be durably persisted —
|
|
120
120
|
// refuse to advertise a session that will not survive a reload. Keep
|
|
121
121
|
// the secret; a later boot/attempt re-mints once storage recovers.
|
|
122
|
-
|
|
122
|
+
logger_1.logger.error('device-secret mint rotated the secret but it could not be durably persisted — not planting', undefined, { component: 'sessionColdBoot', method: 'device-secret-mint' });
|
|
123
123
|
return { kind: 'skip' };
|
|
124
124
|
case 'transient':
|
|
125
125
|
// Network / 5xx: keep the secret; a later attempt can succeed.
|
|
126
|
-
|
|
126
|
+
logger_1.logger.debug('device-secret mint failed (transient) — keeping secret', { component: 'sessionColdBoot', method: 'device-secret-mint' });
|
|
127
127
|
return { kind: 'skip' };
|
|
128
128
|
case 'no-secret':
|
|
129
129
|
return { kind: 'skip' };
|
|
@@ -10,8 +10,7 @@ exports.KeyManager = exports.IdentityPersistError = exports.IdentityAlreadyExist
|
|
|
10
10
|
const elliptic_1 = require("elliptic");
|
|
11
11
|
const platform_1 = require("../utils/platform");
|
|
12
12
|
const protocol_1 = require("@oxyhq/protocol");
|
|
13
|
-
const
|
|
14
|
-
const debugUtils_1 = require("../shared/utils/debugUtils");
|
|
13
|
+
const logger_1 = require("../logger");
|
|
15
14
|
/**
|
|
16
15
|
* Thrown when an identity-mutating operation (createIdentity / importKeyPair)
|
|
17
16
|
* is invoked while a valid identity already exists on the device.
|
|
@@ -253,8 +252,8 @@ class KeyManager {
|
|
|
253
252
|
// Update cache
|
|
254
253
|
KeyManager.cachedSharedPublicKey = publicKey;
|
|
255
254
|
KeyManager.cachedHasSharedIdentity = true;
|
|
256
|
-
if ((0,
|
|
257
|
-
|
|
255
|
+
if ((0, logger_1.isDev)()) {
|
|
256
|
+
logger_1.logger.debug('Shared identity created successfully', { component: 'KeyManager' });
|
|
258
257
|
}
|
|
259
258
|
return publicKey;
|
|
260
259
|
}
|
|
@@ -294,8 +293,8 @@ class KeyManager {
|
|
|
294
293
|
return publicKey;
|
|
295
294
|
}
|
|
296
295
|
catch (error) {
|
|
297
|
-
if ((0,
|
|
298
|
-
|
|
296
|
+
if ((0, logger_1.isDev)()) {
|
|
297
|
+
logger_1.logger.warn('Failed to get shared public key', { component: 'KeyManager' }, error);
|
|
299
298
|
}
|
|
300
299
|
KeyManager.cachedSharedPublicKey = null;
|
|
301
300
|
return null;
|
|
@@ -334,8 +333,8 @@ class KeyManager {
|
|
|
334
333
|
return privateKey;
|
|
335
334
|
}
|
|
336
335
|
catch (error) {
|
|
337
|
-
if ((0,
|
|
338
|
-
|
|
336
|
+
if ((0, logger_1.isDev)()) {
|
|
337
|
+
logger_1.logger.warn('Failed to get shared private key', { component: 'KeyManager' }, error);
|
|
339
338
|
}
|
|
340
339
|
return null;
|
|
341
340
|
}
|
|
@@ -361,8 +360,8 @@ class KeyManager {
|
|
|
361
360
|
return hasShared;
|
|
362
361
|
}
|
|
363
362
|
catch (error) {
|
|
364
|
-
if ((0,
|
|
365
|
-
|
|
363
|
+
if ((0, logger_1.isDev)()) {
|
|
364
|
+
logger_1.logger.warn('Failed to check shared identity', { component: 'KeyManager' }, error);
|
|
366
365
|
}
|
|
367
366
|
KeyManager.cachedHasSharedIdentity = false;
|
|
368
367
|
return false;
|
|
@@ -418,8 +417,8 @@ class KeyManager {
|
|
|
418
417
|
// Update cache
|
|
419
418
|
KeyManager.cachedSharedPublicKey = publicKey;
|
|
420
419
|
KeyManager.cachedHasSharedIdentity = true;
|
|
421
|
-
if ((0,
|
|
422
|
-
|
|
420
|
+
if ((0, logger_1.isDev)()) {
|
|
421
|
+
logger_1.logger.debug('Shared identity imported successfully', { component: 'KeyManager' });
|
|
423
422
|
}
|
|
424
423
|
return publicKey;
|
|
425
424
|
}
|
|
@@ -454,13 +453,13 @@ class KeyManager {
|
|
|
454
453
|
await store.setItemAsync(STORAGE_KEYS.SHARED_SESSION_ID, sessionId);
|
|
455
454
|
await store.setItemAsync(STORAGE_KEYS.SHARED_SESSION_TOKEN, accessToken);
|
|
456
455
|
}
|
|
457
|
-
if ((0,
|
|
458
|
-
|
|
456
|
+
if ((0, logger_1.isDev)()) {
|
|
457
|
+
logger_1.logger.debug('Shared session stored successfully', { component: 'KeyManager' });
|
|
459
458
|
}
|
|
460
459
|
}
|
|
461
460
|
catch (error) {
|
|
462
|
-
if ((0,
|
|
463
|
-
|
|
461
|
+
if ((0, logger_1.isDev)()) {
|
|
462
|
+
logger_1.logger.error('Failed to store shared session', error, { component: 'KeyManager' });
|
|
464
463
|
}
|
|
465
464
|
throw error;
|
|
466
465
|
}
|
|
@@ -496,8 +495,8 @@ class KeyManager {
|
|
|
496
495
|
return { sessionId, accessToken };
|
|
497
496
|
}
|
|
498
497
|
catch (error) {
|
|
499
|
-
if ((0,
|
|
500
|
-
|
|
498
|
+
if ((0, logger_1.isDev)()) {
|
|
499
|
+
logger_1.logger.warn('Failed to get shared session', { component: 'KeyManager' }, error);
|
|
501
500
|
}
|
|
502
501
|
return null;
|
|
503
502
|
}
|
|
@@ -523,13 +522,13 @@ class KeyManager {
|
|
|
523
522
|
await store.deleteItemAsync(STORAGE_KEYS.SHARED_SESSION_ID);
|
|
524
523
|
await store.deleteItemAsync(STORAGE_KEYS.SHARED_SESSION_TOKEN);
|
|
525
524
|
}
|
|
526
|
-
if ((0,
|
|
527
|
-
|
|
525
|
+
if ((0, logger_1.isDev)()) {
|
|
526
|
+
logger_1.logger.debug('Shared session cleared successfully', { component: 'KeyManager' });
|
|
528
527
|
}
|
|
529
528
|
}
|
|
530
529
|
catch (error) {
|
|
531
|
-
if ((0,
|
|
532
|
-
|
|
530
|
+
if ((0, logger_1.isDev)()) {
|
|
531
|
+
logger_1.logger.error('Failed to clear shared session', error, { component: 'KeyManager' });
|
|
533
532
|
}
|
|
534
533
|
}
|
|
535
534
|
}
|
|
@@ -550,29 +549,29 @@ class KeyManager {
|
|
|
550
549
|
// Check if we already have a shared identity
|
|
551
550
|
const hasShared = await KeyManager.hasSharedIdentity();
|
|
552
551
|
if (hasShared) {
|
|
553
|
-
if ((0,
|
|
554
|
-
|
|
552
|
+
if ((0, logger_1.isDev)()) {
|
|
553
|
+
logger_1.logger.debug('Shared identity already exists, skipping migration', { component: 'KeyManager' });
|
|
555
554
|
}
|
|
556
555
|
return true;
|
|
557
556
|
}
|
|
558
557
|
// Get local identity
|
|
559
558
|
const privateKey = await KeyManager.getPrivateKey();
|
|
560
559
|
if (!privateKey) {
|
|
561
|
-
if ((0,
|
|
562
|
-
|
|
560
|
+
if ((0, logger_1.isDev)()) {
|
|
561
|
+
logger_1.logger.debug('No local identity to migrate', { component: 'KeyManager' });
|
|
563
562
|
}
|
|
564
563
|
return false;
|
|
565
564
|
}
|
|
566
565
|
// Import to shared storage
|
|
567
566
|
await KeyManager.importSharedIdentity(privateKey);
|
|
568
|
-
if ((0,
|
|
569
|
-
|
|
567
|
+
if ((0, logger_1.isDev)()) {
|
|
568
|
+
logger_1.logger.debug('Successfully migrated local identity to shared identity', { component: 'KeyManager' });
|
|
570
569
|
}
|
|
571
570
|
return true;
|
|
572
571
|
}
|
|
573
572
|
catch (error) {
|
|
574
|
-
if ((0,
|
|
575
|
-
|
|
573
|
+
if ((0, logger_1.isDev)()) {
|
|
574
|
+
logger_1.logger.error('Failed to migrate to shared identity', error, { component: 'KeyManager' });
|
|
576
575
|
}
|
|
577
576
|
return false;
|
|
578
577
|
}
|
|
@@ -626,7 +625,7 @@ class KeyManager {
|
|
|
626
625
|
priorPublic = await store.getItemAsync(STORAGE_KEYS.PUBLIC_KEY);
|
|
627
626
|
}
|
|
628
627
|
catch (error) {
|
|
629
|
-
|
|
628
|
+
logger_1.logger.error('Failed to read existing primary before persist', error, { component: 'KeyManager' });
|
|
630
629
|
throw new IdentityPersistError('Could not read existing identity before writing a new one; refusing to overwrite blind.', error);
|
|
631
630
|
}
|
|
632
631
|
// If we are replacing a DIFFERENT, currently-healthy identity, make sure
|
|
@@ -659,7 +658,7 @@ class KeyManager {
|
|
|
659
658
|
await store.setItemAsync(STORAGE_KEYS.BACKUP_TIMESTAMP, Date.now().toString());
|
|
660
659
|
}
|
|
661
660
|
catch (error) {
|
|
662
|
-
|
|
661
|
+
logger_1.logger.error('Failed to back up existing identity before overwrite', error, { component: 'KeyManager' });
|
|
663
662
|
throw new IdentityPersistError('Failed to back up existing identity before overwrite', error);
|
|
664
663
|
}
|
|
665
664
|
}
|
|
@@ -675,7 +674,7 @@ class KeyManager {
|
|
|
675
674
|
});
|
|
676
675
|
}
|
|
677
676
|
catch (error) {
|
|
678
|
-
|
|
677
|
+
logger_1.logger.error('Failed to write primary identity to secure store', error, { component: 'KeyManager' });
|
|
679
678
|
await KeyManager._rollbackPrimary(store, priorPrivate, priorPublic);
|
|
680
679
|
throw new IdentityPersistError('Failed to write identity to secure store', error);
|
|
681
680
|
}
|
|
@@ -690,7 +689,7 @@ class KeyManager {
|
|
|
690
689
|
readBackPublic = await store.getItemAsync(STORAGE_KEYS.PUBLIC_KEY);
|
|
691
690
|
}
|
|
692
691
|
catch (error) {
|
|
693
|
-
|
|
692
|
+
logger_1.logger.error('Failed to read identity back after write', error, { component: 'KeyManager' });
|
|
694
693
|
await KeyManager._rollbackPrimary(store, priorPrivate, priorPublic);
|
|
695
694
|
throw new IdentityPersistError('Failed to verify identity after write', error);
|
|
696
695
|
}
|
|
@@ -699,7 +698,7 @@ class KeyManager {
|
|
|
699
698
|
// trigger a spurious mismatch.
|
|
700
699
|
if (readBackPrivate?.toLowerCase() !== canonicalPrivate ||
|
|
701
700
|
readBackPublic?.toLowerCase() !== canonicalPublic) {
|
|
702
|
-
|
|
701
|
+
logger_1.logger.error('Identity round-trip mismatch after write', undefined, { component: 'KeyManager' });
|
|
703
702
|
await KeyManager._rollbackPrimary(store, priorPrivate, priorPublic);
|
|
704
703
|
throw new IdentityPersistError('Identity write was not persisted correctly (round-trip mismatch).');
|
|
705
704
|
}
|
|
@@ -724,7 +723,7 @@ class KeyManager {
|
|
|
724
723
|
await KeyManager._rollbackPrimary(store, priorPrivate, priorPublic);
|
|
725
724
|
if (error instanceof IdentityPersistError)
|
|
726
725
|
throw error;
|
|
727
|
-
|
|
726
|
+
logger_1.logger.error('Identity sign/verify probe failed', error, { component: 'KeyManager' });
|
|
728
727
|
throw new IdentityPersistError('Stored identity failed crypto self-test', error);
|
|
729
728
|
}
|
|
730
729
|
// Step 3: The new primary is durable and functional. NOW it is safe to
|
|
@@ -743,7 +742,7 @@ class KeyManager {
|
|
|
743
742
|
priorBackupTimestamp = await store.getItemAsync(STORAGE_KEYS.BACKUP_TIMESTAMP);
|
|
744
743
|
}
|
|
745
744
|
catch (error) {
|
|
746
|
-
|
|
745
|
+
logger_1.logger.error('Failed to snapshot identity backup before refresh', error, { component: 'KeyManager' });
|
|
747
746
|
await KeyManager._rollbackPrimary(store, priorPrivate, priorPublic);
|
|
748
747
|
throw new IdentityPersistError('Failed to snapshot identity backup before refresh', error);
|
|
749
748
|
}
|
|
@@ -755,7 +754,7 @@ class KeyManager {
|
|
|
755
754
|
await store.setItemAsync(STORAGE_KEYS.BACKUP_TIMESTAMP, Date.now().toString());
|
|
756
755
|
}
|
|
757
756
|
catch (error) {
|
|
758
|
-
|
|
757
|
+
logger_1.logger.error('Failed to refresh identity backup after primary write', error, { component: 'KeyManager' });
|
|
759
758
|
await KeyManager._rollbackBackup(store, priorBackupPrivate, priorBackupPublic, priorBackupTimestamp);
|
|
760
759
|
await KeyManager._rollbackPrimary(store, priorPrivate, priorPublic);
|
|
761
760
|
throw new IdentityPersistError('Failed to refresh identity backup after primary write', error);
|
|
@@ -803,7 +802,7 @@ class KeyManager {
|
|
|
803
802
|
}
|
|
804
803
|
}
|
|
805
804
|
catch (rollbackError) {
|
|
806
|
-
|
|
805
|
+
logger_1.logger.error('Failed to roll back identity backup after a failed refresh', rollbackError, { component: 'KeyManager' });
|
|
807
806
|
}
|
|
808
807
|
}
|
|
809
808
|
/**
|
|
@@ -838,7 +837,7 @@ class KeyManager {
|
|
|
838
837
|
}
|
|
839
838
|
}
|
|
840
839
|
catch (rollbackError) {
|
|
841
|
-
|
|
840
|
+
logger_1.logger.error('Failed to roll back primary identity after a failed write', rollbackError, { component: 'KeyManager' });
|
|
842
841
|
}
|
|
843
842
|
finally {
|
|
844
843
|
// Whatever happened, the cached verdict is no longer trustworthy.
|
|
@@ -922,8 +921,8 @@ class KeyManager {
|
|
|
922
921
|
catch (error) {
|
|
923
922
|
// If secure store is not available, return null (no identity)
|
|
924
923
|
// This allows the app to continue functioning even if secure store fails to load
|
|
925
|
-
if ((0,
|
|
926
|
-
|
|
924
|
+
if ((0, logger_1.isDev)()) {
|
|
925
|
+
logger_1.logger.warn('Failed to access secure store', { component: 'KeyManager' }, error);
|
|
927
926
|
}
|
|
928
927
|
return null;
|
|
929
928
|
}
|
|
@@ -949,8 +948,8 @@ class KeyManager {
|
|
|
949
948
|
// If secure store is not available, return null (no identity)
|
|
950
949
|
// Cache null to avoid repeated failed attempts
|
|
951
950
|
KeyManager.cachedPublicKey = null;
|
|
952
|
-
if ((0,
|
|
953
|
-
|
|
951
|
+
if ((0, logger_1.isDev)()) {
|
|
952
|
+
logger_1.logger.warn('Failed to access secure store', { component: 'KeyManager' }, error);
|
|
954
953
|
}
|
|
955
954
|
return null;
|
|
956
955
|
}
|
|
@@ -988,7 +987,7 @@ class KeyManager {
|
|
|
988
987
|
// did, the next call would skip storage entirely and return false even
|
|
989
988
|
// after the device is unlocked. Just return false and let the next
|
|
990
989
|
// call retry from storage.
|
|
991
|
-
|
|
990
|
+
logger_1.logger.error('Failed to read identity from secure storage', error, { component: 'KeyManager' });
|
|
992
991
|
return false;
|
|
993
992
|
}
|
|
994
993
|
// Storage succeeded. Now classify the result. From here onward, any
|
|
@@ -1009,15 +1008,15 @@ class KeyManager {
|
|
|
1009
1008
|
// tolerate legacy uppercase-stored public keys.
|
|
1010
1009
|
hasIdentity = derived.toLowerCase() === publicKey.toLowerCase();
|
|
1011
1010
|
if (!hasIdentity) {
|
|
1012
|
-
|
|
1011
|
+
logger_1.logger.warn('KeyManager.hasIdentity: stored public key does not match derived public key', { component: 'KeyManager' });
|
|
1013
1012
|
}
|
|
1014
1013
|
}
|
|
1015
1014
|
catch (error) {
|
|
1016
|
-
|
|
1015
|
+
logger_1.logger.warn('KeyManager.hasIdentity: failed to derive public key from stored private key', { component: 'KeyManager' }, error);
|
|
1017
1016
|
}
|
|
1018
1017
|
}
|
|
1019
1018
|
else {
|
|
1020
|
-
|
|
1019
|
+
logger_1.logger.warn('KeyManager.hasIdentity: stored key material is malformed', { component: 'KeyManager' });
|
|
1021
1020
|
}
|
|
1022
1021
|
}
|
|
1023
1022
|
// Cache result. Storage succeeded, so this verdict is stable:
|
|
@@ -1032,8 +1031,8 @@ class KeyManager {
|
|
|
1032
1031
|
// Diagnostic breadcrumb (dev only). Logs lengths + validity flags so we
|
|
1033
1032
|
// can tell from `adb logcat` exactly WHY hasIdentity returned what it
|
|
1034
1033
|
// did. Never log the key material itself.
|
|
1035
|
-
if ((0,
|
|
1036
|
-
|
|
1034
|
+
if ((0, logger_1.isDev)()) {
|
|
1035
|
+
logger_1.logger.debug('KeyManager.hasIdentity result', { component: 'KeyManager' }, {
|
|
1037
1036
|
privateLen: privateKey?.length ?? 0,
|
|
1038
1037
|
publicLen: publicKey?.length ?? 0,
|
|
1039
1038
|
privateValid: privateKey ? KeyManager.isValidPrivateKey(privateKey) : null,
|
|
@@ -1070,13 +1069,13 @@ class KeyManager {
|
|
|
1070
1069
|
if (!skipBackup) {
|
|
1071
1070
|
try {
|
|
1072
1071
|
const backupSuccess = await KeyManager.backupIdentity();
|
|
1073
|
-
if (!backupSuccess && (0,
|
|
1074
|
-
|
|
1072
|
+
if (!backupSuccess && (0, logger_1.isDev)()) {
|
|
1073
|
+
logger_1.logger.warn('Failed to backup identity before deletion - proceeding anyway', { component: 'KeyManager' });
|
|
1075
1074
|
}
|
|
1076
1075
|
}
|
|
1077
1076
|
catch (backupError) {
|
|
1078
|
-
if ((0,
|
|
1079
|
-
|
|
1077
|
+
if ((0, logger_1.isDev)()) {
|
|
1078
|
+
logger_1.logger.warn('Failed to backup identity before deletion', { component: 'KeyManager' }, backupError);
|
|
1080
1079
|
}
|
|
1081
1080
|
}
|
|
1082
1081
|
}
|
|
@@ -1120,8 +1119,8 @@ class KeyManager {
|
|
|
1120
1119
|
return true;
|
|
1121
1120
|
}
|
|
1122
1121
|
catch (error) {
|
|
1123
|
-
if ((0,
|
|
1124
|
-
|
|
1122
|
+
if ((0, logger_1.isDev)()) {
|
|
1123
|
+
logger_1.logger.error('Failed to backup identity', error, { component: 'KeyManager' });
|
|
1125
1124
|
}
|
|
1126
1125
|
return false;
|
|
1127
1126
|
}
|
|
@@ -1165,13 +1164,13 @@ class KeyManager {
|
|
|
1165
1164
|
const probeHash = '0'.repeat(64);
|
|
1166
1165
|
const signature = keyPair.sign(probeHash);
|
|
1167
1166
|
if (!keyPair.verify(probeHash, signature)) {
|
|
1168
|
-
|
|
1167
|
+
logger_1.logger.error('Identity sign/verify probe failed during integrity check', undefined, { component: 'KeyManager' });
|
|
1169
1168
|
return false;
|
|
1170
1169
|
}
|
|
1171
1170
|
return true;
|
|
1172
1171
|
}
|
|
1173
1172
|
catch (error) {
|
|
1174
|
-
|
|
1173
|
+
logger_1.logger.error('Identity integrity check failed', error, { component: 'KeyManager' });
|
|
1175
1174
|
return false;
|
|
1176
1175
|
}
|
|
1177
1176
|
}
|
|
@@ -1212,7 +1211,7 @@ class KeyManager {
|
|
|
1212
1211
|
primaryPublic = await store.getItemAsync(STORAGE_KEYS.PUBLIC_KEY);
|
|
1213
1212
|
}
|
|
1214
1213
|
catch (error) {
|
|
1215
|
-
|
|
1214
|
+
logger_1.logger.warn('restoreIdentityFromBackup: could not read primary (transient?). Refusing to restore.', { component: 'KeyManager' }, error);
|
|
1216
1215
|
return false;
|
|
1217
1216
|
}
|
|
1218
1217
|
// If the primary reads back as a complete, self-consistent identity, it
|
|
@@ -1231,7 +1230,7 @@ class KeyManager {
|
|
|
1231
1230
|
return false; // No backup available
|
|
1232
1231
|
}
|
|
1233
1232
|
if (!KeyManager.isValidPrivateKey(backupPrivateKey) || !KeyManager.isValidPublicKey(backupPublicKey)) {
|
|
1234
|
-
|
|
1233
|
+
logger_1.logger.warn('Backup identity is malformed; refusing to restore', { component: 'KeyManager' });
|
|
1235
1234
|
return false;
|
|
1236
1235
|
}
|
|
1237
1236
|
// Verify backup keys derive consistently. Hex is case-insensitive so
|
|
@@ -1239,7 +1238,7 @@ class KeyManager {
|
|
|
1239
1238
|
// be considered valid.
|
|
1240
1239
|
const derivedPublicKey = KeyManager.derivePublicKey(backupPrivateKey);
|
|
1241
1240
|
if (derivedPublicKey.toLowerCase() !== backupPublicKey.toLowerCase()) {
|
|
1242
|
-
|
|
1241
|
+
logger_1.logger.warn('Backup public key does not match derived; refusing to restore', { component: 'KeyManager' });
|
|
1243
1242
|
return false;
|
|
1244
1243
|
}
|
|
1245
1244
|
// Guard 3: if ANY primary key material is still present and identifies a
|
|
@@ -1250,13 +1249,13 @@ class KeyManager {
|
|
|
1250
1249
|
// different identity is sitting in the primary slot.
|
|
1251
1250
|
if (primaryPublic &&
|
|
1252
1251
|
primaryPublic.toLowerCase() !== backupPublicKey.toLowerCase()) {
|
|
1253
|
-
|
|
1252
|
+
logger_1.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' });
|
|
1254
1253
|
return false;
|
|
1255
1254
|
}
|
|
1256
1255
|
if (primaryPrivate &&
|
|
1257
1256
|
KeyManager.isValidPrivateKey(primaryPrivate) &&
|
|
1258
1257
|
KeyManager.derivePublicKey(primaryPrivate).toLowerCase() !== backupPublicKey.toLowerCase()) {
|
|
1259
|
-
|
|
1258
|
+
logger_1.logger.error('Primary private key identifies a DIFFERENT identity than the backup. Refusing to restore to avoid switching accounts.', undefined, { component: 'KeyManager' });
|
|
1260
1259
|
return false;
|
|
1261
1260
|
}
|
|
1262
1261
|
// Safe to restore: rebuild the primary using the same atomic write
|
|
@@ -1265,14 +1264,14 @@ class KeyManager {
|
|
|
1265
1264
|
await KeyManager._persistIdentityAtomic(backupPrivateKey, backupPublicKey);
|
|
1266
1265
|
}
|
|
1267
1266
|
catch (error) {
|
|
1268
|
-
|
|
1267
|
+
logger_1.logger.error('Failed to persist identity restored from backup', error, { component: 'KeyManager' });
|
|
1269
1268
|
return false;
|
|
1270
1269
|
}
|
|
1271
1270
|
await store.setItemAsync(STORAGE_KEYS.BACKUP_TIMESTAMP, Date.now().toString());
|
|
1272
1271
|
return true;
|
|
1273
1272
|
}
|
|
1274
1273
|
catch (error) {
|
|
1275
|
-
|
|
1274
|
+
logger_1.logger.error('Failed to restore identity from backup', error, { component: 'KeyManager' });
|
|
1276
1275
|
return false;
|
|
1277
1276
|
}
|
|
1278
1277
|
}
|
|
@@ -1322,8 +1321,8 @@ class KeyManager {
|
|
|
1322
1321
|
return true;
|
|
1323
1322
|
}
|
|
1324
1323
|
catch (error) {
|
|
1325
|
-
if ((0,
|
|
1326
|
-
|
|
1324
|
+
if ((0, logger_1.isDev)()) {
|
|
1325
|
+
logger_1.logger.debug('[oxy.crypto] isValidPublicKey rejected input', { component: 'KeyManager' }, error);
|
|
1327
1326
|
}
|
|
1328
1327
|
return false;
|
|
1329
1328
|
}
|
|
@@ -1377,8 +1376,8 @@ class KeyManager {
|
|
|
1377
1376
|
return true;
|
|
1378
1377
|
}
|
|
1379
1378
|
catch (error) {
|
|
1380
|
-
if ((0,
|
|
1381
|
-
|
|
1379
|
+
if ((0, logger_1.isDev)()) {
|
|
1380
|
+
logger_1.logger.debug('[oxy.crypto] isValidPrivateKey rejected input', { component: 'KeyManager' }, error);
|
|
1382
1381
|
}
|
|
1383
1382
|
return false;
|
|
1384
1383
|
}
|
|
@@ -12,7 +12,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
12
12
|
exports.SignatureService = void 0;
|
|
13
13
|
const protocol_1 = require("@oxyhq/protocol");
|
|
14
14
|
const keyManager_1 = require("./keyManager");
|
|
15
|
-
const
|
|
15
|
+
const logger_1 = require("../logger");
|
|
16
16
|
class SignatureService {
|
|
17
17
|
/**
|
|
18
18
|
* Generate a random challenge string (for offline use)
|
|
@@ -34,7 +34,7 @@ class SignatureService {
|
|
|
34
34
|
}
|
|
35
35
|
catch (error) {
|
|
36
36
|
// Node crypto failed to load — log and fall through to Web Crypto API
|
|
37
|
-
|
|
37
|
+
logger_1.logger.warn('[oxy.crypto] Node crypto unavailable, falling back to Web Crypto', { component: 'SignatureService' }, error);
|
|
38
38
|
}
|
|
39
39
|
}
|
|
40
40
|
// Browser: use Web Crypto API
|
package/dist/cjs/index.js
CHANGED
|
@@ -19,9 +19,9 @@
|
|
|
19
19
|
*/
|
|
20
20
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21
21
|
exports.isWeb = exports.setPlatformOS = exports.getPlatformOS = exports.getPrimaryLanguage = exports.getUserLanguages = exports.isRTLLocale = exports.getNativeLanguageName = exports.getLanguageName = exports.getLanguageMetadata = exports.isSupportedLocale = exports.normalizeLocale = exports.getBaseLanguage = exports.FALLBACK_LOCALE = exports.SUPPORTED_LANGUAGES = exports.TopicSource = exports.TopicType = exports.SECURITY_EVENT_SEVERITY_MAP = exports.DeviceManager = exports.RecoveryPhraseService = exports.SignatureService = exports.IdentityPersistError = exports.IdentityAlreadyExistsError = exports.KeyManager = exports.sessionsArraysEqual = exports.normalizeAndSortSessions = exports.mergeSessions = exports.authenticatedApiCall = exports.withAuthErrorHandling = exports.isAuthenticationError = exports.ensureValidToken = exports.AuthenticationFailedError = exports.SessionSyncRequiredError = exports.verifyPublicCardAttestation = exports.parseAttestPayload = exports.parseIdPayload = exports.buildUserDid = exports.ORGANIZATION_CATEGORIES = exports.normalizeProfileLinks = exports.getNormalizedUserHandle = exports.getCanonicalUserHandle = exports.normalizeUserIdentityOrNull = exports.normalizeUserIdentity = exports.getNormalizedUserId = exports.OxyAppDataIdentifierError = exports.ServiceCredentialMismatchError = exports.oxyClient = exports.OXY_CLOUD_URL = exports.OxyAuthenticationTimeoutError = exports.OxyAuthenticationError = exports.OxyServices = void 0;
|
|
22
|
-
exports.
|
|
23
|
-
exports.OXY_OAUTH_CODE_VERIFIER_STORAGE_KEY = exports.OXY_OAUTH_STATE_STORAGE_KEY = exports.OXY_AUTHORIZE_URL = exports.DEFAULT_OAUTH_SCOPE = exports.generatePkcePair = exports.generateOAuthState = exports.computeCodeChallenge = exports.buildOAuthAuthorizeUrl = exports.runColdBoot = exports.CENTRAL_IDP_APEX = exports.registrableApex = exports.getAccountColor = exports.formatPublicKeyHandle = exports.getAccountFallbackHandle = exports.getAccountDisplayName = exports.createQuickAccount = exports.buildAccountsArray = exports.updateAvatarVisibility = exports.
|
|
24
|
-
exports.packageInfo = exports.runSessionColdBoot = exports.TOKEN_REFRESH_LEAD_MS = exports.startTokenRefreshScheduler = exports.installAuthRefreshHandler = exports.createAuthRefreshHandler = exports.refreshDeviceSecretArm = exports.refreshPersistedSession = exports.AUTH_STATE_STORAGE_KEY = exports.createMemoryAuthStateStore = exports.createNativeAuthStateStore = exports.createWebAuthStateStore = exports.createAccountDialogController = exports.AccountDialogController = exports.switchableAccountIds = exports.projectSwitchableAccounts = exports.accountIdsOf = exports.activeUserOf = exports.activeSessionIdOf = exports.deviceStateToClientSessions = exports.createSessionClient = exports.createSessionClientHost = exports.SessionClient = exports.redeemHubTicketOnHub = exports.syncHubAfterSignIn = exports.parseHubSyncReturnUrl = exports.normalizeOfficialReturnOrigin = exports.isAllowedDeviceJoinOrigin = exports.isOfficialWebOrigin = exports.isIdpHubOrigin = exports.buildHubSyncUrl =
|
|
22
|
+
exports.isValidUsername = exports.isValidEmail = exports.PASSWORD_REGEX = exports.USERNAME_REGEX = exports.EMAIL_REGEX = exports.retryAsync = exports.validateRequiredFields = exports.handleHttpError = exports.createApiError = exports.ErrorCodes = exports.safeJsonParse = exports.buildPaginationParams = exports.buildUrl = exports.buildSearchParams = exports.translate = exports.withRetry = exports.delay = exports.shouldAllowRequest = exports.recordSuccess = exports.recordFailure = exports.calculateBackoffInterval = exports.createCircuitBreakerState = exports.DEFAULT_CIRCUIT_BREAKER_CONFIG = exports.isRetryableError = exports.isNetworkError = exports.isServerError = exports.isRateLimitError = exports.isNotFoundError = exports.isForbiddenError = exports.isUnauthorizedError = exports.isAlreadyRegisteredError = exports.getErrorMessage = exports.getErrorStatus = exports.HttpStatus = exports.getSystemColorScheme = exports.systemPrefersDarkMode = exports.getOppositeTheme = exports.normalizeColorScheme = exports.normalizeTheme = exports.getContrastTextColor = exports.isLightColor = exports.withOpacity = exports.rgbToHex = exports.hexToRgb = exports.lightenColor = exports.darkenColor = exports.isWebBrowser = exports.isAndroid = exports.isIOS = exports.isNative = void 0;
|
|
23
|
+
exports.buildIdpHubOrigin = exports.clearOAuthHandshake = exports.readOAuthHandshake = exports.persistOAuthHandshake = exports.normalizeOAuthRedirectUri = exports.OXY_CROSS_ORIGIN_RESTORE_ATTEMPTED_KEY = exports.OXY_SILENT_OAUTH_ATTEMPTED_KEY = exports.OXY_OAUTH_CODE_VERIFIER_STORAGE_KEY = exports.OXY_OAUTH_STATE_STORAGE_KEY = exports.OXY_AUTHORIZE_URL = exports.DEFAULT_OAUTH_SCOPE = exports.generatePkcePair = exports.generateOAuthState = exports.computeCodeChallenge = exports.buildOAuthAuthorizeUrl = exports.runColdBoot = exports.CENTRAL_IDP_APEX = exports.registrableApex = exports.getAccountColor = exports.formatPublicKeyHandle = exports.getAccountFallbackHandle = exports.getAccountDisplayName = exports.createQuickAccount = exports.buildAccountsArray = exports.updateAvatarVisibility = exports.isDev = exports.consoleSink = exports.resetLoggerConfig = exports.getLoggerConfig = exports.configureLogger = exports.createLogger = exports.logger = exports.normalizeMultilineText = exports.normalizeInlineText = exports.validateAndSanitizeUserInput = exports.isValidObjectId = exports.sanitizeHTML = exports.sanitizeString = exports.isValidFileType = exports.isValidFileSize = exports.isValidDate = exports.isValidURL = exports.isValidUUID = exports.isValidObject = exports.isValidArray = exports.isRequiredBoolean = exports.isRequiredNumber = exports.isRequiredString = exports.isValidDisplayName = exports.isValidPassword = void 0;
|
|
24
|
+
exports.packageInfo = exports.runSessionColdBoot = exports.TOKEN_REFRESH_LEAD_MS = exports.startTokenRefreshScheduler = exports.installAuthRefreshHandler = exports.createAuthRefreshHandler = exports.refreshDeviceSecretArm = exports.refreshPersistedSession = exports.AUTH_STATE_STORAGE_KEY = exports.createMemoryAuthStateStore = exports.createNativeAuthStateStore = exports.createWebAuthStateStore = exports.createAccountDialogController = exports.AccountDialogController = exports.switchableAccountIds = exports.projectSwitchableAccounts = exports.accountIdsOf = exports.activeUserOf = exports.activeSessionIdOf = exports.deviceStateToClientSessions = exports.createSessionClient = exports.createSessionClientHost = exports.SessionClient = exports.redeemHubTicketOnHub = exports.syncHubAfterSignIn = exports.parseHubSyncReturnUrl = exports.normalizeOfficialReturnOrigin = exports.isAllowedDeviceJoinOrigin = exports.isOfficialWebOrigin = exports.isIdpHubOrigin = exports.buildHubSyncUrl = void 0;
|
|
25
25
|
// Ensure crypto polyfills are loaded before anything else
|
|
26
26
|
require("./crypto/polyfill");
|
|
27
27
|
// ---------------------------------------------------------------------------
|
|
@@ -181,12 +181,6 @@ Object.defineProperty(exports, "recordSuccess", { enumerable: true, get: functio
|
|
|
181
181
|
Object.defineProperty(exports, "shouldAllowRequest", { enumerable: true, get: function () { return networkUtils_1.shouldAllowRequest; } });
|
|
182
182
|
Object.defineProperty(exports, "delay", { enumerable: true, get: function () { return networkUtils_1.delay; } });
|
|
183
183
|
Object.defineProperty(exports, "withRetry", { enumerable: true, get: function () { return networkUtils_1.withRetry; } });
|
|
184
|
-
var debugUtils_1 = require("./shared/utils/debugUtils");
|
|
185
|
-
Object.defineProperty(exports, "isDev", { enumerable: true, get: function () { return debugUtils_1.isDev; } });
|
|
186
|
-
Object.defineProperty(exports, "debugLog", { enumerable: true, get: function () { return debugUtils_1.debugLog; } });
|
|
187
|
-
Object.defineProperty(exports, "debugWarn", { enumerable: true, get: function () { return debugUtils_1.debugWarn; } });
|
|
188
|
-
Object.defineProperty(exports, "debugError", { enumerable: true, get: function () { return debugUtils_1.debugError; } });
|
|
189
|
-
Object.defineProperty(exports, "createDebugLogger", { enumerable: true, get: function () { return debugUtils_1.createDebugLogger; } });
|
|
190
184
|
// ---------------------------------------------------------------------------
|
|
191
185
|
// i18n
|
|
192
186
|
// ---------------------------------------------------------------------------
|
|
@@ -239,18 +233,16 @@ var textNormalization_1 = require("./utils/textNormalization");
|
|
|
239
233
|
Object.defineProperty(exports, "normalizeInlineText", { enumerable: true, get: function () { return textNormalization_1.normalizeInlineText; } });
|
|
240
234
|
Object.defineProperty(exports, "normalizeMultilineText", { enumerable: true, get: function () { return textNormalization_1.normalizeMultilineText; } });
|
|
241
235
|
// ---------------------------------------------------------------------------
|
|
242
|
-
// Logging
|
|
243
|
-
// ---------------------------------------------------------------------------
|
|
244
|
-
var
|
|
245
|
-
Object.defineProperty(exports, "logger", { enumerable: true, get: function () { return
|
|
246
|
-
Object.defineProperty(exports, "
|
|
247
|
-
Object.defineProperty(exports, "
|
|
248
|
-
Object.defineProperty(exports, "
|
|
249
|
-
Object.defineProperty(exports, "
|
|
250
|
-
Object.defineProperty(exports, "
|
|
251
|
-
Object.defineProperty(exports, "
|
|
252
|
-
Object.defineProperty(exports, "logPayment", { enumerable: true, get: function () { return loggerUtils_1.logPayment; } });
|
|
253
|
-
Object.defineProperty(exports, "logPerformance", { enumerable: true, get: function () { return loggerUtils_1.logPerformance; } });
|
|
236
|
+
// Logging — the ecosystem-wide chokepoint (also at subpath `@oxyhq/core/logger`)
|
|
237
|
+
// ---------------------------------------------------------------------------
|
|
238
|
+
var logger_1 = require("./logger");
|
|
239
|
+
Object.defineProperty(exports, "logger", { enumerable: true, get: function () { return logger_1.logger; } });
|
|
240
|
+
Object.defineProperty(exports, "createLogger", { enumerable: true, get: function () { return logger_1.createLogger; } });
|
|
241
|
+
Object.defineProperty(exports, "configureLogger", { enumerable: true, get: function () { return logger_1.configureLogger; } });
|
|
242
|
+
Object.defineProperty(exports, "getLoggerConfig", { enumerable: true, get: function () { return logger_1.getLoggerConfig; } });
|
|
243
|
+
Object.defineProperty(exports, "resetLoggerConfig", { enumerable: true, get: function () { return logger_1.resetLoggerConfig; } });
|
|
244
|
+
Object.defineProperty(exports, "consoleSink", { enumerable: true, get: function () { return logger_1.consoleSink; } });
|
|
245
|
+
Object.defineProperty(exports, "isDev", { enumerable: true, get: function () { return logger_1.isDev; } });
|
|
254
246
|
// ---------------------------------------------------------------------------
|
|
255
247
|
// Avatars
|
|
256
248
|
// ---------------------------------------------------------------------------
|