@solongate/proxy 0.82.20 → 0.82.22

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: resolve7
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 = resolve7.apply(null, match);
3407
3407
  if (!(res instanceof Scalar)) res = new Scalar(res);
3408
3408
  if (format) res.format = format;
3409
3409
  return res;
@@ -6507,18 +6507,6 @@ var init_src = __esm({
6507
6507
  });
6508
6508
 
6509
6509
  // src/cli-utils.ts
6510
- function log3(msg) {
6511
- process.stderr.write(msg + "\n");
6512
- }
6513
- function printBanner(subtitle) {
6514
- log3("");
6515
- for (let i = 0; i < BANNER_FULL.length; i++) {
6516
- log3(`${c.bold}${BANNER_COLORS[i]}${BANNER_FULL[i]}${c.reset}`);
6517
- }
6518
- log3("");
6519
- log3(` ${c.dim}${c.italic}${subtitle}${c.reset}`);
6520
- log3("");
6521
- }
6522
6510
  var c, BANNER_FULL, BANNER_COLORS;
6523
6511
  var init_cli_utils = __esm({
6524
6512
  "src/cli-utils.ts"() {
@@ -6622,9 +6610,9 @@ async function fetchLatest() {
6622
6610
  function spawnGlobalInstall(version) {
6623
6611
  try {
6624
6612
  mkdirSync3(join4(homedir2(), ".solongate"), { recursive: true });
6625
- const log6 = openSync(LOG_FILE, "a");
6613
+ const log4 = openSync(LOG_FILE, "a");
6626
6614
  const p = spawn("npm", ["install", "-g", `${PKG}@${version}`], {
6627
- stdio: ["ignore", log6, log6],
6615
+ stdio: ["ignore", log4, log4],
6628
6616
  detached: true,
6629
6617
  windowsHide: true,
6630
6618
  shell: process.platform === "win32"
@@ -6638,7 +6626,7 @@ function spawnGlobalInstall(version) {
6638
6626
  }
6639
6627
  }
6640
6628
  function runGlobalInstall(version) {
6641
- return new Promise((resolve10) => {
6629
+ return new Promise((resolve7) => {
6642
6630
  try {
6643
6631
  mkdirSync3(join4(homedir2(), ".solongate"), { recursive: true });
6644
6632
  execFile(
@@ -6653,11 +6641,11 @@ ${stderr}
6653
6641
  `, { flag: "a" });
6654
6642
  } catch {
6655
6643
  }
6656
- resolve10(!err2);
6644
+ resolve7(!err2);
6657
6645
  }
6658
6646
  );
6659
6647
  } catch {
6660
- resolve10(false);
6648
+ resolve7(false);
6661
6649
  }
6662
6650
  });
6663
6651
  }
@@ -6772,11 +6760,11 @@ function startLogsServerDaemon() {
6772
6760
  }
6773
6761
  try {
6774
6762
  mkdirSync4(DIR, { recursive: true });
6775
- const log6 = openSync2(LOG_FILE2, "a");
6763
+ const log4 = openSync2(LOG_FILE2, "a");
6776
6764
  const cli = join5(dirname2(fileURLToPath2(import.meta.url)), "index.js");
6777
6765
  const p = spawn2(process.execPath, [cli, "logs-server"], {
6778
6766
  detached: true,
6779
- stdio: ["ignore", log6, log6],
6767
+ stdio: ["ignore", log4, log4],
6780
6768
  windowsHide: true
6781
6769
  });
6782
6770
  p.on("error", () => {
@@ -7854,7 +7842,7 @@ function LivePanel({ active: active2 }) {
7854
7842
  const [localBuf, setLocalBuf] = useState2([]);
7855
7843
  const [localOn, setLocalOn] = useState2(null);
7856
7844
  const [ring, setRing] = useState2(null);
7857
- const [log6, setLog] = useState2([]);
7845
+ const [log4, setLog] = useState2([]);
7858
7846
  const [filter, setFilter] = useState2("all");
7859
7847
  const [signal, setSignal] = useState2("none");
7860
7848
  const [search, setSearch] = useState2("");
@@ -8698,7 +8686,7 @@ function LivePanel({ active: active2 }) {
8698
8686
  ] }),
8699
8687
  /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", width: colW, overflow: "hidden", children: [
8700
8688
  /* @__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: [
8689
+ log4.slice(-(colH - 1)).map((l, i) => /* @__PURE__ */ jsxs2(Text2, { wrap: "truncate", children: [
8702
8690
  /* @__PURE__ */ jsxs2(Text2, { color: theme.dim, children: [
8703
8691
  hhmmss(l.ts),
8704
8692
  " "
@@ -9635,7 +9623,7 @@ function AuditPanel({ active: active2, focused }) {
9635
9623
  const sessLoading = source === "cloud" ? agentsQ.loading : localQ.loading;
9636
9624
  const doDelete = (kind) => {
9637
9625
  setMsg({ text: "deleting\u2026", level: "ok" });
9638
- const run12 = async () => {
9626
+ const run10 = async () => {
9639
9627
  if (source === "cloud") {
9640
9628
  if (kind === "one") {
9641
9629
  if (!current) throw new Error("nothing selected");
@@ -9651,14 +9639,14 @@ function AuditPanel({ active: active2, focused }) {
9651
9639
  localQ.reload();
9652
9640
  }
9653
9641
  };
9654
- run12().then(() => {
9642
+ run10().then(() => {
9655
9643
  setMsg({ text: kind === "one" ? "\u2713 entry deleted" : `\u2713 ALL ${source} logs deleted`, level: "ok" });
9656
9644
  toTop();
9657
9645
  }).catch((e) => setMsg({ text: "\u2717 " + (e instanceof Error ? e.message : String(e)), level: "bad" }));
9658
9646
  };
9659
9647
  const doExport = (kind) => {
9660
9648
  setMsg({ text: "exporting\u2026", level: "ok" });
9661
- const run12 = async () => {
9649
+ const run10 = async () => {
9662
9650
  const dir = join10(homedir8(), ".solongate");
9663
9651
  const file = join10(dir, `audit-export-${source}.jsonl`);
9664
9652
  let rows2;
@@ -9671,7 +9659,7 @@ function AuditPanel({ active: active2, focused }) {
9671
9659
  writeFileSync8(file, rows2.map((x) => JSON.stringify(x)).join("\n") + (rows2.length ? "\n" : ""));
9672
9660
  return { n: rows2.length, file };
9673
9661
  };
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" }));
9662
+ 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
9663
  };
9676
9664
  useInput5(
9677
9665
  (input, key) => {
@@ -10554,7 +10542,7 @@ function SettingsPanel({
10554
10542
  guardQ.reload();
10555
10543
  selfQ.reload();
10556
10544
  };
10557
- const run12 = (label, fn, reload) => {
10545
+ const run10 = (label, fn, reload) => {
10558
10546
  if (busy) return;
10559
10547
  setBusy(true);
10560
10548
  setMsg({ text: label + "\u2026", level: "ok" });
@@ -10636,8 +10624,8 @@ function SettingsPanel({
10636
10624
  const body = { signal: editor.signal, threshold: editor.threshold, windowSeconds: editor.windowSeconds, enabled: editor.enabled, ...channels };
10637
10625
  const id = editor.id;
10638
10626
  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);
10627
+ if (id) run10("alert updated", () => api.settings.updateAlert(id, body), alertQ.reload);
10628
+ else run10(`${editor.channel} alert added`, () => api.settings.createAlert({ name: "SolonGate alert", ...body }), alertQ.reload);
10641
10629
  };
10642
10630
  const activate = (r) => {
10643
10631
  if (r.kind === "acct") {
@@ -10653,14 +10641,14 @@ function SettingsPanel({
10653
10641
  guardQ.reload();
10654
10642
  } else if (r.kind === "self") {
10655
10643
  if (!selfProt) return;
10656
- run12(selfProt.enabled ? "self-protection disabled" : "self-protection enabled", () => api.settings.setSelfProtection(!selfProt.enabled), selfQ.reload);
10644
+ run10(selfProt.enabled ? "self-protection disabled" : "self-protection enabled", () => api.settings.setSelfProtection(!selfProt.enabled), selfQ.reload);
10657
10645
  } else if (r.kind === "ll-enabled") {
10658
10646
  if (!local) return;
10659
10647
  if (!local.enabled && !local.path.trim()) {
10660
10648
  setMsg({ text: "set a path first (\u2193 then enter)", level: "bad" });
10661
10649
  return;
10662
10650
  }
10663
- run12(local.enabled ? "local logs disabled" : "local logs enabled", () => api.settings.setLocalLogs({ enabled: !local.enabled, path: local.path }), localQ.reload);
10651
+ run10(local.enabled ? "local logs disabled" : "local logs enabled", () => api.settings.setLocalLogs({ enabled: !local.enabled, path: local.path }), localQ.reload);
10664
10652
  } else if (r.kind === "ll-path") {
10665
10653
  setInput(local?.path ?? "");
10666
10654
  setEditing("path");
@@ -10671,7 +10659,7 @@ function SettingsPanel({
10671
10659
  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
10660
  );
10673
10661
  } 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);
10662
+ run10(r.wh.enabled ? "webhook disabled" : "webhook enabled", () => api.settings.updateWebhook(r.wh.id, { enabled: !r.wh.enabled }), whQ.reload);
10675
10663
  } else if (r.kind === "wh-add") {
10676
10664
  setInput("");
10677
10665
  setEditing("wh-url");
@@ -10690,7 +10678,7 @@ function SettingsPanel({
10690
10678
  setEditing(null);
10691
10679
  if (which === "path") {
10692
10680
  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);
10681
+ 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
10682
  } else if (which === "wh-url") {
10695
10683
  const url = v.replace(/^["'<]+|["'>]+$/g, "").trim();
10696
10684
  if (!url) return;
@@ -10698,7 +10686,7 @@ function SettingsPanel({
10698
10686
  setMsg({ text: "\u2717 webhook url must start with http:// or https://", level: "bad" });
10699
10687
  return;
10700
10688
  }
10701
- run12("webhook added", () => api.settings.createWebhook({ url, events: "denials" }), whQ.reload);
10689
+ run10("webhook added", () => api.settings.createWebhook({ url, events: "denials" }), whQ.reload);
10702
10690
  } else if (which === "alert-target" && editor) {
10703
10691
  setEditor({ ...editor, target: v, field: 1 });
10704
10692
  }
@@ -10752,7 +10740,7 @@ function SettingsPanel({
10752
10740
  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
10741
  refreshAccounts();
10754
10742
  } 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);
10743
+ if (cur.kind === "alert") run10(cur.rule.enabled ? "alert disabled" : "alert enabled", () => api.settings.setAlertEnabled(cur.rule.id, !cur.rule.enabled), alertQ.reload);
10756
10744
  else activate(cur);
10757
10745
  }
10758
10746
  } else if (inp === "x" && cur.kind === "acct") {
@@ -10782,13 +10770,13 @@ function SettingsPanel({
10782
10770
  refreshAccounts();
10783
10771
  onAccountsChanged?.();
10784
10772
  } else if (inp === "t" && cur.kind === "wh") {
10785
- run12("webhook test sent \u2014 check your endpoint", () => api.settings.sendTestWebhook(cur.wh.id).then((r) => {
10773
+ run10("webhook test sent \u2014 check your endpoint", () => api.settings.sendTestWebhook(cur.wh.id).then((r) => {
10786
10774
  if (!r.delivered) throw new Error("endpoint rejected the test (non-2xx)");
10787
10775
  }), whQ.reload);
10788
10776
  } else if (inp === "e" && cur.kind === "ll-path") activate(cur);
10789
10777
  else if (inp === "e" && cur.kind === "wh") {
10790
10778
  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);
10779
+ run10(`webhook events \u2192 ${next}`, () => api.settings.updateWebhook(cur.wh.id, { events: next }), whQ.reload);
10792
10780
  } else if (inp === "e" && cur.kind === "alert") {
10793
10781
  const ch = alertChannel(cur.rule);
10794
10782
  if (ch) openAlertEditor(ch, cur.rule);
@@ -10825,10 +10813,10 @@ function SettingsPanel({
10825
10813
  setConfirmDel(null);
10826
10814
  if (cur.kind === "wh") {
10827
10815
  const id = cur.wh.id;
10828
- run12("webhook deleted", () => api.settings.deleteWebhook(id).then(() => setHidden((h) => new Set(h).add("wh:" + id))), whQ.reload);
10816
+ run10("webhook deleted", () => api.settings.deleteWebhook(id).then(() => setHidden((h) => new Set(h).add("wh:" + id))), whQ.reload);
10829
10817
  } else {
10830
10818
  const id = cur.rule.id;
10831
- run12("alert deleted", () => api.settings.deleteAlert(id).then(() => setHidden((h) => new Set(h).add("alert:" + id))), alertQ.reload);
10819
+ run10("alert deleted", () => api.settings.deleteAlert(id).then(() => setHidden((h) => new Set(h).add("alert:" + id))), alertQ.reload);
10832
10820
  }
10833
10821
  } else if (inp === "r") reloadAll();
10834
10822
  },
@@ -11128,9 +11116,9 @@ function App() {
11128
11116
  const [update2, setUpdate] = useState8({ kind: "idle" });
11129
11117
  useEffect7(() => {
11130
11118
  let alive = true;
11131
- const run12 = () => void tuiUpdateFlow((s) => alive && setUpdate(s));
11132
- run12();
11133
- const t = setInterval(run12, 30 * 6e4);
11119
+ const run10 = () => void tuiUpdateFlow((s) => alive && setUpdate(s));
11120
+ run10();
11121
+ const t = setInterval(run10, 30 * 6e4);
11134
11122
  return () => {
11135
11123
  alive = false;
11136
11124
  clearInterval(t);
@@ -12204,7 +12192,7 @@ var init_watch = __esm({
12204
12192
  }
12205
12193
  });
12206
12194
 
12207
- // src/commands/keys.ts
12195
+ // src/commands/alerts.ts
12208
12196
  async function run8(argv) {
12209
12197
  const { positionals, flags } = parse(argv);
12210
12198
  const sub = positionals[0] ?? "list";
@@ -12212,89 +12200,6 @@ async function run8(argv) {
12212
12200
  switch (sub) {
12213
12201
  case "help":
12214
12202
  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
12203
  case "list": {
12299
12204
  const { rules } = await api.settings.getAlerts();
12300
12205
  if (json) return printJson(rules), 0;
@@ -12336,17 +12241,17 @@ async function run10(argv) {
12336
12241
  return err(green(` \u2713 Removed ${id}`)), 0;
12337
12242
  }
12338
12243
  default:
12339
- return err(USAGE7), 1;
12244
+ return err(USAGE6), 1;
12340
12245
  }
12341
12246
  }
12342
- var USAGE7;
12247
+ var USAGE6;
12343
12248
  var init_alerts = __esm({
12344
12249
  "src/commands/alerts.ts"() {
12345
12250
  "use strict";
12346
12251
  init_api_client();
12347
12252
  init_args();
12348
12253
  init_format();
12349
- USAGE7 = `${bold("solongate alerts")} \u2014 spike alerts (Telegram / email)
12254
+ USAGE6 = `${bold("solongate alerts")} \u2014 spike alerts (Telegram / email)
12350
12255
 
12351
12256
  alerts list
12352
12257
  alerts add --signal deny|dlp|ratelimit|any --threshold N --window S
@@ -12358,13 +12263,13 @@ var init_alerts = __esm({
12358
12263
  });
12359
12264
 
12360
12265
  // src/commands/webhooks.ts
12361
- async function run11(argv) {
12266
+ async function run9(argv) {
12362
12267
  const { positionals, flags } = parse(argv);
12363
12268
  const sub = positionals[0] ?? "list";
12364
12269
  const json = flagBool(flags, "json");
12365
12270
  switch (sub) {
12366
12271
  case "help":
12367
- return err(USAGE8), 0;
12272
+ return err(USAGE7), 0;
12368
12273
  case "list": {
12369
12274
  const { webhooks } = await api.settings.getWebhooks();
12370
12275
  if (json) return printJson(webhooks), 0;
@@ -12390,17 +12295,17 @@ async function run11(argv) {
12390
12295
  return err(green(` \u2713 Removed ${id}`)), 0;
12391
12296
  }
12392
12297
  default:
12393
- return err(USAGE8), 1;
12298
+ return err(USAGE7), 1;
12394
12299
  }
12395
12300
  }
12396
- var USAGE8;
12301
+ var USAGE7;
12397
12302
  var init_webhooks = __esm({
12398
12303
  "src/commands/webhooks.ts"() {
12399
12304
  "use strict";
12400
12305
  init_api_client();
12401
12306
  init_args();
12402
12307
  init_format();
12403
- USAGE8 = `${bold("solongate webhooks")} \u2014 event webhooks
12308
+ USAGE7 = `${bold("solongate webhooks")} \u2014 event webhooks
12404
12309
 
12405
12310
  webhooks list
12406
12311
  webhooks add --url <https://\u2026> [--events denials|allowed|all]
@@ -12436,14 +12341,10 @@ async function dispatch(command, argv) {
12436
12341
  return run6(argv);
12437
12342
  case "watch":
12438
12343
  return run7(argv);
12439
- case "keys":
12440
- return run8(argv);
12441
- case "mcp":
12442
- return run9(argv);
12443
12344
  case "alerts":
12444
- return run10(argv);
12345
+ return run8(argv);
12445
12346
  case "webhooks":
12446
- return run11(argv);
12347
+ return run9(argv);
12447
12348
  default:
12448
12349
  err(` Unknown command: ${command}`);
12449
12350
  return 1;
@@ -12480,333 +12381,9 @@ var init_commands = __esm({
12480
12381
  init_agents2();
12481
12382
  init_doctor();
12482
12383
  init_watch();
12483
- init_keys2();
12484
- init_mcp2();
12485
12384
  init_alerts();
12486
12385
  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
- ];
12386
+ COMMAND_NAMES = ["policy", "ratelimit", "dlp", "stats", "audit", "agents", "agent", "doctor", "watch", "alerts", "webhooks"];
12810
12387
  }
12811
12388
  });
12812
12389
 
@@ -12815,11 +12392,11 @@ var logs_server_exports = {};
12815
12392
  __export(logs_server_exports, {
12816
12393
  runLogsServer: () => runLogsServer
12817
12394
  });
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";
12395
+ import { createServer } from "http";
12396
+ import { readFileSync as readFileSync11, statSync as statSync4 } from "fs";
12397
+ import { resolve as resolve5, join as join15, isAbsolute } from "path";
12398
+ import { homedir as homedir13 } from "os";
12399
+ import { readdirSync } from "fs";
12823
12400
  function allowedOrigins() {
12824
12401
  const base = [
12825
12402
  "https://dashboard.solongate.com",
@@ -12835,15 +12412,15 @@ function resolveLocalLogDir(rawPath) {
12835
12412
  const dir = String(rawPath || "").trim().replace(/[\\/]+$/, "");
12836
12413
  if (!dir) return null;
12837
12414
  if (isAbsolute(dir)) return dir;
12838
- return resolve6(homedir14(), ".solongate", "local-logs");
12415
+ return resolve5(homedir13(), ".solongate", "local-logs");
12839
12416
  }
12840
12417
  async function findLogDir() {
12841
- const base = resolve6(homedir14(), ".solongate");
12418
+ const base = resolve5(homedir13(), ".solongate");
12842
12419
  try {
12843
- const files = readdirSync2(base).filter((f) => f.startsWith(".policy-cache-") && f.endsWith(".json"));
12420
+ const files = readdirSync(base).filter((f) => f.startsWith(".policy-cache-") && f.endsWith(".json"));
12844
12421
  for (const f of files) {
12845
12422
  try {
12846
- const c2 = JSON.parse(readFileSync12(join15(base, f), "utf-8"));
12423
+ const c2 = JSON.parse(readFileSync11(join15(base, f), "utf-8"));
12847
12424
  const p = c2?.security?.localLogs?.path;
12848
12425
  if (typeof p === "string" && p.trim()) return { dir: resolveLocalLogDir(p), configured: p };
12849
12426
  } catch {
@@ -12852,7 +12429,7 @@ async function findLogDir() {
12852
12429
  } catch {
12853
12430
  }
12854
12431
  try {
12855
- const cfgRaw = readFileSync12(join15(base, "cloud-guard.json"), "utf-8");
12432
+ const cfgRaw = readFileSync11(join15(base, "cloud-guard.json"), "utf-8");
12856
12433
  const { apiKey, apiUrl } = JSON.parse(cfgRaw);
12857
12434
  if (apiKey) {
12858
12435
  const url = `${apiUrl || "https://api.solongate.com"}/api/v1/policies/active`;
@@ -12883,7 +12460,7 @@ function fileInfo(dir) {
12883
12460
  if (!dir) return { file: null, exists: false, size: 0, mtimeMs: 0 };
12884
12461
  const file = join15(dir, LOG_FILENAME);
12885
12462
  try {
12886
- const st = statSync5(file);
12463
+ const st = statSync4(file);
12887
12464
  return { file, exists: true, size: st.size, mtimeMs: st.mtimeMs };
12888
12465
  } catch {
12889
12466
  return { file, exists: false, size: 0, mtimeMs: 0 };
@@ -12915,7 +12492,7 @@ async function runLogsServer() {
12915
12492
  }
12916
12493
  const portArg = argv[argv.indexOf("--port") + 1];
12917
12494
  const port = Number(process.env.SOLONGATE_LOGS_PORT || (argv.includes("--port") ? portArg : "") || DEFAULT_PORT) || DEFAULT_PORT;
12918
- const server = createServer2(async (req, res) => {
12495
+ const server = createServer(async (req, res) => {
12919
12496
  setCors(req, res);
12920
12497
  if (req.method === "OPTIONS") {
12921
12498
  res.writeHead(204);
@@ -12964,7 +12541,7 @@ async function runLogsServer() {
12964
12541
  return;
12965
12542
  }
12966
12543
  try {
12967
- const text = readFileSync12(info.file, "utf-8");
12544
+ const text = readFileSync11(info.file, "utf-8");
12968
12545
  res.writeHead(200, { "Content-Type": "text/plain; charset=utf-8", "Last-Modified": lastMod, "X-Solongate-Exists": "1" });
12969
12546
  res.end(text);
12970
12547
  } catch {
@@ -13016,644 +12593,16 @@ var init_logs_server = __esm({
13016
12593
  }
13017
12594
  });
13018
12595
 
13019
- // src/inject.ts
13020
- var inject_exports = {};
13021
- import { readFileSync as readFileSync13, writeFileSync as writeFileSync10, existsSync as existsSync8, copyFileSync } from "fs";
13022
- import { resolve as resolve7 } from "path";
13023
- import { execSync } from "child_process";
13024
- function parseInjectArgs(argv) {
13025
- const args = argv.slice(2);
13026
- const opts = {
13027
- dryRun: false,
13028
- restore: false,
13029
- skipInstall: false
13030
- };
13031
- for (let i = 0; i < args.length; i++) {
13032
- switch (args[i]) {
13033
- case "--file":
13034
- opts.file = args[++i];
13035
- break;
13036
- case "--dry-run":
13037
- opts.dryRun = true;
13038
- break;
13039
- case "--restore":
13040
- opts.restore = true;
13041
- break;
13042
- case "--skip-install":
13043
- opts.skipInstall = true;
13044
- break;
13045
- case "--help":
13046
- case "-h":
13047
- printHelp();
13048
- process.exit(0);
13049
- }
13050
- }
13051
- return opts;
13052
- }
13053
- function printHelp() {
13054
- log3(`
13055
- SolonGate Inject \u2014 Add security to your MCP server in seconds
13056
-
13057
- USAGE
13058
- npx @solongate/proxy inject [options]
13059
-
13060
- OPTIONS
13061
- --file <path> Entry file to modify (default: auto-detect)
13062
- --dry-run Preview changes without writing
13063
- --restore Restore original file from backup
13064
- --skip-install Don't install SDK package
13065
- -h, --help Show this help message
13066
-
13067
- EXAMPLES
13068
- npx @solongate/proxy inject # Auto-detect and inject
13069
- npx @solongate/proxy inject --file src/main.ts # Specify entry file
13070
- npx @solongate/proxy inject --dry-run # Preview changes
13071
- npx @solongate/proxy inject --restore # Undo injection
13072
-
13073
- WHAT IT DOES
13074
- Replaces McpServer with SecureMcpServer (2 lines changed)
13075
- All tool() calls are automatically protected by SolonGate.
13076
- `);
13077
- }
13078
- function detectProject() {
13079
- if (!existsSync8(resolve7("package.json"))) return false;
13080
- try {
13081
- const pkg = JSON.parse(readFileSync13(resolve7("package.json"), "utf-8"));
13082
- const allDeps = { ...pkg.dependencies, ...pkg.devDependencies };
13083
- return !!(allDeps["@modelcontextprotocol/sdk"] || allDeps["@modelcontextprotocol/server"]);
13084
- } catch {
13085
- return false;
13086
- }
13087
- }
13088
- function findTsEntryFile() {
13089
- try {
13090
- const pkg = JSON.parse(readFileSync13(resolve7("package.json"), "utf-8"));
13091
- if (pkg.bin) {
13092
- const binPath = typeof pkg.bin === "string" ? pkg.bin : Object.values(pkg.bin)[0];
13093
- if (typeof binPath === "string") {
13094
- 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);
13097
- }
13098
- }
13099
- if (pkg.main) {
13100
- const srcPath = pkg.main.replace(/^\.\/dist\//, "./src/").replace(/\.js$/, ".ts");
13101
- if (existsSync8(resolve7(srcPath))) return resolve7(srcPath);
13102
- }
13103
- } catch {
13104
- }
13105
- const candidates = [
13106
- "src/index.ts",
13107
- "src/server.ts",
13108
- "src/main.ts",
13109
- "index.ts",
13110
- "server.ts",
13111
- "main.ts"
13112
- ];
13113
- for (const c2 of candidates) {
13114
- const full = resolve7(c2);
13115
- if (existsSync8(full)) {
13116
- try {
13117
- const content = readFileSync13(full, "utf-8");
13118
- if (content.includes("McpServer") || content.includes("McpServer")) {
13119
- return full;
13120
- }
13121
- } catch {
13122
- }
13123
- }
13124
- }
13125
- for (const c2 of candidates) {
13126
- if (existsSync8(resolve7(c2))) return resolve7(c2);
13127
- }
13128
- return null;
13129
- }
13130
- function detectPackageManager() {
13131
- if (existsSync8(resolve7("pnpm-lock.yaml"))) return "pnpm";
13132
- if (existsSync8(resolve7("yarn.lock"))) return "yarn";
13133
- return "npm";
13134
- }
13135
- function installSdk() {
13136
- try {
13137
- const pkg = JSON.parse(readFileSync13(resolve7("package.json"), "utf-8"));
13138
- const allDeps = { ...pkg.dependencies, ...pkg.devDependencies };
13139
- if (allDeps["@solongate/proxy"]) {
13140
- log3(" @solongate/proxy already installed");
13141
- return true;
13142
- }
13143
- } catch {
13144
- }
13145
- const pm = detectPackageManager();
13146
- const cmd = pm === "yarn" ? "yarn add @solongate/proxy" : `${pm} install @solongate/proxy`;
13147
- log3(` Installing @solongate/proxy via ${pm}...`);
13148
- try {
13149
- execSync(cmd, { stdio: "pipe", cwd: process.cwd() });
13150
- return true;
13151
- } catch (err2) {
13152
- log3(` Failed to install: ${err2 instanceof Error ? err2.message : String(err2)}`);
13153
- log3(" You can install manually: npm install @solongate/proxy");
13154
- return false;
13155
- }
13156
- }
13157
- function injectTypeScript(filePath) {
13158
- const original = readFileSync13(filePath, "utf-8");
13159
- const changes = [];
13160
- let modified = original;
13161
- if (modified.includes("SecureMcpServer")) {
13162
- return { file: filePath, changes: ["Already injected \u2014 skipping"], original, modified };
13163
- }
13164
- const mcpImportPatterns = [
13165
- // Solo import: import { McpServer } from '...'
13166
- /import\s*\{\s*McpServer\s*\}\s*from\s*['"][^'"]+['"]/,
13167
- // Import with others: import { McpServer, ... } from '...'
13168
- /import\s*\{[^}]*McpServer[^}]*\}\s*from\s*['"][^'"]+['"]/
13169
- ];
13170
- let importReplaced = false;
13171
- for (const pattern of mcpImportPatterns) {
13172
- const match = modified.match(pattern);
13173
- if (match) {
13174
- const importLine = match[0];
13175
- const namedImports = importLine.match(/\{([^}]+)\}/)?.[1] ?? "";
13176
- const importNames = namedImports.split(",").map((s) => s.trim()).filter(Boolean);
13177
- if (importNames.length === 1 && importNames[0] === "McpServer") {
13178
- modified = modified.replace(
13179
- importLine,
13180
- `import { SecureMcpServer } from '@solongate/proxy'`
13181
- );
13182
- changes.push("Replaced McpServer import with SecureMcpServer from @solongate/proxy");
13183
- } else {
13184
- const otherImports = importNames.filter((n) => n !== "McpServer");
13185
- const fromModule = importLine.match(/from\s*['"]([^'"]+)['"]/)?.[1] ?? "";
13186
- modified = modified.replace(
13187
- importLine,
13188
- `import { ${otherImports.join(", ")} } from '${fromModule}';
13189
- import { SecureMcpServer } from '@solongate/proxy'`
13190
- );
13191
- changes.push("Removed McpServer from existing import, added SecureMcpServer import from @solongate/proxy");
13192
- }
13193
- importReplaced = true;
13194
- break;
13195
- }
13196
- }
13197
- if (!importReplaced) {
13198
- const insertPos = findImportInsertPosition(modified);
13199
- modified = modified.slice(0, insertPos) + `import { SecureMcpServer } from '@solongate/proxy';
13200
- ` + modified.slice(insertPos);
13201
- changes.push("Added SecureMcpServer import from @solongate/proxy");
13202
- }
13203
- const constructorPattern = /new\s+McpServer\s*\(/g;
13204
- const constructorCount = (modified.match(constructorPattern) || []).length;
13205
- if (constructorCount > 0) {
13206
- modified = modified.replace(constructorPattern, "new SecureMcpServer(");
13207
- changes.push(`Replaced ${constructorCount} McpServer constructor(s) with SecureMcpServer`);
13208
- }
13209
- return { file: filePath, changes, original, modified };
13210
- }
13211
- function findImportInsertPosition(content) {
13212
- let pos = 0;
13213
- if (content.startsWith("#!")) {
13214
- pos = content.indexOf("\n") + 1;
13215
- }
13216
- const lines = content.slice(pos).split("\n");
13217
- let offset = pos;
13218
- for (const line of lines) {
13219
- const trimmed = line.trim();
13220
- if (trimmed === "" || trimmed.startsWith("//") || trimmed.startsWith("/*") || trimmed.startsWith("*") || trimmed.startsWith("*/")) {
13221
- offset += line.length + 1;
13222
- } else {
13223
- break;
13224
- }
13225
- }
13226
- const importRegex = /^import\s+.+$/gm;
13227
- let lastImportEnd = offset;
13228
- let importMatch;
13229
- while ((importMatch = importRegex.exec(content)) !== null) {
13230
- lastImportEnd = importMatch.index + importMatch[0].length + 1;
13231
- }
13232
- return lastImportEnd > offset ? lastImportEnd : offset;
13233
- }
13234
- function showDiff(result) {
13235
- if (result.original === result.modified) {
13236
- log3(" No changes needed.");
13237
- return;
13238
- }
13239
- const origLines = result.original.split("\n");
13240
- const modLines = result.modified.split("\n");
13241
- log3("");
13242
- log3(` File: ${result.file}`);
13243
- log3(" \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");
13244
- const maxLines = Math.max(origLines.length, modLines.length);
13245
- let diffCount = 0;
13246
- for (let i = 0; i < maxLines; i++) {
13247
- const orig = origLines[i];
13248
- const mod = modLines[i];
13249
- if (orig !== mod) {
13250
- if (diffCount < 30) {
13251
- if (orig !== void 0) log3(` - ${orig}`);
13252
- if (mod !== void 0) log3(` + ${mod}`);
13253
- }
13254
- diffCount++;
13255
- }
13256
- }
13257
- if (diffCount > 30) {
13258
- log3(` ... and ${diffCount - 30} more line changes`);
13259
- }
13260
- log3("");
13261
- }
13262
- async function main() {
13263
- const opts = parseInjectArgs(process.argv);
13264
- printBanner("Inject SDK");
13265
- if (!detectProject()) {
13266
- log3(" Could not detect a TypeScript MCP server project.");
13267
- log3(" Make sure you are in a project directory with:");
13268
- log3(" package.json + @modelcontextprotocol/sdk in dependencies");
13269
- log3("");
13270
- log3(" To create a new MCP server: npx @solongate/proxy create <name>");
13271
- process.exit(1);
13272
- }
13273
- log3(" Language: TypeScript");
13274
- const entryFile = opts.file ? resolve7(opts.file) : findTsEntryFile();
13275
- if (!entryFile || !existsSync8(entryFile)) {
13276
- log3(` Could not find entry file.${opts.file ? ` File not found: ${opts.file}` : ""}`);
13277
- log3("");
13278
- log3(" Specify it manually: --file <path>");
13279
- log3("");
13280
- log3(" Common entry points:");
13281
- log3(" src/index.ts, src/server.ts, index.ts");
13282
- process.exit(1);
13283
- }
13284
- log3(` Entry: ${entryFile}`);
13285
- log3("");
13286
- const backupPath = entryFile + ".solongate-backup";
13287
- if (opts.restore) {
13288
- if (!existsSync8(backupPath)) {
13289
- log3(" No backup found. Nothing to restore.");
13290
- process.exit(1);
13291
- }
13292
- copyFileSync(backupPath, entryFile);
13293
- log3(` Restored original file from backup.`);
13294
- log3(` Backup: ${backupPath}`);
13295
- process.exit(0);
13296
- }
13297
- if (!opts.skipInstall && !opts.dryRun) {
13298
- installSdk();
13299
- log3("");
13300
- }
13301
- const result = injectTypeScript(entryFile);
13302
- log3(` Changes (${result.changes.length}):`);
13303
- for (const change of result.changes) {
13304
- log3(` - ${change}`);
13305
- }
13306
- if (result.changes.length === 1 && result.changes[0].includes("Already injected")) {
13307
- log3("");
13308
- log3(" Your MCP server is already protected by SolonGate!");
13309
- process.exit(0);
13310
- }
13311
- if (result.original === result.modified) {
13312
- log3("");
13313
- log3(" No changes were made. The file may not contain recognizable MCP patterns.");
13314
- log3(" See docs: https://solongate.com/docs/integration");
13315
- process.exit(0);
13316
- }
13317
- if (opts.dryRun) {
13318
- log3("");
13319
- log3(" --- DRY RUN (no changes written) ---");
13320
- showDiff(result);
13321
- log3(" To apply: npx @solongate/proxy inject");
13322
- process.exit(0);
13323
- }
13324
- if (!existsSync8(backupPath)) {
13325
- copyFileSync(entryFile, backupPath);
13326
- log3("");
13327
- log3(` Backup: ${backupPath}`);
13328
- }
13329
- writeFileSync10(entryFile, result.modified);
13330
- log3("");
13331
- log3(" \u250C\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\u2500\u2500\u2500\u2500\u2500\u2510");
13332
- log3(" \u2502 SolonGate SDK injected successfully! \u2502");
13333
- log3(" \u2502 \u2502");
13334
- log3(" \u2502 McpServer \u2192 SecureMcpServer \u2502");
13335
- log3(" \u2502 All tool() calls are now auto-protected. \u2502");
13336
- log3(" \u2502 \u2502");
13337
- log3(" \u2502 Set your API key: \u2502");
13338
- log3(" \u2502 export SOLONGATE_API_KEY=sg_live_xxx \u2502");
13339
- log3(" \u2502 \u2502");
13340
- log3(" \u2502 To undo: \u2502");
13341
- log3(" \u2502 npx @solongate/proxy inject --restore \u2502");
13342
- log3(" \u2514\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\u2500\u2500\u2500\u2500\u2500\u2518");
13343
- log3("");
13344
- }
13345
- var init_inject = __esm({
13346
- "src/inject.ts"() {
13347
- "use strict";
13348
- init_cli_utils();
13349
- main().catch((err2) => {
13350
- log3(`Fatal: ${err2 instanceof Error ? err2.message : String(err2)}`);
13351
- process.exit(1);
13352
- });
13353
- }
13354
- });
13355
-
13356
- // src/create.ts
13357
- 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";
13360
- import { execSync as execSync2 } from "child_process";
13361
- function withSpinner(message, fn) {
13362
- const frames = ["\u28FE", "\u28FD", "\u28FB", "\u28BF", "\u287F", "\u28DF", "\u28EF", "\u28F7"];
13363
- let i = 0;
13364
- const id = setInterval(() => {
13365
- const color = i % 2 === 0 ? c.blue3 : c.blue5;
13366
- process.stderr.write(`\r ${color}${frames[i++ % frames.length]}${c.reset} ${c.dim}${message}${c.reset}`);
13367
- }, 80);
13368
- try {
13369
- const result = fn();
13370
- clearInterval(id);
13371
- process.stderr.write(`\r ${c.green}\u2713${c.reset} ${message}${" ".repeat(20)}
13372
- `);
13373
- return result;
13374
- } catch (err2) {
13375
- clearInterval(id);
13376
- process.stderr.write(`\r ${c.red}\u2717${c.reset} ${message} \u2014 failed${" ".repeat(10)}
13377
- `);
13378
- throw err2;
13379
- }
13380
- }
13381
- function parseCreateArgs(argv) {
13382
- const args = argv.slice(2);
13383
- const opts = {
13384
- name: "",
13385
- policy: "",
13386
- noInstall: false
13387
- };
13388
- for (let i = 0; i < args.length; i++) {
13389
- switch (args[i]) {
13390
- case "--policy":
13391
- opts.policy = args[++i];
13392
- break;
13393
- case "--no-install":
13394
- opts.noInstall = true;
13395
- break;
13396
- case "--help":
13397
- case "-h":
13398
- printHelp2();
13399
- process.exit(0);
13400
- break;
13401
- default:
13402
- if (!args[i].startsWith("-") && !opts.name) {
13403
- opts.name = args[i];
13404
- }
13405
- }
13406
- }
13407
- if (!opts.name) {
13408
- log3("");
13409
- log3(" Error: Project name required.");
13410
- log3("");
13411
- log3(" Usage: npx @solongate/proxy create <name>");
13412
- log3("");
13413
- log3(" Examples:");
13414
- log3(" npx @solongate/proxy create my-mcp-server");
13415
- log3(" npx @solongate/proxy create weather-api");
13416
- process.exit(1);
13417
- }
13418
- return opts;
13419
- }
13420
- function printHelp2() {
13421
- log3(`
13422
- SolonGate Create \u2014 Scaffold a secure MCP server in seconds
13423
-
13424
- USAGE
13425
- npx @solongate/proxy create <name> [options]
13426
-
13427
- OPTIONS
13428
- --policy <file> Policy JSON file (default: cloud-managed)
13429
- --no-install Skip dependency installation
13430
- -h, --help Show this help message
13431
-
13432
- EXAMPLES
13433
- npx @solongate/proxy create my-server
13434
- npx @solongate/proxy create db-tools --policy ./policy.json
13435
- `);
13436
- }
13437
- function createProject(dir, name, _policy) {
13438
- writeFileSync11(
13439
- join16(dir, "package.json"),
13440
- JSON.stringify(
13441
- {
13442
- name,
13443
- version: "0.1.0",
13444
- type: "module",
13445
- private: true,
13446
- bin: { [name]: "./dist/index.js" },
13447
- scripts: {
13448
- build: "tsup src/index.ts --format esm",
13449
- dev: "tsx --env-file=.env src/index.ts",
13450
- start: "node --env-file=.env dist/index.js"
13451
- },
13452
- dependencies: {
13453
- "@modelcontextprotocol/sdk": "^1.26.0",
13454
- "@solongate/proxy": "latest",
13455
- zod: "^3.25.0"
13456
- },
13457
- devDependencies: {
13458
- "@types/node": "^22.0.0",
13459
- tsup: "^8.3.0",
13460
- tsx: "^4.19.0",
13461
- typescript: "^5.7.0"
13462
- }
13463
- },
13464
- null,
13465
- 2
13466
- ) + "\n"
13467
- );
13468
- writeFileSync11(
13469
- join16(dir, "tsconfig.json"),
13470
- JSON.stringify(
13471
- {
13472
- compilerOptions: {
13473
- target: "ES2022",
13474
- module: "ESNext",
13475
- moduleResolution: "bundler",
13476
- esModuleInterop: true,
13477
- strict: true,
13478
- outDir: "dist",
13479
- rootDir: "src",
13480
- declaration: true,
13481
- skipLibCheck: true
13482
- },
13483
- include: ["src"]
13484
- },
13485
- null,
13486
- 2
13487
- ) + "\n"
13488
- );
13489
- mkdirSync10(join16(dir, "src"), { recursive: true });
13490
- writeFileSync11(
13491
- join16(dir, "src", "index.ts"),
13492
- `#!/usr/bin/env node
13493
-
13494
- console.log = (...args: unknown[]) => {
13495
- process.stderr.write(args.map(String).join(' ') + '\\n');
13496
- };
13497
-
13498
- import { SecureMcpServer } from '@solongate/proxy';
13499
- import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
13500
- import { z } from 'zod';
13501
-
13502
- // Policy is managed from the SolonGate Dashboard (https://solongate.com)
13503
- // No local policySet needed \u2014 it's fetched from the cloud via your API key.
13504
- const server = new SecureMcpServer(
13505
- { name: '${name}', version: '0.1.0' },
13506
- );
13507
-
13508
- server.tool(
13509
- 'hello',
13510
- 'Say hello to someone',
13511
- { name: z.string().describe('Name of the person to greet') },
13512
- async ({ name }: { name: string }) => ({
13513
- content: [{ type: 'text', text: \`Hello, \${name}! Welcome to ${name}.\` }],
13514
- }),
13515
- );
13516
-
13517
- const transport = new StdioServerTransport();
13518
- await server.connect(transport);
13519
- console.log('');
13520
- console.log('${name} is running (stdio mode)');
13521
- console.log('');
13522
- console.log('MCP servers communicate over stdin/stdout \u2014 not HTTP.');
13523
- console.log('You need an MCP client to connect:');
13524
- console.log('');
13525
- console.log(' Claude Code Open this folder, .mcp.json is auto-detected');
13526
- console.log(' Antigravity .agents/mcp_config.json (or ~/.gemini/config/mcp_config.json)');
13527
- console.log(' OpenClaw Uses openclaw.plugin.json config');
13528
- console.log('');
13529
- console.log('Press Ctrl+C to stop.');
13530
- `
13531
- );
13532
- writeFileSync11(
13533
- join16(dir, ".mcp.json"),
13534
- JSON.stringify(
13535
- {
13536
- mcpServers: {
13537
- [name]: {
13538
- command: "node",
13539
- args: ["dist/index.js"],
13540
- env: {
13541
- SOLONGATE_API_KEY: "sg_live_YOUR_KEY_HERE"
13542
- }
13543
- }
13544
- }
13545
- },
13546
- null,
13547
- 2
13548
- ) + "\n"
13549
- );
13550
- writeFileSync11(
13551
- join16(dir, ".env"),
13552
- `SOLONGATE_API_KEY=sg_live_YOUR_KEY_HERE
13553
- `
13554
- );
13555
- writeFileSync11(
13556
- join16(dir, ".gitignore"),
13557
- `node_modules/
13558
- dist/
13559
- *.solongate-backup
13560
- .env
13561
- .env.local
13562
- .mcp.json
13563
- `
13564
- );
13565
- }
13566
- async function main2() {
13567
- const opts = parseCreateArgs(process.argv);
13568
- const dir = resolve8(opts.name);
13569
- printBanner("Create MCP Server");
13570
- if (existsSync9(dir)) {
13571
- log3(` ${c.red}Error:${c.reset} Directory "${opts.name}" already exists.`);
13572
- process.exit(1);
13573
- }
13574
- withSpinner(`Setting up ${opts.name}...`, () => {
13575
- mkdirSync10(dir, { recursive: true });
13576
- createProject(dir, opts.name, opts.policy);
13577
- });
13578
- if (!opts.noInstall) {
13579
- withSpinner("Installing dependencies...", () => {
13580
- execSync2("npm install", { cwd: dir, stdio: "pipe" });
13581
- });
13582
- }
13583
- log3("");
13584
- const stripAnsi = (s) => s.replace(/\x1b\[[0-9;]*m/g, "");
13585
- const W = 52;
13586
- const hr = "\u2500".repeat(W + 2);
13587
- const bLine = (text) => {
13588
- const visible = stripAnsi(text);
13589
- const padding = W - visible.length;
13590
- log3(` ${c.dim}\u2502${c.reset} ${text}${" ".repeat(Math.max(0, padding))} ${c.dim}\u2502${c.reset}`);
13591
- };
13592
- const bEmpty = () => log3(` ${c.dim}\u2502${c.reset} ${" ".repeat(W)} ${c.dim}\u2502${c.reset}`);
13593
- log3(` ${c.dim}\u256D${hr}\u256E${c.reset}`);
13594
- log3(` ${c.dim}\u2502${c.reset} ${c.green}${c.bold}\u2714 MCP Server created successfully!${c.reset}${" ".repeat(W - 35)} ${c.dim}\u2502${c.reset}`);
13595
- log3(` ${c.dim}\u251C${hr}\u2524${c.reset}`);
13596
- bEmpty();
13597
- bLine(`${c.yellow}Next steps:${c.reset}`);
13598
- bEmpty();
13599
- bLine(` ${c.cyan}$${c.reset} cd ${c.bold}${opts.name}${c.reset}`);
13600
- bLine(` ${c.cyan}$${c.reset} npm run build`);
13601
- bLine(` ${c.cyan}$${c.reset} npm run dev ${c.dim}# dev mode${c.reset}`);
13602
- bLine(` ${c.cyan}$${c.reset} npm start ${c.dim}# production${c.reset}`);
13603
- bEmpty();
13604
- log3(` ${c.dim}\u251C${hr}\u2524${c.reset}`);
13605
- bEmpty();
13606
- bLine(`${c.yellow}Set your API key:${c.reset}`);
13607
- bEmpty();
13608
- bLine(` ${c.cyan}$${c.reset} export SOLONGATE_API_KEY=${c.blue3}sg_live_xxx${c.reset}`);
13609
- bEmpty();
13610
- bLine(`${c.dim}https://dashboard.solongate.com/api-keys/${c.reset}`);
13611
- bEmpty();
13612
- log3(` ${c.dim}\u251C${hr}\u2524${c.reset}`);
13613
- bEmpty();
13614
- bLine(`${c.yellow}Use with any MCP server:${c.reset}`);
13615
- bEmpty();
13616
- bLine(` ${c.cyan}$${c.reset} solongate-proxy -- npx @modelcontextprotocol/server-filesystem .`);
13617
- bLine(` ${c.cyan}$${c.reset} solongate-proxy -- npx @playwright/mcp@latest`);
13618
- bLine(` ${c.dim}Wraps any MCP server or AI tool with SolonGate protection${c.reset}`);
13619
- bEmpty();
13620
- log3(` ${c.dim}\u251C${hr}\u2524${c.reset}`);
13621
- bEmpty();
13622
- bLine(`${c.yellow}Use with Claude Code / MCP client:${c.reset}`);
13623
- bEmpty();
13624
- bLine(` ${c.dim}1.${c.reset} Replace ${c.blue3}sg_live_YOUR_KEY_HERE${c.reset} in .mcp.json`);
13625
- bLine(` ${c.dim}2.${c.reset} Open this folder in your MCP client`);
13626
- bLine(` ${c.dim}3.${c.reset} .mcp.json is auto-detected on startup`);
13627
- bEmpty();
13628
- bLine(`${c.yellow}Direct test (without MCP client):${c.reset}`);
13629
- bEmpty();
13630
- bLine(` ${c.dim}1.${c.reset} Replace ${c.blue3}sg_live_YOUR_KEY_HERE${c.reset} in .env`);
13631
- bLine(` ${c.dim}2.${c.reset} ${c.cyan}$${c.reset} npm run build && npm start`);
13632
- bEmpty();
13633
- log3(` ${c.dim}\u2570${hr}\u256F${c.reset}`);
13634
- log3("");
13635
- }
13636
- var init_create = __esm({
13637
- "src/create.ts"() {
13638
- "use strict";
13639
- init_cli_utils();
13640
- main2().catch((err2) => {
13641
- log3(`Fatal: ${err2 instanceof Error ? err2.message : String(err2)}`);
13642
- process.exit(1);
13643
- });
13644
- }
13645
- });
13646
-
13647
12596
  // src/pull-push.ts
13648
12597
  var pull_push_exports = {};
13649
- import { readFileSync as readFileSync14, writeFileSync as writeFileSync12, existsSync as existsSync10 } from "fs";
13650
- import { resolve as resolve9 } from "path";
12598
+ import { readFileSync as readFileSync12, writeFileSync as writeFileSync10, existsSync as existsSync7 } from "fs";
12599
+ import { resolve as resolve6 } from "path";
13651
12600
  function loadEnv() {
13652
12601
  if (process.env.SOLONGATE_API_KEY) return;
13653
- const envPath = resolve9(".env");
13654
- if (!existsSync10(envPath)) return;
12602
+ const envPath = resolve6(".env");
12603
+ if (!existsSync7(envPath)) return;
13655
12604
  try {
13656
- const content = readFileSync14(envPath, "utf-8");
12605
+ const content = readFileSync12(envPath, "utf-8");
13657
12606
  for (const line of content.split("\n")) {
13658
12607
  const trimmed = line.trim();
13659
12608
  if (!trimmed || trimmed.startsWith("#")) continue;
@@ -13695,20 +12644,20 @@ function parseCliArgs() {
13695
12644
  }
13696
12645
  }
13697
12646
  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}`);
12647
+ log3(red2("ERROR: API key not found."));
12648
+ log3("");
12649
+ log3("Set it in .env file:");
12650
+ log3(" SOLONGATE_API_KEY=sg_live_...");
12651
+ log3("");
12652
+ log3("Or pass via environment:");
12653
+ log3(` SOLONGATE_API_KEY=sg_live_... solongate-proxy ${command}`);
13705
12654
  process.exit(1);
13706
12655
  }
13707
12656
  if (!apiKey.startsWith("sg_live_")) {
13708
- log5(red2("ERROR: Pull/push/list requires a live API key (sg_live_...)."));
12657
+ log3(red2("ERROR: Pull/push/list requires a live API key (sg_live_...)."));
13709
12658
  process.exit(1);
13710
12659
  }
13711
- return { command, apiKey, file: resolve9(file), policyId };
12660
+ return { command, apiKey, file: resolve6(file), policyId };
13712
12661
  }
13713
12662
  async function listPolicies(apiKey) {
13714
12663
  const res = await fetch(`${API_URL}/api/v1/policies`, {
@@ -13721,18 +12670,18 @@ async function listPolicies(apiKey) {
13721
12670
  async function list5(apiKey, policyId) {
13722
12671
  const policies = await listPolicies(apiKey);
13723
12672
  if (policies.length === 0) {
13724
- log5(yellow2("No policies found. Create one in the dashboard first."));
13725
- log5(dim2(" https://dashboard.solongate.com/policies"));
12673
+ log3(yellow2("No policies found. Create one in the dashboard first."));
12674
+ log3(dim2(" https://dashboard.solongate.com/policies"));
13726
12675
  return;
13727
12676
  }
13728
12677
  if (policyId) {
13729
12678
  const match = policies.find((p) => p.id === policyId);
13730
12679
  if (!match) {
13731
- log5(red2(`Policy not found: ${policyId}`));
13732
- log5("");
13733
- log5("Available policies:");
12680
+ log3(red2(`Policy not found: ${policyId}`));
12681
+ log3("");
12682
+ log3("Available policies:");
13734
12683
  for (const p of policies) {
13735
- log5(` ${dim2("\u2022")} ${p.id}`);
12684
+ log3(` ${dim2("\u2022")} ${p.id}`);
13736
12685
  }
13737
12686
  process.exit(1);
13738
12687
  }
@@ -13740,10 +12689,10 @@ async function list5(apiKey, policyId) {
13740
12689
  printPolicyDetail(full);
13741
12690
  return;
13742
12691
  }
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("");
12692
+ log3("");
12693
+ log3(bold2(` Policies (${policies.length})`));
12694
+ log3(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"));
12695
+ log3("");
13747
12696
  const fullPolicies = await Promise.all(
13748
12697
  policies.map(
13749
12698
  (p) => fetchCloudPolicy(apiKey, API_URL, p.id).then((full) => ({ policy: p, rules: full.rules })).catch(() => ({ policy: p, rules: [] }))
@@ -13752,136 +12701,136 @@ async function list5(apiKey, policyId) {
13752
12701
  for (const { policy, rules } of fullPolicies) {
13753
12702
  printPolicySummary(policy, [...rules]);
13754
12703
  }
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("");
12704
+ log3(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"));
12705
+ log3("");
12706
+ log3(` ${dim2("View details:")} solongate-proxy list --policy-id <ID>`);
12707
+ log3(` ${dim2("Pull policy:")} solongate-proxy pull --policy-id <ID>`);
12708
+ log3(` ${dim2("Push policy:")} solongate-proxy push --policy-id <ID>`);
12709
+ log3("");
13761
12710
  }
13762
12711
  function printPolicySummary(p, rules) {
13763
12712
  const ruleCount = rules.length;
13764
12713
  const allowCount = rules.filter((r) => r.effect === "ALLOW").length;
13765
12714
  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`)}`);
12715
+ log3(` ${cyan2(p.id)}`);
12716
+ log3(` ${bold2(p.name)} ${dim2(`v${p.version ?? "?"}`)}`);
12717
+ log3(` ${dim2("Rules:")} ${ruleCount} ${green2(`${allowCount} ALLOW`)} ${red2(`${denyCount} DENY`)}`);
13769
12718
  if (p.created_at) {
13770
- log5(` ${dim2("Updated:")} ${new Date(p.created_at).toLocaleString()}`);
12719
+ log3(` ${dim2("Updated:")} ${new Date(p.created_at).toLocaleString()}`);
13771
12720
  }
13772
- log5("");
12721
+ log3("");
13773
12722
  }
13774
12723
  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("");
12724
+ log3("");
12725
+ log3(bold2(` ${policy.name}`));
12726
+ log3(` ${dim2("ID:")} ${cyan2(policy.id)} ${dim2("Version:")} ${policy.version} ${dim2("Rules:")} ${policy.rules.length}`);
12727
+ log3("");
13779
12728
  if (policy.rules.length === 0) {
13780
- log5(yellow2(" No rules defined."));
13781
- log5("");
12729
+ log3(yellow2(" No rules defined."));
12730
+ log3("");
13782
12731
  return;
13783
12732
  }
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"));
12733
+ log3(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
12734
  for (const rule of policy.rules) {
13786
12735
  const effectColor = rule.effect === "ALLOW" ? green2 : red2;
13787
- log5("");
13788
- log5(` ${effectColor(rule.effect.padEnd(5))} ${bold2(rule.toolPattern)} ${dim2(`P:${rule.priority}`)}`);
12736
+ log3("");
12737
+ log3(` ${effectColor(rule.effect.padEnd(5))} ${bold2(rule.toolPattern)} ${dim2(`P:${rule.priority}`)}`);
13789
12738
  if (rule.description) {
13790
- log5(` ${dim2(rule.description)}`);
12739
+ log3(` ${dim2(rule.description)}`);
13791
12740
  }
13792
- log5(` ${dim2(`${rule.permission} trust:${rule.minimumTrustLevel || "UNTRUSTED"}`)}`);
12741
+ log3(` ${dim2(`${rule.permission} trust:${rule.minimumTrustLevel || "UNTRUSTED"}`)}`);
13793
12742
  if (rule.pathConstraints) {
13794
12743
  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(", ")}`);
12744
+ if (pc.rootDirectory) log3(` ${magenta("ROOT")} ${pc.rootDirectory}`);
12745
+ if (pc.allowed?.length) log3(` ${green2("PATHS")} ${pc.allowed.join(", ")}`);
12746
+ if (pc.denied?.length) log3(` ${red2("DENY")} ${pc.denied.join(", ")}`);
13798
12747
  }
13799
12748
  if (rule.commandConstraints) {
13800
12749
  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(", ")}`);
12750
+ if (cc.allowed?.length) log3(` ${green2("CMDS")} ${cc.allowed.join(", ")}`);
12751
+ if (cc.denied?.length) log3(` ${red2("DENY")} ${cc.denied.join(", ")}`);
13803
12752
  }
13804
12753
  if (rule.filenameConstraints) {
13805
12754
  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(", ")}`);
12755
+ if (fc.allowed?.length) log3(` ${green2("FILES")} ${fc.allowed.join(", ")}`);
12756
+ if (fc.denied?.length) log3(` ${red2("DENY")} ${fc.denied.join(", ")}`);
13808
12757
  }
13809
12758
  if (rule.urlConstraints) {
13810
12759
  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(", ")}`);
12760
+ if (uc.allowed?.length) log3(` ${green2("URLS")} ${uc.allowed.join(", ")}`);
12761
+ if (uc.denied?.length) log3(` ${red2("DENY")} ${uc.denied.join(", ")}`);
13813
12762
  }
13814
12763
  }
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("");
12764
+ log3("");
12765
+ log3(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"));
12766
+ log3("");
13818
12767
  }
13819
12768
  async function pull(apiKey, file, policyId) {
13820
12769
  if (!policyId) {
13821
12770
  const policies = await listPolicies(apiKey);
13822
12771
  if (policies.length === 0) {
13823
- log5(red2("No policies found. Create one in the dashboard first."));
12772
+ log3(red2("No policies found. Create one in the dashboard first."));
13824
12773
  process.exit(1);
13825
12774
  }
13826
12775
  if (policies.length === 1) {
13827
12776
  policyId = policies[0].id;
13828
- log5(dim2(`Auto-selecting only policy: ${policyId}`));
12777
+ log3(dim2(`Auto-selecting only policy: ${policyId}`));
13829
12778
  } else {
13830
- log5(yellow2(`Found ${policies.length} policies:`));
13831
- log5("");
12779
+ log3(yellow2(`Found ${policies.length} policies:`));
12780
+ log3("");
13832
12781
  for (const p of policies) {
13833
- log5(` ${cyan2(p.id)} ${p.name} ${dim2(`v${p.version ?? "?"}`)}`);
12782
+ log3(` ${cyan2(p.id)} ${p.name} ${dim2(`v${p.version ?? "?"}`)}`);
13834
12783
  }
13835
- log5("");
13836
- log5("Use --policy-id <ID> to specify which one to pull.");
12784
+ log3("");
12785
+ log3("Use --policy-id <ID> to specify which one to pull.");
13837
12786
  process.exit(1);
13838
12787
  }
13839
12788
  }
13840
- log5(`Pulling ${cyan2(policyId)} from dashboard...`);
12789
+ log3(`Pulling ${cyan2(policyId)} from dashboard...`);
13841
12790
  const policy = await fetchCloudPolicy(apiKey, API_URL, policyId);
13842
12791
  const { id: _id, ...policyWithoutId } = policy;
13843
12792
  const json = JSON.stringify(policyWithoutId, null, 2) + "\n";
13844
- 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("");
12793
+ writeFileSync10(file, json, "utf-8");
12794
+ log3("");
12795
+ log3(green2(" Saved to: ") + file);
12796
+ log3(` ${dim2("Name:")} ${policy.name}`);
12797
+ log3(` ${dim2("Version:")} ${policy.version}`);
12798
+ log3(` ${dim2("Rules:")} ${policy.rules.length}`);
12799
+ log3("");
12800
+ log3(dim2("The policy file does not contain an ID."));
12801
+ log3(dim2("Use --policy-id to specify the target when pushing/pulling."));
12802
+ log3("");
13854
12803
  }
13855
12804
  async function push(apiKey, file, policyId) {
13856
- if (!existsSync10(file)) {
13857
- log5(red2(`ERROR: File not found: ${file}`));
12805
+ if (!existsSync7(file)) {
12806
+ log3(red2(`ERROR: File not found: ${file}`));
13858
12807
  process.exit(1);
13859
12808
  }
13860
12809
  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");
12810
+ log3(red2("ERROR: --policy-id is required for push."));
12811
+ log3("");
12812
+ log3("This determines which cloud policy to update.");
12813
+ log3("");
12814
+ log3("Usage:");
12815
+ log3(" solongate-proxy push --policy-id my-policy");
12816
+ log3(" solongate-proxy push --policy-id my-policy --file custom.json");
12817
+ log3("");
12818
+ log3("List your policies:");
12819
+ log3(" solongate-proxy list");
13871
12820
  process.exit(1);
13872
12821
  }
13873
- const content = readFileSync14(file, "utf-8");
12822
+ const content = readFileSync12(file, "utf-8");
13874
12823
  let policy;
13875
12824
  try {
13876
12825
  policy = JSON.parse(content);
13877
12826
  } catch {
13878
- log5(red2(`ERROR: Invalid JSON in ${file}`));
12827
+ log3(red2(`ERROR: Invalid JSON in ${file}`));
13879
12828
  process.exit(1);
13880
12829
  }
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}`);
12830
+ log3(`Pushing to ${cyan2(policyId)}...`);
12831
+ log3(` ${dim2("File:")} ${file}`);
12832
+ log3(` ${dim2("Name:")} ${policy.name || "Unnamed"}`);
12833
+ log3(` ${dim2("Rules:")} ${(policy.rules || []).length}`);
13885
12834
  const checkRes = await fetch(`${API_URL}/api/v1/policies/${policyId}`, {
13886
12835
  headers: { "Authorization": `Bearer ${apiKey}` }
13887
12836
  });
@@ -13903,17 +12852,17 @@ async function push(apiKey, file, policyId) {
13903
12852
  });
13904
12853
  if (!res.ok) {
13905
12854
  const body = await res.text().catch(() => "");
13906
- log5(red2(`ERROR: Push failed (${res.status}): ${body}`));
12855
+ log3(red2(`ERROR: Push failed (${res.status}): ${body}`));
13907
12856
  process.exit(1);
13908
12857
  }
13909
12858
  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("");
12859
+ log3("");
12860
+ log3(green2(` Pushed to cloud: v${data._version ?? "created"}`));
12861
+ log3(` ${dim2("Policy ID:")} ${policyId}`);
12862
+ log3(` ${dim2("Method:")} ${method === "PUT" ? "Updated existing" : "Created new"}`);
12863
+ log3("");
13915
12864
  }
13916
- async function main3() {
12865
+ async function main() {
13917
12866
  const { command, apiKey, file, policyId } = parseCliArgs();
13918
12867
  try {
13919
12868
  if (command === "pull") {
@@ -13923,32 +12872,32 @@ async function main3() {
13923
12872
  } else if (command === "list" || command === "ls") {
13924
12873
  await list5(apiKey, policyId);
13925
12874
  } 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("");
12875
+ log3(red2(`Unknown command: ${command}`));
12876
+ log3("");
12877
+ log3(bold2("Usage:"));
12878
+ log3(" solongate-proxy list List all policies");
12879
+ log3(" solongate-proxy list --policy-id <ID> Show policy details");
12880
+ log3(" solongate-proxy pull --policy-id <ID> Pull policy to local file");
12881
+ log3(" solongate-proxy push --policy-id <ID> Push local file to cloud");
12882
+ log3("");
12883
+ log3(bold2("Flags:"));
12884
+ log3(" --policy-id, --id <ID> Cloud policy ID (required for push)");
12885
+ log3(" --file, -f <path> Local file path (default: policy.json)");
12886
+ log3(" --api-key <key> API key (or set SOLONGATE_API_KEY)");
12887
+ log3("");
13939
12888
  process.exit(1);
13940
12889
  }
13941
12890
  } catch (err2) {
13942
- log5(red2(`ERROR: ${err2 instanceof Error ? err2.message : String(err2)}`));
12891
+ log3(red2(`ERROR: ${err2 instanceof Error ? err2.message : String(err2)}`));
13943
12892
  process.exit(1);
13944
12893
  }
13945
12894
  }
13946
- var log5, dim2, bold2, green2, red2, yellow2, cyan2, magenta, API_URL;
12895
+ var log3, dim2, bold2, green2, red2, yellow2, cyan2, magenta, API_URL;
13947
12896
  var init_pull_push = __esm({
13948
12897
  "src/pull-push.ts"() {
13949
12898
  "use strict";
13950
12899
  init_config();
13951
- log5 = (...args) => process.stderr.write(`${args.map(String).join(" ")}
12900
+ log3 = (...args) => process.stderr.write(`${args.map(String).join(" ")}
13952
12901
  `);
13953
12902
  dim2 = (s) => `\x1B[2m${s}\x1B[0m`;
13954
12903
  bold2 = (s) => `\x1B[1m${s}\x1B[0m`;
@@ -13958,15 +12907,15 @@ var init_pull_push = __esm({
13958
12907
  cyan2 = (s) => `\x1B[36m${s}\x1B[0m`;
13959
12908
  magenta = (s) => `\x1B[35m${s}\x1B[0m`;
13960
12909
  API_URL = "https://api.solongate.com";
13961
- main3();
12910
+ main();
13962
12911
  }
13963
12912
  });
13964
12913
 
13965
12914
  // src/index.ts
13966
12915
  init_config();
13967
- import { readFileSync as readFileSync15 } from "fs";
12916
+ import { readFileSync as readFileSync13 } from "fs";
13968
12917
  import { fileURLToPath as fileURLToPath4 } from "url";
13969
- import { dirname as dirname4, join as join17 } from "path";
12918
+ import { dirname as dirname4, join as join16 } from "path";
13970
12919
 
13971
12920
  // src/proxy.ts
13972
12921
  import { Server } from "@modelcontextprotocol/sdk/server/index.js";
@@ -16390,7 +15339,7 @@ var Mutex = class {
16390
15339
  this.locked = true;
16391
15340
  return;
16392
15341
  }
16393
- return new Promise((resolve10, reject) => {
15342
+ return new Promise((resolve7, reject) => {
16394
15343
  const timer = setTimeout(() => {
16395
15344
  const idx = this.queue.indexOf(onReady);
16396
15345
  if (idx !== -1) this.queue.splice(idx, 1);
@@ -16398,7 +15347,7 @@ var Mutex = class {
16398
15347
  }, timeoutMs);
16399
15348
  const onReady = () => {
16400
15349
  clearTimeout(timer);
16401
- resolve10();
15350
+ resolve7();
16402
15351
  };
16403
15352
  this.queue.push(onReady);
16404
15353
  });
@@ -16989,7 +15938,7 @@ ${msg.content.text}`;
16989
15938
 
16990
15939
  // src/index.ts
16991
15940
  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"]);
15941
+ var CLI_SUBCOMMANDS = /* @__PURE__ */ new Set(["pull", "push", "list", "ls", "logs-server", "local-logs", "policy", "ratelimit", "dlp", "stats", "audit", "agents", "agent", "doctor", "watch", "alerts", "webhooks", "dataroom"]);
16993
15942
  var CLI_INFO_ARGS = /* @__PURE__ */ new Set(["login", "help", "--help", "-h", "--version", "-v", "version"]);
16994
15943
  var IS_HUMAN_CLI = process.argv.length <= 2 || CLI_SUBCOMMANDS.has(process.argv[2] ?? "") || CLI_INFO_ARGS.has(process.argv[2] ?? "");
16995
15944
  if (!IS_HUMAN_CLI) {
@@ -17008,8 +15957,8 @@ if (!IS_HUMAN_CLI) {
17008
15957
  }
17009
15958
  var PKG_VERSION = (() => {
17010
15959
  try {
17011
- const p = join17(dirname4(fileURLToPath4(import.meta.url)), "..", "package.json");
17012
- return JSON.parse(readFileSync15(p, "utf-8")).version || "unknown";
15960
+ const p = join16(dirname4(fileURLToPath4(import.meta.url)), "..", "package.json");
15961
+ return JSON.parse(readFileSync13(p, "utf-8")).version || "unknown";
17013
15962
  } catch {
17014
15963
  return "unknown";
17015
15964
  }
@@ -17028,7 +15977,7 @@ function printWelcome() {
17028
15977
  console.log(` ${c.dim}Manage it at ${c.reset}${c.cyan}https://dashboard.solongate.com${c.reset}`);
17029
15978
  console.log("");
17030
15979
  }
17031
- function printHelp3() {
15980
+ function printHelp() {
17032
15981
  const W = 46;
17033
15982
  const head = (t) => console.log(`
17034
15983
  ${c.bold}${t}${c.reset}`);
@@ -17051,7 +16000,6 @@ function printHelp3() {
17051
16000
  head("Setup & status");
17052
16001
  cmd("solongate", "open the dataroom UI (login, policies, audit, settings)");
17053
16002
  cmd("doctor [--json]", "health check: login, policy, guard, local logs");
17054
- cmd("create", "scaffold a guarded MCP server in this folder");
17055
16003
  cmd("logs-server", "serve local audit logs to the dashboard");
17056
16004
  head("Policies");
17057
16005
  cmd("policy list", "list all policies");
@@ -17090,12 +16038,7 @@ function printHelp3() {
17090
16038
  cmd("webhooks list");
17091
16039
  cmd("webhooks add --url <https://\u2026> [--events denials|allowed|all]", "event webhook");
17092
16040
  cmd("webhooks remove <id>");
17093
- head("Keys, MCP & advanced");
17094
- cmd("keys list", "list API keys (prefix only)");
17095
- cmd("keys create --name <name>", "create a key (secret shown once)");
17096
- cmd("keys revoke <id>", "revoke a key");
17097
- cmd("mcp", "list protected MCP servers");
17098
- cmd("shield -- <command>", "wrap a command with LLM-path secret redaction");
16041
+ head("Policy sync");
17099
16042
  cmd("pull --policy-id <ID> [--file f]", "pull a cloud policy to a local file");
17100
16043
  cmd("push --policy-id <ID> [--file f]", "push a local policy file to the cloud");
17101
16044
  console.log("");
@@ -17103,10 +16046,10 @@ function printHelp3() {
17103
16046
  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}`);
17104
16047
  console.log("");
17105
16048
  }
17106
- async function main4() {
16049
+ async function main2() {
17107
16050
  const subcommand = process.argv[2];
17108
16051
  if (subcommand === "--help" || subcommand === "-h" || subcommand === "help") {
17109
- printHelp3();
16052
+ printHelp();
17110
16053
  return;
17111
16054
  }
17112
16055
  if (subcommand === "--version" || subcommand === "-v" || subcommand === "version") {
@@ -17138,7 +16081,7 @@ async function main4() {
17138
16081
  await launchTui2();
17139
16082
  return;
17140
16083
  }
17141
- const MGMT_COMMANDS = /* @__PURE__ */ new Set(["policy", "ratelimit", "dlp", "stats", "audit", "agents", "agent", "doctor", "watch", "keys", "mcp", "alerts", "webhooks"]);
16084
+ const MGMT_COMMANDS = /* @__PURE__ */ new Set(["policy", "ratelimit", "dlp", "stats", "audit", "agents", "agent", "doctor", "watch", "alerts", "webhooks"]);
17142
16085
  if (MGMT_COMMANDS.has(subcommand ?? "")) {
17143
16086
  const { runCommand: runCommand2 } = await Promise.resolve().then(() => (init_commands(), commands_exports));
17144
16087
  const code = await runCommand2(subcommand, process.argv.slice(3));
@@ -17151,26 +16094,11 @@ async function main4() {
17151
16094
  console.log("");
17152
16095
  return;
17153
16096
  }
17154
- if (subcommand === "shield") {
17155
- const { runShield: runShield2 } = await Promise.resolve().then(() => (init_shield(), shield_exports));
17156
- await runShield2();
17157
- return;
17158
- }
17159
16097
  if (subcommand === "logs-server" || subcommand === "local-logs") {
17160
16098
  const { runLogsServer: runLogsServer2 } = await Promise.resolve().then(() => (init_logs_server(), logs_server_exports));
17161
16099
  await runLogsServer2();
17162
16100
  return;
17163
16101
  }
17164
- if (subcommand === "inject") {
17165
- process.argv.splice(2, 1);
17166
- await Promise.resolve().then(() => (init_inject(), inject_exports));
17167
- return;
17168
- }
17169
- if (subcommand === "create") {
17170
- process.argv.splice(2, 1);
17171
- await Promise.resolve().then(() => (init_create(), create_exports));
17172
- return;
17173
- }
17174
16102
  if (subcommand === "pull" || subcommand === "push" || subcommand === "list" || subcommand === "ls") {
17175
16103
  await Promise.resolve().then(() => (init_pull_push(), pull_push_exports));
17176
16104
  return;
@@ -17197,4 +16125,4 @@ async function main4() {
17197
16125
  process.exit(1);
17198
16126
  }
17199
16127
  }
17200
- main4();
16128
+ main2();