@solongate/proxy 0.81.71 → 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 +166 -104
- package/dist/tui/components.d.ts +4 -1
- package/dist/tui/index.js +165 -103
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -6946,11 +6946,12 @@ function PaneTitle({ label, extra, width: width2 }) {
|
|
|
6946
6946
|
/* @__PURE__ */ jsx(Text, { color: theme.dim, children: tail + "\u2500".repeat(Math.max(0, width2 - used)) })
|
|
6947
6947
|
] });
|
|
6948
6948
|
}
|
|
6949
|
-
function StreamLine({ e, loc, selected }) {
|
|
6949
|
+
function StreamLine({ e, loc, selected, date }) {
|
|
6950
6950
|
return /* @__PURE__ */ jsxs(Text, { wrap: "truncate", backgroundColor: selected ? "#1c2f63" : void 0, children: [
|
|
6951
6951
|
/* @__PURE__ */ jsx(Text, { color: selected ? theme.accentBright : theme.dim, children: selected ? "\u25B8" : " " }),
|
|
6952
6952
|
/* @__PURE__ */ jsxs(Text, { color: theme.dim, children: [
|
|
6953
6953
|
"[",
|
|
6954
|
+
date ? ymd(e.at) + " " : "",
|
|
6954
6955
|
hhmmss(e.at),
|
|
6955
6956
|
" "
|
|
6956
6957
|
] }),
|
|
@@ -7001,7 +7002,7 @@ function KeyHints({ hints }) {
|
|
|
7001
7002
|
i < hints.length - 1 ? " " : ""
|
|
7002
7003
|
] }, i)) });
|
|
7003
7004
|
}
|
|
7004
|
-
var hhmmss;
|
|
7005
|
+
var hhmmss, ymd;
|
|
7005
7006
|
var init_components = __esm({
|
|
7006
7007
|
"src/tui/components.tsx"() {
|
|
7007
7008
|
"use strict";
|
|
@@ -7010,6 +7011,12 @@ var init_components = __esm({
|
|
|
7010
7011
|
const d = new Date(ts);
|
|
7011
7012
|
return Number.isNaN(d.getTime()) ? "--:--:--" : d.toTimeString().slice(0, 8);
|
|
7012
7013
|
};
|
|
7014
|
+
ymd = (ts) => {
|
|
7015
|
+
const d = new Date(ts);
|
|
7016
|
+
if (Number.isNaN(d.getTime())) return "----------";
|
|
7017
|
+
const p = (n) => String(n).padStart(2, "0");
|
|
7018
|
+
return `${d.getFullYear()}-${p(d.getMonth() + 1)}-${p(d.getDate())}`;
|
|
7019
|
+
};
|
|
7013
7020
|
}
|
|
7014
7021
|
});
|
|
7015
7022
|
|
|
@@ -9266,28 +9273,26 @@ import TextInput3 from "ink-text-input";
|
|
|
9266
9273
|
import { useEffect as useEffect5, useState as useState5 } from "react";
|
|
9267
9274
|
import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
9268
9275
|
function DlpPanel({ focused }) {
|
|
9276
|
+
const { cols, rows } = usePanelSize();
|
|
9269
9277
|
const q = useLoader(() => api.settings.getSecurityLayers());
|
|
9270
9278
|
const [dlp, setDlp] = useState5(null);
|
|
9271
9279
|
const [available, setAvailable] = useState5([]);
|
|
9280
|
+
const [ghostOn, setGhostOn] = useState5(false);
|
|
9281
|
+
const [ghostPats, setGhostPats] = useState5([]);
|
|
9272
9282
|
const [sel, setSel] = useState5(0);
|
|
9273
9283
|
const [dirty, setDirty] = useState5(false);
|
|
9274
9284
|
const [status, setStatus] = useState5(null);
|
|
9275
9285
|
const [adding, setAdding] = useState5(null);
|
|
9276
9286
|
const [newName, setNewName] = useState5("");
|
|
9277
|
-
const [
|
|
9278
|
-
const [ghostOn, setGhostOn] = useState5(false);
|
|
9279
|
-
const spQ = useLoader(() => api.settings.getSelfProtection());
|
|
9280
|
-
const [selfProt, setSelfProt] = useState5(null);
|
|
9287
|
+
const [input, setInput] = useState5("");
|
|
9281
9288
|
useEffect5(() => {
|
|
9282
9289
|
if (q.data && !dlp) {
|
|
9283
9290
|
setDlp({ ...q.data.layers.dlp, patterns: [...q.data.layers.dlp.patterns], custom: [...q.data.layers.dlp.custom] });
|
|
9284
9291
|
setAvailable(q.data.availablePatterns);
|
|
9285
9292
|
setGhostOn(q.data.layers.ghost.mode === "on");
|
|
9293
|
+
setGhostPats([...q.data.layers.ghost.patterns]);
|
|
9286
9294
|
}
|
|
9287
9295
|
}, [q.data, dlp]);
|
|
9288
|
-
useEffect5(() => {
|
|
9289
|
-
if (spQ.data && selfProt === null) setSelfProt(spQ.data.enabled);
|
|
9290
|
-
}, [spQ.data, selfProt]);
|
|
9291
9296
|
const mutate = (next) => {
|
|
9292
9297
|
setDlp(next);
|
|
9293
9298
|
setDirty(true);
|
|
@@ -9297,128 +9302,184 @@ function DlpPanel({ focused }) {
|
|
|
9297
9302
|
if (!dlp || !q.data) return;
|
|
9298
9303
|
setStatus("Saving\u2026");
|
|
9299
9304
|
try {
|
|
9300
|
-
const ghost = {
|
|
9305
|
+
const ghost = { mode: ghostOn ? "on" : "off", patterns: ghostPats };
|
|
9301
9306
|
const res = await api.settings.setSecurityLayers({ ...q.data.layers, dlp, ghost });
|
|
9302
9307
|
setDlp({ ...res.layers.dlp, patterns: [...res.layers.dlp.patterns], custom: [...res.layers.dlp.custom] });
|
|
9303
9308
|
setGhostOn(res.layers.ghost.mode === "on");
|
|
9309
|
+
setGhostPats([...res.layers.ghost.patterns]);
|
|
9304
9310
|
setDirty(false);
|
|
9305
9311
|
setStatus("\u2713 Saved");
|
|
9306
9312
|
} catch (e) {
|
|
9307
9313
|
setStatus("\u2717 " + (e instanceof Error ? e.message : String(e)));
|
|
9308
9314
|
}
|
|
9309
9315
|
};
|
|
9310
|
-
const toggleSelfProt = async () => {
|
|
9311
|
-
const next = !(selfProt ?? false);
|
|
9312
|
-
setSelfProt(next);
|
|
9313
|
-
try {
|
|
9314
|
-
await api.settings.setSelfProtection(next);
|
|
9315
|
-
setStatus(`\u2713 self-protection ${next ? "on" : "off"}`);
|
|
9316
|
-
} catch (e) {
|
|
9317
|
-
setSelfProt(!next);
|
|
9318
|
-
setStatus("\u2717 " + (e instanceof Error ? e.message : String(e)));
|
|
9319
|
-
}
|
|
9320
|
-
};
|
|
9321
9316
|
const discard = () => {
|
|
9322
|
-
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]);
|
|
9323
9321
|
setDirty(false);
|
|
9324
9322
|
setStatus("discarded");
|
|
9325
9323
|
};
|
|
9326
|
-
const
|
|
9327
|
-
|
|
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];
|
|
9328
9331
|
useInput4(
|
|
9329
|
-
(
|
|
9332
|
+
(input2, key) => {
|
|
9330
9333
|
if (!dlp) return;
|
|
9331
|
-
if (key.upArrow) setSel((
|
|
9332
|
-
else if (key.downArrow) setSel((
|
|
9333
|
-
else if (
|
|
9334
|
-
|
|
9335
|
-
mutate({ ...dlp, mode: MODES2[idx] });
|
|
9336
|
-
} else if (input === "a") {
|
|
9337
|
-
setNewName("");
|
|
9338
|
-
setNewRe("");
|
|
9339
|
-
setAdding("name");
|
|
9340
|
-
} else if (input === " " && sel < available.length) {
|
|
9341
|
-
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") {
|
|
9342
9338
|
const set = new Set(dlp.patterns);
|
|
9343
|
-
if (set.has(
|
|
9344
|
-
else set.add(
|
|
9339
|
+
if (set.has(cur.name)) set.delete(cur.name);
|
|
9340
|
+
else set.add(cur.name);
|
|
9345
9341
|
mutate({ ...dlp, patterns: [...set] });
|
|
9346
|
-
} else if (
|
|
9347
|
-
|
|
9348
|
-
|
|
9349
|
-
|
|
9350
|
-
} 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") {
|
|
9351
9360
|
setGhostOn((v) => !v);
|
|
9352
9361
|
setDirty(true);
|
|
9353
9362
|
setStatus(null);
|
|
9354
|
-
} else if (
|
|
9355
|
-
else if (
|
|
9356
|
-
else if (input === "x") discard();
|
|
9363
|
+
} else if (input2 === "s") void save();
|
|
9364
|
+
else if (input2 === "x") discard();
|
|
9357
9365
|
},
|
|
9358
9366
|
{ isActive: focused && !adding }
|
|
9359
9367
|
);
|
|
9360
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));
|
|
9361
9430
|
return /* @__PURE__ */ jsx5(DataView, { loading: q.loading && !dlp, error: q.error, children: dlp ? /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", children: [
|
|
9362
|
-
/* @__PURE__ */ jsxs5(
|
|
9431
|
+
/* @__PURE__ */ jsxs5(Text5, { wrap: "truncate", children: [
|
|
9363
9432
|
/* @__PURE__ */ jsx5(Text5, { children: "mode: " }),
|
|
9364
|
-
/* @__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)" }),
|
|
9365
9435
|
dirty ? /* @__PURE__ */ jsx5(Text5, { color: theme.warn, children: " \u25CF unsaved (s save \xB7 x discard)" }) : null
|
|
9366
9436
|
] }),
|
|
9367
|
-
/* @__PURE__ */ jsx5(Text5, { color: theme.dim, children: focused ? "\u2191\u2193 \xB7 space
|
|
9368
|
-
/* @__PURE__ */ jsxs5(
|
|
9369
|
-
|
|
9370
|
-
/* @__PURE__ */ jsx5(Text5, { color:
|
|
9371
|
-
|
|
9372
|
-
/* @__PURE__ */ jsx5(Text5, { color:
|
|
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
|
|
9373
9448
|
] }),
|
|
9374
|
-
/* @__PURE__ */
|
|
9375
|
-
|
|
9376
|
-
|
|
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
|
-
onChange: setNewName,
|
|
9402
|
-
onSubmit: (v) => {
|
|
9403
|
-
if (!v.trim()) return setAdding(null);
|
|
9404
|
-
setNewName(v.trim());
|
|
9405
|
-
setAdding("re");
|
|
9406
|
-
}
|
|
9407
|
-
}
|
|
9408
|
-
) : /* @__PURE__ */ jsx5(
|
|
9409
|
-
TextInput3,
|
|
9410
|
-
{
|
|
9411
|
-
value: newRe,
|
|
9412
|
-
onChange: setNewRe,
|
|
9413
|
-
onSubmit: (v) => {
|
|
9414
|
-
if (v.trim() && dlp) mutate({ ...dlp, custom: [...dlp.custom, { name: newName, re: v.trim() }] });
|
|
9415
|
-
setAdding(null);
|
|
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
|
+
}
|
|
9416
9476
|
}
|
|
9417
|
-
|
|
9418
|
-
)
|
|
9477
|
+
)
|
|
9478
|
+
] }),
|
|
9479
|
+
adding === "re" ? /* @__PURE__ */ jsx5(RegexTest, { re: input }) : null
|
|
9419
9480
|
] }) : null,
|
|
9420
|
-
|
|
9421
|
-
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
|
|
9422
9483
|
] }) : null });
|
|
9423
9484
|
}
|
|
9424
9485
|
function RegexTest({ re }) {
|
|
@@ -9973,7 +10034,7 @@ function AuditPanel({ active: active2, focused }) {
|
|
|
9973
10034
|
)
|
|
9974
10035
|
] }) : null,
|
|
9975
10036
|
/* @__PURE__ */ jsx6(Text6, { color: theme.dim, wrap: "truncate", children: `${total} matched \xB7 page ${Math.min(page + 1, pages)}/${pages} \xB7 ${PAGE}/page \xB7 ${pageRows.length ? selClamped + 1 : 0}/${pageRows.length}${start ? ` \xB7 \u25B2${start} newer` : ""}${start + listRows < pageRows.length ? ` \xB7 \u25BC${pageRows.length - start - listRows} older` : ""}` }),
|
|
9976
|
-
/* @__PURE__ */ jsx6(Box6, { flexDirection: "column", overflow: "hidden", children: windowed.map((e, i) => /* @__PURE__ */ jsx6(StreamLine, { e: toStream(e), loc: source === "local", selected: start + i === selClamped && focused }, e.id)) }),
|
|
10037
|
+
/* @__PURE__ */ jsx6(Box6, { flexDirection: "column", overflow: "hidden", children: windowed.map((e, i) => /* @__PURE__ */ jsx6(StreamLine, { e: toStream(e), loc: source === "local", selected: start + i === selClamped && focused, date: true }, e.id)) }),
|
|
9977
10038
|
pageRows.length === 0 ? /* @__PURE__ */ jsxs6(Text6, { color: theme.dim, children: [
|
|
9978
10039
|
"(no entries",
|
|
9979
10040
|
source === "local" ? " in the local file" : "",
|
|
@@ -11048,12 +11109,12 @@ function App() {
|
|
|
11048
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
|
|
11049
11110
|
] }),
|
|
11050
11111
|
/* @__PURE__ */ jsxs8(Box8, { marginTop: 1, flexGrow: 1, children: [
|
|
11051
|
-
/* @__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) => {
|
|
11052
11113
|
const isCur = i === effectiveSection;
|
|
11053
11114
|
const disabled = locked && s.label !== "Settings";
|
|
11054
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);
|
|
11055
11116
|
}) }),
|
|
11056
|
-
/* @__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 })
|
|
11057
11118
|
] }, viewNonce),
|
|
11058
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"]] }) })
|
|
11059
11120
|
] })
|
|
@@ -11103,7 +11164,8 @@ var init_App = __esm({
|
|
|
11103
11164
|
["Global", [["\u2191\u2193", "move between sections"], ["\u2192 / enter", "open a section"], ["\u2190 / esc", "back to the menu"], ["?", "this help"], ["q", "quit"]]],
|
|
11104
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)"]]],
|
|
11105
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"]]],
|
|
11106
|
-
["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"]]],
|
|
11107
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"]]],
|
|
11108
11170
|
["Settings", [["\u2191\u2193", "move"], ["enter / space", "toggle \xB7 edit \xB7 add"], ["e", "webhook events"], ["d d", "delete"], ["r", "refresh"]]],
|
|
11109
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/components.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import type { ReactNode } from 'react';
|
|
2
2
|
/** HH:MM:SS for a timestamp (ms or ISO); `--:--:--` when unparseable. */
|
|
3
3
|
export declare const hhmmss: (ts: string | number) => string;
|
|
4
|
+
/** YYYY-MM-DD for a timestamp; `----------` when unparseable. */
|
|
5
|
+
export declare const ymd: (ts: string | number) => string;
|
|
4
6
|
/** Section divider title used across the Live/Audit consoles. */
|
|
5
7
|
export declare function PaneTitle({ label, extra, width }: {
|
|
6
8
|
label: string;
|
|
@@ -25,10 +27,11 @@ export interface StreamRow {
|
|
|
25
27
|
evalMs?: number | null;
|
|
26
28
|
rule?: string | null;
|
|
27
29
|
}
|
|
28
|
-
export declare function StreamLine({ e, loc, selected }: {
|
|
30
|
+
export declare function StreamLine({ e, loc, selected, date }: {
|
|
29
31
|
e: StreamRow;
|
|
30
32
|
loc: boolean;
|
|
31
33
|
selected?: boolean;
|
|
34
|
+
date?: boolean;
|
|
32
35
|
}): JSX.Element;
|
|
33
36
|
export declare function Panel({ title, subtitle, children }: {
|
|
34
37
|
title: string;
|
package/dist/tui/index.js
CHANGED
|
@@ -129,6 +129,12 @@ var hhmmss = (ts) => {
|
|
|
129
129
|
const d = new Date(ts);
|
|
130
130
|
return Number.isNaN(d.getTime()) ? "--:--:--" : d.toTimeString().slice(0, 8);
|
|
131
131
|
};
|
|
132
|
+
var ymd = (ts) => {
|
|
133
|
+
const d = new Date(ts);
|
|
134
|
+
if (Number.isNaN(d.getTime())) return "----------";
|
|
135
|
+
const p = (n) => String(n).padStart(2, "0");
|
|
136
|
+
return `${d.getFullYear()}-${p(d.getMonth() + 1)}-${p(d.getDate())}`;
|
|
137
|
+
};
|
|
132
138
|
function PaneTitle({ label, extra, width }) {
|
|
133
139
|
const tail = extra ? ` ${extra} ` : " ";
|
|
134
140
|
const used = 2 + 1 + label.length + tail.length;
|
|
@@ -141,11 +147,12 @@ function PaneTitle({ label, extra, width }) {
|
|
|
141
147
|
/* @__PURE__ */ jsx(Text, { color: theme.dim, children: tail + "\u2500".repeat(Math.max(0, width - used)) })
|
|
142
148
|
] });
|
|
143
149
|
}
|
|
144
|
-
function StreamLine({ e, loc, selected }) {
|
|
150
|
+
function StreamLine({ e, loc, selected, date }) {
|
|
145
151
|
return /* @__PURE__ */ jsxs(Text, { wrap: "truncate", backgroundColor: selected ? "#1c2f63" : void 0, children: [
|
|
146
152
|
/* @__PURE__ */ jsx(Text, { color: selected ? theme.accentBright : theme.dim, children: selected ? "\u25B8" : " " }),
|
|
147
153
|
/* @__PURE__ */ jsxs(Text, { color: theme.dim, children: [
|
|
148
154
|
"[",
|
|
155
|
+
date ? ymd(e.at) + " " : "",
|
|
149
156
|
hhmmss(e.at),
|
|
150
157
|
" "
|
|
151
158
|
] }),
|
|
@@ -2314,28 +2321,26 @@ import { useEffect as useEffect5, useState as useState5 } from "react";
|
|
|
2314
2321
|
import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
2315
2322
|
var MODES2 = ["off", "detect", "block"];
|
|
2316
2323
|
function DlpPanel({ focused }) {
|
|
2324
|
+
const { cols, rows } = usePanelSize();
|
|
2317
2325
|
const q = useLoader(() => api.settings.getSecurityLayers());
|
|
2318
2326
|
const [dlp, setDlp] = useState5(null);
|
|
2319
2327
|
const [available, setAvailable] = useState5([]);
|
|
2328
|
+
const [ghostOn, setGhostOn] = useState5(false);
|
|
2329
|
+
const [ghostPats, setGhostPats] = useState5([]);
|
|
2320
2330
|
const [sel, setSel] = useState5(0);
|
|
2321
2331
|
const [dirty, setDirty] = useState5(false);
|
|
2322
2332
|
const [status, setStatus] = useState5(null);
|
|
2323
2333
|
const [adding, setAdding] = useState5(null);
|
|
2324
2334
|
const [newName, setNewName] = useState5("");
|
|
2325
|
-
const [
|
|
2326
|
-
const [ghostOn, setGhostOn] = useState5(false);
|
|
2327
|
-
const spQ = useLoader(() => api.settings.getSelfProtection());
|
|
2328
|
-
const [selfProt, setSelfProt] = useState5(null);
|
|
2335
|
+
const [input, setInput] = useState5("");
|
|
2329
2336
|
useEffect5(() => {
|
|
2330
2337
|
if (q.data && !dlp) {
|
|
2331
2338
|
setDlp({ ...q.data.layers.dlp, patterns: [...q.data.layers.dlp.patterns], custom: [...q.data.layers.dlp.custom] });
|
|
2332
2339
|
setAvailable(q.data.availablePatterns);
|
|
2333
2340
|
setGhostOn(q.data.layers.ghost.mode === "on");
|
|
2341
|
+
setGhostPats([...q.data.layers.ghost.patterns]);
|
|
2334
2342
|
}
|
|
2335
2343
|
}, [q.data, dlp]);
|
|
2336
|
-
useEffect5(() => {
|
|
2337
|
-
if (spQ.data && selfProt === null) setSelfProt(spQ.data.enabled);
|
|
2338
|
-
}, [spQ.data, selfProt]);
|
|
2339
2344
|
const mutate = (next) => {
|
|
2340
2345
|
setDlp(next);
|
|
2341
2346
|
setDirty(true);
|
|
@@ -2345,128 +2350,184 @@ function DlpPanel({ focused }) {
|
|
|
2345
2350
|
if (!dlp || !q.data) return;
|
|
2346
2351
|
setStatus("Saving\u2026");
|
|
2347
2352
|
try {
|
|
2348
|
-
const ghost = {
|
|
2353
|
+
const ghost = { mode: ghostOn ? "on" : "off", patterns: ghostPats };
|
|
2349
2354
|
const res = await api.settings.setSecurityLayers({ ...q.data.layers, dlp, ghost });
|
|
2350
2355
|
setDlp({ ...res.layers.dlp, patterns: [...res.layers.dlp.patterns], custom: [...res.layers.dlp.custom] });
|
|
2351
2356
|
setGhostOn(res.layers.ghost.mode === "on");
|
|
2357
|
+
setGhostPats([...res.layers.ghost.patterns]);
|
|
2352
2358
|
setDirty(false);
|
|
2353
2359
|
setStatus("\u2713 Saved");
|
|
2354
2360
|
} catch (e) {
|
|
2355
2361
|
setStatus("\u2717 " + (e instanceof Error ? e.message : String(e)));
|
|
2356
2362
|
}
|
|
2357
2363
|
};
|
|
2358
|
-
const toggleSelfProt = async () => {
|
|
2359
|
-
const next = !(selfProt ?? false);
|
|
2360
|
-
setSelfProt(next);
|
|
2361
|
-
try {
|
|
2362
|
-
await api.settings.setSelfProtection(next);
|
|
2363
|
-
setStatus(`\u2713 self-protection ${next ? "on" : "off"}`);
|
|
2364
|
-
} catch (e) {
|
|
2365
|
-
setSelfProt(!next);
|
|
2366
|
-
setStatus("\u2717 " + (e instanceof Error ? e.message : String(e)));
|
|
2367
|
-
}
|
|
2368
|
-
};
|
|
2369
2364
|
const discard = () => {
|
|
2370
|
-
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]);
|
|
2371
2369
|
setDirty(false);
|
|
2372
2370
|
setStatus("discarded");
|
|
2373
2371
|
};
|
|
2374
|
-
const
|
|
2375
|
-
|
|
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];
|
|
2376
2379
|
useInput4(
|
|
2377
|
-
(
|
|
2380
|
+
(input2, key) => {
|
|
2378
2381
|
if (!dlp) return;
|
|
2379
|
-
if (key.upArrow) setSel((
|
|
2380
|
-
else if (key.downArrow) setSel((
|
|
2381
|
-
else if (
|
|
2382
|
-
|
|
2383
|
-
mutate({ ...dlp, mode: MODES2[idx] });
|
|
2384
|
-
} else if (input === "a") {
|
|
2385
|
-
setNewName("");
|
|
2386
|
-
setNewRe("");
|
|
2387
|
-
setAdding("name");
|
|
2388
|
-
} else if (input === " " && sel < available.length) {
|
|
2389
|
-
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") {
|
|
2390
2386
|
const set = new Set(dlp.patterns);
|
|
2391
|
-
if (set.has(
|
|
2392
|
-
else set.add(
|
|
2387
|
+
if (set.has(cur.name)) set.delete(cur.name);
|
|
2388
|
+
else set.add(cur.name);
|
|
2393
2389
|
mutate({ ...dlp, patterns: [...set] });
|
|
2394
|
-
} else if (
|
|
2395
|
-
|
|
2396
|
-
|
|
2397
|
-
|
|
2398
|
-
} 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") {
|
|
2399
2408
|
setGhostOn((v) => !v);
|
|
2400
2409
|
setDirty(true);
|
|
2401
2410
|
setStatus(null);
|
|
2402
|
-
} else if (
|
|
2403
|
-
else if (
|
|
2404
|
-
else if (input === "x") discard();
|
|
2411
|
+
} else if (input2 === "s") void save();
|
|
2412
|
+
else if (input2 === "x") discard();
|
|
2405
2413
|
},
|
|
2406
2414
|
{ isActive: focused && !adding }
|
|
2407
2415
|
);
|
|
2408
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));
|
|
2409
2478
|
return /* @__PURE__ */ jsx5(DataView, { loading: q.loading && !dlp, error: q.error, children: dlp ? /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", children: [
|
|
2410
|
-
/* @__PURE__ */ jsxs5(
|
|
2479
|
+
/* @__PURE__ */ jsxs5(Text5, { wrap: "truncate", children: [
|
|
2411
2480
|
/* @__PURE__ */ jsx5(Text5, { children: "mode: " }),
|
|
2412
|
-
/* @__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)" }),
|
|
2413
2483
|
dirty ? /* @__PURE__ */ jsx5(Text5, { color: theme.warn, children: " \u25CF unsaved (s save \xB7 x discard)" }) : null
|
|
2414
2484
|
] }),
|
|
2415
|
-
/* @__PURE__ */ jsx5(Text5, { color: theme.dim, children: focused ? "\u2191\u2193 \xB7 space
|
|
2416
|
-
/* @__PURE__ */ jsxs5(
|
|
2417
|
-
|
|
2418
|
-
/* @__PURE__ */ jsx5(Text5, { color:
|
|
2419
|
-
|
|
2420
|
-
/* @__PURE__ */ jsx5(Text5, { color:
|
|
2421
|
-
|
|
2422
|
-
|
|
2423
|
-
|
|
2424
|
-
|
|
2425
|
-
|
|
2426
|
-
(active2 ? "\u25B8 " : " ") + (on ? "\u25CF " : "\u25CB "),
|
|
2427
|
-
/* @__PURE__ */ jsx5(Text5, { color: on ? theme.ok : theme.dim, children: p })
|
|
2428
|
-
] }, p);
|
|
2429
|
-
}) }),
|
|
2430
|
-
/* @__PURE__ */ jsxs5(Box5, { marginTop: 1, flexDirection: "column", children: [
|
|
2431
|
-
/* @__PURE__ */ jsx5(Text5, { color: theme.dim, children: "Custom patterns" }),
|
|
2432
|
-
dlp.custom.length === 0 ? /* @__PURE__ */ jsx5(Text5, { color: theme.dim, children: " (none \u2014 press a to add)" }) : null,
|
|
2433
|
-
dlp.custom.map((c2, i) => {
|
|
2434
|
-
const active2 = focused && sel === available.length + i;
|
|
2435
|
-
return /* @__PURE__ */ jsxs5(Text5, { color: active2 ? theme.accentBright : void 0, bold: active2, children: [
|
|
2436
|
-
active2 ? "\u25B8 " : " ",
|
|
2437
|
-
/* @__PURE__ */ jsx5(Text5, { color: theme.accent, children: c2.name }),
|
|
2438
|
-
" ",
|
|
2439
|
-
/* @__PURE__ */ jsx5(Text5, { color: theme.dim, children: c2.re })
|
|
2440
|
-
] }, c2.name + i);
|
|
2441
|
-
})
|
|
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
|
|
2442
2496
|
] }),
|
|
2443
|
-
adding ? /* @__PURE__ */ jsxs5(Box5, {
|
|
2444
|
-
/* @__PURE__ */
|
|
2445
|
-
|
|
2446
|
-
|
|
2447
|
-
|
|
2448
|
-
|
|
2449
|
-
|
|
2450
|
-
|
|
2451
|
-
|
|
2452
|
-
|
|
2453
|
-
|
|
2454
|
-
|
|
2455
|
-
|
|
2456
|
-
|
|
2457
|
-
|
|
2458
|
-
|
|
2459
|
-
|
|
2460
|
-
|
|
2461
|
-
|
|
2462
|
-
|
|
2463
|
-
|
|
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
|
+
}
|
|
2464
2524
|
}
|
|
2465
|
-
|
|
2466
|
-
)
|
|
2525
|
+
)
|
|
2526
|
+
] }),
|
|
2527
|
+
adding === "re" ? /* @__PURE__ */ jsx5(RegexTest, { re: input }) : null
|
|
2467
2528
|
] }) : null,
|
|
2468
|
-
|
|
2469
|
-
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
|
|
2470
2531
|
] }) : null });
|
|
2471
2532
|
}
|
|
2472
2533
|
var SAMPLES = ["AKIA1234567890ABCD00", "sk-ant-api03-xxxxxxxx", "ghp_16chars0000000000000000000000000000", "password=hunter2", "Bearer eyJhbGciOi"];
|
|
@@ -3093,7 +3154,7 @@ function AuditPanel({ active: active2, focused }) {
|
|
|
3093
3154
|
)
|
|
3094
3155
|
] }) : null,
|
|
3095
3156
|
/* @__PURE__ */ jsx6(Text6, { color: theme.dim, wrap: "truncate", children: `${total} matched \xB7 page ${Math.min(page + 1, pages)}/${pages} \xB7 ${PAGE}/page \xB7 ${pageRows.length ? selClamped + 1 : 0}/${pageRows.length}${start ? ` \xB7 \u25B2${start} newer` : ""}${start + listRows < pageRows.length ? ` \xB7 \u25BC${pageRows.length - start - listRows} older` : ""}` }),
|
|
3096
|
-
/* @__PURE__ */ jsx6(Box6, { flexDirection: "column", overflow: "hidden", children: windowed.map((e, i) => /* @__PURE__ */ jsx6(StreamLine, { e: toStream(e), loc: source === "local", selected: start + i === selClamped && focused }, e.id)) }),
|
|
3157
|
+
/* @__PURE__ */ jsx6(Box6, { flexDirection: "column", overflow: "hidden", children: windowed.map((e, i) => /* @__PURE__ */ jsx6(StreamLine, { e: toStream(e), loc: source === "local", selected: start + i === selClamped && focused, date: true }, e.id)) }),
|
|
3097
3158
|
pageRows.length === 0 ? /* @__PURE__ */ jsxs6(Text6, { color: theme.dim, children: [
|
|
3098
3159
|
"(no entries",
|
|
3099
3160
|
source === "local" ? " in the local file" : "",
|
|
@@ -4053,12 +4114,12 @@ function App() {
|
|
|
4053
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
|
|
4054
4115
|
] }),
|
|
4055
4116
|
/* @__PURE__ */ jsxs8(Box8, { marginTop: 1, flexGrow: 1, children: [
|
|
4056
|
-
/* @__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) => {
|
|
4057
4118
|
const isCur = i === effectiveSection;
|
|
4058
4119
|
const disabled = locked && s.label !== "Settings";
|
|
4059
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);
|
|
4060
4121
|
}) }),
|
|
4061
|
-
/* @__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 })
|
|
4062
4123
|
] }, viewNonce),
|
|
4063
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"]] }) })
|
|
4064
4125
|
] })
|
|
@@ -4068,7 +4129,8 @@ var HELP = [
|
|
|
4068
4129
|
["Global", [["\u2191\u2193", "move between sections"], ["\u2192 / enter", "open a section"], ["\u2190 / esc", "back to the menu"], ["?", "this help"], ["q", "quit"]]],
|
|
4069
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)"]]],
|
|
4070
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"]]],
|
|
4071
|
-
["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"]]],
|
|
4072
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"]]],
|
|
4073
4135
|
["Settings", [["\u2191\u2193", "move"], ["enter / space", "toggle \xB7 edit \xB7 add"], ["e", "webhook events"], ["d d", "delete"], ["r", "refresh"]]],
|
|
4074
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": {
|