@solongate/proxy 0.81.74 → 0.81.76
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 +33 -52
- package/dist/shield.js +1 -0
- package/dist/tui/index.js +31 -51
- package/hooks/audit.mjs +7 -0
- package/hooks/guard.bundled.mjs +4 -1
- package/hooks/guard.mjs +4 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -9390,9 +9390,9 @@ function DlpPanel({ focused }) {
|
|
|
9390
9390
|
entry: idx
|
|
9391
9391
|
});
|
|
9392
9392
|
});
|
|
9393
|
-
header("h:custom", "custom patterns", "
|
|
9394
|
-
note("n:custom-help", "
|
|
9395
|
-
if ((dlp?.custom.length ?? 0) === 0) note("n:custom", " (none \u2014 press a to add a name +
|
|
9393
|
+
header("h:custom", "custom patterns", "a add \xB7 d remove");
|
|
9394
|
+
note("n:custom-help", " same glob syntax as ghost, * = any chars, e.g. sk-* AKIA* *PRIVATE KEY*");
|
|
9395
|
+
if ((dlp?.custom.length ?? 0) === 0) note("n:custom", " (none \u2014 press a to add a name + pattern)");
|
|
9396
9396
|
(dlp?.custom ?? []).forEach((c2, i) => {
|
|
9397
9397
|
const isCur = focused && ei === selC;
|
|
9398
9398
|
const idx = ei++;
|
|
@@ -9420,7 +9420,7 @@ function DlpPanel({ focused }) {
|
|
|
9420
9420
|
entry: idx
|
|
9421
9421
|
});
|
|
9422
9422
|
});
|
|
9423
|
-
const editRows = adding
|
|
9423
|
+
const editRows = adding ? 1 : 0;
|
|
9424
9424
|
const headerRows = 2 + editRows + (status ? 1 : 0);
|
|
9425
9425
|
const budget = Math.max(3, rows - headerRows - 1);
|
|
9426
9426
|
const selLine = Math.max(0, lines.findIndex((l) => l.entry === selC));
|
|
@@ -9437,59 +9437,40 @@ function DlpPanel({ focused }) {
|
|
|
9437
9437
|
dirty ? /* @__PURE__ */ jsx5(Text5, { color: theme.warn, children: " \u25CF unsaved (s save \xB7 x discard)" }) : null
|
|
9438
9438
|
] }),
|
|
9439
9439
|
/* @__PURE__ */ jsx5(Text5, { color: theme.dim, wrap: "truncate", children: focused ? `\u2191\u2193 move \xB7 space on/off \xB7 m mode \xB7 a add pattern \xB7 r add route \xB7 d remove \xB7 g ghost \xB7 s save${moreAbove ? ` \xB7 \u25B2${moreAbove}` : ""}${moreBelow ? ` \xB7 \u25BC${moreBelow}` : ""}` : "press \u2192 to edit" }),
|
|
9440
|
-
adding ? /* @__PURE__ */
|
|
9441
|
-
/* @__PURE__ */
|
|
9442
|
-
|
|
9443
|
-
|
|
9444
|
-
|
|
9445
|
-
|
|
9446
|
-
|
|
9447
|
-
|
|
9448
|
-
|
|
9449
|
-
|
|
9450
|
-
if (
|
|
9451
|
-
|
|
9452
|
-
|
|
9453
|
-
|
|
9454
|
-
|
|
9455
|
-
|
|
9456
|
-
|
|
9457
|
-
|
|
9458
|
-
|
|
9459
|
-
|
|
9460
|
-
|
|
9461
|
-
|
|
9462
|
-
setStatus(null);
|
|
9463
|
-
}
|
|
9464
|
-
setAdding(null);
|
|
9440
|
+
adding ? /* @__PURE__ */ jsx5(Box5, { flexDirection: "column", children: /* @__PURE__ */ jsxs5(Box5, { children: [
|
|
9441
|
+
/* @__PURE__ */ jsx5(Text5, { color: theme.warn, children: adding === "name" ? "new pattern name: " : adding === "re" ? `pattern for "${newName}" (glob, * = any chars, e.g. sk-* AKIA*): ` : "ghost path to hide (glob, * = any chars, e.g. */.env *.pem): " }),
|
|
9442
|
+
/* @__PURE__ */ jsx5(
|
|
9443
|
+
TextInput3,
|
|
9444
|
+
{
|
|
9445
|
+
value: input,
|
|
9446
|
+
onChange: setInput,
|
|
9447
|
+
onSubmit: (v) => {
|
|
9448
|
+
const t = v.trim();
|
|
9449
|
+
if (adding === "name") {
|
|
9450
|
+
if (!t) return setAdding(null);
|
|
9451
|
+
setNewName(t);
|
|
9452
|
+
setInput("");
|
|
9453
|
+
setAdding("re");
|
|
9454
|
+
} else if (adding === "re") {
|
|
9455
|
+
if (t && dlp) mutate({ ...dlp, custom: [...dlp.custom, { name: newName, re: t }] });
|
|
9456
|
+
setAdding(null);
|
|
9457
|
+
} else {
|
|
9458
|
+
if (t && !ghostPats.includes(t)) {
|
|
9459
|
+
setGhostPats((ps) => [...ps, t]);
|
|
9460
|
+
setDirty(true);
|
|
9461
|
+
setStatus(null);
|
|
9465
9462
|
}
|
|
9463
|
+
setAdding(null);
|
|
9466
9464
|
}
|
|
9467
9465
|
}
|
|
9468
|
-
|
|
9469
|
-
|
|
9470
|
-
|
|
9471
|
-
] }) : null,
|
|
9466
|
+
}
|
|
9467
|
+
)
|
|
9468
|
+
] }) }) : null,
|
|
9472
9469
|
/* @__PURE__ */ jsx5(Box5, { marginTop: 1, flexDirection: "column", height: budget, overflow: "hidden", children: win.map((l) => l.node) }),
|
|
9473
9470
|
status ? /* @__PURE__ */ jsx5(Text5, { color: status.startsWith("\u2717") ? theme.bad : theme.ok, wrap: "truncate", children: status }) : null
|
|
9474
9471
|
] }) : null });
|
|
9475
9472
|
}
|
|
9476
|
-
|
|
9477
|
-
if (!re.trim()) return /* @__PURE__ */ jsx5(Text5, { color: theme.dim, children: " regex: type a pattern\u2026" });
|
|
9478
|
-
let rx = null;
|
|
9479
|
-
let err2 = "";
|
|
9480
|
-
try {
|
|
9481
|
-
rx = new RegExp(re);
|
|
9482
|
-
} catch (e) {
|
|
9483
|
-
err2 = e instanceof Error ? e.message : String(e);
|
|
9484
|
-
}
|
|
9485
|
-
if (!rx) return /* @__PURE__ */ jsx5(Text5, { color: theme.bad, children: ` \u2717 invalid: ${err2.slice(0, 50)}` });
|
|
9486
|
-
const hits = SAMPLES.filter((s) => rx.test(s));
|
|
9487
|
-
return /* @__PURE__ */ jsxs5(Text5, { wrap: "truncate", children: [
|
|
9488
|
-
/* @__PURE__ */ jsx5(Text5, { color: theme.ok, children: " \u2713 valid" }),
|
|
9489
|
-
/* @__PURE__ */ jsx5(Text5, { color: theme.dim, children: hits.length ? ` matches ${hits.length}/${SAMPLES.length} samples: ${hits.map((h) => h.slice(0, 8)).join(", ")}` : " (no sample match \u2014 will only catch your custom secrets)" })
|
|
9490
|
-
] });
|
|
9491
|
-
}
|
|
9492
|
-
var MODES2, SAMPLES;
|
|
9473
|
+
var MODES2;
|
|
9493
9474
|
var init_Dlp = __esm({
|
|
9494
9475
|
"src/tui/panels/Dlp.tsx"() {
|
|
9495
9476
|
"use strict";
|
|
@@ -9498,7 +9479,6 @@ var init_Dlp = __esm({
|
|
|
9498
9479
|
init_hooks();
|
|
9499
9480
|
init_theme();
|
|
9500
9481
|
MODES2 = ["off", "detect", "block"];
|
|
9501
|
-
SAMPLES = ["AKIA1234567890ABCD00", "sk-ant-api03-xxxxxxxx", "ghp_16chars0000000000000000000000000000", "password=hunter2", "Bearer eyJhbGciOi"];
|
|
9502
9482
|
}
|
|
9503
9483
|
});
|
|
9504
9484
|
|
|
@@ -11156,7 +11136,7 @@ var init_App = __esm({
|
|
|
11156
11136
|
["Live", [["\u2191\u2193", "select a stream row"], ["enter", "full entry content"], ["w", "whitelist the selected DENY"], ["b", "block the selected ALLOW"], ["d / x / r", "filter denies / dlp / rate-limit"], ["f", "local / cloud filter"], ["/", "search"], ["s", "sessions (\u2191\u2193 pick, enter open)"], ["space", "copy mode (freeze)"]]],
|
|
11157
11137
|
["Policies", [["\u2191\u2193", "browse / select"], ["a", "activate (pin) selected policy"], ["x", "deactivate \u2014 no active policy"], ["enter", "open rules \u2192 open a rule"], ["space", "toggle a rule on/off"], ["e", "flip effect"], ["n", "new rule"], ["d", "delete rule"], ["m", "flip mode"], ["D", "dry-run the draft"], ["s", "save"], ["x", "discard"]]],
|
|
11158
11138
|
["Rate limit", [["\u2191\u2193", "field"], ["\u2190\u2192", "adjust (shift = \xB110)"], ["s", "save"]]],
|
|
11159
|
-
["DLP", [["\u2191\u2193", "move"], ["space", "toggle a built-in pattern on/off"], ["m", "cycle mode"], ["a", "add custom pattern (name \u2192
|
|
11139
|
+
["DLP", [["\u2191\u2193", "move"], ["space", "toggle a built-in pattern on/off"], ["m", "cycle mode"], ["a", "add custom pattern (name \u2192 glob, * = any chars)"], ["r", "add a ghost route (glob path to hide)"], ["d", "remove custom / route"], ["g", "ghost on/off"], ["s", "save \xB7 x discard"]]],
|
|
11160
11140
|
["Audit", [["v", "logs \u2194 sessions"], ["s", "source: cloud \u2194 local"], ["\u2190 \u2192", "prev / next page (500 each)"], ["\u2191\u2193", "select (list scrolls)"], ["enter", "full entry / session logs"], ["f / g", "decision / signal filter"], ["t / n / /", "tool / agent / search"], ["x / X", "delete entry / ALL (press twice)"], ["c", "clear filters"]]],
|
|
11161
11141
|
["Settings", [["\u2191\u2193", "move"], ["enter / space", "toggle \xB7 edit \xB7 add"], ["e", "webhook events"], ["d d", "delete"], ["r", "refresh"]]],
|
|
11162
11142
|
["Accounts", [["a", "switch account (view another account logged in on this device)"], ["", "the header shows which account you are viewing; guard/logging keep the active key"]]]
|
|
@@ -12687,6 +12667,7 @@ function redactDeep(value, cfg) {
|
|
|
12687
12667
|
if (typeof value === "string") {
|
|
12688
12668
|
let out2 = redactString(value, cfg);
|
|
12689
12669
|
if (ghost && ghost.length) out2 = ghostStripLines(out2, ghost);
|
|
12670
|
+
if (out2 === "" && value !== "") out2 = "\n";
|
|
12690
12671
|
return out2;
|
|
12691
12672
|
}
|
|
12692
12673
|
if (Array.isArray(value)) {
|
package/dist/shield.js
CHANGED
|
@@ -182,6 +182,7 @@ function redactDeep(value, cfg) {
|
|
|
182
182
|
if (typeof value === "string") {
|
|
183
183
|
let out = redactString(value, cfg);
|
|
184
184
|
if (ghost && ghost.length) out = ghostStripLines(out, ghost);
|
|
185
|
+
if (out === "" && value !== "") out = "\n";
|
|
185
186
|
return out;
|
|
186
187
|
}
|
|
187
188
|
if (Array.isArray(value)) {
|
package/dist/tui/index.js
CHANGED
|
@@ -2438,9 +2438,9 @@ function DlpPanel({ focused }) {
|
|
|
2438
2438
|
entry: idx
|
|
2439
2439
|
});
|
|
2440
2440
|
});
|
|
2441
|
-
header("h:custom", "custom patterns", "
|
|
2442
|
-
note("n:custom-help", "
|
|
2443
|
-
if ((dlp?.custom.length ?? 0) === 0) note("n:custom", " (none \u2014 press a to add a name +
|
|
2441
|
+
header("h:custom", "custom patterns", "a add \xB7 d remove");
|
|
2442
|
+
note("n:custom-help", " same glob syntax as ghost, * = any chars, e.g. sk-* AKIA* *PRIVATE KEY*");
|
|
2443
|
+
if ((dlp?.custom.length ?? 0) === 0) note("n:custom", " (none \u2014 press a to add a name + pattern)");
|
|
2444
2444
|
(dlp?.custom ?? []).forEach((c2, i) => {
|
|
2445
2445
|
const isCur = focused && ei === selC;
|
|
2446
2446
|
const idx = ei++;
|
|
@@ -2468,7 +2468,7 @@ function DlpPanel({ focused }) {
|
|
|
2468
2468
|
entry: idx
|
|
2469
2469
|
});
|
|
2470
2470
|
});
|
|
2471
|
-
const editRows = adding
|
|
2471
|
+
const editRows = adding ? 1 : 0;
|
|
2472
2472
|
const headerRows = 2 + editRows + (status ? 1 : 0);
|
|
2473
2473
|
const budget = Math.max(3, rows - headerRows - 1);
|
|
2474
2474
|
const selLine = Math.max(0, lines.findIndex((l) => l.entry === selC));
|
|
@@ -2485,59 +2485,39 @@ function DlpPanel({ focused }) {
|
|
|
2485
2485
|
dirty ? /* @__PURE__ */ jsx5(Text5, { color: theme.warn, children: " \u25CF unsaved (s save \xB7 x discard)" }) : null
|
|
2486
2486
|
] }),
|
|
2487
2487
|
/* @__PURE__ */ jsx5(Text5, { color: theme.dim, wrap: "truncate", children: focused ? `\u2191\u2193 move \xB7 space on/off \xB7 m mode \xB7 a add pattern \xB7 r add route \xB7 d remove \xB7 g ghost \xB7 s save${moreAbove ? ` \xB7 \u25B2${moreAbove}` : ""}${moreBelow ? ` \xB7 \u25BC${moreBelow}` : ""}` : "press \u2192 to edit" }),
|
|
2488
|
-
adding ? /* @__PURE__ */
|
|
2489
|
-
/* @__PURE__ */
|
|
2490
|
-
|
|
2491
|
-
|
|
2492
|
-
|
|
2493
|
-
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
|
|
2497
|
-
|
|
2498
|
-
if (
|
|
2499
|
-
|
|
2500
|
-
|
|
2501
|
-
|
|
2502
|
-
|
|
2503
|
-
|
|
2504
|
-
|
|
2505
|
-
|
|
2506
|
-
|
|
2507
|
-
|
|
2508
|
-
|
|
2509
|
-
|
|
2510
|
-
setStatus(null);
|
|
2511
|
-
}
|
|
2512
|
-
setAdding(null);
|
|
2488
|
+
adding ? /* @__PURE__ */ jsx5(Box5, { flexDirection: "column", children: /* @__PURE__ */ jsxs5(Box5, { children: [
|
|
2489
|
+
/* @__PURE__ */ jsx5(Text5, { color: theme.warn, children: adding === "name" ? "new pattern name: " : adding === "re" ? `pattern for "${newName}" (glob, * = any chars, e.g. sk-* AKIA*): ` : "ghost path to hide (glob, * = any chars, e.g. */.env *.pem): " }),
|
|
2490
|
+
/* @__PURE__ */ jsx5(
|
|
2491
|
+
TextInput3,
|
|
2492
|
+
{
|
|
2493
|
+
value: input,
|
|
2494
|
+
onChange: setInput,
|
|
2495
|
+
onSubmit: (v) => {
|
|
2496
|
+
const t = v.trim();
|
|
2497
|
+
if (adding === "name") {
|
|
2498
|
+
if (!t) return setAdding(null);
|
|
2499
|
+
setNewName(t);
|
|
2500
|
+
setInput("");
|
|
2501
|
+
setAdding("re");
|
|
2502
|
+
} else if (adding === "re") {
|
|
2503
|
+
if (t && dlp) mutate({ ...dlp, custom: [...dlp.custom, { name: newName, re: t }] });
|
|
2504
|
+
setAdding(null);
|
|
2505
|
+
} else {
|
|
2506
|
+
if (t && !ghostPats.includes(t)) {
|
|
2507
|
+
setGhostPats((ps) => [...ps, t]);
|
|
2508
|
+
setDirty(true);
|
|
2509
|
+
setStatus(null);
|
|
2513
2510
|
}
|
|
2511
|
+
setAdding(null);
|
|
2514
2512
|
}
|
|
2515
2513
|
}
|
|
2516
|
-
|
|
2517
|
-
|
|
2518
|
-
|
|
2519
|
-
] }) : null,
|
|
2514
|
+
}
|
|
2515
|
+
)
|
|
2516
|
+
] }) }) : null,
|
|
2520
2517
|
/* @__PURE__ */ jsx5(Box5, { marginTop: 1, flexDirection: "column", height: budget, overflow: "hidden", children: win.map((l) => l.node) }),
|
|
2521
2518
|
status ? /* @__PURE__ */ jsx5(Text5, { color: status.startsWith("\u2717") ? theme.bad : theme.ok, wrap: "truncate", children: status }) : null
|
|
2522
2519
|
] }) : null });
|
|
2523
2520
|
}
|
|
2524
|
-
var SAMPLES = ["AKIA1234567890ABCD00", "sk-ant-api03-xxxxxxxx", "ghp_16chars0000000000000000000000000000", "password=hunter2", "Bearer eyJhbGciOi"];
|
|
2525
|
-
function RegexTest({ re }) {
|
|
2526
|
-
if (!re.trim()) return /* @__PURE__ */ jsx5(Text5, { color: theme.dim, children: " regex: type a pattern\u2026" });
|
|
2527
|
-
let rx = null;
|
|
2528
|
-
let err = "";
|
|
2529
|
-
try {
|
|
2530
|
-
rx = new RegExp(re);
|
|
2531
|
-
} catch (e) {
|
|
2532
|
-
err = e instanceof Error ? e.message : String(e);
|
|
2533
|
-
}
|
|
2534
|
-
if (!rx) return /* @__PURE__ */ jsx5(Text5, { color: theme.bad, children: ` \u2717 invalid: ${err.slice(0, 50)}` });
|
|
2535
|
-
const hits = SAMPLES.filter((s) => rx.test(s));
|
|
2536
|
-
return /* @__PURE__ */ jsxs5(Text5, { wrap: "truncate", children: [
|
|
2537
|
-
/* @__PURE__ */ jsx5(Text5, { color: theme.ok, children: " \u2713 valid" }),
|
|
2538
|
-
/* @__PURE__ */ jsx5(Text5, { color: theme.dim, children: hits.length ? ` matches ${hits.length}/${SAMPLES.length} samples: ${hits.map((h) => h.slice(0, 8)).join(", ")}` : " (no sample match \u2014 will only catch your custom secrets)" })
|
|
2539
|
-
] });
|
|
2540
|
-
}
|
|
2541
2521
|
|
|
2542
2522
|
// src/tui/panels/Audit.tsx
|
|
2543
2523
|
import { Box as Box6, Text as Text6, useInput as useInput5 } from "ink";
|
|
@@ -4121,7 +4101,7 @@ var HELP = [
|
|
|
4121
4101
|
["Live", [["\u2191\u2193", "select a stream row"], ["enter", "full entry content"], ["w", "whitelist the selected DENY"], ["b", "block the selected ALLOW"], ["d / x / r", "filter denies / dlp / rate-limit"], ["f", "local / cloud filter"], ["/", "search"], ["s", "sessions (\u2191\u2193 pick, enter open)"], ["space", "copy mode (freeze)"]]],
|
|
4122
4102
|
["Policies", [["\u2191\u2193", "browse / select"], ["a", "activate (pin) selected policy"], ["x", "deactivate \u2014 no active policy"], ["enter", "open rules \u2192 open a rule"], ["space", "toggle a rule on/off"], ["e", "flip effect"], ["n", "new rule"], ["d", "delete rule"], ["m", "flip mode"], ["D", "dry-run the draft"], ["s", "save"], ["x", "discard"]]],
|
|
4123
4103
|
["Rate limit", [["\u2191\u2193", "field"], ["\u2190\u2192", "adjust (shift = \xB110)"], ["s", "save"]]],
|
|
4124
|
-
["DLP", [["\u2191\u2193", "move"], ["space", "toggle a built-in pattern on/off"], ["m", "cycle mode"], ["a", "add custom pattern (name \u2192
|
|
4104
|
+
["DLP", [["\u2191\u2193", "move"], ["space", "toggle a built-in pattern on/off"], ["m", "cycle mode"], ["a", "add custom pattern (name \u2192 glob, * = any chars)"], ["r", "add a ghost route (glob path to hide)"], ["d", "remove custom / route"], ["g", "ghost on/off"], ["s", "save \xB7 x discard"]]],
|
|
4125
4105
|
["Audit", [["v", "logs \u2194 sessions"], ["s", "source: cloud \u2194 local"], ["\u2190 \u2192", "prev / next page (500 each)"], ["\u2191\u2193", "select (list scrolls)"], ["enter", "full entry / session logs"], ["f / g", "decision / signal filter"], ["t / n / /", "tool / agent / search"], ["x / X", "delete entry / ALL (press twice)"], ["c", "clear filters"]]],
|
|
4126
4106
|
["Settings", [["\u2191\u2193", "move"], ["enter / space", "toggle \xB7 edit \xB7 add"], ["e", "webhook events"], ["d d", "delete"], ["r", "refresh"]]],
|
|
4127
4107
|
["Accounts", [["a", "switch account (view another account logged in on this device)"], ["", "the header shows which account you are viewing; guard/logging keep the active key"]]]
|
package/hooks/audit.mjs
CHANGED
|
@@ -565,6 +565,13 @@ try { input += readFileSync(0, 'utf-8'); } catch {}
|
|
|
565
565
|
}
|
|
566
566
|
}
|
|
567
567
|
if (typeof out === 'string') {
|
|
568
|
+
// Never emit EMPTY content. When ghost/DLP stripping removes every line
|
|
569
|
+
// (e.g. a grep/cat that hit only hidden or secret lines) and the tool
|
|
570
|
+
// ALSO errored, the resulting tool_result is is_error:true with empty
|
|
571
|
+
// content — which the API rejects ("content cannot be empty if is_error
|
|
572
|
+
// is true") and hard-crashes the whole agent conversation. Fall back to
|
|
573
|
+
// a bare newline: still looks like empty output, but is non-empty.
|
|
574
|
+
if (out === '') out = '\n';
|
|
568
575
|
// Preserve the tool's result SHAPE. Bash and other tools deliver a
|
|
569
576
|
// STRUCTURED result ({ stdout, stderr, ... } or { content }); Claude
|
|
570
577
|
// Code rejects a bare-string replacement for those (hook warning) and
|
package/hooks/guard.bundled.mjs
CHANGED
|
@@ -6808,7 +6808,10 @@ function blockTool(reason) {
|
|
|
6808
6808
|
hookSpecificOutput: {
|
|
6809
6809
|
hookEventName: "PreToolUse",
|
|
6810
6810
|
permissionDecision: "deny",
|
|
6811
|
-
|
|
6811
|
+
// Never empty: a deny with an empty reason becomes an is_error tool_result
|
|
6812
|
+
// with empty content, which the API rejects and crashes the agent. Always
|
|
6813
|
+
// carry a SolonGate-worded reason so the block says WHAT stopped it.
|
|
6814
|
+
permissionDecisionReason: reason || "[SolonGate] Blocked by policy"
|
|
6812
6815
|
}
|
|
6813
6816
|
}));
|
|
6814
6817
|
sgFinish(0);
|
package/hooks/guard.mjs
CHANGED
|
@@ -395,7 +395,10 @@ function blockTool(reason) {
|
|
|
395
395
|
hookSpecificOutput: {
|
|
396
396
|
hookEventName: 'PreToolUse',
|
|
397
397
|
permissionDecision: 'deny',
|
|
398
|
-
|
|
398
|
+
// Never empty: a deny with an empty reason becomes an is_error tool_result
|
|
399
|
+
// with empty content, which the API rejects and crashes the agent. Always
|
|
400
|
+
// carry a SolonGate-worded reason so the block says WHAT stopped it.
|
|
401
|
+
permissionDecisionReason: reason || '[SolonGate] Blocked by policy',
|
|
399
402
|
},
|
|
400
403
|
}));
|
|
401
404
|
sgFinish(0);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@solongate/proxy",
|
|
3
|
-
"version": "0.81.
|
|
3
|
+
"version": "0.81.76",
|
|
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": {
|