@solongate/proxy 0.82.91 → 0.82.93

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.
@@ -1241,7 +1241,7 @@ async function collectChecks() {
1241
1241
  }
1242
1242
  try {
1243
1243
  const g = await api.settings.getGuardStatus();
1244
- checks.push({ name: "guard hook", ok: g.up_to_date ? true : "warn", detail: g.up_to_date ? `v${g.installed} (latest) \xB7 ${g.device_count} device(s)` : `v${g.installed} \u2192 v${g.latest} available \xB7 update from \`solongate\` \u2192 Settings \u2192 guard` });
1244
+ checks.push({ name: "guard hook", ok: g.up_to_date ? true : "warn", detail: g.up_to_date ? `v${g.installed} (latest) \xB7 ${g.device_count} device(s)` : `v${g.installed} \u2192 v${g.latest} available \xB7 run \`solongate update\` in your terminal` });
1245
1245
  } catch {
1246
1246
  }
1247
1247
  }
package/dist/index.js CHANGED
@@ -7446,20 +7446,15 @@ function ensureLocalLogOwner(activeApiKey) {
7446
7446
  } catch {
7447
7447
  }
7448
7448
  if (have === want) return false;
7449
- const cleared = localLogExists();
7450
- if (cleared) clearLocalLog();
7451
7449
  try {
7452
7450
  writeFileSync6(marker, want);
7453
7451
  } catch {
7454
7452
  }
7455
- return cleared;
7453
+ return false;
7456
7454
  } catch {
7457
7455
  return false;
7458
7456
  }
7459
7457
  }
