@agentunion/fastaun 0.5.32 → 0.5.33

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.js CHANGED
@@ -54,7 +54,7 @@ import { AID } from './aid.js';
54
54
  import { certFingerprint, certMatchesFingerprint, normalizeFingerprintHex, publicKeyMatchesFingerprint } from './cert-utils.js';
55
55
  import { validateAgentMdCertificate, validateAgentMdDocument, validateAgentMdReadDocument } from './agent-md-schema.js';
56
56
  import { OwnershipFiles, OwnershipStorageAdapter, ownershipAid, ownershipFailure, ownershipSha256, parseOwnershipFile, signOwnershipFile } from './ownership-v21.js';
57
- import { OwnershipWorkflow, OWNERSHIP_SDK_MESSAGE_TYPE, parseOwnershipMessage } from './ownership-workflow.js';
57
+ import { ownershipApprovalBatch, OwnershipWorkflow, OWNERSHIP_SDK_MESSAGE_TYPE, parseOwnershipMessage } from './ownership-workflow.js';
58
58
  import { canonicalJson, createCredential, createMemberCredential, signMembershipBinding, digest, validateMembershipBinding, verifyMembershipBinding, verifyCredentialSignature, createRepresentationProof, verifyServiceEvent, buildRequestBinding, validateRequestBinding, CredentialRenewal } from './org-protocol.js';
59
59
  import { SemanticProtocolError } from './semantic-protocol.js';
60
60
  function isPromiseLike(value) {
@@ -523,7 +523,16 @@ export class AUNClient {
523
523
  currentType: () => this.getType(), assertCurrent: () => this._ownershipOperationGuard?.(),
524
524
  recoverRequest: (operationId) => this._recoverOwnershipRequest(operationId),
525
525
  send: (to, payload, messageId) => this.call('message.send', { to, encrypt: true, message_id: messageId, payload: payload }),
526
- emit: (event, payload) => { this._ownershipConsensusCache = new Map(); this._dispatcher.enqueue(event, payload); },
526
+ emit: (event, payload) => {
527
+ this._ownershipConsensusCache = new Map();
528
+ if (typeof payload.sub_aid === 'string') {
529
+ try {
530
+ this._agentMdManager.updateRecord(payload.sub_aid, (record) => { delete record.ownership_snapshot; });
531
+ }
532
+ catch { }
533
+ }
534
+ this._dispatcher.enqueue(event, payload);
535
+ },
527
536
  });
528
537
  }
