@astrasyncai/verification-gateway 3.10.1 → 3.11.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 (77) 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 +105 -27
  20. package/dist/bin/astrasync-codex-hook.js +5151 -0
  21. package/dist/bin/astrasync-guard.js +234 -32
  22. package/dist/bin/astrasync.js +242 -32
  23. package/dist/browser/background.js +84 -17
  24. package/dist/browser/background.js.map +1 -1
  25. package/dist/browser/background.mjs +84 -17
  26. package/dist/browser/background.mjs.map +1 -1
  27. package/dist/browser/browser-adapter.d.mts +1 -1
  28. package/dist/browser/browser-adapter.d.ts +1 -1
  29. package/dist/claude-code/claude-code-adapter.d.mts +1 -1
  30. package/dist/claude-code/claude-code-adapter.d.ts +1 -1
  31. package/dist/claude-code/claude-code-adapter.js +9 -1
  32. package/dist/claude-code/claude-code-adapter.js.map +1 -1
  33. package/dist/claude-code/claude-code-adapter.mjs +9 -1
  34. package/dist/claude-code/claude-code-adapter.mjs.map +1 -1
  35. package/dist/cli/index.d.mts +1 -1
  36. package/dist/cli/index.d.ts +1 -1
  37. package/dist/codex/index.d.mts +230 -0
  38. package/dist/codex/index.d.ts +230 -0
  39. package/dist/codex/index.js +5269 -0
  40. package/dist/codex/index.js.map +1 -0
  41. package/dist/codex/index.mjs +5241 -0
  42. package/dist/codex/index.mjs.map +1 -0
  43. package/dist/cursor/cursor-adapter.d.mts +1 -1
  44. package/dist/cursor/cursor-adapter.d.ts +1 -1
  45. package/dist/cursor/extension.d.mts +1 -1
  46. package/dist/cursor/extension.d.ts +1 -1
  47. package/dist/cursor/extension.js +84 -17
  48. package/dist/cursor/extension.js.map +1 -1
  49. package/dist/cursor/extension.mjs +84 -17
  50. package/dist/cursor/extension.mjs.map +1 -1
  51. package/dist/gateway/gateway.d.mts +6 -1
  52. package/dist/gateway/gateway.d.ts +6 -1
  53. package/dist/gateway/gateway.js +84 -17
  54. package/dist/gateway/gateway.js.map +1 -1
  55. package/dist/gateway/gateway.mjs +84 -17
  56. package/dist/gateway/gateway.mjs.map +1 -1
  57. package/dist/git-trigger/git-hooks.d.mts +1 -1
  58. package/dist/git-trigger/git-hooks.d.ts +1 -1
  59. package/dist/index.d.mts +1 -1
  60. package/dist/index.d.ts +1 -1
  61. package/dist/index.js +1 -1
  62. package/dist/index.js.map +1 -1
  63. package/dist/index.mjs +1 -1
  64. package/dist/index.mjs.map +1 -1
  65. package/dist/local-evaluator/evaluator.d.mts +10 -1
  66. package/dist/local-evaluator/evaluator.d.ts +10 -1
  67. package/dist/local-evaluator/evaluator.js +20 -9
  68. package/dist/local-evaluator/evaluator.js.map +1 -1
  69. package/dist/local-evaluator/evaluator.mjs +20 -9
  70. package/dist/local-evaluator/evaluator.mjs.map +1 -1
  71. package/dist/{types-C23_uaY8.d.ts → types-DhFPiZ3t.d.ts} +6 -1
  72. package/dist/{types-BV6abBnF.d.mts → types-cQVCMeNV.d.mts} +6 -1
  73. package/dist/verify.js +1 -1
  74. package/dist/verify.js.map +1 -1
  75. package/dist/verify.mjs +1 -1
  76. package/dist/verify.mjs.map +1 -1
  77. package/package.json +8 -2
@@ -25,9 +25,7 @@ __export(hook_exports, {
25
25
  resolveGuardConfig: () => resolveGuardConfig
26
26
  });
27
27
  module.exports = __toCommonJS(hook_exports);
