@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.
- package/hooks/guard.bundled.mjs +29 -2
- package/hooks/guard.mjs +37 -2
- package/package.json +1 -1
package/hooks/guard.bundled.mjs
CHANGED
|
@@ -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 =
|
|
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(
|
|
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 =
|
|
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(
|
|
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.
|
|
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": {
|