@astrasyncai/verification-gateway 4.2.0 → 4.3.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 (112) hide show
  1. package/README.md +45 -21
  2. package/dist/adapter-interface/interface.d.mts +2 -2
  3. package/dist/adapter-interface/interface.d.ts +2 -2
  4. package/dist/adapters/express.d.mts +2 -2
  5. package/dist/adapters/express.d.ts +2 -2
  6. package/dist/adapters/express.js +56 -4
  7. package/dist/adapters/express.js.map +1 -1
  8. package/dist/adapters/express.mjs +56 -4
  9. package/dist/adapters/express.mjs.map +1 -1
  10. package/dist/adapters/mcp.d.mts +38 -30
  11. package/dist/adapters/mcp.d.ts +38 -30
  12. package/dist/adapters/mcp.js +22 -5
  13. package/dist/adapters/mcp.js.map +1 -1
  14. package/dist/adapters/mcp.mjs +22 -5
  15. package/dist/adapters/mcp.mjs.map +1 -1
  16. package/dist/adapters/nextjs.d.mts +2 -2
  17. package/dist/adapters/nextjs.d.ts +2 -2
  18. package/dist/adapters/nextjs.js +54 -4
  19. package/dist/adapters/nextjs.js.map +1 -1
  20. package/dist/adapters/nextjs.mjs +54 -4
  21. package/dist/adapters/nextjs.mjs.map +1 -1
  22. package/dist/adapters/sdk.d.mts +2 -2
  23. package/dist/adapters/sdk.d.ts +2 -2
  24. package/dist/agent/index.d.mts +2 -2
  25. package/dist/agent/index.d.ts +2 -2
  26. package/dist/agent/index.js +2 -2
  27. package/dist/agent/index.js.map +1 -1
  28. package/dist/agent/index.mjs +2 -2
  29. package/dist/agent/index.mjs.map +1 -1
  30. package/dist/bin/astrasync-claude-hook.js +2 -2
  31. package/dist/bin/astrasync-codex-hook.js +2 -2
  32. package/dist/bin/astrasync-guard.js +2 -2
  33. package/dist/bin/astrasync.js +14 -4
  34. package/dist/browser/background.js +2 -2
  35. package/dist/browser/background.js.map +1 -1
  36. package/dist/browser/background.mjs +2 -2
  37. package/dist/browser/background.mjs.map +1 -1
  38. package/dist/browser/browser-adapter.d.mts +2 -2
  39. package/dist/browser/browser-adapter.d.ts +2 -2
  40. package/dist/claude-code/claude-code-adapter.d.mts +2 -2
  41. package/dist/claude-code/claude-code-adapter.d.ts +2 -2
  42. package/dist/cli/index.d.mts +2 -2
  43. package/dist/cli/index.d.ts +2 -2
  44. package/dist/codex/index.d.mts +2 -2
  45. package/dist/codex/index.d.ts +2 -2
  46. package/dist/codex/index.js +2 -2
  47. package/dist/codex/index.js.map +1 -1
  48. package/dist/codex/index.mjs +2 -2
  49. package/dist/codex/index.mjs.map +1 -1
  50. package/dist/cursor/cursor-adapter.d.mts +2 -2
  51. package/dist/cursor/cursor-adapter.d.ts +2 -2
  52. package/dist/cursor/extension.d.mts +2 -2
  53. package/dist/cursor/extension.d.ts +2 -2
  54. package/dist/cursor/extension.js +2 -2
  55. package/dist/cursor/extension.js.map +1 -1
  56. package/dist/cursor/extension.mjs +2 -2
  57. package/dist/cursor/extension.mjs.map +1 -1
  58. package/dist/edge-config.d.mts +1 -1
  59. package/dist/edge-config.d.ts +1 -1
  60. package/dist/edge-core/index.d.mts +1 -1
  61. package/dist/edge-core/index.d.ts +1 -1
  62. package/dist/edge-core/index.js +25 -5
  63. package/dist/edge-core/index.js.map +1 -1
  64. package/dist/edge-core/index.mjs +25 -5
  65. package/dist/edge-core/index.mjs.map +1 -1
  66. package/dist/{express-D_4hTn5Z.d.mts → express-CR6F3njD.d.mts} +1 -1
  67. package/dist/{express-BVd1_3FE.d.ts → express-DaqL11tx.d.ts} +1 -1
  68. package/dist/gateway/gateway.d.mts +2 -2
  69. package/dist/gateway/gateway.d.ts +2 -2
  70. package/dist/gateway/gateway.js +2 -2
  71. package/dist/gateway/gateway.js.map +1 -1
  72. package/dist/gateway/gateway.mjs +2 -2
  73. package/dist/gateway/gateway.mjs.map +1 -1
  74. package/dist/git-trigger/git-hooks.d.mts +2 -2
  75. package/dist/git-trigger/git-hooks.d.ts +2 -2
  76. package/dist/{index-B0YHu_SP.d.ts → index-B5Ts1WtM.d.ts} +3 -3
  77. package/dist/{index-T1aBoUcc.d.ts → index-BfIxCYIZ.d.ts} +1 -1
  78. package/dist/{index-BPEBlOsE.d.mts → index-Cub7lK-T.d.mts} +3 -3
  79. package/dist/{index-DQb5-_1X.d.mts → index-CwAh7Tln.d.mts} +1 -1
  80. package/dist/index.d.mts +7 -7
  81. package/dist/index.d.ts +7 -7
  82. package/dist/index.js +74 -35
  83. package/dist/index.js.map +1 -1
  84. package/dist/index.mjs +71 -32
  85. package/dist/index.mjs.map +1 -1
  86. package/dist/local-evaluator/evaluator.d.mts +2 -2
  87. package/dist/local-evaluator/evaluator.d.ts +2 -2
  88. package/dist/metadata-capture.d.mts +18 -5
  89. package/dist/metadata-capture.d.ts +18 -5
  90. package/dist/metadata-capture.js +21 -4
  91. package/dist/metadata-capture.js.map +1 -1
  92. package/dist/metadata-capture.mjs +20 -4
  93. package/dist/metadata-capture.mjs.map +1 -1
  94. package/dist/{nextjs-w7RTbP1P.d.ts → nextjs-DL6uE1ye.d.ts} +1 -1
  95. package/dist/{nextjs-WyeVr2Kp.d.mts → nextjs-DlX6xwbU.d.mts} +1 -1
  96. package/dist/{sdk-CbTNIkAa.d.mts → sdk-Bbh9B_dw.d.mts} +1 -1
  97. package/dist/{sdk-QeX0Z8Ho.d.ts → sdk-C6SASmsh.d.ts} +1 -1
  98. package/dist/transport/index.d.mts +2 -2
  99. package/dist/transport/index.d.ts +2 -2
  100. package/dist/transport/index.js +5 -5
  101. package/dist/transport/index.js.map +1 -1
  102. package/dist/transport/index.mjs +2 -2
  103. package/dist/transport/index.mjs.map +1 -1
  104. package/dist/{types-r850cOt0.d.mts → types-C0zfSXMB.d.mts} +22 -0
  105. package/dist/{types-DqfPU5Bl.d.mts → types-C7Rb-w0d.d.mts} +1 -1
  106. package/dist/{types-sMxBT-nM.d.ts → types-DwSfO7Sb.d.ts} +22 -0
  107. package/dist/{types-BLUx92FJ.d.ts → types-nIh3HtuA.d.ts} +1 -1
  108. package/dist/ui/index.d.mts +1 -1
  109. package/dist/ui/index.d.ts +1 -1
  110. package/dist/verify.d.mts +1 -1
  111. package/dist/verify.d.ts +1 -1
  112. package/package.json +2 -4
