@solongate/proxy 0.82.49 → 0.82.50

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
@@ -9223,6 +9223,7 @@ function PoliciesPanel({ focused }) {
9223
9223
  const [editVal, setEditVal] = useState4("");
9224
9224
  const [status, setStatus] = useState4(null);
9225
9225
  const [pendingDel, setPendingDel] = useState4(null);
9226
+ const [permCursor, setPermCursor] = useState4(0);
9226
9227
  const selected = policies[Math.min(pi, Math.max(0, policies.length - 1))];
9227
9228
  const detail = useLoader(() => selected ? api.policies.get(selected.id) : Promise.resolve(null), [selected?.id]);
9228
9229
  useEffect4(() => {
@@ -9365,7 +9366,7 @@ function PoliciesPanel({ focused }) {
9365
9366
  } else if (input === "m") {
9366
9367
  mutate(rules, mode === "denylist" ? "whitelist" : "denylist");
9367
9368
  } else if (input === "n") {
9368
- const nr = { id: `rule-${Date.now()}`, description: "", effect: "DENY", priority: 100, toolPattern: "*", minimumTrustLevel: "UNTRUSTED", enabled: true };
9369
+ const nr = { id: `rule-${Date.now()}`, description: "", effect: "DENY", priority: 100, toolPattern: "*", minimumTrustLevel: "UNTRUSTED", enabled: true, commandConstraints: { denied: [] } };
9369
9370
  mutate([nr, ...rules]);
9370
9371
  setRi(0);
9371
9372
  setFi(0);
@@ -9393,13 +9394,21 @@ function PoliciesPanel({ focused }) {
9393
9394
  const dir = key.leftArrow ? -1 : 1;
9394
9395
  const nextT = CTYPES[(CTYPES.indexOf(currentCType(rule2)) + dir + CTYPES.length) % CTYPES.length];
9395
9396
  mutate(rules.map((r, i) => i === ri ? setCType(r, nextT) : r));
9396
- } else if (field.kind === "perms" && (input === "r" || input === "w" || input === "e" || input === "n")) {
9397
- const p = { r: "READ", w: "WRITE", e: "EXECUTE", n: "NETWORK" }[input];
9397
+ } else if (field.kind === "perms" && key.leftArrow) {
9398
+ setPermCursor((n) => (n + PERMS.length - 1) % PERMS.length);
9399
+ } else if (field.kind === "perms" && key.rightArrow) {
9400
+ setPermCursor((n) => (n + 1) % PERMS.length);
9401
+ } else if (field.kind === "perms" && input === " ") {
9402
+ const p = PERMS[permCursor % PERMS.length];
9398
9403
  mutate(rules.map((rr, i) => i === ri ? togglePerm(rr, p) : rr));
9404
+ } else if (field.kind === "match" && input === "[") {
9405
+ mutate(rules.map((rr, i) => i === ri ? toggleStar(rr, "left") : rr));
9406
+ } else if (field.kind === "match" && input === "]") {
9407
+ mutate(rules.map((rr, i) => i === ri ? toggleStar(rr, "right") : rr));
9399
9408
  } else if (field.kind === "priority" && (key.rightArrow || key.leftArrow)) {
9400
9409
  const d = key.rightArrow ? 1 : -1;
9401
9410
  mutate(rules.map((r, i) => i === ri ? { ...r, priority: Math.max(0, r.priority + d) } : r));
9402
- } else if (field.kind === "text" && key.return) {
9411
+ } else if ((field.kind === "text" || field.kind === "match") && key.return) {
9403
9412
  setEditVal(field.get(rule2));
9404
9413
  setEditing(true);
9405
9414
  } else if (input === "s") void save();
@@ -9500,12 +9509,53 @@ function PoliciesPanel({ focused }) {
9500
9509
  /* @__PURE__ */ jsx4(Text4, { color: theme.dim, children: rule?.id ?? "" }),
9501
9510
  dirtyTag
9502
9511
  ] }),
9503
- /* @__PURE__ */ jsx4(Text4, { color: theme.dim, children: "\u2191\u2193 field \xB7 enter edit text \xB7 space/\u2192 toggle \xB7 r/w/e/n perms \xB7 s save \xB7 \u2190 back" }),
9512
+ /* @__PURE__ */ jsx4(Text4, { color: theme.dim, children: "\u2191\u2193 field \xB7 enter edit \xB7 space toggle \xB7 \u2190\u2192 move/pick \xB7 [ ] wildcards \xB7 s save \xB7 \u2190 back" }),
9504
9513
  /* @__PURE__ */ jsx4(Box4, { marginTop: 1, flexDirection: "column", children: FIELDS.map((f, i) => {
9505
- const val = rule ? f.get(rule) : "";
9506
9514
  const active2 = i === fi;
9515
+ const label = /* @__PURE__ */ jsx4(Text4, { color: active2 ? theme.accentBright : void 0, children: (active2 ? "\u25B8 " : " ") + f.label.padEnd(13) });
9516
+ if (f.kind === "perms" && rule) {
9517
+ return /* @__PURE__ */ jsxs4(Box4, { children: [
9518
+ label,
9519
+ PERMS.map((p, pi2) => {
9520
+ const on = permList(rule).includes(p);
9521
+ const cur = active2 && pi2 === permCursor % PERMS.length;
9522
+ return /* @__PURE__ */ jsxs4(Text4, { color: on ? theme.ok : theme.bad, inverse: cur, children: [
9523
+ p,
9524
+ pi2 < PERMS.length - 1 ? " " : ""
9525
+ ] }, p);
9526
+ })
9527
+ ] }, f.label);
9528
+ }
9529
+ if (f.kind === "match" && rule) {
9530
+ if (active2 && editing) {
9531
+ return /* @__PURE__ */ jsxs4(Box4, { children: [
9532
+ label,
9533
+ /* @__PURE__ */ jsx4(
9534
+ TextInput3,
9535
+ {
9536
+ value: editVal,
9537
+ onChange: setEditVal,
9538
+ onSubmit: (v2) => {
9539
+ if (f.set) mutate(rules.map((r, idx) => idx === ri ? f.set(r, v2) : r));
9540
+ setEditing(false);
9541
+ }
9542
+ }
9543
+ )
9544
+ ] }, f.label);
9545
+ }
9546
+ const v = f.get(rule);
9547
+ const lOn = starActive(rule, "left");
9548
+ const rOn = starActive(rule, "right");
9549
+ return /* @__PURE__ */ jsxs4(Box4, { children: [
9550
+ label,
9551
+ /* @__PURE__ */ jsx4(Text4, { color: lOn ? theme.ok : theme.dim, children: lOn ? "\u2731 " : "\xB7 " }),
9552
+ /* @__PURE__ */ jsx4(Text4, { dimColor: !v, children: v || "\u2014" }),
9553
+ /* @__PURE__ */ jsx4(Text4, { color: rOn ? theme.ok : theme.dim, children: rOn ? " \u2731" : " \xB7" })
9554
+ ] }, f.label);
9555
+ }
9556
+ const val = rule ? f.get(rule) : "";
9507
9557
  return /* @__PURE__ */ jsxs4(Box4, { children: [
9508
- /* @__PURE__ */ jsx4(Text4, { color: active2 ? theme.accentBright : void 0, children: (active2 ? "\u25B8 " : " ") + f.label.padEnd(13) }),
9558
+ label,
9509
9559
  active2 && editing && f.kind === "text" ? /* @__PURE__ */ jsx4(
9510
9560
  TextInput3,
9511
9561
  {
@@ -9526,10 +9576,11 @@ function PoliciesPanel({ focused }) {
9526
9576
  )
9527
9577
  ] }, f.label);
9528
9578
  }) }),
9579
+ /* @__PURE__ */ jsx4(Text4, { color: theme.dim, children: " * = wildcard (matches any run of chars). On Match: [ toggles a leading *, ] a trailing * \xB7 e.g. *ping* matches any command containing ping" }),
9529
9580
  status ? /* @__PURE__ */ jsx4(Text4, { color: status.startsWith("\u2717") ? theme.bad : theme.ok, children: status }) : null
9530
9581
  ] });
9531
9582
  }
