@astrasyncai/verification-gateway 5.13.0 → 5.15.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 +27 -17
  2. package/dist/adapters/express.d.mts +1 -1
  3. package/dist/adapters/express.d.ts +1 -1
  4. package/dist/adapters/express.js +504 -249
  5. package/dist/adapters/express.js.map +1 -1
  6. package/dist/adapters/express.mjs +504 -249
  7. package/dist/adapters/express.mjs.map +1 -1
  8. package/dist/adapters/mcp.d.mts +1 -1
  9. package/dist/adapters/mcp.d.ts +1 -1
  10. package/dist/adapters/mcp.js +20 -6
  11. package/dist/adapters/mcp.js.map +1 -1
  12. package/dist/adapters/mcp.mjs +20 -6
  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 +487 -248
  17. package/dist/adapters/nextjs.js.map +1 -1
  18. package/dist/adapters/nextjs.mjs +487 -248
  19. package/dist/adapters/nextjs.mjs.map +1 -1
  20. package/dist/adapters/sdk.d.mts +18 -10
  21. package/dist/adapters/sdk.d.ts +18 -10
  22. package/dist/adapters/sdk.js +80 -23
  23. package/dist/adapters/sdk.js.map +1 -1
  24. package/dist/adapters/sdk.mjs +80 -23
  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 +82 -20
  31. package/dist/bin/astrasync-codex-hook.js +82 -20
  32. package/dist/bin/astrasync-guard.js +82 -20
  33. package/dist/bin/astrasync.js +316 -43
  34. package/dist/browser/background.js +77 -15
  35. package/dist/browser/background.js.map +1 -1
  36. package/dist/browser/background.mjs +87 -15
  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 +82 -20
  43. package/dist/codex/index.js.map +1 -1
  44. package/dist/codex/index.mjs +92 -20
  45. package/dist/codex/index.mjs.map +1 -1
  46. package/dist/cursor/extension.js +82 -20
  47. package/dist/cursor/extension.js.map +1 -1
  48. package/dist/cursor/extension.mjs +92 -20
  49. package/dist/cursor/extension.mjs.map +1 -1
  50. package/dist/edge-config.d.mts +31 -2
  51. package/dist/edge-config.d.ts +31 -2
  52. package/dist/edge-config.js +35 -5
  53. package/dist/edge-config.js.map +1 -1
  54. package/dist/edge-config.mjs +32 -4
  55. package/dist/edge-config.mjs.map +1 -1
  56. package/dist/edge-core/index.d.mts +43 -6
  57. package/dist/edge-core/index.d.ts +43 -6
  58. package/dist/edge-core/index.js +120 -19
  59. package/dist/edge-core/index.js.map +1 -1
  60. package/dist/edge-core/index.mjs +118 -19
  61. package/dist/edge-core/index.mjs.map +1 -1
  62. package/dist/gateway/gateway.js +77 -15
  63. package/dist/gateway/gateway.js.map +1 -1
  64. package/dist/gateway/gateway.mjs +87 -15
  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 +1314 -34
  69. package/dist/index.d.ts +1314 -34
  70. package/dist/index.js +5143 -2621
  71. package/dist/index.js.map +1 -1
  72. package/dist/index.mjs +5090 -2623
  73. package/dist/index.mjs.map +1 -1
  74. package/dist/registration/index.d.mts +28 -2
  75. package/dist/registration/index.d.ts +28 -2
  76. package/dist/registration/index.js +18 -3
  77. package/dist/registration/index.js.map +1 -1
  78. package/dist/registration/index.mjs +15 -2
  79. package/dist/registration/index.mjs.map +1 -1
  80. package/dist/transport/index.d.mts +7 -5
  81. package/dist/transport/index.d.ts +7 -5
  82. package/dist/transport/index.js +61 -5
  83. package/dist/transport/index.js.map +1 -1
  84. package/dist/transport/index.mjs +67 -11
  85. package/dist/transport/index.mjs.map +1 -1
  86. package/dist/{types-C_b4QTyO.d.ts → types-DtJjlW4O.d.ts} +104 -10
  87. package/dist/{types-BCkwBA84.d.mts → types-Dxf9DBpr.d.mts} +106 -12
  88. package/dist/{types-BCkwBA84.d.ts → types-Dxf9DBpr.d.ts} +106 -12
  89. package/dist/{types-DlshIIR-.d.mts → types-Eg6VoBNH.d.mts} +104 -10
  90. package/dist/ui/index.d.mts +1 -1
  91. package/dist/ui/index.d.ts +1 -1
  92. package/dist/verify.d.mts +1 -1
  93. package/dist/verify.d.ts +1 -1
  94. package/dist/verify.js +20 -6
  95. package/dist/verify.js.map +1 -1
  96. package/dist/verify.mjs +20 -6
  97. package/dist/verify.mjs.map +1 -1
  98. package/package.json +1 -1
