@solongate/proxy 0.82.19 → 0.82.21

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
@@ -3398,12 +3398,12 @@ ${ctx.indent}`;
3398
3398
  for (const {
3399
3399
  format,
3400
3400
  test,
3401
- resolve: resolve10
3401
+ resolve: resolve9
3402
3402
  } of tags) {
3403
3403
  if (test) {
3404
3404
  const match = str.match(test);
3405
3405
  if (match) {
3406
- let res = resolve10.apply(null, match);
3406
+ let res = resolve9.apply(null, match);
3407
3407
  if (!(res instanceof Scalar)) res = new Scalar(res);
3408
3408
  if (format) res.format = format;
3409
3409
  return res;
@@ -6622,9 +6622,9 @@ async function fetchLatest() {
6622
6622
  function spawnGlobalInstall(version) {
6623
6623
  try {
6624
6624
  mkdirSync3(join4(homedir2(), ".solongate"), { recursive: true });
6625
- const log6 = openSync(LOG_FILE, "a");
6625
+ const log5 = openSync(LOG_FILE, "a");
6626
6626
  const p = spawn("npm", ["install", "-g", `${PKG}@${version}`], {
6627
- stdio: ["ignore", log6, log6],
6627
+ stdio: ["ignore", log5, log5],
6628
6628
  detached: true,
6629
6629
  windowsHide: true,
6630
6630
  shell: process.platform === "win32"
@@ -6638,7 +6638,7 @@ function spawnGlobalInstall(version) {
6638
6638
  }
6639
6639
  }
6640
6640
  function runGlobalInstall(version) {
6641
- return new Promise((resolve10) => {
6641
+ return new Promise((resolve9) => {
6642
6642
  try {
6643
6643
  mkdirSync3(join4(homedir2(), ".solongate"), { recursive: true });
6644
6644
  execFile(
@@ -6653,11 +6653,11 @@ ${stderr}
6653
6653
  `, { flag: "a" });
6654
6654
  } catch {
6655
6655
  }
6656
- resolve10(!err2);
6656
+ resolve9(!err2);
6657
6657
  }
6658
6658
  );
6659
6659
  } catch {
6660
- resolve10(false);
6660
+ resolve9(false);
6661
6661
  }
6662
6662
  });
6663
6663
  }
@@ -6772,11 +6772,11 @@ function startLogsServerDaemon() {
6772
6772
  }
