@solongate/proxy 0.83.13 → 0.83.14

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.
@@ -6536,7 +6536,7 @@ import { resolve, join, dirname, isAbsolute } from "node:path";
6536
6536
  import { homedir } from "node:os";
6537
6537
  import { gunzipSync } from "node:zlib";
6538
6538
  import { createHash } from "node:crypto";
6539
- var HOOK_VERSION = 76;
6539
+ var HOOK_VERSION = 77;
6540
6540
  function localLogsOnly(security) {
6541
6541
  if (security !== void 0) {
6542
6542
  const l = security && security.localLogs;
@@ -6714,6 +6714,30 @@ function installedHookVersion(fileName) {
6714
6714
  return 0;
6715
6715
  }
6716
6716
  }
6717
+ function registeredClients() {
6718
+ const home = resolve(homedir());
6719
+ const has = (p, needle) => {
6720
+ try {
6721
+ const s = safeReadFileSync(p);
6722
+ if (!s)
6723
+ return false;
6724
+ return needle ? s.includes(needle) : true;
6725
+ } catch {
6726
+ return false;
6727
+ }
6728
+ };
6729
+ const out = [];
6730
+ if (has(join(home, ".claude", "settings.json"), ".solongate"))
6731
+ out.push("claude-code");
6732
+ if (has(join(home, ".gemini", "config", "hooks.json"), ".solongate"))
6733
+ out.push("antigravity");
6734
+ if (has(join(process.env.CODEX_HOME ? resolve(process.env.CODEX_HOME) : join(home, ".codex"), "hooks.json"), ".solongate"))
6735
+ out.push("codex");
6736
+ const xdg = process.env.XDG_CONFIG_HOME ? resolve(process.env.XDG_CONFIG_HOME) : join(home, ".config");
6737
+ if (has(join(xdg, "opencode", "plugins", "solongate.js"), "tool.execute.before"))
6738
+ out.push("opencode");
6739
+ return out;
6740
+ }
6717
6741
  var CLOUD_HOOK_VERSIONS = null;
6718
6742
  function hooksBehindCloud() {
6719
6743
  const v = CLOUD_HOOK_VERSIONS;
@@ -6808,7 +6832,10 @@ async function refreshPolicyCache() {
6808
6832
  } catch {
6809
6833
  }
6810
6834
  try {
6811
- const res = await fetch(API_URL + "/api/v1/policies/active?agent_id=" + encodeURIComponent(AGENT_ID || "") + "&hv=" + HOOK_VERSION, { headers: AUTH_HEADERS, signal: AbortSignal.timeout(8e3) });
6835
+ const res = await fetch(
6836
+ API_URL + "/api/v1/policies/active?agent_id=" + encodeURIComponent(AGENT_ID || "") + "&hv=" + HOOK_VERSION + "&clients=" + encodeURIComponent(registeredClients().join(",")),
6837
+ { headers: AUTH_HEADERS, signal: AbortSignal.timeout(8e3) }
6838
+ );
6812
6839
  if (res.ok) {
6813
6840
  const body = await res.json();
6814
6841
  if (typeof body?.self_protection_enabled === "boolean")
package/hooks/guard.mjs CHANGED
@@ -32,7 +32,7 @@ import { createHash } from 'node:crypto';
32
32
  // the installed hook self-updates when the cloud version is higher (see
33
33
  // maybeSelfUpdate). This is what makes guard fixes propagate without a manual
34
34
  // reinstall — the same trust model as the OPA WASM this hook already runs.
35
- const HOOK_VERSION = 76;
35
+ const HOOK_VERSION = 77;
36
36
 
37
37
  // True when local log storage is ON. In that mode logs are kept LOCAL ONLY and
38
38
  // nothing is sent to the cloud audit log — local and cloud are one or the
@@ -313,6 +313,36 @@ function installedHookVersion(fileName) {
313
313
  } catch { return 0; }
314
314
  }
315
315
 
316
+ /**
317
+ * Which clients the guard is REGISTERED for on this machine.
318
+ *
319
+ * The dashboard used to infer this from "whose guard has called in", which
320
+ * answers a different question than `repair` and `doctor` do — a client that is
321
+ * installed but has not been opened in days reads as unguarded, and the three
322
+ * surfaces contradicted each other while using identical wording. The machine
323
+ * is the only thing that can see its own files, so it reports them.
324
+ *
325
+ * Cheap on purpose: four existence/substring checks against files this hook
326
+ * already treats as tamper targets, run on a poll that is throttled to 10s.
327
+ */
328
+ function registeredClients() {
329
+ const home = resolve(homedir());
330
+ const has = (p, needle) => {
331
+ try {
332
+ const s = safeReadFileSync(p);
333
+ if (!s) return false;
334
+ return needle ? s.includes(needle) : true;
335
+ } catch { return false; }
336
+ };
337
+ const out = [];
338
+ if (has(join(home, '.claude', 'settings.json'), '.solongate')) out.push('claude-code');
339
+ if (has(join(home, '.gemini', 'config', 'hooks.json'), '.solongate')) out.push('antigravity');
340
+ if (has(join(process.env.CODEX_HOME ? resolve(process.env.CODEX_HOME) : join(home, '.codex'), 'hooks.json'), '.solongate')) out.push('codex');
341
+ const xdg = process.env.XDG_CONFIG_HOME ? resolve(process.env.XDG_CONFIG_HOME) : join(home, '.config');
342
+ if (has(join(xdg, 'opencode', 'plugins', 'solongate.js'), 'tool.execute.before')) out.push('opencode');
343
+ return out;
344
+ }
345
+
316
346
  // Latest hook versions the cloud reports on /policies/active (hook_versions).
317
347
  // Captured during the policy fetch of THIS run (or its short-lived cache); lets
318
348
  // maybeSelfUpdate() know it is behind and bypass the 6h stamp entirely.
@@ -425,7 +455,12 @@ async function refreshPolicyCache() {
425
455
  }
426
456
  } catch {}
427
457
  try {
428
- const res = await fetch(API_URL + '/api/v1/policies/active?agent_id=' + encodeURIComponent(AGENT_ID || '') + '&hv=' + HOOK_VERSION, { headers: AUTH_HEADERS, signal: AbortSignal.timeout(8000) });
458
+ const res = await fetch(
459
+ API_URL + '/api/v1/policies/active?agent_id=' + encodeURIComponent(AGENT_ID || '')
460
+ + '&hv=' + HOOK_VERSION
461
+ + '&clients=' + encodeURIComponent(registeredClients().join(',')),
462
+ { headers: AUTH_HEADERS, signal: AbortSignal.timeout(8000) },
463
+ );
429
464
  if (res.ok) {
430
465
  const body = await res.json();
431
466
  if (typeof body?.self_protection_enabled === 'boolean') selfProtect = body.self_protection_enabled;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@solongate/proxy",
3
- "version": "0.83.13",
3
+ "version": "0.83.14",
4
4
  "description": "AI tool security proxy: protect any AI tool server with customizable policies, path/command constraints, rate limiting, and audit logging. No code changes required.",
5
5
  "type": "module",
6
6
  "bin": {