@@ -1,7 +1,44 @@
1
1
  import { Request, Response, RequestHandler } from 'express';
2
- import { a as AccessLevel, G as GatewayConfig, x as VerificationResult } from '../types-r850cOt0.mjs';
2
+ import { a as AccessLevel, G as GatewayConfig, x as VerificationResult } from '../types-C0zfSXMB.mjs';
3
3
  import '../metadata-capture.mjs';
4
4
 
5
+ /**
6
+ * X-Astra-Verified-Hop — cross-hop verify-access dedupe marker.
7
+ *
8
+ * Header carrying upstream verify-access proof so an inner-hop endpoint can
9
+ * dedupe (skip verify-access when the same ASTRA-id was already verified a
10
+ * few ms earlier). Emitted by the MCP adapter toward tool fetches and by the
11
+ * edge gateway toward the origin at authenticate/authorize depth. Value
12
+ * format:
13
+ *
14
+ * {astraId};{sessionId};{checkedAt-ms}
15
+ *
16
+ * Receivers MUST validate that `checkedAt` is recent (≤ 60s window
17
+ * recommended) and that `astraId` matches the agent identity claimed on the
18
+ * inner hop. The header alone is NOT proof-of-identity — it's an UNSIGNED
19
+ * dedupe advisory: trust it (`trustVerifiedHop`) only where every network
20
+ * path to the inner hop crosses a stripping gateway or an equivalent trusted
21
+ * boundary, exactly like the unsigned X-AstraSync-* attestation headers.
22
+ * Pair with the existing X-Astra-Id auth.
23
+ */
24
+ declare const MCP_VERIFIED_HOP_HEADER = "X-Astra-Verified-Hop";
25
+ interface VerifiedHopMarker {
26
+ astraId: string;
27
+ sessionId?: string;
28
+ checkedAt: number;
29
+ }
30
+ declare function serializeVerifiedHop(marker: VerifiedHopMarker): string;
31
+ declare function parseVerifiedHop(value: string | undefined | null): VerifiedHopMarker | null;
32
+ /**
33
+ * Returns true when `marker.astraId` matches the inner-hop's claimed
34
+ * ASTRA-id AND the marker is recent enough. Inner-hop middleware uses this
35
+ * to skip a duplicate verify-access call.
36
+ */
37
+ declare function isVerifiedHopValidFor(marker: VerifiedHopMarker | null, expectedAstraId: string, opts?: {
38
+ maxAgeMs?: number;
39
+ now?: number;
40
+ }): boolean;
41
+
5
42
  /**
6
43
  * MCP server-side helpers — companion to `transport/mcp.ts` (which handles the
7
44
  * agent-side `_meta.astrasync` block).
@@ -31,35 +68,6 @@ import '../metadata-capture.mjs';
31
68
  * The Express MCP adapter is in `adapters/mcp.ts` and consumes these.
32
69
  */
