@agentunion/fastaun 0.5.26 → 0.5.28

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 (94) hide show
  1. package/CHANGELOG.md +77 -0
  2. package/_packed_docs/CHANGELOG.md +77 -0
  3. package/_packed_docs/INDEX.md +37 -14
  4. package/_packed_docs/KITE_DOCS_GUIDE.md +23 -15
  5. package/_packed_docs/aun/345/210/206/345/270/203/345/274/217/346/265/213/350/257/225/350/277/220/350/241/214/346/214/207/345/215/227.md +16 -1
  6. package/_packed_docs/aun/346/265/213/350/257/225/350/277/220/350/241/214/346/214/207/345/215/227.md +37 -9
  7. package/_packed_docs/cli/AUN-CLI/350/256/276/350/256/241/346/226/207/346/241/243.md +20 -9
  8. package/_packed_docs/cli/CLI/346/211/213/345/206/214.md +57 -12
  9. package/_packed_docs/sdk/0.5.22-SDK/345/274/200/345/217/221/344/270/216/347/247/273/346/244/215/346/214/207/345/215/227.md +2 -2
  10. package/_packed_docs/sdk/06-API/346/211/213/345/206/214.md +2 -2
  11. package/_packed_docs/sdk/09-/345/207/255/350/257/201/346/234/215/345/212/241RPC/346/211/213/345/206/214.md +187 -73
  12. package/_packed_docs/sdk/09-/347/273/204/347/273/207/346/234/215/345/212/241RPC/346/211/213/345/206/214.md +1 -1
  13. package/_packed_docs/sdk/AUN_DOCS_GUIDE.md +13 -9
  14. package/_packed_docs/sdk/INDEX.md +23 -13
  15. 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 +973 -266
  16. 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 +950 -242
  17. package/dist/agent-md-changes.d.ts +42 -0
  18. package/dist/agent-md-changes.js +339 -0
  19. package/dist/agent-md-changes.js.map +1 -0
  20. package/dist/agent-md-schema.d.ts +1 -0
  21. package/dist/agent-md-schema.js +31 -14
  22. package/dist/agent-md-schema.js.map +1 -1
  23. package/dist/agent-md.d.ts +11 -0
  24. package/dist/agent-md.js +91 -15
  25. package/dist/agent-md.js.map +1 -1
  26. package/dist/aid-store.d.ts +11 -0
  27. package/dist/aid-store.js +102 -21
  28. package/dist/aid-store.js.map +1 -1
  29. package/dist/aid.js +3 -3
  30. package/dist/aid.js.map +1 -1
  31. package/dist/auth.d.ts +10 -0
  32. package/dist/auth.js +65 -23
  33. package/dist/auth.js.map +1 -1
  34. package/dist/cert-utils.d.ts +1 -1
  35. package/dist/cert-utils.js +4 -4
  36. package/dist/cert-utils.js.map +1 -1
  37. package/dist/client/control-messages.d.ts +31 -0
  38. package/dist/client/control-messages.js +474 -0
  39. package/dist/client/control-messages.js.map +1 -0
  40. package/dist/client/delivery.js +10 -2
  41. package/dist/client/delivery.js.map +1 -1
  42. package/dist/client/lifecycle.d.ts +1 -1
  43. package/dist/client/lifecycle.js +10 -0
  44. package/dist/client/lifecycle.js.map +1 -1
  45. package/dist/client/rpc-pipeline.js +84 -14
  46. package/dist/client/rpc-pipeline.js.map +1 -1
  47. package/dist/client/v2-e2ee.d.ts +3 -0
  48. package/dist/client/v2-e2ee.js +12 -0
  49. package/dist/client/v2-e2ee.js.map +1 -1
  50. package/dist/client.d.ts +38 -0
  51. package/dist/client.js +572 -36
  52. package/dist/client.js.map +1 -1
  53. package/dist/discovery.d.ts +3 -0
  54. package/dist/discovery.js +52 -2
  55. package/dist/discovery.js.map +1 -1
  56. package/dist/events.js +14 -1
  57. package/dist/events.js.map +1 -1
  58. package/dist/facades.d.ts +38 -0
  59. package/dist/facades.js +49 -5
  60. package/dist/facades.js.map +1 -1
  61. package/dist/index.d.ts +4 -0
  62. package/dist/index.js +3 -0
  63. package/dist/index.js.map +1 -1
  64. package/dist/org-protocol.d.ts +1 -0
  65. package/dist/org-protocol.js +39 -36
  66. package/dist/org-protocol.js.map +1 -1
  67. package/dist/ownership-v21.js +7 -7
  68. package/dist/ownership-v21.js.map +1 -1
  69. package/dist/register-flow.js +2 -2
  70. package/dist/register-flow.js.map +1 -1
  71. package/dist/risk-control.d.ts +68 -0
  72. package/dist/risk-control.js +344 -0
  73. package/dist/risk-control.js.map +1 -0
  74. package/dist/semantic-facade.d.ts +176 -0
  75. package/dist/semantic-facade.js +611 -0
  76. package/dist/semantic-facade.js.map +1 -0
  77. package/dist/semantic-protocol.d.ts +810 -0
  78. package/dist/semantic-protocol.js +894 -0
  79. package/dist/semantic-protocol.js.map +1 -0
  80. package/dist/storage/lowlevel.d.ts +1 -0
  81. package/dist/storage/lowlevel.js +2 -2
  82. package/dist/storage/lowlevel.js.map +1 -1
  83. package/dist/tools/cross-sdk-agent.d.ts +11 -1
  84. package/dist/tools/cross-sdk-agent.js +388 -7
  85. package/dist/tools/cross-sdk-agent.js.map +1 -1
  86. package/dist/transport.d.ts +22 -1
  87. package/dist/transport.js +227 -22
  88. package/dist/transport.js.map +1 -1
  89. package/dist/v2/e2ee/decrypt.d.ts +5 -0
  90. package/dist/v2/e2ee/decrypt.js +22 -2
  91. package/dist/v2/e2ee/decrypt.js.map +1 -1
  92. package/dist/version.d.ts +1 -1
  93. package/dist/version.js +1 -1
  94. package/package.json +1 -1
