@astrasyncai/verification-gateway 3.11.1 → 4.0.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.
- package/dist/adapter-interface/interface.d.mts +2 -2
- package/dist/adapter-interface/interface.d.ts +2 -2
- package/dist/adapters/express.d.mts +2 -2
- package/dist/adapters/express.d.ts +2 -2
- package/dist/adapters/express.js +106 -10
- package/dist/adapters/express.js.map +1 -1
- package/dist/adapters/express.mjs +106 -10
- package/dist/adapters/express.mjs.map +1 -1
- package/dist/adapters/mcp.d.mts +1 -1
- package/dist/adapters/mcp.d.ts +1 -1
- package/dist/adapters/mcp.js +111 -10
- package/dist/adapters/mcp.js.map +1 -1
- package/dist/adapters/mcp.mjs +111 -10
- package/dist/adapters/mcp.mjs.map +1 -1
- package/dist/adapters/nextjs.d.mts +2 -2
- package/dist/adapters/nextjs.d.ts +2 -2
- package/dist/adapters/nextjs.js +107 -10
- package/dist/adapters/nextjs.js.map +1 -1
- package/dist/adapters/nextjs.mjs +107 -10
- package/dist/adapters/nextjs.mjs.map +1 -1
- package/dist/adapters/sdk.d.mts +2 -2
- package/dist/adapters/sdk.d.ts +2 -2
- package/dist/adapters/sdk.js +92 -10
- package/dist/adapters/sdk.js.map +1 -1
- package/dist/adapters/sdk.mjs +92 -10
- package/dist/adapters/sdk.mjs.map +1 -1
- package/dist/agent/index.d.mts +2 -2
- package/dist/agent/index.d.ts +2 -2
- package/dist/bin/astrasync-claude-hook.js +92 -10
- package/dist/bin/astrasync-codex-hook.js +92 -10
- package/dist/bin/astrasync-guard.js +92 -10
- package/dist/bin/astrasync.js +93 -10
- package/dist/browser/background.js +92 -10
- package/dist/browser/background.js.map +1 -1
- package/dist/browser/background.mjs +92 -10
- package/dist/browser/background.mjs.map +1 -1
- package/dist/browser/browser-adapter.d.mts +2 -2
- package/dist/browser/browser-adapter.d.ts +2 -2
- package/dist/claude-code/claude-code-adapter.d.mts +2 -2
- package/dist/claude-code/claude-code-adapter.d.ts +2 -2
- package/dist/cli/index.d.mts +2 -2
- package/dist/cli/index.d.ts +2 -2
- package/dist/codex/index.d.mts +2 -2
- package/dist/codex/index.d.ts +2 -2
- package/dist/codex/index.js +92 -10
- package/dist/codex/index.js.map +1 -1
- package/dist/codex/index.mjs +92 -10
- package/dist/codex/index.mjs.map +1 -1
- package/dist/cursor/cursor-adapter.d.mts +2 -2
- package/dist/cursor/cursor-adapter.d.ts +2 -2
- package/dist/cursor/extension.d.mts +2 -2
- package/dist/cursor/extension.d.ts +2 -2
- package/dist/cursor/extension.js +92 -10
- package/dist/cursor/extension.js.map +1 -1
- package/dist/cursor/extension.mjs +92 -10
- package/dist/cursor/extension.mjs.map +1 -1
- package/dist/edge-config.d.mts +1 -1
- package/dist/edge-config.d.ts +1 -1
- package/dist/{express-DCXa1oqj.d.mts → express-BZajRs4i.d.mts} +1 -1
- package/dist/{express-ClNtDhhc.d.ts → express-CjCUB1k7.d.ts} +1 -1
- package/dist/gateway/gateway.d.mts +2 -2
- package/dist/gateway/gateway.d.ts +2 -2
- package/dist/gateway/gateway.js +92 -10
- package/dist/gateway/gateway.js.map +1 -1
- package/dist/gateway/gateway.mjs +92 -10
- package/dist/gateway/gateway.mjs.map +1 -1
- package/dist/git-trigger/git-hooks.d.mts +2 -2
- package/dist/git-trigger/git-hooks.d.ts +2 -2
- package/dist/{index-BrNKDmiR.d.mts → index-B0cyMZDL.d.mts} +1 -1
- package/dist/{index-Dr_XiN65.d.mts → index-BRYteOqO.d.mts} +1 -1
- package/dist/{index-CfHurO1P.d.ts → index-BZQdVqNw.d.ts} +1 -1
- package/dist/{index-D2ztkumS.d.ts → index-adgKhujR.d.ts} +1 -1
- package/dist/index.d.mts +9 -9
- package/dist/index.d.ts +9 -9
- package/dist/index.js +160 -10
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +159 -10
- package/dist/index.mjs.map +1 -1
- package/dist/local-evaluator/evaluator.d.mts +2 -2
- package/dist/local-evaluator/evaluator.d.ts +2 -2
- package/dist/{nextjs-CEBVBsdi.d.ts → nextjs-D_iFf5k-.d.ts} +1 -1
- package/dist/{nextjs-DcQIk6Zj.d.mts → nextjs-DeUTnOBd.d.mts} +1 -1
- package/dist/{sdk-H0JCLW2y.d.ts → sdk-BM3mwEAq.d.ts} +1 -1
- package/dist/{sdk-CZkbSOeO.d.mts → sdk-_il1Q41f.d.mts} +1 -1
- package/dist/transport/index.d.mts +2 -2
- package/dist/transport/index.d.ts +2 -2
- package/dist/{types-sy3tq8lp.d.mts → types-BcDf9Kk0.d.mts} +118 -1
- package/dist/{types-DhFPiZ3t.d.ts → types-CHKCgDFC.d.ts} +1 -1
- package/dist/{types-cQVCMeNV.d.mts → types-DfnP7JiM.d.mts} +1 -1
- package/dist/{types-9tns4wyl.d.ts → types-fTQD448H.d.ts} +118 -1
- package/dist/ui/index.d.mts +1 -1
- package/dist/ui/index.d.ts +1 -1
- package/dist/verify.d.mts +15 -2
- package/dist/verify.d.ts +15 -2
- package/dist/verify.js +117 -10
- package/dist/verify.js.map +1 -1
- package/dist/verify.mjs +115 -10
- package/dist/verify.mjs.map +1 -1
- package/package.json +1 -1
package/dist/adapters/mcp.mjs
CHANGED
|
@@ -7,7 +7,7 @@ function getTrustLevel(score) {
|
|
|
7
7
|
}
|
|
8
8
|
|
|
9
9
|
// src/version.ts
|
|
10
|
-
var SDK_VERSION = "
|
|
10
|
+
var SDK_VERSION = "4.0.0";
|
|
11
11
|
|
|
12
12
|
// src/well-known.ts
|
|
13
13
|
var CACHE_TTL_MS = 60 * 60 * 1e3;
|
|
@@ -85,7 +85,7 @@ var DEFAULT_CONFIG = {
|
|
|
85
85
|
};
|
|
86
86
|
var initCheckPerformed = false;
|
|
87
87
|
var deprecationWarningShown = false;
|
|
88
|
-
async function performInitCheck(apiBaseUrl, debug, strictInit) {
|
|
88
|
+
async function performInitCheck(apiBaseUrl, debug, strictInit, apiKey) {
|
|
89
89
|
initCheckPerformed = true;
|
|
90
90
|
try {
|
|
91
91
|
const probeUrl = `${apiBaseUrl}/agents/verify-access`;
|
|
@@ -102,6 +102,28 @@ async function performInitCheck(apiBaseUrl, debug, strictInit) {
|
|
|
102
102
|
`[VerificationGateway] init check passed for ${apiBaseUrl} (content-type: ${contentType})`
|
|
103
103
|
);
|
|
104
104
|
}
|
|
105
|
+
if (apiKey) {
|
|
106
|
+
const selfCheck = await fetch(`${apiBaseUrl}/agents/verify-access/self-check`, {
|
|
107
|
+
headers: { Authorization: `Bearer ${apiKey}` }
|
|
108
|
+
});
|
|
109
|
+
if (selfCheck.status === 401) {
|
|
110
|
+
const body = await selfCheck.json().catch(() => ({}));
|
|
111
|
+
const message = `[VerificationGateway] the configured AstraSync API key was REJECTED at startup (${body.code ?? "api_key_invalid"}: ${body.message ?? "invalid key"}). Every inbound agent will be turned away until the key is rotated` + (body.remediation?.manageUrl ? ` at ${body.remediation.manageUrl}` : "") + `.`;
|
|
112
|
+
if (strictInit) {
|
|
113
|
+
throw new Error(`${message} (strictInit=true)`);
|
|
114
|
+
}
|
|
115
|
+
console.error(message);
|
|
116
|
+
} else if (selfCheck.ok) {
|
|
117
|
+
const body = await selfCheck.json().catch(() => ({}));
|
|
118
|
+
if (typeof body.daysToExpiry === "number" && body.daysToExpiry <= 7) {
|
|
119
|
+
console.warn(
|
|
120
|
+
`[VerificationGateway] the configured AstraSync API key expires in ${body.daysToExpiry} day(s) \u2014 rotate it at Settings \u2192 Developer Tools before integrations start failing.`
|
|
121
|
+
);
|
|
122
|
+
} else if (debug) {
|
|
123
|
+
console.log("[VerificationGateway] API key self-check passed");
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
105
127
|
} catch (err) {
|
|
106
128
|
if (strictInit) {
|
|
107
129
|
throw err;
|
|
@@ -213,8 +235,17 @@ function extractCredentials(headers, query) {
|
|
|
213
235
|
function createGuidanceResponse(_config, reason, options = {}) {
|
|
214
236
|
const source = options.source ?? "no_credentials";
|
|
215
237
|
const isApiError = source === "api_error";
|
|
238
|
+
const isMisconfig = source === "merchant_misconfig";
|
|
216
239
|
const urls = options.urls;
|
|
217
|
-
const guidance =
|
|
240
|
+
const guidance = isMisconfig ? {
|
|
241
|
+
message: "This site's AstraSync integration is misconfigured (its API key was revoked, expired, or rotated). Your identity and the AstraSync platform are fine \u2014 contact the site operator. Retrying will not help.",
|
|
242
|
+
registrationUrl: urls?.registrationUrl ?? "",
|
|
243
|
+
documentationUrl: options.remediation?.docsUrl ?? urls?.documentationUrl ?? "",
|
|
244
|
+
steps: [
|
|
245
|
+
"Report the failure to the site operator \u2014 their AstraSync API key needs rotating",
|
|
246
|
+
"Do not retry: the failure is deterministic until the operator updates their key"
|
|
247
|
+
]
|
|
248
|
+
} : isApiError ? {
|
|
218
249
|
message: "Verification is temporarily unavailable. Retry with exponential backoff; if the issue persists, contact support with the correlationId.",
|
|
219
250
|
registrationUrl: urls?.registrationUrl ?? "",
|
|
220
251
|
documentationUrl: urls?.documentationUrl ?? "",
|
|
@@ -252,14 +283,24 @@ function createGuidanceResponse(_config, reason, options = {}) {
|
|
|
252
283
|
// partners (and their custom onDenied handlers) can branch on
|
|
253
284
|
// dimension. Without this, the synthesised stub was indistinguishable
|
|
254
285
|
// from a real policy deny.
|
|
255
|
-
failures:
|
|
286
|
+
failures: isMisconfig ? [
|
|
287
|
+
{
|
|
288
|
+
dimension: "verify_access.merchant_misconfigured",
|
|
289
|
+
message: reason ?? "The integration API key was rejected by AstraSync",
|
|
290
|
+
guidance: guidance.message
|
|
291
|
+
}
|
|
292
|
+
] : isApiError ? [
|
|
256
293
|
{
|
|
257
294
|
dimension: "verify_access.api_error",
|
|
258
295
|
message: reason ?? "Verification temporarily unavailable",
|
|
259
296
|
guidance: guidance.message
|
|
260
297
|
}
|
|
261
298
|
] : void 0,
|
|
299
|
+
// 4.0.0: typed marker so adapters render the misconfig envelope (503 +
|
|
300
|
+
// MERCHANT_VERIFICATION_MISCONFIGURED) without string-matching.
|
|
301
|
+
...isMisconfig && { misconfigured: true },
|
|
262
302
|
correlationId: options.correlationId,
|
|
303
|
+
attemptId: options.attemptId,
|
|
263
304
|
verifiedAt: /* @__PURE__ */ new Date()
|
|
264
305
|
};
|
|
265
306
|
}
|
|
@@ -289,6 +330,8 @@ async function callVerifyAccessAPI(config, request) {
|
|
|
289
330
|
body.runtimeChallengeOptions = requestData.runtimeChallengeOptions;
|
|
290
331
|
if (requestData.invocationProtocol) body.invocationProtocol = requestData.invocationProtocol;
|
|
291
332
|
if (requestData.commerceArtifacts) body.commerceArtifacts = requestData.commerceArtifacts;
|
|
333
|
+
if (requestData.attemptId) body.attemptId = requestData.attemptId;
|
|
334
|
+
if (requestData.considerationSet) body.considerationSet = requestData.considerationSet;
|
|
292
335
|
body.sdkVersion = SDK_VERSION;
|
|
293
336
|
if (requestData.callerMetadata || requestData.clientIp || requestData.userAgent) {
|
|
294
337
|
const meta = {
|
|
@@ -310,12 +353,16 @@ async function callVerifyAccessAPI(config, request) {
|
|
|
310
353
|
const response = await fetch(`${config.apiBaseUrl}/agents/verify-access`, {
|
|
311
354
|
method: "POST",
|
|
312
355
|
headers,
|
|
313
|
-
body: JSON.stringify(body)
|
|
356
|
+
body: JSON.stringify(body),
|
|
357
|
+
signal: AbortSignal.timeout(config.verifyTimeoutMs ?? 1e4)
|
|
314
358
|
});
|
|
315
359
|
const data = await response.json();
|
|
316
360
|
if (response.status === 410) {
|
|
317
361
|
return {
|
|
318
362
|
success: true,
|
|
363
|
+
// 3.12.0 (Trust Record): keep the server-echoed attempt handle even on
|
|
364
|
+
// the synthesised 410 deny shape (echoed on every branch).
|
|
365
|
+
attemptId: typeof data?.attemptId === "string" ? data.attemptId : void 0,
|
|
319
366
|
access: {
|
|
320
367
|
allowed: false,
|
|
321
368
|
accessLevel: "none",
|
|
@@ -331,10 +378,22 @@ async function callVerifyAccessAPI(config, request) {
|
|
|
331
378
|
};
|
|
332
379
|
}
|
|
333
380
|
if (!response.ok) {
|
|
381
|
+
if (response.status === 401) {
|
|
382
|
+
return {
|
|
383
|
+
success: false,
|
|
384
|
+
error: data.message || data.error || "Integration API key rejected",
|
|
385
|
+
misconfig: true,
|
|
386
|
+
misconfigCode: typeof data?.code === "string" ? data.code : void 0,
|
|
387
|
+
remediation: data?.remediation && typeof data.remediation === "object" ? data.remediation : void 0,
|
|
388
|
+
correlationId: typeof data?.correlationId === "string" ? data.correlationId : void 0,
|
|
389
|
+
attemptId: typeof data?.attemptId === "string" ? data.attemptId : void 0
|
|
390
|
+
};
|
|
391
|
+
}
|
|
334
392
|
return {
|
|
335
393
|
success: false,
|
|
336
394
|
error: data.message || data.error || `API returned ${response.status}`,
|
|
337
|
-
correlationId: typeof data?.correlationId === "string" ? data.correlationId : void 0
|
|
395
|
+
correlationId: typeof data?.correlationId === "string" ? data.correlationId : void 0,
|
|
396
|
+
attemptId: typeof data?.attemptId === "string" ? data.attemptId : void 0
|
|
338
397
|
};
|
|
339
398
|
}
|
|
340
399
|
return data;
|
|
@@ -351,9 +410,19 @@ async function verify(config, request, options) {
|
|
|
351
410
|
const urls = mergedConfig.apiBaseUrl ? getCachedWellKnownUrls(mergedConfig.apiBaseUrl) : void 0;
|
|
352
411
|
if (!initCheckPerformed && !mergedConfig.disableInitChecks && mergedConfig.apiBaseUrl) {
|
|
353
412
|
if (mergedConfig.strictInit) {
|
|
354
|
-
await performInitCheck(
|
|
413
|
+
await performInitCheck(
|
|
414
|
+
mergedConfig.apiBaseUrl,
|
|
415
|
+
mergedConfig.debug,
|
|
416
|
+
true,
|
|
417
|
+
mergedConfig.apiKey
|
|
418
|
+
);
|
|
355
419
|
} else {
|
|
356
|
-
void performInitCheck(
|
|
420
|
+
void performInitCheck(
|
|
421
|
+
mergedConfig.apiBaseUrl,
|
|
422
|
+
mergedConfig.debug,
|
|
423
|
+
false,
|
|
424
|
+
mergedConfig.apiKey
|
|
425
|
+
);
|
|
357
426
|
}
|
|
358
427
|
}
|
|
359
428
|
if (!deprecationWarningShown && (config.minTrustScore !== void 0 || config.minTrustScoreForFull !== void 0)) {
|
|
@@ -368,7 +437,13 @@ async function verify(config, request, options) {
|
|
|
368
437
|
if (mergedConfig.debug) {
|
|
369
438
|
console.log("[VerificationGateway] Returning cached result");
|
|
370
439
|
}
|
|
371
|
-
|
|
440
|
+
const hit = { ...cached };
|
|
441
|
+
if (request.attemptId) {
|
|
442
|
+
hit.attemptId = request.attemptId;
|
|
443
|
+
} else {
|
|
444
|
+
delete hit.attemptId;
|
|
445
|
+
}
|
|
446
|
+
return hit;
|
|
372
447
|
}
|
|
373
448
|
}
|
|
374
449
|
const enrichedRequest = { ...request };
|
|
@@ -386,8 +461,10 @@ async function verify(config, request, options) {
|
|
|
386
461
|
const serverDenialReasons = Array.isArray(rawServerDenialReasons) && rawServerDenialReasons.length > 0 ? rawServerDenialReasons : void 0;
|
|
387
462
|
if (!apiResponse.success) {
|
|
388
463
|
return createGuidanceResponse(mergedConfig, apiResponse.error, {
|
|
389
|
-
source: "api_error",
|
|
464
|
+
source: apiResponse.misconfig ? "merchant_misconfig" : "api_error",
|
|
390
465
|
correlationId: apiResponse.correlationId,
|
|
466
|
+
attemptId: apiResponse.attemptId,
|
|
467
|
+
remediation: apiResponse.remediation,
|
|
391
468
|
urls
|
|
392
469
|
});
|
|
393
470
|
}
|
|
@@ -423,6 +500,9 @@ async function verify(config, request, options) {
|
|
|
423
500
|
// Anonymous traffic has no session → correlationId is the per-attempt
|
|
424
501
|
// linking key (the sessionId-equivalent for anonymous callers).
|
|
425
502
|
correlationId: apiResponse.correlationId,
|
|
503
|
+
// 3.12.0 (Trust Record): server echoes the attempt-chain handle on
|
|
504
|
+
// every branch — denials included (the funnel outlives one deny).
|
|
505
|
+
attemptId: apiResponse.attemptId,
|
|
426
506
|
recommendation: apiResponse.recommendation,
|
|
427
507
|
recommendationReasons: apiResponse.recommendationReasons,
|
|
428
508
|
stepUpApproval: apiResponse.stepUpApproval,
|
|
@@ -474,6 +554,8 @@ async function verify(config, request, options) {
|
|
|
474
554
|
// v2.3.10 (defect #34, round-4): anonymous responses surface correlationId
|
|
475
555
|
// (no session row exists for unverified callers).
|
|
476
556
|
correlationId: apiResponse.correlationId,
|
|
557
|
+
// 3.12.0 (Trust Record): server-echoed attempt-chain handle.
|
|
558
|
+
attemptId: apiResponse.attemptId,
|
|
477
559
|
runtimeChallenge: apiResponse.runtimeChallenge,
|
|
478
560
|
tokenGuidance: apiResponse.tokenGuidance,
|
|
479
561
|
recommendation: apiResponse.recommendation,
|
|
@@ -736,6 +818,24 @@ function dedupeFailures(result) {
|
|
|
736
818
|
}
|
|
737
819
|
function defaultMcpDenied(result, req, res) {
|
|
738
820
|
const id = req.body?.id ?? null;
|
|
821
|
+
if (result.misconfigured) {
|
|
822
|
+
res.setHeader("X-Astra-Gateway-Mode", "enforced");
|
|
823
|
+
res.status(503).json({
|
|
824
|
+
jsonrpc: "2.0",
|
|
825
|
+
id,
|
|
826
|
+
error: {
|
|
827
|
+
// -32002 → merchant verification misconfigured (see -32000/-32001 below)
|
|
828
|
+
code: -32002,
|
|
829
|
+
message: result.denialReasons?.[0] ?? "This server's AstraSync integration is misconfigured",
|
|
830
|
+
data: {
|
|
831
|
+
guidance: result.guidance,
|
|
832
|
+
failures: result.failures,
|
|
833
|
+
correlationId: result.correlationId
|
|
834
|
+
}
|
|
835
|
+
}
|
|
836
|
+
});
|
|
837
|
+
return;
|
|
838
|
+
}
|
|
739
839
|
const status = !result.identityVerified ? 401 : 403;
|
|
740
840
|
res.setHeader("X-Astra-Gateway-Mode", "enforced");
|
|
741
841
|
res.status(status).json({
|
|
@@ -745,6 +845,7 @@ function defaultMcpDenied(result, req, res) {
|
|
|
745
845
|
// JSON-RPC error codes:
|
|
746
846
|
// -32000 → unauthorized (no identity resolved)
|
|
747
847
|
// -32001 → insufficient access (identity OK, policy denied)
|
|
848
|
+
// -32002 → merchant verification misconfigured (handled above)
|
|
748
849
|
code: !result.identityVerified ? -32e3 : -32001,
|
|
749
850
|
message: result.denialReasons?.[0] ?? "Access denied",
|
|
750
851
|
data: {
|