33
70
 
34
- /**
35
- * Header carrying upstream verify-access proof so an inner-hop REST endpoint
36
- * can dedupe (skip verify-access when the same ASTRA-id was already verified
37
- * a few ms earlier). Value format:
38
- *
39
- * {astraId};{sessionId};{checkedAt-ms}
40
- *
41
- * Receivers MUST validate that `checkedAt` is recent (≤ 60s window
42
- * recommended) and that `astraId` matches the agent identity claimed on the
43
- * inner hop. The header alone is NOT proof-of-identity — it's a dedupe
44
- * advisory. Pair with the existing X-Astra-Id auth.
45
- */
46
- declare const MCP_VERIFIED_HOP_HEADER = "X-Astra-Verified-Hop";
47
- interface VerifiedHopMarker {
48
- astraId: string;
49
- sessionId?: string;
50
- checkedAt: number;
51
- }
52
- declare function serializeVerifiedHop(marker: VerifiedHopMarker): string;
53
- declare function parseVerifiedHop(value: string | undefined | null): VerifiedHopMarker | null;
54
- /**
55
- * Returns true when `marker.astraId` matches the inner-hop's claimed
56
- * ASTRA-id AND the marker is recent enough. Inner-hop middleware uses this
57
- * to skip a duplicate verify-access call.
58
- */
59
- declare function isVerifiedHopValidFor(marker: VerifiedHopMarker | null, expectedAstraId: string, opts?: {
60
- maxAgeMs?: number;
61
- now?: number;
62
- }): boolean;
63
71
  /**
64
72
  * Output of `parseMcpJsonRpc`. Self-describing so the middleware doesn't have
65
73
  * to re-introspect the body to figure out gating.
@@ -1,7 +1,44 @@
1
1
  import { Request, Response, RequestHandler } from 'express';
2
- import { a as AccessLevel, G as GatewayConfig, x as VerificationResult } from '../types-sMxBT-nM.js';
2
+ import { a as AccessLevel, G as GatewayConfig, x as VerificationResult } from '../types-DwSfO7Sb.js';
3
3
  import '../metadata-capture.js';
4
4
 
5
+ /**
6
+ * X-Astra-Verified-Hop — cross-hop verify-access dedupe marker.
7
+ *
8
+ * Header carrying upstream verify-access proof so an inner-hop endpoint can
9
+ * dedupe (skip verify-access when the same ASTRA-id was already verified a
10
+ * few ms earlier). Emitted by the MCP adapter toward tool fetches and by the
11
+ * edge gateway toward the origin at authenticate/authorize depth. Value
12
+ * format:
13
+ *
14
+ * {astraId};{sessionId};{checkedAt-ms}
15
+ *
16
+ * Receivers MUST validate that `checkedAt` is recent (≤ 60s window
17
+ * recommended) and that `astraId` matches the agent identity claimed on the
18
+ * inner hop. The header alone is NOT proof-of-identity — it's an UNSIGNED
19
+ * dedupe advisory: trust it (`trustVerifiedHop`) only where every network
20
+ * path to the inner hop crosses a stripping gateway or an equivalent trusted
21
+ * boundary, exactly like the unsigned X-AstraSync-* attestation headers.
22
+ * Pair with the existing X-Astra-Id auth.
23
+ */
24
+ declare const MCP_VERIFIED_HOP_HEADER = "X-Astra-Verified-Hop";
25
+ interface VerifiedHopMarker {
26
+ astraId: string;
27
+ sessionId?: string;
28
+ checkedAt: number;
29
+ }
30
+ declare function serializeVerifiedHop(marker: VerifiedHopMarker): string;
31
+ declare function parseVerifiedHop(value: string | undefined | null): VerifiedHopMarker | null;
32
+ /**
33
+ * Returns true when `marker.astraId` matches the inner-hop's claimed
34
+ * ASTRA-id AND the marker is recent enough. Inner-hop middleware uses this
35
+ * to skip a duplicate verify-access call.
36
+ */
37
+ declare function isVerifiedHopValidFor(marker: VerifiedHopMarker | null, expectedAstraId: string, opts?: {
38
+ maxAgeMs?: number;
39
+ now?: number;
40
+ }): boolean;
41
+
5
42
  /**
6
43
  * MCP server-side helpers — companion to `transport/mcp.ts` (which handles the
7
44
  * agent-side `_meta.astrasync` block).
@@ -31,35 +68,6 @@ import '../metadata-capture.js';
31
68
  * The Express MCP adapter is in `adapters/mcp.ts` and consumes these.
32
69
  */
