@agentunion/fastaun-browser 0.2.14 → 0.2.15
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/client.d.ts +4 -0
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +138 -31
- package/dist/client.js.map +1 -1
- package/dist/e2ee-group.d.ts +13 -0
- package/dist/e2ee-group.d.ts.map +1 -1
- package/dist/e2ee-group.js +200 -17
- package/dist/e2ee-group.js.map +1 -1
- package/dist/e2ee.d.ts +23 -0
- package/dist/e2ee.d.ts.map +1 -1
- package/dist/e2ee.js +270 -33
- package/dist/e2ee.js.map +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/keystore/index.d.ts +10 -0
- package/dist/keystore/index.d.ts.map +1 -1
- package/dist/keystore/indexeddb.d.ts +19 -0
- package/dist/keystore/indexeddb.d.ts.map +1 -1
- package/dist/keystore/indexeddb.js +83 -0
- package/dist/keystore/indexeddb.js.map +1 -1
- package/dist/namespaces/auth.d.ts +19 -0
- package/dist/namespaces/auth.d.ts.map +1 -1
- package/dist/namespaces/auth.js +237 -0
- package/dist/namespaces/auth.js.map +1 -1
- package/dist/namespaces/meta.d.ts +106 -0
- package/dist/namespaces/meta.d.ts.map +1 -0
- package/dist/namespaces/meta.js +498 -0
- package/dist/namespaces/meta.js.map +1 -0
- package/package.json +1 -1
package/dist/client.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ import { type EventHandler, type Subscription } from './events.js';
|
|
|
3
3
|
import { GatewayDiscovery } from './discovery.js';
|
|
4
4
|
import { AuthNamespace } from './namespaces/auth.js';
|
|
5
5
|
import { CustodyNamespace } from './namespaces/custody.js';
|
|
6
|
+
import { MetaNamespace } from './namespaces/meta.js';
|
|
6
7
|
import { E2EEManager } from './e2ee.js';
|
|
7
8
|
import { GroupE2EEManager } from './e2ee-group.js';
|
|
8
9
|
import { type ConnectionState, type MetadataRecord, type RpcParams, type RpcResult } from './types.js';
|
|
@@ -45,6 +46,8 @@ export declare class AUNClient {
|
|
|
45
46
|
readonly auth: AuthNamespace;
|
|
46
47
|
/** AID 托管命名空间 */
|
|
47
48
|
readonly custody: CustodyNamespace;
|
|
49
|
+
/** 元数据命名空间(心跳、状态、信任根管理) */
|
|
50
|
+
readonly meta: MetaNamespace;
|
|
48
51
|
private _certCache;
|
|
49
52
|
private _prekeyReplenishInflight;
|
|
50
53
|
private _prekeyReplenished;
|
|
@@ -186,6 +189,7 @@ export declare class AUNClient {
|
|
|
186
189
|
*/
|
|
187
190
|
private _cleanupDissolvedGroup;
|
|
188
191
|
private _verifyEventSignature;
|
|
192
|
+
private _protectedHeadersFromParams;
|
|
189
193
|
/** 自动加密并发送 P2P 消息 */
|
|
190
194
|
private _sendEncrypted;
|
|
191
195
|
/**
|
package/dist/client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAOA,OAAO,EAAkD,KAAK,SAAS,EAAE,MAAM,aAAa,CAAC;AAC7F,OAAO,EAAsC,KAAK,YAAY,EAAE,KAAK,YAAY,EAAE,MAAM,aAAa,CAAC;AACvG,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAIlD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|
package/dist/client.js
CHANGED
|
@@ -12,6 +12,7 @@ import { AuthFlow } from './auth.js';
|
|
|
12
12
|
import { SeqTracker } from './seq-tracker.js';
|
|
13
13
|
import { AuthNamespace } from './namespaces/auth.js';
|
|
14
14
|
import { CustodyNamespace } from './namespaces/custody.js';
|
|
15
|
+
import { MetaNamespace } from './namespaces/meta.js';
|
|
15
16
|
import { CryptoProvider, uint8ToBase64, base64ToUint8, pemToArrayBuffer, p1363ToDer, toBufferSource } from './crypto.js';
|
|
16
17
|
import { E2EEManager, _certificateSha256Fingerprint as certificateSha256Fingerprint, _ecdsaVerifyDer as ecdsaVerifyDer, _importCertPublicKeyEcdsa as importCertPublicKeyEcdsa, } from './e2ee.js';
|
|
17
18
|
import { GroupE2EEManager, computeMembershipCommitment, storeGroupSecret, buildKeyDistribution, buildKeyRequest, buildMembershipManifest, signMembershipManifest, } from './e2ee-group.js';
|
|
@@ -169,6 +170,7 @@ function isGroupServiceAid(value) {
|
|
|
169
170
|
const [name, ...issuerParts] = text.split('.');
|
|
170
171
|
return name === 'group' && issuerParts.join('.').length > 0;
|
|
171
172
|
}
|
|
173
|
+
const PREKEY_FALLBACK_DEVICE_ID = 'aun_device_id';
|
|
172
174
|
function isPeerPrekeyMaterial(value) {
|
|
173
175
|
if (!isJsonObject(value))
|
|
174
176
|
return false;
|
|
@@ -186,6 +188,52 @@ function isPeerPrekeyResponse(value) {
|
|
|
186
188
|
return false;
|
|
187
189
|
return candidate.prekey === undefined || isPeerPrekeyMaterial(candidate.prekey);
|
|
188
190
|
}
|
|
191
|
+
function normalizePeerPrekeys(prekeys) {
|
|
192
|
+
const normalized = [];
|
|
193
|
+
for (const item of prekeys) {
|
|
194
|
+
if (!isPeerPrekeyMaterial(item))
|
|
195
|
+
continue;
|
|
196
|
+
const prekeyId = item.prekey_id.trim();
|
|
197
|
+
const publicKey = item.public_key.trim();
|
|
198
|
+
const signature = item.signature.trim();
|
|
199
|
+
if (!prekeyId || !publicKey || !signature)
|
|
200
|
+
continue;
|
|
201
|
+
const deviceId = String(item.device_id ?? '').trim();
|
|
202
|
+
const certFingerprint = String(item.cert_fingerprint ?? '').trim().toLowerCase();
|
|
203
|
+
const candidate = {
|
|
204
|
+
...item,
|
|
205
|
+
prekey_id: prekeyId,
|
|
206
|
+
public_key: publicKey,
|
|
207
|
+
signature,
|
|
208
|
+
device_id: deviceId,
|
|
209
|
+
};
|
|
210
|
+
if (certFingerprint) {
|
|
211
|
+
candidate.cert_fingerprint = certFingerprint;
|
|
212
|
+
}
|
|
213
|
+
else {
|
|
214
|
+
delete candidate.cert_fingerprint;
|
|
215
|
+
}
|
|
216
|
+
normalized.push(candidate);
|
|
217
|
+
}
|
|
218
|
+
if (normalized.length === 0)
|
|
219
|
+
return [];
|
|
220
|
+
if (normalized.length === 1) {
|
|
221
|
+
if (!String(normalized[0].device_id ?? '').trim()) {
|
|
222
|
+
normalized[0].device_id = PREKEY_FALLBACK_DEVICE_ID;
|
|
223
|
+
}
|
|
224
|
+
return normalized;
|
|
225
|
+
}
|
|
226
|
+
const seen = new Set();
|
|
227
|
+
const filtered = [];
|
|
228
|
+
for (const item of normalized) {
|
|
229
|
+
const deviceId = String(item.device_id ?? '').trim();
|
|
230
|
+
if (!deviceId || deviceId === PREKEY_FALLBACK_DEVICE_ID || seen.has(deviceId))
|
|
231
|
+
continue;
|
|
232
|
+
seen.add(deviceId);
|
|
233
|
+
filtered.push(item);
|
|
234
|
+
}
|
|
235
|
+
return filtered;
|
|
236
|
+
}
|
|
189
237
|
function formatCaughtError(error) {
|
|
190
238
|
return error instanceof Error ? error : String(error);
|
|
191
239
|
}
|
|
@@ -267,6 +315,8 @@ export class AUNClient {
|
|
|
267
315
|
auth;
|
|
268
316
|
/** AID 托管命名空间 */
|
|
269
317
|
custody;
|
|
318
|
+
/** 元数据命名空间(心跳、状态、信任根管理) */
|
|
319
|
+
meta;
|
|
270
320
|
// E2EE 编排状态(内存缓存)
|
|
271
321
|
_certCache = new Map();
|
|
272
322
|
_prekeyReplenishInflight = new Set();
|
|
@@ -350,6 +400,7 @@ export class AUNClient {
|
|
|
350
400
|
});
|
|
351
401
|
this.auth = new AuthNamespace(this);
|
|
352
402
|
this.custody = new CustodyNamespace(this);
|
|
403
|
+
this.meta = new MetaNamespace(this);
|
|
353
404
|
// 内部订阅:推送消息自动解密后 re-publish 给用户
|
|
354
405
|
this._dispatcher.subscribe('_raw.message.received', (data) => {
|
|
355
406
|
this._onRawMessageReceived(data);
|
|
@@ -533,6 +584,8 @@ export class AUNClient {
|
|
|
533
584
|
if (encrypt) {
|
|
534
585
|
return this._sendEncrypted(p);
|
|
535
586
|
}
|
|
587
|
+
delete p.protected_headers;
|
|
588
|
+
delete p.headers;
|
|
536
589
|
}
|
|
537
590
|
// 自动加密:group.send 默认加密(encrypt 默认 true)
|
|
538
591
|
if (method === 'group.send') {
|
|
@@ -541,6 +594,8 @@ export class AUNClient {
|
|
|
541
594
|
if (encrypt) {
|
|
542
595
|
return this._sendGroupEncrypted(p);
|
|
543
596
|
}
|
|
597
|
+
delete p.protected_headers;
|
|
598
|
+
delete p.headers;
|
|
544
599
|
}
|
|
545
600
|
if (method === 'group.thought.put') {
|
|
546
601
|
const encrypt = p.encrypt !== undefined ? p.encrypt : true;
|
|
@@ -696,13 +751,13 @@ export class AUNClient {
|
|
|
696
751
|
}
|
|
697
752
|
// ── 便利方法 ──────────────────────────────────────
|
|
698
753
|
async ping(params) {
|
|
699
|
-
return this.
|
|
754
|
+
return this.meta.ping(params);
|
|
700
755
|
}
|
|
701
756
|
async status(params) {
|
|
702
|
-
return this.
|
|
757
|
+
return this.meta.status(params);
|
|
703
758
|
}
|
|
704
759
|
async trustRoots(params) {
|
|
705
|
-
return this.
|
|
760
|
+
return this.meta.trustRoots(params);
|
|
706
761
|
}
|
|
707
762
|
// ── 事件 ──────────────────────────────────────────
|
|
708
763
|
/**
|
|
@@ -1542,6 +1597,17 @@ export class AUNClient {
|
|
|
1542
1597
|
}
|
|
1543
1598
|
}
|
|
1544
1599
|
// ── E2EE 自动加密 ────────────────────────────────
|
|
1600
|
+
_protectedHeadersFromParams(params) {
|
|
1601
|
+
const value = params.protected_headers ?? params.headers;
|
|
1602
|
+
if (value == null)
|
|
1603
|
+
return null;
|
|
1604
|
+
if (isJsonObject(value))
|
|
1605
|
+
return value;
|
|
1606
|
+
if (typeof value === 'object' && typeof value.toObject === 'function') {
|
|
1607
|
+
return value;
|
|
1608
|
+
}
|
|
1609
|
+
return null;
|
|
1610
|
+
}
|
|
1545
1611
|
/** 自动加密并发送 P2P 消息 */
|
|
1546
1612
|
async _sendEncrypted(params) {
|
|
1547
1613
|
const toAid = String(params.to ?? '');
|
|
@@ -1553,6 +1619,7 @@ export class AUNClient {
|
|
|
1553
1619
|
throw new ValidationError('message.send payload must be an object when encrypt=true');
|
|
1554
1620
|
}
|
|
1555
1621
|
const persistRequired = Boolean(params.persist_required || params.durable);
|
|
1622
|
+
const protectedHeaders = this._protectedHeadersFromParams(params);
|
|
1556
1623
|
// Lazy P2P sync:首次发送前自动拉取历史,避免重连后 seq 空洞
|
|
1557
1624
|
if (!this._p2pSynced) {
|
|
1558
1625
|
await this._lazySyncP2p();
|
|
@@ -1563,6 +1630,7 @@ export class AUNClient {
|
|
|
1563
1630
|
payload,
|
|
1564
1631
|
messageId,
|
|
1565
1632
|
timestamp,
|
|
1633
|
+
protectedHeaders,
|
|
1566
1634
|
});
|
|
1567
1635
|
if (recipientPrekeys.length <= 1 && selfSyncCopies.length === 0) {
|
|
1568
1636
|
return await this._sendEncryptedSingle({
|
|
@@ -1572,6 +1640,7 @@ export class AUNClient {
|
|
|
1572
1640
|
timestamp,
|
|
1573
1641
|
prekey: recipientPrekeys[0],
|
|
1574
1642
|
persistRequired,
|
|
1643
|
+
protectedHeaders,
|
|
1575
1644
|
});
|
|
1576
1645
|
}
|
|
1577
1646
|
const recipientCopies = await this._buildRecipientDeviceCopies({
|
|
@@ -1580,6 +1649,7 @@ export class AUNClient {
|
|
|
1580
1649
|
messageId,
|
|
1581
1650
|
timestamp,
|
|
1582
1651
|
prekeys: recipientPrekeys,
|
|
1652
|
+
protectedHeaders,
|
|
1583
1653
|
});
|
|
1584
1654
|
const sendParams = {
|
|
1585
1655
|
to: toAid,
|
|
@@ -1640,6 +1710,7 @@ export class AUNClient {
|
|
|
1640
1710
|
prekey,
|
|
1641
1711
|
messageId: opts.messageId,
|
|
1642
1712
|
timestamp: opts.timestamp,
|
|
1713
|
+
protectedHeaders: opts.protectedHeaders,
|
|
1643
1714
|
});
|
|
1644
1715
|
await this._ensureEncryptResult(opts.toAid, encryptResult);
|
|
1645
1716
|
const sendParams = {
|
|
@@ -1658,7 +1729,7 @@ export class AUNClient {
|
|
|
1658
1729
|
async _buildRecipientDeviceCopies(opts) {
|
|
1659
1730
|
const recipientCopies = [];
|
|
1660
1731
|
const certCache = new Map();
|
|
1661
|
-
for (const prekey of opts.prekeys) {
|
|
1732
|
+
for (const prekey of normalizePeerPrekeys(opts.prekeys)) {
|
|
1662
1733
|
const deviceId = String(prekey.device_id ?? '').trim();
|
|
1663
1734
|
const peerCertFingerprint = String(prekey.cert_fingerprint ?? '').trim().toLowerCase();
|
|
1664
1735
|
const cacheKey = peerCertFingerprint || '__default__';
|
|
@@ -1674,6 +1745,7 @@ export class AUNClient {
|
|
|
1674
1745
|
prekey,
|
|
1675
1746
|
messageId: opts.messageId,
|
|
1676
1747
|
timestamp: opts.timestamp,
|
|
1748
|
+
protectedHeaders: opts.protectedHeaders,
|
|
1677
1749
|
});
|
|
1678
1750
|
await this._ensureEncryptResult(opts.toAid, encryptResult);
|
|
1679
1751
|
recipientCopies.push({
|
|
@@ -1715,7 +1787,7 @@ export class AUNClient {
|
|
|
1715
1787
|
const myAid = this._aid;
|
|
1716
1788
|
if (!myAid)
|
|
1717
1789
|
return [];
|
|
1718
|
-
const prekeys = await this._fetchPeerPrekeys(myAid);
|
|
1790
|
+
const prekeys = normalizePeerPrekeys(await this._fetchPeerPrekeys(myAid));
|
|
1719
1791
|
if (prekeys.length === 0)
|
|
1720
1792
|
return [];
|
|
1721
1793
|
const copies = [];
|
|
@@ -1732,6 +1804,7 @@ export class AUNClient {
|
|
|
1732
1804
|
prekey,
|
|
1733
1805
|
messageId: opts.messageId,
|
|
1734
1806
|
timestamp: opts.timestamp,
|
|
1807
|
+
protectedHeaders: opts.protectedHeaders,
|
|
1735
1808
|
});
|
|
1736
1809
|
await this._ensureEncryptResult(myAid, encryptResult);
|
|
1737
1810
|
copies.push({
|
|
@@ -1747,6 +1820,8 @@ export class AUNClient {
|
|
|
1747
1820
|
prekey: opts.prekey ?? null,
|
|
1748
1821
|
messageId: opts.messageId,
|
|
1749
1822
|
timestamp: opts.timestamp,
|
|
1823
|
+
protectedHeaders: opts.protectedHeaders,
|
|
1824
|
+
context: opts.context ?? null,
|
|
1750
1825
|
});
|
|
1751
1826
|
return [envelope, encryptResult];
|
|
1752
1827
|
}
|
|
@@ -1862,7 +1937,7 @@ export class AUNClient {
|
|
|
1862
1937
|
return this._callGroupEncryptedRpc('group.thought.put', params, {
|
|
1863
1938
|
idField: 'thought_id',
|
|
1864
1939
|
idPrefix: 'gt',
|
|
1865
|
-
extraFields: ['
|
|
1940
|
+
extraFields: ['context'],
|
|
1866
1941
|
});
|
|
1867
1942
|
}
|
|
1868
1943
|
async _putMessageThoughtEncrypted(params) {
|
|
@@ -1887,6 +1962,8 @@ export class AUNClient {
|
|
|
1887
1962
|
prekey,
|
|
1888
1963
|
messageId: thoughtId,
|
|
1889
1964
|
timestamp,
|
|
1965
|
+
protectedHeaders: this._protectedHeadersFromParams(params),
|
|
1966
|
+
context: isJsonObject(params.context) ? params.context : null,
|
|
1890
1967
|
});
|
|
1891
1968
|
await this._ensureEncryptResult(toAid, encryptResult);
|
|
1892
1969
|
const sendParams = {
|
|
@@ -1896,8 +1973,9 @@ export class AUNClient {
|
|
|
1896
1973
|
encrypted: true,
|
|
1897
1974
|
thought_id: thoughtId,
|
|
1898
1975
|
timestamp,
|
|
1899
|
-
reply_to: params.reply_to,
|
|
1900
1976
|
};
|
|
1977
|
+
if ('context' in params)
|
|
1978
|
+
sendParams.context = params.context;
|
|
1901
1979
|
await this._signClientOperation('message.thought.put', sendParams);
|
|
1902
1980
|
return this._transport.call('message.thought.put', sendParams);
|
|
1903
1981
|
}
|
|
@@ -1934,12 +2012,26 @@ export class AUNClient {
|
|
|
1934
2012
|
await this._waitForGroupMembershipEpochFloor(groupId, 2000);
|
|
1935
2013
|
const epochResult = await this._committedGroupEpochState(groupId);
|
|
1936
2014
|
const committedEpoch = Number(epochResult.committed_epoch ?? epochResult.epoch ?? 0);
|
|
1937
|
-
const envelope = committedEpoch > 0
|
|
1938
|
-
? await this._groupE2ee.encryptWithEpoch(groupId, await this._ensureCommittedGroupSecretForSend(groupId, committedEpoch, epochResult), payload)
|
|
1939
|
-
: await this._groupE2ee.encrypt(groupId, payload);
|
|
1940
2015
|
const operationId = String(params[options.idField] ?? '').trim()
|
|
1941
2016
|
|| `${options.idPrefix}-${crypto.randomUUID()}`;
|
|
1942
2017
|
const timestamp = Number(params.timestamp ?? Date.now());
|
|
2018
|
+
const protectedHeaders = this._protectedHeadersFromParams(params);
|
|
2019
|
+
const context = method === 'group.thought.put' && isJsonObject(params.context)
|
|
2020
|
+
? params.context
|
|
2021
|
+
: null;
|
|
2022
|
+
const envelope = committedEpoch > 0
|
|
2023
|
+
? await this._groupE2ee.encryptWithEpoch(groupId, await this._ensureCommittedGroupSecretForSend(groupId, committedEpoch, epochResult), payload, {
|
|
2024
|
+
messageId: operationId,
|
|
2025
|
+
timestamp,
|
|
2026
|
+
protectedHeaders,
|
|
2027
|
+
context,
|
|
2028
|
+
})
|
|
2029
|
+
: await this._groupE2ee.encrypt(groupId, payload, {
|
|
2030
|
+
messageId: operationId,
|
|
2031
|
+
timestamp,
|
|
2032
|
+
protectedHeaders,
|
|
2033
|
+
context,
|
|
2034
|
+
});
|
|
1943
2035
|
const sendParams = {
|
|
1944
2036
|
group_id: groupId,
|
|
1945
2037
|
payload: envelope,
|
|
@@ -2502,14 +2594,16 @@ export class AUNClient {
|
|
|
2502
2594
|
this._enqueuePendingDecrypt(groupId, message);
|
|
2503
2595
|
continue;
|
|
2504
2596
|
}
|
|
2505
|
-
|
|
2597
|
+
const thought = {
|
|
2506
2598
|
thought_id: thoughtId,
|
|
2507
2599
|
message_id: thoughtId,
|
|
2508
|
-
reply_to: item.reply_to,
|
|
2509
2600
|
payload: decrypted.payload,
|
|
2510
2601
|
created_at: item.created_at,
|
|
2511
2602
|
e2ee: decrypted.e2ee,
|
|
2512
|
-
}
|
|
2603
|
+
};
|
|
2604
|
+
if ('context' in item)
|
|
2605
|
+
thought.context = item.context;
|
|
2606
|
+
thoughts.push(thought);
|
|
2513
2607
|
}
|
|
2514
2608
|
return { ...result, thoughts };
|
|
2515
2609
|
}
|
|
@@ -2552,16 +2646,18 @@ export class AUNClient {
|
|
|
2552
2646
|
continue;
|
|
2553
2647
|
}
|
|
2554
2648
|
}
|
|
2555
|
-
|
|
2649
|
+
const thought = {
|
|
2556
2650
|
thought_id: thoughtId,
|
|
2557
2651
|
message_id: thoughtId,
|
|
2558
|
-
reply_to: item.reply_to,
|
|
2559
2652
|
from: fromAid,
|
|
2560
2653
|
to: toAid,
|
|
2561
2654
|
payload: decrypted.payload,
|
|
2562
2655
|
created_at: item.created_at,
|
|
2563
2656
|
e2ee: decrypted.e2ee,
|
|
2564
|
-
}
|
|
2657
|
+
};
|
|
2658
|
+
if ('context' in item)
|
|
2659
|
+
thought.context = item.context;
|
|
2660
|
+
thoughts.push(thought);
|
|
2565
2661
|
}
|
|
2566
2662
|
return { ...result, thoughts };
|
|
2567
2663
|
}
|
|
@@ -2781,11 +2877,15 @@ export class AUNClient {
|
|
|
2781
2877
|
async _fetchPeerPrekeys(peerAid) {
|
|
2782
2878
|
const cachedList = this._peerPrekeysCache.get(peerAid);
|
|
2783
2879
|
if (cachedList && Date.now() / 1000 < cachedList.expireAt) {
|
|
2784
|
-
|
|
2880
|
+
const normalized = normalizePeerPrekeys(cachedList.items);
|
|
2881
|
+
if (normalized.length > 0)
|
|
2882
|
+
return normalized.map((item) => ({ ...item }));
|
|
2785
2883
|
}
|
|
2786
2884
|
const cached = this._e2ee.getCachedPrekey(peerAid);
|
|
2787
|
-
if (cached !== null
|
|
2788
|
-
|
|
2885
|
+
if (cached !== null) {
|
|
2886
|
+
const normalized = normalizePeerPrekeys([cached]);
|
|
2887
|
+
if (normalized.length > 0)
|
|
2888
|
+
return normalized.map((item) => ({ ...item }));
|
|
2789
2889
|
}
|
|
2790
2890
|
let result;
|
|
2791
2891
|
try {
|
|
@@ -2802,7 +2902,7 @@ export class AUNClient {
|
|
|
2802
2902
|
}
|
|
2803
2903
|
const devicePrekeys = Array.isArray(result.device_prekeys) ? result.device_prekeys : null;
|
|
2804
2904
|
if (devicePrekeys) {
|
|
2805
|
-
const normalized = devicePrekeys
|
|
2905
|
+
const normalized = normalizePeerPrekeys(devicePrekeys);
|
|
2806
2906
|
if (normalized.length > 0) {
|
|
2807
2907
|
this._peerPrekeysCache.set(peerAid, {
|
|
2808
2908
|
items: normalized.map((item) => ({ ...item })),
|
|
@@ -2816,12 +2916,15 @@ export class AUNClient {
|
|
|
2816
2916
|
throw new ValidationError(`invalid prekey response for ${peerAid}`);
|
|
2817
2917
|
}
|
|
2818
2918
|
if (result.prekey) {
|
|
2819
|
-
|
|
2820
|
-
|
|
2821
|
-
|
|
2822
|
-
|
|
2823
|
-
|
|
2824
|
-
|
|
2919
|
+
const normalized = normalizePeerPrekeys([result.prekey]);
|
|
2920
|
+
if (normalized.length > 0) {
|
|
2921
|
+
this._peerPrekeysCache.set(peerAid, {
|
|
2922
|
+
items: normalized.map((item) => ({ ...item })),
|
|
2923
|
+
expireAt: Date.now() / 1000 + 300,
|
|
2924
|
+
});
|
|
2925
|
+
this._e2ee.cachePrekey(peerAid, normalized[0]);
|
|
2926
|
+
return normalized.map((item) => ({ ...item }));
|
|
2927
|
+
}
|
|
2825
2928
|
}
|
|
2826
2929
|
if (result.found) {
|
|
2827
2930
|
throw new ValidationError(`invalid prekey response for ${peerAid}`);
|
|
@@ -2832,7 +2935,9 @@ export class AUNClient {
|
|
|
2832
2935
|
async _fetchPeerPrekey(peerAid) {
|
|
2833
2936
|
const cachedList = this._peerPrekeysCache.get(peerAid);
|
|
2834
2937
|
if (cachedList && Date.now() / 1000 < cachedList.expireAt && cachedList.items.length > 0) {
|
|
2835
|
-
|
|
2938
|
+
const normalized = normalizePeerPrekeys(cachedList.items);
|
|
2939
|
+
if (normalized.length > 0)
|
|
2940
|
+
return { ...normalized[0] };
|
|
2836
2941
|
}
|
|
2837
2942
|
const prekeys = await this._fetchPeerPrekeys(peerAid);
|
|
2838
2943
|
if (prekeys.length === 0) {
|
|
@@ -4046,10 +4151,12 @@ export class AUNClient {
|
|
|
4046
4151
|
}
|
|
4047
4152
|
if (method === 'group.thought.put' || method === 'group.thought.get'
|
|
4048
4153
|
|| method === 'message.thought.put' || method === 'message.thought.get') {
|
|
4049
|
-
const
|
|
4050
|
-
const
|
|
4051
|
-
|
|
4052
|
-
|
|
4154
|
+
const context = isJsonObject(params.context) ? params.context : null;
|
|
4155
|
+
const contextType = String(context?.type ?? '').trim();
|
|
4156
|
+
const contextId = String(context?.id ?? '').trim();
|
|
4157
|
+
const hasContext = contextType.length > 0 && contextId.length > 0;
|
|
4158
|
+
if (!hasContext) {
|
|
4159
|
+
throw new ValidationError(`${method} requires context.type + context.id`);
|
|
4053
4160
|
}
|
|
4054
4161
|
}
|
|
4055
4162
|
if (method === 'group.thought.get' && !String(params.sender_aid ?? '').trim()) {
|