@solongate/proxy 0.81.60 → 0.81.61

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.
@@ -15,3 +15,15 @@
15
15
  {"ms":2,"ts":1784326365762,"tool":"Bash","session":"f5933c65-c315-4440-9afb-7136fce6b695"}
16
16
  {"ms":3,"ts":1784326398280,"tool":"Edit","session":"f5933c65-c315-4440-9afb-7136fce6b695"}
17
17
  {"ms":1,"ts":1784326403539,"tool":"Bash","session":"f5933c65-c315-4440-9afb-7136fce6b695"}
18
+ {"ms":2,"ts":1784359530309,"tool":"Bash","session":"f5933c65-c315-4440-9afb-7136fce6b695"}
19
+ {"ms":4,"ts":1784359565744,"tool":"Bash","session":"f5933c65-c315-4440-9afb-7136fce6b695"}
20
+ {"ms":3,"ts":1784359892056,"tool":"Bash","session":"f5933c65-c315-4440-9afb-7136fce6b695"}
21
+ {"ms":2,"ts":1784359899408,"tool":"Bash","session":"f5933c65-c315-4440-9afb-7136fce6b695"}
22
+ {"ms":3,"ts":1784359942766,"tool":"Bash","session":"f5933c65-c315-4440-9afb-7136fce6b695"}
23
+ {"ms":3,"ts":1784359948446,"tool":"Bash","session":"f5933c65-c315-4440-9afb-7136fce6b695"}
24
+ {"ms":5,"ts":1784360088630,"tool":"Write","session":"f5933c65-c315-4440-9afb-7136fce6b695"}
25
+ {"ms":2,"ts":1784360093227,"tool":"Bash","session":"f5933c65-c315-4440-9afb-7136fce6b695"}
26
+ {"ms":4,"ts":1784360125661,"tool":"Bash","session":"f5933c65-c315-4440-9afb-7136fce6b695"}
27
+ {"ms":2,"ts":1784360134508,"tool":"Bash","session":"f5933c65-c315-4440-9afb-7136fce6b695"}
28
+ {"ms":5,"ts":1784360234461,"tool":"Bash","session":"f5933c65-c315-4440-9afb-7136fce6b695"}
29
+ {"ms":4,"ts":1784360256656,"tool":"Bash","session":"f5933c65-c315-4440-9afb-7136fce6b695"}
@@ -1 +1 @@
1
- {"tool":"Bash","ts":1784138162061}
1
+ {"tool":"Bash","ts":1784360236505}
@@ -1 +1 @@
1
- {"ms":1,"ts":1784326403539,"tool":"Bash","session":"f5933c65-c315-4440-9afb-7136fce6b695"}
1
+ {"ms":4,"ts":1784360256656,"tool":"Bash","session":"f5933c65-c315-4440-9afb-7136fce6b695"}
@@ -1 +1 @@
1
- 1784326398329
1
+ 1784360236504
@@ -6536,10 +6536,26 @@ 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 = 34;
6539
+ var HOOK_VERSION = 35;
6540
6540
  function localLogsOnly(security) {
6541
- const l = security && security.localLogs;
6542
- return !!(l && l.enabled && typeof l.path === "string" && l.path.trim());
6541
+ if (security && typeof security === "object") {
6542
+ const l = security.localLogs;
6543
+ return !!(l && l.enabled && typeof l.path === "string" && l.path.trim());
6544
+ }
6545
+ try {
6546
+ const m = JSON.parse(readFileSync(join(resolve(homedir(), ".solongate"), ".local-logs-mode.json"), "utf-8"));
6547
+ return !!(m && m.localOnly);
6548
+ } catch {
6549
+ return false;
6550
+ }
6551
+ }
6552
+ function writeLocalMarker(security) {
6553
+ try {
6554
+ const l = security && security.localLogs;
6555
+ const localOnly = !!(l && l.enabled && typeof l.path === "string" && l.path.trim());
6556
+ writeFileSync(join(resolve(homedir(), ".solongate"), ".local-logs-mode.json"), JSON.stringify({ localOnly, ts: Date.now() }));
6557
+ } catch {
6558
+ }
6543
6559
  }
6544
6560
  function resolveLocalLogDir(rawPath) {
6545
6561
  const dir = String(rawPath || "").trim().replace(/[\\/]+$/, "");
@@ -6753,6 +6769,7 @@ async function refreshPolicyCache() {
6753
6769
  writeFileSync(cacheFile, JSON.stringify({ _ts: Date.now(), policy, selfProtect, security, hookVersions }));
6754
6770
  } catch {
6755
6771
  }
6772
+ writeLocalMarker(security);
6756
6773
  } catch {
6757
6774
  }