7460
- function localLogExists() {
7461
- return existsSync4(localLogFile());
7462
- }
7463
7458
  function tailLines(file, maxBytes = 131072) {
7464
7459
  try {
7465
7460
  const size = statSync(file).size;
@@ -7519,11 +7514,22 @@ function reasonSignals(reason) {
7519
7514
  }
7520
7515
  return { dlp, burst: RL_REASON.test(r) };
7521
7516
  }
7517
+ function ownMark() {
7518
+ try {
7519
+ const p = join8(homedir6(), ".solongate", "cloud-guard.json");
7520
+ const c2 = JSON.parse(readFileSync8(p, "utf-8"));
7521
+ return c2?.apiKey ? createHash2("sha256").update(c2.apiKey).digest("hex").slice(0, 16) : "";
7522
+ } catch {
7523
+ return "";
7524
+ }
7525
+ }
7522
7526
  function parseLocalLines(lines) {
7523
7527
  const out2 = [];
7528
+ const mine = ownMark();
7524
7529
  for (const line of lines) {
7525
7530
  try {
7526
7531
  const j = JSON.parse(line);
7532
+ if (mine && j.acct !== mine) continue;
7527
7533
  const at = Date.parse(j.ts ?? "");
7528
7534
  if (Number.isFinite(at)) out2.push({ ...j, at });
7529
7535
  } catch {
@@ -11322,7 +11328,7 @@ async function collectChecks() {
11322
11328
  }
11323
11329
  try {
11324
11330
  const g = await api.settings.getGuardStatus();
11325
- checks.push({ name: "guard hook", ok: g.up_to_date ? true : "warn", detail: g.up_to_date ? `v${g.installed} (latest) \xB7 ${g.device_count} device(s)` : `v${g.installed} \u2192 v${g.latest} available \xB7 update from \`solongate\` \u2192 Settings \u2192 guard` });
11331
+ checks.push({ name: "guard hook", ok: g.up_to_date ? true : "warn", detail: g.up_to_date ? `v${g.installed} (latest) \xB7 ${g.device_count} device(s)` : `v${g.installed} \u2192 v${g.latest} available \xB7 run \`solongate update\` in your terminal` });
11326
11332
  } catch {
11327
11333
  }
11328
11334
  }
package/dist/tui/index.js CHANGED
@@ -782,20 +782,15 @@ function ensureLocalLogOwner(activeApiKey) {
782
782
  } catch {
783
783
  }
784
784
  if (have === want) return false;
785
- const cleared = localLogExists();
786
- if (cleared) clearLocalLog();
787
785
  try {
788
786
  writeFileSync(marker, want);
789
787
  } catch {
790
788
  }
791
- return cleared;
789
+ return false;
792
790
  } catch {
793
791
  return false;
794
792
  }
795
793
  }
796
- function localLogExists() {
797
- return existsSync(localLogFile());
798
- }
799
794
  function tailLines(file, maxBytes = 131072) {
800
795
  try {
801
796
  const size = statSync(file).size;
@@ -857,11 +852,22 @@ function reasonSignals(reason) {
857
852
  }
858
853
  return { dlp, burst: RL_REASON.test(r) };
859
854
  }
855
+ function ownMark() {
856
+ try {
857
+ const p = join2(homedir2(), ".solongate", "cloud-guard.json");
858
+ const c2 = JSON.parse(readFileSync2(p, "utf-8"));
859
+ return c2?.apiKey ? createHash("sha256").update(c2.apiKey).digest("hex").slice(0, 16) : "";
860
+ } catch {
861
+ return "";
862
+ }
863
+ }
860
864
  function parseLocalLines(lines) {
861
865
  const out = [];
866
+ const mine = ownMark();
862
867
  for (const line of lines) {
863
868
  try {
864
869
  const j = JSON.parse(line);
870
+ if (mine && j.acct !== mine) continue;
865
871
  const at = Date.parse(j.ts ?? "");
866
872
  if (Number.isFinite(at)) out.push({ ...j, at });
867
873
  } catch {
@@ -4351,7 +4357,7 @@ async function collectChecks() {
4351
4357
  }
4352
4358
  try {
4353
4359
  const g = await api.settings.getGuardStatus();
4354
- checks.push({ name: "guard hook", ok: g.up_to_date ? true : "warn", detail: g.up_to_date ? `v${g.installed} (latest) \xB7 ${g.device_count} device(s)` : `v${g.installed} \u2192 v${g.latest} available \xB7 update from \`solongate\` \u2192 Settings \u2192 guard` });
4360
+ checks.push({ name: "guard hook", ok: g.up_to_date ? true : "warn", detail: g.up_to_date ? `v${g.installed} (latest) \xB7 ${g.device_count} device(s)` : `v${g.installed} \u2192 v${g.latest} available \xB7 run \`solongate update\` in your terminal` });
4355
4361
  } catch {
4356
4362
  }
4357
4363
  }
@@ -49,6 +49,8 @@ export interface LocalLogLine {
49
49
  permission?: string;
50
50
  trust_level?: string;
51
51
  session_id?: string;
52
+ /** Hash prefix of the account that wrote this line. */
53
+ acct?: string;
52
54
  agent_name?: string;
53
55
  evaluation_time_ms?: number;
54
56
  matched_rule_id?: string;
@@ -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 = 66;
6539
+ var HOOK_VERSION = 67;
6540
6540
  function localLogsOnly(security) {
6541
6541
  if (security && typeof security === "object") {
6542
6542
  const l = security.localLogs;
@@ -6557,8 +6557,18 @@ function writeLocalMarker(security) {
6557
6557
  } catch {
6558
6558
  }
6559
6559
  }
6560
+ function accountMark() {
6561
+ try {
6562
+ return API_KEY ? createHash("sha256").update(API_KEY).digest("hex").slice(0, 16) : "";
6563
+ } catch {
6564
+ return "";
6565
+ }
6566
+ }
6560
6567
  function writeLocalLog(security, entry) {
6561
6568
  try {
6569
+ const mark = accountMark();
6570
+ if (mark)
6571
+ entry = { ...entry, acct: mark };
6562
6572
  const l = security && security.localLogs;
6563
6573
  if (!l || !l.enabled || typeof l.path !== "string" || !l.path.trim()) {
6564
6574
  if (!localLogsOnly(security))
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 = 66;
35
+ const HOOK_VERSION = 67;
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.
@@ -96,8 +96,26 @@ function resolveLocalLogDir(rawPath) {
96
96
  // Local log storage (opt-in): write solongate-audit.jsonl inside the user's
97
97
  // chosen FOLDER. The audit hook does the ALLOW path; the guard does DENY (a
98
98
  // blocked call never reaches PostToolUse). `security` is the resolved config.
99
+ /**
100
+ * Short, non-reversible mark of the account an entry belongs to.
101
+ *
102
+ * The machine-local log is one file, and nothing in a line said which account
103
+ * produced it, so after pairing a different account the viewers presented the
104
+ * previous one's calls as yours. Stamping each line lets a reader keep only its
105
+ * own without deleting anybody's history. It is a hash prefix, never the key.
106
+ */
107
+ function accountMark() {
108
+ try {
109
+ return API_KEY ? createHash('sha256').update(API_KEY).digest('hex').slice(0, 16) : '';
110
+ } catch {
111
+ return '';
112
+ }
113
+ }
114
+
99
115
  function writeLocalLog(security, entry) {
100
116
  try {
117
+ const mark = accountMark();
118
+ if (mark) entry = { ...entry, acct: mark };
101
119
  const l = security && security.localLogs;
102
120
  // The cloud POST is skipped whenever localLogsOnly() says this device is in
103
121
  // local-only mode — and that answer can come from the persisted marker alone,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@solongate/proxy",
3
- "version": "0.82.91",
3
+ "version": "0.82.93",
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": {