33
70
 
34
- /**
35
- * Header carrying upstream verify-access proof so an inner-hop REST endpoint
36
- * can dedupe (skip verify-access when the same ASTRA-id was already verified
37
- * a few ms earlier). Value format:
38
- *
39
- * {astraId};{sessionId};{checkedAt-ms}
40
- *
41
- * Receivers MUST validate that `checkedAt` is recent (≤ 60s window
42
- * recommended) and that `astraId` matches the agent identity claimed on the
43
- * inner hop. The header alone is NOT proof-of-identity — it's a dedupe
44
- * advisory. Pair with the existing X-Astra-Id auth.
45
- */
46
- declare const MCP_VERIFIED_HOP_HEADER = "X-Astra-Verified-Hop";
47
- interface VerifiedHopMarker {
48
- astraId: string;
49
- sessionId?: string;
50
- checkedAt: number;
51
- }
52
- declare function serializeVerifiedHop(marker: VerifiedHopMarker): string;
53
- declare function parseVerifiedHop(value: string | undefined | null): VerifiedHopMarker | null;
54
- /**
55
- * Returns true when `marker.astraId` matches the inner-hop's claimed
56
- * ASTRA-id AND the marker is recent enough. Inner-hop middleware uses this
57
- * to skip a duplicate verify-access call.
58
- */
59
- declare function isVerifiedHopValidFor(marker: VerifiedHopMarker | null, expectedAstraId: string, opts?: {
60
- maxAgeMs?: number;
61
- now?: number;
62
- }): boolean;
63
71
  /**
64
72
  * Output of `parseMcpJsonRpc`. Self-describing so the middleware doesn't have
65
73
  * to re-introspect the body to figure out gating.
@@ -644,7 +644,9 @@ var SECRET_HEADER_NAMES = /* @__PURE__ */ new Set([
644
644
  "x-astrasync-signature",
645
645
  "x-astrasync-secret",
646
646
  "x-hub-signature",
647
- "x-hub-signature-256"
647
+ "x-hub-signature-256",
648
+ // Short-lived verify dedupe token — must never persist in stored metadata.
649
+ "x-astra-verified-hop"
648
650
  ]);
