@astrasyncai/verification-gateway 2.1.0 → 2.2.3

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 (84) hide show
  1. package/README.md +64 -30
  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 +74 -95
  7. package/dist/adapters/express.js.map +1 -1
  8. package/dist/adapters/express.mjs +74 -95
  9. package/dist/adapters/express.mjs.map +1 -1
  10. package/dist/adapters/nextjs.d.mts +2 -2
  11. package/dist/adapters/nextjs.d.ts +2 -2
  12. package/dist/adapters/nextjs.js +74 -115
  13. package/dist/adapters/nextjs.js.map +1 -1
  14. package/dist/adapters/nextjs.mjs +74 -115
  15. package/dist/adapters/nextjs.mjs.map +1 -1
  16. package/dist/adapters/sdk.d.mts +2 -2
  17. package/dist/adapters/sdk.d.ts +2 -2
  18. package/dist/adapters/sdk.js +56 -55
  19. package/dist/adapters/sdk.js.map +1 -1
  20. package/dist/adapters/sdk.mjs +56 -55
  21. package/dist/adapters/sdk.mjs.map +1 -1
  22. package/dist/agent/index.d.mts +2 -2
  23. package/dist/agent/index.d.ts +2 -2
  24. package/dist/agent/index.js +68 -2
  25. package/dist/agent/index.js.map +1 -1
  26. package/dist/agent/index.mjs +66 -2
  27. package/dist/agent/index.mjs.map +1 -1
  28. package/dist/browser/background.js +56 -55
  29. package/dist/browser/background.js.map +1 -1
  30. package/dist/browser/background.mjs +56 -55
  31. package/dist/browser/background.mjs.map +1 -1
  32. package/dist/browser/browser-adapter.d.mts +2 -2
  33. package/dist/browser/browser-adapter.d.ts +2 -2
  34. package/dist/cli/index.d.mts +2 -2
  35. package/dist/cli/index.d.ts +2 -2
  36. package/dist/cursor/cursor-adapter.d.mts +2 -2
  37. package/dist/cursor/cursor-adapter.d.ts +2 -2
  38. package/dist/cursor/extension.d.mts +2 -2
  39. package/dist/cursor/extension.d.ts +2 -2
  40. package/dist/cursor/extension.js +56 -55
  41. package/dist/cursor/extension.js.map +1 -1
  42. package/dist/cursor/extension.mjs +56 -55
  43. package/dist/cursor/extension.mjs.map +1 -1
  44. package/dist/{express-Bcl-uBUE.d.ts → express-BtKlLI8U.d.ts} +2 -2
  45. package/dist/{express-CtwDIZyF.d.mts → express-DgwpS8Ha.d.mts} +2 -2
  46. package/dist/gateway/gateway.d.mts +2 -2
  47. package/dist/gateway/gateway.d.ts +2 -2
  48. package/dist/gateway/gateway.js +56 -55
  49. package/dist/gateway/gateway.js.map +1 -1
  50. package/dist/gateway/gateway.mjs +56 -55
  51. package/dist/gateway/gateway.mjs.map +1 -1
  52. package/dist/git-trigger/git-hooks.d.mts +2 -2
  53. package/dist/git-trigger/git-hooks.d.ts +2 -2
  54. package/dist/{index-BY8yQ8N8.d.mts → index-AzhK20t0.d.mts} +46 -3
  55. package/dist/{index-CME6r4uH.d.ts → index-Ba0Lvsjo.d.ts} +1 -1
  56. package/dist/{index-3NRaBNvp.d.mts → index-BaxpmTGA.d.mts} +1 -1
  57. package/dist/{index-CtYSYwn3.d.ts → index-DpJS1JEI.d.ts} +46 -3
  58. package/dist/index.d.mts +7 -7
  59. package/dist/index.d.ts +7 -7
  60. package/dist/index.js +158 -117
  61. package/dist/index.js.map +1 -1
  62. package/dist/index.mjs +158 -117
  63. package/dist/index.mjs.map +1 -1
  64. package/dist/local-evaluator/evaluator.d.mts +2 -2
  65. package/dist/local-evaluator/evaluator.d.ts +2 -2
  66. package/dist/{nextjs-CEldnIJ9.d.ts → nextjs-B2kg19c1.d.ts} +1 -1
  67. package/dist/{nextjs-BQyMCSx_.d.mts → nextjs-ZymQ8jDh.d.mts} +1 -1
  68. package/dist/{sdk-BhvuJSrH.d.mts → sdk-B7id0VFS.d.mts} +2 -2
  69. package/dist/{sdk-BlyVSC_S.d.ts → sdk-Bso0FSI0.d.ts} +2 -2
  70. package/dist/transport/index.d.mts +2 -2
  71. package/dist/transport/index.d.ts +2 -2
  72. package/dist/{types-79qS7aON.d.ts → types-BYKAY6Cc.d.ts} +1 -1
  73. package/dist/{types-jJnPXStc.d.mts → types-CgXPKUwi.d.mts} +1 -1
  74. package/dist/{types-CxQwJKbd.d.mts → types-DOrqNMgy.d.mts} +79 -13
  75. package/dist/{types-CxQwJKbd.d.ts → types-DOrqNMgy.d.ts} +79 -13
  76. package/dist/ui/index.d.mts +1 -1
  77. package/dist/ui/index.d.ts +1 -1
  78. package/dist/webhooks.d.mts +59 -0
  79. package/dist/webhooks.d.ts +59 -0
  80. package/dist/webhooks.js +81 -0
  81. package/dist/webhooks.js.map +1 -0
  82. package/dist/webhooks.mjs +55 -0
  83. package/dist/webhooks.mjs.map +1 -0
  84. package/package.json +8 -3
