@astrasyncai/verification-gateway 3.10.0 → 3.10.1

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.
Files changed (66) hide show
  1. package/dist/adapter-interface/interface.d.mts +1 -1
  2. package/dist/adapter-interface/interface.d.ts +1 -1
  3. package/dist/adapters/express.js +1 -1
  4. package/dist/adapters/express.js.map +1 -1
  5. package/dist/adapters/express.mjs +1 -1
  6. package/dist/adapters/express.mjs.map +1 -1
  7. package/dist/adapters/mcp.js +1 -1
  8. package/dist/adapters/mcp.js.map +1 -1
  9. package/dist/adapters/mcp.mjs +1 -1
  10. package/dist/adapters/mcp.mjs.map +1 -1
  11. package/dist/adapters/nextjs.js +1 -1
  12. package/dist/adapters/nextjs.js.map +1 -1
  13. package/dist/adapters/nextjs.mjs +1 -1
  14. package/dist/adapters/nextjs.mjs.map +1 -1
  15. package/dist/adapters/sdk.js +1 -1
  16. package/dist/adapters/sdk.js.map +1 -1
  17. package/dist/adapters/sdk.mjs +1 -1
  18. package/dist/adapters/sdk.mjs.map +1 -1
  19. package/dist/bin/astrasync-claude-hook.js +273 -25
  20. package/dist/bin/astrasync-guard.js +255 -23
  21. package/dist/bin/astrasync.js +270 -24
  22. package/dist/browser/background.js +254 -22
  23. package/dist/browser/background.js.map +1 -1
  24. package/dist/browser/background.mjs +254 -22
  25. package/dist/browser/background.mjs.map +1 -1
  26. package/dist/browser/browser-adapter.d.mts +1 -1
  27. package/dist/browser/browser-adapter.d.ts +1 -1
  28. package/dist/claude-code/claude-code-adapter.d.mts +1 -1
  29. package/dist/claude-code/claude-code-adapter.d.ts +1 -1
  30. package/dist/cli/index.d.mts +1 -1
  31. package/dist/cli/index.d.ts +1 -1
  32. package/dist/cursor/cursor-adapter.d.mts +1 -1
  33. package/dist/cursor/cursor-adapter.d.ts +1 -1
  34. package/dist/cursor/extension.d.mts +1 -1
  35. package/dist/cursor/extension.d.ts +1 -1
  36. package/dist/cursor/extension.js +254 -22
  37. package/dist/cursor/extension.js.map +1 -1
  38. package/dist/cursor/extension.mjs +254 -22
  39. package/dist/cursor/extension.mjs.map +1 -1
  40. package/dist/gateway/gateway.d.mts +27 -2
  41. package/dist/gateway/gateway.d.ts +27 -2
  42. package/dist/gateway/gateway.js +254 -22
  43. package/dist/gateway/gateway.js.map +1 -1
  44. package/dist/gateway/gateway.mjs +254 -22
  45. package/dist/gateway/gateway.mjs.map +1 -1
  46. package/dist/git-trigger/git-hooks.d.mts +1 -1
  47. package/dist/git-trigger/git-hooks.d.ts +1 -1
  48. package/dist/index.d.mts +1 -1
  49. package/dist/index.d.ts +1 -1
  50. package/dist/index.js +1 -1
  51. package/dist/index.js.map +1 -1
  52. package/dist/index.mjs +1 -1
  53. package/dist/index.mjs.map +1 -1
  54. package/dist/local-evaluator/evaluator.d.mts +1 -1
  55. package/dist/local-evaluator/evaluator.d.ts +1 -1
  56. package/dist/local-evaluator/evaluator.js +165 -7
  57. package/dist/local-evaluator/evaluator.js.map +1 -1
  58. package/dist/local-evaluator/evaluator.mjs +165 -7
  59. package/dist/local-evaluator/evaluator.mjs.map +1 -1
  60. package/dist/{types-D0lCtFQ7.d.mts → types-BV6abBnF.d.mts} +6 -0
  61. package/dist/{types-YbiXYKx1.d.ts → types-C23_uaY8.d.ts} +6 -0
  62. package/dist/verify.js +1 -1
  63. package/dist/verify.js.map +1 -1
  64. package/dist/verify.mjs +1 -1
  65. package/dist/verify.mjs.map +1 -1
  66. package/package.json +1 -1