@@ -133,7 +133,7 @@ export class CredentialRenewal {
133
133
  if (proof.ver !== 'aun-membership-status/1' || proof.org_id !== credential.iss || proof.member_aid !== actor || proof.credential_cid !== credential.cid
134
134
  || proof.membership_id !== binding.membership_id || proof.role !== binding.role || proof.version !== member.version
135
135
  || proof.status !== 'active' || proof.credential_status !== 'active' || proof.responder !== service || proof.target !== actor || proof.request_id !== query.request_id || proof.nonce !== query.nonce
136
- || !isInt(proof.as_of) || proof.as_of > now + 300 || !isInt(proof.expires_at) || proof.expires_at <= now || proof.expires_at <= proof.as_of || proof.expires_at > proof.as_of + 300
136
+ || !isInt(proof.as_of) || proof.as_of > now + 300 || !isInt(proof.expires_at) || now > proof.expires_at + 300 || proof.expires_at <= proof.as_of || proof.expires_at > proof.as_of + 300
137
137
  || !isRecord(proof.signature) || proof.signature.timestamp !== proof.as_of)
138
138
  throw invalid('current membership proof does not match the query');
139
139
  const cert = await this.ports.certificate(service, String(proof.signature.cert_fingerprint));
@@ -231,9 +231,9 @@ export class CredentialRenewal {
231
231
  verifyMembershipBinding(binding, resolve, now, String(orgSigner), true);
232
232
  check();
233
233
  const service = 'credential.' + String(payload.org_id).split('.').slice(1).join('.');
234
- if (!isInt(receipt.registered_at) || !isInt(receipt.exp) || receipt.exp > receipt.registered_at + 300 || receipt.registered_at > now)
234
+ if (!isInt(receipt.registered_at) || !isInt(receipt.exp) || receipt.exp > receipt.registered_at + 300 || receipt.registered_at > now + 300)
235
235
  throw invalid('membership receipt window is invalid');
236
- const late = now >= receipt.exp;
236
+ const late = now > receipt.exp + 300;
237
237
  verifyRegistrationReceipt(receipt, credential, { request_id: binding.request_id, nonce: binding.nonce, registrar_aid: payload.org_id }, resolve, service, late ? receipt.registered_at : now);
238
238
  check();
239
239
  const validUntil = Math.min(Number(credential.exp), late ? await this.status(credential, actor, false, receipt.registered_at) : receipt.exp);
@@ -245,7 +245,7 @@ export class CredentialRenewal {
245
245
  return;
246
246
  const issuerCertificate = certificates.get(String(credential.signature.cert_fingerprint));
247
247
  await this.rememberNow(credential, { membership_binding: binding, registrationReceipt: receipt, terms, version: payload.version,
248
- service_aid: 'org.' + String(payload.org_id).split('.').slice(1).join('.'), long_term: credential.exp === Math.floor(Date.parse(new X509Certificate(issuerCertificate).validTo) / 1000) }, actor, { ...guard, current: () => guard.current() && Date.now() / 1000 < validUntil });
248
+ service_aid: 'org.' + String(payload.org_id).split('.').slice(1).join('.'), long_term: credential.exp === Math.floor(Date.parse(new X509Certificate(issuerCertificate).validTo) / 1000) }, actor, { ...guard, current: () => guard.current() && Date.now() / 1000 <= validUntil + 300 });
249
249
  });
250
250
  }