package/README.md CHANGED
@@ -2,6 +2,18 @@
2
2
 
3
3
  Universal Verification Gateway for AstraSync KYA Platform - verify AI agents across any counterparty type.
4
4
 
5
+ ## Which package do I install?
6
+
7
+ AstraSync ships two npm packages with deliberately distinct roles. Pick by who you are, not by what you're building:
8
+
9
+ | You are… | Install | Use it for |
10
+ | --------------------------------------------------------------------------------------------- | ------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ |
11
+ | **A merchant / counterparty** running an API, MCP server, or website that AI agents call into | `@astrasyncai/verification-gateway` (this package) | Verifying inbound agents before they hit your endpoint. Express + Next.js middleware, Commerce Shield, webhook verifier. |
12
+ | **An agent author** building an AI agent that calls out to other people's services | `@astrasyncai/sdk` (the agent-side SDK on npm, separate repo) | Registering your agent with AstraSync, attaching credentials to outbound HTTP / MCP / A2A calls, KYD onboarding. |
13
+ | **A platform / orchestrator** doing both ends in one place | Both | The two roles compose: each side's flow is independent. |
14
+
15
+ > Both packages talk to the same backend — `POST /agents/verify-access`. The contract is shared; the role is just which side you're sitting on.
16
+
5
17
  ## Overview
6
18
 
7
19
  The Verification Gateway provides a single, universal solution for verifying AI agents. One codebase, multiple deployment targets:
@@ -28,15 +40,17 @@ import { createMiddleware } from '@astrasyncai/verification-gateway/express';
28
40
 
29
41
  const app = express();
30
42
 
31
- app.use(createMiddleware({
32
- apiBaseUrl: 'https://api.astrasync.ai',
33
- routes: [
34
- { pattern: '/api/public/*', method: '*', minAccessLevel: 'none' },
35
- { pattern: '/api/data/*', method: 'GET', minAccessLevel: 'read-only' },
36
- { pattern: '/api/data/*', method: '*', minAccessLevel: 'standard' },
37
- { pattern: '/api/admin/*', method: '*', minAccessLevel: 'internal' },
38
- ],
39
- }));
43
+ app.use(
44
+ createMiddleware({
45
+ apiBaseUrl: 'https://astrasync.ai/api',
46
+ routes: [
47
+ { pattern: '/api/public/*', method: '*', minAccessLevel: 'none' },
48
+ { pattern: '/api/data/*', method: 'GET', minAccessLevel: 'read-only' },
49
+ { pattern: '/api/data/*', method: '*', minAccessLevel: 'standard' },
50
+ { pattern: '/api/admin/*', method: '*', minAccessLevel: 'internal' },
51
+ ],
52
+ })
53
+ );
40
54
  ```
41
55
 
42
56
  ### Next.js Middleware
@@ -82,23 +96,23 @@ if (result.verified && result.accessLevel !== 'none') {
82
96
 
83
97
  ## Access Levels
84
98
 
85
- | Level | Description |
86
- |-------|-------------|
87
- | `none` | No credentials provided |
88
- | `guidance` | Commerce Shield overlay shown |
89
- | `read-only` | Can browse, no mutations |
90
- | `standard` | Normal access per PDLSS |
91
- | `full` | Full access for high-trust agents |
92
- | `internal` | Organization member access |
99
+ | Level | Description |
100
+ | ----------- | --------------------------------- |
101
+ | `none` | No credentials provided |
102
+ | `guidance` | Commerce Shield overlay shown |
103
+ | `read-only` | Can browse, no mutations |
104
+ | `standard` | Normal access per PDLSS |
105
+ | `full` | Full access for high-trust agents |
106
+ | `internal` | Organization member access |
93
107
 
94
108
  ## Trust Levels
95
109
 
96
- | Level | Score Range |
97
- |-------|-------------|
98
- | BRONZE | 0-39 |
99
- | SILVER | 40-59 |
100
- | GOLD | 60-79 |
101
- | PLATINUM | 80-100 |
110
+ | Level | Score Range |
111
+ | -------- | ----------- |
112
+ | BRONZE | 0-39 |
113
+ | SILVER | 40-59 |
114
+ | GOLD | 60-79 |
115
+ | PLATINUM | 80-100 |
102
116
 
103
117
  ## UI Components
104
118
 
@@ -184,16 +198,36 @@ interface VerificationResult {
184
198
 
185
199
  ```typescript
