@agentunion/fastaun 0.5.19 → 0.5.20

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.
Files changed (99) hide show
  1. package/CHANGELOG.md +129 -78
  2. package/_packed_docs/CHANGELOG.md +129 -78
  3. package/_packed_docs/INDEX.md +201 -195
  4. package/_packed_docs/KITE_DOCS_GUIDE.md +93 -90
  5. package/_packed_docs/agent.md/SCHEMA.md +7 -7
  6. 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 +11 -11
  7. package/_packed_docs/protocol/06-/346/234/215/345/212/241/345/215/217/350/256/256.md +1072 -1072
  8. package/_packed_docs/protocol/10-Group-/345/255/220/345/215/217/350/256/256.md +676 -676
  9. package/_packed_docs/protocol/11-Storage-/345/255/220/345/215/217/350/256/256.md +8 -12
  10. package/_packed_docs/protocol/Ownership/345/215/217/350/256/256/345/256/232/344/271/211.md +443 -0
  11. package/_packed_docs/protocol/Ownership/345/215/217/350/256/256/345/256/232/344/271/2112.0.md +161 -0
  12. package/_packed_docs/protocol/Ownership/345/215/217/350/256/256/345/256/232/344/271/2112.1.md +658 -0
  13. package/_packed_docs/protocol/Ownership/345/215/217/350/256/256/345/256/232/344/271/2113.0.md +233 -0
  14. package/_packed_docs/protocol/agent.md/SCHEMA.md +1 -1
  15. package/_packed_docs/sdk/03-/346/240/270/345/277/203/346/246/202/345/277/265.md +1 -1
  16. package/_packed_docs/sdk/04-/350/277/236/346/216/245/344/270/216/350/256/244/350/257/201.md +67 -63
  17. package/_packed_docs/sdk/05-E2EE/345/212/240/345/257/206/351/200/232/344/277/241.md +1 -1
  18. package/_packed_docs/sdk/06-API/346/211/213/345/206/214.md +35 -8
  19. package/_packed_docs/sdk/08-/346/234/200/344/275/263/345/256/236/350/267/265.md +3 -3
  20. package/_packed_docs/sdk/09-group-rpc-manual.md +258 -254
  21. package/_packed_docs/sdk/09-message-rpc-manual.md +7 -4
  22. package/_packed_docs/sdk/09-storage-rpc-manual.md +18 -26
  23. package/_packed_docs/sdk/AUN_DOCS_GUIDE.md +61 -52
  24. package/_packed_docs/sdk/INDEX.md +92 -80
  25. package/_packed_docs/sdk/Ownership-SDK/345/256/236/347/216/260/346/214/207/345/215/227.md +169 -0
  26. package/_packed_docs/sdk/Ownership-SDK/347/274/226/346/216/222/346/214/207/345/215/227.md +349 -0
  27. package/_packed_docs/sdk/Ownership-SDK/347/274/226/346/216/222/346/214/207/345/215/2272.1.md +922 -0
  28. package/_packed_docs/sdk/Ownership-SDK/351/233/206/346/210/220/346/214/207/345/215/227.md +270 -0
  29. package/_packed_docs/sdk/Ownership2.1-SDK/345/272/224/347/224/250/351/233/206/346/210/220/346/214/207/345/215/227.md +300 -0
  30. package/_packed_docs/sdk/Ownership2.1-SDK/345/274/200/345/217/221/344/270/216/347/247/273/346/244/215/346/214/207/345/215/227.md +382 -0
  31. package/_packed_docs/sdk/Ownership2.1-TDD/345/210/206/351/230/266/346/256/265/345/256/236/346/226/275/350/256/241/345/210/222.md +708 -0
  32. package/_packed_docs/sdk/Ownership2.1/350/257/246/347/273/206/350/256/276/350/256/241.md +476 -0
  33. package/_packed_docs/sdk/Ownership/347/256/241/347/220/206/344/270/223/351/242/230.md +559 -0
  34. package/_packed_docs/sdk/ProtectedHeaders/347/224/250/346/263/225/344/270/223/351/242/230.md +299 -0
  35. package/_packed_docs/sdk//345/207/255/350/257/201/344/270/216/347/273/204/347/273/207/346/234/215/345/212/241SDK/345/272/224/347/224/250/351/233/206/346/210/220/346/214/207/345/215/227.md +173 -0
  36. package/_packed_docs/sdk//345/207/255/350/257/201/344/270/216/347/273/204/347/273/207/346/234/215/345/212/241SDK/345/274/200/345/217/221/344/270/216/347/247/273/346/244/215/346/214/207/345/215/227.md +211 -0
  37. package/_packed_docs//350/267/250/350/256/276/345/244/207/345/267/262/350/257/273/346/234/252/350/257/273SDK/345/256/236/347/216/260/347/247/273/346/244/215/346/214/207/345/215/227.md +331 -0
  38. package/_packed_docs//350/267/250/350/256/276/345/244/207/345/267/262/350/257/273/346/234/252/350/257/273SDK/351/233/206/346/210/220/346/214/207/345/215/227.md +207 -0
  39. package/_packed_docs//350/267/250/350/256/276/345/244/207/345/267/262/350/257/273/346/234/252/350/257/273/344/273/243/347/240/201/345/256/241/346/237/245/346/212/245/345/221/212.md +252 -0
  40. package/_packed_docs//350/267/250/350/256/276/345/244/207/345/267/262/350/257/273/346/234/252/350/257/273/345/256/236/346/226/275/350/256/241/345/210/222.md +156 -0
  41. package/_packed_docs//350/267/250/350/256/276/345/244/207/345/267/262/350/257/273/346/234/252/350/257/273/346/226/271/346/241/210.md +273 -0
  42. package/_packed_docs//350/267/250/350/256/276/345/244/207/345/267/262/350/257/273/346/234/252/350/257/273/350/257/246/347/273/206/350/256/276/350/256/241.md +211 -0
  43. package/dist/agent-md-schema.d.ts +13 -1
  44. package/dist/agent-md-schema.js +61 -33
  45. package/dist/agent-md-schema.js.map +1 -1
  46. package/dist/agent-md.d.ts +8 -1
  47. package/dist/agent-md.js +243 -119
  48. package/dist/agent-md.js.map +1 -1
  49. package/dist/aid-store.d.ts +29 -0
  50. package/dist/aid-store.js +179 -34
  51. package/dist/aid-store.js.map +1 -1
  52. package/dist/aid.js +18 -13
  53. package/dist/aid.js.map +1 -1
  54. package/dist/auth.js +74 -2
  55. package/dist/auth.js.map +1 -1
  56. package/dist/cert-utils.d.ts +43 -1
  57. package/dist/cert-utils.js +144 -56
  58. package/dist/cert-utils.js.map +1 -1
  59. package/dist/client/delivery.d.ts +9 -0
  60. package/dist/client/delivery.js +179 -11
  61. package/dist/client/delivery.js.map +1 -1
  62. package/dist/client/rpc-pipeline.d.ts +1 -0
  63. package/dist/client/rpc-pipeline.js +125 -82
  64. package/dist/client/rpc-pipeline.js.map +1 -1
  65. package/dist/client/v2-e2ee.js +95 -89
  66. package/dist/client/v2-e2ee.js.map +1 -1
  67. package/dist/client.js +48 -19
  68. package/dist/client.js.map +1 -1
  69. package/dist/events.d.ts +5 -3
  70. package/dist/events.js +25 -8
  71. package/dist/events.js.map +1 -1
  72. package/dist/facades.js +5 -5
  73. package/dist/facades.js.map +1 -1
  74. package/dist/index.d.ts +2 -1
  75. package/dist/index.js.map +1 -1
  76. package/dist/keystore/aid-db.d.ts +1 -1
  77. package/dist/keystore/aid-db.js +11 -2
  78. package/dist/keystore/aid-db.js.map +1 -1
  79. package/dist/keystore/index.d.ts +1 -1
  80. package/dist/keystore/local-token-store.d.ts +1 -1
  81. package/dist/keystore/local-token-store.js +2 -2
  82. package/dist/keystore/local-token-store.js.map +1 -1
  83. package/dist/org-protocol.js +77 -13
  84. package/dist/org-protocol.js.map +1 -1
  85. package/dist/ownership-v21.d.ts +26 -8
  86. package/dist/ownership-v21.js +147 -70
  87. package/dist/ownership-v21.js.map +1 -1
  88. package/dist/ownership-workflow.d.ts +5 -0
  89. package/dist/ownership-workflow.js +366 -56
  90. package/dist/ownership-workflow.js.map +1 -1
  91. package/dist/tools/cross-sdk-agent.d.ts +2 -1
  92. package/dist/tools/cross-sdk-agent.js +109 -6
  93. package/dist/tools/cross-sdk-agent.js.map +1 -1
  94. package/dist/transport.d.ts +1 -0
  95. package/dist/transport.js +10 -0
  96. package/dist/transport.js.map +1 -1
  97. package/dist/version.d.ts +1 -1
  98. package/dist/version.js +1 -1
  99. package/package.json +1 -1
