@astrasyncai/verification-gateway 5.11.0 → 5.12.0

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 (98) hide show
  1. package/README.md +4 -0
  2. package/dist/adapters/express.d.mts +1 -1
  3. package/dist/adapters/express.d.ts +1 -1
  4. package/dist/adapters/express.js +359 -30
  5. package/dist/adapters/express.js.map +1 -1
  6. package/dist/adapters/express.mjs +359 -30
  7. package/dist/adapters/express.mjs.map +1 -1
  8. package/dist/adapters/mcp.d.mts +5 -1
  9. package/dist/adapters/mcp.d.ts +5 -1
  10. package/dist/adapters/mcp.js +168 -41
  11. package/dist/adapters/mcp.js.map +1 -1
  12. package/dist/adapters/mcp.mjs +168 -41
  13. package/dist/adapters/mcp.mjs.map +1 -1
  14. package/dist/adapters/nextjs.d.mts +1 -1
  15. package/dist/adapters/nextjs.d.ts +1 -1
  16. package/dist/adapters/nextjs.js +352 -13
  17. package/dist/adapters/nextjs.js.map +1 -1
  18. package/dist/adapters/nextjs.mjs +352 -13
  19. package/dist/adapters/nextjs.mjs.map +1 -1
  20. package/dist/adapters/sdk.d.mts +9 -1
  21. package/dist/adapters/sdk.d.ts +9 -1
  22. package/dist/adapters/sdk.js +100 -8
  23. package/dist/adapters/sdk.js.map +1 -1
  24. package/dist/adapters/sdk.mjs +100 -8
  25. package/dist/adapters/sdk.mjs.map +1 -1
  26. package/dist/agent/index.js +1 -1
  27. package/dist/agent/index.js.map +1 -1
  28. package/dist/agent/index.mjs +1 -1
  29. package/dist/agent/index.mjs.map +1 -1
  30. package/dist/bin/astrasync-claude-hook.js +284 -7
  31. package/dist/bin/astrasync-codex-hook.js +284 -7
  32. package/dist/bin/astrasync-guard.js +284 -7
  33. package/dist/bin/astrasync.js +297 -9
  34. package/dist/browser/background.js +284 -7
  35. package/dist/browser/background.js.map +1 -1
  36. package/dist/browser/background.mjs +284 -7
  37. package/dist/browser/background.mjs.map +1 -1
  38. package/dist/cli/index.js +1 -1
  39. package/dist/cli/index.js.map +1 -1
  40. package/dist/cli/index.mjs +1 -1
  41. package/dist/cli/index.mjs.map +1 -1
  42. package/dist/codex/index.js +284 -7
  43. package/dist/codex/index.js.map +1 -1
  44. package/dist/codex/index.mjs +284 -7
  45. package/dist/codex/index.mjs.map +1 -1
  46. package/dist/cursor/extension.js +284 -7
  47. package/dist/cursor/extension.js.map +1 -1
  48. package/dist/cursor/extension.mjs +284 -7
  49. package/dist/cursor/extension.mjs.map +1 -1
  50. package/dist/edge-config.d.mts +1 -1
  51. package/dist/edge-config.d.ts +1 -1
  52. package/dist/edge-config.js +1 -1
  53. package/dist/edge-config.js.map +1 -1
  54. package/dist/edge-config.mjs +1 -1
  55. package/dist/edge-config.mjs.map +1 -1
  56. package/dist/edge-core/index.d.mts +128 -13
  57. package/dist/edge-core/index.d.ts +128 -13
  58. package/dist/edge-core/index.js +337 -55
  59. package/dist/edge-core/index.js.map +1 -1
  60. package/dist/edge-core/index.mjs +334 -55
  61. package/dist/edge-core/index.mjs.map +1 -1
  62. package/dist/gateway/gateway.js +284 -7
  63. package/dist/gateway/gateway.js.map +1 -1
  64. package/dist/gateway/gateway.mjs +284 -7
  65. package/dist/gateway/gateway.mjs.map +1 -1
  66. package/dist/git-trigger/git-hooks.d.mts +1 -1
  67. package/dist/git-trigger/git-hooks.d.ts +1 -1
  68. package/dist/index.d.mts +118 -5
  69. package/dist/index.d.ts +118 -5
  70. package/dist/index.js +486 -63
  71. package/dist/index.js.map +1 -1
  72. package/dist/index.mjs +480 -63
  73. package/dist/index.mjs.map +1 -1
  74. package/dist/platform-signatures.js +4 -1
  75. package/dist/platform-signatures.js.map +1 -1
  76. package/dist/platform-signatures.mjs +4 -1
  77. package/dist/platform-signatures.mjs.map +1 -1
  78. package/dist/registration/index.js +1 -1
  79. package/dist/registration/index.js.map +1 -1
  80. package/dist/registration/index.mjs +1 -1
  81. package/dist/registration/index.mjs.map +1 -1
  82. package/dist/transport/index.js +1 -1
  83. package/dist/transport/index.js.map +1 -1
  84. package/dist/transport/index.mjs +1 -1
  85. package/dist/transport/index.mjs.map +1 -1
  86. package/dist/{types-CTmUpNpS.d.mts → types-BCkwBA84.d.mts} +12 -0
  87. package/dist/{types-CTmUpNpS.d.ts → types-BCkwBA84.d.ts} +12 -0
  88. package/dist/{types-CtFXmDzm.d.ts → types-C_b4QTyO.d.ts} +18 -0
  89. package/dist/{types-DQrn_kei.d.mts → types-DlshIIR-.d.mts} +18 -0
  90. package/dist/ui/index.d.mts +1 -1
  91. package/dist/ui/index.d.ts +1 -1
  92. package/dist/verify.d.mts +35 -4
  93. package/dist/verify.d.ts +35 -4
  94. package/dist/verify.js +130 -16
  95. package/dist/verify.js.map +1 -1
  96. package/dist/verify.mjs +129 -16
  97. package/dist/verify.mjs.map +1 -1
  98. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -51,6 +51,7 @@ __export(src_exports, {
51
51
  RegistrationTimeoutError: () => RegistrationTimeoutError,
52
52
  SDK_USER_AGENT: () => SDK_USER_AGENT,
53
53
  TRUST_LEVEL_RANGES: () => TRUST_LEVEL_RANGES,
54
+ VERIFICATION_STATUS_HEADER: () => VERIFICATION_STATUS_HEADER,
54
55
  VERSION: () => SDK_VERSION,
55
56
  _resetEdgeConfigCache: () => _resetEdgeConfigCache,
56
57
  agent: () => agent_exports,
@@ -58,9 +59,11 @@ __export(src_exports, {
58
59
  awaitStepUpApproval: () => awaitStepUpApproval,
59
60
  buildGuidance: () => buildGuidance,
60
61
  buildSdkObservedMetadata: () => buildSdkObservedMetadata,
62
+ buildVerificationUnavailableBody: () => buildVerificationUnavailableBody,
61
63
  clearCache: () => clearCache,
62
64
  createMcpMiddleware: () => createMcpMiddleware,
63
65
  degradeToObserve: () => degradeToObserve,
66
+ denyStatusFor: () => denyStatusFor,
64
67
  deriveConnectionFromHeaders: () => deriveConnectionFromHeaders,
65
68
  detectPlatformFingerprint: () => detectPlatformFingerprint,
66
69
  detectRuntime: () => detectRuntime,
@@ -77,6 +80,8 @@ __export(src_exports, {
77
80
  getWellKnownUrls: () => getWellKnownUrls,
78
81
  hasCredentials: () => hasCredentials,
79
82
  isEdgeConfig: () => isEdgeConfig,
83
+ isRejectedIdentityClaim: () => isRejectedIdentityClaim,
84
+ isVerificationUnavailable: () => isVerificationUnavailable,
80
85
  isVerifiedHopValidFor: () => isVerifiedHopValidFor,
81
86
  matchEdgePathRule: () => matchEdgePathRule,
82
87
  matchPlatformSignature: () => matchPlatformSignature,
@@ -96,6 +101,7 @@ __export(src_exports, {
96
101
  serializeVerifiedHop: () => serializeVerifiedHop,
97
102
  setMcpMeta: () => setMcpMeta,
98
103
  transport: () => transport_exports,
104
+ unavailableRetryAfterSeconds: () => unavailableRetryAfterSeconds,
99
105
  validateLocalPolicy: () => validatePolicy,
100
106
  verify: () => verify
101
107
  });
@@ -116,7 +122,7 @@ function getTrustLevel(score) {
116
122
  }
117
123
 
118
124
  // src/version.ts
119
- var SDK_VERSION = "5.11.0";
125
+ var SDK_VERSION = "5.12.0";
120
126
 
121
127
  // src/http.ts
122
128
  var SDK_USER_AGENT = `astrasync-sdk/${SDK_VERSION}`;
@@ -195,6 +201,59 @@ function getCachedWellKnownUrls(apiBaseUrl) {
195
201
  return cache.get(apiBaseUrl)?.data;
196
202
  }
197
203
 
204
+ // src/failure-posture.ts
205
+ var VERIFICATION_STATUS_HEADER = "X-Astra-Verification";
206
+ var DEFAULT_UNAVAILABLE_RETRY_AFTER_S = 30;
207
+ var REJECTED_IDENTITY_DIMENSIONS = /* @__PURE__ */ new Set([
208
+ "identity.invalid_agent_id",
209
+ "identity.unknown_agent",
210
+ "agent.lookup"
211
+ ]);
212
+ var UNKNOWN_AGENT_GUIDANCE = "Register your agent with AstraSync (or, inside an MCP host, add the AstraSync MCP connector for keyless, human-approved registration), then present the canonical ASTRA-* id issued after owner approval.";
213
+ var UNAVAILABLE_DIMENSIONS = /* @__PURE__ */ new Set([
214
+ "verify_access.api_error",
215
+ "middleware.internal_error"
216
+ ]);
217
+ function isVerificationUnavailable(result) {
218
+ if (result.misconfigured) return false;
219
+ return (result.failures ?? []).some((f) => UNAVAILABLE_DIMENSIONS.has(f.dimension));
220
+ }
221
+ function unavailableRetryAfterSeconds(result) {
222
+ if (typeof result.retryAfterMs === "number" && Number.isFinite(result.retryAfterMs)) {
223
+ return Math.max(1, Math.ceil(result.retryAfterMs / 1e3));
224
+ }
225
+ return DEFAULT_UNAVAILABLE_RETRY_AFTER_S;
226
+ }
227
+ function isAnonymousRead(method, credentials) {
228
+ const m = (method ?? "").toUpperCase();
229
+ if (m !== "GET" && m !== "HEAD") return false;
230
+ return !credentials.astraId && !credentials.jwt;
231
+ }
232
+ function buildVerificationUnavailableBody(result) {
233
+ return {
234
+ success: false,
235
+ error: {
236
+ code: "VERIFICATION_UNAVAILABLE",
237
+ message: "Agent verification is temporarily unavailable and this path enforces verification. Your identity was not evaluated and no denial was recorded \u2014 retry after the Retry-After interval.",
238
+ retryable: true,
239
+ retryAfterSeconds: unavailableRetryAfterSeconds(result),
240
+ ...result.failures && { failures: result.failures },
241
+ ...result.correlationId && { correlationId: result.correlationId },
242
+ guidance: {
243
+ message: "Retry the request after the Retry-After interval, with exponential backoff; the condition is transient."
244
+ }
245
+ }
246
+ };
247
+ }
248
+ function isRejectedIdentityClaim(result) {
249
+ return (result.failures ?? []).some((f) => REJECTED_IDENTITY_DIMENSIONS.has(f.dimension));
250
+ }
251
+ function denyStatusFor(result, policyDeniedCode) {
252
+ if (isRejectedIdentityClaim(result)) return { status: 403, code: "AGENT_IDENTITY_REJECTED" };
253
+ if (result.identityVerified) return { status: 403, code: policyDeniedCode };
254
+ return { status: 401, code: "UNAUTHORIZED" };
255
+ }
256
+
198
257
  // src/verify.ts
199
258
  var DEFAULT_CONFIG = {
200
259
  apiBaseUrl: "https://astrasync.ai/api",
@@ -446,11 +505,44 @@ function createGuidanceResponse(_config, reason, options = {}) {
446
505
  // coercing the absent recommendation to a policy 'deny'. Misconfig is
447
506
  // deterministic and intentionally NOT marked retryable.
448
507
  ...isApiError && { retryable: true },
508
+ ...options.httpStatus !== void 0 && { httpStatus: options.httpStatus },
509
+ ...options.retryAfterMs !== void 0 && { retryAfterMs: options.retryAfterMs },
449
510
  correlationId: options.correlationId,
450
511
  attemptId: options.attemptId,
451
512
  verifiedAt: /* @__PURE__ */ new Date()
452
513
  };
453
514
  }
515
+ async function readJsonSafe(response) {
516
+ try {
517
+ const parsed = await response.json();
518
+ return parsed && typeof parsed === "object" ? parsed : {};
519
+ } catch {
520
+ return {};
521
+ }
522
+ }
523
+ function rejectedIdentityGuidance(failures) {
524
+ const f = failures?.find((x) => REJECTED_IDENTITY_DIMENSIONS.has(x.dimension));
525
+ if (!f) return void 0;
526
+ if (f.dimension === "agent.lookup") {
527
+ return `The presented agent identifier is not registered with AstraSync. ${UNKNOWN_AGENT_GUIDANCE}`;
528
+ }
529
+ return f.guidance ? `${f.message} ${f.guidance}` : f.message;
530
+ }
531
+ var MAX_RETRY_AFTER_MS = 15 * 60 * 1e3;
532
+ function parseRetryAfterMs(response) {
533
+ const raw = response.headers?.get?.("retry-after");
534
+ if (!raw) return void 0;
535
+ const trimmed = raw.trim();
536
+ let ms;
537
+ if (/^\d+(\.\d+)?$/.test(trimmed)) {
538
+ ms = Number(trimmed) * 1e3;
539
+ } else {
540
+ const at = Date.parse(trimmed);
541
+ if (Number.isNaN(at)) return void 0;
542
+ ms = at - Date.now();
543
+ }
544
+ return Math.min(MAX_RETRY_AFTER_MS, Math.max(0, Math.round(ms)));
545
+ }
454
546
  async function callVerifyAccessAPI(config, request) {
455
547
  const { credentials, ...requestData } = request;
456
548
  const body = {
@@ -507,7 +599,8 @@ async function callVerifyAccessAPI(config, request) {
507
599
  body: JSON.stringify(body),
508
600
  signal: AbortSignal.timeout(config.verifyTimeoutMs ?? 1e4)
509
601
  });
510
- const data = await response.json();
602
+ const data = await readJsonSafe(response);
603
+ const retryAfterMs = parseRetryAfterMs(response);
511
604
  if (response.status === 410) {
512
605
  return {
513
606
  success: true,
@@ -545,6 +638,23 @@ async function callVerifyAccessAPI(config, request) {
545
638
  }
546
639
  };
547
640
  }
641
+ if (response.status === 404 && credentials.astraId && (data?.error === "AGENT_NOT_FOUND" || typeof data?.message === "string" && /agent/i.test(data.message))) {
642
+ return {
643
+ success: true,
644
+ attemptId: typeof data?.attemptId === "string" ? data.attemptId : void 0,
645
+ access: {
646
+ allowed: false,
647
+ reason: "unknown_agent",
648
+ failures: [
649
+ {
650
+ dimension: "identity.unknown_agent",
651
+ message: "The presented agent identifier is not registered with AstraSync.",
652
+ guidance: UNKNOWN_AGENT_GUIDANCE
653
+ }
654
+ ]
655
+ }
656
+ };
657
+ }
548
658
  if (!response.ok) {
549
659
  if (response.status === 401) {
550
660
  return {
@@ -559,9 +669,11 @@ async function callVerifyAccessAPI(config, request) {
559
669
  }
560
670
  return {
561
671
  success: false,
562
- error: data.message || data.error || `API returned ${response.status}`,
672
+ error: typeof data?.message === "string" && data.message || typeof data?.error === "string" && data.error || `API returned ${response.status}`,
563
673
  correlationId: typeof data?.correlationId === "string" ? data.correlationId : void 0,
564
- attemptId: typeof data?.attemptId === "string" ? data.attemptId : void 0
674
+ attemptId: typeof data?.attemptId === "string" ? data.attemptId : void 0,
675
+ httpStatus: response.status,
676
+ ...retryAfterMs !== void 0 && { retryAfterMs }
565
677
  };
566
678
  }
567
679
  return data;
@@ -633,12 +745,14 @@ async function verify(config, request, options) {
633
745
  correlationId: apiResponse.correlationId,
634
746
  attemptId: apiResponse.attemptId,
635
747
  remediation: apiResponse.remediation,
748
+ httpStatus: apiResponse.httpStatus,
749
+ retryAfterMs: apiResponse.retryAfterMs,
636
750
  urls
637
751
  });
638
752
  }
639
753
  if (!apiResponse.access?.allowed) {
640
754
  const aggregatedFailures = apiResponse.access?.failures;
641
- const idVerifiedFromBackend = apiResponse.verificationContext?.idVerified === true;
755
+ const idVerifiedFromBackend = apiResponse.verificationContext?.idVerified === true && !aggregatedFailures?.some((f) => REJECTED_IDENTITY_DIMENSIONS.has(f.dimension));
642
756
  const result2 = {
643
757
  identityVerified: idVerifiedFromBackend,
644
758
  policyAllowed: false,
@@ -650,7 +764,10 @@ async function verify(config, request, options) {
650
764
  requiresStepUp: apiResponse.access?.requiresStepUp,
651
765
  requiresApproval: apiResponse.access?.requiresApproval,
652
766
  guidance: {
653
- message: apiResponse.access?.reason || "Access denied by PDLSS policy",
767
+ // 5.12.0: a presented-but-rejected id (malformed / unknown) carries
768
+ // actionable registration guidance on its failure — surface it
769
+ // instead of the bare machine reason ('unknown_agent').
770
+ message: rejectedIdentityGuidance(aggregatedFailures) ?? (apiResponse.access?.reason || "Access denied by PDLSS policy"),
654
771
  registrationUrl: urls?.registrationUrl ?? "",
655
772
  documentationUrl: urls?.documentationUrl ?? "",
656
773
  // 5.1.0: anonymous callers land on this branch — steer MCP-hosted
@@ -750,7 +867,7 @@ async function verify(config, request, options) {
750
867
  registrationUrl: urls?.registrationUrl ?? "",
751
868
  documentationUrl: urls?.documentationUrl ?? ""
752
869
  };
753
- } else if (result.recommendation === "step_up_required") {
870
+ } else if (result.recommendation === "step_up_required" && result.identityVerified) {
754
871
  result.requiresStepUp = true;
755
872
  result.denialReasons = serverDenialReasons ?? result.recommendationReasons ?? ["Step-up verification required"];
756
873
  }
@@ -773,7 +890,7 @@ async function recordDecision(config, sessionId, decision, reason) {
773
890
  }).catch(() => {
774
891
  });
775
892
  }
776
- async function reportAttempt(config, report) {
893
+ async function reportAttempt(config, report, options = {}) {
777
894
  const apiBaseUrl = config.apiBaseUrl || DEFAULT_CONFIG.apiBaseUrl;
778
895
  const headers = { "Content-Type": "application/json" };
779
896
  if (config.apiKey) {
@@ -784,13 +901,37 @@ async function reportAttempt(config, report) {
784
901
  ...report,
785
902
  ...!report.counterpartyId && config.counterpartyId && { counterpartyId: config.counterpartyId }
786
903
  };
787
- await sdkFetch(`${apiBaseUrl}/agents/verify-access/attempt-report`, {
788
- method: "POST",
789
- headers,
790
- body: JSON.stringify(body)
791
- }).catch(() => {
792
- });
904
+ const url = `${apiBaseUrl}/agents/verify-access/attempt-report`;
905
+ const init = { method: "POST", headers, body: JSON.stringify(body) };
906
+ const fail = (failure) => {
907
+ try {
908
+ options.onFailure?.(failure);
909
+ } catch {
910
+ }
911
+ };
912
+ let response;
913
+ try {
914
+ response = await sdkFetch(url, init);
915
+ } catch (err) {
916
+ fail({ error: err instanceof Error ? err.message : String(err), retried: false });
917
+ return;
918
+ }
919
+ if (response.ok) return;
920
+ if (response.status !== 429 && response.status < 500) {
921
+ fail({ status: response.status, retried: false });
922
+ return;
923
+ }
924
+ const delayMs = Math.min(ATTEMPT_REPORT_MAX_RETRY_DELAY_MS, parseRetryAfterMs(response) ?? 500);
925
+ const timer = setTimeout(() => {
926
+ sdkFetch(url, init).then((retry) => {
927
+ if (!retry.ok) fail({ status: retry.status, retried: true });
928
+ }).catch((err) => {
929
+ fail({ error: err instanceof Error ? err.message : String(err), retried: true });
930
+ });
931
+ }, delayMs);
932
+ timer.unref?.();
793
933
  }
934
+ var ATTEMPT_REPORT_MAX_RETRY_DELAY_MS = 2e3;
794
935
  async function fetchRoutes(config, counterpartyId) {
795
936
  if (!counterpartyId) return null;
796
937
  const headers = { "Content-Type": "application/json" };
@@ -820,7 +961,10 @@ async function reportUnregisteredAttempt(config, data) {
820
961
  };
821
962
  await sdkFetch(`${apiBaseUrl}/verification-activity/unregistered-attempt`, {
822
963
  method: "POST",
823
- headers: { "Content-Type": "application/json" },
964
+ headers: {
965
+ "Content-Type": "application/json",
966
+ ...config.apiKey && { Authorization: `Bearer ${config.apiKey}` }
967
+ },
824
968
  body: JSON.stringify(body)
825
969
  }).catch(() => {
826
970
  });
@@ -842,7 +986,11 @@ async function quickVerify(config, credentials) {
842
986
  return {
843
987
  identityVerified: result.identityVerified,
844
988
  policyAllowed: result.policyAllowed,
845
- reason: result.denialReasons?.[0]
989
+ reason: result.denialReasons?.[0],
990
+ ...isVerificationUnavailable(result) && {
991
+ unavailable: true,
992
+ retryAfterMs: unavailableRetryAfterSeconds(result) * 1e3
993
+ }
846
994
  };
847
995
  }
848
996
 
@@ -1590,7 +1738,10 @@ var PLATFORM_AGENT_SIGNATURES = [
1590
1738
  {
1591
1739
  vendor: "chatgpt",
1592
1740
  displayName: "OpenAI ChatGPT",
1593
- uaPatterns: [/chatgpt/i, /openai/i, /gpt-?\d/i],
1741
+ // GPTBot (training crawler) and OAI-SearchBot (ChatGPT search) are
1742
+ // OpenAI's declared crawler UAs — `gpt-?\d` never matched them, so they
1743
+ // classified as unattributed crawlers (round-27.4 W5).
1744
+ uaPatterns: [/chatgpt/i, /openai/i, /gpt-?\d/i, /\bGPTBot\b/i, /\bOAI-SearchBot\b/i],
1594
1745
  agentCardPatterns: [/openai\.com/i, /chatgpt\.com/i],
1595
1746
  apiKeyFormatPatterns: [/^sk-proj/i, /^sk-svcacct/i],
1596
1747
  headerPatterns: [/^openai-organization/i, /^openai-project/i, /^openai-version/i]
@@ -1725,6 +1876,215 @@ var BROWSER_UA_PATTERN = /mozilla\/\d/i;
1725
1876
  var _patterns = { STATIC_EXTENSIONS, BOT_UA_PATTERN, BROWSER_UA_PATTERN, SELF_UA_PATTERN };
1726
1877
 
1727
1878
  // src/edge-core/events.ts
1879
+ async function withBudget(promise, ms) {
1880
+ let timer;
1881
+ try {
1882
+ return await Promise.race([
1883
+ promise,
1884
+ new Promise((resolve) => {
1885
+ timer = setTimeout(() => resolve(void 0), ms);
1886
+ })
1887
+ ]);
1888
+ } catch {
1889
+ return void 0;
1890
+ } finally {
1891
+ if (timer) clearTimeout(timer);
1892
+ }
1893
+ }
1894
+ var destKeyOf = (d) => `${d.apiBaseUrl}\0${d.apiKey ?? ""}\0${d.counterparty}\0${d.adapter ?? ""}`;
1895
+ var BeaconBuffer = class {
1896
+ constructor(options = {}) {
1897
+ this.queue = [];
1898
+ this.droppedSinceLast = 0;
1899
+ this.droppedTotal = 0;
1900
+ this.deliveredTotal = 0;
1901
+ this.backoffUntil = 0;
1902
+ this.collapse = /* @__PURE__ */ new Map();
1903
+ /** Keys the backend answered 401 for — later batches go unauthenticated. */
1904
+ this.rejectedKeys = /* @__PURE__ */ new Set();
1905
+ this.opts = {
1906
+ maxItems: options.maxItems ?? 1e3,
1907
+ maxBatch: options.maxBatch ?? 100,
1908
+ maxAttempts: options.maxAttempts ?? 3,
1909
+ collapseWindowMs: options.collapseWindowMs ?? 6e4,
1910
+ collapseMaxKeys: options.collapseMaxKeys ?? 1e3,
1911
+ requestTimeoutMs: options.requestTimeoutMs ?? 1e4,
1912
+ retryBackoffMs: options.retryBackoffMs ?? 1e3,
1913
+ now: options.now ?? Date.now
1914
+ };
1915
+ }
1916
+ /**
1917
+ * Queue one beacon. With a `collapseKey`, a repeat inside the window is
1918
+ * merged into a held aggregate (sent when the window closes) instead of
1919
+ * becoming its own item.
1920
+ */
1921
+ enqueue(dest, item, collapseKey) {
1922
+ const now = this.opts.now();
1923
+ if (collapseKey) {
1924
+ const entry = this.collapse.get(collapseKey);
1925
+ if (entry && now - entry.firstSeenAt < this.opts.collapseWindowMs) {
1926
+ for (const target of [entry.first, entry.held]) {
1927
+ if (target && !target.inFlight && this.queue.includes(target)) {
1928
+ target.item.repeatCount = (target.item.repeatCount ?? 1) + 1;
1929
+ return;
1930
+ }
1931
+ }
1932
+ const held = this.push(
1933
+ dest,
1934
+ { ...item, repeatCount: 1 },
1935
+ entry.firstSeenAt + this.opts.collapseWindowMs
1936
+ );
1937
+ entry.held = held;
1938
+ return;
1939
+ }
1940
+ this.collapse.delete(collapseKey);
1941
+ if (this.collapse.size >= this.opts.collapseMaxKeys) {
1942
+ const oldest = this.collapse.keys().next().value;
1943
+ if (oldest !== void 0) this.collapse.delete(oldest);
1944
+ }
1945
+ const fresh = { firstSeenAt: now };
1946
+ this.collapse.set(collapseKey, fresh);
1947
+ fresh.first = this.push(dest, item, now);
1948
+ return;
1949
+ }
1950
+ this.push(dest, item, now);
1951
+ }
1952
+ /**
1953
+ * Deliver every eligible queued item. Concurrent callers share ONE
1954
+ * in-flight drain (it survives the caller's budget and a Lambda freeze),
1955
+ * so nothing in flight is ever sent twice; items queued while it runs are
1956
+ * picked up by the same drain.
1957
+ */
1958
+ flush() {
1959
+ if (!this.inFlight) {
1960
+ this.inFlight = this.drain().finally(() => {
1961
+ this.inFlight = void 0;
1962
+ });
1963
+ }
1964
+ return this.inFlight;
1965
+ }
1966
+ /** Counters for tests and diagnostics. */
1967
+ stats() {
1968
+ return {
1969
+ queueDepth: this.queue.length,
1970
+ droppedSinceLast: this.droppedSinceLast,
1971
+ droppedTotal: this.droppedTotal,
1972
+ deliveredTotal: this.deliveredTotal,
1973
+ flushing: this.inFlight !== void 0
1974
+ };
1975
+ }
1976
+ push(dest, item, eligibleAt) {
1977
+ while (this.queue.length >= this.opts.maxItems) this.dropOldest();
1978
+ const entry = {
1979
+ dest,
1980
+ destKey: destKeyOf(dest),
1981
+ item,
1982
+ attempts: 0,
1983
+ eligibleAt,
1984
+ inFlight: false
1985
+ };
1986
+ this.queue.push(entry);
1987
+ return entry;
1988
+ }
1989
+ dropOldest() {
1990
+ if (this.queue.shift()) this.countDropped(1);
1991
+ }
1992
+ countDropped(n) {
1993
+ this.droppedSinceLast += n;
1994
+ this.droppedTotal += n;
1995
+ }
1996
+ async drain() {
1997
+ for (; ; ) {
1998
+ const now = this.opts.now();
1999
+ if (now < this.backoffUntil) return;
2000
+ const batch = this.takeBatch(now);
2001
+ if (batch.length === 0) return;
2002
+ const ok = await this.send(batch);
2003
+ if (!ok) return;
2004
+ }
2005
+ }
2006
+ /** Oldest eligible item + up to maxBatch-1 more for the same destination. */
2007
+ takeBatch(now) {
2008
+ const first = this.queue.find((q) => q.eligibleAt <= now);
2009
+ if (!first) return [];
2010
+ const batch = [];
2011
+ const rest = [];
2012
+ for (const q of this.queue) {
2013
+ if (batch.length < this.opts.maxBatch && q.destKey === first.destKey && q.eligibleAt <= now) {
2014
+ q.inFlight = true;
2015
+ batch.push(q);
2016
+ } else {
2017
+ rest.push(q);
2018
+ }
2019
+ }
2020
+ this.queue = rest;
2021
+ return batch;
2022
+ }
2023
+ /** POST one batch. Returns false when the drain should pause (backoff). */
2024
+ async send(batch) {
2025
+ const dest = batch[0].dest;
2026
+ const useKey = dest.apiKey && !this.rejectedKeys.has(dest.apiKey) ? dest.apiKey : void 0;
2027
+ const reportedDropped = this.droppedSinceLast;
2028
+ const meta = {
2029
+ droppedSinceLast: reportedDropped,
2030
+ queueDepth: this.queue.length,
2031
+ adapter: dest.adapter ?? "edge-core",
2032
+ version: SDK_VERSION
2033
+ };
2034
+ const controller = typeof AbortController !== "undefined" ? new AbortController() : void 0;
2035
+ const response = await withBudget(
2036
+ sdkFetch(`${dest.apiBaseUrl}/verification-activity/edge-events`, {
2037
+ method: "POST",
2038
+ headers: {
2039
+ "Content-Type": "application/json",
2040
+ ...useKey && { Authorization: `Bearer ${useKey}` }
2041
+ },
2042
+ body: JSON.stringify({ events: batch.map((q) => q.item), meta }),
2043
+ ...controller && { signal: controller.signal }
2044
+ }),
2045
+ this.opts.requestTimeoutMs
2046
+ );
2047
+ if (!response) controller?.abort();
2048
+ const status = response?.status;
2049
+ for (const q of batch) q.inFlight = false;
2050
+ if (status !== void 0 && status >= 200 && status < 300) {
2051
+ this.droppedSinceLast = Math.max(0, this.droppedSinceLast - reportedDropped);
2052
+ this.deliveredTotal += batch.length;
2053
+ return true;
2054
+ }
2055
+ if (status === 401 && useKey) {
2056
+ this.rejectedKeys.add(useKey);
2057
+ this.requeue(batch, false);
2058
+ return true;
2059
+ }
2060
+ if (status === 429) {
2061
+ const retryAfter = Number(response?.headers.get("retry-after"));
2062
+ const waitMs = Number.isFinite(retryAfter) && retryAfter > 0 ? Math.min(retryAfter, 120) * 1e3 : 3e4;
2063
+ this.backoffUntil = this.opts.now() + waitMs;
2064
+ this.requeue(batch, false);
2065
+ return false;
2066
+ }
2067
+ if (status !== void 0 && status >= 400 && status < 500) {
2068
+ this.countDropped(batch.length);
2069
+ return true;
2070
+ }
2071
+ this.backoffUntil = this.opts.now() + this.opts.retryBackoffMs;
2072
+ this.requeue(batch, true);
2073
+ return false;
2074
+ }
2075
+ /** Put a failed batch back at the head of the queue (order preserved). */
2076
+ requeue(batch, countAttempt) {
2077
+ const keep = [];
2078
+ for (const q of batch) {
2079
+ if (countAttempt) q.attempts += 1;
2080
+ if (q.attempts >= this.opts.maxAttempts) this.countDropped(1);
2081
+ else keep.push(q);
2082
+ }
2083
+ this.queue = [...keep, ...this.queue];
2084
+ while (this.queue.length > this.opts.maxItems) this.dropOldest();
2085
+ }
2086
+ };
2087
+ var beaconBuffer = new BeaconBuffer();
1728
2088
  function sampled(rate, random = Math.random) {
1729
2089
  if (rate <= 0) return false;
1730
2090
  if (rate >= 1) return true;
@@ -1901,12 +2261,19 @@ function defaultOnDenied(result, _req, res) {
1901
2261
  });
1902
2262
  return;
1903
2263
  }
1904
- const statusCode = !result.identityVerified ? 401 : 403;
2264
+ if (isVerificationUnavailable(result)) {
2265
+ res.setHeader("X-Astra-Gateway-Mode", "enforced");
2266
+ res.setHeader(VERIFICATION_STATUS_HEADER, "unavailable");
2267
+ res.setHeader("Retry-After", String(unavailableRetryAfterSeconds(result)));
2268
+ res.status(503).json(buildVerificationUnavailableBody(result));
2269
+ return;
2270
+ }
2271
+ const { status: statusCode, code } = denyStatusFor(result, "INSUFFICIENT_ACCESS");
1905
2272
  res.setHeader("X-Astra-Gateway-Mode", "enforced");
1906
2273
  res.status(statusCode).json({
1907
2274
  success: false,
1908
2275
  error: {
1909
- code: !result.identityVerified ? "UNAUTHORIZED" : "INSUFFICIENT_ACCESS",
2276
+ code,
1910
2277
  message: result.denialReasons?.[0] || "Access denied",
1911
2278
  guidance: result.guidance,
1912
2279
  // Round-10: aggregated per-dimension detail + correlation handle.
@@ -2154,6 +2521,21 @@ function createMiddleware(options) {
2154
2521
  result.stepUpOutcome = outcome;
2155
2522
  }
2156
2523
  }
2524
+ if (!result.policyAllowed && isVerificationUnavailable(result) && (!shouldEnforce || isAnonymousRead(req.method, credentials))) {
2525
+ res.setHeader(VERIFICATION_STATUS_HEADER, "unavailable");
2526
+ return next();
2527
+ }
2528
+ if (!shouldEnforce) {
2529
+ if (config.setPassThroughHeader) {
2530
+ res.setHeader("X-Astra-Gateway-Mode", "enforced");
2531
+ res.setHeader("X-Astra-Gateway-Reason", "evaluated-not-enforced");
2532
+ }
2533
+ if (shouldRecordDecisions && sessionId) {
2534
+ recordDecision(config, sessionId, "granted").catch(() => {
2535
+ });
2536
+ }
2537
+ return next();
2538
+ }
2157
2539
  if (!result.policyAllowed) {
2158
2540
  if (shouldRecordDecisions && sessionId) {
2159
2541
  recordDecision(config, sessionId, "denied", result.denialReasons?.[0]).catch(() => {
@@ -2173,17 +2555,6 @@ function createMiddleware(options) {
2173
2555
  onDenied(result, req, res);
2174
2556
  return;
2175
2557
  }
2176
- if (!shouldEnforce) {
2177
- if (config.setPassThroughHeader) {
2178
- res.setHeader("X-Astra-Gateway-Mode", "enforced");
2179
- res.setHeader("X-Astra-Gateway-Reason", "evaluated-not-enforced");
2180
- }
2181
- if (shouldRecordDecisions && sessionId) {
2182
- recordDecision(config, sessionId, "granted").catch(() => {
2183
- });
2184
- }
2185
- return next();
2186
- }
2187
2558
  if (routeConfig.minTrustScore && result.agent) {
2188
2559
  if (result.agent.trustScore < routeConfig.minTrustScore) {
2189
2560
  const trustFailure = {
@@ -2239,14 +2610,6 @@ function createMiddleware(options) {
2239
2610
  verifiedAt: /* @__PURE__ */ new Date(),
2240
2611
  correlationId
2241
2612
  };
2242
- const catchUrls = config.apiBaseUrl ? await getWellKnownUrls(config.apiBaseUrl).catch(() => void 0) : void 0;
2243
- if (catchUrls) {
2244
- result.guidance = {
2245
- message: `Middleware threw ${errorClass} \u2014 failing closed`,
2246
- registrationUrl: catchUrls.registrationUrl,
2247
- documentationUrl: catchUrls.documentationUrl
2248
- };
2249
- }
2250
2613
  dedupeFailures(result);
2251
2614
  return onDenied(result, req, res);
2252
2615
  }
@@ -2666,6 +3029,20 @@ function createMiddleware2(options) {
2666
3029
  }
2667
3030
  const approvalRequired = result.policyAllowed && requiresHumanApproval(result);
2668
3031
  if (approvalRequired) annotateApprovalRequired(result);
3032
+ if (!result.policyAllowed && isVerificationUnavailable(result)) {
3033
+ if (isAnonymousRead(request.method, credentials)) {
3034
+ const passThrough = NextResponse.next();
3035
+ passThrough.headers.set(VERIFICATION_STATUS_HEADER, "unavailable");
3036
+ return passThrough;
3037
+ }
3038
+ return NextResponse.json(buildVerificationUnavailableBody(result), {
3039
+ status: 503,
3040
+ headers: {
3041
+ "Retry-After": String(unavailableRetryAfterSeconds(result)),
3042
+ [VERIFICATION_STATUS_HEADER]: "unavailable"
3043
+ }
3044
+ });
3045
+ }
2669
3046
  if (!result.policyAllowed || approvalRequired) {
2670
3047
  if (result.misconfigured && pathname.startsWith("/api/")) {
2671
3048
  return NextResponse.json(
@@ -2683,13 +3060,12 @@ function createMiddleware2(options) {
2683
3060
  );
2684
3061
  }
2685
3062
  if (pathname.startsWith("/api/")) {
3063
+ const denyStatus = denyStatusFor(result, "POLICY_DENIED");
2686
3064
  return NextResponse.json(
2687
3065
  {
2688
3066
  success: false,
2689
3067
  error: {
2690
- // Round-18 G4: 401 → identity missing (re-auth); 403 → identity
2691
- // OK, policy denied (update PDLSS / step up).
2692
- code: !result.identityVerified ? "UNAUTHORIZED" : "POLICY_DENIED",
3068
+ code: denyStatus.code,
2693
3069
  message: result.denialReasons?.[0] || "Access denied",
2694
3070
  guidance: result.guidance,
2695
3071
  failures: result.failures,
@@ -2699,7 +3075,7 @@ function createMiddleware2(options) {
2699
3075
  }
2700
3076
  },
2701
3077
  {
2702
- status: !result.identityVerified ? 401 : 403,
3078
+ status: denyStatus.status,
2703
3079
  ...stepUpHoldOutcome && {
2704
3080
  headers: { "X-Astra-Step-Up": stepUpHoldOutcome }
2705
3081
  }
@@ -2826,6 +3202,12 @@ var VerificationGatewayClient = class {
2826
3202
  * fulfil against it only once the order is settled / pending_merchant. An
2827
3203
  * explicit `buyerEmail` (here or on the bridge handoff body) wins over the
2828
3204
  * account default.
3205
+ *
3206
+ * 5.12.0 approval binding: pass the bridge handoff body's `attemptId` (and
3207
+ * the same `checkoutSessionId`) so a step-up approval minted for this cart
3208
+ * is matched to — and only to — this confirm. A held cart's approval is
3209
+ * bound to its checkout session and exact value; a confirm for any other
3210
+ * cart is held for its own approval.
2829
3211
  */
2830
3212
  async confirmCheckout(options) {
2831
3213
  const credentials = {
@@ -2845,6 +3227,7 @@ var VerificationGatewayClient = class {
2845
3227
  commercePhase: "confirm",
2846
3228
  checkoutSessionId: options.checkoutSessionId,
2847
3229
  checkoutItems: options.checkoutItems,
3230
+ ...options.attemptId && { attemptId: options.attemptId },
2848
3231
  buyerEmail: options.buyerEmail,
2849
3232
  counterpartyUrl: options.counterpartyUrl,
2850
3233
  counterpartyType: options.counterpartyType
@@ -5645,8 +6028,37 @@ function dedupeFailures2(result) {
5645
6028
  result.denialReasons = [...new Set(result.denialReasons)];
5646
6029
  }
5647
6030
  }
6031
+ function isReadOnlyMcpMethod(parsed) {
6032
+ return parsed.method !== "tools/call";
6033
+ }
5648
6034
  function defaultMcpDenied(result, req, res) {
5649
6035
  const id = req.body?.id ?? null;
6036
+ if (isVerificationUnavailable(result)) {
6037
+ const retryAfterSeconds = unavailableRetryAfterSeconds(result);
6038
+ const body = buildVerificationUnavailableBody(result).error;
6039
+ res.setHeader("X-Astra-Gateway-Mode", "enforced");
6040
+ res.setHeader(VERIFICATION_STATUS_HEADER, "unavailable");
6041
+ res.setHeader("Retry-After", String(retryAfterSeconds));
6042
+ res.status(503).json({
6043
+ jsonrpc: "2.0",
6044
+ id,
6045
+ error: {
6046
+ // -32003 → verification temporarily unavailable (retryable)
6047
+ code: -32003,
6048
+ message: body.message,
6049
+ data: {
6050
+ code: body.code,
6051
+ recommendation: "error",
6052
+ retryable: true,
6053
+ retryAfterSeconds,
6054
+ guidance: body.guidance,
6055
+ failures: result.failures,
6056
+ correlationId: result.correlationId
6057
+ }
6058
+ }
6059
+ });
6060
+ return;
6061
+ }
5650
6062
  if (result.misconfigured) {
5651
6063
  res.setHeader("X-Astra-Gateway-Mode", "enforced");
5652
6064
  res.status(503).json({
@@ -5665,7 +6077,7 @@ function defaultMcpDenied(result, req, res) {
5665
6077
  });
5666
6078
  return;
5667
6079
  }
5668
- const status = !result.identityVerified ? 401 : 403;
6080
+ const { status, code: denyCode } = denyStatusFor(result, "INSUFFICIENT_ACCESS");
5669
6081
  res.setHeader("X-Astra-Gateway-Mode", "enforced");
5670
6082
  res.status(status).json({
5671
6083
  jsonrpc: "2.0",
@@ -5675,9 +6087,11 @@ function defaultMcpDenied(result, req, res) {
5675
6087
  // -32000 → unauthorized (no identity resolved)
5676
6088
  // -32001 → insufficient access (identity OK, policy denied)
5677
6089
  // -32002 → merchant verification misconfigured (handled above)
6090
+ // -32003 → verification temporarily unavailable (handled above)
5678
6091
  code: !result.identityVerified ? -32e3 : -32001,
5679
6092
  message: result.denialReasons?.[0] ?? "Access denied",
5680
6093
  data: {
6094
+ code: denyCode,
5681
6095
  guidance: result.guidance,
5682
6096
  // Round-10: aggregated per-dimension detail + correlation handle.
5683
6097
  failures: result.failures,
@@ -5805,6 +6219,9 @@ function createMcpMiddleware(options) {
5805
6219
  resolved_action: pdlss.action
5806
6220
  });
5807
6221
  }
6222
+ if (!pdlss.purpose && !shouldEnforce) {
6223
+ return next();
6224
+ }
5808
6225
  if (!pdlss.purpose) {
5809
6226
  const id = req.body?.id ?? null;
5810
6227
  res.status(400).json({
@@ -5824,6 +6241,9 @@ function createMcpMiddleware(options) {
5824
6241
  }
5825
6242
  const counterpartyUrl = config.counterpartyUrl || `${req.protocol}://${req.get("host")}${req.path}`;
5826
6243
  const shouldRecordDecisions = recordDecisions !== false;
6244
+ const forwardedFor = req.headers["x-forwarded-for"];
6245
+ const forwardedForStr = Array.isArray(forwardedFor) ? forwardedFor.join(", ") : forwardedFor;
6246
+ const sourceIp = req.ip ?? (forwardedForStr ? forwardedForStr.split(",")[0].trim() : void 0);
5827
6247
  const verificationRequest = {
5828
6248
  credentials,
5829
6249
  purpose: pdlss.purpose,
@@ -5838,9 +6258,10 @@ function createMcpMiddleware(options) {
5838
6258
  counterpartyType: config.counterpartyType || "mcp_server",
5839
6259
  enableRuntimeChallenge,
5840
6260
  callerMetadata: {
5841
- sourceIp: req.ip,
6261
+ sourceIp,
5842
6262
  userAgent: req.headers["user-agent"],
5843
6263
  host: req.headers.host,
6264
+ ...forwardedForStr && { forwardedFor: forwardedForStr },
5844
6265
  // Capture EVERY inbound header (parity with the express adapter —
5845
6266
  // MCP-only merchants have no edge to do it upstream) plus the
5846
6267
  // CDN-derived connection block. Local string work, secrets
@@ -5863,6 +6284,21 @@ function createMcpMiddleware(options) {
5863
6284
  result.stepUpOutcome = outcome;
5864
6285
  }
5865
6286
  }
6287
+ if (!result.policyAllowed && isVerificationUnavailable(result) && (!shouldEnforce || isReadOnlyMcpMethod(parsed) && !credentials.astraId && !credentials.jwt)) {
6288
+ res.setHeader(VERIFICATION_STATUS_HEADER, "unavailable");
6289
+ return next();
6290
+ }
6291
+ if (!shouldEnforce) {
6292
+ if (config.setPassThroughHeader) {
6293
+ res.setHeader("X-Astra-Gateway-Mode", "enforced");
6294
+ res.setHeader("X-Astra-Gateway-Reason", "evaluated-not-enforced");
6295
+ }
6296
+ if (shouldRecordDecisions && sessionId) {
6297
+ recordDecision(config, sessionId, "granted").catch(() => {
6298
+ });
6299
+ }
6300
+ return next();
6301
+ }
5866
6302
  if (!result.policyAllowed) {
5867
6303
  if (shouldRecordDecisions && sessionId) {
5868
6304
  recordDecision(config, sessionId, "denied", result.denialReasons?.[0]).catch(() => {
@@ -5882,17 +6318,6 @@ function createMcpMiddleware(options) {
5882
6318
  onDenied(result, req, res);
5883
6319
  return;
5884
6320
  }
5885
- if (!shouldEnforce) {
5886
- if (config.setPassThroughHeader) {
5887
- res.setHeader("X-Astra-Gateway-Mode", "enforced");
5888
- res.setHeader("X-Astra-Gateway-Reason", "evaluated-not-enforced");
5889
- }
5890
- if (shouldRecordDecisions && sessionId) {
5891
- recordDecision(config, sessionId, "granted").catch(() => {
5892
- });
5893
- }
5894
- return next();
5895
- }
5896
6321
  if (effectiveAstraId) {
5897
6322
  res.setHeader(
5898
6323
  MCP_VERIFIED_HOP_HEADER,
@@ -5933,14 +6358,6 @@ function createMcpMiddleware(options) {
5933
6358
  verifiedAt: /* @__PURE__ */ new Date(),
5934
6359
  correlationId
5935
6360
  };
5936
- const catchUrls = config.apiBaseUrl ? await getWellKnownUrls(config.apiBaseUrl).catch(() => void 0) : void 0;
5937
- if (catchUrls) {
5938
- result.guidance = {
5939
- message: `Middleware threw ${errorClass} \u2014 failing closed`,
5940
- registrationUrl: catchUrls.registrationUrl,
5941
- documentationUrl: catchUrls.documentationUrl
5942
- };
5943
- }
5944
6361
  dedupeFailures2(result);
5945
6362
  return onDenied(result, req, res);
5946
6363
  }
@@ -9948,6 +10365,7 @@ function parseYaml(yamlContent) {
9948
10365
  RegistrationTimeoutError,
9949
10366
  SDK_USER_AGENT,
9950
10367
  TRUST_LEVEL_RANGES,
10368
+ VERIFICATION_STATUS_HEADER,
9951
10369
  VERSION,
9952
10370
  _resetEdgeConfigCache,
9953
10371
  agent,
@@ -9955,9 +10373,11 @@ function parseYaml(yamlContent) {
9955
10373
  awaitStepUpApproval,
9956
10374
  buildGuidance,
9957
10375
  buildSdkObservedMetadata,
10376
+ buildVerificationUnavailableBody,
9958
10377
  clearCache,
9959
10378
  createMcpMiddleware,
9960
10379
  degradeToObserve,
10380
+ denyStatusFor,
9961
10381
  deriveConnectionFromHeaders,
9962
10382
  detectPlatformFingerprint,
9963
10383
  detectRuntime,
@@ -9974,6 +10394,8 @@ function parseYaml(yamlContent) {
9974
10394
  getWellKnownUrls,
9975
10395
  hasCredentials,
9976
10396
  isEdgeConfig,
10397
+ isRejectedIdentityClaim,
10398
+ isVerificationUnavailable,
9977
10399
  isVerifiedHopValidFor,
9978
10400
  matchEdgePathRule,
9979
10401
  matchPlatformSignature,
@@ -9993,6 +10415,7 @@ function parseYaml(yamlContent) {
9993
10415
  serializeVerifiedHop,
9994
10416
  setMcpMeta,
9995
10417
  transport,
10418
+ unavailableRetryAfterSeconds,
9996
10419
  validateLocalPolicy,
9997
10420
  verify
9998
10421
  });