@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,7 +1,28 @@
1
- import { a as AstraSyncGatewayConfig, P as PDLSSContext, V as VerificationDecision } from '../types-D0lCtFQ7.mjs';
1
+ import { a as AstraSyncGatewayConfig, P as PDLSSContext, V as VerificationDecision } from '../types-BV6abBnF.mjs';
2
2
  import '../types-sy3tq8lp.mjs';
3
3
  import '../metadata-capture.mjs';
4
4
 
5
+ /**
6
+ * Hybrid Mode — Local evaluation for speed, async API sync for trust scoring.
7
+ *
8
+ * Immediate: local PDLSS evaluation (< 1ms)
9
+ * Async: queued API verification for audit trail and trust score updates
10
+ *
11
+ * Queue entries are persisted to disk so they survive process restarts.
12
+ */
13
+
14
+ interface FlushOptions {
15
+ /** Max entries to attempt this flush (default: all pending). */
16
+ limit?: number;
17
+ /**
18
+ * Per-entry time budget in ms. A timed-out entry stays pending (no retry
19
+ * penalty — slow network is not a failure) and ends the flush early.
20
+ * Stateless callers (the Claude Code hook) use this to keep sync off the
21
+ * tool-call critical path.
22
+ */
23
+ perEntryTimeoutMs?: number;
24
+ }
25
+
5
26
  /**
6
27
  * AstraSyncGateway — Primary API surface for agent verification.
7
28
  *
@@ -37,8 +58,12 @@ declare class AstraSyncGateway {
37
58
  initialize(): Promise<void>;
38
59
  /**
39
60
  * Graceful shutdown. Flushes sync queue and cleans up resources.
61
+ * Stateless callers (hooks) pass bounded flush options so sync never
62
+ * sits on a tool call's critical path.
40
63
  */
41
- shutdown(): Promise<void>;
64
+ shutdown(options?: {
65
+ syncFlush?: FlushOptions;
66
+ }): Promise<void>;
42
67
  /**
43
68
  * Evaluate an action against the verification policy.
44
69
  * Routes to the appropriate mode handler.
@@ -1,7 +1,28 @@
1
- import { a as AstraSyncGatewayConfig, P as PDLSSContext, V as VerificationDecision } from '../types-YbiXYKx1.js';
1
+ import { a as AstraSyncGatewayConfig, P as PDLSSContext, V as VerificationDecision } from '../types-C23_uaY8.js';
2
2
  import '../types-9tns4wyl.js';
3
3
  import '../metadata-capture.js';
4
4
 
5
+ /**
6
+ * Hybrid Mode — Local evaluation for speed, async API sync for trust scoring.
7
+ *
8
+ * Immediate: local PDLSS evaluation (< 1ms)
9
+ * Async: queued API verification for audit trail and trust score updates
10
+ *
11
+ * Queue entries are persisted to disk so they survive process restarts.
12
+ */
13
+
14
+ interface FlushOptions {
15
+ /** Max entries to attempt this flush (default: all pending). */
16
+ limit?: number;
17
+ /**
18
+ * Per-entry time budget in ms. A timed-out entry stays pending (no retry
19
+ * penalty — slow network is not a failure) and ends the flush early.
20
+ * Stateless callers (the Claude Code hook) use this to keep sync off the
21
+ * tool-call critical path.
22
+ */
23
+ perEntryTimeoutMs?: number;
24
+ }
25
+
5
26
  /**
6
27
  * AstraSyncGateway — Primary API surface for agent verification.
7
28
  *
@@ -37,8 +58,12 @@ declare class AstraSyncGateway {
37
58
  initialize(): Promise<void>;
38
59
  /**
39
60
  * Graceful shutdown. Flushes sync queue and cleans up resources.
61
+ * Stateless callers (hooks) pass bounded flush options so sync never
62
+ * sits on a tool call's critical path.
40
63
  */
