@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/bin/astrasync.js
CHANGED
|
@@ -36,7 +36,7 @@ var SDK_VERSION;
|
|
|
36
36
|
var init_version = __esm({
|
|
37
37
|
"src/version.ts"() {
|
|
38
38
|
"use strict";
|
|
39
|
-
SDK_VERSION = "5.
|
|
39
|
+
SDK_VERSION = "5.13.0";
|
|
40
40
|
}
|
|
41
41
|
});
|
|
42
42
|
|
|
@@ -5057,8 +5057,22 @@ var init_well_known = __esm({
|
|
|
5057
5057
|
}
|
|
5058
5058
|
});
|
|
5059
5059
|
|
|
5060
|
+
// src/failure-posture.ts
|
|
5061
|
+
var REJECTED_IDENTITY_DIMENSIONS, UNKNOWN_AGENT_GUIDANCE;
|
|
5062
|
+
var init_failure_posture = __esm({
|
|
5063
|
+
"src/failure-posture.ts"() {
|
|
5064
|
+
"use strict";
|
|
5065
|
+
REJECTED_IDENTITY_DIMENSIONS = /* @__PURE__ */ new Set([
|
|
5066
|
+
"identity.invalid_agent_id",
|
|
5067
|
+
"identity.unknown_agent",
|
|
5068
|
+
"agent.lookup"
|
|
5069
|
+
]);
|
|
5070
|
+
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.";
|
|
5071
|
+
}
|
|
5072
|
+
});
|
|
5073
|
+
|
|
5060
5074
|
// src/verify.ts
|
|
5061
|
-
async function performInitCheck(apiBaseUrl, debug, strictInit, apiKey) {
|
|
5075
|
+
async function performInitCheck(apiBaseUrl, debug, strictInit, apiKey, counterparty) {
|
|
5062
5076
|
initCheckPerformed = true;
|
|
5063
5077
|
try {
|
|
5064
5078
|
const probeUrl = `${apiBaseUrl}/agents/verify-access`;
|
|
@@ -5076,7 +5090,8 @@ async function performInitCheck(apiBaseUrl, debug, strictInit, apiKey) {
|
|
|
5076
5090
|
);
|
|
5077
5091
|
}
|
|
5078
5092
|
if (apiKey) {
|
|
5079
|
-
const
|
|
5093
|
+
const q = counterparty?.id ? `?counterpartyId=${encodeURIComponent(counterparty.id)}` : counterparty?.url ? `?counterpartyUrl=${encodeURIComponent(counterparty.url)}` : "";
|
|
5094
|
+
const selfCheck = await sdkFetch(`${apiBaseUrl}/agents/verify-access/self-check${q}`, {
|
|
5080
5095
|
headers: { Authorization: `Bearer ${apiKey}` }
|
|
5081
5096
|
});
|
|
5082
5097
|
if (selfCheck.status === 401) {
|
|
@@ -5088,6 +5103,13 @@ async function performInitCheck(apiBaseUrl, debug, strictInit, apiKey) {
|
|
|
5088
5103
|
console.error(message);
|
|
5089
5104
|
} else if (selfCheck.ok) {
|
|
5090
5105
|
const body = await selfCheck.json().catch(() => ({}));
|
|
5106
|
+
if (body.counterparty && body.counterparty.canVerify === false) {
|
|
5107
|
+
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.`;
|
|
5108
|
+
if (strictInit) {
|
|
5109
|
+
throw new Error(`${message} (strictInit=true)`);
|
|
5110
|
+
}
|
|
5111
|
+
console.error(message);
|
|
5112
|
+
}
|
|
5091
5113
|
if (typeof body.daysToExpiry === "number" && body.daysToExpiry <= 7) {
|
|
5092
5114
|
console.warn(
|
|
5093
5115
|
`[VerificationGateway] the configured AstraSync API key expires in ${body.daysToExpiry} day(s) \u2014 rotate it at Settings \u2192 Developer Tools before integrations start failing.`
|
|
@@ -5190,11 +5212,11 @@ function createGuidanceResponse(_config, reason, options = {}) {
|
|
|
5190
5212
|
const isMisconfig = source === "merchant_misconfig";
|
|
5191
5213
|
const urls = options.urls;
|
|
5192
5214
|
const guidance = isMisconfig ? {
|
|
5193
|
-
message: "This site's AstraSync integration is misconfigured (its API key was revoked, expired, or
|
|
5215
|
+
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.",
|
|
5194
5216
|
registrationUrl: urls?.registrationUrl ?? "",
|
|
5195
5217
|
documentationUrl: options.remediation?.docsUrl ?? urls?.documentationUrl ?? "",
|
|
5196
5218
|
steps: [
|
|
5197
|
-
"Report the failure to the site operator \u2014 their AstraSync API key needs
|
|
5219
|
+
"Report the failure to the site operator \u2014 their AstraSync API key needs replacing",
|
|
5198
5220
|
"Do not retry: the failure is deterministic until the operator updates their key"
|
|
5199
5221
|
]
|
|
5200
5222
|
} : isApiError ? {
|
|
@@ -5255,11 +5277,43 @@ function createGuidanceResponse(_config, reason, options = {}) {
|
|
|
5255
5277
|
// coercing the absent recommendation to a policy 'deny'. Misconfig is
|
|
5256
5278
|
// deterministic and intentionally NOT marked retryable.
|
|
5257
5279
|
...isApiError && { retryable: true },
|
|
5280
|
+
...options.httpStatus !== void 0 && { httpStatus: options.httpStatus },
|
|
5281
|
+
...options.retryAfterMs !== void 0 && { retryAfterMs: options.retryAfterMs },
|
|
5258
5282
|
correlationId: options.correlationId,
|
|
5259
5283
|
attemptId: options.attemptId,
|
|
5260
5284
|
verifiedAt: /* @__PURE__ */ new Date()
|
|
5261
5285
|
};
|
|
5262
5286
|
}
|
|
5287
|
+
async function readJsonSafe(response) {
|
|
5288
|
+
try {
|
|
5289
|
+
const parsed = await response.json();
|
|
5290
|
+
return parsed && typeof parsed === "object" ? parsed : {};
|
|
5291
|
+
} catch {
|
|
5292
|
+
return {};
|
|
5293
|
+
}
|
|
5294
|
+
}
|
|
5295
|
+
function rejectedIdentityGuidance(failures) {
|
|
5296
|
+
const f = failures?.find((x) => REJECTED_IDENTITY_DIMENSIONS.has(x.dimension));
|
|
5297
|
+
if (!f) return void 0;
|
|
5298
|
+
if (f.dimension === "agent.lookup") {
|
|
5299
|
+
return `The presented agent identifier is not registered with AstraSync. ${UNKNOWN_AGENT_GUIDANCE}`;
|
|
5300
|
+
}
|
|
5301
|
+
return f.guidance ? `${f.message} ${f.guidance}` : f.message;
|
|
5302
|
+
}
|
|
5303
|
+
function parseRetryAfterMs(response) {
|
|
5304
|
+
const raw = response.headers?.get?.("retry-after");
|
|
5305
|
+
if (!raw) return void 0;
|
|
5306
|
+
const trimmed = raw.trim();
|
|
5307
|
+
let ms;
|
|
5308
|
+
if (/^\d+(\.\d+)?$/.test(trimmed)) {
|
|
5309
|
+
ms = Number(trimmed) * 1e3;
|
|
5310
|
+
} else {
|
|
5311
|
+
const at = Date.parse(trimmed);
|
|
5312
|
+
if (Number.isNaN(at)) return void 0;
|
|
5313
|
+
ms = at - Date.now();
|
|
5314
|
+
}
|
|
5315
|
+
return Math.min(MAX_RETRY_AFTER_MS, Math.max(0, Math.round(ms)));
|
|
5316
|
+
}
|
|
5263
5317
|
async function callVerifyAccessAPI(config, request2) {
|
|
5264
5318
|
const { credentials, ...requestData } = request2;
|
|
5265
5319
|
const body = {
|
|
@@ -5316,7 +5370,8 @@ async function callVerifyAccessAPI(config, request2) {
|
|
|
5316
5370
|
body: JSON.stringify(body),
|
|
5317
5371
|
signal: AbortSignal.timeout(config.verifyTimeoutMs ?? 1e4)
|
|
5318
5372
|
});
|
|
5319
|
-
const data = await response
|
|
5373
|
+
const data = await readJsonSafe(response);
|
|
5374
|
+
const retryAfterMs = parseRetryAfterMs(response);
|
|
5320
5375
|
if (response.status === 410) {
|
|
5321
5376
|
return {
|
|
5322
5377
|
success: true,
|
|
@@ -5354,13 +5409,31 @@ async function callVerifyAccessAPI(config, request2) {
|
|
|
5354
5409
|
}
|
|
5355
5410
|
};
|
|
5356
5411
|
}
|
|
5412
|
+
if (response.status === 404 && credentials.astraId && (data?.error === "AGENT_NOT_FOUND" || typeof data?.message === "string" && /agent/i.test(data.message))) {
|
|
5413
|
+
return {
|
|
5414
|
+
success: true,
|
|
5415
|
+
attemptId: typeof data?.attemptId === "string" ? data.attemptId : void 0,
|
|
5416
|
+
access: {
|
|
5417
|
+
allowed: false,
|
|
5418
|
+
reason: "unknown_agent",
|
|
5419
|
+
failures: [
|
|
5420
|
+
{
|
|
5421
|
+
dimension: "identity.unknown_agent",
|
|
5422
|
+
message: "The presented agent identifier is not registered with AstraSync.",
|
|
5423
|
+
guidance: UNKNOWN_AGENT_GUIDANCE
|
|
5424
|
+
}
|
|
5425
|
+
]
|
|
5426
|
+
}
|
|
5427
|
+
};
|
|
5428
|
+
}
|
|
5357
5429
|
if (!response.ok) {
|
|
5358
|
-
|
|
5430
|
+
const keyMismatch = response.status === 403 && data?.error === "COUNTERPARTY_KEY_MISMATCH";
|
|
5431
|
+
if (response.status === 401 || keyMismatch) {
|
|
5359
5432
|
return {
|
|
5360
5433
|
success: false,
|
|
5361
5434
|
error: data.message || data.error || "Integration API key rejected",
|
|
5362
5435
|
misconfig: true,
|
|
5363
|
-
misconfigCode: typeof data?.code === "string" ? data.code : void 0,
|
|
5436
|
+
misconfigCode: keyMismatch ? "counterparty_key_mismatch" : typeof data?.code === "string" ? data.code : void 0,
|
|
5364
5437
|
remediation: data?.remediation && typeof data.remediation === "object" ? data.remediation : void 0,
|
|
5365
5438
|
correlationId: typeof data?.correlationId === "string" ? data.correlationId : void 0,
|
|
5366
5439
|
attemptId: typeof data?.attemptId === "string" ? data.attemptId : void 0
|
|
@@ -5368,9 +5441,11 @@ async function callVerifyAccessAPI(config, request2) {
|
|
|
5368
5441
|
}
|
|
5369
5442
|
return {
|
|
5370
5443
|
success: false,
|
|
5371
|
-
error: data.message || data.error || `API returned ${response.status}`,
|
|
5444
|
+
error: typeof data?.message === "string" && data.message || typeof data?.error === "string" && data.error || `API returned ${response.status}`,
|
|
5372
5445
|
correlationId: typeof data?.correlationId === "string" ? data.correlationId : void 0,
|
|
5373
|
-
attemptId: typeof data?.attemptId === "string" ? data.attemptId : void 0
|
|
5446
|
+
attemptId: typeof data?.attemptId === "string" ? data.attemptId : void 0,
|
|
5447
|
+
httpStatus: response.status,
|
|
5448
|
+
...retryAfterMs !== void 0 && { retryAfterMs }
|
|
5374
5449
|
};
|
|
5375
5450
|
}
|
|
5376
5451
|
return data;
|
|
@@ -5391,14 +5466,22 @@ async function verify(config, request2, options) {
|
|
|
5391
5466
|
mergedConfig.apiBaseUrl,
|
|
5392
5467
|
mergedConfig.debug,
|
|
5393
5468
|
true,
|
|
5394
|
-
mergedConfig.apiKey
|
|
5469
|
+
mergedConfig.apiKey,
|
|
5470
|
+
{
|
|
5471
|
+
id: mergedConfig.counterpartyId,
|
|
5472
|
+
url: mergedConfig.counterpartyUrl ?? request2.counterpartyUrl
|
|
5473
|
+
}
|
|
5395
5474
|
);
|
|
5396
5475
|
} else {
|
|
5397
5476
|
void performInitCheck(
|
|
5398
5477
|
mergedConfig.apiBaseUrl,
|
|
5399
5478
|
mergedConfig.debug,
|
|
5400
5479
|
false,
|
|
5401
|
-
mergedConfig.apiKey
|
|
5480
|
+
mergedConfig.apiKey,
|
|
5481
|
+
{
|
|
5482
|
+
id: mergedConfig.counterpartyId,
|
|
5483
|
+
url: mergedConfig.counterpartyUrl ?? request2.counterpartyUrl
|
|
5484
|
+
}
|
|
5402
5485
|
);
|
|
5403
5486
|
}
|
|
5404
5487
|
}
|
|
@@ -5442,12 +5525,14 @@ async function verify(config, request2, options) {
|
|
|
5442
5525
|
correlationId: apiResponse.correlationId,
|
|
5443
5526
|
attemptId: apiResponse.attemptId,
|
|
5444
5527
|
remediation: apiResponse.remediation,
|
|
5528
|
+
httpStatus: apiResponse.httpStatus,
|
|
5529
|
+
retryAfterMs: apiResponse.retryAfterMs,
|
|
5445
5530
|
urls
|
|
5446
5531
|
});
|
|
5447
5532
|
}
|
|
5448
5533
|
if (!apiResponse.access?.allowed) {
|
|
5449
5534
|
const aggregatedFailures = apiResponse.access?.failures;
|
|
5450
|
-
const idVerifiedFromBackend = apiResponse.verificationContext?.idVerified === true;
|
|
5535
|
+
const idVerifiedFromBackend = apiResponse.verificationContext?.idVerified === true && !aggregatedFailures?.some((f) => REJECTED_IDENTITY_DIMENSIONS.has(f.dimension));
|
|
5451
5536
|
const result2 = {
|
|
5452
5537
|
identityVerified: idVerifiedFromBackend,
|
|
5453
5538
|
policyAllowed: false,
|
|
@@ -5459,7 +5544,10 @@ async function verify(config, request2, options) {
|
|
|
5459
5544
|
requiresStepUp: apiResponse.access?.requiresStepUp,
|
|
5460
5545
|
requiresApproval: apiResponse.access?.requiresApproval,
|
|
5461
5546
|
guidance: {
|
|
5462
|
-
|
|
5547
|
+
// 5.12.0: a presented-but-rejected id (malformed / unknown) carries
|
|
5548
|
+
// actionable registration guidance on its failure — surface it
|
|
5549
|
+
// instead of the bare machine reason ('unknown_agent').
|
|
5550
|
+
message: rejectedIdentityGuidance(aggregatedFailures) ?? (apiResponse.access?.reason || "Access denied by PDLSS policy"),
|
|
5463
5551
|
registrationUrl: urls?.registrationUrl ?? "",
|
|
5464
5552
|
documentationUrl: urls?.documentationUrl ?? "",
|
|
5465
5553
|
// 5.1.0: anonymous callers land on this branch — steer MCP-hosted
|
|
@@ -5559,7 +5647,7 @@ async function verify(config, request2, options) {
|
|
|
5559
5647
|
registrationUrl: urls?.registrationUrl ?? "",
|
|
5560
5648
|
documentationUrl: urls?.documentationUrl ?? ""
|
|
5561
5649
|
};
|
|
5562
|
-
} else if (result.recommendation === "step_up_required") {
|
|
5650
|
+
} else if (result.recommendation === "step_up_required" && result.identityVerified) {
|
|
5563
5651
|
result.requiresStepUp = true;
|
|
5564
5652
|
result.denialReasons = serverDenialReasons ?? result.recommendationReasons ?? ["Step-up verification required"];
|
|
5565
5653
|
}
|
|
@@ -5569,7 +5657,7 @@ async function verify(config, request2, options) {
|
|
|
5569
5657
|
}
|
|
5570
5658
|
return result;
|
|
5571
5659
|
}
|
|
5572
|
-
var DEFAULT_CONFIG, initCheckPerformed, deprecationWarningShown, verificationCache, DEFAULT_CACHE_TTL_SECONDS;
|
|
5660
|
+
var DEFAULT_CONFIG, initCheckPerformed, deprecationWarningShown, verificationCache, DEFAULT_CACHE_TTL_SECONDS, MAX_RETRY_AFTER_MS;
|
|
5573
5661
|
var init_verify = __esm({
|
|
5574
5662
|
"src/verify.ts"() {
|
|
5575
5663
|
"use strict";
|
|
@@ -5577,6 +5665,7 @@ var init_verify = __esm({
|
|
|
5577
5665
|
init_trust_levels();
|
|
5578
5666
|
init_version();
|
|
5579
5667
|
init_well_known();
|
|
5668
|
+
init_failure_posture();
|
|
5580
5669
|
DEFAULT_CONFIG = {
|
|
5581
5670
|
apiBaseUrl: "https://astrasync.ai/api",
|
|
5582
5671
|
// minTrustScore + minTrustScoreForFull deprecated in v2.3.0 — server decides.
|
|
@@ -5590,6 +5679,7 @@ var init_verify = __esm({
|
|
|
5590
5679
|
deprecationWarningShown = false;
|
|
5591
5680
|
verificationCache = /* @__PURE__ */ new Map();
|
|
5592
5681
|
DEFAULT_CACHE_TTL_SECONDS = 60;
|
|
5682
|
+
MAX_RETRY_AFTER_MS = 15 * 60 * 1e3;
|
|
5593
5683
|
}
|
|
5594
5684
|
});
|
|
5595
5685
|
|
|
@@ -5712,12 +5802,223 @@ var init_classify = __esm({
|
|
|
5712
5802
|
});
|
|
5713
5803
|
|
|
5714
5804
|
// src/edge-core/events.ts
|
|
5805
|
+
async function withBudget(promise, ms) {
|
|
5806
|
+
let timer;
|
|
5807
|
+
try {
|
|
5808
|
+
return await Promise.race([
|
|
5809
|
+
promise,
|
|
5810
|
+
new Promise((resolve) => {
|
|
5811
|
+
timer = setTimeout(() => resolve(void 0), ms);
|
|
5812
|
+
})
|
|
5813
|
+
]);
|
|
5814
|
+
} catch {
|
|
5815
|
+
return void 0;
|
|
5816
|
+
} finally {
|
|
5817
|
+
if (timer) clearTimeout(timer);
|
|
5818
|
+
}
|
|
5819
|
+
}
|
|
5820
|
+
var destKeyOf, BeaconBuffer, beaconBuffer;
|
|
5715
5821
|
var init_events = __esm({
|
|
5716
5822
|
"src/edge-core/events.ts"() {
|
|
5717
5823
|
"use strict";
|
|
5824
|
+
init_http();
|
|
5718
5825
|
init_metadata_capture();
|
|
5719
|
-
|
|
5826
|
+
init_version();
|
|
5720
5827
|
init_request();
|
|
5828
|
+
destKeyOf = (d) => `${d.apiBaseUrl}\0${d.apiKey ?? ""}\0${d.counterparty}\0${d.adapter ?? ""}`;
|
|
5829
|
+
BeaconBuffer = class {
|
|
5830
|
+
constructor(options = {}) {
|
|
5831
|
+
this.queue = [];
|
|
5832
|
+
this.droppedSinceLast = 0;
|
|
5833
|
+
this.droppedTotal = 0;
|
|
5834
|
+
this.deliveredTotal = 0;
|
|
5835
|
+
this.backoffUntil = 0;
|
|
5836
|
+
this.collapse = /* @__PURE__ */ new Map();
|
|
5837
|
+
/** Keys the backend answered 401 for — later batches go unauthenticated. */
|
|
5838
|
+
this.rejectedKeys = /* @__PURE__ */ new Set();
|
|
5839
|
+
this.opts = {
|
|
5840
|
+
maxItems: options.maxItems ?? 1e3,
|
|
5841
|
+
maxBatch: options.maxBatch ?? 100,
|
|
5842
|
+
maxAttempts: options.maxAttempts ?? 3,
|
|
5843
|
+
collapseWindowMs: options.collapseWindowMs ?? 6e4,
|
|
5844
|
+
collapseMaxKeys: options.collapseMaxKeys ?? 1e3,
|
|
5845
|
+
requestTimeoutMs: options.requestTimeoutMs ?? 1e4,
|
|
5846
|
+
retryBackoffMs: options.retryBackoffMs ?? 1e3,
|
|
5847
|
+
now: options.now ?? Date.now
|
|
5848
|
+
};
|
|
5849
|
+
}
|
|
5850
|
+
/**
|
|
5851
|
+
* Queue one beacon. With a `collapseKey`, a repeat inside the window is
|
|
5852
|
+
* merged into a held aggregate (sent when the window closes) instead of
|
|
5853
|
+
* becoming its own item.
|
|
5854
|
+
*/
|
|
5855
|
+
enqueue(dest, item, collapseKey) {
|
|
5856
|
+
const now = this.opts.now();
|
|
5857
|
+
if (collapseKey) {
|
|
5858
|
+
const entry = this.collapse.get(collapseKey);
|
|
5859
|
+
if (entry && now - entry.firstSeenAt < this.opts.collapseWindowMs) {
|
|
5860
|
+
for (const target of [entry.first, entry.held]) {
|
|
5861
|
+
if (target && !target.inFlight && this.queue.includes(target)) {
|
|
5862
|
+
target.item.repeatCount = (target.item.repeatCount ?? 1) + 1;
|
|
5863
|
+
return;
|
|
5864
|
+
}
|
|
5865
|
+
}
|
|
5866
|
+
const held = this.push(
|
|
5867
|
+
dest,
|
|
5868
|
+
{ ...item, repeatCount: 1 },
|
|
5869
|
+
entry.firstSeenAt + this.opts.collapseWindowMs
|
|
5870
|
+
);
|
|
5871
|
+
entry.held = held;
|
|
5872
|
+
return;
|
|
5873
|
+
}
|
|
5874
|
+
this.collapse.delete(collapseKey);
|
|
5875
|
+
if (this.collapse.size >= this.opts.collapseMaxKeys) {
|
|
5876
|
+
const oldest = this.collapse.keys().next().value;
|
|
5877
|
+
if (oldest !== void 0) this.collapse.delete(oldest);
|
|
5878
|
+
}
|
|
5879
|
+
const fresh = { firstSeenAt: now };
|
|
5880
|
+
this.collapse.set(collapseKey, fresh);
|
|
5881
|
+
fresh.first = this.push(dest, item, now);
|
|
5882
|
+
return;
|
|
5883
|
+
}
|
|
5884
|
+
this.push(dest, item, now);
|
|
5885
|
+
}
|
|
5886
|
+
/**
|
|
5887
|
+
* Deliver every eligible queued item. Concurrent callers share ONE
|
|
5888
|
+
* in-flight drain (it survives the caller's budget and a Lambda freeze),
|
|
5889
|
+
* so nothing in flight is ever sent twice; items queued while it runs are
|
|
5890
|
+
* picked up by the same drain.
|
|
5891
|
+
*/
|
|
5892
|
+
flush() {
|
|
5893
|
+
if (!this.inFlight) {
|
|
5894
|
+
this.inFlight = this.drain().finally(() => {
|
|
5895
|
+
this.inFlight = void 0;
|
|
5896
|
+
});
|
|
5897
|
+
}
|
|
5898
|
+
return this.inFlight;
|
|
5899
|
+
}
|
|
5900
|
+
/** Counters for tests and diagnostics. */
|
|
5901
|
+
stats() {
|
|
5902
|
+
return {
|
|
5903
|
+
queueDepth: this.queue.length,
|
|
5904
|
+
droppedSinceLast: this.droppedSinceLast,
|
|
5905
|
+
droppedTotal: this.droppedTotal,
|
|
5906
|
+
deliveredTotal: this.deliveredTotal,
|
|
5907
|
+
flushing: this.inFlight !== void 0
|
|
5908
|
+
};
|
|
5909
|
+
}
|
|
5910
|
+
push(dest, item, eligibleAt) {
|
|
5911
|
+
while (this.queue.length >= this.opts.maxItems) this.dropOldest();
|
|
5912
|
+
const entry = {
|
|
5913
|
+
dest,
|
|
5914
|
+
destKey: destKeyOf(dest),
|
|
5915
|
+
item,
|
|
5916
|
+
attempts: 0,
|
|
5917
|
+
eligibleAt,
|
|
5918
|
+
inFlight: false
|
|
5919
|
+
};
|
|
5920
|
+
this.queue.push(entry);
|
|
5921
|
+
return entry;
|
|
5922
|
+
}
|
|
5923
|
+
dropOldest() {
|
|
5924
|
+
if (this.queue.shift()) this.countDropped(1);
|
|
5925
|
+
}
|
|
5926
|
+
countDropped(n) {
|
|
5927
|
+
this.droppedSinceLast += n;
|
|
5928
|
+
this.droppedTotal += n;
|
|
5929
|
+
}
|
|
5930
|
+
async drain() {
|
|
5931
|
+
for (; ; ) {
|
|
5932
|
+
const now = this.opts.now();
|
|
5933
|
+
if (now < this.backoffUntil) return;
|
|
5934
|
+
const batch = this.takeBatch(now);
|
|
5935
|
+
if (batch.length === 0) return;
|
|
5936
|
+
const ok = await this.send(batch);
|
|
5937
|
+
if (!ok) return;
|
|
5938
|
+
}
|
|
5939
|
+
}
|
|
5940
|
+
/** Oldest eligible item + up to maxBatch-1 more for the same destination. */
|
|
5941
|
+
takeBatch(now) {
|
|
5942
|
+
const first = this.queue.find((q) => q.eligibleAt <= now);
|
|
5943
|
+
if (!first) return [];
|
|
5944
|
+
const batch = [];
|
|
5945
|
+
const rest = [];
|
|
5946
|
+
for (const q of this.queue) {
|
|
5947
|
+
if (batch.length < this.opts.maxBatch && q.destKey === first.destKey && q.eligibleAt <= now) {
|
|
5948
|
+
q.inFlight = true;
|
|
5949
|
+
batch.push(q);
|
|
5950
|
+
} else {
|
|
5951
|
+
rest.push(q);
|
|
5952
|
+
}
|
|
5953
|
+
}
|
|
5954
|
+
this.queue = rest;
|
|
5955
|
+
return batch;
|
|
5956
|
+
}
|
|
5957
|
+
/** POST one batch. Returns false when the drain should pause (backoff). */
|
|
5958
|
+
async send(batch) {
|
|
5959
|
+
const dest = batch[0].dest;
|
|
5960
|
+
const useKey = dest.apiKey && !this.rejectedKeys.has(dest.apiKey) ? dest.apiKey : void 0;
|
|
5961
|
+
const reportedDropped = this.droppedSinceLast;
|
|
5962
|
+
const meta = {
|
|
5963
|
+
droppedSinceLast: reportedDropped,
|
|
5964
|
+
queueDepth: this.queue.length,
|
|
5965
|
+
adapter: dest.adapter ?? "edge-core",
|
|
5966
|
+
version: SDK_VERSION
|
|
5967
|
+
};
|
|
5968
|
+
const controller = typeof AbortController !== "undefined" ? new AbortController() : void 0;
|
|
5969
|
+
const response = await withBudget(
|
|
5970
|
+
sdkFetch(`${dest.apiBaseUrl}/verification-activity/edge-events`, {
|
|
5971
|
+
method: "POST",
|
|
5972
|
+
headers: {
|
|
5973
|
+
"Content-Type": "application/json",
|
|
5974
|
+
...useKey && { Authorization: `Bearer ${useKey}` }
|
|
5975
|
+
},
|
|
5976
|
+
body: JSON.stringify({ events: batch.map((q) => q.item), meta }),
|
|
5977
|
+
...controller && { signal: controller.signal }
|
|
5978
|
+
}),
|
|
5979
|
+
this.opts.requestTimeoutMs
|
|
5980
|
+
);
|
|
5981
|
+
if (!response) controller?.abort();
|
|
5982
|
+
const status = response?.status;
|
|
5983
|
+
for (const q of batch) q.inFlight = false;
|
|
5984
|
+
if (status !== void 0 && status >= 200 && status < 300) {
|
|
5985
|
+
this.droppedSinceLast = Math.max(0, this.droppedSinceLast - reportedDropped);
|
|
5986
|
+
this.deliveredTotal += batch.length;
|
|
5987
|
+
return true;
|
|
5988
|
+
}
|
|
5989
|
+
if (status === 401 && useKey) {
|
|
5990
|
+
this.rejectedKeys.add(useKey);
|
|
5991
|
+
this.requeue(batch, false);
|
|
5992
|
+
return true;
|
|
5993
|
+
}
|
|
5994
|
+
if (status === 429) {
|
|
5995
|
+
const retryAfter = Number(response?.headers.get("retry-after"));
|
|
5996
|
+
const waitMs = Number.isFinite(retryAfter) && retryAfter > 0 ? Math.min(retryAfter, 120) * 1e3 : 3e4;
|
|
5997
|
+
this.backoffUntil = this.opts.now() + waitMs;
|
|
5998
|
+
this.requeue(batch, false);
|
|
5999
|
+
return false;
|
|
6000
|
+
}
|
|
6001
|
+
if (status !== void 0 && status >= 400 && status < 500) {
|
|
6002
|
+
this.countDropped(batch.length);
|
|
6003
|
+
return true;
|
|
6004
|
+
}
|
|
6005
|
+
this.backoffUntil = this.opts.now() + this.opts.retryBackoffMs;
|
|
6006
|
+
this.requeue(batch, true);
|
|
6007
|
+
return false;
|
|
6008
|
+
}
|
|
6009
|
+
/** Put a failed batch back at the head of the queue (order preserved). */
|
|
6010
|
+
requeue(batch, countAttempt) {
|
|
6011
|
+
const keep = [];
|
|
6012
|
+
for (const q of batch) {
|
|
6013
|
+
if (countAttempt) q.attempts += 1;
|
|
6014
|
+
if (q.attempts >= this.opts.maxAttempts) this.countDropped(1);
|
|
6015
|
+
else keep.push(q);
|
|
6016
|
+
}
|
|
6017
|
+
this.queue = [...keep, ...this.queue];
|
|
6018
|
+
while (this.queue.length > this.opts.maxItems) this.dropOldest();
|
|
6019
|
+
}
|
|
6020
|
+
};
|
|
6021
|
+
beaconBuffer = new BeaconBuffer();
|
|
5721
6022
|
}
|
|
5722
6023
|
});
|
|
5723
6024
|
|
|
@@ -5749,6 +6050,7 @@ var init_express = __esm({
|
|
|
5749
6050
|
init_well_known();
|
|
5750
6051
|
init_metadata_capture();
|
|
5751
6052
|
init_anonymous_beacon();
|
|
6053
|
+
init_failure_posture();
|
|
5752
6054
|
DEFAULT_ROUTES_REFRESH_MS = 5 * 60 * 1e3;
|
|
5753
6055
|
}
|
|
5754
6056
|
});
|
|
@@ -5764,6 +6066,7 @@ var init_nextjs = __esm({
|
|
|
5764
6066
|
init_pdlss_pre_check();
|
|
5765
6067
|
init_metadata_capture();
|
|
5766
6068
|
init_anonymous_beacon();
|
|
6069
|
+
init_failure_posture();
|
|
5767
6070
|
init_http_pdlss();
|
|
5768
6071
|
init_approval_gate();
|
|
5769
6072
|
init_verified_hop();
|
|
@@ -6085,6 +6388,7 @@ var init_mcp2 = __esm({
|
|
|
6085
6388
|
init_approval_gate();
|
|
6086
6389
|
init_stepup_poll();
|
|
6087
6390
|
init_well_known();
|
|
6391
|
+
init_failure_posture();
|
|
6088
6392
|
init_mcp_server();
|
|
6089
6393
|
}
|
|
6090
6394
|
});
|
|
@@ -6173,6 +6477,7 @@ var init_src = __esm({
|
|
|
6173
6477
|
"use strict";
|
|
6174
6478
|
init_trust_levels();
|
|
6175
6479
|
init_verify();
|
|
6480
|
+
init_failure_posture();
|
|
6176
6481
|
init_stepup_poll();
|
|
6177
6482
|
init_settlement();
|
|
6178
6483
|
init_express();
|