186
200
  interface GatewayConfig {
187
- // Required
201
+ // Required. Always include the /api path prefix — for prod use
202
+ // 'https://astrasync.ai/api', for staging 'https://staging.astrasync.ai/api'.
188
203
  apiBaseUrl: string;
189
204
 
190
205
  // Optional
191
- apiKey?: string; // For authenticated requests
192
- defaultAccessLevel?: string; // Default: 'guidance'
193
- minTrustScore?: number; // For 'standard' access (default: 40)
194
- minTrustScoreForFull?: number; // For 'full' access (default: 70)
195
- cacheTtl?: number; // Cache duration in seconds (default: 300)
196
- debug?: boolean; // Enable debug logging
206
+ apiKey?: string; // For authenticated requests
207
+ defaultAccessLevel?: string; // Default: 'guidance'
208
+ cacheTtl?: number; // Cache duration in seconds (default: 300)
209
+ debug?: boolean; // Enable debug logging
210
+
211
+ // Counterparty attribution (v2.2.3+)
212
+ counterpartyUrl?: string; // Sent with verify-access for analytics
213
+ counterpartyType?: 'agent' | 'api' | 'mcp_server' | 'website' | 'other' | 'unknown';
214
+ counterpartyId?: string; // Your ASTRAE-id (issued at endpoint registration);
215
+ // forwarded on every verify-access call so the server attributes traffic
216
+ // directly to this endpoint rather than resolving by URL.
217
+
218
+ // Init self-test (v2.2.3+) — fires a HEAD probe to verify-access on first
219
+ // call and warns if apiBaseUrl is pointing at HTML (catches the marketing-
220
+ // 404 case). Set true for tests where the extra request is undesirable.
221
+ disableInitChecks?: boolean;
222
+
223
+ // @deprecated — removed as functional config in v2.3.0. Server is the
224
+ // single source of truth for access-level decisions; the SDK reads
225
+ // access.accessLevel from the response verbatim. Setting these has no
226
+ // effect (a one-shot console.warn fires). To gate access to your
227
+ // endpoint, configure trust_score_requirement server-side via the
228
+ // /api/endpoints registration.
229
+ minTrustScore?: number;
230
+ minTrustScoreForFull?: number;
197
231
  }