@@ -1,5 +1,5 @@
1
1
  import { PlatformAdapter, AdapterConfig } from '../adapter-interface/interface.mjs';
2
- import { P as PDLSSContext, V as VerificationDecision, A as AgentAction, I as InterceptResult } from '../types-D0lCtFQ7.mjs';
2
+ import { P as PDLSSContext, V as VerificationDecision, A as AgentAction, I as InterceptResult } from '../types-BV6abBnF.mjs';
3
3
  import '../gateway/gateway.mjs';
4
4
  import '../types-sy3tq8lp.mjs';
5
5
  import '../metadata-capture.mjs';
@@ -1,5 +1,5 @@
1
1
  import { PlatformAdapter, AdapterConfig } from '../adapter-interface/interface.js';
2
- import { P as PDLSSContext, V as VerificationDecision, A as AgentAction, I as InterceptResult } from '../types-YbiXYKx1.js';
2
+ import { P as PDLSSContext, V as VerificationDecision, A as AgentAction, I as InterceptResult } from '../types-C23_uaY8.js';
3
3
  import '../gateway/gateway.js';
4
4
  import '../types-9tns4wyl.js';
5
5
  import '../metadata-capture.js';
@@ -1,5 +1,5 @@
1
1
  import { PlatformAdapter, AdapterConfig } from '../adapter-interface/interface.mjs';
2
- import { A as AgentAction, I as InterceptResult, P as PDLSSContext, V as VerificationDecision } from '../types-D0lCtFQ7.mjs';
2
+ import { A as AgentAction, I as InterceptResult, P as PDLSSContext, V as VerificationDecision } from '../types-BV6abBnF.mjs';
3
3
  import '../gateway/gateway.mjs';
4
4
  import '../types-sy3tq8lp.mjs';
5
5
  import '../metadata-capture.mjs';
@@ -1,5 +1,5 @@
1
1
  import { PlatformAdapter, AdapterConfig } from '../adapter-interface/interface.js';
2
- import { A as AgentAction, I as InterceptResult, P as PDLSSContext, V as VerificationDecision } from '../types-YbiXYKx1.js';
2
+ import { A as AgentAction, I as InterceptResult, P as PDLSSContext, V as VerificationDecision } from '../types-C23_uaY8.js';
3
3
  import '../gateway/gateway.js';
4
4
  import '../types-9tns4wyl.js';
5
5
  import '../metadata-capture.js';
@@ -1,4 +1,4 @@
1
- import { b as LocalPurposeRule, d as LocalScope, c as LocalRiskThresholds, L as LocalPolicy, P as PDLSSContext, V as VerificationDecision, A as AgentAction, I as InterceptResult } from '../types-D0lCtFQ7.mjs';
1
+ import { b as LocalPurposeRule, d as LocalScope, c as LocalRiskThresholds, L as LocalPolicy, P as PDLSSContext, V as VerificationDecision, A as AgentAction, I as InterceptResult } from '../types-BV6abBnF.mjs';
2
2
  import { PlatformAdapter, AdapterConfig } from '../adapter-interface/interface.mjs';
3
3
  import '../types-sy3tq8lp.mjs';
4
4
  import '../metadata-capture.mjs';
@@ -1,4 +1,4 @@
1
- import { b as LocalPurposeRule, d as LocalScope, c as LocalRiskThresholds, L as LocalPolicy, P as PDLSSContext, V as VerificationDecision, A as AgentAction, I as InterceptResult } from '../types-YbiXYKx1.js';
1
+ import { b as LocalPurposeRule, d as LocalScope, c as LocalRiskThresholds, L as LocalPolicy, P as PDLSSContext, V as VerificationDecision, A as AgentAction, I as InterceptResult } from '../types-C23_uaY8.js';
2
2
  import { PlatformAdapter, AdapterConfig } from '../adapter-interface/interface.js';