6758
6775
  }
@@ -7751,8 +7768,10 @@ if (!REFRESH_MODE) {
7751
7768
  dashboardPolicy = cached.policy;
7752
7769
  if (typeof cached.selfProtect === "boolean")
7753
7770
  selfProtectEnabled = cached.selfProtect;
7754
- if (cached.security !== void 0)
7771
+ if (cached.security !== void 0) {
7755
7772
  securityCfg = cached.security;
7773
+ writeLocalMarker(securityCfg);
7774
+ }
7756
7775
  if (cached.hookVersions)
7757
7776
  CLOUD_HOOK_VERSIONS = cached.hookVersions;
7758
7777
  }
package/hooks/guard.mjs CHANGED
@@ -32,13 +32,36 @@ 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 = 34;
35
+ const HOOK_VERSION = 35;
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.
39
39
  function localLogsOnly(security) {
40
- const l = security && security.localLogs;
41
- return !!(l && l.enabled && typeof l.path === 'string' && l.path.trim());
40
+ if (security && typeof security === 'object') {
41
+ const l = security.localLogs;
42
+ return !!(l && l.enabled && typeof l.path === 'string' && l.path.trim());
43
+ }
44
+ // security UNKNOWN (cold start / policy-cache miss / mid-toggle): consult the
45
+ // persisted local-mode marker so a DENY is NEVER leaked to the cloud when this
46
+ // device is in local-only mode. Without this fallback the first call(s) before
47
+ // the policy cache warms POST the denial to the cloud and fire webhooks/alerts
48
+ // even though the user chose local-only.
49
+ try {
50
+ const m = JSON.parse(readFileSync(join(resolve(homedir(), '.solongate'), '.local-logs-mode.json'), 'utf-8'));
51
+ return !!(m && m.localOnly);
52
+ } catch { return false; }
53
+ }
54
+
55
+ // Persist whether this device is in local-only mode, INDEPENDENT of the policy
56
+ // cache, so localLogsOnly() answers correctly even on a cache-miss call. Written
57
+ // on every policy refresh; switching back to cloud sets localOnly:false so cloud
58
+ // POSTs resume.
59
+ function writeLocalMarker(security) {
60
+ try {
61
+ const l = security && security.localLogs;
62
+ const localOnly = !!(l && l.enabled && typeof l.path === 'string' && l.path.trim());
63
+ writeFileSync(join(resolve(homedir(), '.solongate'), '.local-logs-mode.json'), JSON.stringify({ localOnly, ts: Date.now() }));
64
+ } catch {}
42
65
  }
43
66
 
44
67
  // Resolve the FOLDER local logs may be written into. It MUST be absolute on
@@ -279,6 +302,7 @@ async function refreshPolicyCache() {
279
302
  } catch {}
280
303
  // Always advance _ts (success or failure) so the hot path backs off between refreshes.
281
304
  try { writeFileSync(cacheFile, JSON.stringify({ _ts: Date.now(), policy, selfProtect, security, hookVersions })); } catch {}
305
+ writeLocalMarker(security);
282
306
  } catch {}
283
307
  }
284
308
  if (REFRESH_MODE) { try { setTimeout(() => { try { process.exit(process.exitCode || 0); } catch {} }, 8000).unref(); } catch {} refreshPolicyCache().finally(() => { process.exitCode = 0; }); }
@@ -1553,7 +1577,7 @@ if (!REFRESH_MODE) { try { input += readFileSync(0, 'utf-8'); } catch {} }
1553
1577
  refreshDue = false;
1554
1578
  if (cached.policy) dashboardPolicy = cached.policy;
1555
1579
  if (typeof cached.selfProtect === 'boolean') selfProtectEnabled = cached.selfProtect;
1556
- if (cached.security !== undefined) securityCfg = cached.security;
1580
+ if (cached.security !== undefined) { securityCfg = cached.security; writeLocalMarker(securityCfg); }
1557
1581
  if (cached.hookVersions) CLOUD_HOOK_VERSIONS = cached.hookVersions;
1558
1582
  }
1559
1583
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@solongate/proxy",
3
- "version": "0.81.60",
3
+ "version": "0.81.61",
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": {