@agentunion/fastaun 0.4.13 → 0.5.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/CHANGELOG.md +547 -393
- package/_packed_docs/CHANGELOG-validators.md +144 -0
- package/_packed_docs/CHANGELOG.md +547 -393
- package/_packed_docs/INDEX.md +159 -84
- package/_packed_docs/KITE_DOCS_GUIDE.md +48 -31
- package/_packed_docs/agent.md/SCHEMA.md +2 -0
- package/_packed_docs/agent.md/examples/codeagent-claudecode.md +2 -0
- package/_packed_docs/agent.md/examples/human-developer.md +2 -0
- package/_packed_docs/agent.md/examples/openclaw-lobster.md +2 -0
- package/_packed_docs/agent.md/examples/signed-openclaw-lobster.md +2 -0
- package/_packed_docs/agent.md//350/277/234/347/250/213agent.md/347/274/223/345/255/230/344/270/216etag/351/200/217/344/274/240/346/226/271/346/241/210.md +2 -0
- package/_packed_docs/cli/AUN-CLI/350/256/276/350/256/241/346/226/207/346/241/243.md +266 -686
- package/_packed_docs/cli/CLI/346/211/213/345/206/214.md +331 -0
- package/_packed_docs/design/2026-05-22-aun-rpc-trace-enhancement.md +2 -0
- package/_packed_docs/design/AUNClient/346/213/206/345/210/206/351/207/215/346/236/204/346/211/247/350/241/214/346/226/271/346/241/210.md +2 -0
- package/_packed_docs/design/E2EE_V2/347/256/200/345/214/226/344/270/2721DH/345/212/240Per-AID_Wrap/346/226/271/346/241/210.md +2 -0
- package/_packed_docs/design//350/267/250/350/257/255/350/250/200/345/256/271/345/231/250E2E/346/265/213/350/257/225/346/226/271/346/241/210.md +2 -0
- package/_packed_docs/protocol/00-/346/200/273/350/247/210/344/270/216/345/210/206/345/261/202.md +2 -0
- package/_packed_docs/protocol/00A-/350/256/276/350/256/241/345/216/237/345/210/231-/344/270/272Agent/350/200/214/347/224/237.md +2 -0
- package/_packed_docs/protocol/01-/350/272/253/344/273/275/344/270/216/345/207/255/350/257/201/345/215/217/350/256/256-auth.md +2 -0
- package/_packed_docs/protocol/02-/350/257/201/344/271/246/344/270/216/344/277/241/344/273/273/344/275/223/347/263/273.md +2 -0
- package/_packed_docs/protocol/03-Gateway-/350/277/236/346/216/245/346/250/241/345/274/217.md +2 -0
- package/_packed_docs/protocol/04-Peer-/345/255/220/345/215/217/350/256/256.md +2 -0
- package/_packed_docs/protocol/05-Relay-/345/255/220/345/215/217/350/256/256.md +2 -0
- package/_packed_docs/protocol/07-/351/224/231/350/257/257/347/240/201/344/270/216/347/212/266/346/200/201/346/234/272.md +2 -0
- package/_packed_docs/protocol/08-AUN-E2EE-Group.md +296 -900
- package/_packed_docs/protocol/08-AUN-E2EE.md +2 -0
- package/_packed_docs/protocol/09-/345/256/211/345/205/250/350/200/203/350/231/221.md +2 -0
- package/_packed_docs/protocol/10-Group-/345/255/220/345/215/217/350/256/256.md +66 -173
- package/_packed_docs/protocol/11-Storage-/345/255/220/345/215/217/350/256/256.md +55 -0
- package/_packed_docs/protocol/12-Stream-/345/255/220/345/215/217/350/256/256.md +2 -0
- package/_packed_docs/protocol/13-Agent/350/241/214/344/270/272/350/247/204/350/214/203.md +2 -0
- package/_packed_docs/protocol/14-/344/272/244/344/272/222/346/234/272/345/210/266-/345/223/215/345/272/224/346/250/241/345/274/217/344/270/216/350/207/252/344/270/273/346/250/241/345/274/217.md +2 -0
- package/_packed_docs/protocol/15-/347/246/273/347/272/277/346/216/250/351/200/201/351/200/232/347/237/245/345/215/217/350/256/256.md +2 -0
- package/_packed_docs/protocol/16-/347/263/273/347/273/237/347/233/256/345/275/225/344/277/235/346/212/244/346/226/271/346/241/210.md +177 -0
- package/_packed_docs/protocol/README.md +4 -1
- package/_packed_docs/protocol/agent.md/SCHEMA.md +2 -0
- package/_packed_docs/protocol/agent.md/examples/codeagent-claudecode.md +2 -0
- package/_packed_docs/protocol/agent.md/examples/human-developer.md +2 -0
- package/_packed_docs/protocol/agent.md/examples/openclaw-lobster.md +2 -0
- package/_packed_docs/protocol/aun-docs-guide.md +2 -0
- package/_packed_docs/protocol/index.md +10 -3
- package/_packed_docs/protocol//350/215/211/346/241/210-agent.md/347/255/276/345/220/215/345/215/217/350/256/256.md +2 -0
- package/_packed_docs/protocol//350/215/211/346/241/210-/346/213/222/347/273/235/344/277/241/345/217/267/345/215/217/350/256/256.md +2 -0
- package/_packed_docs/protocol//351/231/204/345/275/225A-/346/234/257/350/257/255/350/241/250.md +2 -0
- package/_packed_docs/protocol//351/231/204/345/275/225B-/346/211/251/345/261/225/346/200/247/346/214/207/345/215/227.md +2 -0
- package/_packed_docs/protocol//351/231/204/345/275/225C-/347/247/201/351/222/245/347/256/241/347/220/206/344/270/216/350/272/253/344/273/275/346/201/242/345/244/215.md +2 -0
- package/_packed_docs/protocol//351/231/204/345/275/225D-Root_CA_/346/262/273/347/220/206/346/234/272/345/210/266.md +2 -0
- package/_packed_docs/protocol//351/231/204/345/275/225E-Root_CA_/345/207/206/345/205/245/346/265/201/347/250/213.md +2 -0
- package/_packed_docs/protocol//351/231/204/345/275/225F-Issuer_CA_/347/224/263/350/257/267/346/265/201/347/250/213.md +2 -0
- package/_packed_docs/protocol//351/231/204/345/275/225G-AID_/345/255/244/345/204/277/351/242/204/351/230/262/344/270/216/346/225/221/346/217/264/346/234/272/345/210/266.md +2 -0
- package/_packed_docs/protocol//351/231/204/345/275/225H-Identity/346/234/215/345/212/241/345/256/236/347/216/260/346/214/207/345/215/227.md +2 -0
- package/_packed_docs/protocol//351/231/204/345/275/225I-/350/267/250/345/237/237/346/266/210/346/201/257/350/267/257/347/224/261/345/256/236/347/216/260/346/214/207/345/215/227.md +2 -0
- package/_packed_docs/protocol//351/231/204/345/275/225J-/345/256/242/346/210/267/347/253/257/346/216/245/345/205/245/347/244/272/344/276/213.md +2 -0
- package/_packed_docs/protocol//351/231/204/345/275/225K-Agent_Web/345/217/221/347/216/260/345/215/217/350/256/256.md +2 -0
- package/_packed_docs/protocol//351/231/204/345/275/225L-E2EE/345/256/236/347/216/260/346/214/207/345/215/227.md +2 -0
- package/_packed_docs/protocol//351/231/204/345/275/225M-JWT/350/256/244/350/257/201/345/256/236/347/216/260/346/214/207/345/215/227.md +2 -0
- package/_packed_docs/protocol//351/231/204/345/275/225N-/345/210/206/345/270/203/345/274/217Trace/345/215/217/350/256/256.md +2 -0
- package/_packed_docs/sdk/01-/345/277/253/351/200/237/345/274/200/345/247/213.md +2 -0
- package/_packed_docs/sdk/02-WebSocket/345/215/217/350/256/256.md +2 -0
- package/_packed_docs/sdk/03-/346/240/270/345/277/203/346/246/202/345/277/265.md +2 -0
- package/_packed_docs/sdk/04-/350/277/236/346/216/245/344/270/216/350/256/244/350/257/201.md +2 -0
- package/_packed_docs/sdk/05-E2EE/345/212/240/345/257/206/351/200/232/344/277/241.md +6 -252
- package/_packed_docs/sdk/06-API/346/211/213/345/206/214.md +219 -177
- package/_packed_docs/sdk/07-/351/224/231/350/257/257/345/244/204/347/220/206.md +4 -1
- package/_packed_docs/sdk/08-/346/234/200/344/275/263/345/256/236/350/267/265.md +2 -0
- package/_packed_docs/sdk/09-collab-rpc-manual.md +581 -0
- package/_packed_docs/sdk/09-custody-api-manual.md +2 -0
- package/_packed_docs/sdk/09-group-rpc-manual.md +301 -634
- package/_packed_docs/sdk/09-message-rpc-manual.md +2 -0
- package/_packed_docs/sdk/09-meta-rpc-manual.md +2 -0
- package/_packed_docs/sdk/09-payload-reference.md +2 -0
- package/_packed_docs/sdk/09-proxy-rpc-manual.md +2 -0
- package/_packed_docs/sdk/09-storage-rpc-manual.md +984 -274
- package/_packed_docs/sdk/09-stream-rpc-manual.md +2 -0
- package/_packed_docs/sdk/AUN_DOCS_GUIDE.md +36 -23
- package/_packed_docs/sdk/E2EE_V2/346/266/210/346/201/257/351/200/232/344/277/241/346/227/266/345/272/217/345/233/276.md +2 -0
- package/_packed_docs/sdk/INDEX.md +47 -30
- package/_packed_docs/sdk/Notify/351/200/232/347/237/245/346/226/271/346/241/210.md +2 -0
- package/_packed_docs/sdk/README.md +17 -15
- package/dist/aid-store.d.ts +25 -0
- package/dist/aid-store.js +80 -0
- package/dist/aid-store.js.map +1 -1
- package/dist/client/delivery.d.ts +11 -0
- package/dist/client/delivery.js +208 -25
- package/dist/client/delivery.js.map +1 -1
- package/dist/client/group-state.js +33 -11
- package/dist/client/group-state.js.map +1 -1
- package/dist/client/rpc-pipeline.d.ts +1 -0
- package/dist/client/rpc-pipeline.js +177 -65
- package/dist/client/rpc-pipeline.js.map +1 -1
- package/dist/client/v2-e2ee.d.ts +6 -1
- package/dist/client/v2-e2ee.js +199 -130
- package/dist/client/v2-e2ee.js.map +1 -1
- package/dist/client.d.ts +37 -1
- package/dist/client.js +491 -44
- package/dist/client.js.map +1 -1
- package/dist/collab/client.d.ts +46 -0
- package/dist/collab/client.js +136 -0
- package/dist/collab/client.js.map +1 -0
- package/dist/collab/errors.d.ts +15 -0
- package/dist/collab/errors.js +60 -0
- package/dist/collab/errors.js.map +1 -0
- package/dist/collab/index.d.ts +3 -0
- package/dist/collab/index.js +4 -0
- package/dist/collab/index.js.map +1 -0
- package/dist/collab/types.d.ts +110 -0
- package/dist/collab/types.js +2 -0
- package/dist/collab/types.js.map +1 -0
- package/dist/crypto.d.ts +2 -0
- package/dist/crypto.js +6 -0
- package/dist/crypto.js.map +1 -1
- package/dist/errors.d.ts +0 -12
- package/dist/errors.js +9 -25
- package/dist/errors.js.map +1 -1
- package/dist/facades.d.ts +94 -0
- package/dist/facades.js +255 -0
- package/dist/facades.js.map +1 -0
- package/dist/group-fs.d.ts +122 -0
- package/dist/group-fs.js +467 -0
- package/dist/group-fs.js.map +1 -0
- package/dist/group-id.d.ts +9 -12
- package/dist/group-id.js +41 -63
- package/dist/group-id.js.map +1 -1
- package/dist/group-resources.d.ts +31 -0
- package/dist/group-resources.js +84 -0
- package/dist/group-resources.js.map +1 -0
- package/dist/index.d.ts +9 -3
- package/dist/index.js +11 -1
- package/dist/index.js.map +1 -1
- package/dist/keystore/aid-db.d.ts +1 -0
- package/dist/keystore/aid-db.js +43 -43
- package/dist/keystore/aid-db.js.map +1 -1
- package/dist/keystore/local-identity-store.d.ts +16 -0
- package/dist/keystore/local-identity-store.js +190 -18
- package/dist/keystore/local-identity-store.js.map +1 -1
- package/dist/keystore/local-token-store.d.ts +0 -13
- package/dist/keystore/local-token-store.js +0 -105
- package/dist/keystore/local-token-store.js.map +1 -1
- package/dist/logger.d.ts +2 -0
- package/dist/logger.js +4 -0
- package/dist/logger.js.map +1 -1
- package/dist/register-flow.d.ts +1 -0
- package/dist/register-flow.js +3 -0
- package/dist/register-flow.js.map +1 -1
- package/dist/service-proxy.d.ts +1 -0
- package/dist/service-proxy.js +17 -4
- package/dist/service-proxy.js.map +1 -1
- package/dist/storage/errors.d.ts +27 -0
- package/dist/storage/errors.js +65 -0
- package/dist/storage/errors.js.map +1 -0
- package/dist/storage/index.d.ts +1 -0
- package/dist/storage/index.js +2 -0
- package/dist/storage/index.js.map +1 -0
- package/dist/storage/lowlevel.d.ts +321 -0
- package/dist/storage/lowlevel.js +475 -0
- package/dist/storage/lowlevel.js.map +1 -0
- package/dist/storage/types.d.ts +57 -0
- package/dist/storage/types.js +116 -0
- package/dist/storage/types.js.map +1 -0
- package/dist/storage/vfs.d.ts +166 -0
- package/dist/storage/vfs.js +524 -0
- package/dist/storage/vfs.js.map +1 -0
- package/dist/tools/cross-sdk-agent.js +708 -1
- package/dist/tools/cross-sdk-agent.js.map +1 -1
- package/dist/transport.d.ts +5 -0
- package/dist/transport.js +124 -21
- package/dist/transport.js.map +1 -1
- package/dist/types.d.ts +38 -0
- package/dist/v2/session/session.d.ts +2 -0
- package/dist/v2/session/session.js +53 -23
- package/dist/v2/session/session.js.map +1 -1
- package/dist/v2/state/commitment.d.ts +1 -1
- package/dist/v2/state/commitment.js +4 -2
- package/dist/v2/state/commitment.js.map +1 -1
- package/dist/validators.d.ts +32 -0
- package/dist/validators.js +128 -0
- package/dist/validators.js.map +1 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/version.js.map +1 -1
- package/package.json +1 -1
package/dist/client/v2-e2ee.js
CHANGED
|
@@ -6,6 +6,7 @@ import { V2Session } from '../v2/session/index.js';
|
|
|
6
6
|
import { isJsonObject } from '../types.js';
|
|
7
7
|
const V2_BOOTSTRAP_TTL_MS = 60 * 60 * 1000;
|
|
8
8
|
const V2_RETRYABLE_CODES = new Set([-33011, -33012, -33050, -33052, -33054]);
|
|
9
|
+
const V2_GROUP_STALE_BOOTSTRAP_CODE = -33054;
|
|
9
10
|
const MEMBERSHIP_ACTIONS = new Set([
|
|
10
11
|
'member_added',
|
|
11
12
|
'member_left',
|
|
@@ -134,6 +135,7 @@ function applyV2WrapPolicyToTargets(targets, policy) {
|
|
|
134
135
|
export class V2E2EECoordinator {
|
|
135
136
|
runtime;
|
|
136
137
|
_initSessionPromise = null;
|
|
138
|
+
targetSetCache = new Map();
|
|
137
139
|
constructor(runtime) {
|
|
138
140
|
this.runtime = runtime;
|
|
139
141
|
}
|
|
@@ -155,16 +157,48 @@ export class V2E2EECoordinator {
|
|
|
155
157
|
}
|
|
156
158
|
deleteBootstrapCacheEntry(key) {
|
|
157
159
|
this.bootstrapCache.delete(key);
|
|
160
|
+
this.targetSetCache.delete(key);
|
|
158
161
|
}
|
|
159
162
|
clearBootstrapCache() {
|
|
160
163
|
this.bootstrapCache.clear();
|
|
164
|
+
this.targetSetCache.clear();
|
|
161
165
|
}
|
|
162
166
|
pruneExpiredBootstrapCache(ttlMs, now = Date.now()) {
|
|
163
167
|
for (const [key, entry] of this.bootstrapCache) {
|
|
164
168
|
if (now - Number(entry.cachedAt ?? 0) >= ttlMs) {
|
|
165
169
|
this.bootstrapCache.delete(key);
|
|
170
|
+
this.targetSetCache.delete(key);
|
|
166
171
|
}
|
|
167
172
|
}
|
|
173
|
+
for (const [key, entry] of this.targetSetCache) {
|
|
174
|
+
if (now - Number(entry.cachedAt ?? 0) >= ttlMs) {
|
|
175
|
+
this.targetSetCache.delete(key);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
getTargetSetCache(key) {
|
|
180
|
+
const cached = this.targetSetCache.get(key);
|
|
181
|
+
if (!cached || Date.now() - cached.cachedAt >= V2_BOOTSTRAP_TTL_MS) {
|
|
182
|
+
if (cached)
|
|
183
|
+
this.targetSetCache.delete(key);
|
|
184
|
+
return undefined;
|
|
185
|
+
}
|
|
186
|
+
return cached.value;
|
|
187
|
+
}
|
|
188
|
+
setTargetSetCache(key, value) {
|
|
189
|
+
this.targetSetCache.set(key, { cachedAt: Date.now(), value });
|
|
190
|
+
return value;
|
|
191
|
+
}
|
|
192
|
+
cloneP2PTargetSet(value) {
|
|
193
|
+
return {
|
|
194
|
+
targets: value.targets.map((target) => ({ ...target })),
|
|
195
|
+
auditRecipients: value.auditRecipients.map((target) => ({ ...target })),
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
cloneGroupTargetSet(value) {
|
|
199
|
+
return {
|
|
200
|
+
targets: value.targets.map((target) => ({ ...target })),
|
|
201
|
+
};
|
|
168
202
|
}
|
|
169
203
|
async onConnected(opts) {
|
|
170
204
|
const client = this.client;
|
|
@@ -453,6 +487,7 @@ export class V2E2EECoordinator {
|
|
|
453
487
|
client._clientLog.debug(`message.v2.bootstrap cache hit: to=${to}, devices=${peerDevices.length}, audit=${auditRaw.length}`);
|
|
454
488
|
}
|
|
455
489
|
else {
|
|
490
|
+
this.targetSetCache.delete(to);
|
|
456
491
|
const bs = await client.call('message.v2.bootstrap', {
|
|
457
492
|
peer_aid: to,
|
|
458
493
|
e2ee_wrap_capabilities: v2WrapCapabilities(),
|
|
@@ -464,7 +499,7 @@ export class V2E2EECoordinator {
|
|
|
464
499
|
peerDevices = (Array.isArray(bs?.peer_devices) ? bs.peer_devices : []);
|
|
465
500
|
auditRaw = (Array.isArray(bs?.audit_recipients) ? bs.audit_recipients : []);
|
|
466
501
|
client._clientLog.debug(`message.v2.bootstrap fetched: to=${to}, devices=${peerDevices.length}, audit=${auditRaw.length}`);
|
|
467
|
-
if (peerDevices.length > 0
|
|
502
|
+
if (peerDevices.length > 0) {
|
|
468
503
|
this.setBootstrapCacheEntry(to, {
|
|
469
504
|
devices: peerDevices,
|
|
470
505
|
auditRecipients: auditRaw,
|
|
@@ -476,83 +511,92 @@ export class V2E2EECoordinator {
|
|
|
476
511
|
if (peerDevices.length === 0) {
|
|
477
512
|
throw new E2EEError(`V2 bootstrap: no devices found for ${to}`);
|
|
478
513
|
}
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
const target = await client._v2BuildTargetFromDevice({
|
|
483
|
-
dev,
|
|
484
|
-
aid: to,
|
|
485
|
-
deviceId: devId.value,
|
|
486
|
-
role: 'peer',
|
|
487
|
-
defaultKeySource: 'peer_device_prekey',
|
|
488
|
-
});
|
|
489
|
-
if (target)
|
|
490
|
-
targets.push(target);
|
|
491
|
-
}
|
|
492
|
-
const auditTargets = [];
|
|
493
|
-
for (const dev of auditRaw) {
|
|
494
|
-
const target = await client._v2BuildTargetFromDevice({
|
|
495
|
-
dev,
|
|
496
|
-
aid: String(dev.aid ?? ''),
|
|
497
|
-
deviceId: String(dev.device_id ?? ''),
|
|
498
|
-
role: 'audit',
|
|
499
|
-
defaultKeySource: 'peer_device_prekey',
|
|
500
|
-
});
|
|
501
|
-
if (target)
|
|
502
|
-
auditTargets.push(target);
|
|
514
|
+
let targetSet = useCache ? this.getTargetSetCache(to) : undefined;
|
|
515
|
+
if (targetSet) {
|
|
516
|
+
targetSet = this.cloneP2PTargetSet(targetSet);
|
|
503
517
|
}
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
+
else {
|
|
519
|
+
const targets = [];
|
|
520
|
+
for (const dev of peerDevices) {
|
|
521
|
+
const devId = getV2DeviceId(dev);
|
|
522
|
+
const target = await client._v2BuildTargetFromDevice({
|
|
523
|
+
dev,
|
|
524
|
+
aid: to,
|
|
525
|
+
deviceId: devId.value,
|
|
526
|
+
role: 'peer',
|
|
527
|
+
defaultKeySource: 'peer_device_prekey',
|
|
528
|
+
});
|
|
529
|
+
if (target)
|
|
530
|
+
targets.push(target);
|
|
531
|
+
}
|
|
532
|
+
const auditTargets = [];
|
|
533
|
+
for (const dev of auditRaw) {
|
|
534
|
+
const target = await client._v2BuildTargetFromDevice({
|
|
535
|
+
dev,
|
|
536
|
+
aid: String(dev.aid ?? ''),
|
|
537
|
+
deviceId: String(dev.device_id ?? ''),
|
|
538
|
+
role: 'audit',
|
|
539
|
+
defaultKeySource: 'peer_device_prekey',
|
|
540
|
+
});
|
|
541
|
+
if (target)
|
|
542
|
+
auditTargets.push(target);
|
|
543
|
+
}
|
|
544
|
+
if (client._aid && client._aid !== to) {
|
|
545
|
+
try {
|
|
546
|
+
const selfCached = this.getBootstrapCacheEntry(client._aid);
|
|
547
|
+
let selfDevices = [];
|
|
548
|
+
if (selfCached && Date.now() - Number(selfCached.cachedAt ?? 0) < V2_BOOTSTRAP_TTL_MS) {
|
|
549
|
+
selfDevices = (selfCached.devices ?? []);
|
|
518
550
|
}
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
auditRecipients: [],
|
|
525
|
-
cachedAt: Date.now(),
|
|
526
|
-
wrapPolicy: selfWrapPolicy,
|
|
551
|
+
else {
|
|
552
|
+
this.targetSetCache.delete(client._aid);
|
|
553
|
+
const selfBs = await client.call('message.v2.bootstrap', {
|
|
554
|
+
peer_aid: client._aid,
|
|
555
|
+
e2ee_wrap_capabilities: v2WrapCapabilities(),
|
|
527
556
|
});
|
|
557
|
+
if (typeof client._primeBootstrapPeerCerts === 'function') {
|
|
558
|
+
await client._primeBootstrapPeerCerts(selfBs, client._aid);
|
|
559
|
+
}
|
|
560
|
+
selfDevices = (Array.isArray(selfBs?.peer_devices) ? selfBs.peer_devices : []);
|
|
561
|
+
const selfWrapPolicy = normalizeV2WrapPolicy(selfBs.e2ee_wrap_policy);
|
|
562
|
+
if (selfDevices.length > 0) {
|
|
563
|
+
this.setBootstrapCacheEntry(client._aid, {
|
|
564
|
+
devices: selfDevices,
|
|
565
|
+
auditRecipients: [],
|
|
566
|
+
cachedAt: Date.now(),
|
|
567
|
+
wrapPolicy: selfWrapPolicy,
|
|
568
|
+
});
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
for (const dev of selfDevices) {
|
|
572
|
+
const devId = getV2DeviceId(dev);
|
|
573
|
+
if (!devId.present || devId.value === client._deviceId)
|
|
574
|
+
continue;
|
|
575
|
+
const target = await client._v2BuildTargetFromDevice({
|
|
576
|
+
dev,
|
|
577
|
+
aid: client._aid,
|
|
578
|
+
deviceId: devId.value,
|
|
579
|
+
role: 'self_sync',
|
|
580
|
+
defaultKeySource: 'peer_device_prekey',
|
|
581
|
+
});
|
|
582
|
+
if (target)
|
|
583
|
+
targets.push(target);
|
|
528
584
|
}
|
|
529
585
|
}
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
if (!devId.present || devId.value === client._deviceId)
|
|
533
|
-
continue;
|
|
534
|
-
const target = await client._v2BuildTargetFromDevice({
|
|
535
|
-
dev,
|
|
536
|
-
aid: client._aid,
|
|
537
|
-
deviceId: devId.value,
|
|
538
|
-
role: 'self_sync',
|
|
539
|
-
defaultKeySource: 'peer_device_prekey',
|
|
540
|
-
});
|
|
541
|
-
if (target)
|
|
542
|
-
targets.push(target);
|
|
586
|
+
catch (exc) {
|
|
587
|
+
client._clientLog.debug(`V2 self-sync bootstrap failed (non-fatal): ${formatE2EEError(exc)}`);
|
|
543
588
|
}
|
|
544
589
|
}
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
590
|
+
targetSet = this.setTargetSetCache(to, {
|
|
591
|
+
targets: applyV2WrapPolicyToTargets(targets, wrapPolicy),
|
|
592
|
+
auditRecipients: applyV2WrapPolicyToTargets(auditTargets, wrapPolicy),
|
|
593
|
+
});
|
|
594
|
+
targetSet = this.cloneP2PTargetSet(targetSet);
|
|
548
595
|
}
|
|
549
|
-
if (targets.length === 0) {
|
|
596
|
+
if (targetSet.targets.length === 0) {
|
|
550
597
|
throw new E2EEError(`V2 bootstrap: no usable devices found for ${to}`);
|
|
551
598
|
}
|
|
552
|
-
const envelope = encryptP2PMessage(session.getSenderIdentity(), {
|
|
553
|
-
targets: applyV2WrapPolicyToTargets(targets, wrapPolicy),
|
|
554
|
-
auditRecipients: applyV2WrapPolicyToTargets(auditTargets, wrapPolicy),
|
|
555
|
-
}, opts.payload, {
|
|
599
|
+
const envelope = encryptP2PMessage(session.getSenderIdentity(), targetSet, opts.payload, {
|
|
556
600
|
messageId: opts.messageId,
|
|
557
601
|
timestamp: opts.timestamp,
|
|
558
602
|
protectedHeaders: opts.protectedHeaders,
|
|
@@ -569,8 +613,8 @@ export class V2E2EECoordinator {
|
|
|
569
613
|
payloadOverride: envelope,
|
|
570
614
|
extra: {
|
|
571
615
|
plaintext_payload: opts.payload,
|
|
572
|
-
target_count: targets.length,
|
|
573
|
-
audit_count:
|
|
616
|
+
target_count: targetSet.targets.length,
|
|
617
|
+
audit_count: targetSet.auditRecipients.length,
|
|
574
618
|
use_cache: useCache,
|
|
575
619
|
},
|
|
576
620
|
});
|
|
@@ -652,6 +696,7 @@ export class V2E2EECoordinator {
|
|
|
652
696
|
const decrypted = [];
|
|
653
697
|
let nextAfterSeq = opts?.force ? afterSeq : (afterSeq || (ns ? client._seqTracker.getContiguousSeq(ns) : 0));
|
|
654
698
|
let pageCount = 0;
|
|
699
|
+
let lastAutoAckSeq = 0;
|
|
655
700
|
const maxPages = 100;
|
|
656
701
|
while (pageCount < maxPages) {
|
|
657
702
|
pageCount += 1;
|
|
@@ -661,8 +706,12 @@ export class V2E2EECoordinator {
|
|
|
661
706
|
limit,
|
|
662
707
|
...(opts?.force ? { force: true } : {}),
|
|
663
708
|
});
|
|
664
|
-
const
|
|
665
|
-
|
|
709
|
+
const pageMessages = (Array.isArray(result?.messages) ? result.messages : []);
|
|
710
|
+
const messages = pageMessages.filter((msg) => {
|
|
711
|
+
const seq = Number(msg.seq ?? 0);
|
|
712
|
+
return Number.isFinite(seq) && seq > nextAfterSeq;
|
|
713
|
+
});
|
|
714
|
+
client._clientLog.debug(`message.v2.pull page response: page=${pageCount}, raw_count=${messages.length}, stale_count=${Math.max(0, pageMessages.length - messages.length)}, has_more=${String(result.has_more ?? '')}, server_ack_seq=${String(result.server_ack_seq ?? '')}`);
|
|
666
715
|
for (const msg of messages) {
|
|
667
716
|
client._logMessageDebug('pull-raw', 'message.v2.pull', 'message.received', msg);
|
|
668
717
|
}
|
|
@@ -752,19 +801,21 @@ export class V2E2EECoordinator {
|
|
|
752
801
|
const contigAdvanced = ackSeq !== pageContigBefore;
|
|
753
802
|
if (contigAdvanced) {
|
|
754
803
|
await client._drainOrderedMessages(ns, undefined, true);
|
|
755
|
-
client.
|
|
804
|
+
client._persistSeq(ns);
|
|
756
805
|
}
|
|
757
|
-
const ackNeeded =
|
|
806
|
+
const ackNeeded = pageMessages.length > 0
|
|
758
807
|
&& ackSeq > 0
|
|
808
|
+
&& ackSeq > lastAutoAckSeq
|
|
759
809
|
&& !opts?.skipAutoAck
|
|
760
810
|
&& (contigAdvanced || (hasServerAckSeq && ackSeq > serverAckSeq));
|
|
761
811
|
if (ackNeeded) {
|
|
762
812
|
client._clientLog.debug(`message.v2.pull sending auto-ack: ns=${ns}, ack_seq=${ackSeq}, raw_count=${messages.length}`);
|
|
763
813
|
await this.ackV2(ackSeq);
|
|
814
|
+
lastAutoAckSeq = ackSeq;
|
|
764
815
|
}
|
|
765
816
|
}
|
|
766
817
|
const nextAfter = Math.max(pageMaxSeq, nextAfterSeq);
|
|
767
|
-
if (messages.length === 0 || nextAfter <= nextAfterSeq
|
|
818
|
+
if (messages.length === 0 || nextAfter <= nextAfterSeq)
|
|
768
819
|
break;
|
|
769
820
|
nextAfterSeq = nextAfter;
|
|
770
821
|
}
|
|
@@ -895,7 +946,8 @@ export class V2E2EECoordinator {
|
|
|
895
946
|
if (!client._v2Session)
|
|
896
947
|
throw new StateError('V2 session not initialized');
|
|
897
948
|
const session = client._v2Session;
|
|
898
|
-
const
|
|
949
|
+
const rawGroupId = String(opts.groupId ?? '').trim();
|
|
950
|
+
const groupId = normalizeGroupId(rawGroupId) || rawGroupId;
|
|
899
951
|
if (!groupId)
|
|
900
952
|
throw new ValidationError("group.send requires 'group_id'");
|
|
901
953
|
const cacheKey = `group:${groupId}`;
|
|
@@ -905,16 +957,27 @@ export class V2E2EECoordinator {
|
|
|
905
957
|
let epoch = 0;
|
|
906
958
|
let stateCommitment = { state_version: 0, state_hash: '', state_chain: '' };
|
|
907
959
|
let wrapPolicy = normalizeV2WrapPolicy(undefined);
|
|
908
|
-
|
|
960
|
+
let usedCachedBootstrap = false;
|
|
961
|
+
let cached = useCache ? this.getBootstrapCacheEntry(cacheKey) : undefined;
|
|
962
|
+
if (!cached && useCache && rawGroupId && rawGroupId !== groupId) {
|
|
963
|
+
const legacyCacheKey = `group:${rawGroupId}`;
|
|
964
|
+
cached = this.getBootstrapCacheEntry(legacyCacheKey);
|
|
965
|
+
if (cached) {
|
|
966
|
+
this.setBootstrapCacheEntry(cacheKey, cached);
|
|
967
|
+
this.deleteBootstrapCacheEntry(legacyCacheKey);
|
|
968
|
+
}
|
|
969
|
+
}
|
|
909
970
|
if (cached && Date.now() - Number(cached.cachedAt ?? 0) < V2_BOOTSTRAP_TTL_MS) {
|
|
910
971
|
allDevices = (cached.devices ?? []);
|
|
911
972
|
auditRecipientsRaw = (cached.auditRecipients ?? []);
|
|
912
973
|
epoch = Number(cached.epoch ?? 0) || 0;
|
|
913
974
|
stateCommitment = cached.stateCommitment ?? stateCommitment;
|
|
914
975
|
wrapPolicy = cached.wrapPolicy ?? wrapPolicy;
|
|
976
|
+
usedCachedBootstrap = true;
|
|
915
977
|
client._clientLog.debug(`group.v2.bootstrap cache hit: group=${groupId}, devices=${allDevices.length}, audit=${auditRecipientsRaw.length}, epoch=${epoch}, state_version=${stateCommitment.state_version}`);
|
|
916
978
|
}
|
|
917
979
|
else {
|
|
980
|
+
this.targetSetCache.delete(cacheKey);
|
|
918
981
|
const bs = await client.call('group.v2.bootstrap', {
|
|
919
982
|
group_id: groupId,
|
|
920
983
|
e2ee_wrap_capabilities: v2WrapCapabilities(),
|
|
@@ -951,38 +1014,63 @@ export class V2E2EECoordinator {
|
|
|
951
1014
|
if (allDevices.length === 0) {
|
|
952
1015
|
throw new E2EEError(`V2 group bootstrap: no devices found for group ${groupId}`);
|
|
953
1016
|
}
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
const
|
|
961
|
-
|
|
962
|
-
dev
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
role
|
|
966
|
-
|
|
1017
|
+
let targetSet = useCache ? this.getTargetSetCache(cacheKey) : undefined;
|
|
1018
|
+
if (targetSet) {
|
|
1019
|
+
targetSet = this.cloneGroupTargetSet(targetSet);
|
|
1020
|
+
}
|
|
1021
|
+
else {
|
|
1022
|
+
const targets = [];
|
|
1023
|
+
for (const dev of allDevices) {
|
|
1024
|
+
const devAid = String(dev.aid ?? '').trim();
|
|
1025
|
+
const devId = getV2DeviceId(dev);
|
|
1026
|
+
if (devAid === client._aid && devId.present && devId.value === client._deviceId)
|
|
1027
|
+
continue;
|
|
1028
|
+
const role = devAid === client._aid ? 'self_sync' : 'member';
|
|
1029
|
+
const target = await client._v2BuildTargetFromDevice({
|
|
1030
|
+
dev,
|
|
1031
|
+
aid: devAid,
|
|
1032
|
+
deviceId: devId.value,
|
|
1033
|
+
role,
|
|
1034
|
+
defaultKeySource: 'peer_device_prekey',
|
|
1035
|
+
});
|
|
1036
|
+
if (target)
|
|
1037
|
+
targets.push(target);
|
|
1038
|
+
}
|
|
1039
|
+
if (targets.length === 0) {
|
|
1040
|
+
if (usedCachedBootstrap) {
|
|
1041
|
+
throw new E2EEError(`V2 group: no target devices for group ${groupId}; bootstrap may be stale`, {
|
|
1042
|
+
code: V2_GROUP_STALE_BOOTSTRAP_CODE,
|
|
1043
|
+
data: { expected_peer_aids: [] },
|
|
1044
|
+
});
|
|
1045
|
+
}
|
|
1046
|
+
throw new E2EEError(`V2 group: no target devices for group ${groupId}`);
|
|
1047
|
+
}
|
|
1048
|
+
for (const dev of auditRecipientsRaw) {
|
|
1049
|
+
const target = await client._v2BuildTargetFromDevice({
|
|
1050
|
+
dev,
|
|
1051
|
+
aid: String(dev.aid ?? ''),
|
|
1052
|
+
deviceId: String(dev.device_id ?? ''),
|
|
1053
|
+
role: 'audit',
|
|
1054
|
+
defaultKeySource: 'peer_device_prekey',
|
|
1055
|
+
});
|
|
1056
|
+
if (target)
|
|
1057
|
+
targets.push(target);
|
|
1058
|
+
}
|
|
1059
|
+
targetSet = this.setTargetSetCache(cacheKey, {
|
|
1060
|
+
targets: applyV2WrapPolicyToTargets(targets, wrapPolicy),
|
|
967
1061
|
});
|
|
968
|
-
|
|
969
|
-
targets.push(target);
|
|
1062
|
+
targetSet = this.cloneGroupTargetSet(targetSet);
|
|
970
1063
|
}
|
|
971
|
-
if (targets.length === 0) {
|
|
1064
|
+
if (targetSet.targets.length === 0) {
|
|
1065
|
+
if (usedCachedBootstrap) {
|
|
1066
|
+
throw new E2EEError(`V2 group: no target devices for group ${groupId}; bootstrap may be stale`, {
|
|
1067
|
+
code: V2_GROUP_STALE_BOOTSTRAP_CODE,
|
|
1068
|
+
data: { expected_peer_aids: [] },
|
|
1069
|
+
});
|
|
1070
|
+
}
|
|
972
1071
|
throw new E2EEError(`V2 group: no target devices for group ${groupId}`);
|
|
973
1072
|
}
|
|
974
|
-
|
|
975
|
-
const target = await client._v2BuildTargetFromDevice({
|
|
976
|
-
dev,
|
|
977
|
-
aid: String(dev.aid ?? ''),
|
|
978
|
-
deviceId: String(dev.device_id ?? ''),
|
|
979
|
-
role: 'audit',
|
|
980
|
-
defaultKeySource: 'peer_device_prekey',
|
|
981
|
-
});
|
|
982
|
-
if (target)
|
|
983
|
-
targets.push(target);
|
|
984
|
-
}
|
|
985
|
-
const envelope = encryptGroupMessage(session.getSenderIdentity(), groupId, epoch, applyV2WrapPolicyToTargets(targets, wrapPolicy), opts.payload, {
|
|
1073
|
+
const envelope = encryptGroupMessage(session.getSenderIdentity(), groupId, epoch, targetSet.targets, opts.payload, {
|
|
986
1074
|
messageId: opts.messageId,
|
|
987
1075
|
timestamp: opts.timestamp,
|
|
988
1076
|
protectedHeaders: opts.protectedHeaders,
|
|
@@ -1000,7 +1088,7 @@ export class V2E2EECoordinator {
|
|
|
1000
1088
|
extra: {
|
|
1001
1089
|
plaintext_payload: opts.payload,
|
|
1002
1090
|
epoch,
|
|
1003
|
-
target_count: targets.length,
|
|
1091
|
+
target_count: targetSet.targets.length,
|
|
1004
1092
|
audit_count: auditRecipientsRaw.length,
|
|
1005
1093
|
state_version: stateCommitment.state_version,
|
|
1006
1094
|
use_cache: useCache,
|
|
@@ -1026,6 +1114,7 @@ export class V2E2EECoordinator {
|
|
|
1026
1114
|
}));
|
|
1027
1115
|
}
|
|
1028
1116
|
const decrypted = [];
|
|
1117
|
+
const wireGroupId = String(opts?.wireGroupId ?? groupId ?? '').trim() || gid;
|
|
1029
1118
|
const cursorParams = opts?.cursorParams ?? {};
|
|
1030
1119
|
const ownsCursor = opts?.ownsCursor !== false;
|
|
1031
1120
|
let nextAfterSeq = opts?.explicitAfterSeq ? afterSeq : (afterSeq || client._seqTracker.getContiguousSeq(ns));
|
|
@@ -1035,7 +1124,8 @@ export class V2E2EECoordinator {
|
|
|
1035
1124
|
pageCount += 1;
|
|
1036
1125
|
client._clientLog.debug(`group.v2.pull page request: group=${gid}, page=${pageCount}, after_seq=${nextAfterSeq}, limit=${limit}, ns=${ns}`);
|
|
1037
1126
|
const result = await client._callRawV2Rpc('group.v2.pull', {
|
|
1038
|
-
group_id:
|
|
1127
|
+
group_id: wireGroupId,
|
|
1128
|
+
group_aid: gid,
|
|
1039
1129
|
after_seq: nextAfterSeq,
|
|
1040
1130
|
limit,
|
|
1041
1131
|
...cursorParams,
|
|
@@ -1139,7 +1229,7 @@ export class V2E2EECoordinator {
|
|
|
1139
1229
|
const contigAdvanced = ackSeq !== pageContigBefore;
|
|
1140
1230
|
if (contigAdvanced) {
|
|
1141
1231
|
await client._drainOrderedMessages(ns, undefined, true);
|
|
1142
|
-
client.
|
|
1232
|
+
client._persistSeq(ns);
|
|
1143
1233
|
}
|
|
1144
1234
|
const ackNeeded = messages.length > 0
|
|
1145
1235
|
&& ackSeq > 0
|
|
@@ -1175,7 +1265,7 @@ export class V2E2EECoordinator {
|
|
|
1175
1265
|
}
|
|
1176
1266
|
seq = client._clampAckSeq('group.v2.ack', 'up_to_seq', ns, seq);
|
|
1177
1267
|
client._clientLog.debug(`group.v2.ack send: group=${gid}, ns=${ns}, up_to_seq=${seq}`);
|
|
1178
|
-
const result = await client._callRawV2Rpc('group.v2.ack', { group_id: gid, up_to_seq: seq });
|
|
1268
|
+
const result = await client._callRawV2Rpc('group.v2.ack', { group_id: gid, group_aid: gid, up_to_seq: seq });
|
|
1179
1269
|
client._clientLog.debug(`group.v2.ack ok: group=${gid}, ns=${ns}, requested=${seq}, result=${client._debugJson(result)}`);
|
|
1180
1270
|
return result;
|
|
1181
1271
|
}
|
|
@@ -1698,26 +1788,5 @@ export class V2E2EECoordinator {
|
|
|
1698
1788
|
this.scheduleGroupSpkRotation(groupId, { reason: `group_changed:${action}` });
|
|
1699
1789
|
}
|
|
1700
1790
|
}
|
|
1701
|
-
async handleV2EpochRotated(data) {
|
|
1702
|
-
const client = this.client;
|
|
1703
|
-
if (!data || typeof data !== 'object' || Array.isArray(data))
|
|
1704
|
-
return;
|
|
1705
|
-
const d = data;
|
|
1706
|
-
const groupId = String(d.group_id ?? '').trim();
|
|
1707
|
-
if (!groupId)
|
|
1708
|
-
return;
|
|
1709
|
-
const epoch = d.epoch ?? 0;
|
|
1710
|
-
client._clientLog.debug(`_onV2EpochRotated: group=${groupId} epoch=${String(epoch)}`);
|
|
1711
|
-
this.deleteBootstrapCacheEntry(`group:${groupId}`);
|
|
1712
|
-
if (!client._v2Session)
|
|
1713
|
-
return;
|
|
1714
|
-
try {
|
|
1715
|
-
await client._v2Session.rotateSPK(client._v2CallFn());
|
|
1716
|
-
client._clientLog.info(`SPK rotated after V2 epoch change: group=${groupId} epoch=${String(epoch)}`);
|
|
1717
|
-
}
|
|
1718
|
-
catch (exc) {
|
|
1719
|
-
client._clientLog.debug(`SPK rotation after V2 epoch change failed (non-fatal): ${formatE2EEError(exc)}`);
|
|
1720
|
-
}
|
|
1721
|
-
}
|
|
1722
1791
|
}
|
|
1723
1792
|
//# sourceMappingURL=v2-e2ee.js.map
|