3
3
  import '../types-9tns4wyl.js';
4
4
  import '../metadata-capture.js';
@@ -1,5 +1,5 @@
1
1
  import { PlatformAdapter, AdapterConfig } from '../adapter-interface/interface.mjs';
2
- import { P as PDLSSContext, V as VerificationDecision, A as AgentAction, I as InterceptResult } from '../types-D0lCtFQ7.mjs';
2
+ import { P as PDLSSContext, V as VerificationDecision, A as AgentAction, I as InterceptResult } from '../types-BV6abBnF.mjs';
3
3
  import '../gateway/gateway.mjs';
4
4
  import '../types-sy3tq8lp.mjs';
5
5
  import '../metadata-capture.mjs';
@@ -1,5 +1,5 @@
1
1
  import { PlatformAdapter, AdapterConfig } from '../adapter-interface/interface.js';
2
- import { P as PDLSSContext, V as VerificationDecision, A as AgentAction, I as InterceptResult } from '../types-YbiXYKx1.js';
2
+ import { P as PDLSSContext, V as VerificationDecision, A as AgentAction, I as InterceptResult } from '../types-C23_uaY8.js';
3
3
  import '../gateway/gateway.js';
4
4
  import '../types-9tns4wyl.js';
5
5
  import '../metadata-capture.js';
@@ -1,7 +1,7 @@
1
1
  import { VSCodeAPI } from './cursor-adapter.mjs';
2
2
  import '../adapter-interface/interface.mjs';
3
3
  import '../gateway/gateway.mjs';
4
- import '../types-D0lCtFQ7.mjs';
4
+ import '../types-BV6abBnF.mjs';
5
5
  import '../types-sy3tq8lp.mjs';
6
6
  import '../metadata-capture.mjs';
7
7
 
@@ -1,7 +1,7 @@
1
1
  import { VSCodeAPI } from './cursor-adapter.js';
2
2
  import '../adapter-interface/interface.js';
3
3
  import '../gateway/gateway.js';
4
- import '../types-YbiXYKx1.js';
4
+ import '../types-C23_uaY8.js';
5
5
  import '../types-9tns4wyl.js';
6
6
  import '../metadata-capture.js';
7
7
 
@@ -288,7 +288,9 @@ var HIGH_RISK_COMMANDS = [
288
288
  "git push",
289
289
  "npm publish",
290
290
  "docker",
291
- "kubectl"
291
+ "kubectl",
292
+ "gh pr create",
293
+ "gh pr merge"
292
294
  ];
