@solongate/proxy 0.81.72 → 0.81.74
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 +148 -102
- package/dist/tui/index.js +148 -102
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -9273,28 +9273,26 @@ import TextInput3 from "ink-text-input";
|
|
|
9273
9273
|
import { useEffect as useEffect5, useState as useState5 } from "react";
|
|
9274
9274
|
import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
9275
9275
|
function DlpPanel({ focused }) {
|
|
9276
|
+
const { cols, rows } = usePanelSize();
|
|
9276
9277
|
const q = useLoader(() => api.settings.getSecurityLayers());
|
|
9277
9278
|
const [dlp, setDlp] = useState5(null);
|
|
9278
9279
|
const [available, setAvailable] = useState5([]);
|
|
9280
|
+
const [ghostOn, setGhostOn] = useState5(false);
|
|
9281
|
+
const [ghostPats, setGhostPats] = useState5([]);
|
|
9279
9282
|
const [sel, setSel] = useState5(0);
|
|
9280
9283
|
const [dirty, setDirty] = useState5(false);
|
|
9281
9284
|
const [status, setStatus] = useState5(null);
|
|
9282
9285
|
const [adding, setAdding] = useState5(null);
|
|
9283
9286
|
const [newName, setNewName] = useState5("");
|
|
9284
|
-
const [
|
|
9285
|
-
const [ghostOn, setGhostOn] = useState5(false);
|
|
9286
|
-
const spQ = useLoader(() => api.settings.getSelfProtection());
|
|
9287
|
-
const [selfProt, setSelfProt] = useState5(null);
|
|
9287
|
+
const [input, setInput] = useState5("");
|
|
9288
9288
|
useEffect5(() => {
|
|
9289
9289
|
if (q.data && !dlp) {
|
|
9290
9290
|
setDlp({ ...q.data.layers.dlp, patterns: [...q.data.layers.dlp.patterns], custom: [...q.data.layers.dlp.custom] });
|
|
9291
9291
|
setAvailable(q.data.availablePatterns);
|
|
9292
9292
|
setGhostOn(q.data.layers.ghost.mode === "on");
|
|
9293
|
+
setGhostPats([...q.data.layers.ghost.patterns]);
|
|
9293
9294
|
}
|
|
9294
9295
|
}, [q.data, dlp]);
|
|
9295
|
-
useEffect5(() => {
|
|
9296
|
-
if (spQ.data && selfProt === null) setSelfProt(spQ.data.enabled);
|
|
9297
|
-
}, [spQ.data, selfProt]);
|
|
9298
9296
|
const mutate = (next) => {
|
|
9299
9297
|
setDlp(next);
|
|
9300
9298
|
setDirty(true);
|
|
@@ -9304,128 +9302,175 @@ function DlpPanel({ focused }) {
|
|
|
9304
9302
|
if (!dlp || !q.data) return;
|
|
9305
9303
|
setStatus("Saving\u2026");
|
|
9306
9304
|
try {
|
|
9307
|
-
const ghost = {
|
|
9305
|
+
const ghost = { mode: ghostOn ? "on" : "off", patterns: ghostPats };
|
|
9308
9306
|
const res = await api.settings.setSecurityLayers({ ...q.data.layers, dlp, ghost });
|
|
9309
9307
|
setDlp({ ...res.layers.dlp, patterns: [...res.layers.dlp.patterns], custom: [...res.layers.dlp.custom] });
|
|
9310
9308
|
setGhostOn(res.layers.ghost.mode === "on");
|
|
9309
|
+
setGhostPats([...res.layers.ghost.patterns]);
|
|
9311
9310
|
setDirty(false);
|
|
9312
9311
|
setStatus("\u2713 Saved");
|
|
9313
9312
|
} catch (e) {
|
|
9314
9313
|
setStatus("\u2717 " + (e instanceof Error ? e.message : String(e)));
|
|
9315
9314
|
}
|
|
9316
9315
|
};
|
|
9317
|
-
const toggleSelfProt = async () => {
|
|
9318
|
-
const next = !(selfProt ?? false);
|
|
9319
|
-
setSelfProt(next);
|
|
9320
|
-
try {
|
|
9321
|
-
await api.settings.setSelfProtection(next);
|
|
9322
|
-
setStatus(`\u2713 self-protection ${next ? "on" : "off"}`);
|
|
9323
|
-
} catch (e) {
|
|
9324
|
-
setSelfProt(!next);
|
|
9325
|
-
setStatus("\u2717 " + (e instanceof Error ? e.message : String(e)));
|
|
9326
|
-
}
|
|
9327
|
-
};
|
|
9328
9316
|
const discard = () => {
|
|
9329
|
-
if (q.data)
|
|
9317
|
+
if (!q.data) return;
|
|
9318
|
+
setDlp({ ...q.data.layers.dlp, patterns: [...q.data.layers.dlp.patterns], custom: [...q.data.layers.dlp.custom] });
|
|
9319
|
+
setGhostOn(q.data.layers.ghost.mode === "on");
|
|
9320
|
+
setGhostPats([...q.data.layers.ghost.patterns]);
|
|
9330
9321
|
setDirty(false);
|
|
9331
9322
|
setStatus("discarded");
|
|
9332
9323
|
};
|
|
9333
|
-
const
|
|
9334
|
-
|
|
9324
|
+
const entries = [
|
|
9325
|
+
...available.map((name) => ({ kind: "builtin", name })),
|
|
9326
|
+
...(dlp?.custom ?? []).map((_, i) => ({ kind: "custom", i })),
|
|
9327
|
+
...ghostPats.map((_, i) => ({ kind: "ghost", i }))
|
|
9328
|
+
];
|
|
9329
|
+
const selC = Math.min(sel, Math.max(0, entries.length - 1));
|
|
9330
|
+
const cur = entries[selC];
|
|
9335
9331
|
useInput4(
|
|
9336
|
-
(
|
|
9332
|
+
(input2, key) => {
|
|
9337
9333
|
if (!dlp) return;
|
|
9338
|
-
if (key.upArrow) setSel((
|
|
9339
|
-
else if (key.downArrow) setSel((
|
|
9340
|
-
else if (
|
|
9341
|
-
|
|
9342
|
-
mutate({ ...dlp, mode: MODES2[idx] });
|
|
9343
|
-
} else if (input === "a") {
|
|
9344
|
-
setNewName("");
|
|
9345
|
-
setNewRe("");
|
|
9346
|
-
setAdding("name");
|
|
9347
|
-
} else if (input === " " && sel < available.length) {
|
|
9348
|
-
const p = available[sel];
|
|
9334
|
+
if (key.upArrow) setSel(() => Math.max(0, selC - 1));
|
|
9335
|
+
else if (key.downArrow) setSel(() => Math.min(entries.length - 1, selC + 1));
|
|
9336
|
+
else if (input2 === "m") mutate({ ...dlp, mode: MODES2[(MODES2.indexOf(dlp.mode) + 1) % MODES2.length] });
|
|
9337
|
+
else if (input2 === " " && cur?.kind === "builtin") {
|
|
9349
9338
|
const set = new Set(dlp.patterns);
|
|
9350
|
-
if (set.has(
|
|
9351
|
-
else set.add(
|
|
9339
|
+
if (set.has(cur.name)) set.delete(cur.name);
|
|
9340
|
+
else set.add(cur.name);
|
|
9352
9341
|
mutate({ ...dlp, patterns: [...set] });
|
|
9353
|
-
} else if (
|
|
9354
|
-
|
|
9355
|
-
|
|
9356
|
-
|
|
9357
|
-
} else if (
|
|
9342
|
+
} else if (input2 === "a") {
|
|
9343
|
+
setNewName("");
|
|
9344
|
+
setInput("");
|
|
9345
|
+
setAdding("name");
|
|
9346
|
+
} else if (input2 === "r") {
|
|
9347
|
+
setInput("");
|
|
9348
|
+
setAdding("route");
|
|
9349
|
+
} else if (input2 === "d") {
|
|
9350
|
+
if (cur?.kind === "custom") {
|
|
9351
|
+
mutate({ ...dlp, custom: dlp.custom.filter((_, i) => i !== cur.i) });
|
|
9352
|
+
setSel(() => Math.max(0, selC - 1));
|
|
9353
|
+
} else if (cur?.kind === "ghost") {
|
|
9354
|
+
setGhostPats((ps) => ps.filter((_, i) => i !== cur.i));
|
|
9355
|
+
setDirty(true);
|
|
9356
|
+
setStatus(null);
|
|
9357
|
+
setSel(() => Math.max(0, selC - 1));
|
|
9358
|
+
}
|
|
9359
|
+
} else if (input2 === "g") {
|
|
9358
9360
|
setGhostOn((v) => !v);
|
|
9359
9361
|
setDirty(true);
|
|
9360
9362
|
setStatus(null);
|
|
9361
|
-
} else if (
|
|
9362
|
-
else if (
|
|
9363
|
-
else if (input === "x") discard();
|
|
9363
|
+
} else if (input2 === "s") void save();
|
|
9364
|
+
else if (input2 === "x") discard();
|
|
9364
9365
|
},
|
|
9365
9366
|
{ isActive: focused && !adding }
|
|
9366
9367
|
);
|
|
9367
9368
|
const enabled = new Set(dlp?.patterns ?? []);
|
|
9369
|
+
const lines = [];
|
|
9370
|
+
const header = (key, label, extra) => lines.push({
|
|
9371
|
+
node: /* @__PURE__ */ jsxs5(Text5, { wrap: "truncate", children: [
|
|
9372
|
+
/* @__PURE__ */ jsx5(Text5, { color: theme.accentBright, bold: true, children: label }),
|
|
9373
|
+
extra ? /* @__PURE__ */ jsx5(Text5, { color: theme.dim, children: " " + extra }) : null
|
|
9374
|
+
] }, key),
|
|
9375
|
+
entry: -1
|
|
9376
|
+
});
|
|
9377
|
+
const note = (key, text) => lines.push({ node: /* @__PURE__ */ jsx5(Text5, { color: theme.dim, wrap: "truncate", children: text }, key), entry: -1 });
|
|
9378
|
+
let ei = 0;
|
|
9379
|
+
header("h:builtin", "built-in secret patterns", "space toggles on/off");
|
|
9380
|
+
available.forEach((p) => {
|
|
9381
|
+
const on = enabled.has(p);
|
|
9382
|
+
const isCur = focused && ei === selC;
|
|
9383
|
+
const idx = ei++;
|
|
9384
|
+
lines.push({
|
|
9385
|
+
node: /* @__PURE__ */ jsxs5(Text5, { wrap: "truncate", backgroundColor: isCur ? "#1c2f63" : void 0, bold: isCur, children: [
|
|
9386
|
+
/* @__PURE__ */ jsx5(Text5, { color: isCur ? theme.accentBright : theme.dim, children: isCur ? "\u25B8 " : " " }),
|
|
9387
|
+
/* @__PURE__ */ jsx5(Text5, { color: on ? theme.ok : theme.dim, children: on ? "\u25CF " : "\u25CB " }),
|
|
9388
|
+
/* @__PURE__ */ jsx5(Text5, { color: on ? void 0 : theme.dim, children: p })
|
|
9389
|
+
] }, "b:" + p),
|
|
9390
|
+
entry: idx
|
|
9391
|
+
});
|
|
9392
|
+
});
|
|
9393
|
+
header("h:custom", "custom patterns", "regex over tool args \xB7 a add \xB7 d remove");
|
|
9394
|
+
note("n:custom-help", " a JS regex, e.g. sk-[a-z0-9]{20} AKIA[0-9A-Z]{16} password=\\S+");
|
|
9395
|
+
if ((dlp?.custom.length ?? 0) === 0) note("n:custom", " (none \u2014 press a to add a name + regex)");
|
|
9396
|
+
(dlp?.custom ?? []).forEach((c2, i) => {
|
|
9397
|
+
const isCur = focused && ei === selC;
|
|
9398
|
+
const idx = ei++;
|
|
9399
|
+
lines.push({
|
|
9400
|
+
node: /* @__PURE__ */ jsxs5(Text5, { wrap: "truncate", backgroundColor: isCur ? "#1c2f63" : void 0, bold: isCur, children: [
|
|
9401
|
+
/* @__PURE__ */ jsx5(Text5, { color: isCur ? theme.accentBright : theme.dim, children: isCur ? "\u25B8 " : " " }),
|
|
9402
|
+
/* @__PURE__ */ jsx5(Text5, { color: theme.accent, children: c2.name }),
|
|
9403
|
+
/* @__PURE__ */ jsx5(Text5, { color: theme.dim, children: " " + truncate2(c2.re, Math.max(10, cols - c2.name.length - 8)) })
|
|
9404
|
+
] }, "c:" + c2.name + i),
|
|
9405
|
+
entry: idx
|
|
9406
|
+
});
|
|
9407
|
+
});
|
|
9408
|
+
header("h:ghost", "ghost \u2014 hidden paths", `${ghostOn ? "ON" : "off"} (g) \xB7 r add route \xB7 d remove`);
|
|
9409
|
+
note("n:ghost-help", " glob path, * = any chars, e.g. */.env *.pem */secrets/* *secret*");
|
|
9410
|
+
if (ghostPats.length === 0) note("n:ghost", " (none \u2014 g turns ghost on, r adds a path to hide)");
|
|
9411
|
+
ghostPats.forEach((p, i) => {
|
|
9412
|
+
const isCur = focused && ei === selC;
|
|
9413
|
+
const idx = ei++;
|
|
9414
|
+
lines.push({
|
|
9415
|
+
node: /* @__PURE__ */ jsxs5(Text5, { wrap: "truncate", backgroundColor: isCur ? "#1c2f63" : void 0, bold: isCur, children: [
|
|
9416
|
+
/* @__PURE__ */ jsx5(Text5, { color: isCur ? theme.accentBright : theme.dim, children: isCur ? "\u25B8 " : " " }),
|
|
9417
|
+
/* @__PURE__ */ jsx5(Text5, { color: ghostOn ? theme.accent : theme.dim, children: truncate2(p, Math.max(10, cols - 6)) }),
|
|
9418
|
+
!ghostOn ? /* @__PURE__ */ jsx5(Text5, { color: theme.dim, children: " (ghost off)" }) : null
|
|
9419
|
+
] }, "g:" + p + i),
|
|
9420
|
+
entry: idx
|
|
9421
|
+
});
|
|
9422
|
+
});
|
|
9423
|
+
const editRows = adding === "re" ? 2 : adding ? 1 : 0;
|
|
9424
|
+
const headerRows = 2 + editRows + (status ? 1 : 0);
|
|
9425
|
+
const budget = Math.max(3, rows - headerRows - 1);
|
|
9426
|
+
const selLine = Math.max(0, lines.findIndex((l) => l.entry === selC));
|
|
9427
|
+
const maxStart = Math.max(0, lines.length - budget);
|
|
9428
|
+
const start = Math.min(Math.max(0, selLine - Math.floor(budget / 2)), maxStart);
|
|
9429
|
+
const win = lines.slice(start, start + budget);
|
|
9430
|
+
const moreAbove = start;
|
|
9431
|
+
const moreBelow = Math.max(0, lines.length - (start + budget));
|
|
9368
9432
|
return /* @__PURE__ */ jsx5(DataView, { loading: q.loading && !dlp, error: q.error, children: dlp ? /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", children: [
|
|
9369
|
-
/* @__PURE__ */ jsxs5(
|
|
9433
|
+
/* @__PURE__ */ jsxs5(Text5, { wrap: "truncate", children: [
|
|
9370
9434
|
/* @__PURE__ */ jsx5(Text5, { children: "mode: " }),
|
|
9371
|
-
/* @__PURE__ */ jsx5(Text5, { color: modeColor(dlp.mode), children: dlp.mode }),
|
|
9435
|
+
/* @__PURE__ */ jsx5(Text5, { color: modeColor(dlp.mode), bold: true, children: dlp.mode }),
|
|
9436
|
+
/* @__PURE__ */ jsx5(Text5, { color: theme.dim, children: dlp.mode === "off" ? " (scanning disabled)" : dlp.mode === "detect" ? " (flag dlp:yes, redact output)" : " (deny + redact secrets)" }),
|
|
9372
9437
|
dirty ? /* @__PURE__ */ jsx5(Text5, { color: theme.warn, children: " \u25CF unsaved (s save \xB7 x discard)" }) : null
|
|
9373
9438
|
] }),
|
|
9374
|
-
/* @__PURE__ */ jsx5(Text5, { color: theme.dim, children: focused ?
|
|
9375
|
-
/* @__PURE__ */ jsxs5(Box5, { children: [
|
|
9376
|
-
/* @__PURE__ */
|
|
9377
|
-
|
|
9378
|
-
|
|
9379
|
-
|
|
9380
|
-
|
|
9381
|
-
|
|
9382
|
-
|
|
9383
|
-
|
|
9384
|
-
|
|
9385
|
-
|
|
9386
|
-
|
|
9387
|
-
|
|
9388
|
-
|
|
9389
|
-
|
|
9390
|
-
|
|
9391
|
-
|
|
9392
|
-
|
|
9393
|
-
|
|
9394
|
-
|
|
9395
|
-
|
|
9396
|
-
|
|
9397
|
-
|
|
9398
|
-
|
|
9399
|
-
|
|
9400
|
-
|
|
9401
|
-
|
|
9402
|
-
adding ? /* @__PURE__ */ jsxs5(Box5, { marginTop: 1, children: [
|
|
9403
|
-
/* @__PURE__ */ jsx5(Text5, { color: theme.warn, children: adding === "name" ? "New pattern name: " : `Regex for "${newName}": ` }),
|
|
9404
|
-
adding === "name" ? /* @__PURE__ */ jsx5(
|
|
9405
|
-
TextInput3,
|
|
9406
|
-
{
|
|
9407
|
-
value: newName,
|
|
9408
|
-
onChange: setNewName,
|
|
9409
|
-
onSubmit: (v) => {
|
|
9410
|
-
if (!v.trim()) return setAdding(null);
|
|
9411
|
-
setNewName(v.trim());
|
|
9412
|
-
setAdding("re");
|
|
9413
|
-
}
|
|
9414
|
-
}
|
|
9415
|
-
) : /* @__PURE__ */ jsx5(
|
|
9416
|
-
TextInput3,
|
|
9417
|
-
{
|
|
9418
|
-
value: newRe,
|
|
9419
|
-
onChange: setNewRe,
|
|
9420
|
-
onSubmit: (v) => {
|
|
9421
|
-
if (v.trim() && dlp) mutate({ ...dlp, custom: [...dlp.custom, { name: newName, re: v.trim() }] });
|
|
9422
|
-
setAdding(null);
|
|
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__ */ jsxs5(Box5, { flexDirection: "column", children: [
|
|
9441
|
+
/* @__PURE__ */ jsxs5(Box5, { children: [
|
|
9442
|
+
/* @__PURE__ */ jsx5(Text5, { color: theme.warn, children: adding === "name" ? "new pattern name: " : adding === "re" ? `regex for "${newName}" (e.g. sk-[a-z0-9]{20}): ` : "ghost path to hide (glob, * = any chars, e.g. */.env *.pem): " }),
|
|
9443
|
+
/* @__PURE__ */ jsx5(
|
|
9444
|
+
TextInput3,
|
|
9445
|
+
{
|
|
9446
|
+
value: input,
|
|
9447
|
+
onChange: setInput,
|
|
9448
|
+
onSubmit: (v) => {
|
|
9449
|
+
const t = v.trim();
|
|
9450
|
+
if (adding === "name") {
|
|
9451
|
+
if (!t) return setAdding(null);
|
|
9452
|
+
setNewName(t);
|
|
9453
|
+
setInput("");
|
|
9454
|
+
setAdding("re");
|
|
9455
|
+
} else if (adding === "re") {
|
|
9456
|
+
if (t && dlp) mutate({ ...dlp, custom: [...dlp.custom, { name: newName, re: t }] });
|
|
9457
|
+
setAdding(null);
|
|
9458
|
+
} else {
|
|
9459
|
+
if (t && !ghostPats.includes(t)) {
|
|
9460
|
+
setGhostPats((ps) => [...ps, t]);
|
|
9461
|
+
setDirty(true);
|
|
9462
|
+
setStatus(null);
|
|
9463
|
+
}
|
|
9464
|
+
setAdding(null);
|
|
9465
|
+
}
|
|
9466
|
+
}
|
|
9423
9467
|
}
|
|
9424
|
-
|
|
9425
|
-
)
|
|
9468
|
+
)
|
|
9469
|
+
] }),
|
|
9470
|
+
adding === "re" ? /* @__PURE__ */ jsx5(RegexTest, { re: input }) : null
|
|
9426
9471
|
] }) : null,
|
|
9427
|
-
|
|
9428
|
-
status ? /* @__PURE__ */ jsx5(
|
|
9472
|
+
/* @__PURE__ */ jsx5(Box5, { marginTop: 1, flexDirection: "column", height: budget, overflow: "hidden", children: win.map((l) => l.node) }),
|
|
9473
|
+
status ? /* @__PURE__ */ jsx5(Text5, { color: status.startsWith("\u2717") ? theme.bad : theme.ok, wrap: "truncate", children: status }) : null
|
|
9429
9474
|
] }) : null });
|
|
9430
9475
|
}
|
|
9431
9476
|
function RegexTest({ re }) {
|
|
@@ -11055,12 +11100,12 @@ function App() {
|
|
|
11055
11100
|
update2.kind === "updating" ? /* @__PURE__ */ jsx8(Text8, { color: theme.warn, children: ` \u2191 updating to v${update2.version}\u2026` }) : update2.kind === "updated" ? /* @__PURE__ */ jsx8(Text8, { color: theme.ok, bold: true, children: ` \u2191 v${update2.version} installed \u2014 restart (q, then solongate) to apply` }) : update2.kind === "manual" ? /* @__PURE__ */ jsx8(Text8, { color: theme.warn, children: ` \u2191 v${update2.version} available \u2014 npm i -g @solongate/proxy@latest` }) : null
|
|
11056
11101
|
] }),
|
|
11057
11102
|
/* @__PURE__ */ jsxs8(Box8, { marginTop: 1, flexGrow: 1, children: [
|
|
11058
|
-
/* @__PURE__ */ jsx8(Box8, { flexDirection: "column", width: 16, borderStyle: "round", borderColor: focus === "nav" ? theme.accent : "gray", paddingX: 1, children: SECTIONS.map((s, i) => {
|
|
11103
|
+
/* @__PURE__ */ jsx8(Box8, { flexDirection: "column", flexShrink: 0, width: 16, borderStyle: "round", borderColor: focus === "nav" ? theme.accent : "gray", paddingX: 1, children: SECTIONS.map((s, i) => {
|
|
11059
11104
|
const isCur = i === effectiveSection;
|
|
11060
11105
|
const disabled = locked && s.label !== "Settings";
|
|
11061
11106
|
return /* @__PURE__ */ jsx8(Text8, { color: isCur ? theme.accentBright : disabled ? theme.dim : void 0, bold: isCur, dimColor: disabled, children: (isCur ? "\u25B8 " : disabled ? "\u2298 " : " ") + s.label }, s.label);
|
|
11062
11107
|
}) }),
|
|
11063
|
-
/* @__PURE__ */ jsx8(Box8, { flexGrow: 1, borderStyle: "round", borderColor: focus === "panel" ? theme.accent : "gray", paddingX: 1, paddingY: 0, overflow: "hidden", children: panelBody })
|
|
11108
|
+
/* @__PURE__ */ jsx8(Box8, { flexGrow: 1, minWidth: 0, borderStyle: "round", borderColor: focus === "panel" ? theme.accent : "gray", paddingX: 1, paddingY: 0, overflow: "hidden", children: panelBody })
|
|
11064
11109
|
] }, viewNonce),
|
|
11065
11110
|
/* @__PURE__ */ jsx8(Box8, { children: locked ? /* @__PURE__ */ jsx8(KeyHints, { hints: [["\u2192/enter", "open Settings"], ["n", "log in"], ["q", "quit"]] }) : focus === "nav" ? /* @__PURE__ */ jsx8(KeyHints, { hints: [["\u2191\u2193", "section"], ["\u2192/enter", "open"], ...accounts.length > 1 ? [["a", "account"]] : [], ["?", "help"], ["q", "quit"]] }) : /* @__PURE__ */ jsx8(KeyHints, { hints: [["\u2190/esc", "back"], ["\u2191\u2193", "in-panel"], ["space/s", "act"]] }) })
|
|
11066
11111
|
] })
|
|
@@ -11110,7 +11155,8 @@ var init_App = __esm({
|
|
|
11110
11155
|
["Global", [["\u2191\u2193", "move between sections"], ["\u2192 / enter", "open a section"], ["\u2190 / esc", "back to the menu"], ["?", "this help"], ["q", "quit"]]],
|
|
11111
11156
|
["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)"]]],
|
|
11112
11157
|
["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"]]],
|
|
11113
|
-
["Rate limit
|
|
11158
|
+
["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 regex)"], ["r", "add a ghost route (path to hide)"], ["d", "remove custom / route"], ["g", "ghost on/off"], ["s", "save \xB7 x discard"]]],
|
|
11114
11160
|
["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"]]],
|
|
11115
11161
|
["Settings", [["\u2191\u2193", "move"], ["enter / space", "toggle \xB7 edit \xB7 add"], ["e", "webhook events"], ["d d", "delete"], ["r", "refresh"]]],
|
|
11116
11162
|
["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/dist/tui/index.js
CHANGED
|
@@ -2321,28 +2321,26 @@ import { useEffect as useEffect5, useState as useState5 } from "react";
|
|
|
2321
2321
|
import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
2322
2322
|
var MODES2 = ["off", "detect", "block"];
|
|
2323
2323
|
function DlpPanel({ focused }) {
|
|
2324
|
+
const { cols, rows } = usePanelSize();
|
|
2324
2325
|
const q = useLoader(() => api.settings.getSecurityLayers());
|
|
2325
2326
|
const [dlp, setDlp] = useState5(null);
|
|
2326
2327
|
const [available, setAvailable] = useState5([]);
|
|
2328
|
+
const [ghostOn, setGhostOn] = useState5(false);
|
|
2329
|
+
const [ghostPats, setGhostPats] = useState5([]);
|
|
2327
2330
|
const [sel, setSel] = useState5(0);
|
|
2328
2331
|
const [dirty, setDirty] = useState5(false);
|
|
2329
2332
|
const [status, setStatus] = useState5(null);
|
|
2330
2333
|
const [adding, setAdding] = useState5(null);
|
|
2331
2334
|
const [newName, setNewName] = useState5("");
|
|
2332
|
-
const [
|
|
2333
|
-
const [ghostOn, setGhostOn] = useState5(false);
|
|
2334
|
-
const spQ = useLoader(() => api.settings.getSelfProtection());
|
|
2335
|
-
const [selfProt, setSelfProt] = useState5(null);
|
|
2335
|
+
const [input, setInput] = useState5("");
|
|
2336
2336
|
useEffect5(() => {
|
|
2337
2337
|
if (q.data && !dlp) {
|
|
2338
2338
|
setDlp({ ...q.data.layers.dlp, patterns: [...q.data.layers.dlp.patterns], custom: [...q.data.layers.dlp.custom] });
|
|
2339
2339
|
setAvailable(q.data.availablePatterns);
|
|
2340
2340
|
setGhostOn(q.data.layers.ghost.mode === "on");
|
|
2341
|
+
setGhostPats([...q.data.layers.ghost.patterns]);
|
|
2341
2342
|
}
|
|
2342
2343
|
}, [q.data, dlp]);
|
|
2343
|
-
useEffect5(() => {
|
|
2344
|
-
if (spQ.data && selfProt === null) setSelfProt(spQ.data.enabled);
|
|
2345
|
-
}, [spQ.data, selfProt]);
|
|
2346
2344
|
const mutate = (next) => {
|
|
2347
2345
|
setDlp(next);
|
|
2348
2346
|
setDirty(true);
|
|
@@ -2352,128 +2350,175 @@ function DlpPanel({ focused }) {
|
|
|
2352
2350
|
if (!dlp || !q.data) return;
|
|
2353
2351
|
setStatus("Saving\u2026");
|
|
2354
2352
|
try {
|
|
2355
|
-
const ghost = {
|
|
2353
|
+
const ghost = { mode: ghostOn ? "on" : "off", patterns: ghostPats };
|
|
2356
2354
|
const res = await api.settings.setSecurityLayers({ ...q.data.layers, dlp, ghost });
|
|
2357
2355
|
setDlp({ ...res.layers.dlp, patterns: [...res.layers.dlp.patterns], custom: [...res.layers.dlp.custom] });
|
|
2358
2356
|
setGhostOn(res.layers.ghost.mode === "on");
|
|
2357
|
+
setGhostPats([...res.layers.ghost.patterns]);
|
|
2359
2358
|
setDirty(false);
|
|
2360
2359
|
setStatus("\u2713 Saved");
|
|
2361
2360
|
} catch (e) {
|
|
2362
2361
|
setStatus("\u2717 " + (e instanceof Error ? e.message : String(e)));
|
|
2363
2362
|
}
|
|
2364
2363
|
};
|
|
2365
|
-
const toggleSelfProt = async () => {
|
|
2366
|
-
const next = !(selfProt ?? false);
|
|
2367
|
-
setSelfProt(next);
|
|
2368
|
-
try {
|
|
2369
|
-
await api.settings.setSelfProtection(next);
|
|
2370
|
-
setStatus(`\u2713 self-protection ${next ? "on" : "off"}`);
|
|
2371
|
-
} catch (e) {
|
|
2372
|
-
setSelfProt(!next);
|
|
2373
|
-
setStatus("\u2717 " + (e instanceof Error ? e.message : String(e)));
|
|
2374
|
-
}
|
|
2375
|
-
};
|
|
2376
2364
|
const discard = () => {
|
|
2377
|
-
if (q.data)
|
|
2365
|
+
if (!q.data) return;
|
|
2366
|
+
setDlp({ ...q.data.layers.dlp, patterns: [...q.data.layers.dlp.patterns], custom: [...q.data.layers.dlp.custom] });
|
|
2367
|
+
setGhostOn(q.data.layers.ghost.mode === "on");
|
|
2368
|
+
setGhostPats([...q.data.layers.ghost.patterns]);
|
|
2378
2369
|
setDirty(false);
|
|
2379
2370
|
setStatus("discarded");
|
|
2380
2371
|
};
|
|
2381
|
-
const
|
|
2382
|
-
|
|
2372
|
+
const entries = [
|
|
2373
|
+
...available.map((name) => ({ kind: "builtin", name })),
|
|
2374
|
+
...(dlp?.custom ?? []).map((_, i) => ({ kind: "custom", i })),
|
|
2375
|
+
...ghostPats.map((_, i) => ({ kind: "ghost", i }))
|
|
2376
|
+
];
|
|
2377
|
+
const selC = Math.min(sel, Math.max(0, entries.length - 1));
|
|
2378
|
+
const cur = entries[selC];
|
|
2383
2379
|
useInput4(
|
|
2384
|
-
(
|
|
2380
|
+
(input2, key) => {
|
|
2385
2381
|
if (!dlp) return;
|
|
2386
|
-
if (key.upArrow) setSel((
|
|
2387
|
-
else if (key.downArrow) setSel((
|
|
2388
|
-
else if (
|
|
2389
|
-
|
|
2390
|
-
mutate({ ...dlp, mode: MODES2[idx] });
|
|
2391
|
-
} else if (input === "a") {
|
|
2392
|
-
setNewName("");
|
|
2393
|
-
setNewRe("");
|
|
2394
|
-
setAdding("name");
|
|
2395
|
-
} else if (input === " " && sel < available.length) {
|
|
2396
|
-
const p = available[sel];
|
|
2382
|
+
if (key.upArrow) setSel(() => Math.max(0, selC - 1));
|
|
2383
|
+
else if (key.downArrow) setSel(() => Math.min(entries.length - 1, selC + 1));
|
|
2384
|
+
else if (input2 === "m") mutate({ ...dlp, mode: MODES2[(MODES2.indexOf(dlp.mode) + 1) % MODES2.length] });
|
|
2385
|
+
else if (input2 === " " && cur?.kind === "builtin") {
|
|
2397
2386
|
const set = new Set(dlp.patterns);
|
|
2398
|
-
if (set.has(
|
|
2399
|
-
else set.add(
|
|
2387
|
+
if (set.has(cur.name)) set.delete(cur.name);
|
|
2388
|
+
else set.add(cur.name);
|
|
2400
2389
|
mutate({ ...dlp, patterns: [...set] });
|
|
2401
|
-
} else if (
|
|
2402
|
-
|
|
2403
|
-
|
|
2404
|
-
|
|
2405
|
-
} else if (
|
|
2390
|
+
} else if (input2 === "a") {
|
|
2391
|
+
setNewName("");
|
|
2392
|
+
setInput("");
|
|
2393
|
+
setAdding("name");
|
|
2394
|
+
} else if (input2 === "r") {
|
|
2395
|
+
setInput("");
|
|
2396
|
+
setAdding("route");
|
|
2397
|
+
} else if (input2 === "d") {
|
|
2398
|
+
if (cur?.kind === "custom") {
|
|
2399
|
+
mutate({ ...dlp, custom: dlp.custom.filter((_, i) => i !== cur.i) });
|
|
2400
|
+
setSel(() => Math.max(0, selC - 1));
|
|
2401
|
+
} else if (cur?.kind === "ghost") {
|
|
2402
|
+
setGhostPats((ps) => ps.filter((_, i) => i !== cur.i));
|
|
2403
|
+
setDirty(true);
|
|
2404
|
+
setStatus(null);
|
|
2405
|
+
setSel(() => Math.max(0, selC - 1));
|
|
2406
|
+
}
|
|
2407
|
+
} else if (input2 === "g") {
|
|
2406
2408
|
setGhostOn((v) => !v);
|
|
2407
2409
|
setDirty(true);
|
|
2408
2410
|
setStatus(null);
|
|
2409
|
-
} else if (
|
|
2410
|
-
else if (
|
|
2411
|
-
else if (input === "x") discard();
|
|
2411
|
+
} else if (input2 === "s") void save();
|
|
2412
|
+
else if (input2 === "x") discard();
|
|
2412
2413
|
},
|
|
2413
2414
|
{ isActive: focused && !adding }
|
|
2414
2415
|
);
|
|
2415
2416
|
const enabled = new Set(dlp?.patterns ?? []);
|
|
2417
|
+
const lines = [];
|
|
2418
|
+
const header = (key, label, extra) => lines.push({
|
|
2419
|
+
node: /* @__PURE__ */ jsxs5(Text5, { wrap: "truncate", children: [
|
|
2420
|
+
/* @__PURE__ */ jsx5(Text5, { color: theme.accentBright, bold: true, children: label }),
|
|
2421
|
+
extra ? /* @__PURE__ */ jsx5(Text5, { color: theme.dim, children: " " + extra }) : null
|
|
2422
|
+
] }, key),
|
|
2423
|
+
entry: -1
|
|
2424
|
+
});
|
|
2425
|
+
const note = (key, text) => lines.push({ node: /* @__PURE__ */ jsx5(Text5, { color: theme.dim, wrap: "truncate", children: text }, key), entry: -1 });
|
|
2426
|
+
let ei = 0;
|
|
2427
|
+
header("h:builtin", "built-in secret patterns", "space toggles on/off");
|
|
2428
|
+
available.forEach((p) => {
|
|
2429
|
+
const on = enabled.has(p);
|
|
2430
|
+
const isCur = focused && ei === selC;
|
|
2431
|
+
const idx = ei++;
|
|
2432
|
+
lines.push({
|
|
2433
|
+
node: /* @__PURE__ */ jsxs5(Text5, { wrap: "truncate", backgroundColor: isCur ? "#1c2f63" : void 0, bold: isCur, children: [
|
|
2434
|
+
/* @__PURE__ */ jsx5(Text5, { color: isCur ? theme.accentBright : theme.dim, children: isCur ? "\u25B8 " : " " }),
|
|
2435
|
+
/* @__PURE__ */ jsx5(Text5, { color: on ? theme.ok : theme.dim, children: on ? "\u25CF " : "\u25CB " }),
|
|
2436
|
+
/* @__PURE__ */ jsx5(Text5, { color: on ? void 0 : theme.dim, children: p })
|
|
2437
|
+
] }, "b:" + p),
|
|
2438
|
+
entry: idx
|
|
2439
|
+
});
|
|
2440
|
+
});
|
|
2441
|
+
header("h:custom", "custom patterns", "regex over tool args \xB7 a add \xB7 d remove");
|
|
2442
|
+
note("n:custom-help", " a JS regex, e.g. sk-[a-z0-9]{20} AKIA[0-9A-Z]{16} password=\\S+");
|
|
2443
|
+
if ((dlp?.custom.length ?? 0) === 0) note("n:custom", " (none \u2014 press a to add a name + regex)");
|
|
2444
|
+
(dlp?.custom ?? []).forEach((c2, i) => {
|
|
2445
|
+
const isCur = focused && ei === selC;
|
|
2446
|
+
const idx = ei++;
|
|
2447
|
+
lines.push({
|
|
2448
|
+
node: /* @__PURE__ */ jsxs5(Text5, { wrap: "truncate", backgroundColor: isCur ? "#1c2f63" : void 0, bold: isCur, children: [
|
|
2449
|
+
/* @__PURE__ */ jsx5(Text5, { color: isCur ? theme.accentBright : theme.dim, children: isCur ? "\u25B8 " : " " }),
|
|
2450
|
+
/* @__PURE__ */ jsx5(Text5, { color: theme.accent, children: c2.name }),
|
|
2451
|
+
/* @__PURE__ */ jsx5(Text5, { color: theme.dim, children: " " + truncate(c2.re, Math.max(10, cols - c2.name.length - 8)) })
|
|
2452
|
+
] }, "c:" + c2.name + i),
|
|
2453
|
+
entry: idx
|
|
2454
|
+
});
|
|
2455
|
+
});
|
|
2456
|
+
header("h:ghost", "ghost \u2014 hidden paths", `${ghostOn ? "ON" : "off"} (g) \xB7 r add route \xB7 d remove`);
|
|
2457
|
+
note("n:ghost-help", " glob path, * = any chars, e.g. */.env *.pem */secrets/* *secret*");
|
|
2458
|
+
if (ghostPats.length === 0) note("n:ghost", " (none \u2014 g turns ghost on, r adds a path to hide)");
|
|
2459
|
+
ghostPats.forEach((p, i) => {
|
|
2460
|
+
const isCur = focused && ei === selC;
|
|
2461
|
+
const idx = ei++;
|
|
2462
|
+
lines.push({
|
|
2463
|
+
node: /* @__PURE__ */ jsxs5(Text5, { wrap: "truncate", backgroundColor: isCur ? "#1c2f63" : void 0, bold: isCur, children: [
|
|
2464
|
+
/* @__PURE__ */ jsx5(Text5, { color: isCur ? theme.accentBright : theme.dim, children: isCur ? "\u25B8 " : " " }),
|
|
2465
|
+
/* @__PURE__ */ jsx5(Text5, { color: ghostOn ? theme.accent : theme.dim, children: truncate(p, Math.max(10, cols - 6)) }),
|
|
2466
|
+
!ghostOn ? /* @__PURE__ */ jsx5(Text5, { color: theme.dim, children: " (ghost off)" }) : null
|
|
2467
|
+
] }, "g:" + p + i),
|
|
2468
|
+
entry: idx
|
|
2469
|
+
});
|
|
2470
|
+
});
|
|
2471
|
+
const editRows = adding === "re" ? 2 : adding ? 1 : 0;
|
|
2472
|
+
const headerRows = 2 + editRows + (status ? 1 : 0);
|
|
2473
|
+
const budget = Math.max(3, rows - headerRows - 1);
|
|
2474
|
+
const selLine = Math.max(0, lines.findIndex((l) => l.entry === selC));
|
|
2475
|
+
const maxStart = Math.max(0, lines.length - budget);
|
|
2476
|
+
const start = Math.min(Math.max(0, selLine - Math.floor(budget / 2)), maxStart);
|
|
2477
|
+
const win = lines.slice(start, start + budget);
|
|
2478
|
+
const moreAbove = start;
|
|
2479
|
+
const moreBelow = Math.max(0, lines.length - (start + budget));
|
|
2416
2480
|
return /* @__PURE__ */ jsx5(DataView, { loading: q.loading && !dlp, error: q.error, children: dlp ? /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", children: [
|
|
2417
|
-
/* @__PURE__ */ jsxs5(
|
|
2481
|
+
/* @__PURE__ */ jsxs5(Text5, { wrap: "truncate", children: [
|
|
2418
2482
|
/* @__PURE__ */ jsx5(Text5, { children: "mode: " }),
|
|
2419
|
-
/* @__PURE__ */ jsx5(Text5, { color: modeColor(dlp.mode), children: dlp.mode }),
|
|
2483
|
+
/* @__PURE__ */ jsx5(Text5, { color: modeColor(dlp.mode), bold: true, children: dlp.mode }),
|
|
2484
|
+
/* @__PURE__ */ jsx5(Text5, { color: theme.dim, children: dlp.mode === "off" ? " (scanning disabled)" : dlp.mode === "detect" ? " (flag dlp:yes, redact output)" : " (deny + redact secrets)" }),
|
|
2420
2485
|
dirty ? /* @__PURE__ */ jsx5(Text5, { color: theme.warn, children: " \u25CF unsaved (s save \xB7 x discard)" }) : null
|
|
2421
2486
|
] }),
|
|
2422
|
-
/* @__PURE__ */ jsx5(Text5, { color: theme.dim, children: focused ?
|
|
2423
|
-
/* @__PURE__ */ jsxs5(Box5, { children: [
|
|
2424
|
-
/* @__PURE__ */
|
|
2425
|
-
|
|
2426
|
-
|
|
2427
|
-
|
|
2428
|
-
|
|
2429
|
-
|
|
2430
|
-
|
|
2431
|
-
|
|
2432
|
-
|
|
2433
|
-
|
|
2434
|
-
|
|
2435
|
-
|
|
2436
|
-
|
|
2437
|
-
|
|
2438
|
-
|
|
2439
|
-
|
|
2440
|
-
|
|
2441
|
-
|
|
2442
|
-
|
|
2443
|
-
|
|
2444
|
-
|
|
2445
|
-
|
|
2446
|
-
|
|
2447
|
-
|
|
2448
|
-
|
|
2449
|
-
|
|
2450
|
-
adding ? /* @__PURE__ */ jsxs5(Box5, { marginTop: 1, children: [
|
|
2451
|
-
/* @__PURE__ */ jsx5(Text5, { color: theme.warn, children: adding === "name" ? "New pattern name: " : `Regex for "${newName}": ` }),
|
|
2452
|
-
adding === "name" ? /* @__PURE__ */ jsx5(
|
|
2453
|
-
TextInput3,
|
|
2454
|
-
{
|
|
2455
|
-
value: newName,
|
|
2456
|
-
onChange: setNewName,
|
|
2457
|
-
onSubmit: (v) => {
|
|
2458
|
-
if (!v.trim()) return setAdding(null);
|
|
2459
|
-
setNewName(v.trim());
|
|
2460
|
-
setAdding("re");
|
|
2461
|
-
}
|
|
2462
|
-
}
|
|
2463
|
-
) : /* @__PURE__ */ jsx5(
|
|
2464
|
-
TextInput3,
|
|
2465
|
-
{
|
|
2466
|
-
value: newRe,
|
|
2467
|
-
onChange: setNewRe,
|
|
2468
|
-
onSubmit: (v) => {
|
|
2469
|
-
if (v.trim() && dlp) mutate({ ...dlp, custom: [...dlp.custom, { name: newName, re: v.trim() }] });
|
|
2470
|
-
setAdding(null);
|
|
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__ */ jsxs5(Box5, { flexDirection: "column", children: [
|
|
2489
|
+
/* @__PURE__ */ jsxs5(Box5, { children: [
|
|
2490
|
+
/* @__PURE__ */ jsx5(Text5, { color: theme.warn, children: adding === "name" ? "new pattern name: " : adding === "re" ? `regex for "${newName}" (e.g. sk-[a-z0-9]{20}): ` : "ghost path to hide (glob, * = any chars, e.g. */.env *.pem): " }),
|
|
2491
|
+
/* @__PURE__ */ jsx5(
|
|
2492
|
+
TextInput3,
|
|
2493
|
+
{
|
|
2494
|
+
value: input,
|
|
2495
|
+
onChange: setInput,
|
|
2496
|
+
onSubmit: (v) => {
|
|
2497
|
+
const t = v.trim();
|
|
2498
|
+
if (adding === "name") {
|
|
2499
|
+
if (!t) return setAdding(null);
|
|
2500
|
+
setNewName(t);
|
|
2501
|
+
setInput("");
|
|
2502
|
+
setAdding("re");
|
|
2503
|
+
} else if (adding === "re") {
|
|
2504
|
+
if (t && dlp) mutate({ ...dlp, custom: [...dlp.custom, { name: newName, re: t }] });
|
|
2505
|
+
setAdding(null);
|
|
2506
|
+
} else {
|
|
2507
|
+
if (t && !ghostPats.includes(t)) {
|
|
2508
|
+
setGhostPats((ps) => [...ps, t]);
|
|
2509
|
+
setDirty(true);
|
|
2510
|
+
setStatus(null);
|
|
2511
|
+
}
|
|
2512
|
+
setAdding(null);
|
|
2513
|
+
}
|
|
2514
|
+
}
|
|
2471
2515
|
}
|
|
2472
|
-
|
|
2473
|
-
)
|
|
2516
|
+
)
|
|
2517
|
+
] }),
|
|
2518
|
+
adding === "re" ? /* @__PURE__ */ jsx5(RegexTest, { re: input }) : null
|
|
2474
2519
|
] }) : null,
|
|
2475
|
-
|
|
2476
|
-
status ? /* @__PURE__ */ jsx5(
|
|
2520
|
+
/* @__PURE__ */ jsx5(Box5, { marginTop: 1, flexDirection: "column", height: budget, overflow: "hidden", children: win.map((l) => l.node) }),
|
|
2521
|
+
status ? /* @__PURE__ */ jsx5(Text5, { color: status.startsWith("\u2717") ? theme.bad : theme.ok, wrap: "truncate", children: status }) : null
|
|
2477
2522
|
] }) : null });
|
|
2478
2523
|
}
|
|
2479
2524
|
var SAMPLES = ["AKIA1234567890ABCD00", "sk-ant-api03-xxxxxxxx", "ghp_16chars0000000000000000000000000000", "password=hunter2", "Bearer eyJhbGciOi"];
|
|
@@ -4060,12 +4105,12 @@ function App() {
|
|
|
4060
4105
|
update2.kind === "updating" ? /* @__PURE__ */ jsx8(Text8, { color: theme.warn, children: ` \u2191 updating to v${update2.version}\u2026` }) : update2.kind === "updated" ? /* @__PURE__ */ jsx8(Text8, { color: theme.ok, bold: true, children: ` \u2191 v${update2.version} installed \u2014 restart (q, then solongate) to apply` }) : update2.kind === "manual" ? /* @__PURE__ */ jsx8(Text8, { color: theme.warn, children: ` \u2191 v${update2.version} available \u2014 npm i -g @solongate/proxy@latest` }) : null
|
|
4061
4106
|
] }),
|
|
4062
4107
|
/* @__PURE__ */ jsxs8(Box8, { marginTop: 1, flexGrow: 1, children: [
|
|
4063
|
-
/* @__PURE__ */ jsx8(Box8, { flexDirection: "column", width: 16, borderStyle: "round", borderColor: focus === "nav" ? theme.accent : "gray", paddingX: 1, children: SECTIONS.map((s, i) => {
|
|
4108
|
+
/* @__PURE__ */ jsx8(Box8, { flexDirection: "column", flexShrink: 0, width: 16, borderStyle: "round", borderColor: focus === "nav" ? theme.accent : "gray", paddingX: 1, children: SECTIONS.map((s, i) => {
|
|
4064
4109
|
const isCur = i === effectiveSection;
|
|
4065
4110
|
const disabled = locked && s.label !== "Settings";
|
|
4066
4111
|
return /* @__PURE__ */ jsx8(Text8, { color: isCur ? theme.accentBright : disabled ? theme.dim : void 0, bold: isCur, dimColor: disabled, children: (isCur ? "\u25B8 " : disabled ? "\u2298 " : " ") + s.label }, s.label);
|
|
4067
4112
|
}) }),
|
|
4068
|
-
/* @__PURE__ */ jsx8(Box8, { flexGrow: 1, borderStyle: "round", borderColor: focus === "panel" ? theme.accent : "gray", paddingX: 1, paddingY: 0, overflow: "hidden", children: panelBody })
|
|
4113
|
+
/* @__PURE__ */ jsx8(Box8, { flexGrow: 1, minWidth: 0, borderStyle: "round", borderColor: focus === "panel" ? theme.accent : "gray", paddingX: 1, paddingY: 0, overflow: "hidden", children: panelBody })
|
|
4069
4114
|
] }, viewNonce),
|
|
4070
4115
|
/* @__PURE__ */ jsx8(Box8, { children: locked ? /* @__PURE__ */ jsx8(KeyHints, { hints: [["\u2192/enter", "open Settings"], ["n", "log in"], ["q", "quit"]] }) : focus === "nav" ? /* @__PURE__ */ jsx8(KeyHints, { hints: [["\u2191\u2193", "section"], ["\u2192/enter", "open"], ...accounts.length > 1 ? [["a", "account"]] : [], ["?", "help"], ["q", "quit"]] }) : /* @__PURE__ */ jsx8(KeyHints, { hints: [["\u2190/esc", "back"], ["\u2191\u2193", "in-panel"], ["space/s", "act"]] }) })
|
|
4071
4116
|
] })
|
|
@@ -4075,7 +4120,8 @@ var HELP = [
|
|
|
4075
4120
|
["Global", [["\u2191\u2193", "move between sections"], ["\u2192 / enter", "open a section"], ["\u2190 / esc", "back to the menu"], ["?", "this help"], ["q", "quit"]]],
|
|
4076
4121
|
["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)"]]],
|
|
4077
4122
|
["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"]]],
|
|
4078
|
-
["Rate limit
|
|
4123
|
+
["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 regex)"], ["r", "add a ghost route (path to hide)"], ["d", "remove custom / route"], ["g", "ghost on/off"], ["s", "save \xB7 x discard"]]],
|
|
4079
4125
|
["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"]]],
|
|
4080
4126
|
["Settings", [["\u2191\u2193", "move"], ["enter / space", "toggle \xB7 edit \xB7 add"], ["e", "webhook events"], ["d d", "delete"], ["r", "refresh"]]],
|
|
4081
4127
|
["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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@solongate/proxy",
|
|
3
|
-
"version": "0.81.
|
|
3
|
+
"version": "0.81.74",
|
|
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": {
|