@anuma/sdk 4.2.0 → 4.2.1
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/expo/{chunk-VBO6KSNQ.mjs → chunk-3CDSIN22.mjs} +304 -49
- package/dist/expo/index.cjs +307 -49
- package/dist/expo/index.d.mts +92 -7
- package/dist/expo/index.d.ts +92 -7
- package/dist/expo/index.mjs +7 -1
- package/dist/expo/{recall-OCQOA7M3.mjs → recall-NARBDQAK.mjs} +1 -1
- package/dist/index.cjs +31 -17
- package/dist/index.mjs +31 -17
- package/dist/react/{chunk-BS7C4CUW.mjs → chunk-CUJDSH55.mjs} +304 -49
- package/dist/react/index.cjs +307 -49
- package/dist/react/index.d.mts +86 -7
- package/dist/react/index.d.ts +86 -7
- package/dist/react/index.mjs +7 -1
- package/dist/react/{recall-WXCZHXHZ.mjs → recall-FPPCKYYH.mjs} +1 -1
- package/dist/server/{chunk-WADHFDMA.mjs → chunk-UQDYBQVF.mjs} +304 -49
- package/dist/server/index.cjs +307 -49
- package/dist/server/index.d.mts +85 -6
- package/dist/server/index.d.ts +85 -6
- package/dist/server/index.mjs +7 -1
- package/dist/server/{recall-QTVT7HCZ.mjs → recall-ZHEPQNEU.mjs} +1 -1
- package/package.json +1 -1
|
@@ -13,8 +13,21 @@ import { v7 as uuidv72 } from "uuid";
|
|
|
13
13
|
|
|
14
14
|
// src/react/useEncryption.ts
|
|
15
15
|
var SIGN_MESSAGE = "The app is asking you to sign this message to generate a key, which will be used to encrypt data.";
|
|
16
|
+
var EncryptionKeyMissingError = class extends Error {
|
|
17
|
+
constructor(address, version) {
|
|
18
|
+
super(
|
|
19
|
+
`Encryption key (${version}) not found for ${address}. Please sign a message to generate your encryption key.`
|
|
20
|
+
);
|
|
21
|
+
this.name = "EncryptionKeyMissingError";
|
|
22
|
+
this.address = address;
|
|
23
|
+
this.version = version;
|
|
24
|
+
}
|
|
25
|
+
};
|
|
16
26
|
var encryptionKeyStore = /* @__PURE__ */ new Map();
|
|
17
27
|
var pendingKeyRequests = /* @__PURE__ */ new Map();
|
|
28
|
+
var pendingCandidateDerives = /* @__PURE__ */ new Map();
|
|
29
|
+
var refreshCandidatesByAddress = /* @__PURE__ */ new Map();
|
|
30
|
+
var divergentDeriveAddresses = /* @__PURE__ */ new Set();
|
|
18
31
|
var sessionEpoch = 0;
|
|
19
32
|
var cryptoKeyCache = /* @__PURE__ */ new Map();
|
|
20
33
|
var keyAvailableCallbacks = /* @__PURE__ */ new Map();
|
|
@@ -57,14 +70,11 @@ function notifyKeyAvailable(address) {
|
|
|
57
70
|
}
|
|
58
71
|
}
|
|
59
72
|
var keyPairStore = /* @__PURE__ */ new Map();
|
|
60
|
-
function getStoredKey(address) {
|
|
61
|
-
const keys = encryptionKeyStore.get(address);
|
|
62
|
-
return keys?.current ?? null;
|
|
63
|
-
}
|
|
64
73
|
function getStoredKeyByVersion(address, version) {
|
|
65
74
|
const keys = encryptionKeyStore.get(address);
|
|
66
75
|
if (!keys) return null;
|
|
67
|
-
|
|
76
|
+
const value = version === "v2" ? keys.legacy : keys.current;
|
|
77
|
+
return value ?? null;
|
|
68
78
|
}
|
|
69
79
|
function setStoredKey(address, keys) {
|
|
70
80
|
encryptionKeyStore.set(address, keys);
|
|
@@ -73,6 +83,8 @@ function clearEncryptionKey(address) {
|
|
|
73
83
|
encryptionKeyStore.delete(address);
|
|
74
84
|
cryptoKeyCache.delete(`${address}:v2`);
|
|
75
85
|
cryptoKeyCache.delete(`${address}:v3`);
|
|
86
|
+
refreshCandidatesByAddress.delete(address);
|
|
87
|
+
divergentDeriveAddresses.delete(address);
|
|
76
88
|
}
|
|
77
89
|
function clearAllEncryptionState() {
|
|
78
90
|
sessionEpoch += 1;
|
|
@@ -80,6 +92,9 @@ function clearAllEncryptionState() {
|
|
|
80
92
|
cryptoKeyCache.clear();
|
|
81
93
|
keyAvailableCallbacks.clear();
|
|
82
94
|
pendingKeyRequests.clear();
|
|
95
|
+
pendingCandidateDerives.clear();
|
|
96
|
+
refreshCandidatesByAddress.clear();
|
|
97
|
+
divergentDeriveAddresses.clear();
|
|
83
98
|
clearAllKeyPairs();
|
|
84
99
|
for (const cb of clearAllEncryptionStateCallbacks) {
|
|
85
100
|
try {
|
|
@@ -265,9 +280,7 @@ async function getEncryptionKey(address, version = "v3") {
|
|
|
265
280
|
}
|
|
266
281
|
const keyHex = getStoredKeyByVersion(address, version);
|
|
267
282
|
if (!keyHex) {
|
|
268
|
-
throw new
|
|
269
|
-
"Encryption key not found. Please sign a message to generate your encryption key."
|
|
270
|
-
);
|
|
283
|
+
throw new EncryptionKeyMissingError(address, version);
|
|
271
284
|
}
|
|
272
285
|
const keyBytes = hexToBytes(keyHex);
|
|
273
286
|
const cryptoKey = await crypto.subtle.importKey(
|
|
@@ -331,8 +344,43 @@ async function decryptDataBytesFromBytes(encrypted, address, version = "v3") {
|
|
|
331
344
|
);
|
|
332
345
|
return new Uint8Array(decryptedData);
|
|
333
346
|
}
|
|
334
|
-
function hasEncryptionKey(address) {
|
|
335
|
-
return
|
|
347
|
+
function hasEncryptionKey(address, version) {
|
|
348
|
+
return getStoredKeyByVersion(address, version ?? "v3") !== null;
|
|
349
|
+
}
|
|
350
|
+
function seedEncryptionKeys(address, keys) {
|
|
351
|
+
if (!isValidWalletAddress(address)) {
|
|
352
|
+
throw new Error(
|
|
353
|
+
`Invalid wallet address: ${address}. Address must start with 0x and be 42 characters (0x + 40 hex characters).`
|
|
354
|
+
);
|
|
355
|
+
}
|
|
356
|
+
if (!keys.legacy && !keys.current) {
|
|
357
|
+
throw new Error("seedEncryptionKeys: at least one of legacy or current is required");
|
|
358
|
+
}
|
|
359
|
+
if (keys.legacy !== void 0) {
|
|
360
|
+
assertAes256KeyHex("legacy", keys.legacy);
|
|
361
|
+
}
|
|
362
|
+
if (keys.current !== void 0) {
|
|
363
|
+
assertAes256KeyHex("current", keys.current);
|
|
364
|
+
}
|
|
365
|
+
const existing = encryptionKeyStore.get(address);
|
|
366
|
+
const next = {
|
|
367
|
+
legacy: keys.legacy ?? existing?.legacy,
|
|
368
|
+
current: keys.current ?? existing?.current
|
|
369
|
+
};
|
|
370
|
+
setStoredKey(address, next);
|
|
371
|
+
if (keys.legacy !== void 0) cryptoKeyCache.delete(`${address}:v2`);
|
|
372
|
+
if (keys.current !== void 0) cryptoKeyCache.delete(`${address}:v3`);
|
|
373
|
+
refreshCandidatesByAddress.delete(address);
|
|
374
|
+
divergentDeriveAddresses.delete(address);
|
|
375
|
+
notifyKeyAvailable(address);
|
|
376
|
+
}
|
|
377
|
+
var AES_256_KEY_HEX = /^[0-9a-fA-F]{64}$/;
|
|
378
|
+
function assertAes256KeyHex(field, value) {
|
|
379
|
+
if (!AES_256_KEY_HEX.test(value)) {
|
|
380
|
+
throw new Error(
|
|
381
|
+
`seedEncryptionKeys: ${field} must be 64 hex characters (32-byte AES key), got length ${value.length}`
|
|
382
|
+
);
|
|
383
|
+
}
|
|
336
384
|
}
|
|
337
385
|
async function encryptBytesWithKey(plaintext, key) {
|
|
338
386
|
const plaintextBytes = typeof plaintext === "string" ? SHARED_TEXT_ENCODER.encode(plaintext) : plaintext;
|
|
@@ -381,20 +429,23 @@ async function decryptDataBatch(encryptedValues, address) {
|
|
|
381
429
|
const key = await getEncryptionKey(address);
|
|
382
430
|
return Promise.all(encryptedValues.map((value) => decryptDataWithKey(value, key)));
|
|
383
431
|
}
|
|
384
|
-
async function requestEncryptionKey(walletAddress, signMessage, embeddedWalletSigner) {
|
|
432
|
+
async function requestEncryptionKey(walletAddress, signMessage, embeddedWalletSigner, options) {
|
|
385
433
|
if (!isValidWalletAddress(walletAddress)) {
|
|
386
434
|
throw new Error(
|
|
387
435
|
`Invalid wallet address: ${walletAddress}. Address must start with 0x and be 42 characters (0x + 40 hex characters).`
|
|
388
436
|
);
|
|
389
437
|
}
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
return;
|
|
438
|
+
if (!options?.force && getStoredKeyByVersion(walletAddress, "v3") && getStoredKeyByVersion(walletAddress, "v2")) {
|
|
439
|
+
return true;
|
|
393
440
|
}
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
441
|
+
if (!options?.force && divergentDeriveAddresses.has(walletAddress)) {
|
|
442
|
+
return false;
|
|
443
|
+
}
|
|
444
|
+
if (!options?.force) {
|
|
445
|
+
const pending = pendingKeyRequests.get(walletAddress);
|
|
446
|
+
if (pending) {
|
|
447
|
+
return pending;
|
|
448
|
+
}
|
|
398
449
|
}
|
|
399
450
|
const startEpoch = sessionEpoch;
|
|
400
451
|
const promise = (async () => {
|
|
@@ -422,20 +473,143 @@ async function requestEncryptionKey(walletAddress, signMessage, embeddedWalletSi
|
|
|
422
473
|
deriveKeyFromSignatureV3(signature)
|
|
423
474
|
]);
|
|
424
475
|
if (sessionEpoch !== startEpoch) {
|
|
425
|
-
return;
|
|
476
|
+
return false;
|
|
426
477
|
}
|
|
427
|
-
|
|
478
|
+
const existing = encryptionKeyStore.get(walletAddress);
|
|
479
|
+
if (!options?.force && existing && (existing.legacy || existing.current)) {
|
|
480
|
+
const matchesCurrent = Boolean(existing.current && existing.current === currentKey);
|
|
481
|
+
const matchesLegacy = Boolean(existing.legacy && existing.legacy === legacyKey);
|
|
482
|
+
if (!matchesCurrent && !matchesLegacy) {
|
|
483
|
+
getLogger().warn(
|
|
484
|
+
"requestEncryptionKey: derived keys do not match existing store; leaving unchanged"
|
|
485
|
+
);
|
|
486
|
+
divergentDeriveAddresses.add(walletAddress);
|
|
487
|
+
return false;
|
|
488
|
+
}
|
|
489
|
+
setStoredKey(walletAddress, {
|
|
490
|
+
legacy: existing.legacy ?? legacyKey,
|
|
491
|
+
current: existing.current ?? currentKey
|
|
492
|
+
});
|
|
493
|
+
} else {
|
|
494
|
+
setStoredKey(walletAddress, { legacy: legacyKey, current: currentKey });
|
|
495
|
+
}
|
|
496
|
+
cryptoKeyCache.delete(`${walletAddress}:v2`);
|
|
497
|
+
cryptoKeyCache.delete(`${walletAddress}:v3`);
|
|
498
|
+
refreshCandidatesByAddress.delete(walletAddress);
|
|
499
|
+
divergentDeriveAddresses.delete(walletAddress);
|
|
428
500
|
notifyKeyAvailable(walletAddress);
|
|
501
|
+
return true;
|
|
429
502
|
})();
|
|
430
503
|
pendingKeyRequests.set(walletAddress, promise);
|
|
431
504
|
try {
|
|
432
|
-
await promise;
|
|
505
|
+
return await promise;
|
|
433
506
|
} finally {
|
|
434
507
|
if (pendingKeyRequests.get(walletAddress) === promise) {
|
|
435
508
|
pendingKeyRequests.delete(walletAddress);
|
|
436
509
|
}
|
|
437
510
|
}
|
|
438
511
|
}
|
|
512
|
+
async function refreshEncryptionKeyIfMatches(walletAddress, probeCiphertext, signMessage, embeddedWalletSigner) {
|
|
513
|
+
if (!isValidWalletAddress(walletAddress)) {
|
|
514
|
+
throw new Error(
|
|
515
|
+
`Invalid wallet address: ${walletAddress}. Address must start with 0x and be 42 characters (0x + 40 hex characters).`
|
|
516
|
+
);
|
|
517
|
+
}
|
|
518
|
+
const parsed = parsePrefixedCiphertext(probeCiphertext);
|
|
519
|
+
if (!parsed) {
|
|
520
|
+
return false;
|
|
521
|
+
}
|
|
522
|
+
const cached = refreshCandidatesByAddress.get(walletAddress);
|
|
523
|
+
if (cached) {
|
|
524
|
+
return tryCommitCandidatesIfProbeMatches(walletAddress, parsed, cached);
|
|
525
|
+
}
|
|
526
|
+
let derivePromise = pendingCandidateDerives.get(walletAddress);
|
|
527
|
+
if (!derivePromise) {
|
|
528
|
+
derivePromise = (async () => {
|
|
529
|
+
const candidates2 = await deriveRefreshCandidates(signMessage, embeddedWalletSigner);
|
|
530
|
+
if (candidates2) {
|
|
531
|
+
refreshCandidatesByAddress.set(walletAddress, candidates2);
|
|
532
|
+
}
|
|
533
|
+
return candidates2;
|
|
534
|
+
})().finally(() => {
|
|
535
|
+
if (pendingCandidateDerives.get(walletAddress) === derivePromise) {
|
|
536
|
+
pendingCandidateDerives.delete(walletAddress);
|
|
537
|
+
}
|
|
538
|
+
});
|
|
539
|
+
pendingCandidateDerives.set(walletAddress, derivePromise);
|
|
540
|
+
}
|
|
541
|
+
const candidates = await derivePromise;
|
|
542
|
+
if (!candidates) {
|
|
543
|
+
return false;
|
|
544
|
+
}
|
|
545
|
+
return tryCommitCandidatesIfProbeMatches(walletAddress, parsed, candidates);
|
|
546
|
+
}
|
|
547
|
+
function parsePrefixedCiphertext(probeCiphertext) {
|
|
548
|
+
const version = probeCiphertext.startsWith("enc:v3:") ? "v3" : probeCiphertext.startsWith("enc:v2:") ? "v2" : null;
|
|
549
|
+
if (!version) return null;
|
|
550
|
+
const encryptedData = probeCiphertext.slice(
|
|
551
|
+
version === "v3" ? "enc:v3:".length : "enc:v2:".length
|
|
552
|
+
);
|
|
553
|
+
if (encryptedData.length < 56 || !/^[0-9a-f]+$/i.test(encryptedData)) {
|
|
554
|
+
return null;
|
|
555
|
+
}
|
|
556
|
+
return { version, encryptedData };
|
|
557
|
+
}
|
|
558
|
+
async function deriveRefreshCandidates(signMessage, embeddedWalletSigner) {
|
|
559
|
+
const startEpoch = sessionEpoch;
|
|
560
|
+
const signOptions = { showWalletUIs: false };
|
|
561
|
+
let signature;
|
|
562
|
+
try {
|
|
563
|
+
if (embeddedWalletSigner) {
|
|
564
|
+
signature = await embeddedWalletSigner(SIGN_MESSAGE, signOptions);
|
|
565
|
+
} else {
|
|
566
|
+
signature = await signMessage(SIGN_MESSAGE, signOptions);
|
|
567
|
+
}
|
|
568
|
+
} catch (error) {
|
|
569
|
+
if (embeddedWalletSigner && error instanceof Error) {
|
|
570
|
+
getLogger().warn(
|
|
571
|
+
"Embedded wallet signing failed during key refresh, falling back to standard signMessage:",
|
|
572
|
+
error.message
|
|
573
|
+
);
|
|
574
|
+
signature = await signMessage(SIGN_MESSAGE, signOptions);
|
|
575
|
+
} else {
|
|
576
|
+
throw error;
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
const [legacyKey, currentKey] = await Promise.all([
|
|
580
|
+
deriveKeyFromSignature(signature),
|
|
581
|
+
deriveKeyFromSignatureV3(signature)
|
|
582
|
+
]);
|
|
583
|
+
if (sessionEpoch !== startEpoch) {
|
|
584
|
+
return null;
|
|
585
|
+
}
|
|
586
|
+
return { legacy: legacyKey, current: currentKey };
|
|
587
|
+
}
|
|
588
|
+
async function tryCommitCandidatesIfProbeMatches(walletAddress, parsed, candidates) {
|
|
589
|
+
const candidateHex = parsed.version === "v2" ? candidates.legacy : candidates.current;
|
|
590
|
+
const keyBytes = hexToBytes(candidateHex);
|
|
591
|
+
const candidateCryptoKey = await crypto.subtle.importKey(
|
|
592
|
+
"raw",
|
|
593
|
+
keyBytes.buffer,
|
|
594
|
+
{ name: "AES-GCM" },
|
|
595
|
+
false,
|
|
596
|
+
["encrypt", "decrypt"]
|
|
597
|
+
);
|
|
598
|
+
try {
|
|
599
|
+
await decryptDataWithKey(parsed.encryptedData, candidateCryptoKey);
|
|
600
|
+
} catch {
|
|
601
|
+
getLogger().warn(
|
|
602
|
+
"refreshEncryptionKeyIfMatches: candidate keys failed to decrypt probe; leaving store unchanged"
|
|
603
|
+
);
|
|
604
|
+
return false;
|
|
605
|
+
}
|
|
606
|
+
setStoredKey(walletAddress, { legacy: candidates.legacy, current: candidates.current });
|
|
607
|
+
cryptoKeyCache.delete(`${walletAddress}:v2`);
|
|
608
|
+
cryptoKeyCache.delete(`${walletAddress}:v3`);
|
|
609
|
+
divergentDeriveAddresses.delete(walletAddress);
|
|
610
|
+
notifyKeyAvailable(walletAddress);
|
|
611
|
+
return true;
|
|
612
|
+
}
|
|
439
613
|
var KEYPAIR_STORAGE_PREFIX = "ecdh_keypair_";
|
|
440
614
|
async function persistKeyPair(address, startEpoch) {
|
|
441
615
|
if (typeof window === "undefined") {
|
|
@@ -715,20 +889,29 @@ async function encryptField(value, address, signMessage, embeddedWalletSigner, s
|
|
|
715
889
|
const encrypted = await encryptData(value, address);
|
|
716
890
|
return `${ENCRYPTION_PREFIX}${encrypted}`;
|
|
717
891
|
}
|
|
718
|
-
async function
|
|
719
|
-
if (!value) return value;
|
|
892
|
+
async function decryptFieldDetailed(value, address) {
|
|
893
|
+
if (!value) return { status: "plaintext", value };
|
|
720
894
|
const detected = detectEncryptionVersion(value);
|
|
721
|
-
if (!detected) return value;
|
|
895
|
+
if (!detected) return { status: "plaintext", value };
|
|
722
896
|
if (detected.encryptedData.length < 56 || !/^[0-9a-f]+$/i.test(detected.encryptedData)) {
|
|
723
|
-
return value;
|
|
897
|
+
return { status: "invalid_payload", value, version: detected.version };
|
|
724
898
|
}
|
|
725
899
|
try {
|
|
726
|
-
|
|
900
|
+
const plaintext = await decryptData(detected.encryptedData, address, detected.version);
|
|
901
|
+
return { status: "ok", value: plaintext, version: detected.version };
|
|
727
902
|
} catch (error) {
|
|
728
|
-
|
|
729
|
-
|
|
903
|
+
if (error instanceof EncryptionKeyMissingError) {
|
|
904
|
+
getLogger().warn("Failed to decrypt field (key missing for version):", error.message);
|
|
905
|
+
return { status: "key_missing", value, version: detected.version };
|
|
906
|
+
}
|
|
907
|
+
getLogger().warn("Failed to decrypt field (auth mismatch or crypto error):", error);
|
|
908
|
+
return { status: "auth_mismatch", value, version: detected.version };
|
|
730
909
|
}
|
|
731
910
|
}
|
|
911
|
+
async function decryptField(value, address) {
|
|
912
|
+
const result = await decryptFieldDetailed(value, address);
|
|
913
|
+
return result.value;
|
|
914
|
+
}
|
|
732
915
|
async function encryptJsonField(value, address, signMessage, embeddedWalletSigner, skipKeyRequest) {
|
|
733
916
|
if (!value) return void 0;
|
|
734
917
|
const jsonString = JSON.stringify(value);
|
|
@@ -828,20 +1011,40 @@ async function encryptMessageFields(message, address, signMessage, embeddedWalle
|
|
|
828
1011
|
throw error;
|
|
829
1012
|
}
|
|
830
1013
|
}
|
|
831
|
-
async function
|
|
832
|
-
if (value === void 0) return void 0;
|
|
833
|
-
if (value === null) return value;
|
|
1014
|
+
async function decryptMaybeJsonFieldDetailed(value, address) {
|
|
1015
|
+
if (value === void 0) return { value: void 0, status: "plaintext" };
|
|
1016
|
+
if (value === null) return { value, status: "plaintext" };
|
|
834
1017
|
if (typeof value === "string") {
|
|
835
1018
|
if (isEncrypted(value)) {
|
|
836
|
-
|
|
1019
|
+
const detailed = await decryptFieldDetailed(value, address);
|
|
1020
|
+
if (detailed.status !== "ok") {
|
|
1021
|
+
return { value: void 0, status: detailed.status, probe: value };
|
|
1022
|
+
}
|
|
1023
|
+
try {
|
|
1024
|
+
return { value: JSON.parse(detailed.value), status: "ok" };
|
|
1025
|
+
} catch (error) {
|
|
1026
|
+
getLogger().warn("Failed to parse decrypted JSON field:", error);
|
|
1027
|
+
return { value: void 0, status: "invalid_payload", probe: value };
|
|
1028
|
+
}
|
|
837
1029
|
}
|
|
838
1030
|
try {
|
|
839
|
-
return JSON.parse(value);
|
|
1031
|
+
return { value: JSON.parse(value), status: "plaintext" };
|
|
840
1032
|
} catch {
|
|
841
|
-
return void 0;
|
|
1033
|
+
return { value: void 0, status: "plaintext" };
|
|
842
1034
|
}
|
|
843
1035
|
}
|
|
844
|
-
return value;
|
|
1036
|
+
return { value, status: "plaintext" };
|
|
1037
|
+
}
|
|
1038
|
+
function worseDecryptStatus(a, b) {
|
|
1039
|
+
if (b === "ok" || b === "plaintext") return a;
|
|
1040
|
+
if (!a || a === "ok" || a === "plaintext") return b;
|
|
1041
|
+
const rank = (s) => {
|
|
1042
|
+
if (s === "auth_mismatch") return 3;
|
|
1043
|
+
if (s === "key_missing") return 2;
|
|
1044
|
+
if (s === "invalid_payload") return 1;
|
|
1045
|
+
return 0;
|
|
1046
|
+
};
|
|
1047
|
+
return rank(b) >= rank(a) ? b : a;
|
|
845
1048
|
}
|
|
846
1049
|
async function decryptMessageFields(message, address, signMessage, embeddedWalletSigner) {
|
|
847
1050
|
if (!address) {
|
|
@@ -854,33 +1057,82 @@ async function decryptMessageFields(message, address, signMessage, embeddedWalle
|
|
|
854
1057
|
getLogger().warn("Failed to request encryption key for decryption:", error);
|
|
855
1058
|
}
|
|
856
1059
|
}
|
|
857
|
-
|
|
858
|
-
const
|
|
859
|
-
|
|
1060
|
+
let assembled = await assembleDecryptedMessage(message, address);
|
|
1061
|
+
const needsRefresh = assembled.decryptionStatus === "auth_mismatch" || assembled.decryptionStatus === "key_missing";
|
|
1062
|
+
if (needsRefresh && signMessage && assembled.refreshProbe) {
|
|
1063
|
+
try {
|
|
1064
|
+
const refreshed = await refreshEncryptionKeyIfMatches(
|
|
1065
|
+
address,
|
|
1066
|
+
assembled.refreshProbe,
|
|
1067
|
+
signMessage,
|
|
1068
|
+
embeddedWalletSigner
|
|
1069
|
+
);
|
|
1070
|
+
if (refreshed) {
|
|
1071
|
+
assembled = await assembleDecryptedMessage(message, address);
|
|
1072
|
+
}
|
|
1073
|
+
} catch (error) {
|
|
1074
|
+
getLogger().warn("Failed to refresh encryption key after decrypt failure:", error);
|
|
1075
|
+
}
|
|
1076
|
+
}
|
|
1077
|
+
const { refreshProbe: _probe, ...result } = assembled;
|
|
1078
|
+
return result;
|
|
1079
|
+
}
|
|
1080
|
+
async function assembleDecryptedMessage(message, address) {
|
|
1081
|
+
const contentResult = await decryptFieldDetailed(message.content, address);
|
|
1082
|
+
const thinkingResult = message.thinking ? await decryptFieldDetailed(message.thinking, address) : null;
|
|
1083
|
+
const vectorResult = await decryptMaybeJsonFieldDetailed(
|
|
860
1084
|
message.vector,
|
|
861
1085
|
address
|
|
862
1086
|
);
|
|
863
|
-
const
|
|
1087
|
+
const chunksResult = await decryptMaybeJsonFieldDetailed(
|
|
864
1088
|
message.chunks,
|
|
865
1089
|
address
|
|
866
1090
|
);
|
|
867
|
-
const
|
|
1091
|
+
const sourcesResult = await decryptMaybeJsonFieldDetailed(
|
|
868
1092
|
message.sources,
|
|
869
1093
|
address
|
|
870
1094
|
);
|
|
871
|
-
const
|
|
1095
|
+
const thoughtProcessResult = await decryptMaybeJsonFieldDetailed(
|
|
872
1096
|
message.thoughtProcess,
|
|
873
1097
|
address
|
|
874
1098
|
);
|
|
875
|
-
|
|
1099
|
+
let decryptionStatus;
|
|
1100
|
+
let refreshProbe;
|
|
1101
|
+
const consider = (status, probe) => {
|
|
1102
|
+
decryptionStatus = worseDecryptStatus(decryptionStatus, status);
|
|
1103
|
+
if (!refreshProbe && probe && (status === "auth_mismatch" || status === "key_missing")) {
|
|
1104
|
+
refreshProbe = probe;
|
|
1105
|
+
}
|
|
1106
|
+
};
|
|
1107
|
+
consider(contentResult.status, isEncrypted(message.content) ? message.content : void 0);
|
|
1108
|
+
if (thinkingResult && message.thinking && typeof message.thinking === "string") {
|
|
1109
|
+
consider(thinkingResult.status, isEncrypted(message.thinking) ? message.thinking : void 0);
|
|
1110
|
+
}
|
|
1111
|
+
if (vectorResult.probe) consider(vectorResult.status, vectorResult.probe);
|
|
1112
|
+
if (chunksResult.probe) consider(chunksResult.status, chunksResult.probe);
|
|
1113
|
+
if (sourcesResult.probe) consider(sourcesResult.status, sourcesResult.probe);
|
|
1114
|
+
if (thoughtProcessResult.probe) {
|
|
1115
|
+
consider(thoughtProcessResult.status, thoughtProcessResult.probe);
|
|
1116
|
+
}
|
|
1117
|
+
const statusForConsumer = decryptionStatus === "ok" || decryptionStatus === "plaintext" || !decryptionStatus ? void 0 : decryptionStatus;
|
|
1118
|
+
const result = {
|
|
876
1119
|
...message,
|
|
877
|
-
content:
|
|
878
|
-
thinking:
|
|
879
|
-
vector:
|
|
880
|
-
chunks:
|
|
881
|
-
sources:
|
|
882
|
-
thoughtProcess:
|
|
1120
|
+
content: contentResult.value,
|
|
1121
|
+
thinking: thinkingResult ? thinkingResult.value : message.thinking,
|
|
1122
|
+
vector: vectorResult.value,
|
|
1123
|
+
chunks: chunksResult.value,
|
|
1124
|
+
sources: sourcesResult.value,
|
|
1125
|
+
thoughtProcess: thoughtProcessResult.value
|
|
883
1126
|
};
|
|
1127
|
+
if (statusForConsumer) {
|
|
1128
|
+
result.decryptionStatus = statusForConsumer;
|
|
1129
|
+
} else {
|
|
1130
|
+
delete result.decryptionStatus;
|
|
1131
|
+
}
|
|
1132
|
+
if (refreshProbe) {
|
|
1133
|
+
result.refreshProbe = refreshProbe;
|
|
1134
|
+
}
|
|
1135
|
+
return result;
|
|
884
1136
|
}
|
|
885
1137
|
|
|
886
1138
|
// src/lib/db/chat/types.ts
|
|
@@ -6442,7 +6694,7 @@ function createMemoryVaultSearchTool(vaultCtx, embeddingOptions, cache, searchOp
|
|
|
6442
6694
|
legacy.map((r) => ({ id: r.uniqueId, content: r.content, score: r.similarity }))
|
|
6443
6695
|
);
|
|
6444
6696
|
}
|
|
6445
|
-
const { recall: recall2 } = await import("./recall-
|
|
6697
|
+
const { recall: recall2 } = await import("./recall-FPPCKYYH.mjs");
|
|
6446
6698
|
let recallDegraded = [];
|
|
6447
6699
|
const result = await recall2(
|
|
6448
6700
|
query,
|
|
@@ -7382,6 +7634,7 @@ function toChunkMemory(r) {
|
|
|
7382
7634
|
|
|
7383
7635
|
export {
|
|
7384
7636
|
createSseClient,
|
|
7637
|
+
EncryptionKeyMissingError,
|
|
7385
7638
|
onClearAllEncryptionState,
|
|
7386
7639
|
onKeyAvailable,
|
|
7387
7640
|
clearEncryptionKey,
|
|
@@ -7394,11 +7647,13 @@ export {
|
|
|
7394
7647
|
decryptDataBytes,
|
|
7395
7648
|
decryptDataBytesFromBytes,
|
|
7396
7649
|
hasEncryptionKey,
|
|
7650
|
+
seedEncryptionKeys,
|
|
7397
7651
|
encryptDataWithKey,
|
|
7398
7652
|
decryptDataWithKey,
|
|
7399
7653
|
encryptDataBatch,
|
|
7400
7654
|
decryptDataBatch,
|
|
7401
7655
|
requestEncryptionKey,
|
|
7656
|
+
refreshEncryptionKeyIfMatches,
|
|
7402
7657
|
requestKeyPair,
|
|
7403
7658
|
exportPublicKey,
|
|
7404
7659
|
hasKeyPair,
|