@solongate/proxy 0.81.72 → 0.81.73
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 +156 -101
- package/dist/tui/index.js +156 -101
- 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,184 @@ 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");
|
|
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", "a add \xB7 d remove");
|
|
9394
|
+
if ((dlp?.custom.length ?? 0) === 0) note("n:custom", " (none \u2014 press a to add a name + regex)");
|
|
9395
|
+
(dlp?.custom ?? []).forEach((c2, i) => {
|
|
9396
|
+
const isCur = focused && ei === selC;
|
|
9397
|
+
const idx = ei++;
|
|
9398
|
+
lines.push({
|
|
9399
|
+
node: /* @__PURE__ */ jsxs5(Text5, { wrap: "truncate", backgroundColor: isCur ? "#1c2f63" : void 0, bold: isCur, children: [
|
|
9400
|
+
/* @__PURE__ */ jsx5(Text5, { color: isCur ? theme.accentBright : theme.dim, children: isCur ? "\u25B8 " : " " }),
|
|
9401
|
+
/* @__PURE__ */ jsx5(Text5, { color: theme.accent, children: c2.name }),
|
|
9402
|
+
/* @__PURE__ */ jsx5(Text5, { color: theme.dim, children: " " + truncate2(c2.re, Math.max(10, cols - c2.name.length - 8)) })
|
|
9403
|
+
] }, "c:" + c2.name + i),
|
|
9404
|
+
entry: idx
|
|
9405
|
+
});
|
|
9406
|
+
});
|
|
9407
|
+
header("h:ghost", "ghost \u2014 hidden paths", `${ghostOn ? "ON" : "off"} (g) \xB7 r add route \xB7 d remove`);
|
|
9408
|
+
if (ghostPats.length === 0) note("n:ghost", " (none \u2014 g turns ghost on, r adds a path to hide, e.g. **/.env)");
|
|
9409
|
+
ghostPats.forEach((p, i) => {
|
|
9410
|
+
const isCur = focused && ei === selC;
|
|
9411
|
+
const idx = ei++;
|
|
9412
|
+
lines.push({
|
|
9413
|
+
node: /* @__PURE__ */ jsxs5(Text5, { wrap: "truncate", backgroundColor: isCur ? "#1c2f63" : void 0, bold: isCur, children: [
|
|
9414
|
+
/* @__PURE__ */ jsx5(Text5, { color: isCur ? theme.accentBright : theme.dim, children: isCur ? "\u25B8 " : " " }),
|
|
9415
|
+
/* @__PURE__ */ jsx5(Text5, { color: ghostOn ? theme.accent : theme.dim, children: truncate2(p, Math.max(10, cols - 6)) }),
|
|
9416
|
+
!ghostOn ? /* @__PURE__ */ jsx5(Text5, { color: theme.dim, children: " (ghost off)" }) : null
|
|
9417
|
+
] }, "g:" + p + i),
|
|
9418
|
+
entry: idx
|
|
9419
|
+
});
|
|
9420
|
+
});
|
|
9421
|
+
const editRows = adding === "re" ? 2 : adding ? 1 : 0;
|
|
9422
|
+
const headerRows = 3 + editRows + (status ? 1 : 0);
|
|
9423
|
+
const budget = Math.max(3, rows - headerRows - 1);
|
|
9424
|
+
const selLine = Math.max(0, lines.findIndex((l) => l.entry === selC));
|
|
9425
|
+
const maxStart = Math.max(0, lines.length - budget);
|
|
9426
|
+
const start = Math.min(Math.max(0, selLine - Math.floor(budget / 2)), maxStart);
|
|
9427
|
+
const win = lines.slice(start, start + budget);
|
|
9428
|
+
const moreAbove = start;
|
|
9429
|
+
const moreBelow = Math.max(0, lines.length - (start + budget));
|
|
9368
9430
|
return /* @__PURE__ */ jsx5(DataView, { loading: q.loading && !dlp, error: q.error, children: dlp ? /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", children: [
|
|
9369
|
-
/* @__PURE__ */ jsxs5(
|
|
9431
|
+
/* @__PURE__ */ jsxs5(Text5, { wrap: "truncate", children: [
|
|
9370
9432
|
/* @__PURE__ */ jsx5(Text5, { children: "mode: " }),
|
|
9371
|
-
/* @__PURE__ */ jsx5(Text5, { color: modeColor(dlp.mode), children: dlp.mode }),
|
|
9433
|
+
/* @__PURE__ */ jsx5(Text5, { color: modeColor(dlp.mode), bold: true, children: dlp.mode }),
|
|
9434
|
+
/* @__PURE__ */ jsx5(Text5, { color: theme.dim, children: dlp.mode === "off" ? " (scanning disabled)" : dlp.mode === "detect" ? " (flag dlp:yes, redact output)" : " (deny + redact secrets)" }),
|
|
9372
9435
|
dirty ? /* @__PURE__ */ jsx5(Text5, { color: theme.warn, children: " \u25CF unsaved (s save \xB7 x discard)" }) : null
|
|
9373
9436
|
] }),
|
|
9374
|
-
/* @__PURE__ */ jsx5(Text5, { color: theme.dim, children: focused ? "\u2191\u2193 \xB7 space
|
|
9375
|
-
/* @__PURE__ */ jsxs5(
|
|
9376
|
-
|
|
9377
|
-
/* @__PURE__ */ jsx5(Text5, { color:
|
|
9378
|
-
|
|
9379
|
-
/* @__PURE__ */ jsx5(Text5, { color:
|
|
9380
|
-
|
|
9381
|
-
|
|
9382
|
-
|
|
9383
|
-
|
|
9384
|
-
|
|
9385
|
-
(active2 ? "\u25B8 " : " ") + (on ? "\u25CF " : "\u25CB "),
|
|
9386
|
-
/* @__PURE__ */ jsx5(Text5, { color: on ? theme.ok : theme.dim, children: p })
|
|
9387
|
-
] }, p);
|
|
9388
|
-
}) }),
|
|
9389
|
-
/* @__PURE__ */ jsxs5(Box5, { marginTop: 1, flexDirection: "column", children: [
|
|
9390
|
-
/* @__PURE__ */ jsx5(Text5, { color: theme.dim, children: "Custom patterns" }),
|
|
9391
|
-
dlp.custom.length === 0 ? /* @__PURE__ */ jsx5(Text5, { color: theme.dim, children: " (none \u2014 press a to add)" }) : null,
|
|
9392
|
-
dlp.custom.map((c2, i) => {
|
|
9393
|
-
const active2 = focused && sel === available.length + i;
|
|
9394
|
-
return /* @__PURE__ */ jsxs5(Text5, { color: active2 ? theme.accentBright : void 0, bold: active2, children: [
|
|
9395
|
-
active2 ? "\u25B8 " : " ",
|
|
9396
|
-
/* @__PURE__ */ jsx5(Text5, { color: theme.accent, children: c2.name }),
|
|
9397
|
-
" ",
|
|
9398
|
-
/* @__PURE__ */ jsx5(Text5, { color: theme.dim, children: c2.re })
|
|
9399
|
-
] }, c2.name + i);
|
|
9400
|
-
})
|
|
9437
|
+
/* @__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" : "press \u2192 to edit" }),
|
|
9438
|
+
/* @__PURE__ */ jsxs5(Text5, { color: theme.dim, wrap: "truncate", children: [
|
|
9439
|
+
"legend ",
|
|
9440
|
+
/* @__PURE__ */ jsx5(Text5, { color: theme.ok, children: "\u25CF" }),
|
|
9441
|
+
" on \xB7 ",
|
|
9442
|
+
/* @__PURE__ */ jsx5(Text5, { color: theme.dim, children: "\u25CB" }),
|
|
9443
|
+
" off \xB7 ",
|
|
9444
|
+
/* @__PURE__ */ jsx5(Text5, { color: theme.accentBright, children: "\u25B8" }),
|
|
9445
|
+
" cursor",
|
|
9446
|
+
moreAbove ? /* @__PURE__ */ jsx5(Text5, { children: ` \u25B2${moreAbove}` }) : null,
|
|
9447
|
+
moreBelow ? /* @__PURE__ */ jsx5(Text5, { children: ` \u25BC${moreBelow}` }) : null
|
|
9401
9448
|
] }),
|
|
9402
|
-
adding ? /* @__PURE__ */ jsxs5(Box5, {
|
|
9403
|
-
/* @__PURE__ */
|
|
9404
|
-
|
|
9405
|
-
|
|
9406
|
-
|
|
9407
|
-
|
|
9408
|
-
|
|
9409
|
-
|
|
9410
|
-
|
|
9411
|
-
|
|
9412
|
-
|
|
9413
|
-
|
|
9414
|
-
|
|
9415
|
-
|
|
9416
|
-
|
|
9417
|
-
|
|
9418
|
-
|
|
9419
|
-
|
|
9420
|
-
|
|
9421
|
-
|
|
9422
|
-
|
|
9449
|
+
adding ? /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", children: [
|
|
9450
|
+
/* @__PURE__ */ jsxs5(Box5, { children: [
|
|
9451
|
+
/* @__PURE__ */ jsx5(Text5, { color: theme.warn, children: adding === "name" ? "new pattern name: " : adding === "re" ? `regex for "${newName}": ` : "ghost route (glob path to hide, e.g. **/.env): " }),
|
|
9452
|
+
/* @__PURE__ */ jsx5(
|
|
9453
|
+
TextInput3,
|
|
9454
|
+
{
|
|
9455
|
+
value: input,
|
|
9456
|
+
onChange: setInput,
|
|
9457
|
+
onSubmit: (v) => {
|
|
9458
|
+
const t = v.trim();
|
|
9459
|
+
if (adding === "name") {
|
|
9460
|
+
if (!t) return setAdding(null);
|
|
9461
|
+
setNewName(t);
|
|
9462
|
+
setInput("");
|
|
9463
|
+
setAdding("re");
|
|
9464
|
+
} else if (adding === "re") {
|
|
9465
|
+
if (t && dlp) mutate({ ...dlp, custom: [...dlp.custom, { name: newName, re: t }] });
|
|
9466
|
+
setAdding(null);
|
|
9467
|
+
} else {
|
|
9468
|
+
if (t && !ghostPats.includes(t)) {
|
|
9469
|
+
setGhostPats((ps) => [...ps, t]);
|
|
9470
|
+
setDirty(true);
|
|
9471
|
+
setStatus(null);
|
|
9472
|
+
}
|
|
9473
|
+
setAdding(null);
|
|
9474
|
+
}
|
|
9475
|
+
}
|
|
9423
9476
|
}
|
|
9424
|
-
|
|
9425
|
-
)
|
|
9477
|
+
)
|
|
9478
|
+
] }),
|
|
9479
|
+
adding === "re" ? /* @__PURE__ */ jsx5(RegexTest, { re: input }) : null
|
|
9426
9480
|
] }) : null,
|
|
9427
|
-
|
|
9428
|
-
status ? /* @__PURE__ */ jsx5(
|
|
9481
|
+
/* @__PURE__ */ jsx5(Box5, { marginTop: 1, flexDirection: "column", height: budget, overflow: "hidden", children: win.map((l) => l.node) }),
|
|
9482
|
+
status ? /* @__PURE__ */ jsx5(Text5, { color: status.startsWith("\u2717") ? theme.bad : theme.ok, wrap: "truncate", children: status }) : null
|
|
9429
9483
|
] }) : null });
|
|
9430
9484
|
}
|
|
9431
9485
|
function RegexTest({ re }) {
|
|
@@ -11055,12 +11109,12 @@ function App() {
|
|
|
11055
11109
|
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
11110
|
] }),
|
|
11057
11111
|
/* @__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) => {
|
|
11112
|
+
/* @__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
11113
|
const isCur = i === effectiveSection;
|
|
11060
11114
|
const disabled = locked && s.label !== "Settings";
|
|
11061
11115
|
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
11116
|
}) }),
|
|
11063
|
-
/* @__PURE__ */ jsx8(Box8, { flexGrow: 1, borderStyle: "round", borderColor: focus === "panel" ? theme.accent : "gray", paddingX: 1, paddingY: 0, overflow: "hidden", children: panelBody })
|
|
11117
|
+
/* @__PURE__ */ jsx8(Box8, { flexGrow: 1, minWidth: 0, borderStyle: "round", borderColor: focus === "panel" ? theme.accent : "gray", paddingX: 1, paddingY: 0, overflow: "hidden", children: panelBody })
|
|
11064
11118
|
] }, viewNonce),
|
|
11065
11119
|
/* @__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
11120
|
] })
|
|
@@ -11110,7 +11164,8 @@ var init_App = __esm({
|
|
|
11110
11164
|
["Global", [["\u2191\u2193", "move between sections"], ["\u2192 / enter", "open a section"], ["\u2190 / esc", "back to the menu"], ["?", "this help"], ["q", "quit"]]],
|
|
11111
11165
|
["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
11166
|
["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
|
|
11167
|
+
["Rate limit", [["\u2191\u2193", "field"], ["\u2190\u2192", "adjust (shift = \xB110)"], ["s", "save"]]],
|
|
11168
|
+
["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
11169
|
["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
11170
|
["Settings", [["\u2191\u2193", "move"], ["enter / space", "toggle \xB7 edit \xB7 add"], ["e", "webhook events"], ["d d", "delete"], ["r", "refresh"]]],
|
|
11116
11171
|
["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,184 @@ 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");
|
|
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", "a add \xB7 d remove");
|
|
2442
|
+
if ((dlp?.custom.length ?? 0) === 0) note("n:custom", " (none \u2014 press a to add a name + regex)");
|
|
2443
|
+
(dlp?.custom ?? []).forEach((c2, i) => {
|
|
2444
|
+
const isCur = focused && ei === selC;
|
|
2445
|
+
const idx = ei++;
|
|
2446
|
+
lines.push({
|
|
2447
|
+
node: /* @__PURE__ */ jsxs5(Text5, { wrap: "truncate", backgroundColor: isCur ? "#1c2f63" : void 0, bold: isCur, children: [
|
|
2448
|
+
/* @__PURE__ */ jsx5(Text5, { color: isCur ? theme.accentBright : theme.dim, children: isCur ? "\u25B8 " : " " }),
|
|
2449
|
+
/* @__PURE__ */ jsx5(Text5, { color: theme.accent, children: c2.name }),
|
|
2450
|
+
/* @__PURE__ */ jsx5(Text5, { color: theme.dim, children: " " + truncate(c2.re, Math.max(10, cols - c2.name.length - 8)) })
|
|
2451
|
+
] }, "c:" + c2.name + i),
|
|
2452
|
+
entry: idx
|
|
2453
|
+
});
|
|
2454
|
+
});
|
|
2455
|
+
header("h:ghost", "ghost \u2014 hidden paths", `${ghostOn ? "ON" : "off"} (g) \xB7 r add route \xB7 d remove`);
|
|
2456
|
+
if (ghostPats.length === 0) note("n:ghost", " (none \u2014 g turns ghost on, r adds a path to hide, e.g. **/.env)");
|
|
2457
|
+
ghostPats.forEach((p, i) => {
|
|
2458
|
+
const isCur = focused && ei === selC;
|
|
2459
|
+
const idx = ei++;
|
|
2460
|
+
lines.push({
|
|
2461
|
+
node: /* @__PURE__ */ jsxs5(Text5, { wrap: "truncate", backgroundColor: isCur ? "#1c2f63" : void 0, bold: isCur, children: [
|
|
2462
|
+
/* @__PURE__ */ jsx5(Text5, { color: isCur ? theme.accentBright : theme.dim, children: isCur ? "\u25B8 " : " " }),
|
|
2463
|
+
/* @__PURE__ */ jsx5(Text5, { color: ghostOn ? theme.accent : theme.dim, children: truncate(p, Math.max(10, cols - 6)) }),
|
|
2464
|
+
!ghostOn ? /* @__PURE__ */ jsx5(Text5, { color: theme.dim, children: " (ghost off)" }) : null
|
|
2465
|
+
] }, "g:" + p + i),
|
|
2466
|
+
entry: idx
|
|
2467
|
+
});
|
|
2468
|
+
});
|
|
2469
|
+
const editRows = adding === "re" ? 2 : adding ? 1 : 0;
|
|
2470
|
+
const headerRows = 3 + editRows + (status ? 1 : 0);
|
|
2471
|
+
const budget = Math.max(3, rows - headerRows - 1);
|
|
2472
|
+
const selLine = Math.max(0, lines.findIndex((l) => l.entry === selC));
|
|
2473
|
+
const maxStart = Math.max(0, lines.length - budget);
|
|
2474
|
+
const start = Math.min(Math.max(0, selLine - Math.floor(budget / 2)), maxStart);
|
|
2475
|
+
const win = lines.slice(start, start + budget);
|
|
2476
|
+
const moreAbove = start;
|
|
2477
|
+
const moreBelow = Math.max(0, lines.length - (start + budget));
|
|
2416
2478
|
return /* @__PURE__ */ jsx5(DataView, { loading: q.loading && !dlp, error: q.error, children: dlp ? /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", children: [
|
|
2417
|
-
/* @__PURE__ */ jsxs5(
|
|
2479
|
+
/* @__PURE__ */ jsxs5(Text5, { wrap: "truncate", children: [
|
|
2418
2480
|
/* @__PURE__ */ jsx5(Text5, { children: "mode: " }),
|
|
2419
|
-
/* @__PURE__ */ jsx5(Text5, { color: modeColor(dlp.mode), children: dlp.mode }),
|
|
2481
|
+
/* @__PURE__ */ jsx5(Text5, { color: modeColor(dlp.mode), bold: true, children: dlp.mode }),
|
|
2482
|
+
/* @__PURE__ */ jsx5(Text5, { color: theme.dim, children: dlp.mode === "off" ? " (scanning disabled)" : dlp.mode === "detect" ? " (flag dlp:yes, redact output)" : " (deny + redact secrets)" }),
|
|
2420
2483
|
dirty ? /* @__PURE__ */ jsx5(Text5, { color: theme.warn, children: " \u25CF unsaved (s save \xB7 x discard)" }) : null
|
|
2421
2484
|
] }),
|
|
2422
|
-
/* @__PURE__ */ jsx5(Text5, { color: theme.dim, children: focused ? "\u2191\u2193 \xB7 space
|
|
2423
|
-
/* @__PURE__ */ jsxs5(
|
|
2424
|
-
|
|
2425
|
-
/* @__PURE__ */ jsx5(Text5, { color:
|
|
2426
|
-
|
|
2427
|
-
/* @__PURE__ */ jsx5(Text5, { color:
|
|
2485
|
+
/* @__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" : "press \u2192 to edit" }),
|
|
2486
|
+
/* @__PURE__ */ jsxs5(Text5, { color: theme.dim, wrap: "truncate", children: [
|
|
2487
|
+
"legend ",
|
|
2488
|
+
/* @__PURE__ */ jsx5(Text5, { color: theme.ok, children: "\u25CF" }),
|
|
2489
|
+
" on \xB7 ",
|
|
2490
|
+
/* @__PURE__ */ jsx5(Text5, { color: theme.dim, children: "\u25CB" }),
|
|
2491
|
+
" off \xB7 ",
|
|
2492
|
+
/* @__PURE__ */ jsx5(Text5, { color: theme.accentBright, children: "\u25B8" }),
|
|
2493
|
+
" cursor",
|
|
2494
|
+
moreAbove ? /* @__PURE__ */ jsx5(Text5, { children: ` \u25B2${moreAbove}` }) : null,
|
|
2495
|
+
moreBelow ? /* @__PURE__ */ jsx5(Text5, { children: ` \u25BC${moreBelow}` }) : null
|
|
2428
2496
|
] }),
|
|
2429
|
-
/* @__PURE__ */
|
|
2430
|
-
|
|
2431
|
-
|
|
2432
|
-
|
|
2433
|
-
|
|
2434
|
-
|
|
2435
|
-
|
|
2436
|
-
|
|
2437
|
-
|
|
2438
|
-
|
|
2439
|
-
|
|
2440
|
-
|
|
2441
|
-
|
|
2442
|
-
|
|
2443
|
-
|
|
2444
|
-
|
|
2445
|
-
|
|
2446
|
-
|
|
2447
|
-
|
|
2448
|
-
|
|
2449
|
-
|
|
2450
|
-
|
|
2451
|
-
|
|
2452
|
-
|
|
2453
|
-
|
|
2454
|
-
|
|
2455
|
-
|
|
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);
|
|
2497
|
+
adding ? /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", children: [
|
|
2498
|
+
/* @__PURE__ */ jsxs5(Box5, { children: [
|
|
2499
|
+
/* @__PURE__ */ jsx5(Text5, { color: theme.warn, children: adding === "name" ? "new pattern name: " : adding === "re" ? `regex for "${newName}": ` : "ghost route (glob path to hide, e.g. **/.env): " }),
|
|
2500
|
+
/* @__PURE__ */ jsx5(
|
|
2501
|
+
TextInput3,
|
|
2502
|
+
{
|
|
2503
|
+
value: input,
|
|
2504
|
+
onChange: setInput,
|
|
2505
|
+
onSubmit: (v) => {
|
|
2506
|
+
const t = v.trim();
|
|
2507
|
+
if (adding === "name") {
|
|
2508
|
+
if (!t) return setAdding(null);
|
|
2509
|
+
setNewName(t);
|
|
2510
|
+
setInput("");
|
|
2511
|
+
setAdding("re");
|
|
2512
|
+
} else if (adding === "re") {
|
|
2513
|
+
if (t && dlp) mutate({ ...dlp, custom: [...dlp.custom, { name: newName, re: t }] });
|
|
2514
|
+
setAdding(null);
|
|
2515
|
+
} else {
|
|
2516
|
+
if (t && !ghostPats.includes(t)) {
|
|
2517
|
+
setGhostPats((ps) => [...ps, t]);
|
|
2518
|
+
setDirty(true);
|
|
2519
|
+
setStatus(null);
|
|
2520
|
+
}
|
|
2521
|
+
setAdding(null);
|
|
2522
|
+
}
|
|
2523
|
+
}
|
|
2471
2524
|
}
|
|
2472
|
-
|
|
2473
|
-
)
|
|
2525
|
+
)
|
|
2526
|
+
] }),
|
|
2527
|
+
adding === "re" ? /* @__PURE__ */ jsx5(RegexTest, { re: input }) : null
|
|
2474
2528
|
] }) : null,
|
|
2475
|
-
|
|
2476
|
-
status ? /* @__PURE__ */ jsx5(
|
|
2529
|
+
/* @__PURE__ */ jsx5(Box5, { marginTop: 1, flexDirection: "column", height: budget, overflow: "hidden", children: win.map((l) => l.node) }),
|
|
2530
|
+
status ? /* @__PURE__ */ jsx5(Text5, { color: status.startsWith("\u2717") ? theme.bad : theme.ok, wrap: "truncate", children: status }) : null
|
|
2477
2531
|
] }) : null });
|
|
2478
2532
|
}
|
|
2479
2533
|
var SAMPLES = ["AKIA1234567890ABCD00", "sk-ant-api03-xxxxxxxx", "ghp_16chars0000000000000000000000000000", "password=hunter2", "Bearer eyJhbGciOi"];
|
|
@@ -4060,12 +4114,12 @@ function App() {
|
|
|
4060
4114
|
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
4115
|
] }),
|
|
4062
4116
|
/* @__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) => {
|
|
4117
|
+
/* @__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
4118
|
const isCur = i === effectiveSection;
|
|
4065
4119
|
const disabled = locked && s.label !== "Settings";
|
|
4066
4120
|
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
4121
|
}) }),
|
|
4068
|
-
/* @__PURE__ */ jsx8(Box8, { flexGrow: 1, borderStyle: "round", borderColor: focus === "panel" ? theme.accent : "gray", paddingX: 1, paddingY: 0, overflow: "hidden", children: panelBody })
|
|
4122
|
+
/* @__PURE__ */ jsx8(Box8, { flexGrow: 1, minWidth: 0, borderStyle: "round", borderColor: focus === "panel" ? theme.accent : "gray", paddingX: 1, paddingY: 0, overflow: "hidden", children: panelBody })
|
|
4069
4123
|
] }, viewNonce),
|
|
4070
4124
|
/* @__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
4125
|
] })
|
|
@@ -4075,7 +4129,8 @@ var HELP = [
|
|
|
4075
4129
|
["Global", [["\u2191\u2193", "move between sections"], ["\u2192 / enter", "open a section"], ["\u2190 / esc", "back to the menu"], ["?", "this help"], ["q", "quit"]]],
|
|
4076
4130
|
["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
4131
|
["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
|
|
4132
|
+
["Rate limit", [["\u2191\u2193", "field"], ["\u2190\u2192", "adjust (shift = \xB110)"], ["s", "save"]]],
|
|
4133
|
+
["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
4134
|
["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
4135
|
["Settings", [["\u2191\u2193", "move"], ["enter / space", "toggle \xB7 edit \xB7 add"], ["e", "webhook events"], ["d d", "delete"], ["r", "refresh"]]],
|
|
4081
4136
|
["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.73",
|
|
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": {
|