649
651
  var SECRET_HEADER_PREFIXES = ["x-astrasync-", "kya-", "kya_"];
650
652
  var CREDENTIAL_HEADER_NAMES = /* @__PURE__ */ new Set([
@@ -779,16 +781,25 @@ var CONNECTION_HEADER_SOURCES = [
779
781
  ["cf-ipcountry", "x-vercel-ip-country", "cloudfront-viewer-country", "fastly-geo-country"]
780
782
  ],
781
783
  ["region", ["x-vercel-ip-country-region", "cloudfront-viewer-country-region"]],
784
+ ["countryRegionName", ["cloudfront-viewer-country-region-name"]],
782
785
  ["city", ["x-vercel-ip-city", "cloudfront-viewer-city"]],
783
786
  ["asn", ["cloudfront-viewer-asn"]],
784
787
  ["tlsVersion", ["cloudfront-viewer-tls"]],
785
788
  ["httpVersion", ["cloudfront-viewer-http-version"]],
789
+ ["timeZone", ["x-vercel-ip-timezone", "cloudfront-viewer-time-zone"]],
790
+ ["metroCode", ["cloudfront-viewer-metro-code"]],
786
791
  // TLS fingerprints can only be computed where TLS terminates. When a CDN
787
792
  // terminates TLS in front of the merchant, its fingerprint headers ARE the
788
793
  // connection-layer truth — normalising them here is the permanent design.
789
- ["tlsFingerprint", ["cf-ja3-hash"]],
790
- ["ja4", ["cf-ja4"]]
794
+ // CloudFront delivers JA3/JA4 only via an origin request policy and only
795
+ // for HTTPS viewer connections.
796
+ ["tlsFingerprint", ["cf-ja3-hash", "cloudfront-viewer-ja3-fingerprint"]],
797
+ ["ja4", ["cf-ja4", "cloudfront-viewer-ja4-fingerprint"]],
798
+ // Header-structure fingerprint: browser/SDK-distinctive header ordering.
799
+ ["headerOrder", ["cloudfront-viewer-header-order"]],
800
+ ["headerCount", ["cloudfront-viewer-header-count"]]
791
801
  ];
802
+ var MAX_CONNECTION_VALUE_CHARS = 256;
792
803
  function deriveConnectionFromHeaders(headers) {
793
804
  if (!headers) return void 0;
794
805
  const lower = {};
@@ -801,11 +812,15 @@ function deriveConnectionFromHeaders(headers) {
801
812
  for (const source of sources) {
802
813
  const value = lower[source]?.trim();
803
814
  if (value) {
804
- connection[key] = value;
815
+ connection[key] = value.slice(0, MAX_CONNECTION_VALUE_CHARS);
805
816
  break;
806
817
  }
807
818
  }
808
819
  }
820
+ if (!connection.ip) {
821
+ const addr = lower["cloudfront-viewer-address"]?.trim();
822
+ if (addr) connection.ip = addr.replace(/:\d+$/, "");
823
+ }
809
824
  if (!connection.ip) {
810
825
  const xff = lower["x-forwarded-for"];
811
826
  const client = xff?.split(",")[0]?.trim();
@@ -904,7 +919,7 @@ async function awaitStepUpApproval(config, approval) {
904
919
  return "timeout";
905
920
  }
906
921
 
907
- // src/transport/mcp-server.ts
922
+ // src/verified-hop.ts
908
923
  var MCP_VERIFIED_HOP_HEADER = "X-Astra-Verified-Hop";
909
924
  var MCP_VERIFIED_HOP_MAX_AGE_MS = 6e4;
910
925
  function serializeVerifiedHop(marker) {
@@ -931,6 +946,8 @@ function isVerifiedHopValidFor(marker, expectedAstraId, opts = {}) {
931
946
  const now = opts.now ?? Date.now();
932
947
  return now - marker.checkedAt <= maxAge && now >= marker.checkedAt;
933
948
  }
949
+
950
+ // src/transport/mcp-server.ts
934
951
  function parseMcpJsonRpc(body) {
935
952
  if (!body || typeof body !== "object" || Array.isArray(body)) return null;
936
953
  const obj = body;