529
538
  async _recoverOwnershipRequest(operationId) {
@@ -1333,8 +1342,8 @@ export class AUNClient {
1333
1342
  get_ownership_status() {
1334
1343
  return this.getOwnershipStatus();
1335
1344
  }
1336
- async bindOwneraid(ownerAid) { return this._getOwnershipWorkflow().bindOwneraid(ownerAid); }
1337
- async bindSubaid(subAid) { return this._getOwnershipWorkflow().bindSubaid(subAid); }
1345
+ async bindOwneraid(ownerAid, options) { return this._getOwnershipWorkflow().bindOwneraid(ownerAid, options); }
1346
+ async bindSubaid(subAid, options) { return this._getOwnershipWorkflow().bindSubaid(subAid, options); }
1338
1347
  async bindLocalSubaid(subClient) { return this._localOwnershipOperation(subClient); }
1339
1348
  async transferLocalSubaid(subClient, newOwnerClient) { return this._localOwnershipOperation(subClient, newOwnerClient); }
1340
1349
  _createOwnershipOperationClient(slotId) {
@@ -1383,24 +1392,34 @@ export class AUNClient {
1383
1392
  }
1384
1393
  }
1385
1394
  async releaseSubaid(subAid) { return this._getOwnershipWorkflow().releaseSubaid(subAid); }
1386
- async transferSubaid(subAid, newOwnerAid) { return this._getOwnershipWorkflow().transferSubaid(subAid, newOwnerAid); }
1395
+ async transferSubaid(subAid, newOwnerAid, options) { return this._getOwnershipWorkflow().transferSubaid(subAid, newOwnerAid, options); }
1387
1396
  async checkOwnershipConsensus(subAid, force = false) {
1388
1397
  const target = ownershipAid(subAid ?? this._aid, 'sub_aid');
1389
- const record = this._agentMdManager.loadRecord(target);
1398
+ const manager = this._agentMdManager;
1399
+ const record = manager.loadRecord(target);
1390
1400
  const observedEtag = String(record?.remote_etag ?? '');
1401
+ const observation = { root: manager.root, etag: observedEtag, version: Number(record?.observation_version ?? 0), content_hash: typeof record?.content === 'string' ? ownershipSha256(record.content) : '' };
1391
1402
  const cache = this._ownershipConsensusCache ??= new Map();
1392
1403
  const cached = cache.get(target);
1393
1404
  if (!force && cached?.result.status === 'consensus' && record?.remote_status !== 'missing'
1394
- && (observedEtag === cached.observedEtag || observedEtag === cached.result.agent_md_etag)) {
1405
+ && (observedEtag === cached.observedEtag || observedEtag === cached.result.agent_md_etag)
1406
+ && (typeof record?.content !== 'string' || ownershipSha256(record.content) === cached.result.agent_md_sha256)) {
1395
1407
  cached.observedEtag = observedEtag;
1396
1408
  return { ...cached.result };
1397
1409
  }
1410
+ if (!force && !cached) {
1411
+ const local = manager.localOwnershipConsensus(target, record);
1412
+ if (local) {
1413
+ cache.set(target, { observedEtag, result: local });
1414
+ return { ...local };
1415
+ }
1416
+ }
1398
1417
  cache.delete(target);
1399
1418
  const result = { status: 'unavailable', sub_aid: target, owner_aid: null, relation_version: 0, lock: 'unlocked', agent_md_etag: '', agent_md_sha256: '' };
1400
1419
  const entry = { observedEtag, result: { ...result } };
1401
1420
  cache.set(target, entry);
1402
1421
  try {
1403
- const snapshot = await this._agentMdManager.readOwnershipFresh(target);
1422
+ const snapshot = await manager.readOwnershipFresh(target);
1404
1423
  Object.assign(result, { relation_version: snapshot.relation_version, lock: snapshot.lock, agent_md_etag: snapshot.etag,
1405
1424
  agent_md_sha256: snapshot.exists ? ownershipSha256(snapshot.content) : '' });
1406
1425
  if (snapshot.ownership_status)
@@ -1420,8 +1439,13 @@ export class AUNClient {
1420
1439
  result.reason = error instanceof Error ? error.message : String(error);
1421
1440
  result.retryable = result.status === 'unavailable';
1422
1441
  }
1423
- if (cache.get(target) === entry)
1442
+ if (this._agentMdManager === manager && this._ownershipConsensusCache === cache && cache.get(target) === entry) {
1424
1443
  entry.result = { ...result };
1444
+ try {
1445
+ manager.cacheOwnershipSnapshot(target, result, observation);
1446
+ }
1447
+ catch { }
1448
+ }
1425
1449
  return result;
1426
1450
  }
1427
1451
  async _checkOwnershipConsensusFresh(subAid) {
@@ -1437,6 +1461,20 @@ export class AUNClient {
1437
1461
  async bind_owner(ownerAid, options = {}) { return this.bindOwner(ownerAid, options); }
1438
1462
  async releaseOwnership(subjectAid) { throw ownershipFailure('unsupported_protocol', 'legacy releaseOwnership is unsupported; use releaseSubaid'); }
1439
1463
  async release_ownership(subjectAid) { return this.releaseOwnership(subjectAid); }
1464
+ async acceptOwnershipRequests(operationIds) {
1465
+ return this._approveOwnershipRequests(operationIds);
1466
+ }
1467
+ async rejectOwnershipRequests(operationIds, reason) {
1468
+ return this._approveOwnershipRequests(operationIds, true, reason);
1469
+ }
1470
+ async _approveOwnershipRequests(operationIds, reject = false, reason) {
1471
+ const aid = this._aid, generation = this._serviceEventIdentityVersion;
1472
+ return ownershipApprovalBatch(operationIds, async (operationId) => {
1473
+ if (this._aid !== aid || this._serviceEventIdentityVersion !== generation)
1474
+ throw new StateError('ownership approval identity changed', { stringCode: 'conflict' });
1475
+ return reject ? this.rejectOwnershipRequest(operationId, reason) : this.acceptOwnershipRequest(operationId);
1476
+ });
1477
+ }
1440
1478
  async acceptOwnershipRequest(operationId) {
1441
1479
  return this._getOwnershipWorkflow().acceptOwnershipRequest(operationId);
1442
1480
  }
@@ -2028,6 +2066,9 @@ export class AUNClient {
2028
2066
  if (!pending?.private_key_pem || !pending.public_key_der_b64)
2029
2067
  return false;
2030
2068
  }
2069
+ const local = this._agentMdManager.localOwnershipConsensus(target, this._agentMdManager.loadRecord(target));
2070
+ if (local?.owner_aid === this._aid)
2071
+ return true;
2031
2072
  const result = await this._entityLifecycle(target, type);
2032
2073
  const data = result;
2033
2074
  const entity = (isJsonObject(data.group) ? data.group : isJsonObject(data.organization) ? data.organization : data);
@@ -2040,7 +2081,7 @@ export class AUNClient {
2040
2081
  return await existing;
2041
2082
  this._entityOwnershipChecks.set(`${identity}:${aid}`, task);
2042
2083
  }
2043
- const consensus = await this.checkOwnershipConsensus(aid, true);
2084
+ const consensus = await this.checkOwnershipConsensus(aid);
2044
2085
  if (consensus.status === 'consensus' && consensus.owner_aid === this._aid)
2045
2086
  return true;
2046
2087
  await this._completeEntityOwnership(aid, type, undefined, () => {
@@ -2201,12 +2242,19 @@ export class AUNClient {
2201
2242
  if (!aid)
2202
2243
  return;
2203
2244
  try {
2204
- const checked = await this._agentMdManager.check(aid, 0);
2205
- if (!checked.remote_found) {
2206
- await this._ensureInitialAgentMd();
2207
- }
2208
- else if (checked.in_sync === false) {
2209
- await this._agentMdManager.download(aid);
2245
+ const record = this._agentMdManager.loadRecord(aid);
2246
+ const verified = record?.verified_agent_md;
2247
+ const local = record?.content && record.remote_status !== 'missing' && record.remote_etag
2248
+ && (record.local_etag === record.remote_etag || record.verify_status === 'verified' && verified?.etag === record.remote_etag && verified.content_hash === record.local_etag
2249
+ || this._agentMdManager.localOwnershipConsensus(aid, record));
2250
+ if (!local) {
2251
+ const checked = await this._agentMdManager.check(aid, 0);
2252
+ if (!checked.remote_found) {
2253
+ await this._ensureInitialAgentMd();
2254
+ }
2255
+ else if (checked.in_sync === false) {
2256
+ await this._agentMdManager.download(aid);
2257
+ }
2210
2258
  }
2211
2259
  }
2212
2260
  catch (exc) {