198
232
  ```
199
233
 
@@ -1,6 +1,6 @@
1
1
  import { AstraSyncGateway } from '../gateway/gateway.mjs';
2
- import { A as AgentAction, I as InterceptResult, P as PDLSSContext, V as VerificationDecision } from '../types-jJnPXStc.mjs';
3
- import '../types-CxQwJKbd.mjs';
2
+ import { A as AgentAction, I as InterceptResult, P as PDLSSContext, V as VerificationDecision } from '../types-CgXPKUwi.mjs';
3
+ import '../types-DOrqNMgy.mjs';
4
4
 
5
5
  /**
6
6
  * PlatformAdapter Interface
@@ -1,6 +1,6 @@
1
1
  import { AstraSyncGateway } from '../gateway/gateway.js';
2
- import { A as AgentAction, I as InterceptResult, P as PDLSSContext, V as VerificationDecision } from '../types-79qS7aON.js';
3
- import '../types-CxQwJKbd.js';
2
+ import { A as AgentAction, I as InterceptResult, P as PDLSSContext, V as VerificationDecision } from '../types-BYKAY6Cc.js';
3
+ import '../types-DOrqNMgy.js';
4
4
 
5
5
  /**
6
6
  * PlatformAdapter Interface
@@ -1,3 +1,3 @@
1
1
  import 'express';
2
- import '../types-CxQwJKbd.mjs';
3
- export { c as createMiddleware, a as extractAstraSyncCredentials, r as requireAccess, v as verifyOnly } from '../express-CtwDIZyF.mjs';
2
+ import '../types-DOrqNMgy.mjs';
3
+ export { c as createMiddleware, a as extractAstraSyncCredentials, r as requireAccess, v as verifyOnly } from '../express-DgwpS8Ha.mjs';
@@ -1,3 +1,3 @@
1
1
  import 'express';
2
- import '../types-CxQwJKbd.js';
3
- export { c as createMiddleware, a as extractAstraSyncCredentials, r as requireAccess, v as verifyOnly } from '../express-Bcl-uBUE.js';
2
+ import '../types-DOrqNMgy.js';
3
+ export { c as createMiddleware, a as extractAstraSyncCredentials, r as requireAccess, v as verifyOnly } from '../express-BtKlLI8U.js';
@@ -36,15 +36,6 @@ var ACCESS_LEVEL_HIERARCHY = {
36
36
  full: 4,
37
37
  internal: 5
38
38
  };
39
- var DEFAULT_TRUST_THRESHOLDS = {
40
- none: 0,
41
- guidance: 0,
42
- "read-only": 20,
43
- standard: 40,
44
- full: 70,
45
- internal: 0
46
- // Internal is based on org membership, not score
47
- };
48
39
  function getTrustLevel(score) {
49
40
  if (score >= 80) return "PLATINUM";
50
41
  if (score >= 60) return "GOLD";
@@ -54,36 +45,39 @@ function getTrustLevel(score) {
54
45
  function hasMinimumAccess(actual, required) {
55
46
  return ACCESS_LEVEL_HIERARCHY[actual] >= ACCESS_LEVEL_HIERARCHY[required];
56
47
  }
57
- function getAccessLevelForScore(trustScore, thresholds = DEFAULT_TRUST_THRESHOLDS) {
58
- if (trustScore >= thresholds.full) return "full";
59
- if (trustScore >= thresholds.standard) return "standard";
60
- if (trustScore >= thresholds["read-only"]) return "read-only";
61
- return "guidance";
62
- }
63
- function determineAccessLevel(verified, trustScore, isOrgMember, customThresholds) {
64
- if (!verified) {
65
- return "guidance";
66
- }
67
- if (isOrgMember) {
68
- return "internal";
69
- }
70
- const thresholds = {
71
- ...DEFAULT_TRUST_THRESHOLDS,
72
- ...customThresholds
73
- };
74
- return getAccessLevelForScore(trustScore, thresholds);
75
- }
76
48
 
77
49
  // src/verify.ts
78
50
  var DEFAULT_CONFIG = {
79
- apiBaseUrl: "https://api.astrasync.ai",
51
+ apiBaseUrl: "https://astrasync.ai/api",
80
52
  defaultAccessLevel: "guidance",
81
- minTrustScore: 40,
82
- minTrustScoreForFull: 70,
53
+ // minTrustScore + minTrustScoreForFull deprecated in v2.3.0 — server decides.
83
54
  cacheTtl: 300,
84
55
  // 5 minutes
85
56
  debug: false
86
57
  };
58
+ var initCheckPerformed = false;
59
+ var deprecationWarningShown = false;
60
+ async function performInitCheck(apiBaseUrl, debug) {
61
+ initCheckPerformed = true;
62
+ try {
63
+ const probeUrl = `${apiBaseUrl}/agents/verify-access`;
64
+ const response = await fetch(probeUrl, { method: "HEAD" });
65
+ const contentType = response.headers.get("content-type") ?? "";
66
+ if (contentType.startsWith("text/html")) {
67
+ console.warn(
68
+ `[VerificationGateway] apiBaseUrl '${apiBaseUrl}' returned HTML (content-type: ${contentType}). This usually means apiBaseUrl is pointing at a marketing site instead of the API. Expected: 'https://astrasync.ai/api' (prod) or 'https://staging.astrasync.ai/api' (staging). Set disableInitChecks: true on GatewayConfig to silence this warning.`
69
+ );
70
+ } else if (debug) {
71
+ console.log(
72
+ `[VerificationGateway] init check passed for ${apiBaseUrl} (content-type: ${contentType})`
73
+ );
74
+ }
75
+ } catch (err) {
76
+ if (debug) {
77
+ console.log(`[VerificationGateway] init check failed (non-blocking): ${String(err)}`);
78
+ }
79
+ }
80
+ }
87
81
  var verificationCache = /* @__PURE__ */ new Map();
88
82
  function getCacheKey(credentials) {
89
83
  return `${credentials.astraId || ""}-${credentials.apiKey || ""}-${credentials.jwt || ""}`;
@@ -108,7 +102,7 @@ function cacheResult(credentials, result, ttlSeconds) {
108
102
  }
109
103
  function extractCredentials(headers, query) {
110
104
  const credentials = {};
111
- const astraIdHeader = headers["x-astra-id"] || headers["X-Astra-Id"] || headers["X-ASTRA-ID"];
105
+ const astraIdHeader = headers["x-astra-id"] || headers["X-Astra-Id"] || headers["X-ASTRA-ID"] || headers["x-astra-agentid"] || headers["X-Astra-AgentId"] || headers["x-astra-agent-id"] || headers["X-Astra-Agent-Id"] || headers["X-ASTRA-AGENT-ID"];
112
106
  if (astraIdHeader) {
113
107
  credentials.astraId = Array.isArray(astraIdHeader) ? astraIdHeader[0] : astraIdHeader;
114
108
  }
@@ -134,9 +128,6 @@ function extractCredentials(headers, query) {
134
128
  }
135
129
  return credentials;
136
130
  }
137
- function hasCredentials(credentials) {
138
- return !!(credentials.astraId || credentials.apiKey || credentials.jwt);
139
- }
140
131
  function createGuidanceResponse(config, reason) {
141
132
  const guidance = {
142
133
  message: "This service verifies AI agents before granting access. Please register your agent with AstraSync.",
@@ -160,7 +151,7 @@ function createGuidanceResponse(config, reason) {
160
151
  async function callVerifyAccessAPI(config, request) {
161
152
  const { credentials, ...requestData } = request;
162
153
  const body = {
163
- agentId: credentials.astraId,
154
+ ...credentials.astraId && { agentId: credentials.astraId },
164
155
  purpose: requestData.purpose || "general"
165
156
  };
166
157
  if (requestData.action) body.action = requestData.action;
@@ -172,21 +163,34 @@ async function callVerifyAccessAPI(config, request) {
172
163
  if (requestData.isSubAgentRequest) body.isSubAgentRequest = requestData.isSubAgentRequest;
173
164
  if (requestData.parentAgentId) body.parentAgentId = requestData.parentAgentId;
174
165
  if (requestData.subAgentDepth !== void 0) body.subAgentDepth = requestData.subAgentDepth;
175
- if (requestData.enableRuntimeChallenge) body.enableRuntimeChallenge = requestData.enableRuntimeChallenge;
166
+ if (requestData.enableRuntimeChallenge)
167
+ body.enableRuntimeChallenge = requestData.enableRuntimeChallenge;
176
168
  if (requestData.createSession) body.createSession = requestData.createSession;
177
169
  if (requestData.durationRequired) body.durationRequired = requestData.durationRequired;
178
170
  if (requestData.counterpartyType) body.counterpartyType = requestData.counterpartyType;
179
171
  if (requestData.counterpartyUrl) body.counterpartyUrl = requestData.counterpartyUrl;
180
- if (requestData.runtimeChallengeOptions) body.runtimeChallengeOptions = requestData.runtimeChallengeOptions;
172
+ if (config.counterpartyId) body.counterpartyId = config.counterpartyId;
173
+ if (requestData.runtimeChallengeOptions)
174
+ body.runtimeChallengeOptions = requestData.runtimeChallengeOptions;
175
+ if (requestData.callerMetadata || requestData.clientIp || requestData.userAgent) {
176
+ const meta = {
177
+ ...requestData.clientIp && { sourceIp: requestData.clientIp },
178
+ ...requestData.userAgent && { userAgent: requestData.userAgent },
179
+ ...requestData.callerMetadata
180
+ };
181
+ if (Object.keys(meta).length > 0) body.callerMetadata = meta;
182
+ }
181
183
  const headers = {
182
184
  "Content-Type": "application/json",
183
185
  ...config.customHeaders
184
186
  };
185
- if (config.apiKey) {
186
- headers["X-API-Key"] = config.apiKey;
187
- }
188
187
  if (credentials.authorizationHeader) {
189
188
  headers["Authorization"] = credentials.authorizationHeader;
189
+ } else if (config.apiKey) {
190
+ headers["Authorization"] = `Bearer ${config.apiKey}`;
191
+ }
192
+ if (config.apiKey) {
193
+ headers["X-API-Key"] = config.apiKey;
190
194
  }
191
195
  try {
192
196
  const response = await fetch(`${config.apiBaseUrl}/agents/verify-access`, {
@@ -212,8 +216,14 @@ async function callVerifyAccessAPI(config, request) {
212
216
  }
213
217
  async function verify(config, request) {
214
218
  const mergedConfig = { ...DEFAULT_CONFIG, ...config };
215
- if (!hasCredentials(request.credentials)) {
216
- return createGuidanceResponse(mergedConfig, "No agent credentials provided");
219
+ if (!initCheckPerformed && !mergedConfig.disableInitChecks && mergedConfig.apiBaseUrl) {
220
+ void performInitCheck(mergedConfig.apiBaseUrl, mergedConfig.debug);
221
+ }
222
+ if (!deprecationWarningShown && (config.minTrustScore !== void 0 || config.minTrustScoreForFull !== void 0)) {
223
+ deprecationWarningShown = true;
224
+ console.warn(
225
+ "[VerificationGateway] minTrustScore / minTrustScoreForFull are deprecated in v2.3.0 and have no effect. Server is now the single source of truth for access-level decisions (the SDK reads access.accessLevel from the verify-access response). To gate access to an endpoint, configure the endpoint's trust_score_requirement server-side."
226
+ );
217
227
  }
218
228
  if (mergedConfig.cacheTtl && mergedConfig.cacheTtl > 0) {
219
229
  const cached = getCachedResult(request.credentials);
@@ -285,18 +295,7 @@ async function verify(config, request) {
285
295
  selfInstantiationAllowed: apiResponse.access.pdlss.selfInstantiationAllowed,
286
296
  appliedPolicy: apiResponse.access.appliedPolicy
287
297
  } : void 0;
288
- const trustScore = agent?.trustScore || 0;
289
- const isOrgMember = false;
290
- const accessLevel = determineAccessLevel(
291
- true,
292
- trustScore,
293
- isOrgMember,
294
- {
295
- "read-only": 20,
296
- standard: mergedConfig.minTrustScore || 40,
297
- full: mergedConfig.minTrustScoreForFull || 70
298
- }
299
- );
298
+ const accessLevel = apiResponse.access?.accessLevel ?? "standard";
300
299
  const result = {
301
300
  verified: true,
302
301
  accessLevel,
@@ -318,7 +317,9 @@ async function verify(config, request) {
318
317
  if (result.recommendation === "deny") {
319
318
  result.verified = false;
320
319
  result.accessLevel = "none";
321
- result.denialReasons = result.recommendationReasons || ["Access denied by AstraSync recommendation"];
320
+ result.denialReasons = result.recommendationReasons || [
321
+ "Access denied by AstraSync recommendation"
322
+ ];
322
323
  if (result.runtimeChallenge) {
323
324
  result.guidance = {
324
325
  message: `Verification failed: ${result.runtimeChallenge.reason || "runtime challenge failed"}`,
@@ -340,7 +341,10 @@ async function verify(config, request) {
340
341
  }
341
342
  async function recordDecision(config, sessionId, decision, reason) {
342
343
  const headers = { "Content-Type": "application/json" };
343
- if (config.apiKey) headers["X-API-Key"] = config.apiKey;
344
+ if (config.apiKey) {
345
+ headers["Authorization"] = `Bearer ${config.apiKey}`;
346
+ headers["X-API-Key"] = config.apiKey;
347
+ }
344
348
  await fetch(`${config.apiBaseUrl}/agents/verify-access/${sessionId}/decision`, {
345
349
  method: "POST",
346
350
  headers,
@@ -348,15 +352,6 @@ async function recordDecision(config, sessionId, decision, reason) {
348
352
  }).catch(() => {
349
353
  });
350
354
  }
351
- async function reportUnregisteredAttempt(config, data) {
352
- const apiBaseUrl = config.apiBaseUrl || DEFAULT_CONFIG.apiBaseUrl;
353
- await fetch(`${apiBaseUrl}/verification-activity/unregistered-attempt`, {
354
- method: "POST",
355
- headers: { "Content-Type": "application/json" },
356
- body: JSON.stringify(data)
357
- }).catch(() => {
358
- });
359
- }
360
355
  async function reportCounterpartyPreCheckFailure(config, data) {
361
356
  const apiBaseUrl = config.apiBaseUrl || DEFAULT_CONFIG.apiBaseUrl;
362
357
  await fetch(`${apiBaseUrl}/verification-activity/counterparty-pre-check-failure`, {
@@ -541,32 +536,6 @@ function createMiddleware(options) {
541
536
  return next();
542
537
  }
543
538
  const credentials = customExtractCredentials ? customExtractCredentials(req) : defaultExtractCredentials(req);
544
- if (!hasCredentials(credentials) && routeConfig.minAccessLevel !== "guidance") {
545
- const counterpartyUrl2 = config.counterpartyUrl || `${req.protocol}://${req.get("host")}`;
546
- reportUnregisteredAttempt(config, {
547
- counterpartyUrl: counterpartyUrl2,
548
- counterpartyType: config.counterpartyType || "api",
549
- sourceIp: req.ip,
550
- userAgent: req.headers["user-agent"],
551
- requestPath: req.path,
552
- requestMethod: req.method
553
- }).catch(() => {
554
- });
555
- const result2 = {
556
- verified: false,
557
- accessLevel: "none",
558
- denialReasons: ["No agent credentials provided"],
559
- guidance: {
560
- message: "This endpoint requires agent verification. Please provide your ASTRA-ID.",
561
- registrationUrl: `${config.apiBaseUrl?.replace("/api", "")}/register`,
562
- documentationUrl: `${config.apiBaseUrl?.replace("/api", "")}/docs/agent-access`
563
- },
564
- verifiedAt: /* @__PURE__ */ new Date()
565
- };
566
- req.agentVerification = result2;
567
- onDenied(result2, req, res);
568
- return;
569
- }
570
539
  const purpose = customExtractPurpose ? customExtractPurpose(req) : defaultExtractPurpose(req);