28
- var import_fs4 = require("fs");
29
- var import_os = require("os");
30
- var import_path3 = require("path");
28
+ var import_path4 = require("path");
31
29
 
32
30
  // src/gateway/types.ts
33
31
  var HIGH_RISK_COMMANDS = [
@@ -152,8 +150,9 @@ function extractBacktickSubstitutions(text, collect) {
152
150
  return kept.join(" ");
153
151
  }
154
152
  function basename(token) {
155
- const slash = token.lastIndexOf("/");
156
- return slash === -1 ? token : token.slice(slash + 1);
153
+ const slash = Math.max(token.lastIndexOf("/"), token.lastIndexOf("\\"));
154
+ const name = slash === -1 ? token : token.slice(slash + 1);
155
+ return name.replace(/\.(exe|cmd|bat|ps1)$/i, "");
157
156
  }
158
157
  function matchSegment(segment, list) {
159
158
  const tokens = segment.split(/\s+/).filter((t) => /[a-z0-9]/.test(t));
@@ -286,7 +285,9 @@ var LocalEvaluator = class {
286
285
  }
287
286
  return {
288
287
  recommendation: "ALLOW",
289
- reason: "All PDLSS checks passed",
288
+ // "evaluated": dimensions absent from the policy are skipped, not
289
+ // failed — evaluatedDimensions below records which ones ran.
290
+ reason: "All evaluated PDLSS checks passed",
290
291
  evaluatedDimensions: {
291
292
  purpose: true,
292
293
  scope: !!this.policy.scope,
@@ -385,7 +386,7 @@ var LocalEvaluator = class {
385
386
  }
386
387
  }
387
388
  if ((context.purpose === "file.read" || context.purpose === "file.write" || context.purpose === "file.delete") && context.target) {
388
- const targetLower = context.target.toLowerCase();
389
+ const targetLower = context.target.toLowerCase().replace(/\\/g, "/");
389
390
  for (const sensitivePath of SENSITIVE_PATHS) {
390
391
  if (targetLower.includes(sensitivePath.toLowerCase())) {
391
392
  score = Math.max(score, 50);
@@ -414,12 +415,20 @@ var LocalEvaluator = class {
414
415
  matchesAnyPattern(value, patterns) {
415
416
  return patterns.some((pattern) => this.matchGlob(value, pattern));
416
417
  }
417
- /**
418
- * Simple glob pattern matching.
419
- * Supports * (matches any characters including / and spaces) and ? (single char).
420
- * Uses the same approach as the backend's matchGlobPattern.
421
- */
418
+ homePrefix() {
419
+ if (this.cachedHomePrefix !== void 0) return this.cachedHomePrefix;
420
+ const env = typeof process !== "undefined" ? process.env : void 0;
421
+ const home = env?.HOME || env?.USERPROFILE;
422
+ this.cachedHomePrefix = home ? home.replace(/\\/g, "/") : null;
423
+ return this.cachedHomePrefix;
424
+ }
422
425
  matchGlob(value, pattern) {
426
+ value = value.replace(/\\/g, "/");
427
+ pattern = pattern.replace(/\\/g, "/");
428
+ if (pattern === "~" || pattern.startsWith("~/")) {
429
+ const home = this.homePrefix();
430
+ if (home) pattern = home + pattern.slice(1);
431
+ }
423
432
  if (pattern === value) return true;
424
433
  const starCount = (pattern.match(/\*/g) ?? []).length;
425
434
  if (starCount > 8) {
@@ -3692,7 +3701,7 @@ function getTrustLevel(score) {
3692
3701
  }
3693
3702
 
3694
3703
  // src/version.ts
3695
- var SDK_VERSION = "3.10.1";
3704
+ var SDK_VERSION = "3.11.1";
3696
3705
 
3697
3706
  // src/well-known.ts
3698
3707
  var CACHE_TTL_MS = 60 * 60 * 1e3;
@@ -4207,10 +4216,12 @@ function toGatewayConfig(config) {
4207
4216
  };
4208
4217
  }
4209
4218
  function toVerificationRequest(context, astraId) {
4219
+ const dotIndex = context.purpose.indexOf(".");
4220
+ const dotted = dotIndex > 0;
4210
4221
  return {
4211
4222
  credentials: { astraId },
4212
- purpose: context.purpose,
4213
- action: context.action,
4223
+ purpose: dotted ? context.purpose.slice(0, dotIndex) : context.purpose,
4224
+ action: dotted ? context.purpose : context.action,
4214
4225
  resourceType: context.resourceType,
4215
4226
  resource: context.target,
4216
4227
  transactionValue: context.transactionValue,
@@ -4453,13 +4464,43 @@ var TraceLogger = class {
4453
4464
  * Log an evaluation event.
4454
4465
  */
4455
4466
  logEvaluation(context, decision) {
4467
+ if (!this.enabled) return;
4468
+ let event;
4469
+ try {
4470
+ event = {
4471
+ id: this.generateId(),
4472
+ timestamp: /* @__PURE__ */ new Date(),
4473
+ type: "evaluation",
4474
+ context: redactDeep(context),
4475
+ decision: redactDeep(decision)
4476
+ };
4477
+ } catch (err) {
4478
+ event = {
4479
+ id: this.generateId(),
4480
+ timestamp: /* @__PURE__ */ new Date(),
4481
+ type: "error",
4482
+ metadata: {
4483
+ error: `trace redaction failed: ${err instanceof Error ? err.message : String(err)}`,
4484
+ recommendation: decision.recommendation,
4485
+ purpose: context.purpose,
4486
+ action: context.action
4487
+ }
4488
+ };
4489
+ }
4490
+ this.write(event);
4491
+ }
4492
+ /**
4493
+ * Log a tool call the guard saw but did not govern. One line per skip
4494
+ * keeps coverage holes (unmapped platform tools) visible in the traces
4495
+ * instead of silently indistinguishable from ALLOW.
4496
+ */
4497
+ logSkipped(toolName, reason) {
4456
4498
  if (!this.enabled) return;
4457
4499
  this.write({
4458
4500
  id: this.generateId(),
4459
4501
  timestamp: /* @__PURE__ */ new Date(),
4460
- type: "evaluation",
4461
- context: redactDeep(context),
4462
- decision: redactDeep(decision)
4502
+ type: "skipped",
4503
+ metadata: { toolName, reason }
4463
4504
  });
4464
4505
  }
4465
4506
  /**
@@ -4488,17 +4529,34 @@ var TraceLogger = class {
4488
4529
  });
4489
4530
  }
4490
4531
  write(event) {
4532
+ let line;
4533
+ try {
4534
+ line = JSON.stringify(event) + "\n";
4535
+ } catch {
4536
+ return;
4537
+ }
4491
4538
  try {
4492
4539
  const filePath = this.getCurrentFilePath();
4493
- const line = JSON.stringify(event) + "\n";
4494
4540
  if ((0, import_fs3.existsSync)(filePath)) {
4495
4541
  const stats = (0, import_fs3.statSync)(filePath);
4496
4542
  if (stats.size > MAX_FILE_SIZE) {
4497
4543
  this.rotate();
4498
4544
  }
4499
4545
  }
4500
- (0, import_fs3.appendFileSync)(filePath, line);
4546
+ for (let attempt = 0; attempt < 3; attempt++) {
4547
+ try {
4548
+ (0, import_fs3.appendFileSync)(filePath, line);
4549
+ return;
4550
+ } catch {
4551
+ }
4552
+ }
4553
+ const fallbackPath = filePath.replace(/\.jsonl$/, `-r${process.pid}.jsonl`);
4554
+ (0, import_fs3.appendFileSync)(fallbackPath, line);
4501
4555
  } catch {
4556
+ try {
4557
+ console.error(`[AstraSync TraceLogger] failed to persist trace line: ${line.trim()}`);
4558
+ } catch {
4559
+ }
4502
4560
  }
4503
4561
  }
4504
4562
  getCurrentFilePath() {
@@ -4659,6 +4717,13 @@ var AstraSyncGateway = class {
4659
4717
  getSyncStatus() {
4660
4718
  return this.syncQueue?.getStatus() || null;
4661
4719
  }
4720
+ /**
4721
+ * Record a tool call the calling adapter saw but did not govern
4722
+ * (unmapped tool, skipTools, MCP with governMcp off). Trace-only.
4723
+ */
4724
+ logSkippedTool(toolName, reason) {
4725
+ this.traceLogger?.logSkipped(toolName, reason);
4726
+ }
4662
4727
  };
4663
4728
 
4664
4729
  // src/adapter-interface/interface.ts
@@ -4750,6 +4815,11 @@ function extractNetworkDomains(target) {
4750
4815
  // src/claude-code/tool-mapping.ts
4751
4816
  var CLAUDE_CODE_TOOL_MAP = {
4752
4817
  Bash: "shell.exec",
4818
+ // Native Windows ships shell execution as a distinct PowerShell tool
4819
+ // (hooks docs: "Tool Names in PreToolUse"). Found live on 10 Jul 2026 —
4820
+ // the desktop-app runtime verification showed shell commands bypassing
4821
+ // the guard entirely on Windows because only Bash was mapped/matched.
4822
+ PowerShell: "shell.exec",
4753
4823
  Write: "file.write",
4754
4824
  Edit: "file.write",
4755
4825
  MultiEdit: "file.write",
@@ -4894,7 +4964,10 @@ var ClaudeCodeAdapter = class {
4894
4964
  timestamp: /* @__PURE__ */ new Date()
4895
4965
  };
4896
4966
  const interception = await this.interceptAction(action);
4897
- if (!interception.intercepted || !interception.context) return null;
4967
+ if (!interception.intercepted || !interception.context) {
4968
+ this.gateway.logSkippedTool(payload.tool_name, interception.skipReason ?? "not intercepted");
4969
+ return null;
4970
+ }
4898
4971
  const decision = await this.gateway.evaluate(interception.context);
4899
4972
  return this.decisionToHookOutput(decision);
4900
4973
  }
@@ -4906,11 +4979,10 @@ var ClaudeCodeAdapter = class {
4906
4979
  }
4907
4980
  };
4908
4981
 
4909
- // src/claude-code/hook.ts
4910
- var MAX_STDIN_BYTES = 1024 * 1024;
4911
- var STDIN_TIMEOUT_MS = 5e3;
4912
- var HYBRID_FLUSH_LIMIT = 3;
4913
- var HYBRID_FLUSH_TIMEOUT_MS = 1500;
4982
+ // src/claude-code/guard-config.ts
4983
+ var import_fs4 = require("fs");
4984
+ var import_os = require("os");
4985
+ var import_path3 = require("path");
4914
4986
  function resolveGuardConfig(env, payloadCwd, home = (0, import_os.homedir)()) {
4915
4987
  const candidateRoots = [env.CLAUDE_PROJECT_DIR, payloadCwd, home].filter(
4916
4988
  (root) => typeof root === "string" && root.length > 0
@@ -4932,6 +5004,12 @@ function resolveGuardConfig(env, payloadCwd, home = (0, import_os.homedir)()) {
4932
5004
  }
4933
5005
  return null;
4934
5006
  }
5007
+
5008
+ // src/claude-code/hook.ts
5009
+ var MAX_STDIN_BYTES = 1024 * 1024;
5010
+ var STDIN_TIMEOUT_MS = 5e3;
5011
+ var HYBRID_FLUSH_LIMIT = 3;
5012
+ var HYBRID_FLUSH_TIMEOUT_MS = 1500;
4935
5013
  function denyOutput(reason) {
4936
5014
  return {
4937
5015
  hookSpecificOutput: {
@@ -4975,7 +5053,7 @@ async function processHookPayload(payloadJson, options = {}) {
4975
5053
  policyFile: resolved.policyFile,
4976
5054
  posture: resolved.settings.posture ?? "active",
4977
5055
  traceEnabled: true,
4978
- tracePath: (0, import_path3.join)(resolved.guardDir, "traces"),
5056
+ tracePath: (0, import_path4.join)(resolved.guardDir, "traces"),
4979
5057
  debug: false,
4980
5058
  ...mode === "hybrid" && {
4981
5059
  apiBaseUrl: resolved.settings.apiBaseUrl,