@astrasyncai/verification-gateway 5.11.0 → 5.13.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/README.md +4 -0
- package/dist/adapters/express.d.mts +1 -1
- package/dist/adapters/express.d.ts +1 -1
- package/dist/adapters/express.js +394 -39
- package/dist/adapters/express.js.map +1 -1
- package/dist/adapters/express.mjs +394 -39
- package/dist/adapters/express.mjs.map +1 -1
- package/dist/adapters/mcp.d.mts +5 -1
- package/dist/adapters/mcp.d.ts +5 -1
- package/dist/adapters/mcp.js +193 -49
- package/dist/adapters/mcp.js.map +1 -1
- package/dist/adapters/mcp.mjs +193 -49
- package/dist/adapters/mcp.mjs.map +1 -1
- package/dist/adapters/nextjs.d.mts +1 -1
- package/dist/adapters/nextjs.d.ts +1 -1
- package/dist/adapters/nextjs.js +387 -22
- package/dist/adapters/nextjs.js.map +1 -1
- package/dist/adapters/nextjs.mjs +387 -22
- package/dist/adapters/nextjs.mjs.map +1 -1
- package/dist/adapters/sdk.d.mts +9 -1
- package/dist/adapters/sdk.d.ts +9 -1
- package/dist/adapters/sdk.js +125 -16
- package/dist/adapters/sdk.js.map +1 -1
- package/dist/adapters/sdk.mjs +125 -16
- package/dist/adapters/sdk.mjs.map +1 -1
- package/dist/agent/index.js +1 -1
- package/dist/agent/index.js.map +1 -1
- package/dist/agent/index.mjs +1 -1
- package/dist/agent/index.mjs.map +1 -1
- package/dist/bin/astrasync-claude-hook.js +309 -15
- package/dist/bin/astrasync-codex-hook.js +309 -15
- package/dist/bin/astrasync-guard.js +309 -15
- package/dist/bin/astrasync.js +322 -17
- package/dist/browser/background.js +309 -15
- package/dist/browser/background.js.map +1 -1
- package/dist/browser/background.mjs +309 -15
- package/dist/browser/background.mjs.map +1 -1
- package/dist/cli/index.js +1 -1
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/index.mjs +1 -1
- package/dist/cli/index.mjs.map +1 -1
- package/dist/codex/index.js +309 -15
- package/dist/codex/index.js.map +1 -1
- package/dist/codex/index.mjs +309 -15
- package/dist/codex/index.mjs.map +1 -1
- package/dist/cursor/extension.js +309 -15
- package/dist/cursor/extension.js.map +1 -1
- package/dist/cursor/extension.mjs +309 -15
- 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/edge-config.js +1 -1
- package/dist/edge-config.js.map +1 -1
- package/dist/edge-config.mjs +1 -1
- package/dist/edge-config.mjs.map +1 -1
- package/dist/edge-core/index.d.mts +128 -13
- package/dist/edge-core/index.d.ts +128 -13
- package/dist/edge-core/index.js +362 -63
- package/dist/edge-core/index.js.map +1 -1
- package/dist/edge-core/index.mjs +359 -63
- package/dist/edge-core/index.mjs.map +1 -1
- package/dist/gateway/gateway.js +309 -15
- package/dist/gateway/gateway.js.map +1 -1
- package/dist/gateway/gateway.mjs +309 -15
- package/dist/gateway/gateway.mjs.map +1 -1
- package/dist/git-trigger/git-hooks.d.mts +1 -1
- package/dist/git-trigger/git-hooks.d.ts +1 -1
- package/dist/index.d.mts +118 -15
- package/dist/index.d.ts +118 -15
- package/dist/index.js +521 -72
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +515 -72
- package/dist/index.mjs.map +1 -1
- package/dist/platform-signatures.js +4 -1
- package/dist/platform-signatures.js.map +1 -1
- package/dist/platform-signatures.mjs +4 -1
- package/dist/platform-signatures.mjs.map +1 -1
- package/dist/registration/index.js +1 -1
- package/dist/registration/index.js.map +1 -1
- package/dist/registration/index.mjs +1 -1
- package/dist/registration/index.mjs.map +1 -1
- package/dist/transport/index.js +1 -1
- package/dist/transport/index.js.map +1 -1
- package/dist/transport/index.mjs +1 -1
- package/dist/transport/index.mjs.map +1 -1
- package/dist/{types-CTmUpNpS.d.mts → types-BCkwBA84.d.mts} +12 -0
- package/dist/{types-CTmUpNpS.d.ts → types-BCkwBA84.d.ts} +12 -0
- package/dist/{types-CtFXmDzm.d.ts → types-C_b4QTyO.d.ts} +18 -0
- package/dist/{types-DQrn_kei.d.mts → types-DlshIIR-.d.mts} +18 -0
- package/dist/ui/index.d.mts +1 -1
- package/dist/ui/index.d.ts +1 -1
- package/dist/verify.d.mts +35 -14
- package/dist/verify.d.ts +35 -14
- package/dist/verify.js +165 -25
- package/dist/verify.js.map +1 -1
- package/dist/verify.mjs +164 -25
- package/dist/verify.mjs.map +1 -1
- package/package.json +3 -2
package/dist/adapters/sdk.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/version.ts
|
|
2
|
-
var SDK_VERSION = "5.
|
|
2
|
+
var SDK_VERSION = "5.13.0";
|
|
3
3
|
|
|
4
4
|
// src/http.ts
|
|
5
5
|
var SDK_USER_AGENT = `astrasync-sdk/${SDK_VERSION}`;
|
|
@@ -34,6 +34,29 @@ function getCachedWellKnownUrls(apiBaseUrl) {
|
|
|
34
34
|
return cache.get(apiBaseUrl)?.data;
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
+
// src/failure-posture.ts
|
|
38
|
+
var DEFAULT_UNAVAILABLE_RETRY_AFTER_S = 30;
|
|
39
|
+
var REJECTED_IDENTITY_DIMENSIONS = /* @__PURE__ */ new Set([
|
|
40
|
+
"identity.invalid_agent_id",
|
|
41
|
+
"identity.unknown_agent",
|
|
42
|
+
"agent.lookup"
|
|
43
|
+
]);
|
|
44
|
+
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.";
|
|
45
|
+
var UNAVAILABLE_DIMENSIONS = /* @__PURE__ */ new Set([
|
|
46
|
+
"verify_access.api_error",
|
|
47
|
+
"middleware.internal_error"
|
|
48
|
+
]);
|
|
49
|
+
function isVerificationUnavailable(result) {
|
|
50
|
+
if (result.misconfigured) return false;
|
|
51
|
+
return (result.failures ?? []).some((f) => UNAVAILABLE_DIMENSIONS.has(f.dimension));
|
|
52
|
+
}
|
|
53
|
+
function unavailableRetryAfterSeconds(result) {
|
|
54
|
+
if (typeof result.retryAfterMs === "number" && Number.isFinite(result.retryAfterMs)) {
|
|
55
|
+
return Math.max(1, Math.ceil(result.retryAfterMs / 1e3));
|
|
56
|
+
}
|
|
57
|
+
return DEFAULT_UNAVAILABLE_RETRY_AFTER_S;
|
|
58
|
+
}
|
|
59
|
+
|
|
37
60
|
// src/verify.ts
|
|
38
61
|
var DEFAULT_CONFIG = {
|
|
39
62
|
apiBaseUrl: "https://astrasync.ai/api",
|
|
@@ -46,7 +69,7 @@ var DEFAULT_CONFIG = {
|
|
|
46
69
|
};
|
|
47
70
|
var initCheckPerformed = false;
|
|
48
71
|
var deprecationWarningShown = false;
|
|
49
|
-
async function performInitCheck(apiBaseUrl, debug, strictInit, apiKey) {
|
|
72
|
+
async function performInitCheck(apiBaseUrl, debug, strictInit, apiKey, counterparty) {
|
|
50
73
|
initCheckPerformed = true;
|
|
51
74
|
try {
|
|
52
75
|
const probeUrl = `${apiBaseUrl}/agents/verify-access`;
|
|
@@ -64,7 +87,8 @@ async function performInitCheck(apiBaseUrl, debug, strictInit, apiKey) {
|
|
|
64
87
|
);
|
|
65
88
|
}
|
|
66
89
|
if (apiKey) {
|
|
67
|
-
const
|
|
90
|
+
const q = counterparty?.id ? `?counterpartyId=${encodeURIComponent(counterparty.id)}` : counterparty?.url ? `?counterpartyUrl=${encodeURIComponent(counterparty.url)}` : "";
|
|
91
|
+
const selfCheck = await sdkFetch(`${apiBaseUrl}/agents/verify-access/self-check${q}`, {
|
|
68
92
|
headers: { Authorization: `Bearer ${apiKey}` }
|
|
69
93
|
});
|
|
70
94
|
if (selfCheck.status === 401) {
|
|
@@ -76,6 +100,13 @@ async function performInitCheck(apiBaseUrl, debug, strictInit, apiKey) {
|
|
|
76
100
|
console.error(message);
|
|
77
101
|
} else if (selfCheck.ok) {
|
|
78
102
|
const body = await selfCheck.json().catch(() => ({}));
|
|
103
|
+
if (body.counterparty && body.counterparty.canVerify === false) {
|
|
104
|
+
const message = `[VerificationGateway] the configured AstraSync API key cannot verify for this endpoint (${body.counterparty.message ?? "endpoint not found or owned by another account"}). Every inbound agent will be turned away until the key or counterparty is corrected.`;
|
|
105
|
+
if (strictInit) {
|
|
106
|
+
throw new Error(`${message} (strictInit=true)`);
|
|
107
|
+
}
|
|
108
|
+
console.error(message);
|
|
109
|
+
}
|
|
79
110
|
if (typeof body.daysToExpiry === "number" && body.daysToExpiry <= 7) {
|
|
80
111
|
console.warn(
|
|
81
112
|
`[VerificationGateway] the configured AstraSync API key expires in ${body.daysToExpiry} day(s) \u2014 rotate it at Settings \u2192 Developer Tools before integrations start failing.`
|
|
@@ -183,11 +214,11 @@ function createGuidanceResponse(_config, reason, options = {}) {
|
|
|
183
214
|
const isMisconfig = source === "merchant_misconfig";
|
|
184
215
|
const urls = options.urls;
|
|
185
216
|
const guidance = isMisconfig ? {
|
|
186
|
-
message: "This site's AstraSync integration is misconfigured (its API key was revoked, expired, or
|
|
217
|
+
message: "This site's AstraSync integration is misconfigured (its API key was revoked, expired, rotated, or belongs to another account). Your identity and the AstraSync platform are fine \u2014 contact the site operator. Retrying will not help.",
|
|
187
218
|
registrationUrl: urls?.registrationUrl ?? "",
|
|
188
219
|
documentationUrl: options.remediation?.docsUrl ?? urls?.documentationUrl ?? "",
|
|
189
220
|
steps: [
|
|
190
|
-
"Report the failure to the site operator \u2014 their AstraSync API key needs
|
|
221
|
+
"Report the failure to the site operator \u2014 their AstraSync API key needs replacing",
|
|
191
222
|
"Do not retry: the failure is deterministic until the operator updates their key"
|
|
192
223
|
]
|
|
193
224
|
} : isApiError ? {
|
|
@@ -248,11 +279,44 @@ function createGuidanceResponse(_config, reason, options = {}) {
|
|
|
248
279
|
// coercing the absent recommendation to a policy 'deny'. Misconfig is
|
|
249
280
|
// deterministic and intentionally NOT marked retryable.
|
|
250
281
|
...isApiError && { retryable: true },
|
|
282
|
+
...options.httpStatus !== void 0 && { httpStatus: options.httpStatus },
|
|
283
|
+
...options.retryAfterMs !== void 0 && { retryAfterMs: options.retryAfterMs },
|
|
251
284
|
correlationId: options.correlationId,
|
|
252
285
|
attemptId: options.attemptId,
|
|
253
286
|
verifiedAt: /* @__PURE__ */ new Date()
|
|
254
287
|
};
|
|
255
288
|
}
|
|
289
|
+
async function readJsonSafe(response) {
|
|
290
|
+
try {
|
|
291
|
+
const parsed = await response.json();
|
|
292
|
+
return parsed && typeof parsed === "object" ? parsed : {};
|
|
293
|
+
} catch {
|
|
294
|
+
return {};
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
function rejectedIdentityGuidance(failures) {
|
|
298
|
+
const f = failures?.find((x) => REJECTED_IDENTITY_DIMENSIONS.has(x.dimension));
|
|
299
|
+
if (!f) return void 0;
|
|
300
|
+
if (f.dimension === "agent.lookup") {
|
|
301
|
+
return `The presented agent identifier is not registered with AstraSync. ${UNKNOWN_AGENT_GUIDANCE}`;
|
|
302
|
+
}
|
|
303
|
+
return f.guidance ? `${f.message} ${f.guidance}` : f.message;
|
|
304
|
+
}
|
|
305
|
+
var MAX_RETRY_AFTER_MS = 15 * 60 * 1e3;
|
|
306
|
+
function parseRetryAfterMs(response) {
|
|
307
|
+
const raw = response.headers?.get?.("retry-after");
|
|
308
|
+
if (!raw) return void 0;
|
|
309
|
+
const trimmed = raw.trim();
|
|
310
|
+
let ms;
|
|
311
|
+
if (/^\d+(\.\d+)?$/.test(trimmed)) {
|
|
312
|
+
ms = Number(trimmed) * 1e3;
|
|
313
|
+
} else {
|
|
314
|
+
const at = Date.parse(trimmed);
|
|
315
|
+
if (Number.isNaN(at)) return void 0;
|
|
316
|
+
ms = at - Date.now();
|
|
317
|
+
}
|
|
318
|
+
return Math.min(MAX_RETRY_AFTER_MS, Math.max(0, Math.round(ms)));
|
|
319
|
+
}
|
|
256
320
|
async function callVerifyAccessAPI(config, request) {
|
|
257
321
|
const { credentials, ...requestData } = request;
|
|
258
322
|
const body = {
|
|
@@ -309,7 +373,8 @@ async function callVerifyAccessAPI(config, request) {
|
|
|
309
373
|
body: JSON.stringify(body),
|
|
310
374
|
signal: AbortSignal.timeout(config.verifyTimeoutMs ?? 1e4)
|
|
311
375
|
});
|
|
312
|
-
const data = await response
|
|
376
|
+
const data = await readJsonSafe(response);
|
|
377
|
+
const retryAfterMs = parseRetryAfterMs(response);
|
|
313
378
|
if (response.status === 410) {
|
|
314
379
|
return {
|
|
315
380
|
success: true,
|
|
@@ -347,13 +412,31 @@ async function callVerifyAccessAPI(config, request) {
|
|
|
347
412
|
}
|
|
348
413
|
};
|
|
349
414
|
}
|
|
415
|
+
if (response.status === 404 && credentials.astraId && (data?.error === "AGENT_NOT_FOUND" || typeof data?.message === "string" && /agent/i.test(data.message))) {
|
|
416
|
+
return {
|
|
417
|
+
success: true,
|
|
418
|
+
attemptId: typeof data?.attemptId === "string" ? data.attemptId : void 0,
|
|
419
|
+
access: {
|
|
420
|
+
allowed: false,
|
|
421
|
+
reason: "unknown_agent",
|
|
422
|
+
failures: [
|
|
423
|
+
{
|
|
424
|
+
dimension: "identity.unknown_agent",
|
|
425
|
+
message: "The presented agent identifier is not registered with AstraSync.",
|
|
426
|
+
guidance: UNKNOWN_AGENT_GUIDANCE
|
|
427
|
+
}
|
|
428
|
+
]
|
|
429
|
+
}
|
|
430
|
+
};
|
|
431
|
+
}
|
|
350
432
|
if (!response.ok) {
|
|
351
|
-
|
|
433
|
+
const keyMismatch = response.status === 403 && data?.error === "COUNTERPARTY_KEY_MISMATCH";
|
|
434
|
+
if (response.status === 401 || keyMismatch) {
|
|
352
435
|
return {
|
|
353
436
|
success: false,
|
|
354
437
|
error: data.message || data.error || "Integration API key rejected",
|
|
355
438
|
misconfig: true,
|
|
356
|
-
misconfigCode: typeof data?.code === "string" ? data.code : void 0,
|
|
439
|
+
misconfigCode: keyMismatch ? "counterparty_key_mismatch" : typeof data?.code === "string" ? data.code : void 0,
|
|
357
440
|
remediation: data?.remediation && typeof data.remediation === "object" ? data.remediation : void 0,
|
|
358
441
|
correlationId: typeof data?.correlationId === "string" ? data.correlationId : void 0,
|
|
359
442
|
attemptId: typeof data?.attemptId === "string" ? data.attemptId : void 0
|
|
@@ -361,9 +444,11 @@ async function callVerifyAccessAPI(config, request) {
|
|
|
361
444
|
}
|
|
362
445
|
return {
|
|
363
446
|
success: false,
|
|
364
|
-
error: data.message || data.error || `API returned ${response.status}`,
|
|
447
|
+
error: typeof data?.message === "string" && data.message || typeof data?.error === "string" && data.error || `API returned ${response.status}`,
|
|
365
448
|
correlationId: typeof data?.correlationId === "string" ? data.correlationId : void 0,
|
|
366
|
-
attemptId: typeof data?.attemptId === "string" ? data.attemptId : void 0
|
|
449
|
+
attemptId: typeof data?.attemptId === "string" ? data.attemptId : void 0,
|
|
450
|
+
httpStatus: response.status,
|
|
451
|
+
...retryAfterMs !== void 0 && { retryAfterMs }
|
|
367
452
|
};
|
|
368
453
|
}
|
|
369
454
|
return data;
|
|
@@ -384,14 +469,22 @@ async function verify(config, request, options) {
|
|
|
384
469
|
mergedConfig.apiBaseUrl,
|
|
385
470
|
mergedConfig.debug,
|
|
386
471
|
true,
|
|
387
|
-
mergedConfig.apiKey
|
|
472
|
+
mergedConfig.apiKey,
|
|
473
|
+
{
|
|
474
|
+
id: mergedConfig.counterpartyId,
|
|
475
|
+
url: mergedConfig.counterpartyUrl ?? request.counterpartyUrl
|
|
476
|
+
}
|
|
388
477
|
);
|
|
389
478
|
} else {
|
|
390
479
|
void performInitCheck(
|
|
391
480
|
mergedConfig.apiBaseUrl,
|
|
392
481
|
mergedConfig.debug,
|
|
393
482
|
false,
|
|
394
|
-
mergedConfig.apiKey
|
|
483
|
+
mergedConfig.apiKey,
|
|
484
|
+
{
|
|
485
|
+
id: mergedConfig.counterpartyId,
|
|
486
|
+
url: mergedConfig.counterpartyUrl ?? request.counterpartyUrl
|
|
487
|
+
}
|
|
395
488
|
);
|
|
396
489
|
}
|
|
397
490
|
}
|
|
@@ -435,12 +528,14 @@ async function verify(config, request, options) {
|
|
|
435
528
|
correlationId: apiResponse.correlationId,
|
|
436
529
|
attemptId: apiResponse.attemptId,
|
|
437
530
|
remediation: apiResponse.remediation,
|
|
531
|
+
httpStatus: apiResponse.httpStatus,
|
|
532
|
+
retryAfterMs: apiResponse.retryAfterMs,
|
|
438
533
|
urls
|
|
439
534
|
});
|
|
440
535
|
}
|
|
441
536
|
if (!apiResponse.access?.allowed) {
|
|
442
537
|
const aggregatedFailures = apiResponse.access?.failures;
|
|
443
|
-
const idVerifiedFromBackend = apiResponse.verificationContext?.idVerified === true;
|
|
538
|
+
const idVerifiedFromBackend = apiResponse.verificationContext?.idVerified === true && !aggregatedFailures?.some((f) => REJECTED_IDENTITY_DIMENSIONS.has(f.dimension));
|
|
444
539
|
const result2 = {
|
|
445
540
|
identityVerified: idVerifiedFromBackend,
|
|
446
541
|
policyAllowed: false,
|
|
@@ -452,7 +547,10 @@ async function verify(config, request, options) {
|
|
|
452
547
|
requiresStepUp: apiResponse.access?.requiresStepUp,
|
|
453
548
|
requiresApproval: apiResponse.access?.requiresApproval,
|
|
454
549
|
guidance: {
|
|
455
|
-
|
|
550
|
+
// 5.12.0: a presented-but-rejected id (malformed / unknown) carries
|
|
551
|
+
// actionable registration guidance on its failure — surface it
|
|
552
|
+
// instead of the bare machine reason ('unknown_agent').
|
|
553
|
+
message: rejectedIdentityGuidance(aggregatedFailures) ?? (apiResponse.access?.reason || "Access denied by PDLSS policy"),
|
|
456
554
|
registrationUrl: urls?.registrationUrl ?? "",
|
|
457
555
|
documentationUrl: urls?.documentationUrl ?? "",
|
|
458
556
|
// 5.1.0: anonymous callers land on this branch — steer MCP-hosted
|
|
@@ -552,7 +650,7 @@ async function verify(config, request, options) {
|
|
|
552
650
|
registrationUrl: urls?.registrationUrl ?? "",
|
|
553
651
|
documentationUrl: urls?.documentationUrl ?? ""
|
|
554
652
|
};
|
|
555
|
-
} else if (result.recommendation === "step_up_required") {
|
|
653
|
+
} else if (result.recommendation === "step_up_required" && result.identityVerified) {
|
|
556
654
|
result.requiresStepUp = true;
|
|
557
655
|
result.denialReasons = serverDenialReasons ?? result.recommendationReasons ?? ["Step-up verification required"];
|
|
558
656
|
}
|
|
@@ -570,7 +668,11 @@ async function quickVerify(config, credentials) {
|
|
|
570
668
|
return {
|
|
571
669
|
identityVerified: result.identityVerified,
|
|
572
670
|
policyAllowed: result.policyAllowed,
|
|
573
|
-
reason: result.denialReasons?.[0]
|
|
671
|
+
reason: result.denialReasons?.[0],
|
|
672
|
+
...isVerificationUnavailable(result) && {
|
|
673
|
+
unavailable: true,
|
|
674
|
+
retryAfterMs: unavailableRetryAfterSeconds(result) * 1e3
|
|
675
|
+
}
|
|
574
676
|
};
|
|
575
677
|
}
|
|
576
678
|
|
|
@@ -656,6 +758,12 @@ var VerificationGatewayClient = class {
|
|
|
656
758
|
* fulfil against it only once the order is settled / pending_merchant. An
|
|
657
759
|
* explicit `buyerEmail` (here or on the bridge handoff body) wins over the
|
|
658
760
|
* account default.
|
|
761
|
+
*
|
|
762
|
+
* 5.12.0 approval binding: pass the bridge handoff body's `attemptId` (and
|
|
763
|
+
* the same `checkoutSessionId`) so a step-up approval minted for this cart
|
|
764
|
+
* is matched to — and only to — this confirm. A held cart's approval is
|
|
765
|
+
* bound to its checkout session and exact value; a confirm for any other
|
|
766
|
+
* cart is held for its own approval.
|
|
659
767
|
*/
|
|
660
768
|
async confirmCheckout(options) {
|
|
661
769
|
const credentials = {
|
|
@@ -675,6 +783,7 @@ var VerificationGatewayClient = class {
|
|
|
675
783
|
commercePhase: "confirm",
|
|
676
784
|
checkoutSessionId: options.checkoutSessionId,
|
|
677
785
|
checkoutItems: options.checkoutItems,
|
|
786
|
+
...options.attemptId && { attemptId: options.attemptId },
|
|
678
787
|
buyerEmail: options.buyerEmail,
|
|
679
788
|
counterpartyUrl: options.counterpartyUrl,
|
|
680
789
|
counterpartyType: options.counterpartyType
|