@solongate/proxy 0.82.96 → 0.82.98

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/dist/index.js CHANGED
@@ -11407,7 +11407,26 @@ var init_doctor = __esm({
11407
11407
  import { Box as Box8, Text as Text8, useInput as useInput7 } from "ink";
11408
11408
  import TextInput6 from "ink-text-input";
11409
11409
  import { useEffect as useEffect7, useRef as useRef3, useState as useState8 } from "react";
11410
+ import { readFileSync as readFileSync11, readdirSync as readdirSync2 } from "fs";
11411
+ import { homedir as homedir11 } from "os";
11412
+ import { join as join13 } from "path";
11410
11413
  import { Fragment as Fragment5, jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
11414
+ function guestAllowance() {
11415
+ try {
11416
+ const dir = join13(homedir11(), ".solongate");
11417
+ for (const f of readdirSync2(dir)) {
11418
+ if (!f.startsWith(".policy-cache-") || !f.endsWith(".json")) continue;
11419
+ try {
11420
+ const c2 = JSON.parse(readFileSync11(join13(dir, f), "utf-8"));
11421
+ const q = c2?.security?.guestQuota;
11422
+ if (q && typeof q.limit === "number") return { used: q.used ?? 0, limit: q.limit };
11423
+ } catch {
11424
+ }
11425
+ }
11426
+ } catch {
11427
+ }
11428
+ return null;
11429
+ }
11411
11430
  function SettingsPanel({
11412
11431
  active: active2,
11413
11432
  focused,
@@ -11443,6 +11462,7 @@ function SettingsPanel({
11443
11462
  const step = setInterval(() => setDiagStep((s) => Math.min(s + 1, total - 1)), 220);
11444
11463
  return () => clearInterval(step);
11445
11464
  }, [diagBusy]);
11465
+ void guestAllowance;
11446
11466
  const ver = currentVersion();
11447
11467
  useEffect7(() => {
11448
11468
  let live2 = true;
@@ -11965,6 +11985,15 @@ function SettingsPanel({
11965
11985
  cursor(r),
11966
11986
  /* @__PURE__ */ jsx8(Text8, { color: theme.dim, children: "+ add account (enter \u2014 device login in the browser)" })
11967
11987
  ] });
11988
+ case "allowance": {
11989
+ const left = Math.max(0, r.limit - r.used);
11990
+ return /* @__PURE__ */ jsxs8(Text8, { wrap: "truncate", children: [
11991
+ cursor(r),
11992
+ /* @__PURE__ */ jsx8(Text8, { color: theme.dim, children: "allowance".padEnd(11) }),
11993
+ /* @__PURE__ */ jsx8(Text8, { color: left === 0 ? theme.bad : left <= 20 ? theme.warn : theme.ok, bold: true, children: `${r.used}/${r.limit} tool calls` }),
11994
+ /* @__PURE__ */ jsx8(Text8, { color: theme.dim, children: left === 0 ? " used up \u2014 every call is denied \xB7 create an account to carry on" : ` ${left} left on this guest account \xB7 create an account for no limit` })
11995
+ ] });
11996
+ }
11968
11997
  case "guard":
11969
11998
  return /* @__PURE__ */ jsxs8(Text8, { wrap: "truncate", children: [
11970
11999
  cursor(r),
@@ -12051,7 +12080,7 @@ function SettingsPanel({
12051
12080
  ] });
12052
12081
  }
12053
12082
  };
12054
- const sectionOf = (r) => r.kind === "acct" || r.kind === "acct-add" ? "ACCOUNTS" : r.kind === "guard" || r.kind === "self" || r.kind === "doctor" || r.kind === "repair" ? "PROTECTION" : r.kind === "ll-enabled" || r.kind === "ll-path" || r.kind === "ll-server" ? "LOCAL LOGS" : r.kind === "wh" || r.kind === "wh-add" ? "WEBHOOKS" : "ALERTS";
12083
+ const sectionOf = (r) => r.kind === "acct" || r.kind === "acct-add" || r.kind === "allowance" ? "ACCOUNTS" : r.kind === "guard" || r.kind === "self" || r.kind === "doctor" || r.kind === "repair" ? "PROTECTION" : r.kind === "ll-enabled" || r.kind === "ll-path" || r.kind === "ll-server" ? "LOCAL LOGS" : r.kind === "wh" || r.kind === "wh-add" ? "WEBHOOKS" : "ALERTS";
12055
12084
  const SECTION_DESC = {
12056
12085
  ACCOUNTS: `on this device (${accounts.length}) \xB7 \u25CF viewing \xB7 ACTIVE = guard key \xB7 x removes`,
12057
12086
  PROTECTION: "guard hook: enter install/update \xB7 d remove \xB7 self-protection \xB7 doctor + repair",
@@ -12409,8 +12438,8 @@ __export(tui_exports, {
12409
12438
  launchTui: () => launchTui
12410
12439
  });
12411
12440
  import { appendFileSync as appendFileSync2, mkdirSync as mkdirSync9 } from "fs";
12412
- import { homedir as homedir11 } from "os";
12413
- import { join as join13 } from "path";
12441
+ import { homedir as homedir12 } from "os";
12442
+ import { join as join14 } from "path";
12414
12443
  import { render } from "ink";
12415
12444
  import { jsx as jsx10 } from "react/jsx-runtime";
12416
12445
  async function launchTui() {
@@ -12421,11 +12450,11 @@ async function launchTui() {
12421
12450
  return;
12422
12451
  }
12423
12452
  process.stdout.write("\x1B[?1049h\x1B[H");
12424
- const debugLog = join13(homedir11(), ".solongate", "dataroom-debug.log");
12453
+ const debugLog = join14(homedir12(), ".solongate", "dataroom-debug.log");
12425
12454
  const saved = { log: console.log, warn: console.warn, error: console.error, info: console.info, debug: console.debug };
12426
12455
  const toFile = (level) => (...args) => {
12427
12456
  try {
12428
- mkdirSync9(join13(homedir11(), ".solongate"), { recursive: true });
12457
+ mkdirSync9(join14(homedir12(), ".solongate"), { recursive: true });
12429
12458
  appendFileSync2(debugLog, `${(/* @__PURE__ */ new Date()).toISOString()} [${level}] ${args.map((a) => typeof a === "string" ? a : JSON.stringify(a)).join(" ")}
12430
12459
  `);
12431
12460
  } catch {
@@ -12452,7 +12481,7 @@ var init_tui = __esm({
12452
12481
  });
12453
12482
 
12454
12483
  // src/commands/policy.ts
12455
- import { readFileSync as readFileSync11 } from "fs";
12484
+ import { readFileSync as readFileSync12 } from "fs";
12456
12485
  async function run2(argv) {
12457
12486
  const { positionals, flags } = parse(argv);
12458
12487
  const sub = positionals[0];
@@ -12609,7 +12638,7 @@ function printRules(rules) {
12609
12638
  }
12610
12639
  async function resolveRules(target) {
12611
12640
  if (target.endsWith(".json")) {
12612
- const parsed = JSON.parse(readFileSync11(target, "utf-8"));
12641
+ const parsed = JSON.parse(readFileSync12(target, "utf-8"));
12613
12642
  return parsed.rules ?? [];
12614
12643
  }
12615
12644
  const p = await api.policies.get(target);
@@ -13323,10 +13352,10 @@ __export(logs_server_exports, {
13323
13352
  runLogsServer: () => runLogsServer
13324
13353
  });
13325
13354
  import { createServer } from "http";
13326
- import { readFileSync as readFileSync12, statSync as statSync4 } from "fs";
13327
- import { resolve as resolve5, join as join14, isAbsolute as isAbsolute2 } from "path";
13328
- import { homedir as homedir12 } from "os";
13329
- import { readdirSync as readdirSync2 } from "fs";
13355
+ import { readFileSync as readFileSync13, statSync as statSync4 } from "fs";
13356
+ import { resolve as resolve5, join as join15, isAbsolute as isAbsolute2 } from "path";
13357
+ import { homedir as homedir13 } from "os";
13358
+ import { readdirSync as readdirSync3 } from "fs";
13330
13359
  function allowedOrigins() {
13331
13360
  const base = [
13332
13361
  "https://dashboard.solongate.com",
@@ -13342,15 +13371,15 @@ function resolveLocalLogDir(rawPath) {
13342
13371
  const dir = String(rawPath || "").trim().replace(/[\\/]+$/, "");
13343
13372
  if (!dir) return null;
13344
13373
  if (isAbsolute2(dir)) return dir;
13345
- return resolve5(homedir12(), ".solongate", "local-logs");
13374
+ return resolve5(homedir13(), ".solongate", "local-logs");
13346
13375
  }
13347
13376
  async function findLogDir() {
13348
- const base = resolve5(homedir12(), ".solongate");
13377
+ const base = resolve5(homedir13(), ".solongate");
13349
13378
  try {
13350
- const files = readdirSync2(base).filter((f) => f.startsWith(".policy-cache-") && f.endsWith(".json"));
13379
+ const files = readdirSync3(base).filter((f) => f.startsWith(".policy-cache-") && f.endsWith(".json"));
13351
13380
  for (const f of files) {
13352
13381
  try {
13353
- const c2 = JSON.parse(readFileSync12(join14(base, f), "utf-8"));
13382
+ const c2 = JSON.parse(readFileSync13(join15(base, f), "utf-8"));
13354
13383
  const p = c2?.security?.localLogs?.path;
13355
13384
  if (typeof p === "string" && p.trim()) return { dir: resolveLocalLogDir(p), configured: p };
13356
13385
  } catch {
@@ -13359,7 +13388,7 @@ async function findLogDir() {
13359
13388
  } catch {
13360
13389
  }
13361
13390
  try {
13362
- const cfgRaw = readFileSync12(join14(base, "cloud-guard.json"), "utf-8");
13391
+ const cfgRaw = readFileSync13(join15(base, "cloud-guard.json"), "utf-8");
13363
13392
  const { apiKey, apiUrl } = JSON.parse(cfgRaw);
13364
13393
  if (apiKey) {
13365
13394
  const url = `${apiUrl || "https://api.solongate.com"}/api/v1/policies/active`;
@@ -13388,7 +13417,7 @@ function setCors(req, res) {
13388
13417
  }
13389
13418
  function fileInfo(dir) {
13390
13419
  if (!dir) return { file: null, exists: false, size: 0, mtimeMs: 0 };
13391
- const file = join14(dir, LOG_FILENAME);
13420
+ const file = join15(dir, LOG_FILENAME);
13392
13421
  try {
13393
13422
  const st = statSync4(file);
13394
13423
  return { file, exists: true, size: st.size, mtimeMs: st.mtimeMs };
@@ -13471,7 +13500,7 @@ async function runLogsServer() {
13471
13500
  return;
13472
13501
  }
13473
13502
  try {
13474
- const text = readFileSync12(info.file, "utf-8");
13503
+ const text = readFileSync13(info.file, "utf-8");
13475
13504
  res.writeHead(200, { "Content-Type": "text/plain; charset=utf-8", "Last-Modified": lastMod, "X-Solongate-Exists": "1" });
13476
13505
  res.end(text);
13477
13506
  } catch {
@@ -13524,9 +13553,9 @@ var init_logs_server = __esm({
13524
13553
  });
13525
13554
 
13526
13555
  // src/index.ts
13527
- import { readFileSync as readFileSync13 } from "fs";
13556
+ import { readFileSync as readFileSync14 } from "fs";
13528
13557
  import { fileURLToPath as fileURLToPath4 } from "url";
13529
- import { dirname as dirname4, join as join15 } from "path";
13558
+ import { dirname as dirname4, join as join16 } from "path";
13530
13559
 
13531
13560
  // src/config.ts
13532
13561
  import { readFileSync, existsSync } from "fs";
@@ -16921,8 +16950,8 @@ if (!IS_HUMAN_CLI) {
16921
16950
  }
16922
16951
  var PKG_VERSION = (() => {
16923
16952
  try {
16924
- const p = join15(dirname4(fileURLToPath4(import.meta.url)), "..", "package.json");
16925
- return JSON.parse(readFileSync13(p, "utf-8")).version || "unknown";
16953
+ const p = join16(dirname4(fileURLToPath4(import.meta.url)), "..", "package.json");
16954
+ return JSON.parse(readFileSync14(p, "utf-8")).version || "unknown";
16926
16955
  } catch {
16927
16956
  return "unknown";
16928
16957
  }
package/dist/tui/index.js CHANGED
@@ -530,8 +530,8 @@ var init_global_install = __esm({
530
530
 
531
531
  // src/tui/index.tsx
532
532
  import { appendFileSync, mkdirSync as mkdirSync7 } from "fs";
533
- import { homedir as homedir10 } from "os";
534
- import { join as join10 } from "path";
533
+ import { homedir as homedir11 } from "os";
534
+ import { join as join11 } from "path";
535
535
  import { render } from "ink";
536
536
 
537
537
  // src/tui/App.tsx
@@ -4587,7 +4587,26 @@ async function tuiUpdateFlow(onStatus) {
4587
4587
  }
4588
4588
 
4589
4589
  // src/tui/panels/Settings.tsx
4590
+ import { readFileSync as readFileSync8, readdirSync as readdirSync2 } from "fs";
4591
+ import { homedir as homedir10 } from "os";
4592
+ import { join as join10 } from "path";
4590
4593
  import { Fragment as Fragment5, jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
4594
+ function guestAllowance() {
4595
+ try {
4596
+ const dir = join10(homedir10(), ".solongate");
4597
+ for (const f of readdirSync2(dir)) {
4598
+ if (!f.startsWith(".policy-cache-") || !f.endsWith(".json")) continue;
4599
+ try {
4600
+ const c2 = JSON.parse(readFileSync8(join10(dir, f), "utf-8"));
4601
+ const q = c2?.security?.guestQuota;
4602
+ if (q && typeof q.limit === "number") return { used: q.used ?? 0, limit: q.limit };
4603
+ } catch {
4604
+ }
4605
+ }
4606
+ } catch {
4607
+ }
4608
+ return null;
4609
+ }
4591
4610
  var EVENTS = ["denials", "allowed", "all"];
4592
4611
  var SPIN2 = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
4593
4612
  var SIGNALS2 = ["any", "deny", "dlp", "ratelimit"];
@@ -4639,6 +4658,7 @@ function SettingsPanel({
4639
4658
  const step = setInterval(() => setDiagStep((s) => Math.min(s + 1, total - 1)), 220);
4640
4659
  return () => clearInterval(step);
4641
4660
  }, [diagBusy]);
4661
+ void guestAllowance;
4642
4662
  const ver = currentVersion();
4643
4663
  useEffect7(() => {
4644
4664
  let live2 = true;
@@ -5161,6 +5181,15 @@ function SettingsPanel({
5161
5181
  cursor(r),
5162
5182
  /* @__PURE__ */ jsx8(Text8, { color: theme.dim, children: "+ add account (enter \u2014 device login in the browser)" })
5163
5183
  ] });
5184
+ case "allowance": {
5185
+ const left = Math.max(0, r.limit - r.used);
5186
+ return /* @__PURE__ */ jsxs8(Text8, { wrap: "truncate", children: [
5187
+ cursor(r),
5188
+ /* @__PURE__ */ jsx8(Text8, { color: theme.dim, children: "allowance".padEnd(11) }),
5189
+ /* @__PURE__ */ jsx8(Text8, { color: left === 0 ? theme.bad : left <= 20 ? theme.warn : theme.ok, bold: true, children: `${r.used}/${r.limit} tool calls` }),
5190
+ /* @__PURE__ */ jsx8(Text8, { color: theme.dim, children: left === 0 ? " used up \u2014 every call is denied \xB7 create an account to carry on" : ` ${left} left on this guest account \xB7 create an account for no limit` })
5191
+ ] });
5192
+ }
5164
5193
  case "guard":
5165
5194
  return /* @__PURE__ */ jsxs8(Text8, { wrap: "truncate", children: [
5166
5195
  cursor(r),
@@ -5247,7 +5276,7 @@ function SettingsPanel({
5247
5276
  ] });
5248
5277
  }
5249
5278
  };
5250
- const sectionOf = (r) => r.kind === "acct" || r.kind === "acct-add" ? "ACCOUNTS" : r.kind === "guard" || r.kind === "self" || r.kind === "doctor" || r.kind === "repair" ? "PROTECTION" : r.kind === "ll-enabled" || r.kind === "ll-path" || r.kind === "ll-server" ? "LOCAL LOGS" : r.kind === "wh" || r.kind === "wh-add" ? "WEBHOOKS" : "ALERTS";
5279
+ const sectionOf = (r) => r.kind === "acct" || r.kind === "acct-add" || r.kind === "allowance" ? "ACCOUNTS" : r.kind === "guard" || r.kind === "self" || r.kind === "doctor" || r.kind === "repair" ? "PROTECTION" : r.kind === "ll-enabled" || r.kind === "ll-path" || r.kind === "ll-server" ? "LOCAL LOGS" : r.kind === "wh" || r.kind === "wh-add" ? "WEBHOOKS" : "ALERTS";
5251
5280
  const SECTION_DESC = {
5252
5281
  ACCOUNTS: `on this device (${accounts.length}) \xB7 \u25CF viewing \xB7 ACTIVE = guard key \xB7 x removes`,
5253
5282
  PROTECTION: "guard hook: enter install/update \xB7 d remove \xB7 self-protection \xB7 doctor + repair",
@@ -5552,11 +5581,11 @@ async function launchTui() {
5552
5581
  return;
5553
5582
  }
5554
5583
  process.stdout.write("\x1B[?1049h\x1B[H");
5555
- const debugLog = join10(homedir10(), ".solongate", "dataroom-debug.log");
5584
+ const debugLog = join11(homedir11(), ".solongate", "dataroom-debug.log");
5556
5585
  const saved = { log: console.log, warn: console.warn, error: console.error, info: console.info, debug: console.debug };
5557
5586
  const toFile = (level) => (...args) => {
5558
5587
  try {
5559
- mkdirSync7(join10(homedir10(), ".solongate"), { recursive: true });
5588
+ mkdirSync7(join11(homedir11(), ".solongate"), { recursive: true });
5560
5589
  appendFileSync(debugLog, `${(/* @__PURE__ */ new Date()).toISOString()} [${level}] ${args.map((a) => typeof a === "string" ? a : JSON.stringify(a)).join(" ")}
5561
5590
  `);
5562
5591
  } catch {
@@ -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 = 68;
6539
+ var HOOK_VERSION = 69;
6540
6540
  function localLogsOnly(security) {
6541
6541
  if (security && typeof security === "object") {
6542
6542
  const l = security.localLogs;
@@ -7957,7 +7957,7 @@ function securityLayerCheck(toolName, args, cfg, agentKey) {
7957
7957
  try {
7958
7958
  const q = cfg.guestQuota;
7959
7959
  if (q && q.exhausted) {
7960
- return `Guest allowance used up (${q.limit} tool calls). Create an account at https://auth.solongate.com to carry on \u2014 your project, its policy and everything recorded carry over, and this device keeps working. To stop guarding this machine instead: solongate \u2192 Settings \u2192 guard \u2192 d.`;
7960
+ return `Guest allowance used up (${q.limit} tool calls). Create an account at https://auth.solongate.com to carry on. Your project, its policy and everything recorded carry over, and this device keeps working. To stop guarding this machine instead: solongate, Settings, guard, then press d.`;
7961
7961
  }
7962
7962
  if (cfg.dlpBlock) {
7963
7963
  const hit = dlpScan(args, cfg.dlpBlock);
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 = 68;
35
+ const HOOK_VERSION = 69;
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.
@@ -1772,7 +1772,7 @@ function securityLayerCheck(toolName, args, cfg, agentKey) {
1772
1772
  // call through after the allowance is gone.
1773
1773
  const q = cfg.guestQuota;
1774
1774
  if (q && q.exhausted) {
1775
- return `Guest allowance used up (${q.limit} tool calls). Create an account at https://auth.solongate.com to carry on your project, its policy and everything recorded carry over, and this device keeps working. To stop guarding this machine instead: solongate Settings guard d.`;
1775
+ return `Guest allowance used up (${q.limit} tool calls). Create an account at https://auth.solongate.com to carry on. Your project, its policy and everything recorded carry over, and this device keeps working. To stop guarding this machine instead: solongate, Settings, guard, then press d.`;
1776
1776
  }
1777
1777
  if (cfg.dlpBlock) {
1778
1778
  const hit = dlpScan(args, cfg.dlpBlock);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@solongate/proxy",
3
- "version": "0.82.96",
3
+ "version": "0.82.98",
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": {