571
540
  const astraCreds = extractAstraSyncCredentials(req);
572
541
  const counterpartyUrl = config.counterpartyUrl || `${req.protocol}://${req.get("host")}`;
@@ -597,18 +566,28 @@ function createMiddleware(options) {
597
566
  return;
598
567
  }
599
568
  const shouldRecordDecisions = recordDecisions !== false;
569
+ const forwardedFor = req.headers["x-forwarded-for"];
570
+ const forwardedForStr = Array.isArray(forwardedFor) ? forwardedFor.join(", ") : forwardedFor;
571
+ const originalClientIp = forwardedForStr ? forwardedForStr.split(",")[0].trim() : req.ip;
572
+ const agentCardUrl = typeof req.headers["x-astrasync-agent-card"] === "string" ? req.headers["x-astrasync-agent-card"] : void 0;
600
573
  const result = await verify(config, {
601
574
  credentials,
602
575
  purpose,
603
576
  action: req.method.toLowerCase(),
604
577
  resource: req.path,
605
- clientIp: req.ip,
606
- userAgent: req.headers["user-agent"],
607
578
  createSession: shouldRecordDecisions,
608
579
  counterpartyUrl,
609
580
  counterpartyType: config.counterpartyType || "api",
610
581
  enableRuntimeChallenge,
611
- durationRequired: astraCreds?.pdlss?.duration?.maxSessionDuration
582
+ durationRequired: astraCreds?.pdlss?.duration?.maxSessionDuration,
583
+ callerMetadata: {
584
+ sourceIp: originalClientIp,
585
+ userAgent: req.headers["user-agent"],
586
+ referer: req.headers.referer,
587
+ host: req.headers.host,
588
+ forwardedFor: forwardedForStr,
589
+ agentCardUrl
590
+ }
612
591
  });
613
592
  req.agentVerification = result;
614
593
  const sessionId = result.sessionId;