package/dist/client.js CHANGED
@@ -47,7 +47,7 @@ import { decryptedOwnershipJsonText } from './v2/e2ee/decrypt.js';
47
47
  import { isJsonObject, ConnectionState, STATE_TO_PUBLIC, } from './types.js';
48
48
  import { AID } from './aid.js';
49
49
  import { certFingerprint, certMatchesFingerprint, normalizeFingerprintHex, publicKeyMatchesFingerprint } from './cert-utils.js';
50
- import { validateAgentMdDocument } from './agent-md-schema.js';
50
+ import { validateAgentMdCertificate, validateAgentMdDocument } from './agent-md-schema.js';
51
51
  import { OwnershipFiles, OwnershipStorageAdapter, ownershipFailure, signOwnershipFile } from './ownership-v21.js';
52
52
  import { OwnershipWorkflow } from './ownership-workflow.js';
53
53
  import { canonicalJson, createCredential, createMemberCredential, signMembershipBinding, verifyServiceEvent } from './org-protocol.js';
@@ -440,7 +440,7 @@ function createAgentMdManagerForRuntime(opts) {
440
440
  const target = String(aid ?? '').trim();
441
441
  const expectedFp = String(certFingerprint ?? '').trim().toLowerCase();
442
442
  const current = opts.currentAid();
443
- if (current?.aid === target) {
443
+ if (signedAt === undefined && current?.aid === target) {
444
444
  if (!expectedFp || certMatchesFingerprint(current.certPem, expectedFp))
445
445
  return current;
446
446
  }
@@ -485,7 +485,7 @@ export class AUNClient {
485
485
  _ownershipFiles = null;
486
486
  _ownershipWorkflow = null;
487
487
  _getOwnershipStorage() {
488
- return this._ownershipStorage ??= new OwnershipStorageAdapter({ currentAid: () => this._aid, call: (method, params) => this.call(method, params) });
488
+ return this._ownershipStorage ??= new OwnershipStorageAdapter({ currentAid: () => this._aid, call: (method, params) => this.call(method, params), httpPut: (url, data, headers) => this.storage.lowlevel.httpPut(url, data, headers) });
489
489
  }
490
490
  _getOwnershipFiles() {
491
491
  return this._ownershipFiles ??= new OwnershipFiles({
@@ -496,8 +496,8 @@ export class AUNClient {
496
496
  readAgentMdFresh: (subAid) => this._agentMdManager.readOwnershipFresh(subAid),
497
497
  submitAgentMdRaw: (subAid, raw, condition) => this._agentMdManager.submitOwnershipRaw(subAid, raw, condition),
498
498
  readOwnerMd: (ownerAid, subAid) => this._getOwnershipStorage().readOwnerMd(ownerAid, subAid),
499
- writeOwnerMd: (ownerAid, subAid, raw, revision) => this._getOwnershipStorage().writeOwnerMd(ownerAid, subAid, raw, revision),
500
- deleteOwnerMd: (ownerAid, subAid, revision) => this._getOwnershipStorage().deleteOwnerMd(ownerAid, subAid, revision),
499
+ writeOwnerMd: (ownerAid, subAid, raw) => this._getOwnershipStorage().writeOwnerMd(ownerAid, subAid, raw),
500
+ deleteOwnerMd: (ownerAid, subAid) => this._getOwnershipStorage().deleteOwnerMd(ownerAid, subAid),
501
501
  resolveCertificate: async (aid, fingerprint, purpose) => this._auth.resolveOwnershipCertificate(await this._resolveOwnershipCertificateGateway(aid), aid, fingerprint, purpose),
502
502
  });
503
503
  }
@@ -725,7 +725,7 @@ export class AUNClient {
725
725
  if (debugFlag) {
726
726
  this._clientLog.info(`AUNClient initialized (debug=true, aunPath=${this._configModel.aunPath})`);
727
727
  }
728
- this._dispatcher = new EventDispatcher(this._logger.for('aun_core.events'), () => this._identity?.aid ?? '');
728
+ this._dispatcher = new EventDispatcher(this._logger.for('aun_core.events'), () => this._identity?.aid ?? '', () => this._ensureReadStateIdentity());
729
729
  const dnsNet = new DnsResilientNet({
730
730
  verifySsl: this._configModel.verifySsl,
731
731
  logger: this._clientLog,
@@ -771,7 +771,7 @@ export class AUNClient {
771
771
  },
772
772
  auth: () => this._auth,
773
773
  tokenStore: () => this._tokenStore,
774
- fetchPeerCert: (target, certFingerprint, signedAt) => this._fetchPeerCert(target, certFingerprint || undefined, undefined, signedAt),
774
+ fetchPeerCert: (target, certFingerprint, signedAt) => this._fetchPeerCert(target, certFingerprint || undefined, undefined, signedAt, true),
775
775
  resolveEntityOwner: (target, type) => this._resolveEntityAgentMdOwner(target, type),
776
776
  fetchEntityIdentity: (target, type) => this._freshEntityCertificate(target, type),
777
777
  fetchEntitySigner: (target, fingerprint) => this._freshEntitySigner(target, fingerprint),
@@ -787,6 +787,7 @@ export class AUNClient {
787
787
  this._transport.setServiceEventVerifier((event, payload) => verifyServiceEvent(event, payload, { targetAid: this._identity?.aid ?? '', resolveEventCertificate: (aid, fingerprint) => this._fetchServiceEventCertificate(aid, fingerprint), resolveCredentialService: this.resolveCredentialService }), () => this._identity?.aid ?? '', () => this._serviceEventIdentityVersion);
788
788
  this._transport.setProtocolDisconnectCallback((err, closeCode) => this._handleTransportDisconnect(err, closeCode));
789
789
  this._transport._onForegroundDrained = () => this._delivery.onForegroundPullsDrained();
790
+ this._transport._onRpcResponse = () => this._delivery.requestBackgroundPullRecovery();
790
791
  this._runtime = new ClientRuntime(this);
791
792
  this._identityRuntime = new IdentityRuntimeManager(this._runtime);
792
793
  this._peerDirectory = new PeerDirectory(this._runtime);
@@ -1159,7 +1160,7 @@ export class AUNClient {
1159
1160
  },
1160
1161
  auth: () => this._auth,
1161
1162
  tokenStore: () => this._tokenStore,
1162
- fetchPeerCert: (target, certFingerprint, signedAt) => this._fetchPeerCert(target, certFingerprint || undefined, undefined, signedAt),
1163
+ fetchPeerCert: (target, certFingerprint, signedAt) => this._fetchPeerCert(target, certFingerprint || undefined, undefined, signedAt, true),
1163
1164
  resolveEntityOwner: (target, type) => this._resolveEntityAgentMdOwner(target, type),
1164
1165
  fetchEntityIdentity: (target, type) => this._freshEntityCertificate(target, type),
1165
1166
  fetchEntitySigner: (target, fingerprint) => this._freshEntitySigner(target, fingerprint),
@@ -1175,6 +1176,7 @@ export class AUNClient {
1175
1176
  this._transport.setServiceEventVerifier((event, payload) => verifyServiceEvent(event, payload, { targetAid: this._identity?.aid ?? '', resolveEventCertificate: (aid, fingerprint) => this._fetchServiceEventCertificate(aid, fingerprint), resolveCredentialService: this.resolveCredentialService }), () => this._identity?.aid ?? '', () => this._serviceEventIdentityVersion);
1176
1177
  this._transport.setProtocolDisconnectCallback((err, closeCode) => this._handleTransportDisconnect(err, closeCode));
1177
1178
  this._transport._onForegroundDrained = () => this._delivery.onForegroundPullsDrained();
1179
+ this._transport._onRpcResponse = () => this._delivery.requestBackgroundPullRecovery();
1178
1180
  }
1179
1181
  loadIdentity(aid) {
1180
1182
  const previousAid = this._aid;
@@ -1333,6 +1335,9 @@ export class AUNClient {
1333
1335
  const loaded = store.load(groupAid);
1334
1336
  if (!loaded.ok || !loaded.data?.aid?.isPrivateKeyValid())
1335
1337
  return false;
1338
+ const groupManager = store._agentMdManager ?? this._agentMdManager;
1339
+ if (String((groupManager._loadRecord?.(groupAid, true) ?? groupManager.loadRecord(groupAid))?.local_draft_content ?? ''))
1340
+ return false;
1336
1341
  await this._runGroupIdentityOperation(groupAid, () => this._uploadGroupAgentMd(store, groupAid, {}, {}));
1337
1342
  return true;
1338
1343
  }
@@ -1349,7 +1354,7 @@ export class AUNClient {
1349
1354
  if (!aid || !this._currentAid)
1350
1355
  return false;
1351
1356
  const observed = await this._getOwnershipFiles().readAgent(aid);
1352
- if (observed.exists)
1357
+ if (observed.exists || String(this._agentMdManager._loadRecord?.(aid, true)?.local_draft_content ?? this._agentMdManager.loadRecord(aid)?.local_draft_content ?? ''))
1353
1358
  return false;
1354
1359
  let agentMd = buildDefaultAgentMd(aid, { type: this.getType() });
1355
1360
  try {
@@ -1412,6 +1417,11 @@ export class AUNClient {
1412
1417
  await this.completeGroupTransfer({ group_id: groupId, group_aid: groupAid }, { aidStore: store });
1413
1418
  return;
1414
1419
  }
1420
+ const groupManager = store._agentMdManager ?? this._agentMdManager;
1421
+ if (String((groupManager._loadRecord?.(groupAid, true) ?? groupManager.loadRecord(groupAid))?.local_draft_content ?? '')) {
1422
+ await this._agentMdManager.check(groupAid);
1423
+ return;
1424
+ }
1415
1425
  const loaded = store.load(groupAid);
1416
1426
  if (!loaded.ok || !loaded.data?.aid?.isPrivateKeyValid()) {
1417
1427
  await this.bindGroupAid({ group_id: groupId, group_aid: groupAid }, { aidStore: store });
@@ -1503,6 +1513,9 @@ export class AUNClient {
1503
1513
  await this.completeOrgTransfer(transfer.source_params, { aidStore: store });
1504
1514
  continue;
1505
1515
  }
1516
+ const orgManager = store._agentMdManager;
1517
+ if (String((orgManager?._loadRecord?.(aid, true) ?? orgManager?.loadRecord?.(aid))?.local_draft_content ?? ''))
1518
+ continue;
1506
1519
  const pending = store._agentMdManager.pendingUpload(aid);
1507
1520
  if (!pending)
1508
1521
  continue;
@@ -1522,20 +1535,29 @@ export class AUNClient {
1522
1535
  const transferId = String(params.transfer_id ?? '').trim();
1523
1536
  if (!store || !owner?.isPrivateKeyValid() || !orgAid || !transferId)
1524
1537
  throw new ValidationError('completeOrgTransfer requires aidStore, org_id, transfer_id and current accepting owner');
1538
+ for (const field of ['previous_owner', 'new_owner']) {
1539
+ const material = params[field];
1540
+ if (!isJsonObject(material) || !isJsonObject(material.membership_binding) || !isJsonObject(material.terms) || field === 'previous_owner' && !isJsonObject(material.credential_template))
1541
+ throw ownershipFailure('invalid', 'Org transfer requires both replacement membership bindings, terms and previous-owner credential');
1542
+ }
1525
1543
  this._aidStore = store;
1526
1544
  const localStore = store._keystore;
1527
1545
  const tokenStore = store._tokenStore;
1528
1546
  const pendingKey = `org-transfer:${orgAid}:${transferId}`;
1529
1547
  const inputHash = crypto.createHash('sha256').update(canonicalJson(params)).digest('hex');
1548
+ let pending = tokenStore.loadMetadata(orgAid)?.org_identity_transfer;
1549
+ if (pending && (pending.transfer_id !== transferId || pending.owner_aid !== owner.aid || pending.input_hash !== inputHash))
1550
+ throw ownershipFailure('conflict', 'pending Org transfer context changed');
1530
1551
  let keyPair = localStore.loadPendingGroupBind(pendingKey);
1531
1552
  if (!keyPair) {
1553
+ if (pending)
1554
+ throw ownershipFailure('persistence_unavailable', 'Org transfer private key checkpoint is unavailable');
1532
1555
  keyPair = new CryptoProvider().generateIdentity();
1533
1556
  localStore.savePendingGroupBind(pendingKey, keyPair);
1534
1557
  }
1535
1558
  const target = options.serviceAid ?? `org.${orgAid.slice(orgAid.indexOf('.') + 1)}`;
1536
1559
  const publicKey = crypto.createPublicKey({ key: Buffer.from(keyPair.public_key_der_b64, 'base64'), format: 'der', type: 'spki' }).export({ format: 'pem', type: 'spki' }).toString();
1537
- let pending = tokenStore.loadMetadata(orgAid)?.org_identity_transfer;
1538
- if (pending && (pending.transfer_id !== transferId || pending.owner_aid !== owner.aid || pending.public_key !== publicKey || pending.input_hash !== inputHash))
1560
+ if (pending && pending.public_key !== publicKey)
1539
1561
  throw ownershipFailure('conflict', 'pending Org transfer context changed');
1540
1562
  if (!pending) {
1541
1563
  const rekey = { ...params, stage: 'rekey', public_key: publicKey, curve: 'P-256' };
@@ -1584,8 +1606,8 @@ export class AUNClient {
1584
1606
  }
1585
1607
  const result = await this.call('org.lifecycle.transferAccept', pending.finalize_params);
1586
1608
  await this._uploadOrgAgentMd(store, orgAid, pending.source_params);
1587
- localStore.clearPendingGroupBind(pendingKey);
1588
1609
  tokenStore.saveMetadata(orgAid, { org_identity_transfer: null });
1610
+ localStore.clearPendingGroupBind(pendingKey);
1589
1611
  return result;
1590
1612
  }
1591
1613
  async dissolveOrg(params = {}, options = {}) {
@@ -2443,7 +2465,8 @@ export class AUNClient {
2443
2465
  return;
2444
2466
  this._readStateCache.set(key, { method, params: query, state: { ...eventData } });
2445
2467
  }
2446
- this._dispatcher.enqueue(scope === 'group' ? 'group.read_changed' : 'message.read_changed', eventData);
2468
+ const identity = this._ensureReadStateIdentity();
2469
+ this._dispatcher.enqueue(scope === 'group' ? 'group.read_changed' : 'message.read_changed', eventData, () => identity === this._ensureReadStateIdentity());
2447
2470
  }
2448
2471
  async _reconcileReadStates() {
2449
2472
  const identity = this._ensureReadStateIdentity();
@@ -2475,7 +2498,7 @@ export class AUNClient {
2475
2498
  owner_aid: this._aid ?? '',
2476
2499
  states: [...keys].map((key) => ({ ...this._readStateCache.get(key).state })),
2477
2500
  errors,
2478
- });
2501
+ }, () => identity === this._ensureReadStateIdentity());
2479
2502
  }
2480
2503
  async _callRawV2Rpc(method, params, pullGateKey = '') {
2481
2504
  const p = { ...(params ?? {}) };
@@ -3015,8 +3038,13 @@ export class AUNClient {
3015
3038
  try {
3016
3039
  if (opts.signedAt === undefined)
3017
3040
  await this._auth.verifyPeerCertificate(peerGatewayUrl, certPem, aid);
3018
- else
3041
+ else if (opts.agentMdRead) {
3042
+ validateAgentMdCertificate(certPem, aid, opts.signedAt, { requireCurrentValidity: false, readCompatibility: true });
3043
+ await this._auth._verifyAuthCertChain(peerGatewayUrl, new crypto.X509Certificate(certPem), aid, opts.signedAt);
3044
+ }
3045
+ else {
3019
3046
  await this._auth.verifyPeerCertificate(peerGatewayUrl, certPem, aid, opts.signedAt);
3047
+ }
3020
3048
  }
3021
3049
  catch (exc) {
3022
3050
  if (cachedBootstrapChain) {
@@ -3030,7 +3058,7 @@ export class AUNClient {
3030
3058
  validatedAt: nowSec,
3031
3059
  refreshAfter: nowSec + PEER_CERT_CACHE_TTL,
3032
3060
  };
3033
- const cacheKey = AUNClient._certCacheKey(aid, certFingerprint) + (opts.signedAt === undefined ? '' : `:signed:${opts.signedAt}`);
3061
+ const cacheKey = AUNClient._certCacheKey(aid, certFingerprint) + (opts.signedAt === undefined ? '' : `:signed:${opts.signedAt}${opts.agentMdRead ? ':agentmd' : ''}`);
3034
3062
  this._certCache.set(cacheKey, entry);
3035
3063
  if (!certFingerprint && opts.signedAt === undefined) {
3036
3064
  const bareKey = AUNClient._certCacheKey(aid);
@@ -3040,7 +3068,7 @@ export class AUNClient {
3040
3068
  }
3041
3069
  try {
3042
3070
  // peer 证书只存版本目录,不覆盖 cert.pem
3043
- this._tokenStore.saveCert(aid, certPem, certFingerprint, { makeActive: false });
3071
+ this._tokenStore.saveCert(aid, certPem, opts.agentMdRead && opts.signedAt !== undefined ? `sha256:${x509Cert.fingerprint256.replace(/:/g, '').toLowerCase()}` : certFingerprint, { makeActive: false });
3044
3072
  }
3045
3073
  catch (exc) {
3046
3074
  this._clientLog.error(`failed to write cert to keystore (aid=${aid}, fp=${certFingerprint ?? ''}): ${formatCaughtError(exc)}`, exc instanceof Error ? exc : undefined);
@@ -3055,11 +3083,11 @@ export class AUNClient {
3055
3083
  return certificate;
3056
3084
  }
3057
3085
  /** 获取对方证书(带缓存 + 完整 PKI 验证),跨域时自动路由到 peer 所在域。 */
3058
- async _fetchPeerCert(aid, certFingerprint, timeoutMs = 30_000, signedAt) {
3086
+ async _fetchPeerCert(aid, certFingerprint, timeoutMs = 30_000, signedAt, agentMdRead = false) {
3059
3087
  const tStart = Date.now();
3060
3088
  this._clientLog.debug(`_fetchPeerCert enter: aid=${aid}, fp=${certFingerprint ?? ''}`);
3061
3089
  try {
3062
- const cacheKey = AUNClient._certCacheKey(aid, certFingerprint) + (signedAt === undefined ? '' : `:signed:${signedAt}`);
3090
+ const cacheKey = AUNClient._certCacheKey(aid, certFingerprint) + (signedAt === undefined ? '' : `:signed:${signedAt}${agentMdRead ? ':agentmd' : ''}`);
3063
3091
  const cached = this._certCache.get(cacheKey);
3064
3092
  const now = Date.now() / 1000;
3065
3093
  if (cached && now < cached.refreshAfter) {
@@ -3078,6 +3106,7 @@ export class AUNClient {
3078
3106
  certFingerprint,
3079
3107
  source: 'fetch',
3080
3108
  signedAt,
3109
+ agentMdRead,
3081
3110
  });
3082
3111
  this._clientLog.debug(`_fetchPeerCert exit: elapsed=${Date.now() - tStart}ms aid=${aid} (fetched)`);
3083
3112
  return validated;