@astrasyncai/verification-gateway 3.10.0 → 3.11.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 +1 -1
- package/dist/adapter-interface/interface.d.ts +1 -1
- package/dist/adapters/express.js +1 -1
- package/dist/adapters/express.js.map +1 -1
- package/dist/adapters/express.mjs +1 -1
- package/dist/adapters/express.mjs.map +1 -1
- package/dist/adapters/mcp.js +1 -1
- package/dist/adapters/mcp.js.map +1 -1
- package/dist/adapters/mcp.mjs +1 -1
- package/dist/adapters/mcp.mjs.map +1 -1
- package/dist/adapters/nextjs.js +1 -1
- package/dist/adapters/nextjs.js.map +1 -1
- package/dist/adapters/nextjs.mjs +1 -1
- package/dist/adapters/nextjs.mjs.map +1 -1
- package/dist/adapters/sdk.js +1 -1
- package/dist/adapters/sdk.js.map +1 -1
- package/dist/adapters/sdk.mjs +1 -1
- package/dist/adapters/sdk.mjs.map +1 -1
- package/dist/bin/astrasync-claude-hook.js +317 -35
- package/dist/bin/astrasync-codex-hook.js +5107 -0
- package/dist/bin/astrasync-guard.js +430 -40
- package/dist/bin/astrasync.js +453 -41
- package/dist/browser/background.js +279 -24
- package/dist/browser/background.js.map +1 -1
- package/dist/browser/background.mjs +279 -24
- package/dist/browser/background.mjs.map +1 -1
- package/dist/browser/browser-adapter.d.mts +1 -1
- package/dist/browser/browser-adapter.d.ts +1 -1
- package/dist/claude-code/claude-code-adapter.d.mts +1 -1
- package/dist/claude-code/claude-code-adapter.d.ts +1 -1
- package/dist/claude-code/claude-code-adapter.js +9 -1
- package/dist/claude-code/claude-code-adapter.js.map +1 -1
- package/dist/claude-code/claude-code-adapter.mjs +9 -1
- package/dist/claude-code/claude-code-adapter.mjs.map +1 -1
- package/dist/cli/index.d.mts +1 -1
- package/dist/cli/index.d.ts +1 -1
- package/dist/codex/index.d.mts +230 -0
- package/dist/codex/index.d.ts +230 -0
- package/dist/codex/index.js +5225 -0
- package/dist/codex/index.js.map +1 -0
- package/dist/codex/index.mjs +5197 -0
- package/dist/codex/index.mjs.map +1 -0
- package/dist/cursor/cursor-adapter.d.mts +1 -1
- package/dist/cursor/cursor-adapter.d.ts +1 -1
- package/dist/cursor/extension.d.mts +1 -1
- package/dist/cursor/extension.d.ts +1 -1
- package/dist/cursor/extension.js +279 -24
- package/dist/cursor/extension.js.map +1 -1
- package/dist/cursor/extension.mjs +279 -24
- package/dist/cursor/extension.mjs.map +1 -1
- package/dist/gateway/gateway.d.mts +32 -2
- package/dist/gateway/gateway.d.ts +32 -2
- package/dist/gateway/gateway.js +279 -24
- package/dist/gateway/gateway.js.map +1 -1
- package/dist/gateway/gateway.mjs +279 -24
- 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 +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.map +1 -1
- package/dist/local-evaluator/evaluator.d.mts +1 -1
- package/dist/local-evaluator/evaluator.d.ts +1 -1
- package/dist/local-evaluator/evaluator.js +165 -7
- package/dist/local-evaluator/evaluator.js.map +1 -1
- package/dist/local-evaluator/evaluator.mjs +165 -7
- package/dist/local-evaluator/evaluator.mjs.map +1 -1
- package/dist/{types-D0lCtFQ7.d.mts → types-BV6abBnF.d.mts} +6 -0
- package/dist/{types-YbiXYKx1.d.ts → types-C23_uaY8.d.ts} +6 -0
- package/dist/verify.js +1 -1
- package/dist/verify.js.map +1 -1
- package/dist/verify.mjs +1 -1
- package/dist/verify.mjs.map +1 -1
- package/package.json +8 -2
|
@@ -284,7 +284,9 @@ var HIGH_RISK_COMMANDS = [
|
|
|
284
284
|
"git push",
|
|
285
285
|
"npm publish",
|
|
286
286
|
"docker",
|
|
287
|
-
"kubectl"
|
|
287
|
+
"kubectl",
|
|
288
|
+
"gh pr create",
|
|
289
|
+
"gh pr merge"
|
|
288
290
|
];
|
|
289
291
|
var SENSITIVE_PATHS = [
|
|
290
292
|
".ssh",
|
|
@@ -303,6 +305,164 @@ var SENSITIVE_PATHS = [
|
|
|
303
305
|
".pypirc"
|
|
304
306
|
];
|
|
305
307
|
|
|
308
|
+
// src/local-evaluator/command-matcher.ts
|
|
309
|
+
var WRAPPERS = /* @__PURE__ */ new Set([
|
|
310
|
+
"sudo",
|
|
311
|
+
"doas",
|
|
312
|
+
"env",
|
|
313
|
+
"nohup",
|
|
314
|
+
"time",
|
|
315
|
+
"timeout",
|
|
316
|
+
"nice",
|
|
317
|
+
"ionice",
|
|
318
|
+
"stdbuf",
|
|
319
|
+
"xargs",
|
|
320
|
+
"command",
|
|
321
|
+
"exec",
|
|
322
|
+
"builtin"
|
|
323
|
+
]);
|
|
324
|
+
var ASSIGN_RE = /^[a-z_][a-z0-9_]*=/;
|
|
325
|
+
var MAX_WRAPPER_HOPS = 4;
|
|
326
|
+
var MAX_RECURSION_DEPTH = 3;
|
|
327
|
+
var MAX_COMMAND_LENGTH = 1e5;
|
|
328
|
+
var LOCAL_HOST_RE = /^(localhost|127\.0\.0\.1|::1|[a-z0-9.-]*\.localhost)$/;
|
|
329
|
+
function buildRiskList(entries) {
|
|
330
|
+
const singleWord = /* @__PURE__ */ new Set();
|
|
331
|
+
const multiWord = [];
|
|
332
|
+
for (const entry of entries) {
|
|
333
|
+
const words = entry.toLowerCase().trim().split(/\s+/);
|
|
334
|
+
if (words.length === 1) singleWord.add(words[0]);
|
|
335
|
+
else multiWord.push(words);
|
|
336
|
+
}
|
|
337
|
+
multiWord.sort((a, b) => b.length - a.length);
|
|
338
|
+
return { singleWord, multiWord };
|
|
339
|
+
}
|
|
340
|
+
function stripHeredocBodies(text) {
|
|
341
|
+
const lines = text.split("\n");
|
|
342
|
+
const kept = [];
|
|
343
|
+
let terminator = null;
|
|
344
|
+
for (const line of lines) {
|
|
345
|
+
if (terminator !== null) {
|
|
346
|
+
if (line.trim() === terminator) terminator = null;
|
|
347
|
+
continue;
|
|
348
|
+
}
|
|
349
|
+
kept.push(line);
|
|
350
|
+
const heredoc = line.match(/<<-?\s*['"]?(\w+)['"]?/);
|
|
351
|
+
if (heredoc) terminator = heredoc[1];
|
|
352
|
+
}
|
|
353
|
+
return kept.join("\n");
|
|
354
|
+
}
|
|
355
|
+
function extractDollarSubstitutions(text, collect) {
|
|
356
|
+
let result = text;
|
|
357
|
+
let start = result.indexOf("$(");
|
|
358
|
+
let iterations = 0;
|
|
359
|
+
while (start !== -1 && iterations < 50) {
|
|
360
|
+
iterations++;
|
|
361
|
+
let depth = 0;
|
|
362
|
+
let end = result.length;
|
|
363
|
+
for (let i = start + 1; i < result.length; i++) {
|
|
364
|
+
if (result[i] === "(") depth++;
|
|
365
|
+
else if (result[i] === ")") {
|
|
366
|
+
depth--;
|
|
367
|
+
if (depth === 0) {
|
|
368
|
+
end = i;
|
|
369
|
+
break;
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
collect(result.slice(start + 2, end));
|
|
374
|
+
result = `${result.slice(0, start)} ${result.slice(Math.min(end + 1, result.length))}`;
|
|
375
|
+
start = result.indexOf("$(");
|
|
376
|
+
}
|
|
377
|
+
return result;
|
|
378
|
+
}
|
|
379
|
+
function extractBacktickSubstitutions(text, collect) {
|
|
380
|
+
if (!text.includes("`")) return text;
|
|
381
|
+
const chunks = text.split("`");
|
|
382
|
+
const kept = [];
|
|
383
|
+
for (let i = 0; i < chunks.length; i++) {
|
|
384
|
+
if (i % 2 === 1) collect(chunks[i]);
|
|
385
|
+
else kept.push(chunks[i]);
|
|
386
|
+
}
|
|
387
|
+
return kept.join(" ");
|
|
388
|
+
}
|
|
389
|
+
function basename(token) {
|
|
390
|
+
const slash = token.lastIndexOf("/");
|
|
391
|
+
return slash === -1 ? token : token.slice(slash + 1);
|
|
392
|
+
}
|
|
393
|
+
function matchSegment(segment, list) {
|
|
394
|
+
const tokens = segment.split(/\s+/).filter((t) => /[a-z0-9]/.test(t));
|
|
395
|
+
let i = 0;
|
|
396
|
+
let hops = 0;
|
|
397
|
+
while (i < tokens.length) {
|
|
398
|
+
while (i < tokens.length && (tokens[i] === "export" || ASSIGN_RE.test(tokens[i]))) i++;
|
|
399
|
+
if (i >= tokens.length) return null;
|
|
400
|
+
const cmd = basename(tokens[i]);
|
|
401
|
+
const significant = [cmd, ...tokens.slice(i + 1).filter((t) => !t.startsWith("-"))];
|
|
402
|
+
for (const entry of list.multiWord) {
|
|
403
|
+
if (entry.length <= significant.length && entry.every((w, j) => significant[j] === w)) {
|
|
404
|
+
return entry.join(" ");
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
if (list.singleWord.has(cmd)) return cmd;
|
|
408
|
+
if (WRAPPERS.has(cmd) && hops < MAX_WRAPPER_HOPS) {
|
|
409
|
+
hops++;
|
|
410
|
+
i++;
|
|
411
|
+
while (i < tokens.length && (tokens[i].startsWith("-") || ASSIGN_RE.test(tokens[i]))) i++;
|
|
412
|
+
continue;
|
|
413
|
+
}
|
|
414
|
+
return null;
|
|
415
|
+
}
|
|
416
|
+
return null;
|
|
417
|
+
}
|
|
418
|
+
function collectMatches(command, list, matches, depth) {
|
|
419
|
+
if (depth > MAX_RECURSION_DEPTH || command.length > MAX_COMMAND_LENGTH) return;
|
|
420
|
+
let text = command.toLowerCase();
|
|
421
|
+
text = stripHeredocBodies(text);
|
|
422
|
+
const recurse = (inner) => collectMatches(inner, list, matches, depth + 1);
|
|
423
|
+
text = extractDollarSubstitutions(text, recurse);
|
|
424
|
+
text = extractBacktickSubstitutions(text, recurse);
|
|
425
|
+
text = text.replace(/'[^']*'/g, " ").replace(/"[^"]*"/g, " ");
|
|
426
|
+
text = text.replace(/(^|\s)#[^\n]*/g, " ");
|
|
427
|
+
const segments = text.split(/\|\||&&|[;|&\n]|[({]/);
|
|
428
|
+
for (const segment of segments) {
|
|
429
|
+
const matched = matchSegment(segment, list);
|
|
430
|
+
if (matched) matches.add(matched);
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
function matchHighRiskCommands(command, highRiskCommands = HIGH_RISK_COMMANDS) {
|
|
434
|
+
if (!command) return [];
|
|
435
|
+
const matches = /* @__PURE__ */ new Set();
|
|
436
|
+
collectMatches(command, buildRiskList(highRiskCommands), matches, 0);
|
|
437
|
+
return [...matches];
|
|
438
|
+
}
|
|
439
|
+
function isLocalhostOnlyNetworkCommand(command) {
|
|
440
|
+
const text = command.toLowerCase();
|
|
441
|
+
const tokens = text.split(/\s+/).map((t) => t.replace(/^["'`]+|["'`,;)]+$/g, ""));
|
|
442
|
+
let localCount = 0;
|
|
443
|
+
for (const token of tokens) {
|
|
444
|
+
let host = null;
|
|
445
|
+
if (token.includes("://")) {
|
|
446
|
+
let rest = token.slice(token.indexOf("://") + 3);
|
|
447
|
+
const at = rest.indexOf("@");
|
|
448
|
+
if (at !== -1) rest = rest.slice(at + 1);
|
|
449
|
+
host = rest.split(/[/?#]/)[0];
|
|
450
|
+
} else if (/^[a-z0-9.[\]:-]+:\d+(\/.*)?$/.test(token)) {
|
|
451
|
+
host = token.split("/")[0];
|
|
452
|
+
} else if (/^(localhost|127\.0\.0\.1|\[?::1\]?)(\/.*)?$/.test(token)) {
|
|
453
|
+
host = token.split("/")[0];
|
|
454
|
+
}
|
|
455
|
+
if (host === null) continue;
|
|
456
|
+
const bare = host.replace(/:\d+$/, "").replace(/^\[|\]$/g, "");
|
|
457
|
+
if (LOCAL_HOST_RE.test(bare)) {
|
|
458
|
+
localCount++;
|
|
459
|
+
} else {
|
|
460
|
+
return false;
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
return localCount > 0;
|
|
464
|
+
}
|
|
465
|
+
|
|
306
466
|
// src/local-evaluator/evaluator.ts
|
|
307
467
|
var LocalEvaluator = class {
|
|
308
468
|
constructor(policy) {
|
|
@@ -453,12 +613,10 @@ var LocalEvaluator = class {
|
|
|
453
613
|
return score;
|
|
454
614
|
}
|
|
455
615
|
if (context.purpose === "shell.exec" && context.target) {
|
|
456
|
-
const
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
break;
|
|
461
|
-
}
|
|
616
|
+
const matched = matchHighRiskCommands(context.target);
|
|
617
|
+
const localProbeOnly = matched.length > 0 && matched.every((cmd) => cmd === "curl" || cmd === "wget") && isLocalhostOnlyNetworkCommand(context.target);
|
|
618
|
+
if (matched.length > 0 && !localProbeOnly) {
|
|
619
|
+
score = Math.max(score, 80);
|
|
462
620
|
}
|
|
463
621
|
}
|
|
464
622
|
if ((context.purpose === "file.read" || context.purpose === "file.write" || context.purpose === "file.delete") && context.target) {
|
|
@@ -3769,7 +3927,7 @@ function getTrustLevel(score) {
|
|
|
3769
3927
|
}
|
|
3770
3928
|
|
|
3771
3929
|
// src/version.ts
|
|
3772
|
-
var SDK_VERSION = "3.
|
|
3930
|
+
var SDK_VERSION = "3.11.0";
|
|
3773
3931
|
|
|
3774
3932
|
// src/well-known.ts
|
|
3775
3933
|
var CACHE_TTL_MS = 60 * 60 * 1e3;
|
|
@@ -4284,10 +4442,12 @@ function toGatewayConfig(config) {
|
|
|
4284
4442
|
};
|
|
4285
4443
|
}
|
|
4286
4444
|
function toVerificationRequest(context, astraId) {
|
|
4445
|
+
const dotIndex = context.purpose.indexOf(".");
|
|
4446
|
+
const dotted = dotIndex > 0;
|
|
4287
4447
|
return {
|
|
4288
4448
|
credentials: { astraId },
|
|
4289
|
-
purpose: context.purpose,
|
|
4290
|
-
action: context.action,
|
|
4449
|
+
purpose: dotted ? context.purpose.slice(0, dotIndex) : context.purpose,
|
|
4450
|
+
action: dotted ? context.purpose : context.action,
|
|
4291
4451
|
resourceType: context.resourceType,
|
|
4292
4452
|
resource: context.target,
|
|
4293
4453
|
transactionValue: context.transactionValue,
|
|
@@ -4327,8 +4487,75 @@ async function verifyOnline(config, context, astraId) {
|
|
|
4327
4487
|
// src/gateway/modes/hybrid.ts
|
|
4328
4488
|
var import_fs2 = require("fs");
|
|
4329
4489
|
var import_path = require("path");
|
|
4490
|
+
|
|
4491
|
+
// src/gateway/redact.ts
|
|
4492
|
+
var marker = (type2) => `[REDACTED:${type2}]`;
|
|
4493
|
+
var REDACTION_PATTERNS = [
|
|
4494
|
+
// Multi-line blocks first so later single-line patterns don't shred them.
|
|
4495
|
+
{
|
|
4496
|
+
type: "private-key",
|
|
4497
|
+
re: /-----BEGIN [A-Z ]*PRIVATE KEY-----[\s\S]*?(?:-----END [A-Z ]*PRIVATE KEY-----|$)/g
|
|
4498
|
+
},
|
|
4499
|
+
// URL userinfo credentials (https://user:pass@, x-access-token:ghp_…@).
|
|
4500
|
+
{
|
|
4501
|
+
type: "url-credentials",
|
|
4502
|
+
re: /([a-z][a-z0-9+.-]*:\/\/)[^\s/@]+:[^\s/@]+@/gi,
|
|
4503
|
+
replacement: `$1${marker("url-credentials")}@`
|
|
4504
|
+
},
|
|
4505
|
+
// Known token formats.
|
|
4506
|
+
{ type: "github-token", re: /\bgh[pousr]_[A-Za-z0-9]{20,255}\b/g },
|
|
4507
|
+
{ type: "github-token", re: /\bgithub_pat_[A-Za-z0-9_]{20,255}\b/g },
|
|
4508
|
+
{ type: "astrasync-key", re: /\bkya_[A-Fa-f0-9]{32,128}\b/g },
|
|
4509
|
+
{ type: "openai-key", re: /\bsk-[A-Za-z0-9_-]{20,}\b/g },
|
|
4510
|
+
{ type: "aws-access-key-id", re: /\bAKIA[0-9A-Z]{16}\b/g },
|
|
4511
|
+
{ type: "jwt", re: /\beyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\b/g },
|
|
4512
|
+
// Bearer/token headers.
|
|
4513
|
+
{
|
|
4514
|
+
type: "bearer-token",
|
|
4515
|
+
re: /\b(bearer\s+)[a-z0-9._~+/=-]{16,}/gi,
|
|
4516
|
+
replacement: `$1${marker("bearer-token")}`
|
|
4517
|
+
},
|
|
4518
|
+
// Generic KEY=value / key: value assignments with secret-ish names.
|
|
4519
|
+
{
|
|
4520
|
+
type: "assigned-secret",
|
|
4521
|
+
re: /\b((?:password|passwd|secret|token|api[_-]?key|apikey|access[_-]?key|client[_-]?secret|private[_-]?key)\s*[=:]\s*)(['"]?)[^\s'"&;]{8,}\2/gi,
|
|
4522
|
+
replacement: `$1$2${marker("assigned-secret")}$2`
|
|
4523
|
+
}
|
|
4524
|
+
];
|
|
4525
|
+
function redactSecrets(text) {
|
|
4526
|
+
let result = text;
|
|
4527
|
+
for (const { type: type2, re, replacement } of REDACTION_PATTERNS) {
|
|
4528
|
+
result = result.replace(re, replacement ?? marker(type2));
|
|
4529
|
+
}
|
|
4530
|
+
return result;
|
|
4531
|
+
}
|
|
4532
|
+
function redactDeep(value) {
|
|
4533
|
+
if (typeof value === "string") {
|
|
4534
|
+
return redactSecrets(value);
|
|
4535
|
+
}
|
|
4536
|
+
if (Array.isArray(value)) {
|
|
4537
|
+
return value.map((item) => redactDeep(item));
|
|
4538
|
+
}
|
|
4539
|
+
if (value !== null && typeof value === "object" && !(value instanceof Date)) {
|
|
4540
|
+
const out = {};
|
|
4541
|
+
for (const [k, v] of Object.entries(value)) {
|
|
4542
|
+
out[k] = redactDeep(v);
|
|
4543
|
+
}
|
|
4544
|
+
return out;
|
|
4545
|
+
}
|
|
4546
|
+
return value;
|
|
4547
|
+
}
|
|
4548
|
+
|
|
4549
|
+
// src/gateway/modes/hybrid.ts
|
|
4330
4550
|
var MAX_QUEUE_SIZE = 1e3;
|
|
4331
4551
|
var MAX_RETRIES = 3;
|
|
4552
|
+
var FLUSH_TIMEOUT = /* @__PURE__ */ Symbol("flush-timeout");
|
|
4553
|
+
function delay(ms) {
|
|
4554
|
+
return new Promise((resolve) => {
|
|
4555
|
+
const timer = setTimeout(() => resolve(FLUSH_TIMEOUT), ms);
|
|
4556
|
+
if (typeof timer.unref === "function") timer.unref();
|
|
4557
|
+
});
|
|
4558
|
+
}
|
|
4332
4559
|
var HybridSyncQueue = class {
|
|
4333
4560
|
constructor(config, persistPath) {
|
|
4334
4561
|
this.queue = [];
|
|
@@ -4349,12 +4576,12 @@ var HybridSyncQueue = class {
|
|
|
4349
4576
|
/**
|
|
4350
4577
|
* Stop periodic sync and flush remaining entries.
|
|
4351
4578
|
*/
|
|
4352
|
-
async stop() {
|
|
4579
|
+
async stop(flushOptions = {}) {
|
|
4353
4580
|
if (this.timer) {
|
|
4354
4581
|
clearInterval(this.timer);
|
|
4355
4582
|
this.timer = null;
|
|
4356
4583
|
}
|
|
4357
|
-
await this.flush();
|
|
4584
|
+
await this.flush(flushOptions);
|
|
4358
4585
|
this.saveToDisk();
|
|
4359
4586
|
}
|
|
4360
4587
|
/**
|
|
@@ -4366,8 +4593,8 @@ var HybridSyncQueue = class {
|
|
|
4366
4593
|
}
|
|
4367
4594
|
this.queue.push({
|
|
4368
4595
|
id: `${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
|
|
4369
|
-
context,
|
|
4370
|
-
decision,
|
|
4596
|
+
context: redactDeep(context),
|
|
4597
|
+
decision: redactDeep(decision),
|
|
4371
4598
|
timestamp: /* @__PURE__ */ new Date(),
|
|
4372
4599
|
retryCount: 0,
|
|
4373
4600
|
status: "pending"
|
|
@@ -4377,16 +4604,21 @@ var HybridSyncQueue = class {
|
|
|
4377
4604
|
/**
|
|
4378
4605
|
* Flush pending entries to the API.
|
|
4379
4606
|
*/
|
|
4380
|
-
async flush() {
|
|
4607
|
+
async flush(options = {}) {
|
|
4381
4608
|
if (this.processing) return;
|
|
4382
4609
|
this.processing = true;
|
|
4383
4610
|
try {
|
|
4384
4611
|
const pending = this.queue.filter((e) => e.status === "pending");
|
|
4385
|
-
|
|
4386
|
-
|
|
4387
|
-
|
|
4612
|
+
const batch = typeof options.limit === "number" ? pending.slice(0, options.limit) : pending;
|
|
4613
|
+
for (const entry of batch) {
|
|
4614
|
+
const attempt = verifyOnline(this.config, entry.context, this.config.agentId).then(() => "synced").catch(() => "error");
|
|
4615
|
+
const result = options.perEntryTimeoutMs ? await Promise.race([attempt, delay(options.perEntryTimeoutMs)]) : await attempt;
|
|
4616
|
+
if (result === FLUSH_TIMEOUT) {
|
|
4617
|
+
break;
|
|
4618
|
+
}
|
|
4619
|
+
if (result === "synced") {
|
|
4388
4620
|
entry.status = "synced";
|
|
4389
|
-
}
|
|
4621
|
+
} else {
|
|
4390
4622
|
entry.retryCount++;
|
|
4391
4623
|
if (entry.retryCount >= MAX_RETRIES) {
|
|
4392
4624
|
entry.status = "failed";
|
|
@@ -4463,8 +4695,22 @@ var TraceLogger = class {
|
|
|
4463
4695
|
id: this.generateId(),
|
|
4464
4696
|
timestamp: /* @__PURE__ */ new Date(),
|
|
4465
4697
|
type: "evaluation",
|
|
4466
|
-
context,
|
|
4467
|
-
decision
|
|
4698
|
+
context: redactDeep(context),
|
|
4699
|
+
decision: redactDeep(decision)
|
|
4700
|
+
});
|
|
4701
|
+
}
|
|
4702
|
+
/**
|
|
4703
|
+
* Log a tool call the guard saw but did not govern. One line per skip
|
|
4704
|
+
* keeps coverage holes (unmapped platform tools) visible in the traces
|
|
4705
|
+
* instead of silently indistinguishable from ALLOW.
|
|
4706
|
+
*/
|
|
4707
|
+
logSkipped(toolName, reason) {
|
|
4708
|
+
if (!this.enabled) return;
|
|
4709
|
+
this.write({
|
|
4710
|
+
id: this.generateId(),
|
|
4711
|
+
timestamp: /* @__PURE__ */ new Date(),
|
|
4712
|
+
type: "skipped",
|
|
4713
|
+
metadata: { toolName, reason }
|
|
4468
4714
|
});
|
|
4469
4715
|
}
|
|
4470
4716
|
/**
|
|
@@ -4581,10 +4827,12 @@ var AstraSyncGateway = class {
|
|
|
4581
4827
|
}
|
|
4582
4828
|
/**
|
|
4583
4829
|
* Graceful shutdown. Flushes sync queue and cleans up resources.
|
|
4830
|
+
* Stateless callers (hooks) pass bounded flush options so sync never
|
|
4831
|
+
* sits on a tool call's critical path.
|
|
4584
4832
|
*/
|
|
4585
|
-
async shutdown() {
|
|
4833
|
+
async shutdown(options) {
|
|
4586
4834
|
if (this.syncQueue) {
|
|
4587
|
-
await this.syncQueue.stop();
|
|
4835
|
+
await this.syncQueue.stop(options?.syncFlush ?? {});
|
|
4588
4836
|
this.syncQueue = null;
|
|
4589
4837
|
}
|
|
4590
4838
|
this.evaluator = null;
|
|
@@ -4607,7 +4855,7 @@ var AstraSyncGateway = class {
|
|
|
4607
4855
|
let decision;
|
|
4608
4856
|
switch (this.config.mode) {
|
|
4609
4857
|
case "online":
|
|
4610
|
-
decision = await verifyOnline(this.config, context, astraId);
|
|
4858
|
+
decision = await verifyOnline(this.config, context, astraId ?? this.config.agentId);
|
|
4611
4859
|
break;
|
|
4612
4860
|
case "local":
|
|
4613
4861
|
if (!this.evaluator) throw new Error("Local evaluator not initialized");
|
|
@@ -4662,6 +4910,13 @@ var AstraSyncGateway = class {
|
|
|
4662
4910
|
getSyncStatus() {
|
|
4663
4911
|
return this.syncQueue?.getStatus() || null;
|
|
4664
4912
|
}
|
|
4913
|
+
/**
|
|
4914
|
+
* Record a tool call the calling adapter saw but did not govern
|
|
4915
|
+
* (unmapped tool, skipTools, MCP with governMcp off). Trace-only.
|
|
4916
|
+
*/
|
|
4917
|
+
logSkippedTool(toolName, reason) {
|
|
4918
|
+
this.traceLogger?.logSkipped(toolName, reason);
|
|
4919
|
+
}
|
|
4665
4920
|
};
|
|
4666
4921
|
|
|
4667
4922
|
// src/browser/background.ts
|