251
251
  observe(method, params, result) {
@@ -298,7 +298,7 @@ export class CredentialRenewal {
298
298
  }
299
299
  if (initial.submission && initial.received_result && !initial.successor_cid)
300
300
  await this.receiveNow(String(initial.credential.iss), initial.received_result, undefined, true);
301
- else if (initial.incoming?.payload.exp > Math.trunc(Date.now() / 1000))
301
+ else if (initial.incoming && Math.trunc(Date.now() / 1000) <= initial.incoming.payload.exp + 300)
302
302
  await this.receiveNow(initial.incoming.from, initial.incoming.payload);
303
303
  const record = (await this.ports.load(actor))[cid];
304
304
  if (record.commit_pending)
@@ -370,7 +370,7 @@ export class CredentialRenewal {
370
370
  }
371
371
  async verifyEnvelope(from, payload, expected, replay = false) {
372
372
  const now = Math.trunc(Date.now() / 1000);
373
- if (from !== expected || payload.ver !== 'aun-credential-renewal/1' || !isInt(payload.iat) || !isInt(payload.exp) || payload.iat > (replay ? payload.iat : now) || payload.exp <= (replay ? payload.iat : now) || payload.exp > payload.iat + 300 || !isRecord(payload.signature))
373
+ if (from !== expected || payload.ver !== 'aun-credential-renewal/1' || !isInt(payload.iat) || !isInt(payload.exp) || payload.exp <= payload.iat || !replay && (now < payload.iat - 300 || now > payload.exp + 300) || payload.exp > payload.iat + 300 || !isRecord(payload.signature))
374
374
  throw invalid('renewal message identity or validity is invalid');
375
375
  const cert = await this.ports.certificate(expected, String(payload.signature.cert_fingerprint));
376
376
  const unsigned = { ...payload };
@@ -395,7 +395,7 @@ export class CredentialRenewal {
395
395
  if (!isRecord(proof) || proof.ver !== 'aun-credential-status/1' || proof.credentialCid !== credential.cid || proof.credential_hash !== digest(credential)
396
396
  || proof.issuerAid !== credential.iss || proof.subjectAid !== credential.sub || proof.expiresAt !== credential.exp || proof.responder !== target
397
397
  || proof.request_id !== query.request_id || proof.nonce !== query.nonce || proof.target !== actor
398
- || !isInt(proof.asOf) || !isInt(proof.proofExpiresAt) || proof.asOf > now + 300 || proof.proofExpiresAt <= proof.asOf || proof.proofExpiresAt <= now || proof.proofExpiresAt > proof.asOf + 300
398
+ || !isInt(proof.asOf) || !isInt(proof.proofExpiresAt) || proof.asOf > now + 300 || proof.proofExpiresAt <= proof.asOf || now > proof.proofExpiresAt + 300 || proof.proofExpiresAt > proof.asOf + 300
399
399
  || !isRecord(proof.signature) || proof.signature.timestamp !== proof.asOf)
400
400
  throw new ProtocolError('CREDENTIAL_STATUS_UNKNOWN', 'renewal status proof does not match the query');
401
401
  const cert = await this.ports.certificate(target, String(proof.signature.cert_fingerprint));
@@ -404,7 +404,7 @@ export class CredentialRenewal {
404
404
  verifyAgentSignature(proof.signature, unsigned, target, () => cert, now, false);
405
405
  if (proof.status !== 'active' && !(allowExpired && proof.status === 'expired' && proof.credentialStatus === 'expired' && Array.isArray(proof.chain) && proof.chain.every((item) => item.status === 'active')))
406
406
  throw new ProtocolError('CREDENTIAL_STATUS_UNKNOWN', 'renewal credential is not active');
407
- if (registrationConfirmedAt !== undefined && (proof.asOf < requestedAt || proof.asOf > now || !isInt(proof.registrationConfirmedAt) || proof.registrationConfirmedAt < registrationConfirmedAt || proof.registrationConfirmedAt > proof.asOf || proof.credentialStatus !== 'active' || proof.proofExpiresAt <= Math.trunc(Date.now() / 1000)))
407
+ if (registrationConfirmedAt !== undefined && (proof.asOf < requestedAt - 300 || proof.asOf > now + 300 || !isInt(proof.registrationConfirmedAt) || proof.registrationConfirmedAt < registrationConfirmedAt - 300 || proof.registrationConfirmedAt > proof.asOf || proof.credentialStatus !== 'active' || Math.trunc(Date.now() / 1000) > proof.proofExpiresAt + 300))
408
408
  throw new ProtocolError('CREDENTIAL_STATUS_UNKNOWN', 'membership registration confirmation is invalid');
409
409
  if (confirmation)
410
410
  Object.assign(confirmation, structuredClone(proof));
@@ -414,7 +414,7 @@ export class CredentialRenewal {
414
414
  if (!isRecord(value) || !['credential.renewal.request', 'credential.renewal.result'].includes(String(value.type)))
415
415
  return false;
416
416
  const payload = value;
417
- if (!replay && isInt(payload.exp) && payload.exp <= Math.trunc(Date.now() / 1000))
417
+ if (!replay && isInt(payload.exp) && Math.trunc(Date.now() / 1000) > payload.exp + 300)
418
418
  return true;
419
419
  const isRequest = payload.type === 'credential.renewal.request';
420
420
  const actor = localIssuer ?? this.ports.currentAid();
@@ -614,8 +614,8 @@ export class CredentialRenewal {
614
614
  if (!isRecord(proof) || proof.ver !== 'aun-membership-status/1' || proof.org_id !== credential.iss || proof.member_aid !== actor || proof.credential_cid !== credential.cid
615
615
  || proof.membership_id !== params.membership_binding.membership_id || proof.role !== params.membership_binding.role || proof.version !== Number(params.expected_version) + 1
616
616
  || proof.status !== 'active' || proof.credential_status !== 'active' || proof.responder !== record.service_aid || proof.target !== actor || proof.request_id !== query.request_id || proof.nonce !== query.nonce
617
- || !isInt(proof.as_of) || proof.as_of < Number(query.request_binding.iat) || proof.as_of > now || !isInt(proof.expires_at) || proof.expires_at <= now || proof.expires_at > proof.as_of + 300
618
- || !isRecord(proof.signature) || proof.signature.timestamp !== proof.as_of || proofExpiresAt <= now)
617
+ || !isInt(proof.as_of) || proof.as_of < Number(query.request_binding.iat) - 300 || proof.as_of > now + 300 || !isInt(proof.expires_at) || now > proof.expires_at + 300 || proof.expires_at > proof.as_of + 300
618
+ || !isRecord(proof.signature) || proof.signature.timestamp !== proof.as_of || now > proofExpiresAt + 300)
619
619
  throw invalid('renewal membership confirmation is invalid');
620
620
  const cert = await this.ports.certificate(record.service_aid, String(proof.signature.cert_fingerprint));
621
621
  const unsigned = { ...proof };
@@ -660,7 +660,7 @@ export class CredentialRenewal {
660
660
  records[cid].successor_cid = credential.cid;
661
661
  records[cid].response = structuredClone(payload);
662
662
  records[cid].commit_pending = true;
663
- const recoveryGuard = { current: () => Date.now() / 1000 >= Number(credential.nbf) && Date.now() / 1000 < Math.min(recoveryValidUntil, Number(credential.exp)) };
663
+ const recoveryGuard = { current: () => Date.now() / 1000 >= Number(credential.nbf) - 300 && Date.now() / 1000 <= Math.min(recoveryValidUntil, Number(credential.exp)) + 300 };
664
664
  if (!recoveryGuard.current())
665
665
  throw invalid('renewal recovery confirmation has expired');
666
666
  await this.ports.save(actor, records, recoveryGuard);
@@ -687,7 +687,7 @@ export class CredentialRenewal {
687
687
  const validUntil = await this.status(credential, actor, false, record.registration_submitted_at, confirmation);
688
688
  records[String(credential.cid)] = { credential: structuredClone(credential), long_term: true, issued: true };
689
689
  records[cid].registration_confirmation = confirmation;
690
- const guard = { current: () => Date.now() / 1000 >= Number(credential.nbf) && Date.now() / 1000 < Math.min(validUntil, Number(credential.exp)) };
690
+ const guard = { current: () => Date.now() / 1000 >= Number(credential.nbf) - 300 && Date.now() / 1000 <= Math.min(validUntil, Number(credential.exp)) + 300 };
691
691
  if (!guard.current())
692
692
  throw invalid('registration recovery confirmation has expired');
693
693
  await this.ports.save(actor, records, guard);
@@ -782,7 +782,7 @@ export class CredentialRenewal {
782
782
  return Promise.resolve();
783
783
  return this.serial(async () => {
784
784
  const actor = this.ports.currentAid();
785
- const current = () => this.ports.currentAid() === actor && guard.current() && Date.now() / 1000 < Number(payload.expires_at);
785
+ const current = () => this.ports.currentAid() === actor && guard.current() && Date.now() / 1000 <= Number(payload.expires_at) + 300;
786
786
  if (!current())
787
787
  throw new ProtocolError('CREDENTIAL_STATUS_UNKNOWN', 'credential revocation event was superseded');
788
788
  const list = payload.type === 'credential.revocationList';
@@ -831,7 +831,7 @@ export class CredentialRenewal {
831
831
  check();
832
832
  const records = await this.ports.load(actor);
833
833
  check();
834
- const authorities = new Set();
834
+ const authorities = new Set(Object.keys(state.authorities));
835
835
  for (const record of Object.values(records)) {
836
836
  if (!isRecord(record) || !isRecord(record.credential))
837
837
  continue;
@@ -869,7 +869,7 @@ export class CredentialRenewal {
869
869
  const now = Math.trunc(Date.now() / 1000);
870
870
  if (!isRecord(proof) || proof.responder !== authority || proof.target !== actor || proof.request_id !== query.request_id || proof.nonce !== query.nonce || proof.issuer_aid !== ''
871
871
  || !Array.isArray(proof.events) || proof.events.length > 1000 || typeof proof.next_cursor !== 'string'
872
- || !isInt(proof.as_of) || proof.as_of <= 0 || proof.as_of > now + 300 || !isInt(proof.expires_at) || proof.expires_at <= now || proof.expires_at <= proof.as_of || proof.expires_at > proof.as_of + 300
872
+ || !isInt(proof.as_of) || proof.as_of <= 0 || proof.as_of > now + 300 || !isInt(proof.expires_at) || now > proof.expires_at + 300 || proof.expires_at <= proof.as_of || proof.expires_at > proof.as_of + 300
873
873
  || !isRecord(proof.signature) || proof.signature.timestamp !== proof.as_of)
874
874
  throw new ProtocolError('CREDENTIAL_STATUS_UNKNOWN', 'revocation list does not match the query');
875
875
  let last = since;
@@ -893,7 +893,7 @@ export class CredentialRenewal {
893
893
  Object.defineProperty(revoked, String(event.cid), { value: Math.max(Object.hasOwn(revoked, String(event.cid)) ? Number(revoked[String(event.cid)]) : 0, Number(event.event_seq)), enumerable: true, configurable: true, writable: true });
894
894
  next.authorities[authority] = { revoked, since_event_seq: proof.next_cursor === '' ? last : Number(proof.next_cursor), cursor: proof.next_cursor, as_of: proof.as_of, expires_at: proof.expires_at };
895
895
  expiresAt = Math.min(expiresAt, Number(proof.expires_at), Date.parse(new X509Certificate(certificate).validTo) / 1000);
896
- const commitGuard = { ...guard, current: () => epoch === this.queryEpoch && scope === this.queryScope() && this.ports.currentAid() === actor && (!guard || guard.current()) && Date.now() / 1000 < expiresAt };
896
+ const commitGuard = { ...guard, current: () => epoch === this.queryEpoch && scope === this.queryScope() && this.ports.currentAid() === actor && (!guard || guard.current()) && Date.now() / 1000 <= expiresAt + 300 };
897
897
  if (!commitGuard.current())
898
898
  throw new ProtocolError('CREDENTIAL_STATUS_UNKNOWN', 'revocation list expired before persistence');
899
899
  await this.ports.saveRevocations(actor, next, commitGuard);
@@ -928,7 +928,7 @@ export async function verifyServiceEvent(eventName, payload, context) {
928
928
  if (typeof context.targetAid !== 'string' || !AID_RE.test(context.targetAid))
929
929
  throw invalid('service event target is invalid');
930
930
  const now = context.now ?? Math.trunc(Date.now() / 1000);
931
- if (!isInt(now) || !isInt(payload.as_of) || !isInt(payload.expires_at) || payload.as_of <= 0 || payload.expires_at <= payload.as_of || payload.expires_at > payload.as_of + 300 || payload.as_of > now + 300 || now >= payload.expires_at)
931
+ if (!isInt(now) || !isInt(payload.as_of) || !isInt(payload.expires_at) || payload.as_of <= 0 || payload.expires_at <= payload.as_of || payload.expires_at > payload.as_of + 300 || payload.as_of > now + 300 || now > payload.expires_at + 300)
932
932
  throw invalid('service event time window is invalid');
933
933
  if (!Array.isArray(payload.target_aids) || !payload.target_aids.length || payload.target_aids.some((target) => typeof target !== 'string' || !AID_RE.test(target)))
934
934
  throw invalid('service event target is invalid');
@@ -970,7 +970,7 @@ export async function verifyServiceEvent(eventName, payload, context) {
970
970
  catch {
971
971
  throw new ProtocolError('CREDENTIAL_SIGNATURE_INVALID', 'service event signature is invalid');
972
972
  }
973
- if ((context.now ?? Math.trunc(Date.now() / 1000)) >= payload.expires_at)
973
+ if ((context.now ?? Math.trunc(Date.now() / 1000)) > payload.expires_at + 300)
974
974
  throw invalid('service event time window is invalid');
975
975
  return { signature_valid: true, credential_known: known };
976
976
  }
@@ -1232,7 +1232,7 @@ function validConstraintRegex(value) {
1232
1232
  }
1233
1233
  return !inside;
1234
1234
  }
1235
- function validateCapability(capability) {
1235
+ export function validateCapability(capability) {
1236
1236
  const constraints = capability.constraints;
1237
1237
  if (!Array.isArray(constraints) || constraints.length > 64)
1238
1238
  throw invalid('capability constraints are invalid');
@@ -1547,7 +1547,7 @@ export function createRepresentationProof(credential, params, binding, signer, p
1547
1547
  return proof;
1548
1548
  }
1549
1549
  export function signTransferAcceptance(proposal, signer) {
1550
- if (!isRecord(proposal) || proposal.ver !== 'aun-org-transfer/1' || proposal.target_member_aid !== signer.aid || !isInt(proposal.exp) || proposal.exp <= Math.trunc(Date.now() / 1000))
1550
+ if (!isRecord(proposal) || proposal.ver !== 'aun-org-transfer/1' || proposal.target_member_aid !== signer.aid || !isInt(proposal.exp) || Math.trunc(Date.now() / 1000) > proposal.exp + 300)
1551
1551
  throw invalid('transfer proposal does not match the accepting identity');
1552
1552
  const payload = { ...proposal };
1553
1553
  delete payload.signature;
@@ -1739,9 +1739,9 @@ export function prepareOrganizationRequest(method, params, target, signer, optio
1739
1739
  throw representationBindingInvalid('invitation rejection requires a distinct action identity');
1740
1740
  value.credentials = credentials;
1741
1741
  const now = Math.trunc(Date.now() / 1000);
1742
- if (now >= Number(binding.exp))
1742
+ if (now > Number(binding.exp) + 300)
1743
1743
  throw representationBindingInvalid('membership binding has expired');
1744
- let exp = Math.min(now + 300, Number(binding.exp));
1744
+ let exp = Number(binding.exp);
1745
1745
  for (const field of ['credential_template', 'registration_authorization'])
1746
1746
  if (field in value) {
1747
1747
  const material = value[field];
@@ -1749,8 +1749,8 @@ export function prepareOrganizationRequest(method, params, target, signer, optio
1749
1749
  throw invalid('admission material expiry is invalid');
1750
1750
  exp = Math.min(exp, material.exp);
1751
1751
  }
1752
- const request = Object.hasOwn(value, 'request_binding') ? value.request_binding : { ver: 'aun-membership-admission-request/1', request_id: value.request_id, nonce: value.nonce, target, method, params_hash: digest(orgRequestBindingParams(method, value)), membership_id: binding.membership_id, iat: now, exp };
1753
- if (!isRecord(request) || Object.keys(request).length !== 9 || Object.keys(request).some((key) => !['ver', 'request_id', 'nonce', 'target', 'method', 'params_hash', 'membership_id', 'iat', 'exp'].includes(key)) || request.ver !== 'aun-membership-admission-request/1' || request.request_id !== value.request_id || request.nonce !== value.nonce || request.target !== target || request.method !== method || request.membership_id !== binding.membership_id || request.params_hash !== digest(orgRequestBindingParams(method, value)) || !isInt(request.iat) || !isInt(request.exp) || request.iat < 0 || request.iat > now || request.iat < Number(binding.iat) || request.exp <= now || request.exp > request.iat + 300 || request.exp > exp)
1752
+ const request = Object.hasOwn(value, 'request_binding') ? value.request_binding : { ver: 'aun-membership-admission-request/1', request_id: value.request_id, nonce: value.nonce, target, method, params_hash: digest(orgRequestBindingParams(method, value)), membership_id: binding.membership_id, iat: now, exp: Math.min(now + 300, exp) };
1753
+ if (!isRecord(request) || Object.keys(request).length !== 9 || Object.keys(request).some((key) => !['ver', 'request_id', 'nonce', 'target', 'method', 'params_hash', 'membership_id', 'iat', 'exp'].includes(key)) || request.ver !== 'aun-membership-admission-request/1' || request.request_id !== value.request_id || request.nonce !== value.nonce || request.target !== target || request.method !== method || request.membership_id !== binding.membership_id || request.params_hash !== digest(orgRequestBindingParams(method, value)) || !isInt(request.iat) || !isInt(request.exp) || request.iat < 0 || request.iat > now + 300 || request.iat < Number(binding.iat) || request.exp <= request.iat || now > request.exp + 300 || request.exp > request.iat + 300 || request.exp > exp)
1754
1754
  throw representationBindingInvalid('admission request binding does not match request');
1755
1755
  value.request_binding = request;
1756
1756
  if (value.for === undefined || value.for === signer.aid)
@@ -1847,7 +1847,7 @@ export function verifyCredential(credential, context) {
1847
1847
  if (isRecord(proof))
1848
1848
  statusProofs.push(proof);
1849
1849
  if (proof != null || document !== value) {
1850
- if (!isRecord(proof) || proof.ver !== 'aun-credential-status/1' || typeof proof.credentialCid !== 'string' || !proof.credentialCid || typeof proof.credential_hash !== 'string' || !DIGEST_RE.test(proof.credential_hash) || !isInt(proof.asOf) || !isInt(proof.proofExpiresAt) || proof.asOf > now + 300 || proof.proofExpiresAt <= proof.asOf || proof.proofExpiresAt > proof.asOf + 300 || now >= proof.proofExpiresAt)
1850
+ if (!isRecord(proof) || proof.ver !== 'aun-credential-status/1' || typeof proof.credentialCid !== 'string' || !proof.credentialCid || typeof proof.credential_hash !== 'string' || !DIGEST_RE.test(proof.credential_hash) || !isInt(proof.asOf) || !isInt(proof.proofExpiresAt) || proof.asOf > now + 300 || proof.proofExpiresAt <= proof.asOf || proof.proofExpiresAt > proof.asOf + 300 || now > proof.proofExpiresAt + 300)
1851
1851
  throw new ProtocolError('CREDENTIAL_STATUS_UNKNOWN', 'trusted credential status proof is invalid');
1852
1852
  if (typeof proof.responder !== 'string' || !AID_RE.test(proof.responder) || !proof.responder.startsWith('credential.') || typeof proof.request_id !== 'string' || !proof.request_id || typeof proof.nonce !== 'string' || !proof.nonce || typeof proof.target !== 'string' || !AID_RE.test(proof.target) || !isRecord(proof.signature) || proof.signature.timestamp !== proof.asOf)
1853
1853
  throw new ProtocolError('CREDENTIAL_STATUS_UNKNOWN', 'trusted credential status proof is incomplete');
@@ -1934,17 +1934,17 @@ export function verifyCredential(credential, context) {
1934
1934
  validateCredentialCapability(credential, { ns: context.ns, action: context.action, resource: context.resource, params: context.params, units: context.units, now: completedAt, client_ip: context.clientIp, proof_chain: context.proofChain }, () => true);
1935
1935
  validateRequestBinding(context.requestBinding, context.method, context.target, context.params ?? {}, String(value.cid), context.nonce ?? '', context.requestId ?? '', completedAt);
1936
1936
  for (const proof of statusProofs) {
1937
- if (proof.asOf > completedAt + 300 || completedAt >= proof.proofExpiresAt)
1937
+ if (proof.asOf > completedAt + 300 || completedAt > proof.proofExpiresAt + 300)
1938
1938
  throw new ProtocolError('CREDENTIAL_STATUS_UNKNOWN', 'trusted credential status proof is invalid');
1939
1939
  }
1940
1940
  for (const material of resolvedCertificates) {
1941
1941
  const certificate = new X509Certificate(certificatePem(material));
1942
- if (completedAt < new Date(certificate.validFrom).getTime() / 1000 || completedAt > new Date(certificate.validTo).getTime() / 1000)
1942
+ if (completedAt < new Date(certificate.validFrom).getTime() / 1000 - 300 || completedAt > new Date(certificate.validTo).getTime() / 1000 + 300)
1943
1943
  throw new ProtocolError('CREDENTIAL_SIGNATURE_INVALID', 'certificate is not valid');
1944
1944
  }
1945
1945
  if (verifiedRepresentation) {
1946
1946
  const { proof, request } = verifiedRepresentation;
1947
- if (completedAt < proof.iat || completedAt >= proof.exp)
1947
+ if (completedAt < proof.iat - 300 || completedAt > proof.exp + 300)
1948
1948
  throw representationBindingInvalid('representation time window is invalid');
1949
1949
  validateRepresentationContext(proof, value, request, completedAt);
1950
1950
  }
@@ -1958,7 +1958,7 @@ export function validateCredentialAt(credential, now, audience, proofChain) {
1958
1958
  const value = credential;
1959
1959
  const nbf = value.nbf;
1960
1960
  const exp = value.exp;
1961
- if (!isInt(nbf) || !isInt(exp) || now < nbf || now >= exp)
1961
+ if (!isInt(nbf) || !isInt(exp) || now < nbf - 300 || now > exp + 300)
1962
1962
  throw new ProtocolError('CREDENTIAL_EXPIRED', 'credential is outside its validity window');
1963
1963
  if (audience !== undefined) {
1964
1964
  if (!Array.isArray(value.aud) || !value.aud.includes(audience))
@@ -2146,7 +2146,10 @@ function capabilitiesNarrower(child, parent, subject, depth) {
2146
2146
  function verifyAgentSignature(signatureValue, payload, expectedAid, resolveCertificate, now, enforceWindow = true) {
2147
2147
  const certPem = certificatePem(resolveCertificate(String(signatureValue.cert_fingerprint)));
2148
2148
  const lower = payload.iat ?? payload.registered_at;
2149
- if (enforceWindow && typeof lower === 'number' && (Number(signatureValue.timestamp) < lower || Number(signatureValue.timestamp) >= Number(payload.exp)))
2149
+ const outsideWindow = typeof lower === 'number' && (payload.ver === 'aun-org-transfer/1'
2150
+ ? Number(signatureValue.timestamp) < lower - 300 || Number(signatureValue.timestamp) > Number(payload.exp) + 300
2151
+ : Number(signatureValue.timestamp) < lower || Number(signatureValue.timestamp) >= Number(payload.exp));
2152
+ if (enforceWindow && outsideWindow)
2150
2153
  throw new Error('signature timestamp is outside the signed object window');
2151
2154
  if (!certPem)
2152
2155
  throw new Error('certificate is missing');
@@ -2285,7 +2288,7 @@ export function validateMembershipBindingAt(binding, now, expectedRole) {
2285
2288
  const value = binding;
2286
2289
  const iat = value.iat;
2287
2290
  const exp = value.exp;
2288
- if (!isInt(now) || !isInt(iat) || !isInt(exp) || now < iat || now >= exp)
2291
+ if (!isInt(now) || !isInt(iat) || !isInt(exp) || now < iat - 300 || now > exp + 300)
2289
2292
  throw new ProtocolError('CREDENTIAL_REQUEST_BINDING_INVALID', 'membership binding is outside its validity window');
2290
2293
  if (expectedRole !== undefined && value.role !== expectedRole)
2291
2294
  throw invalid('membership role is invalid');
@@ -2341,7 +2344,7 @@ export function validateRegistrationReceipt(receipt, credential, request, expect
2341
2344
  throw new ProtocolError('CREDENTIAL_REGISTRATION_RECEIPT_MISMATCH', 'receipt registrar does not match request');
2342
2345
  if (expectedServiceAid !== undefined && receipt.service_aid !== expectedServiceAid)
2343
2346
  throw new ProtocolError('CREDENTIAL_REGISTRATION_RECEIPT_INVALID', 'receipt service AID mismatch');
2344
- if (now !== undefined && (!isInt(now) || now < receipt.registered_at || now >= receipt.exp))
2347
+ if (now !== undefined && (!isInt(now) || now < receipt.registered_at - 300 || now > receipt.exp + 300))
2345
2348
  throw new ProtocolError('CREDENTIAL_REGISTRATION_RECEIPT_INVALID', 'receipt is outside its validity window');
2346
2349
  signature(receipt.signature);
2347
2350
  }
@@ -2410,7 +2413,7 @@ export function validateRequestBinding(binding, method, target, params, credenti
2410
2413
  throw new ProtocolError('CREDENTIAL_REQUEST_BINDING_INVALID', 'request binding is invalid');
2411
2414
  if (binding.request_id !== requestId || binding.nonce !== nonce || binding.target !== target || binding.method !== method || binding.credential_cid !== credentialCid || binding.params_hash !== digest(orgRequestBindingParams(method, params)))
2412
2415
  throw new ProtocolError('CREDENTIAL_REQUEST_BINDING_INVALID', 'request binding does not match request');
2413
- if (!isInt(binding.iat) || !isInt(binding.exp) || binding.exp <= binding.iat || binding.exp > binding.iat + 300 || !isInt(now) || now < binding.iat || now >= binding.exp)
2416
+ if (!isInt(binding.iat) || !isInt(binding.exp) || binding.exp <= binding.iat || binding.exp > binding.iat + 300 || !isInt(now) || now < binding.iat - 300 || now > binding.exp + 300)
2414
2417
  throw new ProtocolError('CREDENTIAL_REQUEST_BINDING_INVALID', 'request binding is outside its validity window');
2415
2418
  }
2416
2419
  function representationBindingInvalid(message) {
@@ -2467,7 +2470,7 @@ export function verifyRepresentationProof(proof, credential, request, resolveCer
2467
2470
  throw representationBindingInvalid('representation proof AID is invalid');
2468
2471
  if (!DIGEST_RE.test(proof.params_hash))
2469
2472
  throw representationBindingInvalid('representation params_hash is invalid');
2470
- if (!isInt(proof.iat) || !isInt(proof.exp) || proof.exp <= proof.iat || !isInt(now) || now < proof.iat || now >= proof.exp)
2473
+ if (!isInt(proof.iat) || !isInt(proof.exp) || proof.exp <= proof.iat || !isInt(now) || now < proof.iat - 300 || now > proof.exp + 300)
2471
2474
  throw representationBindingInvalid('representation time window is invalid');
2472
2475
  validateRepresentationSignature(proof.signature);
2473
2476
  if (!isRecord(credential))
@@ -2490,7 +2493,7 @@ export function verifyRepresentationProof(proof, credential, request, resolveCer
2490
2493
  const timestamp = proof.signature.timestamp;
2491
2494
  if (timestamp > now + 300 || timestamp < proof.iat || timestamp >= proof.exp)
2492
2495
  throw new Error('representation signature timestamp is outside its window');
2493
- if (timestamp < Math.floor(new Date(cert.validFrom).getTime() / 1000) || timestamp > Math.floor(new Date(cert.validTo).getTime() / 1000) || now < Math.floor(new Date(cert.validFrom).getTime() / 1000) || now > Math.floor(new Date(cert.validTo).getTime() / 1000))
2496
+ if (timestamp < Math.floor(new Date(cert.validFrom).getTime() / 1000) || timestamp > Math.floor(new Date(cert.validTo).getTime() / 1000) || now < Math.floor(new Date(cert.validFrom).getTime() / 1000) - 300 || now > Math.floor(new Date(cert.validTo).getTime() / 1000) + 300)
2494
2497
  throw new Error('certificate is not valid at signature or verification time');
2495
2498
  const payload = { ...proof };
2496
2499
  delete payload.signature;