@@ -1,6 +1,6 @@
1
1
  import { EdgeMode, EdgeVerificationDepth, EdgeConfig } from '../edge-config.js';
2
2
  import { PlatformFingerprint } from '../platform-signatures.js';
3
- import { C as CommerceArtifactsPayload, V as VerificationRequest } from '../types-C_b4QTyO.js';
3
+ import { C as CommerceArtifactsPayload, V as VerificationRequest } from '../types-DtJjlW4O.js';
4
4
  import { verify } from '../verify.js';
5
5
  import { ObservedMetadata } from '../metadata-capture.js';
6
6
 
@@ -140,6 +140,7 @@ interface TierOutcome {
140
140
  };
141
141
  stepUp?: {
142
142
  pollUrl?: string;
143
+ approvalUrl?: string;
143
144
  expiresAt?: string;
144
145
  };
145
146
  correlationId?: string;
@@ -306,6 +307,13 @@ interface EdgeEvaluation {
306
307
  * response).
307
308
  */
308
309
  declare function evaluateEdgeRequest(options: EdgeCoreOptions, req: NormalizedRequest, config: EdgeConfig, apiKey: string | undefined): Promise<EdgeEvaluation>;
310
+ /** Negotiated TLS version from CloudFront-Viewer-TLS (`TLSv1.3:cipher:…`). */
311
+ declare function negotiatedTlsVersion(req: NormalizedRequest): string | null;
312
+ /** The violation when the request's TLS is below `minTls`; null = fine or unknown. */
313
+ declare function checkMinTls(req: NormalizedRequest, minTls: EdgeConfig['minTls']): {
314
+ minimum: string;
315
+ negotiated: string;
316
+ } | null;
309
317
 
310
318
  /**
311
319
  * Decision → abstract outcome-application wiring. Executed in BOTH modes
@@ -369,9 +377,14 @@ declare function applyOutcome(options: {
369
377
  * without spending an attempt; a 401 on the key falls back to
370
378
  * unauthenticated delivery);
371
379
  * - collapses identical requests (same counterparty, IP, UA, method, path,
372
- * attempt id) inside a 60s window into one item carrying `repeatCount`;
380
+ * attempt id) inside a 60s window into one item carrying `repeatCount`
381
+ * — but only while that item is still queued (5.14.0, round 27.6: the
382
+ * old 60s held aggregate waited for a later invocation that a reclaimed
383
+ * Lambda container never gets; S1003 measured ~68% delivery);
373
384
  * - stamps each batch with `meta { droppedSinceLast, queueDepth, adapter,
374
- * version }` so the backend can report delivery loss.
385
+ * version, containerId, enqueuedTotal, deliveredTotal, droppedTotal }`
386
+ * so the backend can report delivery loss — including what a container
387
+ * that stops reporting left behind (5.14.0).
375
388
  * Delivery is at-least-once: a POST that times out after the backend
376
389
  * recorded it is retried.
377
390
  */
@@ -398,6 +411,16 @@ interface BeaconBatchMeta {
398
411
  queueDepth: number;
399
412
  adapter: string;
400
413
  version: string;
414
+ /**
415
+ * 5.14.0 (round 27.6): this container's id (one per cold start) and its
416
+ * cumulative item counters. The backend keeps the last report per
417
+ * container, so items stranded in a container that stops reporting (a
418
+ * reclaimed Lambda) are counted instead of silently vanishing.
419
+ */
420
+ containerId: string;
421
+ enqueuedTotal: number;
422
+ deliveredTotal: number;
423
+ droppedTotal: number;
401
424
  }