6773
6773
  try {
6774
6774
  mkdirSync4(DIR, { recursive: true });
6775
- const log6 = openSync2(LOG_FILE2, "a");
6775
+ const log5 = openSync2(LOG_FILE2, "a");
6776
6776
  const cli = join5(dirname2(fileURLToPath2(import.meta.url)), "index.js");
6777
6777
  const p = spawn2(process.execPath, [cli, "logs-server"], {
6778
6778
  detached: true,
6779
- stdio: ["ignore", log6, log6],
6779
+ stdio: ["ignore", log5, log5],
6780
6780
  windowsHide: true
6781
6781
  });
6782
6782
  p.on("error", () => {
@@ -7854,7 +7854,7 @@ function LivePanel({ active: active2 }) {
7854
7854
  const [localBuf, setLocalBuf] = useState2([]);
7855
7855
  const [localOn, setLocalOn] = useState2(null);
7856
7856
  const [ring, setRing] = useState2(null);
7857
- const [log6, setLog] = useState2([]);
7857
+ const [log5, setLog] = useState2([]);
7858
7858
  const [filter, setFilter] = useState2("all");
7859
7859
  const [signal, setSignal] = useState2("none");
7860
7860
  const [search, setSearch] = useState2("");
@@ -8698,7 +8698,7 @@ function LivePanel({ active: active2 }) {
8698
8698
  ] }),
8699
8699
  /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", width: colW, overflow: "hidden", children: [
8700
8700
  /* @__PURE__ */ jsx2(PaneTitle, { label: "EVENT LOG", extra: "system heartbeat", width: colW }),
8701
- log6.slice(-(colH - 1)).map((l, i) => /* @__PURE__ */ jsxs2(Text2, { wrap: "truncate", children: [
8701
+ log5.slice(-(colH - 1)).map((l, i) => /* @__PURE__ */ jsxs2(Text2, { wrap: "truncate", children: [
8702
8702
  /* @__PURE__ */ jsxs2(Text2, { color: theme.dim, children: [
8703
8703
  hhmmss(l.ts),
8704
8704
  " "
@@ -9635,7 +9635,7 @@ function AuditPanel({ active: active2, focused }) {
9635
9635
  const sessLoading = source === "cloud" ? agentsQ.loading : localQ.loading;
9636
9636
  const doDelete = (kind) => {
9637
9637
  setMsg({ text: "deleting\u2026", level: "ok" });
9638
- const run12 = async () => {
9638
+ const run10 = async () => {
9639
9639
  if (source === "cloud") {
9640
9640
  if (kind === "one") {
9641
9641
  if (!current) throw new Error("nothing selected");
@@ -9651,14 +9651,14 @@ function AuditPanel({ active: active2, focused }) {
9651
9651
  localQ.reload();
9652
9652
  }
9653
9653
  };
9654
- run12().then(() => {
9654
+ run10().then(() => {
9655
9655
  setMsg({ text: kind === "one" ? "\u2713 entry deleted" : `\u2713 ALL ${source} logs deleted`, level: "ok" });
9656
9656
  toTop();
9657
9657
  }).catch((e) => setMsg({ text: "\u2717 " + (e instanceof Error ? e.message : String(e)), level: "bad" }));
9658
9658
  };
9659
9659
  const doExport = (kind) => {
9660
9660
  setMsg({ text: "exporting\u2026", level: "ok" });
9661
- const run12 = async () => {
9661
+ const run10 = async () => {
9662
9662
  const dir = join10(homedir8(), ".solongate");
9663
9663
  const file = join10(dir, `audit-export-${source}.jsonl`);
9664
9664
  let rows2;
@@ -9671,7 +9671,7 @@ function AuditPanel({ active: active2, focused }) {
9671
9671
  writeFileSync8(file, rows2.map((x) => JSON.stringify(x)).join("\n") + (rows2.length ? "\n" : ""));
9672
9672
  return { n: rows2.length, file };
9673
9673
  };
9674
- run12().then(({ n, file }) => setMsg({ text: `\u2713 exported ${n} rows \u2192 ${file}`, level: "ok" })).catch((e) => setMsg({ text: "\u2717 export failed: " + (e instanceof Error ? e.message : String(e)), level: "bad" }));
9674
+ run10().then(({ n, file }) => setMsg({ text: `\u2713 exported ${n} rows \u2192 ${file}`, level: "ok" })).catch((e) => setMsg({ text: "\u2717 export failed: " + (e instanceof Error ? e.message : String(e)), level: "bad" }));
9675
9675
  };
9676
9676
  useInput5(
9677
9677
  (input, key) => {
@@ -10554,7 +10554,7 @@ function SettingsPanel({
10554
10554
  guardQ.reload();
10555
10555
  selfQ.reload();
10556
10556
  };
10557
- const run12 = (label, fn, reload) => {
10557
+ const run10 = (label, fn, reload) => {
10558
10558
  if (busy) return;
10559
10559
  setBusy(true);
10560
10560
  setMsg({ text: label + "\u2026", level: "ok" });
@@ -10636,8 +10636,8 @@ function SettingsPanel({
10636
10636
  const body = { signal: editor.signal, threshold: editor.threshold, windowSeconds: editor.windowSeconds, enabled: editor.enabled, ...channels };
10637
10637
  const id = editor.id;
10638
10638
  setEditor(null);
10639
- if (id) run12("alert updated", () => api.settings.updateAlert(id, body), alertQ.reload);
10640
- else run12(`${editor.channel} alert added`, () => api.settings.createAlert({ name: "SolonGate alert", ...body }), alertQ.reload);
10639
+ if (id) run10("alert updated", () => api.settings.updateAlert(id, body), alertQ.reload);
10640
+ else run10(`${editor.channel} alert added`, () => api.settings.createAlert({ name: "SolonGate alert", ...body }), alertQ.reload);
10641
10641
  };
10642
10642
  const activate = (r) => {
10643
10643
  if (r.kind === "acct") {
@@ -10653,14 +10653,14 @@ function SettingsPanel({
10653
10653
  guardQ.reload();
10654
10654
  } else if (r.kind === "self") {
10655
10655
  if (!selfProt) return;
10656
- run12(selfProt.enabled ? "self-protection disabled" : "self-protection enabled", () => api.settings.setSelfProtection(!selfProt.enabled), selfQ.reload);
10656
+ run10(selfProt.enabled ? "self-protection disabled" : "self-protection enabled", () => api.settings.setSelfProtection(!selfProt.enabled), selfQ.reload);
10657
10657
  } else if (r.kind === "ll-enabled") {
10658
10658
  if (!local) return;
10659
10659
  if (!local.enabled && !local.path.trim()) {
10660
10660
  setMsg({ text: "set a path first (\u2193 then enter)", level: "bad" });
10661
10661
  return;
10662
10662
  }
10663
- run12(local.enabled ? "local logs disabled" : "local logs enabled", () => api.settings.setLocalLogs({ enabled: !local.enabled, path: local.path }), localQ.reload);
10663
+ run10(local.enabled ? "local logs disabled" : "local logs enabled", () => api.settings.setLocalLogs({ enabled: !local.enabled, path: local.path }), localQ.reload);
10664
10664
  } else if (r.kind === "ll-path") {
10665
10665
  setInput(local?.path ?? "");
10666
10666
  setEditing("path");
@@ -10671,7 +10671,7 @@ function SettingsPanel({
10671
10671
  next.running ? { text: `\u2713 dashboard link running on 127.0.0.1:${next.port} \u2014 keeps running after you close the dataroom`, level: "ok" } : { text: "\u2713 dashboard link stopped (disabled until you start it again)", level: "ok" }
10672
10672
  );
10673
10673
  } else if (r.kind === "wh") {
10674
- run12(r.wh.enabled ? "webhook disabled" : "webhook enabled", () => api.settings.updateWebhook(r.wh.id, { enabled: !r.wh.enabled }), whQ.reload);
10674
+ run10(r.wh.enabled ? "webhook disabled" : "webhook enabled", () => api.settings.updateWebhook(r.wh.id, { enabled: !r.wh.enabled }), whQ.reload);
10675
10675
  } else if (r.kind === "wh-add") {
10676
10676
  setInput("");
10677
10677
  setEditing("wh-url");
@@ -10690,7 +10690,7 @@ function SettingsPanel({
10690
10690
  setEditing(null);
10691
10691
  if (which === "path") {
10692
10692
  const enabled = (local?.enabled ?? false) && v.length > 0;
10693
- run12(v ? `path saved${enabled ? "" : " (press enter on enabled to turn on)"}` : "path cleared (local logs off)", () => api.settings.setLocalLogs({ enabled, path: v }), localQ.reload);
10693
+ run10(v ? `path saved${enabled ? "" : " (press enter on enabled to turn on)"}` : "path cleared (local logs off)", () => api.settings.setLocalLogs({ enabled, path: v }), localQ.reload);
10694
10694
  } else if (which === "wh-url") {
10695
10695
  const url = v.replace(/^["'<]+|["'>]+$/g, "").trim();
10696
10696
  if (!url) return;
@@ -10698,7 +10698,7 @@ function SettingsPanel({
10698
10698
  setMsg({ text: "\u2717 webhook url must start with http:// or https://", level: "bad" });
10699
10699
  return;
10700
10700
  }
10701
- run12("webhook added", () => api.settings.createWebhook({ url, events: "denials" }), whQ.reload);
10701
+ run10("webhook added", () => api.settings.createWebhook({ url, events: "denials" }), whQ.reload);
10702
10702
  } else if (which === "alert-target" && editor) {
10703
10703
  setEditor({ ...editor, target: v, field: 1 });
10704
10704
  }
@@ -10752,7 +10752,7 @@ function SettingsPanel({
10752
10752
  setMsg(ok ? { text: `\u2713 ${acctLabel(cur.acc)} is now the ACTIVE key (guard + logging)`, level: "ok" } : { text: "\u2717 could not set active", level: "bad" });
10753
10753
  refreshAccounts();
10754
10754
  } else if (cur.kind === "wh" || cur.kind === "alert" || cur.kind === "self" || cur.kind === "ll-enabled" || cur.kind === "ll-server") {
10755
- if (cur.kind === "alert") run12(cur.rule.enabled ? "alert disabled" : "alert enabled", () => api.settings.setAlertEnabled(cur.rule.id, !cur.rule.enabled), alertQ.reload);
10755
+ if (cur.kind === "alert") run10(cur.rule.enabled ? "alert disabled" : "alert enabled", () => api.settings.setAlertEnabled(cur.rule.id, !cur.rule.enabled), alertQ.reload);
10756
10756
  else activate(cur);
10757
10757
  }
10758
10758
  } else if (inp === "x" && cur.kind === "acct") {
@@ -10782,13 +10782,13 @@ function SettingsPanel({
10782
10782
  refreshAccounts();
10783
10783
  onAccountsChanged?.();
10784
10784
  } else if (inp === "t" && cur.kind === "wh") {
10785
- run12("webhook test sent \u2014 check your endpoint", () => api.settings.sendTestWebhook(cur.wh.id).then((r) => {
10785
+ run10("webhook test sent \u2014 check your endpoint", () => api.settings.sendTestWebhook(cur.wh.id).then((r) => {
10786
10786
  if (!r.delivered) throw new Error("endpoint rejected the test (non-2xx)");
10787
10787
  }), whQ.reload);
10788
10788
  } else if (inp === "e" && cur.kind === "ll-path") activate(cur);
10789
10789
  else if (inp === "e" && cur.kind === "wh") {
10790
10790
  const next = EVENTS[(EVENTS.indexOf(cur.wh.events) + 1) % EVENTS.length];
10791
- run12(`webhook events \u2192 ${next}`, () => api.settings.updateWebhook(cur.wh.id, { events: next }), whQ.reload);
10791
+ run10(`webhook events \u2192 ${next}`, () => api.settings.updateWebhook(cur.wh.id, { events: next }), whQ.reload);
10792
10792
  } else if (inp === "e" && cur.kind === "alert") {
10793
10793
  const ch = alertChannel(cur.rule);
10794
10794
  if (ch) openAlertEditor(ch, cur.rule);
@@ -10825,10 +10825,10 @@ function SettingsPanel({
10825
10825
  setConfirmDel(null);
10826
10826
  if (cur.kind === "wh") {
10827
10827
  const id = cur.wh.id;
10828
- run12("webhook deleted", () => api.settings.deleteWebhook(id).then(() => setHidden((h) => new Set(h).add("wh:" + id))), whQ.reload);
10828
+ run10("webhook deleted", () => api.settings.deleteWebhook(id).then(() => setHidden((h) => new Set(h).add("wh:" + id))), whQ.reload);
10829
10829
  } else {
10830
10830
  const id = cur.rule.id;
10831
- run12("alert deleted", () => api.settings.deleteAlert(id).then(() => setHidden((h) => new Set(h).add("alert:" + id))), alertQ.reload);
10831
+ run10("alert deleted", () => api.settings.deleteAlert(id).then(() => setHidden((h) => new Set(h).add("alert:" + id))), alertQ.reload);
10832
10832
  }
10833
10833
  } else if (inp === "r") reloadAll();
10834
10834
  },
@@ -11128,9 +11128,9 @@ function App() {
11128
11128
  const [update2, setUpdate] = useState8({ kind: "idle" });
11129
11129
  useEffect7(() => {
11130
11130
  let alive = true;
11131
- const run12 = () => void tuiUpdateFlow((s) => alive && setUpdate(s));
11132
- run12();
11133
- const t = setInterval(run12, 30 * 6e4);
11131
+ const run10 = () => void tuiUpdateFlow((s) => alive && setUpdate(s));
11132
+ run10();
11133
+ const t = setInterval(run10, 30 * 6e4);
11134
11134
  return () => {
11135
11135
  alive = false;
11136
11136
  clearInterval(t);
@@ -12204,7 +12204,7 @@ var init_watch = __esm({
12204
12204
  }
12205
12205
  });
12206
12206
 
12207
- // src/commands/keys.ts
12207
+ // src/commands/alerts.ts
12208
12208
  async function run8(argv) {
12209
12209
  const { positionals, flags } = parse(argv);
12210
12210
  const sub = positionals[0] ?? "list";
@@ -12212,89 +12212,6 @@ async function run8(argv) {
12212
12212
  switch (sub) {
12213
12213
  case "help":
12214
12214
  return err(USAGE6), 0;
12215
- case "list": {
12216
- const { keys } = await api.keys.list();
12217
- if (json) return printJson(keys), 0;
12218
- if (!keys.length) return err(dim(" No API keys.")), 0;
12219
- table(
12220
- ["ID", "NAME", "PREFIX", "CREATED"],
12221
- keys.map((k) => [dim(truncate3(k.id, 10)), truncate3(k.name, 24), cyan(k.key_prefix), dim(k.created_at)])
12222
- );
12223
- return 0;
12224
- }
12225
- case "create": {
12226
- const name = flagStr(flags, "name");
12227
- if (!name) return err(" Usage: keys create --name <name>"), 1;
12228
- const res = await api.keys.create(name, !flagBool(flags, "test"));
12229
- if (json) return printJson(res), 0;
12230
- err(green(` \u2713 Created "${res.name}"`));
12231
- err("");
12232
- err(" " + bold(res.key));
12233
- err(dim(" \u2191 shown only once \u2014 copy it now."));
12234
- return 0;
12235
- }
12236
- case "revoke": {
12237
- const id = positionals[1];
12238
- if (!id) return err(" Usage: keys revoke <id>"), 1;
12239
- await api.keys.revoke(id);
12240
- if (json) return printJson({ ok: true, id }), 0;
12241
- return err(green(` \u2713 Revoked ${id}`)), 0;
12242
- }
12243
- default:
12244
- return err(USAGE6), 1;
12245
- }
12246
- }
12247
- var USAGE6;
12248
- var init_keys2 = __esm({
12249
- "src/commands/keys.ts"() {
12250
- "use strict";
12251
- init_api_client();
12252
- init_args();
12253
- init_format();
12254
- USAGE6 = `${bold("solongate keys")} \u2014 API keys
12255
-
12256
- keys list List keys (prefix only)
12257
- keys create --name <n> Create a key (secret shown once)
12258
- keys revoke <id> Revoke a key
12259
-
12260
- Add --json for machine-readable output.`;
12261
- }
12262
- });
12263
-
12264
- // src/commands/mcp.ts
12265
- async function run9(argv) {
12266
- const { flags } = parse(argv);
12267
- const json = flagBool(flags, "json");
12268
- const { servers } = await api.mcp.list();
12269
- if (json) return printJson(servers), 0;
12270
- if (!servers.length) return err(dim(" No MCP servers registered.")), 0;
12271
- table(
12272
- ["STATUS", "NAME", "TARGET"],
12273
- servers.map((s) => [
12274
- s.status === "active" ? green(s.status) : yellow(s.status),
12275
- cyan(truncate3(s.name, 24)),
12276
- dim(truncate3(s.url || s.command || "\u2014", 46))
12277
- ])
12278
- );
12279
- return 0;
12280
- }
12281
- var init_mcp2 = __esm({
12282
- "src/commands/mcp.ts"() {
12283
- "use strict";
12284
- init_api_client();
12285
- init_args();
12286
- init_format();
12287
- }
12288
- });
12289
-
12290
- // src/commands/alerts.ts
12291
- async function run10(argv) {
12292
- const { positionals, flags } = parse(argv);
12293
- const sub = positionals[0] ?? "list";
12294
- const json = flagBool(flags, "json");
12295
- switch (sub) {
12296
- case "help":
12297
- return err(USAGE7), 0;
12298
12215
  case "list": {
12299
12216
  const { rules } = await api.settings.getAlerts();
12300
12217
  if (json) return printJson(rules), 0;
@@ -12336,17 +12253,17 @@ async function run10(argv) {
12336
12253
  return err(green(` \u2713 Removed ${id}`)), 0;
12337
12254
  }
12338
12255
  default:
12339
- return err(USAGE7), 1;
12256
+ return err(USAGE6), 1;
12340
12257
  }
12341
12258
  }
12342
- var USAGE7;
12259
+ var USAGE6;
12343
12260
  var init_alerts = __esm({
12344
12261
  "src/commands/alerts.ts"() {
12345
12262
  "use strict";
12346
12263
  init_api_client();
12347
12264
  init_args();
12348
12265
  init_format();
12349
- USAGE7 = `${bold("solongate alerts")} \u2014 spike alerts (Telegram / email)
12266
+ USAGE6 = `${bold("solongate alerts")} \u2014 spike alerts (Telegram / email)
12350
12267
 
12351
12268
  alerts list
12352
12269
  alerts add --signal deny|dlp|ratelimit|any --threshold N --window S
@@ -12358,13 +12275,13 @@ var init_alerts = __esm({
12358
12275
  });
12359
12276
 
12360
12277
  // src/commands/webhooks.ts
12361
- async function run11(argv) {
12278
+ async function run9(argv) {
12362
12279
  const { positionals, flags } = parse(argv);
12363
12280
  const sub = positionals[0] ?? "list";
12364
12281
  const json = flagBool(flags, "json");
12365
12282
  switch (sub) {
12366
12283
  case "help":
12367
- return err(USAGE8), 0;
12284
+ return err(USAGE7), 0;
12368
12285
  case "list": {
12369
12286
  const { webhooks } = await api.settings.getWebhooks();
12370
12287
  if (json) return printJson(webhooks), 0;
@@ -12390,17 +12307,17 @@ async function run11(argv) {
12390
12307
  return err(green(` \u2713 Removed ${id}`)), 0;
12391
12308
  }
12392
12309
  default:
12393
- return err(USAGE8), 1;
12310
+ return err(USAGE7), 1;
12394
12311
  }
12395
12312
  }
12396
- var USAGE8;
12313
+ var USAGE7;
12397
12314
  var init_webhooks = __esm({
12398
12315
  "src/commands/webhooks.ts"() {
12399
12316
  "use strict";
12400
12317
  init_api_client();
12401
12318
  init_args();
12402
12319
  init_format();
12403
- USAGE8 = `${bold("solongate webhooks")} \u2014 event webhooks
12320
+ USAGE7 = `${bold("solongate webhooks")} \u2014 event webhooks
12404
12321
 
12405
12322
  webhooks list
12406
12323
  webhooks add --url <https://\u2026> [--events denials|allowed|all]
@@ -12436,14 +12353,10 @@ async function dispatch(command, argv) {
12436
12353
  return run6(argv);
12437
12354
  case "watch":
12438
12355
  return run7(argv);
12439
- case "keys":
12440
- return run8(argv);
12441
- case "mcp":
12442
- return run9(argv);
12443
12356
  case "alerts":
12444
- return run10(argv);
12357
+ return run8(argv);
12445
12358
  case "webhooks":
12446
- return run11(argv);
12359
+ return run9(argv);
12447
12360
  default:
12448
12361
  err(` Unknown command: ${command}`);
12449
12362
  return 1;
@@ -12480,333 +12393,9 @@ var init_commands = __esm({
12480
12393
  init_agents2();
12481
12394
  init_doctor();
12482
12395
  init_watch();
12483
- init_keys2();
12484
- init_mcp2();
12485
12396
  init_alerts();
12486
12397
  init_webhooks();
12487
- COMMAND_NAMES = ["policy", "ratelimit", "dlp", "stats", "audit", "agents", "agent", "doctor", "watch", "keys", "mcp", "alerts", "webhooks"];
12488
- }
12489
- });
12490
-
12491
- // src/shield.ts
12492
- var shield_exports = {};
12493
- __export(shield_exports, {
12494
- runShield: () => runShield
12495
- });
12496
- import { createServer, request as httpRequest } from "http";
12497
- import { request as httpsRequest } from "https";
12498
- import { spawn as spawn5 } from "child_process";
12499
- import { URL as URL2 } from "url";
12500
- import { readFileSync as readFileSync11, existsSync as existsSync7, readdirSync, statSync as statSync4 } from "fs";
12501
- import { resolve as resolve5 } from "path";
12502
- import { homedir as homedir13 } from "os";
12503
- function findCacheFile() {
12504
- const dir = resolve5(homedir13(), ".solongate");
12505
- const envSel = process.env.SOLONGATE_AGENT_ID;
12506
- if (envSel) {
12507
- const f = resolve5(dir, ".policy-cache-" + envSel.replace(/[^a-zA-Z0-9_-]/g, "_") + ".json");
12508
- if (existsSync7(f)) return f;
12509
- }
12510
- let best = null, bestTs = -1;
12511
- try {
12512
- for (const name of readdirSync(dir)) {
12513
- if (name.startsWith(".policy-cache-") && name.endsWith(".json")) {
12514
- const full = resolve5(dir, name);
12515
- const ts = statSync4(full).mtimeMs;
12516
- if (ts > bestTs) {
12517
- bestTs = ts;
12518
- best = full;
12519
- }
12520
- }
12521
- }
12522
- } catch {
12523
- }
12524
- return best;
12525
- }
12526
- function loadCfg() {
12527
- try {
12528
- const f = findCacheFile();
12529
- if (f && existsSync7(f)) {
12530
- const c2 = JSON.parse(readFileSync11(f, "utf-8"));
12531
- const d = c2?.security?.dlpRedact;
12532
- const g = c2?.security?.ghost;
12533
- const ghost = g && Array.isArray(g.patterns) ? g.patterns : [];
12534
- if (d && Array.isArray(d.patterns)) return { patterns: d.patterns, custom: Array.isArray(d.custom) ? d.custom : [], ghost };
12535
- return { patterns: DLP_PATTERNS.map((p) => p.name), custom: [], ghost };
12536
- }
12537
- } catch {
12538
- }
12539
- return { patterns: DLP_PATTERNS.map((p) => p.name), custom: [], ghost: [] };
12540
- }
12541
- function ghostGlobToRegExp(glob) {
12542
- let re = "";
12543
- for (let i = 0; i < glob.length; i++) {
12544
- const c2 = glob[i];
12545
- if (c2 === "*") {
12546
- if (glob[i + 1] === "*") {
12547
- re += ".*";
12548
- i++;
12549
- } else re += "[^/]*";
12550
- } else if (c2 === "?") re += "[^/]";
12551
- else if ("\\^$.|+()[]{}".indexOf(c2) !== -1) re += "\\" + c2;
12552
- else re += c2;
12553
- }
12554
- try {
12555
- return new RegExp("^" + re + "$");
12556
- } catch {
12557
- return null;
12558
- }
12559
- }
12560
- function ghostMatch(targetPath, patterns) {
12561
- if (!targetPath || !Array.isArray(patterns) || patterns.length === 0) return false;
12562
- const norm = String(targetPath).replace(/\\/g, "/").replace(/\/+$/, "");
12563
- if (!norm) return false;
12564
- const segments = norm.split("/").filter(Boolean);
12565
- const base = segments.length ? segments[segments.length - 1] : norm;
12566
- for (let pat of patterns) {
12567
- pat = String(pat || "").trim();
12568
- if (!pat) continue;
12569
- let dirOnly = false;
12570
- if (pat.endsWith("/")) {
12571
- dirOnly = true;
12572
- pat = pat.slice(0, -1);
12573
- }
12574
- if (!pat) continue;
12575
- const hasSlash = pat.indexOf("/") !== -1;
12576
- const hasWild = /[*?]/.test(pat);
12577
- const re = ghostGlobToRegExp(pat);
12578
- if (!re) continue;
12579
- if (dirOnly) {
12580
- if (!hasSlash && !hasWild) {
12581
- if (segments.indexOf(pat) !== -1) return true;
12582
- continue;
12583
- }
12584
- let acc = "";
12585
- for (const s of segments) {
12586
- acc = acc ? acc + "/" + s : s;
12587
- if (re.test(acc) || re.test(s)) return true;
12588
- }
12589
- continue;
12590
- }
12591
- if (!hasSlash) {
12592
- if (re.test(base)) return true;
12593
- if (segments.some((s) => re.test(s))) return true;
12594
- continue;
12595
- }
12596
- if (re.test(norm)) return true;
12597
- }
12598
- return false;
12599
- }
12600
- function ghostCleanToken(tok) {
12601
- let t = String(tok || "").trim();
12602
- t = t.replace(/^[<>|;&(]+/, "").replace(/[);&|]+$/, "");
12603
- t = t.replace(/^['"]+/, "").replace(/['"]+$/, "");
12604
- t = t.replace(/^\d*>>?/, "");
12605
- return t.trim();
12606
- }
12607
- function ghostStripLines(text, pats) {
12608
- if (!Array.isArray(pats) || pats.length === 0) return text;
12609
- const lines = String(text).split("\n");
12610
- const kept = [];
12611
- for (const line of lines) {
12612
- const trimmed = line.trim();
12613
- if (!trimmed) {
12614
- kept.push(line);
12615
- continue;
12616
- }
12617
- if (ghostMatch(trimmed, pats)) continue;
12618
- const toks = trimmed.split(/\s+/);
12619
- const anyHit = toks.some((t) => ghostMatch(ghostCleanToken(t), pats));
12620
- if (!anyHit) {
12621
- kept.push(line);
12622
- continue;
12623
- }
12624
- if (toks.length > 3) continue;
12625
- const remaining = toks.filter((t) => !ghostMatch(ghostCleanToken(t), pats));
12626
- if (remaining.length === 0) continue;
12627
- kept.push(remaining.join(" "));
12628
- }
12629
- return kept.join("\n");
12630
- }
12631
- function dlpGlobToRe(glob, flags) {
12632
- let re = "";
12633
- for (const ch of String(glob || "")) {
12634
- if (ch === "*") re += "[^\\s]*";
12635
- else if (".+?^${}()|[]\\".indexOf(ch) !== -1) re += "\\" + ch;
12636
- else re += ch;
12637
- }
12638
- return new RegExp(re, flags);
12639
- }
12640
- function redactString(s, cfg) {
12641
- if (!cfg || typeof s !== "string" || !s) return s;
12642
- const allow = new Set(cfg.patterns);
12643
- const NUL = String.fromCharCode(0);
12644
- const labels = [];
12645
- const stash = (label) => NUL + (labels.push(label) - 1) + NUL;
12646
- let out2 = s;
12647
- for (const p of DLP_PATTERNS) if (allow.has(p.name)) out2 = out2.replace(p.re, () => stash(`[REDACTED: ${p.name}]`));
12648
- for (const c2 of cfg.custom) {
12649
- try {
12650
- out2 = out2.replace(dlpGlobToRe(c2.re, "gi"), () => stash(`[REDACTED: ${c2.name || "custom"}]`));
12651
- } catch {
12652
- }
12653
- }
12654
- return out2.replace(new RegExp(NUL + "(\\d+)" + NUL, "g"), (_, i) => labels[+i] || "");
12655
- }
12656
- function redactDeep(value, cfg) {
12657
- const ghost = cfg && Array.isArray(cfg.ghost) ? cfg.ghost : null;
12658
- if (typeof value === "string") {
12659
- let out2 = redactString(value, cfg);
12660
- if (ghost && ghost.length) out2 = ghostStripLines(out2, ghost);
12661
- if (out2 === "" && value !== "") out2 = "\n";
12662
- return out2;
12663
- }
12664
- if (Array.isArray(value)) {
12665
- const arr = ghost && ghost.length ? value.filter((v) => !(typeof v === "string" && ghostMatch(v.trim(), ghost))) : value;
12666
- return arr.map((v) => redactDeep(v, cfg));
12667
- }
12668
- if (value && typeof value === "object") {
12669
- const out2 = {};
12670
- for (const [k, v] of Object.entries(value)) out2[k] = redactDeep(v, cfg);
12671
- return out2;
12672
- }
12673
- return value;
12674
- }
12675
- function pickUpstream() {
12676
- const raw = process.env.SOLONGATE_SHIELD_UPSTREAM || process.env.ANTHROPIC_BASE_URL || "https://api.anthropic.com";
12677
- try {
12678
- return new URL2(raw);
12679
- } catch {
12680
- return new URL2("https://api.anthropic.com");
12681
- }
12682
- }
12683
- function startProxy(upstream) {
12684
- const forward = upstream.protocol === "https:" ? httpsRequest : httpRequest;
12685
- const server = createServer((req, res) => {
12686
- const cfg = loadCfg();
12687
- const chunks = [];
12688
- req.on("data", (c2) => chunks.push(c2));
12689
- req.on("end", () => {
12690
- let body = Buffer.concat(chunks);
12691
- try {
12692
- if (body.length && (req.headers["content-type"] || "").includes("json")) {
12693
- const parsed = JSON.parse(body.toString("utf-8"));
12694
- if (parsed && typeof parsed === "object" && Array.isArray(parsed["messages"])) {
12695
- if (parsed["system"] !== void 0) parsed["system"] = redactDeep(parsed["system"], cfg);
12696
- const msgs = parsed["messages"];
12697
- for (let i = 0; i < msgs.length; i++) {
12698
- const m = msgs[i];
12699
- if (m && m["role"] !== "assistant") msgs[i] = redactDeep(m, cfg);
12700
- }
12701
- body = Buffer.from(JSON.stringify(parsed), "utf-8");
12702
- } else {
12703
- body = Buffer.from(JSON.stringify(redactDeep(parsed, cfg)), "utf-8");
12704
- }
12705
- }
12706
- } catch {
12707
- }
12708
- const headers = { ...req.headers };
12709
- delete headers["host"];
12710
- delete headers["content-length"];
12711
- delete headers["accept-encoding"];
12712
- headers["content-length"] = String(body.length);
12713
- const upstreamReq = forward(
12714
- {
12715
- protocol: upstream.protocol,
12716
- hostname: upstream.hostname,
12717
- port: upstream.port || (upstream.protocol === "https:" ? 443 : 80),
12718
- method: req.method,
12719
- path: req.url,
12720
- headers: { ...headers, host: upstream.host }
12721
- },
12722
- (upRes) => {
12723
- res.writeHead(upRes.statusCode || 502, upRes.headers);
12724
- upRes.pipe(res);
12725
- }
12726
- );
12727
- upstreamReq.on("error", (e) => {
12728
- log4("upstream error:", e.message);
12729
- if (!res.headersSent) res.writeHead(502, { "content-type": "text/plain" });
12730
- res.end("shield upstream error");
12731
- });
12732
- upstreamReq.end(body);
12733
- });
12734
- req.on("error", () => {
12735
- try {
12736
- res.destroy();
12737
- } catch {
12738
- }
12739
- });
12740
- });
12741
- return new Promise((resolveP) => {
12742
- server.listen(0, "127.0.0.1", () => {
12743
- const addr = server.address();
12744
- const port = typeof addr === "object" && addr ? addr.port : 0;
12745
- resolveP({ port, close: () => server.close() });
12746
- });
12747
- });
12748
- }
12749
- async function runShield() {
12750
- const sep = process.argv.indexOf("--");
12751
- const cmd = sep !== -1 ? process.argv.slice(sep + 1) : [];
12752
- if (cmd.length === 0) {
12753
- log4("usage: npx @solongate/proxy shield -- <command> [args...] (e.g. shield -- claude)");
12754
- process.exit(1);
12755
- }
12756
- const upstream = pickUpstream();
12757
- const { port, close } = await startProxy(upstream);
12758
- log4(`redacting secrets on the LLM path \u2192 masking before ${upstream.host} (127.0.0.1:${port})`);
12759
- const child = spawn5(cmd[0], cmd.slice(1), {
12760
- stdio: "inherit",
12761
- env: { ...process.env, ANTHROPIC_BASE_URL: `http://127.0.0.1:${port}` },
12762
- shell: process.platform === "win32"
12763
- // resolve `claude.cmd` etc. on Windows
12764
- });
12765
- const shutdown = () => {
12766
- try {
12767
- close();
12768
- } catch {
12769
- }
12770
- };
12771
- child.on("exit", (code, signal) => {
12772
- shutdown();
12773
- if (signal) process.kill(process.pid, signal);
12774
- else process.exit(code ?? 0);
12775
- });
12776
- child.on("error", (e) => {
12777
- log4("failed to launch command:", e.message);
12778
- shutdown();
12779
- process.exit(1);
12780
- });
12781
- for (const sig of ["SIGINT", "SIGTERM"]) process.on(sig, () => {
12782
- try {
12783
- child.kill(sig);
12784
- } catch {
12785
- }
12786
- });
12787
- }
12788
- var log4, DLP_PATTERNS;
12789
- var init_shield = __esm({
12790
- "src/shield.ts"() {
12791
- "use strict";
12792
- log4 = (...a) => process.stderr.write(`[SolonGate shield] ${a.map(String).join(" ")}
12793
- `);
12794
- DLP_PATTERNS = [
12795
- { name: "AWS access key", re: /AKIA[0-9A-Z]{16}/g },
12796
- { name: "Private key block", re: /-----BEGIN [A-Z ]*PRIVATE KEY-----[\s\S]*?-----END [A-Z ]*PRIVATE KEY-----|-----BEGIN [A-Z ]*PRIVATE KEY-----/g },
12797
- { name: "Anthropic key", re: /sk-ant-[A-Za-z0-9_-]{20,}/g },
12798
- { name: "OpenAI key", re: /sk-(proj-)?[A-Za-z0-9_-]{20,}/g },
12799
- { name: "GitHub token", re: /gh[pousr]_[A-Za-z0-9]{20,}/g },
12800
- { name: "GitHub fine-grained PAT", re: /github_pat_[A-Za-z0-9_]{20,}/g },
12801
- { name: "GitLab token", re: /glpat-[A-Za-z0-9_-]{20,}/g },
12802
- { name: "Slack token", re: /xox[baprs]-[A-Za-z0-9-]{10,}/g },
12803
- { name: "Stripe key", re: /[sr]k_(live|test)_[A-Za-z0-9]{20,}/g },
12804
- { name: "SendGrid key", re: /SG\.[A-Za-z0-9_-]{16,}\.[A-Za-z0-9_-]{16,}/g },
12805
- { name: "Twilio key", re: /SK[0-9a-fA-F]{32}/g },
12806
- { name: "npm token", re: /npm_[A-Za-z0-9]{36}/g },
12807
- { name: "JWT", re: /eyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}/g },
12808
- { name: "Bearer token", re: /bearer\s+[A-Za-z0-9._-]{20,}/gi }
12809
- ];
12398
+ COMMAND_NAMES = ["policy", "ratelimit", "dlp", "stats", "audit", "agents", "agent", "doctor", "watch", "alerts", "webhooks"];
12810
12399
  }
12811
12400
  });
12812
12401
 
@@ -12815,11 +12404,11 @@ var logs_server_exports = {};
12815
12404
  __export(logs_server_exports, {
12816
12405
  runLogsServer: () => runLogsServer
12817
12406
  });
12818
- import { createServer as createServer2 } from "http";
12819
- import { readFileSync as readFileSync12, statSync as statSync5 } from "fs";
12820
- import { resolve as resolve6, join as join15, isAbsolute } from "path";
12821
- import { homedir as homedir14 } from "os";
12822
- import { readdirSync as readdirSync2 } from "fs";
12407
+ import { createServer } from "http";
12408
+ import { readFileSync as readFileSync11, statSync as statSync4 } from "fs";
12409
+ import { resolve as resolve5, join as join15, isAbsolute } from "path";
12410
+ import { homedir as homedir13 } from "os";
12411
+ import { readdirSync } from "fs";
12823
12412
  function allowedOrigins() {
12824
12413
  const base = [
12825
12414
  "https://dashboard.solongate.com",
@@ -12835,15 +12424,15 @@ function resolveLocalLogDir(rawPath) {
12835
12424
  const dir = String(rawPath || "").trim().replace(/[\\/]+$/, "");
12836
12425
  if (!dir) return null;
12837
12426
  if (isAbsolute(dir)) return dir;
12838
- return resolve6(homedir14(), ".solongate", "local-logs");
12427
+ return resolve5(homedir13(), ".solongate", "local-logs");
12839
12428
  }
12840
12429
  async function findLogDir() {
12841
- const base = resolve6(homedir14(), ".solongate");
12430
+ const base = resolve5(homedir13(), ".solongate");
12842
12431
  try {
12843
- const files = readdirSync2(base).filter((f) => f.startsWith(".policy-cache-") && f.endsWith(".json"));
12432
+ const files = readdirSync(base).filter((f) => f.startsWith(".policy-cache-") && f.endsWith(".json"));
12844
12433
  for (const f of files) {
12845
12434
  try {
12846
- const c2 = JSON.parse(readFileSync12(join15(base, f), "utf-8"));
12435
+ const c2 = JSON.parse(readFileSync11(join15(base, f), "utf-8"));
12847
12436
  const p = c2?.security?.localLogs?.path;
12848
12437
  if (typeof p === "string" && p.trim()) return { dir: resolveLocalLogDir(p), configured: p };
12849
12438
  } catch {
@@ -12852,7 +12441,7 @@ async function findLogDir() {
12852
12441
  } catch {
12853
12442
  }
12854
12443
  try {
12855
- const cfgRaw = readFileSync12(join15(base, "cloud-guard.json"), "utf-8");
12444
+ const cfgRaw = readFileSync11(join15(base, "cloud-guard.json"), "utf-8");
12856
12445
  const { apiKey, apiUrl } = JSON.parse(cfgRaw);
12857
12446
  if (apiKey) {
12858
12447
  const url = `${apiUrl || "https://api.solongate.com"}/api/v1/policies/active`;
@@ -12883,7 +12472,7 @@ function fileInfo(dir) {
12883
12472
  if (!dir) return { file: null, exists: false, size: 0, mtimeMs: 0 };
12884
12473
  const file = join15(dir, LOG_FILENAME);
12885
12474
  try {
12886
- const st = statSync5(file);
12475
+ const st = statSync4(file);
12887
12476
  return { file, exists: true, size: st.size, mtimeMs: st.mtimeMs };
12888
12477
  } catch {
12889
12478
  return { file, exists: false, size: 0, mtimeMs: 0 };
@@ -12915,7 +12504,7 @@ async function runLogsServer() {
12915
12504
  }
12916
12505
  const portArg = argv[argv.indexOf("--port") + 1];
12917
12506
  const port = Number(process.env.SOLONGATE_LOGS_PORT || (argv.includes("--port") ? portArg : "") || DEFAULT_PORT) || DEFAULT_PORT;
12918
- const server = createServer2(async (req, res) => {
12507
+ const server = createServer(async (req, res) => {
12919
12508
  setCors(req, res);
12920
12509
  if (req.method === "OPTIONS") {
12921
12510
  res.writeHead(204);
@@ -12964,7 +12553,7 @@ async function runLogsServer() {
12964
12553
  return;
12965
12554
  }
12966
12555
  try {
12967
- const text = readFileSync12(info.file, "utf-8");
12556
+ const text = readFileSync11(info.file, "utf-8");
12968
12557
  res.writeHead(200, { "Content-Type": "text/plain; charset=utf-8", "Last-Modified": lastMod, "X-Solongate-Exists": "1" });
12969
12558
  res.end(text);
12970
12559
  } catch {
@@ -13018,8 +12607,8 @@ var init_logs_server = __esm({
13018
12607
 
13019
12608
  // src/inject.ts
13020
12609
  var inject_exports = {};
13021
- import { readFileSync as readFileSync13, writeFileSync as writeFileSync10, existsSync as existsSync8, copyFileSync } from "fs";
13022
- import { resolve as resolve7 } from "path";
12610
+ import { readFileSync as readFileSync12, writeFileSync as writeFileSync10, existsSync as existsSync7, copyFileSync } from "fs";
12611
+ import { resolve as resolve6 } from "path";
13023
12612
  import { execSync } from "child_process";
13024
12613
  function parseInjectArgs(argv) {
13025
12614
  const args = argv.slice(2);
@@ -13076,9 +12665,9 @@ WHAT IT DOES
13076
12665
  `);
13077
12666
  }
13078
12667
  function detectProject() {
13079
- if (!existsSync8(resolve7("package.json"))) return false;
12668
+ if (!existsSync7(resolve6("package.json"))) return false;
13080
12669
  try {
13081
- const pkg = JSON.parse(readFileSync13(resolve7("package.json"), "utf-8"));
12670
+ const pkg = JSON.parse(readFileSync12(resolve6("package.json"), "utf-8"));
13082
12671
  const allDeps = { ...pkg.dependencies, ...pkg.devDependencies };
13083
12672
  return !!(allDeps["@modelcontextprotocol/sdk"] || allDeps["@modelcontextprotocol/server"]);
13084
12673
  } catch {
@@ -13087,18 +12676,18 @@ function detectProject() {
13087
12676
  }
13088
12677
  function findTsEntryFile() {
13089
12678
  try {
13090
- const pkg = JSON.parse(readFileSync13(resolve7("package.json"), "utf-8"));
12679
+ const pkg = JSON.parse(readFileSync12(resolve6("package.json"), "utf-8"));
13091
12680
  if (pkg.bin) {
13092
12681
  const binPath = typeof pkg.bin === "string" ? pkg.bin : Object.values(pkg.bin)[0];
13093
12682
  if (typeof binPath === "string") {
13094
12683
  const srcPath = binPath.replace(/^\.\/dist\//, "./src/").replace(/\.js$/, ".ts");
13095
- if (existsSync8(resolve7(srcPath))) return resolve7(srcPath);
13096
- if (existsSync8(resolve7(binPath))) return resolve7(binPath);
12684
+ if (existsSync7(resolve6(srcPath))) return resolve6(srcPath);
12685
+ if (existsSync7(resolve6(binPath))) return resolve6(binPath);
13097
12686
  }
13098
12687
  }
13099
12688
  if (pkg.main) {
13100
12689
  const srcPath = pkg.main.replace(/^\.\/dist\//, "./src/").replace(/\.js$/, ".ts");
13101
- if (existsSync8(resolve7(srcPath))) return resolve7(srcPath);
12690
+ if (existsSync7(resolve6(srcPath))) return resolve6(srcPath);
13102
12691
  }
13103
12692
  } catch {
13104
12693
  }
@@ -13111,10 +12700,10 @@ function findTsEntryFile() {
13111
12700
  "main.ts"
13112
12701
  ];
13113
12702
  for (const c2 of candidates) {
13114
- const full = resolve7(c2);
13115
- if (existsSync8(full)) {
12703
+ const full = resolve6(c2);
12704
+ if (existsSync7(full)) {
13116
12705
  try {
13117
- const content = readFileSync13(full, "utf-8");
12706
+ const content = readFileSync12(full, "utf-8");
13118
12707
  if (content.includes("McpServer") || content.includes("McpServer")) {
13119
12708
  return full;
13120
12709
  }
@@ -13123,18 +12712,18 @@ function findTsEntryFile() {
13123
12712
  }
13124
12713
  }
13125
12714
  for (const c2 of candidates) {
13126
- if (existsSync8(resolve7(c2))) return resolve7(c2);
12715
+ if (existsSync7(resolve6(c2))) return resolve6(c2);
13127
12716
  }
13128
12717
  return null;
13129
12718
  }
13130
12719
  function detectPackageManager() {
13131
- if (existsSync8(resolve7("pnpm-lock.yaml"))) return "pnpm";
13132
- if (existsSync8(resolve7("yarn.lock"))) return "yarn";
12720
+ if (existsSync7(resolve6("pnpm-lock.yaml"))) return "pnpm";
12721
+ if (existsSync7(resolve6("yarn.lock"))) return "yarn";
13133
12722
  return "npm";
13134
12723
  }
13135
12724
  function installSdk() {
13136
12725
  try {
13137
- const pkg = JSON.parse(readFileSync13(resolve7("package.json"), "utf-8"));
12726
+ const pkg = JSON.parse(readFileSync12(resolve6("package.json"), "utf-8"));
13138
12727
  const allDeps = { ...pkg.dependencies, ...pkg.devDependencies };
13139
12728
  if (allDeps["@solongate/proxy"]) {
13140
12729
  log3(" @solongate/proxy already installed");
@@ -13155,7 +12744,7 @@ function installSdk() {
13155
12744
  }
13156
12745
  }
13157
12746
  function injectTypeScript(filePath) {
13158
- const original = readFileSync13(filePath, "utf-8");
12747
+ const original = readFileSync12(filePath, "utf-8");
13159
12748
  const changes = [];
13160
12749
  let modified = original;
13161
12750
  if (modified.includes("SecureMcpServer")) {
@@ -13271,8 +12860,8 @@ async function main() {
13271
12860
  process.exit(1);
13272
12861
  }
13273
12862
  log3(" Language: TypeScript");
13274
- const entryFile = opts.file ? resolve7(opts.file) : findTsEntryFile();
13275
- if (!entryFile || !existsSync8(entryFile)) {
12863
+ const entryFile = opts.file ? resolve6(opts.file) : findTsEntryFile();
12864
+ if (!entryFile || !existsSync7(entryFile)) {
13276
12865
  log3(` Could not find entry file.${opts.file ? ` File not found: ${opts.file}` : ""}`);
13277
12866
  log3("");
13278
12867
  log3(" Specify it manually: --file <path>");
@@ -13285,7 +12874,7 @@ async function main() {
13285
12874
  log3("");
13286
12875
  const backupPath = entryFile + ".solongate-backup";
13287
12876
  if (opts.restore) {
13288
- if (!existsSync8(backupPath)) {
12877
+ if (!existsSync7(backupPath)) {
13289
12878
  log3(" No backup found. Nothing to restore.");
13290
12879
  process.exit(1);
13291
12880
  }
@@ -13321,7 +12910,7 @@ async function main() {
13321
12910
  log3(" To apply: npx @solongate/proxy inject");
13322
12911
  process.exit(0);
13323
12912
  }
13324
- if (!existsSync8(backupPath)) {
12913
+ if (!existsSync7(backupPath)) {
13325
12914
  copyFileSync(entryFile, backupPath);
13326
12915
  log3("");
13327
12916
  log3(` Backup: ${backupPath}`);
@@ -13355,8 +12944,8 @@ var init_inject = __esm({
13355
12944
 
13356
12945
  // src/create.ts
13357
12946
  var create_exports = {};
13358
- import { mkdirSync as mkdirSync10, writeFileSync as writeFileSync11, existsSync as existsSync9 } from "fs";
13359
- import { resolve as resolve8, join as join16 } from "path";
12947
+ import { mkdirSync as mkdirSync10, writeFileSync as writeFileSync11, existsSync as existsSync8 } from "fs";
12948
+ import { resolve as resolve7, join as join16 } from "path";
13360
12949
  import { execSync as execSync2 } from "child_process";
13361
12950
  function withSpinner(message, fn) {
13362
12951
  const frames = ["\u28FE", "\u28FD", "\u28FB", "\u28BF", "\u287F", "\u28DF", "\u28EF", "\u28F7"];
@@ -13565,9 +13154,9 @@ dist/
13565
13154
  }
13566
13155
  async function main2() {
13567
13156
  const opts = parseCreateArgs(process.argv);
13568
- const dir = resolve8(opts.name);
13157
+ const dir = resolve7(opts.name);
13569
13158
  printBanner("Create MCP Server");
13570
- if (existsSync9(dir)) {
13159
+ if (existsSync8(dir)) {
13571
13160
  log3(` ${c.red}Error:${c.reset} Directory "${opts.name}" already exists.`);
13572
13161
  process.exit(1);
13573
13162
  }
@@ -13646,14 +13235,14 @@ var init_create = __esm({
13646
13235
 
13647
13236
  // src/pull-push.ts
13648
13237
  var pull_push_exports = {};
13649
- import { readFileSync as readFileSync14, writeFileSync as writeFileSync12, existsSync as existsSync10 } from "fs";
13650
- import { resolve as resolve9 } from "path";
13238
+ import { readFileSync as readFileSync13, writeFileSync as writeFileSync12, existsSync as existsSync9 } from "fs";
13239
+ import { resolve as resolve8 } from "path";
13651
13240
  function loadEnv() {
13652
13241
  if (process.env.SOLONGATE_API_KEY) return;
13653
- const envPath = resolve9(".env");
13654
- if (!existsSync10(envPath)) return;
13242
+ const envPath = resolve8(".env");
13243
+ if (!existsSync9(envPath)) return;
13655
13244
  try {
13656
- const content = readFileSync14(envPath, "utf-8");
13245
+ const content = readFileSync13(envPath, "utf-8");
13657
13246
  for (const line of content.split("\n")) {
13658
13247
  const trimmed = line.trim();
13659
13248
  if (!trimmed || trimmed.startsWith("#")) continue;
@@ -13695,20 +13284,20 @@ function parseCliArgs() {
13695
13284
  }
13696
13285
  }
13697
13286
  if (!apiKey) {
13698
- log5(red2("ERROR: API key not found."));
13699
- log5("");
13700
- log5("Set it in .env file:");
13701
- log5(" SOLONGATE_API_KEY=sg_live_...");
13702
- log5("");
13703
- log5("Or pass via environment:");
13704
- log5(` SOLONGATE_API_KEY=sg_live_... solongate-proxy ${command}`);
13287
+ log4(red2("ERROR: API key not found."));
13288
+ log4("");
13289
+ log4("Set it in .env file:");
13290
+ log4(" SOLONGATE_API_KEY=sg_live_...");
13291
+ log4("");
13292
+ log4("Or pass via environment:");
13293
+ log4(` SOLONGATE_API_KEY=sg_live_... solongate-proxy ${command}`);
13705
13294
  process.exit(1);
13706
13295
  }
13707
13296
  if (!apiKey.startsWith("sg_live_")) {
13708
- log5(red2("ERROR: Pull/push/list requires a live API key (sg_live_...)."));
13297
+ log4(red2("ERROR: Pull/push/list requires a live API key (sg_live_...)."));
13709
13298
  process.exit(1);
13710
13299
  }
13711
- return { command, apiKey, file: resolve9(file), policyId };
13300
+ return { command, apiKey, file: resolve8(file), policyId };
13712
13301
  }
13713
13302
  async function listPolicies(apiKey) {
13714
13303
  const res = await fetch(`${API_URL}/api/v1/policies`, {
@@ -13721,18 +13310,18 @@ async function listPolicies(apiKey) {
13721
13310
  async function list5(apiKey, policyId) {
13722
13311
  const policies = await listPolicies(apiKey);
13723
13312
  if (policies.length === 0) {
13724
- log5(yellow2("No policies found. Create one in the dashboard first."));
13725
- log5(dim2(" https://dashboard.solongate.com/policies"));
13313
+ log4(yellow2("No policies found. Create one in the dashboard first."));
13314
+ log4(dim2(" https://dashboard.solongate.com/policies"));
13726
13315
  return;
13727
13316
  }
13728
13317
  if (policyId) {
13729
13318
  const match = policies.find((p) => p.id === policyId);
13730
13319
  if (!match) {
13731
- log5(red2(`Policy not found: ${policyId}`));
13732
- log5("");
13733
- log5("Available policies:");
13320
+ log4(red2(`Policy not found: ${policyId}`));
13321
+ log4("");
13322
+ log4("Available policies:");
13734
13323
  for (const p of policies) {
13735
- log5(` ${dim2("\u2022")} ${p.id}`);
13324
+ log4(` ${dim2("\u2022")} ${p.id}`);
13736
13325
  }
13737
13326
  process.exit(1);
13738
13327
  }
@@ -13740,10 +13329,10 @@ async function list5(apiKey, policyId) {
13740
13329
  printPolicyDetail(full);
13741
13330
  return;
13742
13331
  }
13743
- log5("");
13744
- log5(bold2(` Policies (${policies.length})`));
13745
- log5(dim2(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
13746
- log5("");
13332
+ log4("");
13333
+ log4(bold2(` Policies (${policies.length})`));
13334
+ log4(dim2(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
13335
+ log4("");
13747
13336
  const fullPolicies = await Promise.all(
13748
13337
  policies.map(
13749
13338
  (p) => fetchCloudPolicy(apiKey, API_URL, p.id).then((full) => ({ policy: p, rules: full.rules })).catch(() => ({ policy: p, rules: [] }))
@@ -13752,136 +13341,136 @@ async function list5(apiKey, policyId) {
13752
13341
  for (const { policy, rules } of fullPolicies) {
13753
13342
  printPolicySummary(policy, [...rules]);
13754
13343
  }
13755
- log5(dim2(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
13756
- log5("");
13757
- log5(` ${dim2("View details:")} solongate-proxy list --policy-id <ID>`);
13758
- log5(` ${dim2("Pull policy:")} solongate-proxy pull --policy-id <ID>`);
13759
- log5(` ${dim2("Push policy:")} solongate-proxy push --policy-id <ID>`);
13760
- log5("");
13344
+ log4(dim2(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
13345
+ log4("");
13346
+ log4(` ${dim2("View details:")} solongate-proxy list --policy-id <ID>`);
13347
+ log4(` ${dim2("Pull policy:")} solongate-proxy pull --policy-id <ID>`);
13348
+ log4(` ${dim2("Push policy:")} solongate-proxy push --policy-id <ID>`);
13349
+ log4("");
13761
13350
  }
13762
13351
  function printPolicySummary(p, rules) {
13763
13352
  const ruleCount = rules.length;
13764
13353
  const allowCount = rules.filter((r) => r.effect === "ALLOW").length;
13765
13354
  const denyCount = rules.filter((r) => r.effect === "DENY").length;
13766
- log5(` ${cyan2(p.id)}`);
13767
- log5(` ${bold2(p.name)} ${dim2(`v${p.version ?? "?"}`)}`);
13768
- log5(` ${dim2("Rules:")} ${ruleCount} ${green2(`${allowCount} ALLOW`)} ${red2(`${denyCount} DENY`)}`);
13355
+ log4(` ${cyan2(p.id)}`);
13356
+ log4(` ${bold2(p.name)} ${dim2(`v${p.version ?? "?"}`)}`);
13357
+ log4(` ${dim2("Rules:")} ${ruleCount} ${green2(`${allowCount} ALLOW`)} ${red2(`${denyCount} DENY`)}`);
13769
13358
  if (p.created_at) {
13770
- log5(` ${dim2("Updated:")} ${new Date(p.created_at).toLocaleString()}`);
13359
+ log4(` ${dim2("Updated:")} ${new Date(p.created_at).toLocaleString()}`);
13771
13360
  }
13772
- log5("");
13361
+ log4("");
13773
13362
  }
13774
13363
  function printPolicyDetail(policy) {
13775
- log5("");
13776
- log5(bold2(` ${policy.name}`));
13777
- log5(` ${dim2("ID:")} ${cyan2(policy.id)} ${dim2("Version:")} ${policy.version} ${dim2("Rules:")} ${policy.rules.length}`);
13778
- log5("");
13364
+ log4("");
13365
+ log4(bold2(` ${policy.name}`));
13366
+ log4(` ${dim2("ID:")} ${cyan2(policy.id)} ${dim2("Version:")} ${policy.version} ${dim2("Rules:")} ${policy.rules.length}`);
13367
+ log4("");
13779
13368
  if (policy.rules.length === 0) {
13780
- log5(yellow2(" No rules defined."));
13781
- log5("");
13369
+ log4(yellow2(" No rules defined."));
13370
+ log4("");
13782
13371
  return;
13783
13372
  }
13784
- log5(dim2(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
13373
+ log4(dim2(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
13785
13374
  for (const rule of policy.rules) {
13786
13375
  const effectColor = rule.effect === "ALLOW" ? green2 : red2;
13787
- log5("");
13788
- log5(` ${effectColor(rule.effect.padEnd(5))} ${bold2(rule.toolPattern)} ${dim2(`P:${rule.priority}`)}`);
13376
+ log4("");
13377
+ log4(` ${effectColor(rule.effect.padEnd(5))} ${bold2(rule.toolPattern)} ${dim2(`P:${rule.priority}`)}`);
13789
13378
  if (rule.description) {
13790
- log5(` ${dim2(rule.description)}`);
13379
+ log4(` ${dim2(rule.description)}`);
13791
13380
  }
13792
- log5(` ${dim2(`${rule.permission} trust:${rule.minimumTrustLevel || "UNTRUSTED"}`)}`);
13381
+ log4(` ${dim2(`${rule.permission} trust:${rule.minimumTrustLevel || "UNTRUSTED"}`)}`);
13793
13382
  if (rule.pathConstraints) {
13794
13383
  const pc = rule.pathConstraints;
13795
- if (pc.rootDirectory) log5(` ${magenta("ROOT")} ${pc.rootDirectory}`);
13796
- if (pc.allowed?.length) log5(` ${green2("PATHS")} ${pc.allowed.join(", ")}`);
13797
- if (pc.denied?.length) log5(` ${red2("DENY")} ${pc.denied.join(", ")}`);
13384
+ if (pc.rootDirectory) log4(` ${magenta("ROOT")} ${pc.rootDirectory}`);
13385
+ if (pc.allowed?.length) log4(` ${green2("PATHS")} ${pc.allowed.join(", ")}`);
13386
+ if (pc.denied?.length) log4(` ${red2("DENY")} ${pc.denied.join(", ")}`);
13798
13387
  }
13799
13388
  if (rule.commandConstraints) {
13800
13389
  const cc = rule.commandConstraints;
13801
- if (cc.allowed?.length) log5(` ${green2("CMDS")} ${cc.allowed.join(", ")}`);
13802
- if (cc.denied?.length) log5(` ${red2("DENY")} ${cc.denied.join(", ")}`);
13390
+ if (cc.allowed?.length) log4(` ${green2("CMDS")} ${cc.allowed.join(", ")}`);
13391
+ if (cc.denied?.length) log4(` ${red2("DENY")} ${cc.denied.join(", ")}`);
13803
13392
  }
13804
13393
  if (rule.filenameConstraints) {
13805
13394
  const fc = rule.filenameConstraints;
13806
- if (fc.allowed?.length) log5(` ${green2("FILES")} ${fc.allowed.join(", ")}`);
13807
- if (fc.denied?.length) log5(` ${red2("DENY")} ${fc.denied.join(", ")}`);
13395
+ if (fc.allowed?.length) log4(` ${green2("FILES")} ${fc.allowed.join(", ")}`);
13396
+ if (fc.denied?.length) log4(` ${red2("DENY")} ${fc.denied.join(", ")}`);
13808
13397
  }
13809
13398
  if (rule.urlConstraints) {
13810
13399
  const uc = rule.urlConstraints;
13811
- if (uc.allowed?.length) log5(` ${green2("URLS")} ${uc.allowed.join(", ")}`);
13812
- if (uc.denied?.length) log5(` ${red2("DENY")} ${uc.denied.join(", ")}`);
13400
+ if (uc.allowed?.length) log4(` ${green2("URLS")} ${uc.allowed.join(", ")}`);
13401
+ if (uc.denied?.length) log4(` ${red2("DENY")} ${uc.denied.join(", ")}`);
13813
13402
  }
13814
13403
  }
13815
- log5("");
13816
- log5(dim2(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
13817
- log5("");
13404
+ log4("");
13405
+ log4(dim2(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
13406
+ log4("");
13818
13407
  }
13819
13408
  async function pull(apiKey, file, policyId) {
13820
13409
  if (!policyId) {
13821
13410
  const policies = await listPolicies(apiKey);
13822
13411
  if (policies.length === 0) {
13823
- log5(red2("No policies found. Create one in the dashboard first."));
13412
+ log4(red2("No policies found. Create one in the dashboard first."));
13824
13413
  process.exit(1);
13825
13414
  }
13826
13415
  if (policies.length === 1) {
13827
13416
  policyId = policies[0].id;
13828
- log5(dim2(`Auto-selecting only policy: ${policyId}`));
13417
+ log4(dim2(`Auto-selecting only policy: ${policyId}`));
13829
13418
  } else {
13830
- log5(yellow2(`Found ${policies.length} policies:`));
13831
- log5("");
13419
+ log4(yellow2(`Found ${policies.length} policies:`));
13420
+ log4("");
13832
13421
  for (const p of policies) {
13833
- log5(` ${cyan2(p.id)} ${p.name} ${dim2(`v${p.version ?? "?"}`)}`);
13422
+ log4(` ${cyan2(p.id)} ${p.name} ${dim2(`v${p.version ?? "?"}`)}`);
13834
13423
  }
13835
- log5("");
13836
- log5("Use --policy-id <ID> to specify which one to pull.");
13424
+ log4("");
13425
+ log4("Use --policy-id <ID> to specify which one to pull.");
13837
13426
  process.exit(1);
13838
13427
  }
13839
13428
  }
13840
- log5(`Pulling ${cyan2(policyId)} from dashboard...`);
13429
+ log4(`Pulling ${cyan2(policyId)} from dashboard...`);
13841
13430
  const policy = await fetchCloudPolicy(apiKey, API_URL, policyId);
13842
13431
  const { id: _id, ...policyWithoutId } = policy;
13843
13432
  const json = JSON.stringify(policyWithoutId, null, 2) + "\n";
13844
13433
  writeFileSync12(file, json, "utf-8");
13845
- log5("");
13846
- log5(green2(" Saved to: ") + file);
13847
- log5(` ${dim2("Name:")} ${policy.name}`);
13848
- log5(` ${dim2("Version:")} ${policy.version}`);
13849
- log5(` ${dim2("Rules:")} ${policy.rules.length}`);
13850
- log5("");
13851
- log5(dim2("The policy file does not contain an ID."));
13852
- log5(dim2("Use --policy-id to specify the target when pushing/pulling."));
13853
- log5("");
13434
+ log4("");
13435
+ log4(green2(" Saved to: ") + file);
13436
+ log4(` ${dim2("Name:")} ${policy.name}`);
13437
+ log4(` ${dim2("Version:")} ${policy.version}`);
13438
+ log4(` ${dim2("Rules:")} ${policy.rules.length}`);
13439
+ log4("");
13440
+ log4(dim2("The policy file does not contain an ID."));
13441
+ log4(dim2("Use --policy-id to specify the target when pushing/pulling."));
13442
+ log4("");
13854
13443
  }
13855
13444
  async function push(apiKey, file, policyId) {
13856
- if (!existsSync10(file)) {
13857
- log5(red2(`ERROR: File not found: ${file}`));
13445
+ if (!existsSync9(file)) {
13446
+ log4(red2(`ERROR: File not found: ${file}`));
13858
13447
  process.exit(1);
13859
13448
  }
13860
13449
  if (!policyId) {
13861
- log5(red2("ERROR: --policy-id is required for push."));
13862
- log5("");
13863
- log5("This determines which cloud policy to update.");
13864
- log5("");
13865
- log5("Usage:");
13866
- log5(" solongate-proxy push --policy-id my-policy");
13867
- log5(" solongate-proxy push --policy-id my-policy --file custom.json");
13868
- log5("");
13869
- log5("List your policies:");
13870
- log5(" solongate-proxy list");
13450
+ log4(red2("ERROR: --policy-id is required for push."));
13451
+ log4("");
13452
+ log4("This determines which cloud policy to update.");
13453
+ log4("");
13454
+ log4("Usage:");
13455
+ log4(" solongate-proxy push --policy-id my-policy");
13456
+ log4(" solongate-proxy push --policy-id my-policy --file custom.json");
13457
+ log4("");
13458
+ log4("List your policies:");
13459
+ log4(" solongate-proxy list");
13871
13460
  process.exit(1);
13872
13461
  }
13873
- const content = readFileSync14(file, "utf-8");
13462
+ const content = readFileSync13(file, "utf-8");
13874
13463
  let policy;
13875
13464
  try {
13876
13465
  policy = JSON.parse(content);
13877
13466
  } catch {
13878
- log5(red2(`ERROR: Invalid JSON in ${file}`));
13467
+ log4(red2(`ERROR: Invalid JSON in ${file}`));
13879
13468
  process.exit(1);
13880
13469
  }
13881
- log5(`Pushing to ${cyan2(policyId)}...`);
13882
- log5(` ${dim2("File:")} ${file}`);
13883
- log5(` ${dim2("Name:")} ${policy.name || "Unnamed"}`);
13884
- log5(` ${dim2("Rules:")} ${(policy.rules || []).length}`);
13470
+ log4(`Pushing to ${cyan2(policyId)}...`);
13471
+ log4(` ${dim2("File:")} ${file}`);
13472
+ log4(` ${dim2("Name:")} ${policy.name || "Unnamed"}`);
13473
+ log4(` ${dim2("Rules:")} ${(policy.rules || []).length}`);
13885
13474
  const checkRes = await fetch(`${API_URL}/api/v1/policies/${policyId}`, {
13886
13475
  headers: { "Authorization": `Bearer ${apiKey}` }
13887
13476
  });
@@ -13903,15 +13492,15 @@ async function push(apiKey, file, policyId) {
13903
13492
  });
13904
13493
  if (!res.ok) {
13905
13494
  const body = await res.text().catch(() => "");
13906
- log5(red2(`ERROR: Push failed (${res.status}): ${body}`));
13495
+ log4(red2(`ERROR: Push failed (${res.status}): ${body}`));
13907
13496
  process.exit(1);
13908
13497
  }
13909
13498
  const data = await res.json();
13910
- log5("");
13911
- log5(green2(` Pushed to cloud: v${data._version ?? "created"}`));
13912
- log5(` ${dim2("Policy ID:")} ${policyId}`);
13913
- log5(` ${dim2("Method:")} ${method === "PUT" ? "Updated existing" : "Created new"}`);
13914
- log5("");
13499
+ log4("");
13500
+ log4(green2(` Pushed to cloud: v${data._version ?? "created"}`));
13501
+ log4(` ${dim2("Policy ID:")} ${policyId}`);
13502
+ log4(` ${dim2("Method:")} ${method === "PUT" ? "Updated existing" : "Created new"}`);
13503
+ log4("");
13915
13504
  }
13916
13505
  async function main3() {
13917
13506
  const { command, apiKey, file, policyId } = parseCliArgs();
@@ -13923,32 +13512,32 @@ async function main3() {
13923
13512
  } else if (command === "list" || command === "ls") {
13924
13513
  await list5(apiKey, policyId);
13925
13514
  } else {
13926
- log5(red2(`Unknown command: ${command}`));
13927
- log5("");
13928
- log5(bold2("Usage:"));
13929
- log5(" solongate-proxy list List all policies");
13930
- log5(" solongate-proxy list --policy-id <ID> Show policy details");
13931
- log5(" solongate-proxy pull --policy-id <ID> Pull policy to local file");
13932
- log5(" solongate-proxy push --policy-id <ID> Push local file to cloud");
13933
- log5("");
13934
- log5(bold2("Flags:"));
13935
- log5(" --policy-id, --id <ID> Cloud policy ID (required for push)");
13936
- log5(" --file, -f <path> Local file path (default: policy.json)");
13937
- log5(" --api-key <key> API key (or set SOLONGATE_API_KEY)");
13938
- log5("");
13515
+ log4(red2(`Unknown command: ${command}`));
13516
+ log4("");
13517
+ log4(bold2("Usage:"));
13518
+ log4(" solongate-proxy list List all policies");
13519
+ log4(" solongate-proxy list --policy-id <ID> Show policy details");
13520
+ log4(" solongate-proxy pull --policy-id <ID> Pull policy to local file");
13521
+ log4(" solongate-proxy push --policy-id <ID> Push local file to cloud");
13522
+ log4("");
13523
+ log4(bold2("Flags:"));
13524
+ log4(" --policy-id, --id <ID> Cloud policy ID (required for push)");
13525
+ log4(" --file, -f <path> Local file path (default: policy.json)");
13526
+ log4(" --api-key <key> API key (or set SOLONGATE_API_KEY)");
13527
+ log4("");
13939
13528
  process.exit(1);
13940
13529
  }
13941
13530
  } catch (err2) {
13942
- log5(red2(`ERROR: ${err2 instanceof Error ? err2.message : String(err2)}`));
13531
+ log4(red2(`ERROR: ${err2 instanceof Error ? err2.message : String(err2)}`));
13943
13532
  process.exit(1);
13944
13533
  }
13945
13534
  }
13946
- var log5, dim2, bold2, green2, red2, yellow2, cyan2, magenta, API_URL;
13535
+ var log4, dim2, bold2, green2, red2, yellow2, cyan2, magenta, API_URL;
13947
13536
  var init_pull_push = __esm({
13948
13537
  "src/pull-push.ts"() {
13949
13538
  "use strict";
13950
13539
  init_config();
13951
- log5 = (...args) => process.stderr.write(`${args.map(String).join(" ")}
13540
+ log4 = (...args) => process.stderr.write(`${args.map(String).join(" ")}
13952
13541
  `);
13953
13542
  dim2 = (s) => `\x1B[2m${s}\x1B[0m`;
13954
13543
  bold2 = (s) => `\x1B[1m${s}\x1B[0m`;
@@ -13964,7 +13553,7 @@ var init_pull_push = __esm({
13964
13553
 
13965
13554
  // src/index.ts
13966
13555
  init_config();
13967
- import { readFileSync as readFileSync15 } from "fs";
13556
+ import { readFileSync as readFileSync14 } from "fs";
13968
13557
  import { fileURLToPath as fileURLToPath4 } from "url";
13969
13558
  import { dirname as dirname4, join as join17 } from "path";
13970
13559
 
@@ -16390,7 +15979,7 @@ var Mutex = class {
16390
15979
  this.locked = true;
16391
15980
  return;
16392
15981
  }
16393
- return new Promise((resolve10, reject) => {
15982
+ return new Promise((resolve9, reject) => {
16394
15983
  const timer = setTimeout(() => {
16395
15984
  const idx = this.queue.indexOf(onReady);
16396
15985
  if (idx !== -1) this.queue.splice(idx, 1);
@@ -16398,7 +15987,7 @@ var Mutex = class {
16398
15987
  }, timeoutMs);
16399
15988
  const onReady = () => {
16400
15989
  clearTimeout(timer);
16401
- resolve10();
15990
+ resolve9();
16402
15991
  };
16403
15992
  this.queue.push(onReady);
16404
15993
  });
@@ -16989,7 +16578,7 @@ ${msg.content.text}`;
16989
16578
 
16990
16579
  // src/index.ts
16991
16580
  init_cli_utils();
16992
- var CLI_SUBCOMMANDS = /* @__PURE__ */ new Set(["shield", "create", "inject", "pull", "push", "list", "ls", "logs-server", "local-logs", "policy", "ratelimit", "dlp", "stats", "audit", "agents", "agent", "doctor", "watch", "keys", "mcp", "alerts", "webhooks", "dataroom"]);
16581
+ var CLI_SUBCOMMANDS = /* @__PURE__ */ new Set(["create", "inject", "pull", "push", "list", "ls", "logs-server", "local-logs", "policy", "ratelimit", "dlp", "stats", "audit", "agents", "agent", "doctor", "watch", "alerts", "webhooks", "dataroom"]);
16993
16582
  var CLI_INFO_ARGS = /* @__PURE__ */ new Set(["login", "help", "--help", "-h", "--version", "-v", "version"]);
16994
16583
  var IS_HUMAN_CLI = process.argv.length <= 2 || CLI_SUBCOMMANDS.has(process.argv[2] ?? "") || CLI_INFO_ARGS.has(process.argv[2] ?? "");
16995
16584
  if (!IS_HUMAN_CLI) {
@@ -17009,7 +16598,7 @@ if (!IS_HUMAN_CLI) {
17009
16598
  var PKG_VERSION = (() => {
17010
16599
  try {
17011
16600
  const p = join17(dirname4(fileURLToPath4(import.meta.url)), "..", "package.json");
17012
- return JSON.parse(readFileSync15(p, "utf-8")).version || "unknown";
16601
+ return JSON.parse(readFileSync14(p, "utf-8")).version || "unknown";
17013
16602
  } catch {
17014
16603
  return "unknown";
17015
16604
  }
@@ -17029,41 +16618,73 @@ function printWelcome() {
17029
16618
  console.log("");
17030
16619
  }
17031
16620
  function printHelp3() {
17032
- const row = (name, desc) => console.log(` ${c.cyan}${name.padEnd(13)}${c.reset}${c.dim}${desc}${c.reset}`);
17033
- console.log("");
17034
- console.log(` ${c.bold}${c.blue4}SolonGate${c.reset} ${c.dim}secure gateway for your AI agents${c.reset}`);
17035
- console.log("");
17036
- console.log(` ${c.dim}Usage:${c.reset} ${c.cyan}solongate${c.reset} ${c.dim}[command]${c.reset}`);
17037
- console.log(` ${c.dim}With no command, opens the dataroom: accounts, policies, rate limits,${c.reset}`);
17038
- console.log(` ${c.dim}DLP, audit and settings in one terminal UI.${c.reset}`);
17039
- console.log("");
17040
- console.log(` ${c.bold}Setup & status${c.reset}`);
17041
- row("doctor", "health check: login, active policy, guard, local logs");
17042
- row("create", "scaffold a guarded MCP server in the current folder");
17043
- row("logs-server", "serve local audit logs to the dashboard");
17044
- console.log("");
17045
- console.log(` ${c.bold}Security config${c.reset}`);
17046
- row("policy", "view and manage policies");
17047
- row("ratelimit", "view and manage rate limits");
17048
- row("dlp", "view and manage DLP (secret) rules");
17049
- row("alerts", "view and manage alerts");
17050
- row("webhooks", "view and manage webhooks");
16621
+ const W = 46;
16622
+ const head = (t) => console.log(`
16623
+ ${c.bold}${t}${c.reset}`);
16624
+ const cmd = (syntax, desc = "") => {
16625
+ if (!desc) {
16626
+ console.log(` ${c.cyan}${syntax}${c.reset}`);
16627
+ return;
16628
+ }
16629
+ if (syntax.length <= W) {
16630
+ console.log(` ${c.cyan}${syntax}${c.reset}${" ".repeat(W - syntax.length)}${c.dim}${desc}${c.reset}`);
16631
+ } else {
16632
+ console.log(` ${c.cyan}${syntax}${c.reset}`);
16633
+ console.log(` ${" ".repeat(W)}${c.dim}${desc}${c.reset}`);
16634
+ }
16635
+ };
17051
16636
  console.log("");
17052
- console.log(` ${c.bold}Monitoring${c.reset}`);
17053
- row("audit", "browse the audit log of tool-call decisions");
17054
- row("stats", "usage statistics");
17055
- row("watch", "live-tail tool calls as they happen");
17056
- row("agents", "list agents and sessions");
16637
+ console.log(` ${c.bold}${c.blue4}SolonGate${c.reset} ${c.dim}secure gateway for your AI agents${c.reset} ${c.dim}v${PKG_VERSION}${c.reset}`);
17057
16638
  console.log("");
17058
- console.log(` ${c.bold}Advanced${c.reset}`);
17059
- row("keys", "manage API keys");
17060
- row("mcp", "manage MCP servers");
17061
- row("shield", "wrap a command with LLM-path secret redaction: shield -- <cmd>");
17062
- row("pull", "pull a cloud policy to a local file");
17063
- row("push", "push a local policy file to the cloud");
17064
- row("list", "list cloud policies");
16639
+ console.log(` ${c.dim}Usage:${c.reset} ${c.cyan}solongate${c.reset} ${c.dim}[command]${c.reset} ${c.dim}(no command opens the dataroom: all of this in a terminal UI)${c.reset}`);
16640
+ head("Setup & status");
16641
+ cmd("solongate", "open the dataroom UI (login, policies, audit, settings)");
16642
+ cmd("doctor [--json]", "health check: login, policy, guard, local logs");
16643
+ cmd("create", "scaffold a guarded MCP server in this folder");
16644
+ cmd("logs-server", "serve local audit logs to the dashboard");
16645
+ head("Policies");
16646
+ cmd("policy list", "list all policies");
16647
+ cmd("policy show <id> [--version N]", "show one policy (rules, mode)");
16648
+ cmd("policy rules <id>", "list a policy's rules");
16649
+ cmd("policy allow <id> --tool <p> [--command|--path|--url <val>]", "add an ALLOW rule");
16650
+ cmd("policy revoke <id> <ruleId>", "remove a rule");
16651
+ cmd("policy activate <id> | --clear", "pin / unpin the active policy");
16652
+ cmd("policy rollback <id> <version>", "roll back to a version");
16653
+ cmd("policy versions <id>", "version history");
16654
+ cmd("policy active", "show the resolved active policy");
16655
+ cmd("policy dry-run <id|file.json> [--mode denylist|whitelist]", "replay recent traffic against rules");
16656
+ head("Rate limits");
16657
+ cmd("ratelimit show", "current limits + change history");
16658
+ cmd("ratelimit set --minute N [--hour N] [--day N] [--mode off|detect|block]", "edit limits (unset fields kept)");
16659
+ cmd("ratelimit history", "recent limit changes");
16660
+ head("DLP (secrets)");
16661
+ cmd("dlp show", "current mode + enabled patterns");
16662
+ cmd("dlp mode <off|detect|block>", "set enforcement mode");
16663
+ cmd("dlp enable <pattern>", "enable a built-in pattern");
16664
+ cmd("dlp disable <pattern>", "disable a built-in pattern");
16665
+ cmd("dlp add-custom --name X --re <regex>", "add a custom pattern");
16666
+ cmd("dlp remove-custom <name>", "remove a custom pattern");
16667
+ head("Monitoring");
16668
+ cmd("audit [--filter ALLOW|DENY] [--tool <s>] [--signal dlp|ratelimit] [--limit N]", "browse the audit log");
16669
+ cmd("audit whitelist <logId> [--scope exact|tool]", "turn a denial into an ALLOW rule");
16670
+ cmd("audit block <logId> [--scope exact|tool]", "turn a call into a DENY rule");
16671
+ cmd("stats [timeseries|drift]", "traffic & security statistics");
16672
+ cmd("watch [--filter DENY] [--tool <s>]", "live-tail tool calls (Ctrl+C to stop)");
16673
+ cmd("agents [--all]", "live agent feed");
16674
+ cmd("agent <agent_id>", "one-agent detail");
16675
+ head("Alerts & webhooks");
16676
+ cmd("alerts list");
16677
+ cmd("alerts add --signal deny|dlp|ratelimit|any --threshold N --window S (--email <a> | --telegram <id> | --slack <url>)", "spike alert");
16678
+ cmd("alerts remove <id>");
16679
+ cmd("webhooks list");
16680
+ cmd("webhooks add --url <https://\u2026> [--events denials|allowed|all]", "event webhook");
16681
+ cmd("webhooks remove <id>");
16682
+ head("Policy sync");
16683
+ cmd("pull --policy-id <ID> [--file f]", "pull a cloud policy to a local file");
16684
+ cmd("push --policy-id <ID> [--file f]", "push a local policy file to the cloud");
17065
16685
  console.log("");
17066
- console.log(` ${c.dim}Dashboard: ${c.reset}${c.cyan}https://dashboard.solongate.com${c.reset}`);
16686
+ console.log(` ${c.dim}Add ${c.reset}${c.cyan}--json${c.reset}${c.dim} to most read commands for machine output.${c.reset}`);
16687
+ console.log(` ${c.dim}Details for a command: ${c.reset}${c.cyan}solongate <command> help${c.reset}${c.dim} \xB7 Dashboard: ${c.reset}${c.cyan}https://dashboard.solongate.com${c.reset}`);
17067
16688
  console.log("");
17068
16689
  }
17069
16690
  async function main4() {
@@ -17101,7 +16722,7 @@ async function main4() {
17101
16722
  await launchTui2();
17102
16723
  return;
17103
16724
  }
17104
- const MGMT_COMMANDS = /* @__PURE__ */ new Set(["policy", "ratelimit", "dlp", "stats", "audit", "agents", "agent", "doctor", "watch", "keys", "mcp", "alerts", "webhooks"]);
16725
+ const MGMT_COMMANDS = /* @__PURE__ */ new Set(["policy", "ratelimit", "dlp", "stats", "audit", "agents", "agent", "doctor", "watch", "alerts", "webhooks"]);
17105
16726
  if (MGMT_COMMANDS.has(subcommand ?? "")) {
17106
16727
  const { runCommand: runCommand2 } = await Promise.resolve().then(() => (init_commands(), commands_exports));
17107
16728
  const code = await runCommand2(subcommand, process.argv.slice(3));
@@ -17114,11 +16735,6 @@ async function main4() {
17114
16735
  console.log("");
17115
16736
  return;
17116
16737
  }
17117
- if (subcommand === "shield") {
17118
- const { runShield: runShield2 } = await Promise.resolve().then(() => (init_shield(), shield_exports));
17119
- await runShield2();
17120
- return;
17121
- }
17122
16738
  if (subcommand === "logs-server" || subcommand === "local-logs") {
17123
16739
  const { runLogsServer: runLogsServer2 } = await Promise.resolve().then(() => (init_logs_server(), logs_server_exports));
17124
16740
  await runLogsServer2();
@@ -17138,6 +16754,17 @@ async function main4() {
17138
16754
  await Promise.resolve().then(() => (init_pull_push(), pull_push_exports));
17139
16755
  return;
17140
16756
  }
16757
+ const hasProxySeparator = process.argv.includes("--");
16758
+ const looksLikeProxyFlag = (subcommand ?? "").startsWith("-");
16759
+ if (subcommand && !hasProxySeparator && !looksLikeProxyFlag) {
16760
+ process.stdout.write(`
16761
+ Unknown command: ${subcommand}
16762
+ `);
16763
+ process.stdout.write(` Run \`solongate --help\` to see every command, or \`solongate\` for the dataroom.
16764
+
16765
+ `);
16766
+ process.exit(1);
16767
+ }
17141
16768
  try {
17142
16769
  const config = parseArgs(process.argv);
17143
16770
  const proxy = new SolonGateProxy(config);