293
295
  var SENSITIVE_PATHS = [
294
296
  ".ssh",
@@ -307,6 +309,164 @@ var SENSITIVE_PATHS = [
307
309
  ".pypirc"
308
310
  ];
309
311
 
312
+ // src/local-evaluator/command-matcher.ts
313
+ var WRAPPERS = /* @__PURE__ */ new Set([
314
+ "sudo",
315
+ "doas",
316
+ "env",
317
+ "nohup",
318
+ "time",
319
+ "timeout",
320
+ "nice",
321
+ "ionice",
322
+ "stdbuf",
323
+ "xargs",
324
+ "command",
325
+ "exec",
326
+ "builtin"
327
+ ]);
328
+ var ASSIGN_RE = /^[a-z_][a-z0-9_]*=/;
329
+ var MAX_WRAPPER_HOPS = 4;
330
+ var MAX_RECURSION_DEPTH = 3;
331
+ var MAX_COMMAND_LENGTH = 1e5;
332
+ var LOCAL_HOST_RE = /^(localhost|127\.0\.0\.1|::1|[a-z0-9.-]*\.localhost)$/;
333
+ function buildRiskList(entries) {
334
+ const singleWord = /* @__PURE__ */ new Set();
335
+ const multiWord = [];
336
+ for (const entry of entries) {
337
+ const words = entry.toLowerCase().trim().split(/\s+/);
338
+ if (words.length === 1) singleWord.add(words[0]);
339
+ else multiWord.push(words);
340
+ }
341
+ multiWord.sort((a, b) => b.length - a.length);
342
+ return { singleWord, multiWord };
343
+ }
344
+ function stripHeredocBodies(text) {
345
+ const lines = text.split("\n");
346
+ const kept = [];
347
+ let terminator = null;
348
+ for (const line of lines) {
349
+ if (terminator !== null) {
350
+ if (line.trim() === terminator) terminator = null;
351
+ continue;
352
+ }
353
+ kept.push(line);
354
+ const heredoc = line.match(/<<-?\s*['"]?(\w+)['"]?/);
355
+ if (heredoc) terminator = heredoc[1];
356
+ }
357
+ return kept.join("\n");
358
+ }
359
+ function extractDollarSubstitutions(text, collect) {
360
+ let result = text;
361
+ let start = result.indexOf("$(");
362
+ let iterations = 0;
363
+ while (start !== -1 && iterations < 50) {
364
+ iterations++;
365
+ let depth = 0;
366
+ let end = result.length;
367
+ for (let i = start + 1; i < result.length; i++) {
368
+ if (result[i] === "(") depth++;
369
+ else if (result[i] === ")") {
370
+ depth--;
371
+ if (depth === 0) {
372
+ end = i;
373
+ break;
374
+ }
375
+ }
376
+ }
377
+ collect(result.slice(start + 2, end));
378
+ result = `${result.slice(0, start)} ${result.slice(Math.min(end + 1, result.length))}`;
379
+ start = result.indexOf("$(");
380
+ }
381
+ return result;
382
+ }
383
+ function extractBacktickSubstitutions(text, collect) {
384
+ if (!text.includes("`")) return text;
385
+ const chunks = text.split("`");
386
+ const kept = [];
387
+ for (let i = 0; i < chunks.length; i++) {
388
+ if (i % 2 === 1) collect(chunks[i]);
389
+ else kept.push(chunks[i]);
390
+ }
391
+ return kept.join(" ");
392
+ }
393
+ function basename(token) {
394
+ const slash = token.lastIndexOf("/");
395
+ return slash === -1 ? token : token.slice(slash + 1);
396
+ }
397
+ function matchSegment(segment, list) {
398
+ const tokens = segment.split(/\s+/).filter((t) => /[a-z0-9]/.test(t));
399
+ let i = 0;
400
+ let hops = 0;
401
+ while (i < tokens.length) {
402
+ while (i < tokens.length && (tokens[i] === "export" || ASSIGN_RE.test(tokens[i]))) i++;
403
+ if (i >= tokens.length) return null;
404
+ const cmd = basename(tokens[i]);
405
+ const significant = [cmd, ...tokens.slice(i + 1).filter((t) => !t.startsWith("-"))];
406
+ for (const entry of list.multiWord) {
407
+ if (entry.length <= significant.length && entry.every((w, j) => significant[j] === w)) {
408
+ return entry.join(" ");
409
+ }
410
+ }
411
+ if (list.singleWord.has(cmd)) return cmd;
412
+ if (WRAPPERS.has(cmd) && hops < MAX_WRAPPER_HOPS) {
413
+ hops++;
414
+ i++;
415
+ while (i < tokens.length && (tokens[i].startsWith("-") || ASSIGN_RE.test(tokens[i]))) i++;
416
+ continue;
417
+ }
418
+ return null;
419
+ }
420
+ return null;
421
+ }
422
+ function collectMatches(command, list, matches, depth) {
423
+ if (depth > MAX_RECURSION_DEPTH || command.length > MAX_COMMAND_LENGTH) return;
424
+ let text = command.toLowerCase();
425
+ text = stripHeredocBodies(text);
426
+ const recurse = (inner) => collectMatches(inner, list, matches, depth + 1);
427
+ text = extractDollarSubstitutions(text, recurse);
428
+ text = extractBacktickSubstitutions(text, recurse);
429
+ text = text.replace(/'[^']*'/g, " ").replace(/"[^"]*"/g, " ");
430
+ text = text.replace(/(^|\s)#[^\n]*/g, " ");
431
+ const segments = text.split(/\|\||&&|[;|&\n]|[({]/);
432
+ for (const segment of segments) {
433
+ const matched = matchSegment(segment, list);
434
+ if (matched) matches.add(matched);
435
+ }
436
+ }
437
+ function matchHighRiskCommands(command, highRiskCommands = HIGH_RISK_COMMANDS) {
438
+ if (!command) return [];
439
+ const matches = /* @__PURE__ */ new Set();
440
+ collectMatches(command, buildRiskList(highRiskCommands), matches, 0);
441
+ return [...matches];
442
+ }
443
+ function isLocalhostOnlyNetworkCommand(command) {
444
+ const text = command.toLowerCase();
445
+ const tokens = text.split(/\s+/).map((t) => t.replace(/^["'`]+|["'`,;)]+$/g, ""));
446
+ let localCount = 0;
447
+ for (const token of tokens) {
448
+ let host = null;
449
+ if (token.includes("://")) {
450
+ let rest = token.slice(token.indexOf("://") + 3);
451
+ const at = rest.indexOf("@");
452
+ if (at !== -1) rest = rest.slice(at + 1);
453
+ host = rest.split(/[/?#]/)[0];
454
+ } else if (/^[a-z0-9.[\]:-]+:\d+(\/.*)?$/.test(token)) {
455
+ host = token.split("/")[0];
456
+ } else if (/^(localhost|127\.0\.0\.1|\[?::1\]?)(\/.*)?$/.test(token)) {
457
+ host = token.split("/")[0];
458
+ }
459
+ if (host === null) continue;
460
+ const bare = host.replace(/:\d+$/, "").replace(/^\[|\]$/g, "");
461
+ if (LOCAL_HOST_RE.test(bare)) {
462
+ localCount++;
463
+ } else {
464
+ return false;
465
+ }
466
+ }
467
+ return localCount > 0;
468
+ }
469
+
310
470
  // src/local-evaluator/evaluator.ts
311
471
  var LocalEvaluator = class {
312
472
  constructor(policy) {
@@ -457,12 +617,10 @@ var LocalEvaluator = class {
457
617
  return score;
458
618
  }
459
619
  if (context.purpose === "shell.exec" && context.target) {
460
- const targetLower = context.target.toLowerCase();
461
- for (const cmd of HIGH_RISK_COMMANDS) {
462
- if (targetLower.startsWith(cmd) || targetLower.includes(` ${cmd} `) || targetLower.includes(` ${cmd}`)) {
463
- score = Math.max(score, 80);
464
- break;
465
- }
620
+ const matched = matchHighRiskCommands(context.target);
621
+ const localProbeOnly = matched.length > 0 && matched.every((cmd) => cmd === "curl" || cmd === "wget") && isLocalhostOnlyNetworkCommand(context.target);
622
+ if (matched.length > 0 && !localProbeOnly) {
623
+ score = Math.max(score, 80);
466
624
  }
467
625
  }
468
626
  if ((context.purpose === "file.read" || context.purpose === "file.write" || context.purpose === "file.delete") && context.target) {
@@ -3773,7 +3931,7 @@ function getTrustLevel(score) {
3773
3931
  }
3774
3932
 
3775
3933
  // src/version.ts
3776
- var SDK_VERSION = "3.10.0";
3934
+ var SDK_VERSION = "3.10.1";
3777
3935
 
3778
3936
  // src/well-known.ts
3779
3937
  var CACHE_TTL_MS = 60 * 60 * 1e3;
@@ -4331,8 +4489,75 @@ async function verifyOnline(config, context, astraId) {
4331
4489
  // src/gateway/modes/hybrid.ts
4332
4490
  var import_fs2 = require("fs");
4333
4491
  var import_path = require("path");
4492
+
4493
+ // src/gateway/redact.ts
4494
+ var marker = (type2) => `[REDACTED:${type2}]`;
4495
+ var REDACTION_PATTERNS = [
4496
+ // Multi-line blocks first so later single-line patterns don't shred them.
4497
+ {
4498
+ type: "private-key",
4499
+ re: /-----BEGIN [A-Z ]*PRIVATE KEY-----[\s\S]*?(?:-----END [A-Z ]*PRIVATE KEY-----|$)/g
4500
+ },
4501
+ // URL userinfo credentials (https://user:pass@, x-access-token:ghp_…@).
4502
+ {
4503
+ type: "url-credentials",
4504
+ re: /([a-z][a-z0-9+.-]*:\/\/)[^\s/@]+:[^\s/@]+@/gi,
4505
+ replacement: `$1${marker("url-credentials")}@`
4506
+ },
4507
+ // Known token formats.
4508
+ { type: "github-token", re: /\bgh[pousr]_[A-Za-z0-9]{20,255}\b/g },
4509
+ { type: "github-token", re: /\bgithub_pat_[A-Za-z0-9_]{20,255}\b/g },
4510
+ { type: "astrasync-key", re: /\bkya_[A-Fa-f0-9]{32,128}\b/g },
4511
+ { type: "openai-key", re: /\bsk-[A-Za-z0-9_-]{20,}\b/g },
4512
+ { type: "aws-access-key-id", re: /\bAKIA[0-9A-Z]{16}\b/g },
4513
+ { type: "jwt", re: /\beyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\b/g },
4514
+ // Bearer/token headers.
4515
+ {
4516
+ type: "bearer-token",
4517
+ re: /\b(bearer\s+)[a-z0-9._~+/=-]{16,}/gi,
4518
+ replacement: `$1${marker("bearer-token")}`
4519
+ },
4520
+ // Generic KEY=value / key: value assignments with secret-ish names.
4521
+ {
4522
+ type: "assigned-secret",
4523
+ re: /\b((?:password|passwd|secret|token|api[_-]?key|apikey|access[_-]?key|client[_-]?secret|private[_-]?key)\s*[=:]\s*)(['"]?)[^\s'"&;]{8,}\2/gi,
4524
+ replacement: `$1$2${marker("assigned-secret")}$2`
4525
+ }
4526
+ ];
4527
+ function redactSecrets(text) {
4528
+ let result = text;
4529
+ for (const { type: type2, re, replacement } of REDACTION_PATTERNS) {
4530
+ result = result.replace(re, replacement ?? marker(type2));
4531
+ }
4532
+ return result;
4533
+ }
4534
+ function redactDeep(value) {
4535
+ if (typeof value === "string") {
4536
+ return redactSecrets(value);
4537
+ }
4538
+ if (Array.isArray(value)) {
4539
+ return value.map((item) => redactDeep(item));
4540
+ }
4541
+ if (value !== null && typeof value === "object" && !(value instanceof Date)) {
4542
+ const out = {};
4543
+ for (const [k, v] of Object.entries(value)) {
4544
+ out[k] = redactDeep(v);
4545
+ }
4546
+ return out;
4547
+ }
4548
+ return value;
4549
+ }
4550
+
4551
+ // src/gateway/modes/hybrid.ts
4334
4552
  var MAX_QUEUE_SIZE = 1e3;
4335
4553
  var MAX_RETRIES = 3;
4554
+ var FLUSH_TIMEOUT = /* @__PURE__ */ Symbol("flush-timeout");
4555
+ function delay(ms) {
4556
+ return new Promise((resolve) => {
4557
+ const timer = setTimeout(() => resolve(FLUSH_TIMEOUT), ms);
4558
+ if (typeof timer.unref === "function") timer.unref();
4559
+ });
4560
+ }
4336
4561
  var HybridSyncQueue = class {
4337
4562
  constructor(config, persistPath) {
4338
4563
  this.queue = [];
@@ -4353,12 +4578,12 @@ var HybridSyncQueue = class {
4353
4578
  /**
4354
4579
  * Stop periodic sync and flush remaining entries.
4355
4580
  */
4356
- async stop() {
4581
+ async stop(flushOptions = {}) {
4357
4582
  if (this.timer) {
4358
4583
  clearInterval(this.timer);
4359
4584
  this.timer = null;
4360
4585
  }
4361
- await this.flush();
4586
+ await this.flush(flushOptions);
4362
4587
  this.saveToDisk();
4363
4588
  }
4364
4589
  /**
@@ -4370,8 +4595,8 @@ var HybridSyncQueue = class {
4370
4595
  }
4371
4596
  this.queue.push({
4372
4597
  id: `${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
4373
- context,
4374
- decision,
4598
+ context: redactDeep(context),
4599
+ decision: redactDeep(decision),
4375
4600
  timestamp: /* @__PURE__ */ new Date(),
4376
4601
  retryCount: 0,
4377
4602
  status: "pending"
@@ -4381,16 +4606,21 @@ var HybridSyncQueue = class {
4381
4606
  /**
4382
4607
  * Flush pending entries to the API.
4383
4608
  */
4384
- async flush() {
4609
+ async flush(options = {}) {
4385
4610
  if (this.processing) return;
4386
4611
  this.processing = true;
4387
4612
  try {
4388
4613
  const pending = this.queue.filter((e) => e.status === "pending");
4389
- for (const entry of pending) {
4390
- try {
4391
- await verifyOnline(this.config, entry.context);
4614
+ const batch = typeof options.limit === "number" ? pending.slice(0, options.limit) : pending;
4615
+ for (const entry of batch) {
4616
+ const attempt = verifyOnline(this.config, entry.context, this.config.agentId).then(() => "synced").catch(() => "error");
4617
+ const result = options.perEntryTimeoutMs ? await Promise.race([attempt, delay(options.perEntryTimeoutMs)]) : await attempt;
4618
+ if (result === FLUSH_TIMEOUT) {
4619
+ break;
4620
+ }
4621
+ if (result === "synced") {
4392
4622
  entry.status = "synced";
4393
- } catch {
4623
+ } else {
4394
4624
  entry.retryCount++;
4395
4625
  if (entry.retryCount >= MAX_RETRIES) {
4396
4626
  entry.status = "failed";
@@ -4467,8 +4697,8 @@ var TraceLogger = class {
4467
4697
  id: this.generateId(),
4468
4698
  timestamp: /* @__PURE__ */ new Date(),
4469
4699
  type: "evaluation",
4470
- context,
4471
- decision
4700
+ context: redactDeep(context),
4701
+ decision: redactDeep(decision)
4472
4702
  });
4473
4703
  }
4474
4704
  /**
@@ -4585,10 +4815,12 @@ var AstraSyncGateway = class {
4585
4815
  }
4586
4816
  /**
4587
4817
  * Graceful shutdown. Flushes sync queue and cleans up resources.
4818
+ * Stateless callers (hooks) pass bounded flush options so sync never
4819
+ * sits on a tool call's critical path.
4588
4820
  */
4589
- async shutdown() {
4821
+ async shutdown(options) {
4590
4822
  if (this.syncQueue) {
4591
- await this.syncQueue.stop();
4823
+ await this.syncQueue.stop(options?.syncFlush ?? {});
4592
4824
  this.syncQueue = null;
4593
4825
  }
4594
4826
  this.evaluator = null;
@@ -4611,7 +4843,7 @@ var AstraSyncGateway = class {
4611
4843
  let decision;
4612
4844
  switch (this.config.mode) {
4613
4845
  case "online":
4614
- decision = await verifyOnline(this.config, context, astraId);
4846
+ decision = await verifyOnline(this.config, context, astraId ?? this.config.agentId);
4615
4847
  break;
4616
4848
  case "local":
4617
4849
  if (!this.evaluator) throw new Error("Local evaluator not initialized");