402
425
  interface BeaconBufferOptions {
403
426
  /** Max queued items; the oldest is dropped (and counted) beyond it. Default 1000. */
@@ -408,6 +431,16 @@ interface BeaconBufferOptions {
408
431
  maxAttempts?: number;
409
432
  /** Repeat-collapse window. Default 60s. */
410
433
  collapseWindowMs?: number;
434
+ /**
435
+ * Pre-5.14 behaviour: hold a repeat aggregate until its collapse window
436
+ * closes. Off by default — a held item waits up to 60s for a later
437
+ * invocation of the same container, and a container that is never
438
+ * invoked again loses it (round 27.6, S1003: ~32% loss on staging). Kept
439
+ * only so the delivery simulator can compare the two.
440
+ */
441
+ holdRepeats?: boolean;
442
+ /** Container id stamped on batch meta. Default: one per module load. */
443
+ containerId?: string;
411
444
  /** Max distinct repeat keys remembered (LRU). Default 1000. */
412
445
  collapseMaxKeys?: number;
413
446
  /** Per-POST timeout (the budget is the caller's; this bounds a hung POST). Default 10s. */
@@ -422,6 +455,7 @@ declare class BeaconBuffer {
422
455
  private droppedSinceLast;
423
456
  private droppedTotal;
424
457
  private deliveredTotal;
458
+ private enqueuedTotal;
425
459
  private inFlight;
426
460
  private backoffUntil;
427
461
  private readonly collapse;
@@ -431,8 +465,9 @@ declare class BeaconBuffer {
431
465
  constructor(options?: BeaconBufferOptions);
432
466
  /**
433
467
  * Queue one beacon. With a `collapseKey`, a repeat inside the window is
434
- * merged into a held aggregate (sent when the window closes) instead of
435
- * becoming its own item.
468
+ * merged into this key's item while that item is still queued (not yet in
469
+ * flight). Once it has left, the repeat becomes a new item, sendable on
470
+ * this flush — nothing waits for a later invocation (round 27.6).
436
471
  */
437
472
  enqueue(dest: BeaconDestination, item: BeaconItem, collapseKey?: string): void;
438
473
  /**
@@ -448,6 +483,7 @@ declare class BeaconBuffer {
448
483
  droppedSinceLast: number;
449
484
  droppedTotal: number;
450
485
  deliveredTotal: number;
486
+ enqueuedTotal: number;
451
487
  flushing: boolean;
452
488
  };
453
489
  private push;
@@ -510,6 +546,7 @@ interface ManualReviewBody {
510
546
  message: string;
511
547
  stepUpApproval?: {
512
548
  pollUrl?: string;
549
+ approvalUrl?: string;
513
550
  expiresAt?: string;
514
551
  };
515
552
  correlationId?: string;
@@ -576,4 +613,4 @@ declare function requestUrl(req: NormalizedRequest, host: string): string;
576
613
  */
577
614
  declare function buildObservedMetadata(req: NormalizedRequest, queryValueAllowlist?: string[]): ObservedMetadata;
578
615
 
579
- export { ASAT_HEADERS, type BeaconBatchMeta, BeaconBuffer, type BeaconBufferOptions, type BeaconDestination, type BeaconItem, type Classification, type DenyBody, type DetectedCommerce, type EdgeCoreOptions, type EdgeDecision, type EdgeEvaluation, type EdgeLogger, type EffectivePolicy, type ManualReviewBody, type NormalizedRequest, type OutcomeApplication, type PlatformIo, type TierOutcome, type TrafficTier, _patterns, applyOutcome, buildDenyBody, buildManualReviewBody, buildObservedMetadata, buildVerificationRequest, classify, detectCommerce, emitBeacon, evaluateEdgeRequest, getBeaconBuffer, headerValue, outcomeFromVerifyResult, passUntouched, requestUrl, resetBeaconBuffer, resolvePolicy, runTier, sampled, withBudget };
616
+ export { ASAT_HEADERS, type BeaconBatchMeta, BeaconBuffer, type BeaconBufferOptions, type BeaconDestination, type BeaconItem, type Classification, type DenyBody, type DetectedCommerce, type EdgeCoreOptions, type EdgeDecision, type EdgeEvaluation, type EdgeLogger, type EffectivePolicy, type ManualReviewBody, type NormalizedRequest, type OutcomeApplication, type PlatformIo, type TierOutcome, type TrafficTier, _patterns, applyOutcome, buildDenyBody, buildManualReviewBody, buildObservedMetadata, buildVerificationRequest, checkMinTls, classify, detectCommerce, emitBeacon, evaluateEdgeRequest, getBeaconBuffer, headerValue, negotiatedTlsVersion, outcomeFromVerifyResult, passUntouched, requestUrl, resetBeaconBuffer, resolvePolicy, runTier, sampled, withBudget };
@@ -28,12 +28,14 @@ __export(edge_core_exports, {
28
28
  buildManualReviewBody: () => buildManualReviewBody,
29
29
  buildObservedMetadata: () => buildObservedMetadata,
30
30
  buildVerificationRequest: () => buildVerificationRequest,
31
+ checkMinTls: () => checkMinTls,
31
32
  classify: () => classify,
32
33
  detectCommerce: () => detectCommerce,
33
34
  emitBeacon: () => emitBeacon,
34
35
  evaluateEdgeRequest: () => evaluateEdgeRequest,
35
36
  getBeaconBuffer: () => getBeaconBuffer,
36
37
  headerValue: () => headerValue,
38
+ negotiatedTlsVersion: () => negotiatedTlsVersion,
37
39
  outcomeFromVerifyResult: () => outcomeFromVerifyResult,
38
40
  passUntouched: () => passUntouched,
39
41
  requestUrl: () => requestUrl,
@@ -46,7 +48,7 @@ __export(edge_core_exports, {
46
48
  module.exports = __toCommonJS(edge_core_exports);
47
49
 
48
50
  // src/version.ts
49
- var SDK_VERSION = "5.13.0";
51
+ var SDK_VERSION = "5.15.0";
50
52
 
51
53
  // src/http.ts
52
54
  var SDK_USER_AGENT = `astrasync-sdk/${SDK_VERSION}`;
@@ -66,6 +68,29 @@ function withUserAgent(initHeaders) {
66
68
  }
67
69
  var sdkFetch = (input, init) => fetch(input, { ...init, headers: withUserAgent(init?.headers) });
68
70
 
71
+ // src/route-pattern.ts
72
+ function routePatternToRegExp(pattern, opts = {}) {
73
+ let source = "";
74
+ for (let i = 0; i < pattern.length; i++) {
75
+ const ch = pattern[i];
76
+ if (ch === "*") {
77
+ source += ".*";
78
+ } else if (ch === ":" && /[A-Za-z_]/.test(pattern[i + 1] ?? "") && (i === 0 || pattern[i - 1] === "/")) {
79
+ let j = i + 1;
80
+ while (j < pattern.length && /[A-Za-z0-9_]/.test(pattern[j])) j++;
81
+ source += "[^/]+";
82
+ i = j - 1;
83
+ } else {
84
+ source += ch.replace(/[.+?^${}()|[\]\\/]/g, "\\$&");
85
+ }
86
+ }
87
+ try {
88
+ return new RegExp(`^${source}$`, opts.caseInsensitive ? "i" : "");
89
+ } catch {
90
+ return null;
91
+ }
92
+ }
93
+
69
94
  // src/edge-config.ts
70
95
  var DEFAULT_EDGE_CONFIG = Object.freeze({
71
96
  version: 1,
@@ -84,8 +109,7 @@ function matchEdgePathRule(rules, path) {
84
109
  return void 0;
85
110
  }
86
111
  function globToRegExp(pattern) {
87
- const escaped = pattern.replace(/[.+?^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*");
88
- return new RegExp(`^${escaped}$`, "i");
112
+ return routePatternToRegExp(pattern, { caseInsensitive: true }) ?? /$^/;
89
113
  }
90
114
 
91
115
  // src/metadata-capture.ts
@@ -730,6 +754,7 @@ async function callVerifyAccessAPI(config, request) {
730
754
  if (requestData.invocationProtocol) body.invocationProtocol = requestData.invocationProtocol;
731
755
  if (requestData.commercePhase) body.commercePhase = requestData.commercePhase;
732
756
  if (requestData.checkoutSessionId) body.checkoutSessionId = requestData.checkoutSessionId;
757
+ if (requestData.checkoutJwt) body.checkoutJwt = requestData.checkoutJwt;
733
758
  if (requestData.checkoutItems) body.checkoutItems = requestData.checkoutItems;
734
759
  if (requestData.buyerEmail) body.buyerEmail = requestData.buyerEmail;
735
760
  if (requestData.commerceArtifacts) body.commerceArtifacts = requestData.commerceArtifacts;
@@ -880,7 +905,8 @@ async function verify(config, request, options) {
880
905
  "[VerificationGateway] minTrustScore / minTrustScoreForFull are deprecated in v2.3.0 and have no effect. Server is now the single source of truth for access decisions (verified ID + runtime challenge + PDLSS + trust score). To gate access to an endpoint, configure the endpoint's trust_score_requirement server-side."
881
906
  );
882
907
  }
883
- if (mergedConfig.cacheTtl !== 0 && !options?.bypassCache) {
908
+ const uncacheable = Boolean(request.commerceArtifacts);
909
+ if (mergedConfig.cacheTtl !== 0 && !options?.bypassCache && !uncacheable) {
884
910
  const cached = getCachedResult(request, mergedConfig.counterpartyId);
885
911
  if (cached) {
886
912
  if (mergedConfig.debug) {
@@ -961,7 +987,10 @@ async function verify(config, request, options) {
961
987
  // MERCHANT caller only (bridge callers strip it before the agent plane).
962
988
  settlementToken: apiResponse.settlementToken,
963
989
  // 5.6.0: fulfilment contact — merchant-only lane, same strip rule.
964
- fulfilment: apiResponse.fulfilment
990
+ fulfilment: apiResponse.fulfilment,
991
+ mandates: apiResponse.mandates,
992
+ kyaToken: apiResponse.kyaToken,
993
+ aep: apiResponse.aep
965
994
  };
966
995
  return result2;
967
996
  }
@@ -971,7 +1000,10 @@ async function verify(config, request, options) {
971
1000
  trustScore: apiResponse.agent.trustScore,
972
1001
  trustLevel: getTrustLevel(apiResponse.agent.trustScore),
973
1002
  blockchainAnchored: apiResponse.agent.blockchainStatus === "anchored",
974
- status: apiResponse.agent.agentStatus
1003
+ status: apiResponse.agent.agentStatus,
1004
+ ...apiResponse.agent.protocolIdentities && {
1005
+ protocolIdentities: apiResponse.agent.protocolIdentities
1006
+ }
975
1007
  } : void 0;
976
1008
  const developer = apiResponse.developer ? {
977
1009
  astradId: apiResponse.developer.kyaOwnerId,
@@ -1022,7 +1054,11 @@ async function verify(config, request, options) {
1022
1054
  settlementOutcome: apiResponse.settlementOutcome,
1023
1055
  settlementToken: apiResponse.settlementToken,
1024
1056
  // 5.6.0: fulfilment contact — merchant-only lane, same strip rule.
1025
- fulfilment: apiResponse.fulfilment
1057
+ fulfilment: apiResponse.fulfilment,
1058
+ // 5.15.0: merchant-lane AP2 mandates + KYAPay identity token.
1059
+ mandates: apiResponse.mandates,
1060
+ kyaToken: apiResponse.kyaToken,
1061
+ aep: apiResponse.aep
1026
1062
  };
1027
1063
  if (result.recommendation === "deny") {
1028
1064
  result.policyAllowed = false;
@@ -1042,7 +1078,9 @@ async function verify(config, request, options) {
1042
1078
  }
1043
1079
  const escalates = result.requiresStepUp === true || result.requiresApproval === true || result.recommendation === "step_up_required";
1044
1080
  if (mergedConfig.cacheTtl !== 0 && result.recommendation !== "deny" && !escalates) {
1045
- cacheResult(request, result, mergedConfig.cacheTtl, mergedConfig.counterpartyId);
1081
+ if (!uncacheable) {
1082
+ cacheResult(request, result, mergedConfig.cacheTtl, mergedConfig.counterpartyId);
1083
+ }
1046
1084
  }
1047
1085
  return result;
1048
1086
  }
@@ -1241,7 +1279,7 @@ function detectCommerce(req, host) {
1241
1279
  };
1242
1280
  }
1243
1281
  }
1244
- if (authHeader && /^Payment\s+/i.test(authHeader)) {
1282
+ if (authHeader && /^Payment\s+/i.test(authHeader) || headerValue(req, "payment-authorization")) {
1245
1283
  return {
1246
1284
  protocol: "mpp",
1247
1285
  artifacts: {
@@ -1256,7 +1294,7 @@ function detectCommerce(req, host) {
1256
1294
  evidence: truncated
1257
1295
  };
1258
1296
  }
1259
- if (headerValue(req, "x-payment")) {
1297
+ if (headerValue(req, "payment-signature") || headerValue(req, "x-payment")) {
1260
1298
  return {
1261
1299
  protocol: "x402",
1262
1300
  artifacts: {
@@ -1581,6 +1619,11 @@ async function withBudget(promise, ms) {
1581
1619
  if (timer) clearTimeout(timer);
1582
1620
  }
1583
1621
  }
1622
+ var CONTAINER_ID = (() => {
1623
+ const c = globalThis.crypto;
1624
+ if (c?.randomUUID) return c.randomUUID();
1625
+ return `c-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 12)}`;
1626
+ })();
1584
1627
  var destKeyOf = (d) => `${d.apiBaseUrl}\0${d.apiKey ?? ""}\0${d.counterparty}\0${d.adapter ?? ""}`;
1585
1628
  var BeaconBuffer = class {
1586
1629
  constructor(options = {}) {
@@ -1588,6 +1631,7 @@ var BeaconBuffer = class {
1588
1631
  this.droppedSinceLast = 0;
1589
1632
  this.droppedTotal = 0;
1590
1633
  this.deliveredTotal = 0;
1634
+ this.enqueuedTotal = 0;
1591
1635
  this.backoffUntil = 0;
1592
1636
  this.collapse = /* @__PURE__ */ new Map();
1593
1637
  /** Keys the backend answered 401 for — later batches go unauthenticated. */
@@ -1600,13 +1644,16 @@ var BeaconBuffer = class {
1600
1644
  collapseMaxKeys: options.collapseMaxKeys ?? 1e3,
1601
1645
  requestTimeoutMs: options.requestTimeoutMs ?? 1e4,
1602
1646
  retryBackoffMs: options.retryBackoffMs ?? 1e3,
1647
+ holdRepeats: options.holdRepeats ?? false,
1648
+ containerId: options.containerId ?? CONTAINER_ID,
1603
1649
  now: options.now ?? Date.now
1604
1650
  };
1605
1651
  }
1606
1652
  /**
1607
1653
  * Queue one beacon. With a `collapseKey`, a repeat inside the window is
1608
- * merged into a held aggregate (sent when the window closes) instead of
1609
- * becoming its own item.
1654
+ * merged into this key's item while that item is still queued (not yet in
1655
+ * flight). Once it has left, the repeat becomes a new item, sendable on
1656
+ * this flush — nothing waits for a later invocation (round 27.6).
1610
1657
  */
1611
1658
  enqueue(dest, item, collapseKey) {
1612
1659
  const now = this.opts.now();
@@ -1619,12 +1666,15 @@ var BeaconBuffer = class {
1619
1666
  return;
1620
1667
  }
1621
1668
  }
1622
- const held = this.push(
1623
- dest,
1624
- { ...item, repeatCount: 1 },
1625
- entry.firstSeenAt + this.opts.collapseWindowMs
1626
- );
1627
- entry.held = held;
1669
+ if (this.opts.holdRepeats) {
1670
+ entry.held = this.push(
1671
+ dest,
1672
+ { ...item, repeatCount: 1 },
1673
+ entry.firstSeenAt + this.opts.collapseWindowMs
1674
+ );
1675
+ return;
1676
+ }
1677
+ entry.first = this.push(dest, { ...item, repeatCount: 1 }, now);
1628
1678
  return;
1629
1679
  }
1630
1680
  this.collapse.delete(collapseKey);
@@ -1660,6 +1710,7 @@ var BeaconBuffer = class {
1660
1710
  droppedSinceLast: this.droppedSinceLast,
1661
1711
  droppedTotal: this.droppedTotal,
1662
1712
  deliveredTotal: this.deliveredTotal,
1713
+ enqueuedTotal: this.enqueuedTotal,
1663
1714
  flushing: this.inFlight !== void 0
1664
1715
  };
1665
1716
  }
@@ -1674,6 +1725,7 @@ var BeaconBuffer = class {
1674
1725
  inFlight: false
1675
1726
  };
1676
1727
  this.queue.push(entry);
1728
+ this.enqueuedTotal += 1;
1677
1729
  return entry;
1678
1730
  }
1679
1731
  dropOldest() {
@@ -1719,7 +1771,11 @@ var BeaconBuffer = class {
1719
1771
  droppedSinceLast: reportedDropped,
1720
1772
  queueDepth: this.queue.length,
1721
1773
  adapter: dest.adapter ?? "edge-core",
1722
- version: SDK_VERSION
1774
+ version: SDK_VERSION,
1775
+ containerId: this.opts.containerId,
1776
+ enqueuedTotal: this.enqueuedTotal,
1777
+ deliveredTotal: this.deliveredTotal,
1778
+ droppedTotal: this.droppedTotal
1723
1779
  };
1724
1780
  const controller = typeof AbortController !== "undefined" ? new AbortController() : void 0;
1725
1781
  const response = await withBudget(
@@ -1900,6 +1956,7 @@ function outcomeFromVerifyResult(classification, result) {
1900
1956
  outcome.reasons = ["step-up approval required"];
1901
1957
  outcome.stepUp = {
1902
1958
  pollUrl: result.stepUpApproval?.pollUrl,
1959
+ approvalUrl: result.stepUpApproval?.approvalUrl,
1903
1960
  expiresAt: result.stepUpApproval?.expiresAt
1904
1961
  };
1905
1962
  return outcome;
@@ -2045,6 +2102,20 @@ async function evaluateEdgeRequest(options, req, config, apiKey) {
2045
2102
  if (classification.tier === "human" || classification.tier === "self") {
2046
2103
  return { policy, classification, application: passUntouched() };
2047
2104
  }
2105
+ const tls = checkMinTls(req, config.minTls);
2106
+ if (tls) {
2107
+ if (policy.mode === "enforce") {
2108
+ options.log?.(
2109
+ "info",
2110
+ `TLS ${tls.negotiated} below ${tls.minimum}: ${req.method} ${req.uri}`
2111
+ );
2112
+ return { policy, classification, application: tlsUpgradeRequired(tls) };
2113
+ }
2114
+ options.log?.(
2115
+ "info",
2116
+ `[OBSERVE] would have required TLS ${tls.minimum} (got ${tls.negotiated}): ${req.method} ${req.uri}`
2117
+ );
2118
+ }
2048
2119
  const outcome = await runTier(options, req, classification, policy, apiKey, {
2049
2120
  sampling: policy.sampling ?? config.sampling,
2050
2121
  queryValueAllowlist: config.queryValueAllowlist
@@ -2069,6 +2140,34 @@ async function evaluateEdgeRequest(options, req, config, apiKey) {
2069
2140
  return { policy, application: passUntouched() };
2070
2141
  }
2071
2142
  }
2143
+ function negotiatedTlsVersion(req) {
2144
+ const raw = req.connection?.tlsVersion ?? headerValue(req, "cloudfront-viewer-tls");
2145
+ const m = raw ? /^TLSv(1(?:\.\d)?)/i.exec(raw) : null;
2146
+ return m ? m[1] === "1" ? "1.0" : m[1] : null;
2147
+ }
2148
+ function checkMinTls(req, minTls) {
2149
+ if (!minTls) return null;
2150
+ const negotiated = negotiatedTlsVersion(req);
2151
+ if (!negotiated) return null;
2152
+ return Number(negotiated) < Number(minTls) ? { minimum: minTls, negotiated } : null;
2153
+ }
2154
+ function tlsUpgradeRequired(v) {
2155
+ return {
2156
+ action: "respond",
2157
+ status: 426,
2158
+ headers: {
2159
+ "content-type": "application/json",
2160
+ upgrade: `TLS/${v.minimum}`,
2161
+ connection: "Upgrade"
2162
+ },
2163
+ bodyJson: {
2164
+ error: "tls_version_too_low",
2165
+ minimum: `TLS ${v.minimum}`,
2166
+ negotiated: `TLS ${v.negotiated}`,
2167
+ message: `This endpoint requires TLS ${v.minimum} or later for agent requests. Reconnect with TLS ${v.minimum}.`
2168
+ }
2169
+ };
2170
+ }
2072
2171
  // Annotate the CommonJS export names for ESM import in node:
2073
2172
  0 && (module.exports = {
2074
2173
  ASAT_HEADERS,
@@ -2079,12 +2178,14 @@ async function evaluateEdgeRequest(options, req, config, apiKey) {
2079
2178
  buildManualReviewBody,
2080
2179
  buildObservedMetadata,
2081
2180
  buildVerificationRequest,
2181
+ checkMinTls,
2082
2182
  classify,
2083
2183
  detectCommerce,
2084
2184
  emitBeacon,
2085
2185
  evaluateEdgeRequest,
2086
2186
  getBeaconBuffer,
2087
2187
  headerValue,
2188
+ negotiatedTlsVersion,
2088
2189
  outcomeFromVerifyResult,
2089
2190
  passUntouched,
2090
2191
  requestUrl,