41
- shutdown(): Promise<void>;
64
+ shutdown(options?: {
65
+ syncFlush?: FlushOptions;
66
+ }): Promise<void>;
42
67
  /**
43
68
  * Evaluate an action against the verification policy.
44
69
  * Routes to the appropriate mode handler.
@@ -44,7 +44,9 @@ var HIGH_RISK_COMMANDS = [
44
44
  "git push",
45
45
  "npm publish",
46
46
  "docker",
47
- "kubectl"
47
+ "kubectl",
48
+ "gh pr create",
49
+ "gh pr merge"
48
50
  ];
49
51
  var SENSITIVE_PATHS = [
50
52
  ".ssh",
@@ -63,6 +65,164 @@ var SENSITIVE_PATHS = [
63
65
  ".pypirc"
64
66
  ];
65
67
 
68
+ // src/local-evaluator/command-matcher.ts
69
+ var WRAPPERS = /* @__PURE__ */ new Set([
70
+ "sudo",
71
+ "doas",
72
+ "env",
73
+ "nohup",
74
+ "time",
75
+ "timeout",
76
+ "nice",
77
+ "ionice",
78
+ "stdbuf",
79
+ "xargs",
80
+ "command",
81
+ "exec",
82
+ "builtin"
83
+ ]);
84
+ var ASSIGN_RE = /^[a-z_][a-z0-9_]*=/;
85
+ var MAX_WRAPPER_HOPS = 4;
86
+ var MAX_RECURSION_DEPTH = 3;
87
+ var MAX_COMMAND_LENGTH = 1e5;
88
+ var LOCAL_HOST_RE = /^(localhost|127\.0\.0\.1|::1|[a-z0-9.-]*\.localhost)$/;
89
+ function buildRiskList(entries) {
90
+ const singleWord = /* @__PURE__ */ new Set();
91
+ const multiWord = [];
92
+ for (const entry of entries) {
93
+ const words = entry.toLowerCase().trim().split(/\s+/);
94
+ if (words.length === 1) singleWord.add(words[0]);
95
+ else multiWord.push(words);
96
+ }
97
+ multiWord.sort((a, b) => b.length - a.length);
98
+ return { singleWord, multiWord };
99
+ }
100
+ function stripHeredocBodies(text) {
101
+ const lines = text.split("\n");
102
+ const kept = [];
103
+ let terminator = null;
104
+ for (const line of lines) {
105
+ if (terminator !== null) {
106
+ if (line.trim() === terminator) terminator = null;
107
+ continue;
108
+ }
109
+ kept.push(line);
110
+ const heredoc = line.match(/<<-?\s*['"]?(\w+)['"]?/);
111
+ if (heredoc) terminator = heredoc[1];
112
+ }
113
+ return kept.join("\n");
114
+ }
115
+ function extractDollarSubstitutions(text, collect) {
116
+ let result = text;
117
+ let start = result.indexOf("$(");
118
+ let iterations = 0;
119
+ while (start !== -1 && iterations < 50) {
120
+ iterations++;
121
+ let depth = 0;
122
+ let end = result.length;
123
+ for (let i = start + 1; i < result.length; i++) {
124
+ if (result[i] === "(") depth++;
125
+ else if (result[i] === ")") {
126
+ depth--;
127
+ if (depth === 0) {
128
+ end = i;
129
+ break;
130
+ }
131
+ }
132
+ }
133
+ collect(result.slice(start + 2, end));
134
+ result = `${result.slice(0, start)} ${result.slice(Math.min(end + 1, result.length))}`;
135
+ start = result.indexOf("$(");
136
+ }
137
+ return result;
138
+ }
139
+ function extractBacktickSubstitutions(text, collect) {
140
+ if (!text.includes("`")) return text;
141
+ const chunks = text.split("`");
142
+ const kept = [];
143
+ for (let i = 0; i < chunks.length; i++) {
144
+ if (i % 2 === 1) collect(chunks[i]);
145
+ else kept.push(chunks[i]);
146
+ }
147
+ return kept.join(" ");
148
+ }
149
+ function basename(token) {
150
+ const slash = token.lastIndexOf("/");
151
+ return slash === -1 ? token : token.slice(slash + 1);
152
+ }
153
+ function matchSegment(segment, list) {
154
+ const tokens = segment.split(/\s+/).filter((t) => /[a-z0-9]/.test(t));
155
+ let i = 0;
156
+ let hops = 0;
157
+ while (i < tokens.length) {
158
+ while (i < tokens.length && (tokens[i] === "export" || ASSIGN_RE.test(tokens[i]))) i++;
159
+ if (i >= tokens.length) return null;
160
+ const cmd = basename(tokens[i]);
161
+ const significant = [cmd, ...tokens.slice(i + 1).filter((t) => !t.startsWith("-"))];
162
+ for (const entry of list.multiWord) {
163
+ if (entry.length <= significant.length && entry.every((w, j) => significant[j] === w)) {
164
+ return entry.join(" ");
165
+ }
166
+ }
167
+ if (list.singleWord.has(cmd)) return cmd;
168
+ if (WRAPPERS.has(cmd) && hops < MAX_WRAPPER_HOPS) {
169
+ hops++;
170
+ i++;
171
+ while (i < tokens.length && (tokens[i].startsWith("-") || ASSIGN_RE.test(tokens[i]))) i++;
172
+ continue;
173
+ }
174
+ return null;
175
+ }
176
+ return null;
177
+ }
178
+ function collectMatches(command, list, matches, depth) {
179
+ if (depth > MAX_RECURSION_DEPTH || command.length > MAX_COMMAND_LENGTH) return;
180
+ let text = command.toLowerCase();
181
+ text = stripHeredocBodies(text);
182
+ const recurse = (inner) => collectMatches(inner, list, matches, depth + 1);
183
+ text = extractDollarSubstitutions(text, recurse);
184
+ text = extractBacktickSubstitutions(text, recurse);
185
+ text = text.replace(/'[^']*'/g, " ").replace(/"[^"]*"/g, " ");
186
+ text = text.replace(/(^|\s)#[^\n]*/g, " ");
187
+ const segments = text.split(/\|\||&&|[;|&\n]|[({]/);
188
+ for (const segment of segments) {
189
+ const matched = matchSegment(segment, list);
190
+ if (matched) matches.add(matched);
191
+ }
192
+ }
193
+ function matchHighRiskCommands(command, highRiskCommands = HIGH_RISK_COMMANDS) {
194
+ if (!command) return [];
195
+ const matches = /* @__PURE__ */ new Set();
196
+ collectMatches(command, buildRiskList(highRiskCommands), matches, 0);
197
+ return [...matches];
198
+ }
199
+ function isLocalhostOnlyNetworkCommand(command) {
200
+ const text = command.toLowerCase();
201
+ const tokens = text.split(/\s+/).map((t) => t.replace(/^["'`]+|["'`,;)]+$/g, ""));
202
+ let localCount = 0;
203
+ for (const token of tokens) {
204
+ let host = null;
205
+ if (token.includes("://")) {
206
+ let rest = token.slice(token.indexOf("://") + 3);
207
+ const at = rest.indexOf("@");
208
+ if (at !== -1) rest = rest.slice(at + 1);
209
+ host = rest.split(/[/?#]/)[0];
210
+ } else if (/^[a-z0-9.[\]:-]+:\d+(\/.*)?$/.test(token)) {
211
+ host = token.split("/")[0];
212
+ } else if (/^(localhost|127\.0\.0\.1|\[?::1\]?)(\/.*)?$/.test(token)) {
213
+ host = token.split("/")[0];
214
+ }
215
+ if (host === null) continue;
216
+ const bare = host.replace(/:\d+$/, "").replace(/^\[|\]$/g, "");
217
+ if (LOCAL_HOST_RE.test(bare)) {
218
+ localCount++;
219
+ } else {
220
+ return false;
221
+ }
222
+ }
223
+ return localCount > 0;
224
+ }
225
+
66
226
  // src/local-evaluator/evaluator.ts
67
227
  var LocalEvaluator = class {
68
228
  constructor(policy) {
@@ -213,12 +373,10 @@ var LocalEvaluator = class {
213
373
  return score;
214
374
  }
215
375
  if (context.purpose === "shell.exec" && context.target) {
216
- const targetLower = context.target.toLowerCase();
217
- for (const cmd of HIGH_RISK_COMMANDS) {
218
- if (targetLower.startsWith(cmd) || targetLower.includes(` ${cmd} `) || targetLower.includes(` ${cmd}`)) {
219
- score = Math.max(score, 80);
220
- break;
221
- }
376
+ const matched = matchHighRiskCommands(context.target);
377
+ const localProbeOnly = matched.length > 0 && matched.every((cmd) => cmd === "curl" || cmd === "wget") && isLocalhostOnlyNetworkCommand(context.target);
378
+ if (matched.length > 0 && !localProbeOnly) {
379
+ score = Math.max(score, 80);
222
380
  }
223
381
  }
224
382
  if ((context.purpose === "file.read" || context.purpose === "file.write" || context.purpose === "file.delete") && context.target) {
@@ -3529,7 +3687,7 @@ function getTrustLevel(score) {
3529
3687
  }
3530
3688
 
3531
3689
  // src/version.ts
3532
- var SDK_VERSION = "3.10.0";
3690
+ var SDK_VERSION = "3.10.1";
3533
3691
 
3534
3692
  // src/well-known.ts
3535
3693
  var CACHE_TTL_MS = 60 * 60 * 1e3;
@@ -4087,8 +4245,75 @@ async function verifyOnline(config, context, astraId) {
4087
4245
  // src/gateway/modes/hybrid.ts
4088
4246
  var import_fs2 = require("fs");
4089
4247
  var import_path = require("path");
4248
+
4249
+ // src/gateway/redact.ts
4250
+ var marker = (type2) => `[REDACTED:${type2}]`;
4251
+ var REDACTION_PATTERNS = [
4252
+ // Multi-line blocks first so later single-line patterns don't shred them.
4253
+ {
4254
+ type: "private-key",
4255
+ re: /-----BEGIN [A-Z ]*PRIVATE KEY-----[\s\S]*?(?:-----END [A-Z ]*PRIVATE KEY-----|$)/g
4256
+ },
4257
+ // URL userinfo credentials (https://user:pass@, x-access-token:ghp_…@).
4258
+ {
4259
+ type: "url-credentials",
4260
+ re: /([a-z][a-z0-9+.-]*:\/\/)[^\s/@]+:[^\s/@]+@/gi,
4261
+ replacement: `$1${marker("url-credentials")}@`
4262
+ },
4263
+ // Known token formats.
4264
+ { type: "github-token", re: /\bgh[pousr]_[A-Za-z0-9]{20,255}\b/g },
4265
+ { type: "github-token", re: /\bgithub_pat_[A-Za-z0-9_]{20,255}\b/g },
4266
+ { type: "astrasync-key", re: /\bkya_[A-Fa-f0-9]{32,128}\b/g },
4267
+ { type: "openai-key", re: /\bsk-[A-Za-z0-9_-]{20,}\b/g },
4268
+ { type: "aws-access-key-id", re: /\bAKIA[0-9A-Z]{16}\b/g },
4269
+ { type: "jwt", re: /\beyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\b/g },
4270
+ // Bearer/token headers.
4271
+ {
4272
+ type: "bearer-token",
4273
+ re: /\b(bearer\s+)[a-z0-9._~+/=-]{16,}/gi,
4274
+ replacement: `$1${marker("bearer-token")}`
4275
+ },
4276
+ // Generic KEY=value / key: value assignments with secret-ish names.
4277
+ {
4278
+ type: "assigned-secret",
4279
+ re: /\b((?:password|passwd|secret|token|api[_-]?key|apikey|access[_-]?key|client[_-]?secret|private[_-]?key)\s*[=:]\s*)(['"]?)[^\s'"&;]{8,}\2/gi,
4280
+ replacement: `$1$2${marker("assigned-secret")}$2`
4281
+ }
4282
+ ];
4283
+ function redactSecrets(text) {
4284
+ let result = text;
4285
+ for (const { type: type2, re, replacement } of REDACTION_PATTERNS) {
4286
+ result = result.replace(re, replacement ?? marker(type2));
4287
+ }
4288
+ return result;
4289
+ }
4290
+ function redactDeep(value) {
4291
+ if (typeof value === "string") {
4292
+ return redactSecrets(value);
4293
+ }
4294
+ if (Array.isArray(value)) {
4295
+ return value.map((item) => redactDeep(item));
4296
+ }
4297
+ if (value !== null && typeof value === "object" && !(value instanceof Date)) {
4298
+ const out = {};
4299
+ for (const [k, v] of Object.entries(value)) {
4300
+ out[k] = redactDeep(v);
4301
+ }
4302
+ return out;
4303
+ }
4304
+ return value;
4305
+ }
4306
+
4307
+ // src/gateway/modes/hybrid.ts
4090
4308
  var MAX_QUEUE_SIZE = 1e3;
4091
4309
  var MAX_RETRIES = 3;
4310
+ var FLUSH_TIMEOUT = /* @__PURE__ */ Symbol("flush-timeout");
4311
+ function delay(ms) {
4312
+ return new Promise((resolve) => {
4313
+ const timer = setTimeout(() => resolve(FLUSH_TIMEOUT), ms);
4314
+ if (typeof timer.unref === "function") timer.unref();
4315
+ });
4316
+ }
4092
4317
  var HybridSyncQueue = class {
4093
4318
  constructor(config, persistPath) {
4094
4319
  this.queue = [];
@@ -4109,12 +4334,12 @@ var HybridSyncQueue = class {
4109
4334
  /**
4110
4335
  * Stop periodic sync and flush remaining entries.
4111
4336
  */
4112
- async stop() {
4337
+ async stop(flushOptions = {}) {
4113
4338
  if (this.timer) {
4114
4339
  clearInterval(this.timer);
4115
4340
  this.timer = null;
4116
4341
  }
4117
- await this.flush();
4342
+ await this.flush(flushOptions);
4118
4343
  this.saveToDisk();
4119
4344
  }
4120
4345
  /**
@@ -4126,8 +4351,8 @@ var HybridSyncQueue = class {
4126
4351
  }
4127
4352
  this.queue.push({
4128
4353
  id: `${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
4129
- context,
4130
- decision,
4354
+ context: redactDeep(context),
4355
+ decision: redactDeep(decision),
4131
4356
  timestamp: /* @__PURE__ */ new Date(),
4132
4357
  retryCount: 0,
4133
4358
  status: "pending"
@@ -4137,16 +4362,21 @@ var HybridSyncQueue = class {
4137
4362
  /**
4138
4363
  * Flush pending entries to the API.
4139
4364
  */
4140
- async flush() {
4365
+ async flush(options = {}) {
4141
4366
  if (this.processing) return;
4142
4367
  this.processing = true;
4143
4368
  try {
4144
4369
  const pending = this.queue.filter((e) => e.status === "pending");
4145
- for (const entry of pending) {
4146
- try {
4147
- await verifyOnline(this.config, entry.context);
4370
+ const batch = typeof options.limit === "number" ? pending.slice(0, options.limit) : pending;
4371
+ for (const entry of batch) {
4372
+ const attempt = verifyOnline(this.config, entry.context, this.config.agentId).then(() => "synced").catch(() => "error");
4373
+ const result = options.perEntryTimeoutMs ? await Promise.race([attempt, delay(options.perEntryTimeoutMs)]) : await attempt;
4374
+ if (result === FLUSH_TIMEOUT) {
4375
+ break;
4376
+ }
4377
+ if (result === "synced") {
4148
4378
  entry.status = "synced";
4149
- } catch {
4379
+ } else {
4150
4380
  entry.retryCount++;
4151
4381
  if (entry.retryCount >= MAX_RETRIES) {
4152
4382
  entry.status = "failed";
@@ -4223,8 +4453,8 @@ var TraceLogger = class {
4223
4453
  id: this.generateId(),
4224
4454
  timestamp: /* @__PURE__ */ new Date(),
4225
4455
  type: "evaluation",
4226
- context,
4227
- decision
4456
+ context: redactDeep(context),
4457
+ decision: redactDeep(decision)
4228
4458
  });
4229
4459
  }
4230
4460
  /**
@@ -4341,10 +4571,12 @@ var AstraSyncGateway = class {
4341
4571
  }
4342
4572
  /**
4343
4573
  * Graceful shutdown. Flushes sync queue and cleans up resources.
4574
+ * Stateless callers (hooks) pass bounded flush options so sync never
4575
+ * sits on a tool call's critical path.
4344
4576
  */
4345
- async shutdown() {
4577
+ async shutdown(options) {
4346
4578
  if (this.syncQueue) {
4347
- await this.syncQueue.stop();
4579
+ await this.syncQueue.stop(options?.syncFlush ?? {});
4348
4580
  this.syncQueue = null;
4349
4581
  }
4350
4582
  this.evaluator = null;
@@ -4367,7 +4599,7 @@ var AstraSyncGateway = class {
4367
4599
  let decision;
4368
4600
  switch (this.config.mode) {
4369
4601
  case "online":
4370
- decision = await verifyOnline(this.config, context, astraId);
4602
+ decision = await verifyOnline(this.config, context, astraId ?? this.config.agentId);
4371
4603
  break;
4372
4604
  case "local":
4373
4605
  if (!this.evaluator) throw new Error("Local evaluator not initialized");