@oxyhq/core 12.8.0 → 12.10.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 +16 -3
- package/dist/cjs/crypto/identityMarker.js +255 -0
- package/dist/cjs/crypto/keyManager.js +933 -106
- package/dist/cjs/index.js +11 -4
- package/dist/cjs/mixins/OxyServices.auth.js +25 -7
- package/dist/cjs/mixins/OxyServices.deviceBoot.js +9 -1
- package/dist/cjs/mixins/OxyServices.identityBackup.js +11 -0
- package/dist/cjs/mixins/OxyServices.user.js +4 -0
- package/dist/cjs/utils/commonsApproval.js +31 -0
- package/dist/esm/.tsbuildinfo +1 -1
- package/dist/esm/boot/sessionColdBoot.js +16 -3
- package/dist/esm/crypto/identityMarker.js +248 -0
- package/dist/esm/crypto/keyManager.js +932 -106
- package/dist/esm/index.js +4 -2
- package/dist/esm/mixins/OxyServices.auth.js +22 -6
- package/dist/esm/mixins/OxyServices.deviceBoot.js +9 -1
- package/dist/esm/mixins/OxyServices.identityBackup.js +11 -0
- package/dist/esm/mixins/OxyServices.user.js +4 -0
- package/dist/esm/utils/commonsApproval.js +27 -0
- package/dist/types/.tsbuildinfo +1 -1
- package/dist/types/boot/sessionColdBoot.d.ts +25 -0
- package/dist/types/crypto/identityMarker.d.ts +94 -0
- package/dist/types/crypto/keyManager.d.ts +245 -3
- package/dist/types/index.d.ts +6 -3
- package/dist/types/mixins/OxyServices.auth.d.ts +31 -6
- package/dist/types/mixins/OxyServices.deviceBoot.d.ts +8 -0
- package/dist/types/utils/commonsApproval.d.ts +13 -0
- package/package.json +1 -1
- package/src/boot/__tests__/sessionColdBoot.test.ts +113 -0
- package/src/boot/sessionColdBoot.ts +42 -3
- package/src/crypto/__tests__/identityMocks.ts +125 -0
- package/src/crypto/__tests__/keyManager.atomicity.test.ts +79 -94
- package/src/crypto/__tests__/keyManager.cacheSafety.test.ts +175 -0
- package/src/crypto/__tests__/keyManager.identityStatus.test.ts +217 -0
- package/src/crypto/__tests__/keyManager.recoveryLadder.test.ts +179 -0
- package/src/crypto/__tests__/keyManager.recoveryMnemonic.test.ts +138 -0
- package/src/crypto/__tests__/keyManager.storageMigration.test.ts +227 -0
- package/src/crypto/__tests__/keyManager.test.ts +77 -87
- package/src/crypto/identityMarker.ts +291 -0
- package/src/crypto/keyManager.ts +1125 -105
- package/src/index.ts +14 -2
- package/src/mixins/OxyServices.auth.ts +40 -12
- package/src/mixins/OxyServices.deviceBoot.ts +9 -1
- package/src/mixins/OxyServices.identityBackup.ts +13 -0
- package/src/mixins/OxyServices.user.ts +4 -0
- package/src/mixins/__tests__/OxyServices.deviceBoot.test.ts +4 -2
- package/src/mixins/__tests__/commonsSignIn.test.ts +84 -1
- package/src/mixins/__tests__/identityBackup.test.ts +57 -0
- package/src/mixins/__tests__/privacyCacheInvalidation.test.ts +6 -0
- package/src/utils/__tests__/commonsApproval.test.ts +60 -0
- package/src/utils/commonsApproval.ts +39 -0
package/dist/cjs/index.js
CHANGED
|
@@ -18,10 +18,10 @@
|
|
|
18
18
|
* If a symbol does not appear here, it is NOT part of the public API.
|
|
19
19
|
*/
|
|
20
20
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21
|
-
exports.
|
|
22
|
-
exports.
|
|
23
|
-
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.isLoopbackOrigin = exports.isIdpHubOrigin = exports.buildHubSyncUrl = 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 = void 0;
|
|
21
|
+
exports.FALLBACK_LOCALE = exports.SUPPORTED_LANGUAGES = exports.TopicSource = exports.TopicType = exports.SECURITY_EVENT_SEVERITY_MAP = exports.DeviceManager = exports.deriveSharedSecret = exports.AEAD_NONCE_LENGTH = exports.AEAD_KEY_LENGTH = exports.decryptAead = exports.encryptAead = exports.hkdfSha256 = exports.RecoveryPhraseService = exports.SignatureService = exports.updateIdentityMarker = exports.readIdentityMarker = exports.IdentityUnavailableError = 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.parseCommonsApprovalExpiresAt = exports.getCommonsApprovalBlockingReason = exports.ServiceCredentialMismatchError = exports.oxyClient = exports.OXY_CLOUD_URL = exports.OxyAuthenticationTimeoutError = exports.OxyAuthenticationError = exports.AssetUrlResolutionError = exports.OxyServices = void 0;
|
|
22
|
+
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 = exports.isWeb = exports.setPlatformOS = exports.getPlatformOS = exports.getPrimaryLanguage = exports.getUserLanguages = exports.isRTLLocale = exports.getNativeLanguageName = exports.getLanguageName = exports.getLanguageMetadata = exports.isSupportedLocale = exports.normalizeLocale = exports.getBaseLanguage = void 0;
|
|
23
|
+
exports.isOxyRpOrigin = 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.DISPLAY_NAME_ORPHANED_MARK_SOURCE = exports.DISPLAY_NAME_DISALLOWED_SOURCE = exports.DISPLAY_NAME_ALLOWED_SCRIPTS = exports.isValidDisplayName = exports.isValidPassword = 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 = 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.isLoopbackOrigin = exports.isIdpHubOrigin = exports.buildHubSyncUrl = 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 = void 0;
|
|
25
25
|
// Ensure crypto polyfills are loaded before anything else
|
|
26
26
|
require("./crypto/polyfill");
|
|
27
27
|
// ---------------------------------------------------------------------------
|
|
@@ -40,6 +40,9 @@ Object.defineProperty(exports, "oxyClient", { enumerable: true, get: function ()
|
|
|
40
40
|
// ---------------------------------------------------------------------------
|
|
41
41
|
var OxyServices_auth_1 = require("./mixins/OxyServices.auth");
|
|
42
42
|
Object.defineProperty(exports, "ServiceCredentialMismatchError", { enumerable: true, get: function () { return OxyServices_auth_1.ServiceCredentialMismatchError; } });
|
|
43
|
+
var commonsApproval_1 = require("./utils/commonsApproval");
|
|
44
|
+
Object.defineProperty(exports, "getCommonsApprovalBlockingReason", { enumerable: true, get: function () { return commonsApproval_1.getCommonsApprovalBlockingReason; } });
|
|
45
|
+
Object.defineProperty(exports, "parseCommonsApprovalExpiresAt", { enumerable: true, get: function () { return commonsApproval_1.parseCommonsApprovalExpiresAt; } });
|
|
43
46
|
var OxyServices_appData_1 = require("./mixins/OxyServices.appData");
|
|
44
47
|
Object.defineProperty(exports, "OxyAppDataIdentifierError", { enumerable: true, get: function () { return OxyServices_appData_1.OxyAppDataIdentifierError; } });
|
|
45
48
|
// ---------------------------------------------------------------------------
|
|
@@ -100,6 +103,10 @@ var keyManager_1 = require("./crypto/keyManager");
|
|
|
100
103
|
Object.defineProperty(exports, "KeyManager", { enumerable: true, get: function () { return keyManager_1.KeyManager; } });
|
|
101
104
|
Object.defineProperty(exports, "IdentityAlreadyExistsError", { enumerable: true, get: function () { return keyManager_1.IdentityAlreadyExistsError; } });
|
|
102
105
|
Object.defineProperty(exports, "IdentityPersistError", { enumerable: true, get: function () { return keyManager_1.IdentityPersistError; } });
|
|
106
|
+
Object.defineProperty(exports, "IdentityUnavailableError", { enumerable: true, get: function () { return keyManager_1.IdentityUnavailableError; } });
|
|
107
|
+
var identityMarker_1 = require("./crypto/identityMarker");
|
|
108
|
+
Object.defineProperty(exports, "readIdentityMarker", { enumerable: true, get: function () { return identityMarker_1.readIdentityMarker; } });
|
|
109
|
+
Object.defineProperty(exports, "updateIdentityMarker", { enumerable: true, get: function () { return identityMarker_1.updateIdentityMarker; } });
|
|
103
110
|
var signatureService_1 = require("./crypto/signatureService");
|
|
104
111
|
Object.defineProperty(exports, "SignatureService", { enumerable: true, get: function () { return signatureService_1.SignatureService; } });
|
|
105
112
|
var recoveryPhrase_1 = require("./crypto/recoveryPhrase");
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.ServiceCredentialMismatchError = void 0;
|
|
3
|
+
exports.ServiceCredentialMismatchError = exports.parseCommonsApprovalExpiresAt = exports.getCommonsApprovalBlockingReason = void 0;
|
|
4
4
|
exports.OxyServicesAuthMixin = OxyServicesAuthMixin;
|
|
5
5
|
const contracts_1 = require("@oxyhq/contracts");
|
|
6
|
+
var commonsApproval_1 = require("../utils/commonsApproval");
|
|
7
|
+
Object.defineProperty(exports, "getCommonsApprovalBlockingReason", { enumerable: true, get: function () { return commonsApproval_1.getCommonsApprovalBlockingReason; } });
|
|
8
|
+
Object.defineProperty(exports, "parseCommonsApprovalExpiresAt", { enumerable: true, get: function () { return commonsApproval_1.parseCommonsApprovalExpiresAt; } });
|
|
6
9
|
const OxyServices_errors_1 = require("../OxyServices.errors");
|
|
7
10
|
const keyManager_1 = require("../crypto/keyManager");
|
|
8
11
|
const signatureService_1 = require("../crypto/signatureService");
|
|
@@ -298,12 +301,16 @@ function OxyServicesAuthMixin(Base) {
|
|
|
298
301
|
* The client must sign this challenge with their private key
|
|
299
302
|
*
|
|
300
303
|
* @param publicKey - The user's public key
|
|
304
|
+
* @param requestOptions - Optional per-call transport overrides (`retry`,
|
|
305
|
+
* `timeout`). Interactive callers omit it (defaults keep retries); the
|
|
306
|
+
* cold-boot `shared-key-signin` step passes `{ retry: false }` so a slow
|
|
307
|
+
* network cannot multiply boot latency via the inner retry loop.
|
|
301
308
|
*/
|
|
302
|
-
async requestChallenge(publicKey) {
|
|
309
|
+
async requestChallenge(publicKey, requestOptions) {
|
|
303
310
|
try {
|
|
304
311
|
return await this.makeRequest('POST', '/auth/challenge', {
|
|
305
312
|
publicKey,
|
|
306
|
-
}, { cache: false });
|
|
313
|
+
}, { cache: false, ...requestOptions });
|
|
307
314
|
}
|
|
308
315
|
catch (error) {
|
|
309
316
|
throw this.handleError(error);
|
|
@@ -318,8 +325,12 @@ function OxyServicesAuthMixin(Base) {
|
|
|
318
325
|
* @param timestamp - Timestamp when the signature was created
|
|
319
326
|
* @param deviceName - Optional device name
|
|
320
327
|
* @param deviceFingerprint - Optional device fingerprint
|
|
328
|
+
* @param requestOptions - Optional per-call transport overrides (`retry`,
|
|
329
|
+
* `timeout`). Interactive callers omit it (defaults keep retries); the
|
|
330
|
+
* cold-boot `shared-key-signin` step passes `{ retry: false }` so a slow
|
|
331
|
+
* network cannot multiply boot latency via the inner retry loop.
|
|
321
332
|
*/
|
|
322
|
-
async verifyChallenge(publicKey, challenge, signature, timestamp, deviceName, deviceFingerprint) {
|
|
333
|
+
async verifyChallenge(publicKey, challenge, signature, timestamp, deviceName, deviceFingerprint, requestOptions) {
|
|
323
334
|
try {
|
|
324
335
|
const res = await this.makeRequest('POST', '/auth/verify', {
|
|
325
336
|
publicKey,
|
|
@@ -328,7 +339,7 @@ function OxyServicesAuthMixin(Base) {
|
|
|
328
339
|
timestamp,
|
|
329
340
|
deviceName,
|
|
330
341
|
deviceFingerprint,
|
|
331
|
-
}, { cache: false });
|
|
342
|
+
}, { cache: false, ...requestOptions });
|
|
332
343
|
// Plant the freshly-minted tokens, mirroring `claimSessionByToken`.
|
|
333
344
|
// `/auth/verify` returns the first access token (and refresh token) in
|
|
334
345
|
// its body, so installing it here means callers get an authenticated
|
|
@@ -466,6 +477,13 @@ function OxyServicesAuthMixin(Base) {
|
|
|
466
477
|
*
|
|
467
478
|
* The cold-boot wiring that CALLS this lives in `OxyContext`
|
|
468
479
|
* (`@oxyhq/services`); this method just performs the exchange.
|
|
480
|
+
*
|
|
481
|
+
* @param opts.requestOptions - Optional per-call transport overrides
|
|
482
|
+
* (`retry`, `timeout`) forwarded to BOTH the `requestChallenge` and
|
|
483
|
+
* `verifyChallenge` round-trips. Interactive flows omit it (defaults keep
|
|
484
|
+
* retries); the cold-boot `shared-key-signin` step passes `{ retry: false }`
|
|
485
|
+
* so this network step cannot multiply boot latency via the inner retry
|
|
486
|
+
* loop. The token-refresh scheduler / 401 lane still retry later.
|
|
469
487
|
*/
|
|
470
488
|
async signInWithSharedIdentity(opts = {}) {
|
|
471
489
|
try {
|
|
@@ -479,10 +497,10 @@ function OxyServicesAuthMixin(Base) {
|
|
|
479
497
|
if (!sharedPublicKey) {
|
|
480
498
|
return null;
|
|
481
499
|
}
|
|
482
|
-
const { challenge } = await this.requestChallenge(sharedPublicKey);
|
|
500
|
+
const { challenge } = await this.requestChallenge(sharedPublicKey, opts.requestOptions);
|
|
483
501
|
const signed = await signatureService_1.SignatureService.signChallengeWithSharedKey(challenge);
|
|
484
502
|
// `signed.challenge` carries the SIGNATURE (mirrors `signChallenge`).
|
|
485
|
-
return await this.verifyChallenge(signed.publicKey, challenge, signed.challenge, signed.timestamp, opts.deviceName, opts.deviceFingerprint);
|
|
503
|
+
return await this.verifyChallenge(signed.publicKey, challenge, signed.challenge, signed.timestamp, opts.deviceName, opts.deviceFingerprint, opts.requestOptions);
|
|
486
504
|
}
|
|
487
505
|
catch (error) {
|
|
488
506
|
throw this.handleError(error);
|
|
@@ -32,11 +32,19 @@ function OxyServicesDeviceBootMixin(Base) {
|
|
|
32
32
|
* `no_active_session`) to decide whether to drop the secret and fall back or
|
|
33
33
|
* resolve signed-out.
|
|
34
34
|
*
|
|
35
|
+
* `retry: false`: the mint is a single logical attempt. The proactive
|
|
36
|
+
* token-refresh scheduler and the reactive 401 lane already own backoff and
|
|
37
|
+
* re-arm, so `HttpService`'s inner retry loop here would only multiply the
|
|
38
|
+
* mint's latency on a slow/black-hole network (3 retries × 5s timeout ≈ 20s
|
|
39
|
+
* per lane) with no correctness benefit — it is the dominant term in the cold
|
|
40
|
+
* boot's worst-case time-to-route. A transient failure surfaces once and the
|
|
41
|
+
* scheduler/401 path retries it later.
|
|
42
|
+
*
|
|
35
43
|
* @throws if the response does not match {@link deviceTokenMintResponseSchema}.
|
|
36
44
|
*/
|
|
37
45
|
async mintFromDeviceSecret(deviceId, deviceSecret) {
|
|
38
46
|
try {
|
|
39
|
-
const res = await this.makeRequest('POST', '/session/device/token', { deviceId, deviceSecret }, { cache: false, skipAuth: true });
|
|
47
|
+
const res = await this.makeRequest('POST', '/session/device/token', { deviceId, deviceSecret }, { cache: false, skipAuth: true, retry: false });
|
|
40
48
|
const parsed = (0, contracts_1.safeParseContract)(contracts_1.deviceTokenMintResponseSchema, res);
|
|
41
49
|
if (!parsed) {
|
|
42
50
|
throw new Error('session/device/token returned an unexpected response shape');
|
|
@@ -141,6 +141,17 @@ function OxyServicesIdentityBackupMixin(Base) {
|
|
|
141
141
|
const aad = buildBackupAad(envelope.version, envelope.publicKeyHint);
|
|
142
142
|
const plaintext = (0, aead_1.decryptAead)(backupKey, fromHex(envelope.nonce), fromHex(envelope.ciphertext), aad);
|
|
143
143
|
const payload = JSON.parse(new TextDecoder().decode(plaintext));
|
|
144
|
+
if (!payload.privateKey || !payload.publicKey) {
|
|
145
|
+
throw new Error('Backup payload is missing key material');
|
|
146
|
+
}
|
|
147
|
+
const derivedFromPhrase = await recoveryPhrase_1.RecoveryPhraseService.derivePublicKeyFromPhrase(phrase);
|
|
148
|
+
const derivedFromPrivate = keyManager_1.KeyManager.derivePublicKey(payload.privateKey);
|
|
149
|
+
const phrasePk = derivedFromPhrase.toLowerCase();
|
|
150
|
+
const payloadPk = payload.publicKey.toLowerCase();
|
|
151
|
+
const privatePk = derivedFromPrivate.toLowerCase();
|
|
152
|
+
if (phrasePk !== payloadPk || privatePk !== payloadPk) {
|
|
153
|
+
throw new Error('Backup payload does not match the recovery phrase');
|
|
154
|
+
}
|
|
144
155
|
// Persist the recovered key. Native-only; refuses to clobber a different
|
|
145
156
|
// identity unless overwrite — the IdentityAlreadyExistsError propagates.
|
|
146
157
|
return await keyManager_1.KeyManager.importKeyPair(payload.privateKey, {
|
|
@@ -423,6 +423,10 @@ function OxyServicesUserMixin(Base) {
|
|
|
423
423
|
const result = await this.makeRequest('PATCH', `/privacy/${id}/privacy`, settings, {
|
|
424
424
|
cache: false,
|
|
425
425
|
});
|
|
426
|
+
this.clearCacheByPrefix('GET:/session/user/');
|
|
427
|
+
this.clearCacheByPrefix('GET:/users/me');
|
|
428
|
+
this.clearCacheByPrefix('GET:/profiles/username/');
|
|
429
|
+
this.clearCacheEntry(`GET:/users/${id}`);
|
|
426
430
|
this.clearCacheEntry(`GET:/privacy/${id}/privacy`);
|
|
427
431
|
return result;
|
|
428
432
|
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getCommonsApprovalBlockingReason = getCommonsApprovalBlockingReason;
|
|
4
|
+
exports.parseCommonsApprovalExpiresAt = parseCommonsApprovalExpiresAt;
|
|
5
|
+
/**
|
|
6
|
+
* Returns a user-facing blocking reason when an approval payload must not be
|
|
7
|
+
* shown as actionable, or `null` when the request is still pending and valid.
|
|
8
|
+
*/
|
|
9
|
+
function getCommonsApprovalBlockingReason(info) {
|
|
10
|
+
if (!info.application?.id) {
|
|
11
|
+
return 'The requesting application could not be resolved.';
|
|
12
|
+
}
|
|
13
|
+
if (info.status !== 'pending') {
|
|
14
|
+
return 'This sign-in request is invalid, already used, or expired.';
|
|
15
|
+
}
|
|
16
|
+
const expiresAtMs = parseCommonsApprovalExpiresAt(info.expiresAt);
|
|
17
|
+
if (expiresAtMs !== null && expiresAtMs < Date.now()) {
|
|
18
|
+
return 'This sign-in request has expired. Ask for a new QR code.';
|
|
19
|
+
}
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
/** Normalize API `expiresAt` (number or ISO string) to epoch ms. */
|
|
23
|
+
function parseCommonsApprovalExpiresAt(expiresAt) {
|
|
24
|
+
if (typeof expiresAt === 'number' && Number.isFinite(expiresAt))
|
|
25
|
+
return expiresAt;
|
|
26
|
+
if (typeof expiresAt === 'string') {
|
|
27
|
+
const ms = Date.parse(expiresAt);
|
|
28
|
+
return Number.isFinite(ms) ? ms : null;
|
|
29
|
+
}
|
|
30
|
+
return null;
|
|
31
|
+
}
|