@solongate/proxy 0.62.0 → 0.63.0
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 +169 -82
- package/dist/tui/index.js +168 -81
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -7020,78 +7020,165 @@ var init_hooks = __esm({
|
|
|
7020
7020
|
|
|
7021
7021
|
// src/tui/panels/Live.tsx
|
|
7022
7022
|
import { Box as Box2, Text as Text2 } from "ink";
|
|
7023
|
+
import { useEffect as useEffect2, useRef as useRef2, useState as useState2 } from "react";
|
|
7023
7024
|
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
7024
|
-
function Tile({ label, value, color }) {
|
|
7025
|
-
return /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", borderStyle: "round", borderColor: "gray", paddingX: 1, marginRight: 1, minWidth: 14, children: [
|
|
7026
|
-
/* @__PURE__ */ jsx2(Text2, { color: theme.dim, children: label }),
|
|
7027
|
-
/* @__PURE__ */ jsx2(Text2, { bold: true, color, children: value })
|
|
7028
|
-
] });
|
|
7029
|
-
}
|
|
7030
7025
|
function LivePanel({ active: active2 }) {
|
|
7031
7026
|
const stats = useLoader(() => api.stats.get());
|
|
7032
7027
|
const ts = useLoader(() => api.stats.timeseries({ period: "24h" }));
|
|
7033
|
-
const feed = useLoader(() => api.audit.list({ limit:
|
|
7028
|
+
const feed = useLoader(() => api.audit.list({ limit: 40 }));
|
|
7034
7029
|
usePoll(() => {
|
|
7035
7030
|
stats.reload();
|
|
7036
7031
|
ts.reload();
|
|
7037
7032
|
feed.reload();
|
|
7038
7033
|
}, 2e3, active2);
|
|
7034
|
+
const [tick, setTick] = useState2(0);
|
|
7035
|
+
useEffect2(() => {
|
|
7036
|
+
if (!active2) return;
|
|
7037
|
+
const t = setInterval(() => setTick((n) => n + 1), 200);
|
|
7038
|
+
return () => clearInterval(t);
|
|
7039
|
+
}, [active2]);
|
|
7040
|
+
const startRef = useRef2(Date.now());
|
|
7041
|
+
const [buffer, setBuffer] = useState2([]);
|
|
7042
|
+
useEffect2(() => {
|
|
7043
|
+
const incoming = feed.data?.entries;
|
|
7044
|
+
if (!incoming?.length) return;
|
|
7045
|
+
setBuffer((prev) => {
|
|
7046
|
+
const seen = new Set(prev.map((e) => e.id));
|
|
7047
|
+
const fresh = incoming.filter((e) => !seen.has(e.id)).sort((a, b) => Date.parse(a.created_at) - Date.parse(b.created_at));
|
|
7048
|
+
return fresh.length ? [...prev, ...fresh].slice(-300) : prev;
|
|
7049
|
+
});
|
|
7050
|
+
}, [feed.data]);
|
|
7039
7051
|
const s = stats.data;
|
|
7040
7052
|
const points = ts.data?.timeseries ?? [];
|
|
7041
|
-
const
|
|
7042
|
-
const
|
|
7043
|
-
|
|
7053
|
+
const cols = process.stdout.columns ?? 100;
|
|
7054
|
+
const rows = process.stdout.rows ?? 32;
|
|
7055
|
+
const feedRows = Math.max(8, Math.min(20, rows - 18));
|
|
7056
|
+
const wide = cols >= 112;
|
|
7057
|
+
const tail = buffer.slice(-feedRows);
|
|
7058
|
+
const denies = buffer.filter((e) => e.decision !== "ALLOW");
|
|
7059
|
+
const dlpHits = buffer.filter((e) => e.dlp_matches?.length);
|
|
7060
|
+
const lastDeny = denies[denies.length - 1];
|
|
7061
|
+
const spin = SPIN[tick % SPIN.length];
|
|
7062
|
+
const cursor = tick % 4 < 2 ? "\u258C" : " ";
|
|
7063
|
+
if (stats.error) return /* @__PURE__ */ jsxs2(Text2, { color: theme.bad, children: [
|
|
7064
|
+
"\u2717 ",
|
|
7065
|
+
stats.error
|
|
7066
|
+
] });
|
|
7067
|
+
return /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", children: [
|
|
7044
7068
|
/* @__PURE__ */ jsxs2(Box2, { children: [
|
|
7045
|
-
/* @__PURE__ */ jsx2(Text2, { color: theme.bad, children: "\u25CF" }),
|
|
7046
|
-
/* @__PURE__ */ jsx2(Text2, { color: theme.
|
|
7069
|
+
/* @__PURE__ */ jsx2(Text2, { color: theme.bad, children: "\u25CF " }),
|
|
7070
|
+
/* @__PURE__ */ jsx2(Text2, { bold: true, color: theme.accentBright, children: "LIVE" }),
|
|
7071
|
+
/* @__PURE__ */ jsxs2(Text2, { color: theme.dim, children: [
|
|
7072
|
+
" ",
|
|
7073
|
+
spin,
|
|
7074
|
+
" scanning"
|
|
7075
|
+
] }),
|
|
7076
|
+
/* @__PURE__ */ jsxs2(Text2, { color: theme.dim, children: [
|
|
7077
|
+
" up ",
|
|
7078
|
+
fmtUp(Date.now() - startRef.current)
|
|
7079
|
+
] }),
|
|
7080
|
+
/* @__PURE__ */ jsxs2(Text2, { color: theme.dim, children: [
|
|
7081
|
+
" ",
|
|
7082
|
+
hhmmss(Date.now())
|
|
7083
|
+
] }),
|
|
7084
|
+
/* @__PURE__ */ jsx2(Text2, { color: theme.dim, children: " poll 2s" })
|
|
7047
7085
|
] }),
|
|
7048
|
-
|
|
7049
|
-
/* @__PURE__ */ jsx2(
|
|
7050
|
-
/* @__PURE__ */ jsx2(
|
|
7051
|
-
/* @__PURE__ */ jsx2(
|
|
7052
|
-
/* @__PURE__ */ jsx2(
|
|
7053
|
-
/* @__PURE__ */ jsx2(
|
|
7054
|
-
|
|
7055
|
-
|
|
7056
|
-
/* @__PURE__ */ jsx2(Text2, { color: theme.dim, children:
|
|
7057
|
-
/* @__PURE__ */
|
|
7058
|
-
|
|
7059
|
-
|
|
7086
|
+
/* @__PURE__ */ jsxs2(Box2, { children: [
|
|
7087
|
+
/* @__PURE__ */ jsx2(Text2, { color: theme.dim, children: "calls " }),
|
|
7088
|
+
/* @__PURE__ */ jsx2(Text2, { bold: true, children: s ? s.total_calls : "\xB7\xB7\xB7\xB7" }),
|
|
7089
|
+
/* @__PURE__ */ jsx2(Text2, { color: theme.dim, children: " allow " }),
|
|
7090
|
+
/* @__PURE__ */ jsx2(Text2, { color: theme.ok, children: s ? s.allowed : "\xB7\xB7\xB7" }),
|
|
7091
|
+
/* @__PURE__ */ jsx2(Text2, { color: theme.dim, children: " deny " }),
|
|
7092
|
+
/* @__PURE__ */ jsx2(Text2, { color: theme.bad, bold: true, children: s ? s.denied : "\xB7\xB7" }),
|
|
7093
|
+
/* @__PURE__ */ jsx2(Text2, { color: theme.dim, children: " dlp(buf) " }),
|
|
7094
|
+
/* @__PURE__ */ jsx2(Text2, { color: dlpHits.length ? theme.bad : theme.dim, children: dlpHits.length }),
|
|
7095
|
+
/* @__PURE__ */ jsx2(Text2, { color: theme.dim, children: " policies " }),
|
|
7096
|
+
/* @__PURE__ */ jsx2(Text2, { color: theme.accent, children: s ? s.active_policies : "\xB7" })
|
|
7097
|
+
] }),
|
|
7098
|
+
/* @__PURE__ */ jsxs2(Box2, { children: [
|
|
7099
|
+
/* @__PURE__ */ jsx2(Text2, { color: theme.dim, children: "act " }),
|
|
7100
|
+
/* @__PURE__ */ jsx2(Text2, { color: theme.accent, children: sparkline(points.map((p) => p.total), Math.min(64, cols - 30)) })
|
|
7101
|
+
] }),
|
|
7102
|
+
/* @__PURE__ */ jsxs2(Box2, { children: [
|
|
7103
|
+
/* @__PURE__ */ jsx2(Text2, { color: theme.dim, children: "dny " }),
|
|
7104
|
+
/* @__PURE__ */ jsx2(Text2, { color: theme.bad, children: sparkline(points.map((p) => p.denied), Math.min(64, cols - 30)) })
|
|
7105
|
+
] }),
|
|
7106
|
+
/* @__PURE__ */ jsxs2(Box2, { children: [
|
|
7107
|
+
/* @__PURE__ */ jsx2(Text2, { color: theme.dim, children: ">> " }),
|
|
7108
|
+
lastDeny ? /* @__PURE__ */ jsxs2(Text2, { color: theme.bad, children: [
|
|
7109
|
+
"last deny ",
|
|
7110
|
+
hhmmss(lastDeny.created_at),
|
|
7111
|
+
" ",
|
|
7112
|
+
lastDeny.tool_name,
|
|
7113
|
+
" \xB7 ",
|
|
7114
|
+
truncate2(lastDeny.reason ?? "policy", Math.max(20, cols - 50))
|
|
7115
|
+
] }) : /* @__PURE__ */ jsx2(Text2, { color: theme.dim, children: "no denials in buffer" })
|
|
7116
|
+
] }),
|
|
7117
|
+
/* @__PURE__ */ jsxs2(Box2, { marginTop: 1, children: [
|
|
7118
|
+
/* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", flexGrow: 3, borderStyle: "single", borderColor: "gray", paddingX: 1, children: [
|
|
7119
|
+
/* @__PURE__ */ jsx2(Text2, { color: theme.dim, bold: true, children: "\u2500\u2500 tool stream \u2500\u2500" }),
|
|
7120
|
+
tail.length === 0 ? /* @__PURE__ */ jsx2(Text2, { color: theme.dim, children: "awaiting traffic\u2026" }) : null,
|
|
7121
|
+
tail.map((e) => /* @__PURE__ */ jsxs2(Text2, { wrap: "truncate", children: [
|
|
7122
|
+
/* @__PURE__ */ jsxs2(Text2, { color: theme.dim, children: [
|
|
7123
|
+
"[",
|
|
7124
|
+
hhmmss(e.created_at),
|
|
7125
|
+
"] "
|
|
7126
|
+
] }),
|
|
7127
|
+
/* @__PURE__ */ jsx2(Text2, { color: decisionColor(e.decision), bold: e.decision !== "ALLOW", children: e.decision.padEnd(6) }),
|
|
7128
|
+
/* @__PURE__ */ jsx2(Text2, { color: theme.accent, children: truncate2(e.tool_name, 14).padEnd(15) }),
|
|
7129
|
+
/* @__PURE__ */ jsx2(Text2, { color: theme.dim, children: (e.permission ?? "").slice(0, 4).padEnd(5) }),
|
|
7130
|
+
e.dlp_matches?.length ? /* @__PURE__ */ jsx2(Text2, { color: theme.bad, children: "DLP! " }) : null,
|
|
7131
|
+
/* @__PURE__ */ jsx2(Text2, { color: theme.dim, children: (e.arguments_summary ? JSON.stringify(e.arguments_summary) : e.reason ?? "").replace(/\s+/g, " ") })
|
|
7132
|
+
] }, e.id))
|
|
7060
7133
|
] }),
|
|
7061
|
-
/* @__PURE__ */ jsxs2(Box2, { children: [
|
|
7062
|
-
/* @__PURE__ */ jsx2(Text2, { children: "
|
|
7063
|
-
|
|
7064
|
-
|
|
7134
|
+
wide ? /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", width: 34, borderStyle: "single", borderColor: "gray", paddingX: 1, children: [
|
|
7135
|
+
/* @__PURE__ */ jsx2(Text2, { color: theme.dim, bold: true, children: "\u2500\u2500 raw \u2500\u2500" }),
|
|
7136
|
+
tail.slice(-Math.floor(feedRows / 2)).flatMap((e) => {
|
|
7137
|
+
const raw = e.arguments_summary ? JSON.stringify(e.arguments_summary) : `hash:${e.id.slice(0, 12)}`;
|
|
7138
|
+
return [
|
|
7139
|
+
/* @__PURE__ */ jsxs2(Text2, { wrap: "truncate", color: e.decision === "ALLOW" ? theme.dim : theme.bad, children: [
|
|
7140
|
+
e.id.slice(0, 8),
|
|
7141
|
+
" ",
|
|
7142
|
+
e.tool_name.slice(0, 12)
|
|
7143
|
+
] }, e.id + ":h"),
|
|
7144
|
+
/* @__PURE__ */ jsx2(Text2, { wrap: "truncate", color: theme.dim, children: " " + raw.replace(/\s+/g, " ") }, e.id + ":b")
|
|
7145
|
+
];
|
|
7146
|
+
})
|
|
7147
|
+
] }) : null
|
|
7065
7148
|
] }),
|
|
7066
|
-
/* @__PURE__ */ jsxs2(Box2, {
|
|
7067
|
-
/* @__PURE__ */ jsx2(Text2, { color: theme.
|
|
7068
|
-
|
|
7069
|
-
|
|
7070
|
-
|
|
7071
|
-
|
|
7072
|
-
e.dlp_matches?.length ? /* @__PURE__ */ jsx2(Text2, { color: theme.bad, children: "DLP " }) : /* @__PURE__ */ jsx2(Text2, { children: " " }),
|
|
7073
|
-
/* @__PURE__ */ jsxs2(Text2, { color: theme.dim, children: [
|
|
7074
|
-
ago(e.created_at),
|
|
7075
|
-
" ago"
|
|
7076
|
-
] })
|
|
7077
|
-
] }, e.id))
|
|
7149
|
+
/* @__PURE__ */ jsxs2(Box2, { children: [
|
|
7150
|
+
/* @__PURE__ */ jsx2(Text2, { color: theme.ok, children: "root@solongate" }),
|
|
7151
|
+
/* @__PURE__ */ jsx2(Text2, { color: theme.dim, children: ":" }),
|
|
7152
|
+
/* @__PURE__ */ jsx2(Text2, { color: theme.accentBright, children: "~/live" }),
|
|
7153
|
+
/* @__PURE__ */ jsx2(Text2, { color: theme.dim, children: "$ " }),
|
|
7154
|
+
/* @__PURE__ */ jsx2(Text2, { color: theme.accentBright, children: cursor })
|
|
7078
7155
|
] })
|
|
7079
|
-
] })
|
|
7156
|
+
] });
|
|
7080
7157
|
}
|
|
7158
|
+
var SPIN, hhmmss, fmtUp;
|
|
7081
7159
|
var init_Live = __esm({
|
|
7082
7160
|
"src/tui/panels/Live.tsx"() {
|
|
7083
7161
|
"use strict";
|
|
7084
7162
|
init_api_client();
|
|
7085
|
-
init_components();
|
|
7086
7163
|
init_hooks();
|
|
7087
7164
|
init_theme();
|
|
7165
|
+
SPIN = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
7166
|
+
hhmmss = (ts) => {
|
|
7167
|
+
const d = new Date(ts);
|
|
7168
|
+
return Number.isNaN(d.getTime()) ? "--:--:--" : d.toTimeString().slice(0, 8);
|
|
7169
|
+
};
|
|
7170
|
+
fmtUp = (ms) => {
|
|
7171
|
+
const s = Math.floor(ms / 1e3);
|
|
7172
|
+
const p = (n) => String(n).padStart(2, "0");
|
|
7173
|
+
return `${p(Math.floor(s / 3600))}:${p(Math.floor(s % 3600 / 60))}:${p(s % 60)}`;
|
|
7174
|
+
};
|
|
7088
7175
|
}
|
|
7089
7176
|
});
|
|
7090
7177
|
|
|
7091
7178
|
// src/tui/panels/Policies.tsx
|
|
7092
7179
|
import { Box as Box3, Text as Text3, useInput } from "ink";
|
|
7093
7180
|
import TextInput from "ink-text-input";
|
|
7094
|
-
import { useEffect as
|
|
7181
|
+
import { useEffect as useEffect3, useState as useState3 } from "react";
|
|
7095
7182
|
import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
7096
7183
|
function ruleSummary(r) {
|
|
7097
7184
|
const bits = [];
|
|
@@ -7105,19 +7192,19 @@ function ruleSummary(r) {
|
|
|
7105
7192
|
function PoliciesPanel({ focused }) {
|
|
7106
7193
|
const list4 = useLoader(() => api.policies.list());
|
|
7107
7194
|
const policies = list4.data?.policies ?? [];
|
|
7108
|
-
const [view, setView] =
|
|
7109
|
-
const [pi, setPi] =
|
|
7110
|
-
const [ri, setRi] =
|
|
7111
|
-
const [fi, setFi] =
|
|
7112
|
-
const [rules, setRules] =
|
|
7113
|
-
const [mode, setMode] =
|
|
7114
|
-
const [dirty, setDirty] =
|
|
7115
|
-
const [editing, setEditing] =
|
|
7116
|
-
const [editVal, setEditVal] =
|
|
7117
|
-
const [status, setStatus] =
|
|
7195
|
+
const [view, setView] = useState3("list");
|
|
7196
|
+
const [pi, setPi] = useState3(0);
|
|
7197
|
+
const [ri, setRi] = useState3(0);
|
|
7198
|
+
const [fi, setFi] = useState3(0);
|
|
7199
|
+
const [rules, setRules] = useState3([]);
|
|
7200
|
+
const [mode, setMode] = useState3("denylist");
|
|
7201
|
+
const [dirty, setDirty] = useState3(false);
|
|
7202
|
+
const [editing, setEditing] = useState3(false);
|
|
7203
|
+
const [editVal, setEditVal] = useState3("");
|
|
7204
|
+
const [status, setStatus] = useState3(null);
|
|
7118
7205
|
const selected = policies[Math.min(pi, Math.max(0, policies.length - 1))];
|
|
7119
7206
|
const detail = useLoader(() => selected ? api.policies.get(selected.id) : Promise.resolve(null), [selected?.id]);
|
|
7120
|
-
|
|
7207
|
+
useEffect3(() => {
|
|
7121
7208
|
if (detail.data) {
|
|
7122
7209
|
setRules(detail.data.rules);
|
|
7123
7210
|
setMode(detail.data.mode ?? "denylist");
|
|
@@ -7335,7 +7422,7 @@ var init_Policies = __esm({
|
|
|
7335
7422
|
|
|
7336
7423
|
// src/tui/panels/RateLimit.tsx
|
|
7337
7424
|
import { Box as Box4, Text as Text4, useInput as useInput2 } from "ink";
|
|
7338
|
-
import { useEffect as
|
|
7425
|
+
import { useEffect as useEffect4, useState as useState4 } from "react";
|
|
7339
7426
|
import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
7340
7427
|
function ColoredSpark({ values, limit, width: width2 = 60 }) {
|
|
7341
7428
|
const v = values.length > width2 ? values.slice(values.length - width2) : values;
|
|
@@ -7350,11 +7437,11 @@ function RateLimitPanel({ focused }) {
|
|
|
7350
7437
|
const layersQ = useLoader(() => api.settings.getSecurityLayers());
|
|
7351
7438
|
const historyQ = useLoader(() => api.settings.getRateLimitHistory());
|
|
7352
7439
|
const insightsQ = useLoader(() => api.stats.securityInsights(7));
|
|
7353
|
-
const [draft, setDraft] =
|
|
7354
|
-
const [dirty, setDirty] =
|
|
7355
|
-
const [fi, setFi] =
|
|
7356
|
-
const [status, setStatus] =
|
|
7357
|
-
|
|
7440
|
+
const [draft, setDraft] = useState4(null);
|
|
7441
|
+
const [dirty, setDirty] = useState4(false);
|
|
7442
|
+
const [fi, setFi] = useState4(0);
|
|
7443
|
+
const [status, setStatus] = useState4(null);
|
|
7444
|
+
useEffect4(() => {
|
|
7358
7445
|
if (layersQ.data && !draft) setDraft({ ...layersQ.data.layers.rateLimit });
|
|
7359
7446
|
}, [layersQ.data, draft]);
|
|
7360
7447
|
const adjust = (dir, step) => {
|
|
@@ -7476,19 +7563,19 @@ var init_RateLimit = __esm({
|
|
|
7476
7563
|
// src/tui/panels/Dlp.tsx
|
|
7477
7564
|
import { Box as Box5, Text as Text5, useInput as useInput3 } from "ink";
|
|
7478
7565
|
import TextInput2 from "ink-text-input";
|
|
7479
|
-
import { useEffect as
|
|
7566
|
+
import { useEffect as useEffect5, useState as useState5 } from "react";
|
|
7480
7567
|
import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
7481
7568
|
function DlpPanel({ focused }) {
|
|
7482
7569
|
const q = useLoader(() => api.settings.getSecurityLayers());
|
|
7483
|
-
const [dlp, setDlp] =
|
|
7484
|
-
const [available, setAvailable] =
|
|
7485
|
-
const [sel, setSel] =
|
|
7486
|
-
const [dirty, setDirty] =
|
|
7487
|
-
const [status, setStatus] =
|
|
7488
|
-
const [adding, setAdding] =
|
|
7489
|
-
const [newName, setNewName] =
|
|
7490
|
-
const [newRe, setNewRe] =
|
|
7491
|
-
|
|
7570
|
+
const [dlp, setDlp] = useState5(null);
|
|
7571
|
+
const [available, setAvailable] = useState5([]);
|
|
7572
|
+
const [sel, setSel] = useState5(0);
|
|
7573
|
+
const [dirty, setDirty] = useState5(false);
|
|
7574
|
+
const [status, setStatus] = useState5(null);
|
|
7575
|
+
const [adding, setAdding] = useState5(null);
|
|
7576
|
+
const [newName, setNewName] = useState5("");
|
|
7577
|
+
const [newRe, setNewRe] = useState5("");
|
|
7578
|
+
useEffect5(() => {
|
|
7492
7579
|
if (q.data && !dlp) {
|
|
7493
7580
|
setDlp({ ...q.data.layers.dlp, patterns: [...q.data.layers.dlp.patterns], custom: [...q.data.layers.dlp.custom] });
|
|
7494
7581
|
setAvailable(q.data.availablePatterns);
|
|
@@ -7702,17 +7789,17 @@ var init_Stats = __esm({
|
|
|
7702
7789
|
// src/tui/panels/Audit.tsx
|
|
7703
7790
|
import { Box as Box7, Text as Text7, useInput as useInput4 } from "ink";
|
|
7704
7791
|
import TextInput3 from "ink-text-input";
|
|
7705
|
-
import { useState as
|
|
7792
|
+
import { useState as useState6 } from "react";
|
|
7706
7793
|
import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
7707
7794
|
function AuditPanel({ active: active2, focused }) {
|
|
7708
|
-
const [di, setDi] =
|
|
7709
|
-
const [gi, setGi] =
|
|
7710
|
-
const [tool, setTool] =
|
|
7711
|
-
const [agent, setAgent] =
|
|
7712
|
-
const [search, setSearch] =
|
|
7713
|
-
const [sel, setSel] =
|
|
7714
|
-
const [view, setView] =
|
|
7715
|
-
const [editing, setEditing] =
|
|
7795
|
+
const [di, setDi] = useState6(0);
|
|
7796
|
+
const [gi, setGi] = useState6(0);
|
|
7797
|
+
const [tool, setTool] = useState6("");
|
|
7798
|
+
const [agent, setAgent] = useState6("");
|
|
7799
|
+
const [search, setSearch] = useState6("");
|
|
7800
|
+
const [sel, setSel] = useState6(0);
|
|
7801
|
+
const [view, setView] = useState6("list");
|
|
7802
|
+
const [editing, setEditing] = useState6(null);
|
|
7716
7803
|
const query = {
|
|
7717
7804
|
filter: DECISIONS[di],
|
|
7718
7805
|
signal: SIGNALS[gi],
|
|
@@ -7880,7 +7967,7 @@ var init_Audit = __esm({
|
|
|
7880
7967
|
|
|
7881
7968
|
// src/tui/App.tsx
|
|
7882
7969
|
import { Box as Box8, Text as Text8, useApp, useInput as useInput5 } from "ink";
|
|
7883
|
-
import { useState as
|
|
7970
|
+
import { useState as useState7 } from "react";
|
|
7884
7971
|
import { jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
7885
7972
|
function Banner() {
|
|
7886
7973
|
const wide = (process.stdout.columns ?? 80) >= 82;
|
|
@@ -7897,8 +7984,8 @@ function Banner() {
|
|
|
7897
7984
|
}
|
|
7898
7985
|
function App() {
|
|
7899
7986
|
const { exit } = useApp();
|
|
7900
|
-
const [section, setSection] =
|
|
7901
|
-
const [focus, setFocus] =
|
|
7987
|
+
const [section, setSection] = useState7(0);
|
|
7988
|
+
const [focus, setFocus] = useState7("nav");
|
|
7902
7989
|
useInput5((input, key) => {
|
|
7903
7990
|
if (focus === "nav") {
|
|
7904
7991
|
if (key.upArrow) setSection((n) => (n - 1 + SECTIONS.length) % SECTIONS.length);
|
package/dist/tui/index.js
CHANGED
|
@@ -9,7 +9,7 @@ import { render } from "ink";
|
|
|
9
9
|
|
|
10
10
|
// src/tui/App.tsx
|
|
11
11
|
import { Box as Box8, Text as Text8, useApp, useInput as useInput5 } from "ink";
|
|
12
|
-
import { useState as
|
|
12
|
+
import { useState as useState7 } from "react";
|
|
13
13
|
|
|
14
14
|
// src/cli-utils.ts
|
|
15
15
|
var c = {
|
|
@@ -126,6 +126,7 @@ function KeyHints({ hints }) {
|
|
|
126
126
|
|
|
127
127
|
// src/tui/panels/Live.tsx
|
|
128
128
|
import { Box as Box2, Text as Text2 } from "ink";
|
|
129
|
+
import { useEffect as useEffect2, useRef as useRef2, useState as useState2 } from "react";
|
|
129
130
|
|
|
130
131
|
// src/api-client/client.ts
|
|
131
132
|
import { readFileSync, existsSync } from "fs";
|
|
@@ -430,68 +431,154 @@ function usePoll(reload, intervalMs, enabled = true) {
|
|
|
430
431
|
|
|
431
432
|
// src/tui/panels/Live.tsx
|
|
432
433
|
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
434
|
+
var SPIN = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
435
|
+
var hhmmss = (ts) => {
|
|
436
|
+
const d = new Date(ts);
|
|
437
|
+
return Number.isNaN(d.getTime()) ? "--:--:--" : d.toTimeString().slice(0, 8);
|
|
438
|
+
};
|
|
439
|
+
var fmtUp = (ms) => {
|
|
440
|
+
const s = Math.floor(ms / 1e3);
|
|
441
|
+
const p = (n) => String(n).padStart(2, "0");
|
|
442
|
+
return `${p(Math.floor(s / 3600))}:${p(Math.floor(s % 3600 / 60))}:${p(s % 60)}`;
|
|
443
|
+
};
|
|
439
444
|
function LivePanel({ active: active2 }) {
|
|
440
445
|
const stats = useLoader(() => api.stats.get());
|
|
441
446
|
const ts = useLoader(() => api.stats.timeseries({ period: "24h" }));
|
|
442
|
-
const feed = useLoader(() => api.audit.list({ limit:
|
|
447
|
+
const feed = useLoader(() => api.audit.list({ limit: 40 }));
|
|
443
448
|
usePoll(() => {
|
|
444
449
|
stats.reload();
|
|
445
450
|
ts.reload();
|
|
446
451
|
feed.reload();
|
|
447
452
|
}, 2e3, active2);
|
|
453
|
+
const [tick, setTick] = useState2(0);
|
|
454
|
+
useEffect2(() => {
|
|
455
|
+
if (!active2) return;
|
|
456
|
+
const t = setInterval(() => setTick((n) => n + 1), 200);
|
|
457
|
+
return () => clearInterval(t);
|
|
458
|
+
}, [active2]);
|
|
459
|
+
const startRef = useRef2(Date.now());
|
|
460
|
+
const [buffer, setBuffer] = useState2([]);
|
|
461
|
+
useEffect2(() => {
|
|
462
|
+
const incoming = feed.data?.entries;
|
|
463
|
+
if (!incoming?.length) return;
|
|
464
|
+
setBuffer((prev) => {
|
|
465
|
+
const seen = new Set(prev.map((e) => e.id));
|
|
466
|
+
const fresh = incoming.filter((e) => !seen.has(e.id)).sort((a, b) => Date.parse(a.created_at) - Date.parse(b.created_at));
|
|
467
|
+
return fresh.length ? [...prev, ...fresh].slice(-300) : prev;
|
|
468
|
+
});
|
|
469
|
+
}, [feed.data]);
|
|
448
470
|
const s = stats.data;
|
|
449
471
|
const points = ts.data?.timeseries ?? [];
|
|
450
|
-
const
|
|
451
|
-
const
|
|
452
|
-
|
|
472
|
+
const cols = process.stdout.columns ?? 100;
|
|
473
|
+
const rows = process.stdout.rows ?? 32;
|
|
474
|
+
const feedRows = Math.max(8, Math.min(20, rows - 18));
|
|
475
|
+
const wide = cols >= 112;
|
|
476
|
+
const tail = buffer.slice(-feedRows);
|
|
477
|
+
const denies = buffer.filter((e) => e.decision !== "ALLOW");
|
|
478
|
+
const dlpHits = buffer.filter((e) => e.dlp_matches?.length);
|
|
479
|
+
const lastDeny = denies[denies.length - 1];
|
|
480
|
+
const spin = SPIN[tick % SPIN.length];
|
|
481
|
+
const cursor = tick % 4 < 2 ? "\u258C" : " ";
|
|
482
|
+
if (stats.error) return /* @__PURE__ */ jsxs2(Text2, { color: theme.bad, children: [
|
|
483
|
+
"\u2717 ",
|
|
484
|
+
stats.error
|
|
485
|
+
] });
|
|
486
|
+
return /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", children: [
|
|
453
487
|
/* @__PURE__ */ jsxs2(Box2, { children: [
|
|
454
|
-
/* @__PURE__ */ jsx2(Text2, { color: theme.bad, children: "\u25CF" }),
|
|
455
|
-
/* @__PURE__ */ jsx2(Text2, { color: theme.
|
|
488
|
+
/* @__PURE__ */ jsx2(Text2, { color: theme.bad, children: "\u25CF " }),
|
|
489
|
+
/* @__PURE__ */ jsx2(Text2, { bold: true, color: theme.accentBright, children: "LIVE" }),
|
|
490
|
+
/* @__PURE__ */ jsxs2(Text2, { color: theme.dim, children: [
|
|
491
|
+
" ",
|
|
492
|
+
spin,
|
|
493
|
+
" scanning"
|
|
494
|
+
] }),
|
|
495
|
+
/* @__PURE__ */ jsxs2(Text2, { color: theme.dim, children: [
|
|
496
|
+
" up ",
|
|
497
|
+
fmtUp(Date.now() - startRef.current)
|
|
498
|
+
] }),
|
|
499
|
+
/* @__PURE__ */ jsxs2(Text2, { color: theme.dim, children: [
|
|
500
|
+
" ",
|
|
501
|
+
hhmmss(Date.now())
|
|
502
|
+
] }),
|
|
503
|
+
/* @__PURE__ */ jsx2(Text2, { color: theme.dim, children: " poll 2s" })
|
|
456
504
|
] }),
|
|
457
|
-
|
|
458
|
-
/* @__PURE__ */ jsx2(
|
|
459
|
-
/* @__PURE__ */ jsx2(
|
|
460
|
-
/* @__PURE__ */ jsx2(
|
|
461
|
-
/* @__PURE__ */ jsx2(
|
|
462
|
-
/* @__PURE__ */ jsx2(
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
/* @__PURE__ */ jsx2(Text2, { color: theme.dim, children:
|
|
466
|
-
/* @__PURE__ */
|
|
467
|
-
|
|
468
|
-
|
|
505
|
+
/* @__PURE__ */ jsxs2(Box2, { children: [
|
|
506
|
+
/* @__PURE__ */ jsx2(Text2, { color: theme.dim, children: "calls " }),
|
|
507
|
+
/* @__PURE__ */ jsx2(Text2, { bold: true, children: s ? s.total_calls : "\xB7\xB7\xB7\xB7" }),
|
|
508
|
+
/* @__PURE__ */ jsx2(Text2, { color: theme.dim, children: " allow " }),
|
|
509
|
+
/* @__PURE__ */ jsx2(Text2, { color: theme.ok, children: s ? s.allowed : "\xB7\xB7\xB7" }),
|
|
510
|
+
/* @__PURE__ */ jsx2(Text2, { color: theme.dim, children: " deny " }),
|
|
511
|
+
/* @__PURE__ */ jsx2(Text2, { color: theme.bad, bold: true, children: s ? s.denied : "\xB7\xB7" }),
|
|
512
|
+
/* @__PURE__ */ jsx2(Text2, { color: theme.dim, children: " dlp(buf) " }),
|
|
513
|
+
/* @__PURE__ */ jsx2(Text2, { color: dlpHits.length ? theme.bad : theme.dim, children: dlpHits.length }),
|
|
514
|
+
/* @__PURE__ */ jsx2(Text2, { color: theme.dim, children: " policies " }),
|
|
515
|
+
/* @__PURE__ */ jsx2(Text2, { color: theme.accent, children: s ? s.active_policies : "\xB7" })
|
|
516
|
+
] }),
|
|
517
|
+
/* @__PURE__ */ jsxs2(Box2, { children: [
|
|
518
|
+
/* @__PURE__ */ jsx2(Text2, { color: theme.dim, children: "act " }),
|
|
519
|
+
/* @__PURE__ */ jsx2(Text2, { color: theme.accent, children: sparkline(points.map((p) => p.total), Math.min(64, cols - 30)) })
|
|
520
|
+
] }),
|
|
521
|
+
/* @__PURE__ */ jsxs2(Box2, { children: [
|
|
522
|
+
/* @__PURE__ */ jsx2(Text2, { color: theme.dim, children: "dny " }),
|
|
523
|
+
/* @__PURE__ */ jsx2(Text2, { color: theme.bad, children: sparkline(points.map((p) => p.denied), Math.min(64, cols - 30)) })
|
|
524
|
+
] }),
|
|
525
|
+
/* @__PURE__ */ jsxs2(Box2, { children: [
|
|
526
|
+
/* @__PURE__ */ jsx2(Text2, { color: theme.dim, children: ">> " }),
|
|
527
|
+
lastDeny ? /* @__PURE__ */ jsxs2(Text2, { color: theme.bad, children: [
|
|
528
|
+
"last deny ",
|
|
529
|
+
hhmmss(lastDeny.created_at),
|
|
530
|
+
" ",
|
|
531
|
+
lastDeny.tool_name,
|
|
532
|
+
" \xB7 ",
|
|
533
|
+
truncate(lastDeny.reason ?? "policy", Math.max(20, cols - 50))
|
|
534
|
+
] }) : /* @__PURE__ */ jsx2(Text2, { color: theme.dim, children: "no denials in buffer" })
|
|
535
|
+
] }),
|
|
536
|
+
/* @__PURE__ */ jsxs2(Box2, { marginTop: 1, children: [
|
|
537
|
+
/* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", flexGrow: 3, borderStyle: "single", borderColor: "gray", paddingX: 1, children: [
|
|
538
|
+
/* @__PURE__ */ jsx2(Text2, { color: theme.dim, bold: true, children: "\u2500\u2500 tool stream \u2500\u2500" }),
|
|
539
|
+
tail.length === 0 ? /* @__PURE__ */ jsx2(Text2, { color: theme.dim, children: "awaiting traffic\u2026" }) : null,
|
|
540
|
+
tail.map((e) => /* @__PURE__ */ jsxs2(Text2, { wrap: "truncate", children: [
|
|
541
|
+
/* @__PURE__ */ jsxs2(Text2, { color: theme.dim, children: [
|
|
542
|
+
"[",
|
|
543
|
+
hhmmss(e.created_at),
|
|
544
|
+
"] "
|
|
545
|
+
] }),
|
|
546
|
+
/* @__PURE__ */ jsx2(Text2, { color: decisionColor(e.decision), bold: e.decision !== "ALLOW", children: e.decision.padEnd(6) }),
|
|
547
|
+
/* @__PURE__ */ jsx2(Text2, { color: theme.accent, children: truncate(e.tool_name, 14).padEnd(15) }),
|
|
548
|
+
/* @__PURE__ */ jsx2(Text2, { color: theme.dim, children: (e.permission ?? "").slice(0, 4).padEnd(5) }),
|
|
549
|
+
e.dlp_matches?.length ? /* @__PURE__ */ jsx2(Text2, { color: theme.bad, children: "DLP! " }) : null,
|
|
550
|
+
/* @__PURE__ */ jsx2(Text2, { color: theme.dim, children: (e.arguments_summary ? JSON.stringify(e.arguments_summary) : e.reason ?? "").replace(/\s+/g, " ") })
|
|
551
|
+
] }, e.id))
|
|
469
552
|
] }),
|
|
470
|
-
/* @__PURE__ */ jsxs2(Box2, { children: [
|
|
471
|
-
/* @__PURE__ */ jsx2(Text2, { children: "
|
|
472
|
-
|
|
473
|
-
|
|
553
|
+
wide ? /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", width: 34, borderStyle: "single", borderColor: "gray", paddingX: 1, children: [
|
|
554
|
+
/* @__PURE__ */ jsx2(Text2, { color: theme.dim, bold: true, children: "\u2500\u2500 raw \u2500\u2500" }),
|
|
555
|
+
tail.slice(-Math.floor(feedRows / 2)).flatMap((e) => {
|
|
556
|
+
const raw = e.arguments_summary ? JSON.stringify(e.arguments_summary) : `hash:${e.id.slice(0, 12)}`;
|
|
557
|
+
return [
|
|
558
|
+
/* @__PURE__ */ jsxs2(Text2, { wrap: "truncate", color: e.decision === "ALLOW" ? theme.dim : theme.bad, children: [
|
|
559
|
+
e.id.slice(0, 8),
|
|
560
|
+
" ",
|
|
561
|
+
e.tool_name.slice(0, 12)
|
|
562
|
+
] }, e.id + ":h"),
|
|
563
|
+
/* @__PURE__ */ jsx2(Text2, { wrap: "truncate", color: theme.dim, children: " " + raw.replace(/\s+/g, " ") }, e.id + ":b")
|
|
564
|
+
];
|
|
565
|
+
})
|
|
566
|
+
] }) : null
|
|
474
567
|
] }),
|
|
475
|
-
/* @__PURE__ */ jsxs2(Box2, {
|
|
476
|
-
/* @__PURE__ */ jsx2(Text2, { color: theme.
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
e.dlp_matches?.length ? /* @__PURE__ */ jsx2(Text2, { color: theme.bad, children: "DLP " }) : /* @__PURE__ */ jsx2(Text2, { children: " " }),
|
|
482
|
-
/* @__PURE__ */ jsxs2(Text2, { color: theme.dim, children: [
|
|
483
|
-
ago(e.created_at),
|
|
484
|
-
" ago"
|
|
485
|
-
] })
|
|
486
|
-
] }, e.id))
|
|
568
|
+
/* @__PURE__ */ jsxs2(Box2, { children: [
|
|
569
|
+
/* @__PURE__ */ jsx2(Text2, { color: theme.ok, children: "root@solongate" }),
|
|
570
|
+
/* @__PURE__ */ jsx2(Text2, { color: theme.dim, children: ":" }),
|
|
571
|
+
/* @__PURE__ */ jsx2(Text2, { color: theme.accentBright, children: "~/live" }),
|
|
572
|
+
/* @__PURE__ */ jsx2(Text2, { color: theme.dim, children: "$ " }),
|
|
573
|
+
/* @__PURE__ */ jsx2(Text2, { color: theme.accentBright, children: cursor })
|
|
487
574
|
] })
|
|
488
|
-
] })
|
|
575
|
+
] });
|
|
489
576
|
}
|
|
490
577
|
|
|
491
578
|
// src/tui/panels/Policies.tsx
|
|
492
579
|
import { Box as Box3, Text as Text3, useInput } from "ink";
|
|
493
580
|
import TextInput from "ink-text-input";
|
|
494
|
-
import { useEffect as
|
|
581
|
+
import { useEffect as useEffect3, useState as useState3 } from "react";
|
|
495
582
|
import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
496
583
|
var constr = (r, g, side) => (r[g]?.[side] ?? []).join(", ");
|
|
497
584
|
var setConstr = (r, g, side, val) => {
|
|
@@ -526,19 +613,19 @@ function ruleSummary(r) {
|
|
|
526
613
|
function PoliciesPanel({ focused }) {
|
|
527
614
|
const list3 = useLoader(() => api.policies.list());
|
|
528
615
|
const policies = list3.data?.policies ?? [];
|
|
529
|
-
const [view, setView] =
|
|
530
|
-
const [pi, setPi] =
|
|
531
|
-
const [ri, setRi] =
|
|
532
|
-
const [fi, setFi] =
|
|
533
|
-
const [rules, setRules] =
|
|
534
|
-
const [mode, setMode] =
|
|
535
|
-
const [dirty, setDirty] =
|
|
536
|
-
const [editing, setEditing] =
|
|
537
|
-
const [editVal, setEditVal] =
|
|
538
|
-
const [status, setStatus] =
|
|
616
|
+
const [view, setView] = useState3("list");
|
|
617
|
+
const [pi, setPi] = useState3(0);
|
|
618
|
+
const [ri, setRi] = useState3(0);
|
|
619
|
+
const [fi, setFi] = useState3(0);
|
|
620
|
+
const [rules, setRules] = useState3([]);
|
|
621
|
+
const [mode, setMode] = useState3("denylist");
|
|
622
|
+
const [dirty, setDirty] = useState3(false);
|
|
623
|
+
const [editing, setEditing] = useState3(false);
|
|
624
|
+
const [editVal, setEditVal] = useState3("");
|
|
625
|
+
const [status, setStatus] = useState3(null);
|
|
539
626
|
const selected = policies[Math.min(pi, Math.max(0, policies.length - 1))];
|
|
540
627
|
const detail = useLoader(() => selected ? api.policies.get(selected.id) : Promise.resolve(null), [selected?.id]);
|
|
541
|
-
|
|
628
|
+
useEffect3(() => {
|
|
542
629
|
if (detail.data) {
|
|
543
630
|
setRules(detail.data.rules);
|
|
544
631
|
setMode(detail.data.mode ?? "denylist");
|
|
@@ -725,7 +812,7 @@ function PoliciesPanel({ focused }) {
|
|
|
725
812
|
|
|
726
813
|
// src/tui/panels/RateLimit.tsx
|
|
727
814
|
import { Box as Box4, Text as Text4, useInput as useInput2 } from "ink";
|
|
728
|
-
import { useEffect as
|
|
815
|
+
import { useEffect as useEffect4, useState as useState4 } from "react";
|
|
729
816
|
import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
730
817
|
var MODES = ["off", "detect", "block"];
|
|
731
818
|
var FIELDS2 = ["mode", "perMinute", "perHour", "perDay"];
|
|
@@ -743,11 +830,11 @@ function RateLimitPanel({ focused }) {
|
|
|
743
830
|
const layersQ = useLoader(() => api.settings.getSecurityLayers());
|
|
744
831
|
const historyQ = useLoader(() => api.settings.getRateLimitHistory());
|
|
745
832
|
const insightsQ = useLoader(() => api.stats.securityInsights(7));
|
|
746
|
-
const [draft, setDraft] =
|
|
747
|
-
const [dirty, setDirty] =
|
|
748
|
-
const [fi, setFi] =
|
|
749
|
-
const [status, setStatus] =
|
|
750
|
-
|
|
833
|
+
const [draft, setDraft] = useState4(null);
|
|
834
|
+
const [dirty, setDirty] = useState4(false);
|
|
835
|
+
const [fi, setFi] = useState4(0);
|
|
836
|
+
const [status, setStatus] = useState4(null);
|
|
837
|
+
useEffect4(() => {
|
|
751
838
|
if (layersQ.data && !draft) setDraft({ ...layersQ.data.layers.rateLimit });
|
|
752
839
|
}, [layersQ.data, draft]);
|
|
753
840
|
const adjust = (dir, step) => {
|
|
@@ -856,20 +943,20 @@ function FieldRow({ label, active: active2, children }) {
|
|
|
856
943
|
// src/tui/panels/Dlp.tsx
|
|
857
944
|
import { Box as Box5, Text as Text5, useInput as useInput3 } from "ink";
|
|
858
945
|
import TextInput2 from "ink-text-input";
|
|
859
|
-
import { useEffect as
|
|
946
|
+
import { useEffect as useEffect5, useState as useState5 } from "react";
|
|
860
947
|
import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
861
948
|
var MODES2 = ["off", "detect", "block"];
|
|
862
949
|
function DlpPanel({ focused }) {
|
|
863
950
|
const q = useLoader(() => api.settings.getSecurityLayers());
|
|
864
|
-
const [dlp, setDlp] =
|
|
865
|
-
const [available, setAvailable] =
|
|
866
|
-
const [sel, setSel] =
|
|
867
|
-
const [dirty, setDirty] =
|
|
868
|
-
const [status, setStatus] =
|
|
869
|
-
const [adding, setAdding] =
|
|
870
|
-
const [newName, setNewName] =
|
|
871
|
-
const [newRe, setNewRe] =
|
|
872
|
-
|
|
951
|
+
const [dlp, setDlp] = useState5(null);
|
|
952
|
+
const [available, setAvailable] = useState5([]);
|
|
953
|
+
const [sel, setSel] = useState5(0);
|
|
954
|
+
const [dirty, setDirty] = useState5(false);
|
|
955
|
+
const [status, setStatus] = useState5(null);
|
|
956
|
+
const [adding, setAdding] = useState5(null);
|
|
957
|
+
const [newName, setNewName] = useState5("");
|
|
958
|
+
const [newRe, setNewRe] = useState5("");
|
|
959
|
+
useEffect5(() => {
|
|
873
960
|
if (q.data && !dlp) {
|
|
874
961
|
setDlp({ ...q.data.layers.dlp, patterns: [...q.data.layers.dlp.patterns], custom: [...q.data.layers.dlp.custom] });
|
|
875
962
|
setAvailable(q.data.availablePatterns);
|
|
@@ -1063,19 +1150,19 @@ function StatsPanel({ active: active2 }) {
|
|
|
1063
1150
|
// src/tui/panels/Audit.tsx
|
|
1064
1151
|
import { Box as Box7, Text as Text7, useInput as useInput4 } from "ink";
|
|
1065
1152
|
import TextInput3 from "ink-text-input";
|
|
1066
|
-
import { useState as
|
|
1153
|
+
import { useState as useState6 } from "react";
|
|
1067
1154
|
import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
1068
1155
|
var DECISIONS = [void 0, "DENY", "ALLOW"];
|
|
1069
1156
|
var SIGNALS = [void 0, "dlp", "ratelimit"];
|
|
1070
1157
|
function AuditPanel({ active: active2, focused }) {
|
|
1071
|
-
const [di, setDi] =
|
|
1072
|
-
const [gi, setGi] =
|
|
1073
|
-
const [tool, setTool] =
|
|
1074
|
-
const [agent, setAgent] =
|
|
1075
|
-
const [search, setSearch] =
|
|
1076
|
-
const [sel, setSel] =
|
|
1077
|
-
const [view, setView] =
|
|
1078
|
-
const [editing, setEditing] =
|
|
1158
|
+
const [di, setDi] = useState6(0);
|
|
1159
|
+
const [gi, setGi] = useState6(0);
|
|
1160
|
+
const [tool, setTool] = useState6("");
|
|
1161
|
+
const [agent, setAgent] = useState6("");
|
|
1162
|
+
const [search, setSearch] = useState6("");
|
|
1163
|
+
const [sel, setSel] = useState6(0);
|
|
1164
|
+
const [view, setView] = useState6("list");
|
|
1165
|
+
const [editing, setEditing] = useState6(null);
|
|
1079
1166
|
const query = {
|
|
1080
1167
|
filter: DECISIONS[di],
|
|
1081
1168
|
signal: SIGNALS[gi],
|
|
@@ -1255,8 +1342,8 @@ function Banner() {
|
|
|
1255
1342
|
}
|
|
1256
1343
|
function App() {
|
|
1257
1344
|
const { exit } = useApp();
|
|
1258
|
-
const [section, setSection] =
|
|
1259
|
-
const [focus, setFocus] =
|
|
1345
|
+
const [section, setSection] = useState7(0);
|
|
1346
|
+
const [focus, setFocus] = useState7("nav");
|
|
1260
1347
|
useInput5((input, key) => {
|
|
1261
1348
|
if (focus === "nav") {
|
|
1262
1349
|
if (key.upArrow) setSection((n) => (n - 1 + SECTIONS.length) % SECTIONS.length);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@solongate/proxy",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.63.0",
|
|
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": {
|