9532
- var CTYPES, CTYPE_GROUP, currentCType, clearConstraints, setCType, cValue, setCValue, migrateEffect, PERMS, permList, permIsAny, togglePerm, permDisplay, ruleHasValues, isBlanketRule, FIELDS;
9583
+ var CTYPES, CTYPE_GROUP, currentCType, clearConstraints, setCType, cValue, setCValue, matchItems, starActive, toggleStar, migrateEffect, PERMS, permList, permIsAny, togglePerm, permDisplay, ruleHasValues, isBlanketRule, FIELDS;
9533
9584
  var init_Policies = __esm({
9534
9585
  "src/tui/panels/Policies.tsx"() {
9535
9586
  "use strict";
@@ -9579,6 +9630,26 @@ var init_Policies = __esm({
9579
9630
  const listKey = r.effect === "ALLOW" ? "allowed" : "denied";
9580
9631
  return { ...r, [CTYPE_GROUP[t]]: { [listKey]: arr } };
9581
9632
  };
9633
+ matchItems = (r) => {
9634
+ const t = currentCType(r);
9635
+ if (t === "none") return [];
9636
+ const c2 = r[CTYPE_GROUP[t]];
9637
+ return [...c2?.allowed ?? [], ...c2?.denied ?? []];
9638
+ };
9639
+ starActive = (r, side) => {
9640
+ const items = matchItems(r);
9641
+ return items.length > 0 && items.every((v) => side === "left" ? v.startsWith("*") : v.endsWith("*"));
9642
+ };
9643
+ toggleStar = (r, side) => {
9644
+ const t = currentCType(r);
9645
+ if (t === "none") return r;
9646
+ const on = starActive(r, side);
9647
+ const listKey = r.effect === "ALLOW" ? "allowed" : "denied";
9648
+ const items = matchItems(r).map(
9649
+ (v) => side === "left" ? on ? v.replace(/^\*+/, "") : "*" + v : on ? v.replace(/\*+$/, "") : v + "*"
9650
+ );
9651
+ return { ...r, [CTYPE_GROUP[t]]: { [listKey]: items } };
9652
+ };
9582
9653
  migrateEffect = (r, nextEffect) => {
9583
9654
  const flipped = { ...r, effect: nextEffect };
9584
9655
  const t = currentCType(r);
@@ -9611,7 +9682,7 @@ var init_Policies = __esm({
9611
9682
  { label: "Permissions", kind: "perms", get: permDisplay },
9612
9683
  { label: "Priority", kind: "priority", get: (r) => String(r.priority) },
9613
9684
  { label: "Description", kind: "text", get: (r) => r.description ?? "", set: (r, v) => ({ ...r, description: v }) },
9614
- { label: "Match", kind: "text", get: cValue, set: setCValue }
9685
+ { label: "Match", kind: "match", get: cValue, set: setCValue }
9615
9686
  ];
9616
9687
  }
9617
9688
  });
package/dist/tui/index.js CHANGED
@@ -2460,6 +2460,26 @@ var setCValue = (r, val) => {
2460
2460
  const listKey = r.effect === "ALLOW" ? "allowed" : "denied";
2461
2461
  return { ...r, [CTYPE_GROUP[t]]: { [listKey]: arr } };
2462
2462
  };
2463
+ var matchItems = (r) => {
2464
+ const t = currentCType(r);
2465
+ if (t === "none") return [];
2466
+ const c2 = r[CTYPE_GROUP[t]];
2467
+ return [...c2?.allowed ?? [], ...c2?.denied ?? []];
2468
+ };
2469
+ var starActive = (r, side) => {
2470
+ const items = matchItems(r);
2471
+ return items.length > 0 && items.every((v) => side === "left" ? v.startsWith("*") : v.endsWith("*"));
2472
+ };
2473
+ var toggleStar = (r, side) => {
2474
+ const t = currentCType(r);
2475
+ if (t === "none") return r;
2476
+ const on = starActive(r, side);
2477
+ const listKey = r.effect === "ALLOW" ? "allowed" : "denied";
2478
+ const items = matchItems(r).map(
2479
+ (v) => side === "left" ? on ? v.replace(/^\*+/, "") : "*" + v : on ? v.replace(/\*+$/, "") : v + "*"
2480
+ );
2481
+ return { ...r, [CTYPE_GROUP[t]]: { [listKey]: items } };
2482
+ };
2463
2483
  var migrateEffect = (r, nextEffect) => {
2464
2484
  const flipped = { ...r, effect: nextEffect };
2465
2485
  const t = currentCType(r);
@@ -2492,7 +2512,7 @@ var FIELDS = [
2492
2512
  { label: "Permissions", kind: "perms", get: permDisplay },
2493
2513
  { label: "Priority", kind: "priority", get: (r) => String(r.priority) },
2494
2514
  { label: "Description", kind: "text", get: (r) => r.description ?? "", set: (r, v) => ({ ...r, description: v }) },
2495
- { label: "Match", kind: "text", get: cValue, set: setCValue }
2515
+ { label: "Match", kind: "match", get: cValue, set: setCValue }
2496
2516
  ];
2497
2517
  function ruleSummary(r) {
2498
2518
  const bits = [];
@@ -2521,6 +2541,7 @@ function PoliciesPanel({ focused }) {
2521
2541
  const [editVal, setEditVal] = useState4("");
2522
2542
  const [status, setStatus] = useState4(null);
2523
2543
  const [pendingDel, setPendingDel] = useState4(null);
2544
+ const [permCursor, setPermCursor] = useState4(0);
2524
2545
  const selected = policies[Math.min(pi, Math.max(0, policies.length - 1))];
2525
2546
  const detail = useLoader(() => selected ? api.policies.get(selected.id) : Promise.resolve(null), [selected?.id]);
2526
2547
  useEffect4(() => {
@@ -2663,7 +2684,7 @@ function PoliciesPanel({ focused }) {
2663
2684
  } else if (input === "m") {
2664
2685
  mutate(rules, mode === "denylist" ? "whitelist" : "denylist");
2665
2686
  } else if (input === "n") {
2666
- const nr = { id: `rule-${Date.now()}`, description: "", effect: "DENY", priority: 100, toolPattern: "*", minimumTrustLevel: "UNTRUSTED", enabled: true };
2687
+ const nr = { id: `rule-${Date.now()}`, description: "", effect: "DENY", priority: 100, toolPattern: "*", minimumTrustLevel: "UNTRUSTED", enabled: true, commandConstraints: { denied: [] } };
2667
2688
  mutate([nr, ...rules]);
2668
2689
  setRi(0);
2669
2690
  setFi(0);
@@ -2691,13 +2712,21 @@ function PoliciesPanel({ focused }) {
2691
2712
  const dir = key.leftArrow ? -1 : 1;
2692
2713
  const nextT = CTYPES[(CTYPES.indexOf(currentCType(rule2)) + dir + CTYPES.length) % CTYPES.length];
2693
2714
  mutate(rules.map((r, i) => i === ri ? setCType(r, nextT) : r));
2694
- } else if (field.kind === "perms" && (input === "r" || input === "w" || input === "e" || input === "n")) {
2695
- const p = { r: "READ", w: "WRITE", e: "EXECUTE", n: "NETWORK" }[input];
2715
+ } else if (field.kind === "perms" && key.leftArrow) {
2716
+ setPermCursor((n) => (n + PERMS.length - 1) % PERMS.length);
2717
+ } else if (field.kind === "perms" && key.rightArrow) {
2718
+ setPermCursor((n) => (n + 1) % PERMS.length);
2719
+ } else if (field.kind === "perms" && input === " ") {
2720
+ const p = PERMS[permCursor % PERMS.length];
2696
2721
  mutate(rules.map((rr, i) => i === ri ? togglePerm(rr, p) : rr));
2722
+ } else if (field.kind === "match" && input === "[") {
2723
+ mutate(rules.map((rr, i) => i === ri ? toggleStar(rr, "left") : rr));
2724
+ } else if (field.kind === "match" && input === "]") {
2725
+ mutate(rules.map((rr, i) => i === ri ? toggleStar(rr, "right") : rr));
2697
2726
  } else if (field.kind === "priority" && (key.rightArrow || key.leftArrow)) {
2698
2727
  const d = key.rightArrow ? 1 : -1;
2699
2728
  mutate(rules.map((r, i) => i === ri ? { ...r, priority: Math.max(0, r.priority + d) } : r));
2700
- } else if (field.kind === "text" && key.return) {
2729
+ } else if ((field.kind === "text" || field.kind === "match") && key.return) {
2701
2730
  setEditVal(field.get(rule2));
2702
2731
  setEditing(true);
2703
2732
  } else if (input === "s") void save();
@@ -2798,12 +2827,53 @@ function PoliciesPanel({ focused }) {
2798
2827
  /* @__PURE__ */ jsx4(Text4, { color: theme.dim, children: rule?.id ?? "" }),
2799
2828
  dirtyTag
2800
2829
  ] }),
2801
- /* @__PURE__ */ jsx4(Text4, { color: theme.dim, children: "\u2191\u2193 field \xB7 enter edit text \xB7 space/\u2192 toggle \xB7 r/w/e/n perms \xB7 s save \xB7 \u2190 back" }),
2830
+ /* @__PURE__ */ jsx4(Text4, { color: theme.dim, children: "\u2191\u2193 field \xB7 enter edit \xB7 space toggle \xB7 \u2190\u2192 move/pick \xB7 [ ] wildcards \xB7 s save \xB7 \u2190 back" }),
2802
2831
  /* @__PURE__ */ jsx4(Box4, { marginTop: 1, flexDirection: "column", children: FIELDS.map((f, i) => {
2803
- const val = rule ? f.get(rule) : "";
2804
2832
  const active2 = i === fi;
2833
+ const label = /* @__PURE__ */ jsx4(Text4, { color: active2 ? theme.accentBright : void 0, children: (active2 ? "\u25B8 " : " ") + f.label.padEnd(13) });
2834
+ if (f.kind === "perms" && rule) {
2835
+ return /* @__PURE__ */ jsxs4(Box4, { children: [
2836
+ label,
2837
+ PERMS.map((p, pi2) => {
2838
+ const on = permList(rule).includes(p);
2839
+ const cur = active2 && pi2 === permCursor % PERMS.length;
2840
+ return /* @__PURE__ */ jsxs4(Text4, { color: on ? theme.ok : theme.bad, inverse: cur, children: [
2841
+ p,
2842
+ pi2 < PERMS.length - 1 ? " " : ""
2843
+ ] }, p);
2844
+ })
2845
+ ] }, f.label);
2846
+ }
2847
+ if (f.kind === "match" && rule) {
2848
+ if (active2 && editing) {
2849
+ return /* @__PURE__ */ jsxs4(Box4, { children: [
2850
+ label,
2851
+ /* @__PURE__ */ jsx4(
2852
+ TextInput3,
2853
+ {
2854
+ value: editVal,
2855
+ onChange: setEditVal,
2856
+ onSubmit: (v2) => {
2857
+ if (f.set) mutate(rules.map((r, idx) => idx === ri ? f.set(r, v2) : r));
2858
+ setEditing(false);
2859
+ }
2860
+ }
2861
+ )
2862
+ ] }, f.label);
2863
+ }
2864
+ const v = f.get(rule);
2865
+ const lOn = starActive(rule, "left");
2866
+ const rOn = starActive(rule, "right");
2867
+ return /* @__PURE__ */ jsxs4(Box4, { children: [
2868
+ label,
2869
+ /* @__PURE__ */ jsx4(Text4, { color: lOn ? theme.ok : theme.dim, children: lOn ? "\u2731 " : "\xB7 " }),
2870
+ /* @__PURE__ */ jsx4(Text4, { dimColor: !v, children: v || "\u2014" }),
2871
+ /* @__PURE__ */ jsx4(Text4, { color: rOn ? theme.ok : theme.dim, children: rOn ? " \u2731" : " \xB7" })
2872
+ ] }, f.label);
2873
+ }
2874
+ const val = rule ? f.get(rule) : "";
2805
2875
  return /* @__PURE__ */ jsxs4(Box4, { children: [
2806
- /* @__PURE__ */ jsx4(Text4, { color: active2 ? theme.accentBright : void 0, children: (active2 ? "\u25B8 " : " ") + f.label.padEnd(13) }),
2876
+ label,
2807
2877
  active2 && editing && f.kind === "text" ? /* @__PURE__ */ jsx4(
2808
2878
  TextInput3,
2809
2879
  {
@@ -2824,6 +2894,7 @@ function PoliciesPanel({ focused }) {
2824
2894
  )
2825
2895
  ] }, f.label);
2826
2896
  }) }),
2897
+ /* @__PURE__ */ jsx4(Text4, { color: theme.dim, children: " * = wildcard (matches any run of chars). On Match: [ toggles a leading *, ] a trailing * \xB7 e.g. *ping* matches any command containing ping" }),
2827
2898
  status ? /* @__PURE__ */ jsx4(Text4, { color: status.startsWith("\u2717") ? theme.bad : theme.ok, children: status }) : null
2828
2899
  ] });
2829
2900
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@solongate/proxy",
3
- "version": "0.82.49",
3
+ "version": "0.82.50",
4
4
  "description": "AI tool security proxy: protect any AI tool server with customizable policies, path/command constraints, rate limiting, and audit logging. No code changes required.",
5
5
  "type": "module",
6
6
  "bin": {