@astrasyncai/verification-gateway 5.11.0 → 5.12.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 +359 -30
- package/dist/adapters/express.js.map +1 -1
- package/dist/adapters/express.mjs +359 -30
- 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 +168 -41
- package/dist/adapters/mcp.js.map +1 -1
- package/dist/adapters/mcp.mjs +168 -41
- 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 +352 -13
- package/dist/adapters/nextjs.js.map +1 -1
- package/dist/adapters/nextjs.mjs +352 -13
- 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 +100 -8
- package/dist/adapters/sdk.js.map +1 -1
- package/dist/adapters/sdk.mjs +100 -8
- 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 +284 -7
- package/dist/bin/astrasync-codex-hook.js +284 -7
- package/dist/bin/astrasync-guard.js +284 -7
- package/dist/bin/astrasync.js +297 -9
- package/dist/browser/background.js +284 -7
- package/dist/browser/background.js.map +1 -1
- package/dist/browser/background.mjs +284 -7
- 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 +284 -7
- package/dist/codex/index.js.map +1 -1
- package/dist/codex/index.mjs +284 -7
- package/dist/codex/index.mjs.map +1 -1
- package/dist/cursor/extension.js +284 -7
- package/dist/cursor/extension.js.map +1 -1
- package/dist/cursor/extension.mjs +284 -7
- 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 +337 -55
- package/dist/edge-core/index.js.map +1 -1
- package/dist/edge-core/index.mjs +334 -55
- package/dist/edge-core/index.mjs.map +1 -1
- package/dist/gateway/gateway.js +284 -7
- package/dist/gateway/gateway.js.map +1 -1
- package/dist/gateway/gateway.mjs +284 -7
- 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 -5
- package/dist/index.d.ts +118 -5
- package/dist/index.js +486 -63
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +480 -63
- 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 -4
- package/dist/verify.d.ts +35 -4
- package/dist/verify.js +130 -16
- package/dist/verify.js.map +1 -1
- package/dist/verify.mjs +129 -16
- package/dist/verify.mjs.map +1 -1
- package/package.json +1 -1
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.12.0";
|
|
40
40
|
}
|
|
41
41
|
});
|
|
42
42
|
|
|
@@ -5057,6 +5057,20 @@ 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
5075
|
async function performInitCheck(apiBaseUrl, debug, strictInit, apiKey) {
|
|
5062
5076
|
initCheckPerformed = true;
|
|
@@ -5255,11 +5269,43 @@ function createGuidanceResponse(_config, reason, options = {}) {
|
|
|
5255
5269
|
// coercing the absent recommendation to a policy 'deny'. Misconfig is
|
|
5256
5270
|
// deterministic and intentionally NOT marked retryable.
|
|
5257
5271
|
...isApiError && { retryable: true },
|
|
5272
|
+
...options.httpStatus !== void 0 && { httpStatus: options.httpStatus },
|
|
5273
|
+
...options.retryAfterMs !== void 0 && { retryAfterMs: options.retryAfterMs },
|
|
5258
5274
|
correlationId: options.correlationId,
|
|
5259
5275
|
attemptId: options.attemptId,
|
|
5260
5276
|
verifiedAt: /* @__PURE__ */ new Date()
|
|
5261
5277
|
};
|
|
5262
5278
|
}
|
|
5279
|
+
async function readJsonSafe(response) {
|
|
5280
|
+
try {
|
|
5281
|
+
const parsed = await response.json();
|
|
5282
|
+
return parsed && typeof parsed === "object" ? parsed : {};
|
|
5283
|
+
} catch {
|
|
5284
|
+
return {};
|
|
5285
|
+
}
|
|
5286
|
+
}
|
|
5287
|
+
function rejectedIdentityGuidance(failures) {
|
|
5288
|
+
const f = failures?.find((x) => REJECTED_IDENTITY_DIMENSIONS.has(x.dimension));
|
|
5289
|
+
if (!f) return void 0;
|
|
5290
|
+
if (f.dimension === "agent.lookup") {
|
|
5291
|
+
return `The presented agent identifier is not registered with AstraSync. ${UNKNOWN_AGENT_GUIDANCE}`;
|
|
5292
|
+
}
|
|
5293
|
+
return f.guidance ? `${f.message} ${f.guidance}` : f.message;
|
|
5294
|
+
}
|
|
5295
|
+
function parseRetryAfterMs(response) {
|
|
5296
|
+
const raw = response.headers?.get?.("retry-after");
|
|
5297
|
+
if (!raw) return void 0;
|
|
5298
|
+
const trimmed = raw.trim();
|
|
5299
|
+
let ms;
|
|
5300
|
+
if (/^\d+(\.\d+)?$/.test(trimmed)) {
|
|
5301
|
+
ms = Number(trimmed) * 1e3;
|
|
5302
|
+
} else {
|
|
5303
|
+
const at = Date.parse(trimmed);
|
|
5304
|
+
if (Number.isNaN(at)) return void 0;
|
|
5305
|
+
ms = at - Date.now();
|
|
5306
|
+
}
|
|
5307
|
+
return Math.min(MAX_RETRY_AFTER_MS, Math.max(0, Math.round(ms)));
|
|
5308
|
+
}
|
|
5263
5309
|
async function callVerifyAccessAPI(config, request2) {
|
|
5264
5310
|
const { credentials, ...requestData } = request2;
|
|
5265
5311
|
const body = {
|
|
@@ -5316,7 +5362,8 @@ async function callVerifyAccessAPI(config, request2) {
|
|
|
5316
5362
|
body: JSON.stringify(body),
|
|
5317
5363
|
signal: AbortSignal.timeout(config.verifyTimeoutMs ?? 1e4)
|
|
5318
5364
|
});
|
|
5319
|
-
const data = await response
|
|
5365
|
+
const data = await readJsonSafe(response);
|
|
5366
|
+
const retryAfterMs = parseRetryAfterMs(response);
|
|
5320
5367
|
if (response.status === 410) {
|
|
5321
5368
|
return {
|
|
5322
5369
|
success: true,
|
|
@@ -5354,6 +5401,23 @@ async function callVerifyAccessAPI(config, request2) {
|
|
|
5354
5401
|
}
|
|
5355
5402
|
};
|
|
5356
5403
|
}
|
|
5404
|
+
if (response.status === 404 && credentials.astraId && (data?.error === "AGENT_NOT_FOUND" || typeof data?.message === "string" && /agent/i.test(data.message))) {
|
|
5405
|
+
return {
|
|
5406
|
+
success: true,
|
|
5407
|
+
attemptId: typeof data?.attemptId === "string" ? data.attemptId : void 0,
|
|
5408
|
+
access: {
|
|
5409
|
+
allowed: false,
|
|
5410
|
+
reason: "unknown_agent",
|
|
5411
|
+
failures: [
|
|
5412
|
+
{
|
|
5413
|
+
dimension: "identity.unknown_agent",
|
|
5414
|
+
message: "The presented agent identifier is not registered with AstraSync.",
|
|
5415
|
+
guidance: UNKNOWN_AGENT_GUIDANCE
|
|
5416
|
+
}
|
|
5417
|
+
]
|
|
5418
|
+
}
|
|
5419
|
+
};
|
|
5420
|
+
}
|
|
5357
5421
|
if (!response.ok) {
|
|
5358
5422
|
if (response.status === 401) {
|
|
5359
5423
|
return {
|
|
@@ -5368,9 +5432,11 @@ async function callVerifyAccessAPI(config, request2) {
|
|
|
5368
5432
|
}
|
|
5369
5433
|
return {
|
|
5370
5434
|
success: false,
|
|
5371
|
-
error: data.message || data.error || `API returned ${response.status}`,
|
|
5435
|
+
error: typeof data?.message === "string" && data.message || typeof data?.error === "string" && data.error || `API returned ${response.status}`,
|
|
5372
5436
|
correlationId: typeof data?.correlationId === "string" ? data.correlationId : void 0,
|
|
5373
|
-
attemptId: typeof data?.attemptId === "string" ? data.attemptId : void 0
|
|
5437
|
+
attemptId: typeof data?.attemptId === "string" ? data.attemptId : void 0,
|
|
5438
|
+
httpStatus: response.status,
|
|
5439
|
+
...retryAfterMs !== void 0 && { retryAfterMs }
|
|
5374
5440
|
};
|
|
5375
5441
|
}
|
|
5376
5442
|
return data;
|
|
@@ -5442,12 +5508,14 @@ async function verify(config, request2, options) {
|
|
|
5442
5508
|
correlationId: apiResponse.correlationId,
|
|
5443
5509
|
attemptId: apiResponse.attemptId,
|
|
5444
5510
|
remediation: apiResponse.remediation,
|
|
5511
|
+
httpStatus: apiResponse.httpStatus,
|
|
5512
|
+
retryAfterMs: apiResponse.retryAfterMs,
|
|
5445
5513
|
urls
|
|
5446
5514
|
});
|
|
5447
5515
|
}
|
|
5448
5516
|
if (!apiResponse.access?.allowed) {
|
|
5449
5517
|
const aggregatedFailures = apiResponse.access?.failures;
|
|
5450
|
-
const idVerifiedFromBackend = apiResponse.verificationContext?.idVerified === true;
|
|
5518
|
+
const idVerifiedFromBackend = apiResponse.verificationContext?.idVerified === true && !aggregatedFailures?.some((f) => REJECTED_IDENTITY_DIMENSIONS.has(f.dimension));
|
|
5451
5519
|
const result2 = {
|
|
5452
5520
|
identityVerified: idVerifiedFromBackend,
|
|
5453
5521
|
policyAllowed: false,
|
|
@@ -5459,7 +5527,10 @@ async function verify(config, request2, options) {
|
|
|
5459
5527
|
requiresStepUp: apiResponse.access?.requiresStepUp,
|
|
5460
5528
|
requiresApproval: apiResponse.access?.requiresApproval,
|
|
5461
5529
|
guidance: {
|
|
5462
|
-
|
|
5530
|
+
// 5.12.0: a presented-but-rejected id (malformed / unknown) carries
|
|
5531
|
+
// actionable registration guidance on its failure — surface it
|
|
5532
|
+
// instead of the bare machine reason ('unknown_agent').
|
|
5533
|
+
message: rejectedIdentityGuidance(aggregatedFailures) ?? (apiResponse.access?.reason || "Access denied by PDLSS policy"),
|
|
5463
5534
|
registrationUrl: urls?.registrationUrl ?? "",
|
|
5464
5535
|
documentationUrl: urls?.documentationUrl ?? "",
|
|
5465
5536
|
// 5.1.0: anonymous callers land on this branch — steer MCP-hosted
|
|
@@ -5559,7 +5630,7 @@ async function verify(config, request2, options) {
|
|
|
5559
5630
|
registrationUrl: urls?.registrationUrl ?? "",
|
|
5560
5631
|
documentationUrl: urls?.documentationUrl ?? ""
|
|
5561
5632
|
};
|
|
5562
|
-
} else if (result.recommendation === "step_up_required") {
|
|
5633
|
+
} else if (result.recommendation === "step_up_required" && result.identityVerified) {
|
|
5563
5634
|
result.requiresStepUp = true;
|
|
5564
5635
|
result.denialReasons = serverDenialReasons ?? result.recommendationReasons ?? ["Step-up verification required"];
|
|
5565
5636
|
}
|
|
@@ -5569,7 +5640,7 @@ async function verify(config, request2, options) {
|
|
|
5569
5640
|
}
|
|
5570
5641
|
return result;
|
|
5571
5642
|
}
|
|
5572
|
-
var DEFAULT_CONFIG, initCheckPerformed, deprecationWarningShown, verificationCache, DEFAULT_CACHE_TTL_SECONDS;
|
|
5643
|
+
var DEFAULT_CONFIG, initCheckPerformed, deprecationWarningShown, verificationCache, DEFAULT_CACHE_TTL_SECONDS, MAX_RETRY_AFTER_MS;
|
|
5573
5644
|
var init_verify = __esm({
|
|
5574
5645
|
"src/verify.ts"() {
|
|
5575
5646
|
"use strict";
|
|
@@ -5577,6 +5648,7 @@ var init_verify = __esm({
|
|
|
5577
5648
|
init_trust_levels();
|
|
5578
5649
|
init_version();
|
|
5579
5650
|
init_well_known();
|
|
5651
|
+
init_failure_posture();
|
|
5580
5652
|
DEFAULT_CONFIG = {
|
|
5581
5653
|
apiBaseUrl: "https://astrasync.ai/api",
|
|
5582
5654
|
// minTrustScore + minTrustScoreForFull deprecated in v2.3.0 — server decides.
|
|
@@ -5590,6 +5662,7 @@ var init_verify = __esm({
|
|
|
5590
5662
|
deprecationWarningShown = false;
|
|
5591
5663
|
verificationCache = /* @__PURE__ */ new Map();
|
|
5592
5664
|
DEFAULT_CACHE_TTL_SECONDS = 60;
|
|
5665
|
+
MAX_RETRY_AFTER_MS = 15 * 60 * 1e3;
|
|
5593
5666
|
}
|
|
5594
5667
|
});
|
|
5595
5668
|
|
|
@@ -5712,12 +5785,223 @@ var init_classify = __esm({
|
|
|
5712
5785
|
});
|
|
5713
5786
|
|
|
5714
5787
|
// src/edge-core/events.ts
|
|
5788
|
+
async function withBudget(promise, ms) {
|
|
5789
|
+
let timer;
|
|
5790
|
+
try {
|
|
5791
|
+
return await Promise.race([
|
|
5792
|
+
promise,
|
|
5793
|
+
new Promise((resolve) => {
|
|
5794
|
+
timer = setTimeout(() => resolve(void 0), ms);
|
|
5795
|
+
})
|
|
5796
|
+
]);
|
|
5797
|
+
} catch {
|
|
5798
|
+
return void 0;
|
|
5799
|
+
} finally {
|
|
5800
|
+
if (timer) clearTimeout(timer);
|
|
5801
|
+
}
|
|
5802
|
+
}
|
|
5803
|
+
var destKeyOf, BeaconBuffer, beaconBuffer;
|
|
5715
5804
|
var init_events = __esm({
|
|
5716
5805
|
"src/edge-core/events.ts"() {
|
|
5717
5806
|
"use strict";
|
|
5807
|
+
init_http();
|
|
5718
5808
|
init_metadata_capture();
|
|
5719
|
-
|
|
5809
|
+
init_version();
|
|
5720
5810
|
init_request();
|
|
5811
|
+
destKeyOf = (d) => `${d.apiBaseUrl}\0${d.apiKey ?? ""}\0${d.counterparty}\0${d.adapter ?? ""}`;
|
|
5812
|
+
BeaconBuffer = class {
|
|
5813
|
+
constructor(options = {}) {
|
|
5814
|
+
this.queue = [];
|
|
5815
|
+
this.droppedSinceLast = 0;
|
|
5816
|
+
this.droppedTotal = 0;
|
|
5817
|
+
this.deliveredTotal = 0;
|
|
5818
|
+
this.backoffUntil = 0;
|
|
5819
|
+
this.collapse = /* @__PURE__ */ new Map();
|
|
5820
|
+
/** Keys the backend answered 401 for — later batches go unauthenticated. */
|
|
5821
|
+
this.rejectedKeys = /* @__PURE__ */ new Set();
|
|
5822
|
+
this.opts = {
|
|
5823
|
+
maxItems: options.maxItems ?? 1e3,
|
|
5824
|
+
maxBatch: options.maxBatch ?? 100,
|
|
5825
|
+
maxAttempts: options.maxAttempts ?? 3,
|
|
5826
|
+
collapseWindowMs: options.collapseWindowMs ?? 6e4,
|
|
5827
|
+
collapseMaxKeys: options.collapseMaxKeys ?? 1e3,
|
|
5828
|
+
requestTimeoutMs: options.requestTimeoutMs ?? 1e4,
|
|
5829
|
+
retryBackoffMs: options.retryBackoffMs ?? 1e3,
|
|
5830
|
+
now: options.now ?? Date.now
|
|
5831
|
+
};
|
|
5832
|
+
}
|
|
5833
|
+
/**
|
|
5834
|
+
* Queue one beacon. With a `collapseKey`, a repeat inside the window is
|
|
5835
|
+
* merged into a held aggregate (sent when the window closes) instead of
|
|
5836
|
+
* becoming its own item.
|
|
5837
|
+
*/
|
|
5838
|
+
enqueue(dest, item, collapseKey) {
|
|
5839
|
+
const now = this.opts.now();
|
|
5840
|
+
if (collapseKey) {
|
|
5841
|
+
const entry = this.collapse.get(collapseKey);
|
|
5842
|
+
if (entry && now - entry.firstSeenAt < this.opts.collapseWindowMs) {
|
|
5843
|
+
for (const target of [entry.first, entry.held]) {
|
|
5844
|
+
if (target && !target.inFlight && this.queue.includes(target)) {
|
|
5845
|
+
target.item.repeatCount = (target.item.repeatCount ?? 1) + 1;
|
|
5846
|
+
return;
|
|
5847
|
+
}
|
|
5848
|
+
}
|
|
5849
|
+
const held = this.push(
|
|
5850
|
+
dest,
|
|
5851
|
+
{ ...item, repeatCount: 1 },
|
|
5852
|
+
entry.firstSeenAt + this.opts.collapseWindowMs
|
|
5853
|
+
);
|
|
5854
|
+
entry.held = held;
|
|
5855
|
+
return;
|
|
5856
|
+
}
|
|
5857
|
+
this.collapse.delete(collapseKey);
|
|
5858
|
+
if (this.collapse.size >= this.opts.collapseMaxKeys) {
|
|
5859
|
+
const oldest = this.collapse.keys().next().value;
|
|
5860
|
+
if (oldest !== void 0) this.collapse.delete(oldest);
|
|
5861
|
+
}
|
|
5862
|
+
const fresh = { firstSeenAt: now };
|
|
5863
|
+
this.collapse.set(collapseKey, fresh);
|
|
5864
|
+
fresh.first = this.push(dest, item, now);
|
|
5865
|
+
return;
|
|
5866
|
+
}
|
|
5867
|
+
this.push(dest, item, now);
|
|
5868
|
+
}
|
|
5869
|
+
/**
|
|
5870
|
+
* Deliver every eligible queued item. Concurrent callers share ONE
|
|
5871
|
+
* in-flight drain (it survives the caller's budget and a Lambda freeze),
|
|
5872
|
+
* so nothing in flight is ever sent twice; items queued while it runs are
|
|
5873
|
+
* picked up by the same drain.
|
|
5874
|
+
*/
|
|
5875
|
+
flush() {
|
|
5876
|
+
if (!this.inFlight) {
|
|
5877
|
+
this.inFlight = this.drain().finally(() => {
|
|
5878
|
+
this.inFlight = void 0;
|
|
5879
|
+
});
|
|
5880
|
+
}
|
|
5881
|
+
return this.inFlight;
|
|
5882
|
+
}
|
|
5883
|
+
/** Counters for tests and diagnostics. */
|
|
5884
|
+
stats() {
|
|
5885
|
+
return {
|
|
5886
|
+
queueDepth: this.queue.length,
|
|
5887
|
+
droppedSinceLast: this.droppedSinceLast,
|
|
5888
|
+
droppedTotal: this.droppedTotal,
|
|
5889
|
+
deliveredTotal: this.deliveredTotal,
|
|
5890
|
+
flushing: this.inFlight !== void 0
|
|
5891
|
+
};
|
|
5892
|
+
}
|
|
5893
|
+
push(dest, item, eligibleAt) {
|
|
5894
|
+
while (this.queue.length >= this.opts.maxItems) this.dropOldest();
|
|
5895
|
+
const entry = {
|
|
5896
|
+
dest,
|
|
5897
|
+
destKey: destKeyOf(dest),
|
|
5898
|
+
item,
|
|
5899
|
+
attempts: 0,
|
|
5900
|
+
eligibleAt,
|
|
5901
|
+
inFlight: false
|
|
5902
|
+
};
|
|
5903
|
+
this.queue.push(entry);
|
|
5904
|
+
return entry;
|
|
5905
|
+
}
|
|
5906
|
+
dropOldest() {
|
|
5907
|
+
if (this.queue.shift()) this.countDropped(1);
|
|
5908
|
+
}
|
|
5909
|
+
countDropped(n) {
|
|
5910
|
+
this.droppedSinceLast += n;
|
|
5911
|
+
this.droppedTotal += n;
|
|
5912
|
+
}
|
|
5913
|
+
async drain() {
|
|
5914
|
+
for (; ; ) {
|
|
5915
|
+
const now = this.opts.now();
|
|
5916
|
+
if (now < this.backoffUntil) return;
|
|
5917
|
+
const batch = this.takeBatch(now);
|
|
5918
|
+
if (batch.length === 0) return;
|
|
5919
|
+
const ok = await this.send(batch);
|
|
5920
|
+
if (!ok) return;
|
|
5921
|
+
}
|
|
5922
|
+
}
|
|
5923
|
+
/** Oldest eligible item + up to maxBatch-1 more for the same destination. */
|
|
5924
|
+
takeBatch(now) {
|
|
5925
|
+
const first = this.queue.find((q) => q.eligibleAt <= now);
|
|
5926
|
+
if (!first) return [];
|
|
5927
|
+
const batch = [];
|
|
5928
|
+
const rest = [];
|
|
5929
|
+
for (const q of this.queue) {
|
|
5930
|
+
if (batch.length < this.opts.maxBatch && q.destKey === first.destKey && q.eligibleAt <= now) {
|
|
5931
|
+
q.inFlight = true;
|
|
5932
|
+
batch.push(q);
|
|
5933
|
+
} else {
|
|
5934
|
+
rest.push(q);
|
|
5935
|
+
}
|
|
5936
|
+
}
|
|
5937
|
+
this.queue = rest;
|
|
5938
|
+
return batch;
|
|
5939
|
+
}
|
|
5940
|
+
/** POST one batch. Returns false when the drain should pause (backoff). */
|
|
5941
|
+
async send(batch) {
|
|
5942
|
+
const dest = batch[0].dest;
|
|
5943
|
+
const useKey = dest.apiKey && !this.rejectedKeys.has(dest.apiKey) ? dest.apiKey : void 0;
|
|
5944
|
+
const reportedDropped = this.droppedSinceLast;
|
|
5945
|
+
const meta = {
|
|
5946
|
+
droppedSinceLast: reportedDropped,
|
|
5947
|
+
queueDepth: this.queue.length,
|
|
5948
|
+
adapter: dest.adapter ?? "edge-core",
|
|
5949
|
+
version: SDK_VERSION
|
|
5950
|
+
};
|
|
5951
|
+
const controller = typeof AbortController !== "undefined" ? new AbortController() : void 0;
|
|
5952
|
+
const response = await withBudget(
|
|
5953
|
+
sdkFetch(`${dest.apiBaseUrl}/verification-activity/edge-events`, {
|
|
5954
|
+
method: "POST",
|
|
5955
|
+
headers: {
|
|
5956
|
+
"Content-Type": "application/json",
|
|
5957
|
+
...useKey && { Authorization: `Bearer ${useKey}` }
|
|
5958
|
+
},
|
|
5959
|
+
body: JSON.stringify({ events: batch.map((q) => q.item), meta }),
|
|
5960
|
+
...controller && { signal: controller.signal }
|
|
5961
|
+
}),
|
|
5962
|
+
this.opts.requestTimeoutMs
|
|
5963
|
+
);
|
|
5964
|
+
if (!response) controller?.abort();
|
|
5965
|
+
const status = response?.status;
|
|
5966
|
+
for (const q of batch) q.inFlight = false;
|
|
5967
|
+
if (status !== void 0 && status >= 200 && status < 300) {
|
|
5968
|
+
this.droppedSinceLast = Math.max(0, this.droppedSinceLast - reportedDropped);
|
|
5969
|
+
this.deliveredTotal += batch.length;
|
|
5970
|
+
return true;
|
|
5971
|
+
}
|
|
5972
|
+
if (status === 401 && useKey) {
|
|
5973
|
+
this.rejectedKeys.add(useKey);
|
|
5974
|
+
this.requeue(batch, false);
|
|
5975
|
+
return true;
|
|
5976
|
+
}
|
|
5977
|
+
if (status === 429) {
|
|
5978
|
+
const retryAfter = Number(response?.headers.get("retry-after"));
|
|
5979
|
+
const waitMs = Number.isFinite(retryAfter) && retryAfter > 0 ? Math.min(retryAfter, 120) * 1e3 : 3e4;
|
|
5980
|
+
this.backoffUntil = this.opts.now() + waitMs;
|
|
5981
|
+
this.requeue(batch, false);
|
|
5982
|
+
return false;
|
|
5983
|
+
}
|
|
5984
|
+
if (status !== void 0 && status >= 400 && status < 500) {
|
|
5985
|
+
this.countDropped(batch.length);
|
|
5986
|
+
return true;
|
|
5987
|
+
}
|
|
5988
|
+
this.backoffUntil = this.opts.now() + this.opts.retryBackoffMs;
|
|
5989
|
+
this.requeue(batch, true);
|
|
5990
|
+
return false;
|
|
5991
|
+
}
|
|
5992
|
+
/** Put a failed batch back at the head of the queue (order preserved). */
|
|
5993
|
+
requeue(batch, countAttempt) {
|
|
5994
|
+
const keep = [];
|
|
5995
|
+
for (const q of batch) {
|
|
5996
|
+
if (countAttempt) q.attempts += 1;
|
|
5997
|
+
if (q.attempts >= this.opts.maxAttempts) this.countDropped(1);
|
|
5998
|
+
else keep.push(q);
|
|
5999
|
+
}
|
|
6000
|
+
this.queue = [...keep, ...this.queue];
|
|
6001
|
+
while (this.queue.length > this.opts.maxItems) this.dropOldest();
|
|
6002
|
+
}
|
|
6003
|
+
};
|
|
6004
|
+
beaconBuffer = new BeaconBuffer();
|
|
5721
6005
|
}
|
|
5722
6006
|
});
|
|
5723
6007
|
|
|
@@ -5749,6 +6033,7 @@ var init_express = __esm({
|
|
|
5749
6033
|
init_well_known();
|
|
5750
6034
|
init_metadata_capture();
|
|
5751
6035
|
init_anonymous_beacon();
|
|
6036
|
+
init_failure_posture();
|
|
5752
6037
|
DEFAULT_ROUTES_REFRESH_MS = 5 * 60 * 1e3;
|
|
5753
6038
|
}
|
|
5754
6039
|
});
|
|
@@ -5764,6 +6049,7 @@ var init_nextjs = __esm({
|
|
|
5764
6049
|
init_pdlss_pre_check();
|
|
5765
6050
|
init_metadata_capture();
|
|
5766
6051
|
init_anonymous_beacon();
|
|
6052
|
+
init_failure_posture();
|
|
5767
6053
|
init_http_pdlss();
|
|
5768
6054
|
init_approval_gate();
|
|
5769
6055
|
init_verified_hop();
|
|
@@ -6085,6 +6371,7 @@ var init_mcp2 = __esm({
|
|
|
6085
6371
|
init_approval_gate();
|
|
6086
6372
|
init_stepup_poll();
|
|
6087
6373
|
init_well_known();
|
|
6374
|
+
init_failure_posture();
|
|
6088
6375
|
init_mcp_server();
|
|
6089
6376
|
}
|
|
6090
6377
|
});
|
|
@@ -6173,6 +6460,7 @@ var init_src = __esm({
|
|
|
6173
6460
|
"use strict";
|
|
6174
6461
|
init_trust_levels();
|
|
6175
6462
|
init_verify();
|
|
6463
|
+
init_failure_posture();
|
|
6176
6464
|
init_stepup_poll();
|
|
6177
6465
|
init_settlement();
|
|
6178
6466
|
init_express();
|