@solongate/proxy 0.81.52 → 0.81.54

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.
@@ -82,6 +82,9 @@ export declare function createWebhook(body: {
82
82
  export declare function deleteWebhook(id: string): Promise<{
83
83
  ok: true;
84
84
  }>;
85
+ export declare function sendTestWebhook(id: string): Promise<{
86
+ delivered: boolean;
87
+ }>;
85
88
  export declare function updateWebhook(id: string, patch: {
86
89
  enabled?: boolean;
87
90
  events?: DenialWebhook['events'];
@@ -221,6 +221,7 @@ __export(settings_exports, {
221
221
  getSecurityLayers: () => getSecurityLayers,
222
222
  getSelfProtection: () => getSelfProtection,
223
223
  getWebhooks: () => getWebhooks,
224
+ sendTestWebhook: () => sendTestWebhook,
224
225
  setAlertEnabled: () => setAlertEnabled,
225
226
  setLocalLogs: () => setLocalLogs,
226
227
  setSecurityLayers: () => setSecurityLayers,
@@ -275,6 +276,9 @@ function createWebhook(body) {
275
276
  function deleteWebhook(id) {
276
277
  return request("DELETE", "/settings/denial-webhook", { query: { id } });
277
278
  }
279
+ function sendTestWebhook(id) {
280
+ return request("POST", "/settings/denial-webhook/send-test", { body: { id } });
281
+ }
278
282
  function updateWebhook(id, patch) {
279
283
  return request("PATCH", "/settings/denial-webhook", { body: { id, ...patch } });
280
284
  }
package/dist/index.js CHANGED
@@ -7394,6 +7394,7 @@ __export(settings_exports, {
7394
7394
  getSecurityLayers: () => getSecurityLayers,
7395
7395
  getSelfProtection: () => getSelfProtection,
7396
7396
  getWebhooks: () => getWebhooks,
7397
+ sendTestWebhook: () => sendTestWebhook,
7397
7398
  setAlertEnabled: () => setAlertEnabled,
7398
7399
  setLocalLogs: () => setLocalLogs,
7399
7400
  setSecurityLayers: () => setSecurityLayers,
@@ -7448,6 +7449,9 @@ function createWebhook(body) {
7448
7449
  function deleteWebhook(id) {
7449
7450
  return request("DELETE", "/settings/denial-webhook", { query: { id } });
7450
7451
  }
7452
+ function sendTestWebhook(id) {
7453
+ return request("POST", "/settings/denial-webhook/send-test", { body: { id } });
7454
+ }
7451
7455
  function updateWebhook(id, patch) {
7452
7456
  return request("PATCH", "/settings/denial-webhook", { body: { id, ...patch } });
7453
7457
  }
@@ -10058,13 +10062,6 @@ import { Box as Box7, Text as Text7, useInput as useInput6 } from "ink";
10058
10062
  import TextInput5 from "ink-text-input";
10059
10063
  import { useEffect as useEffect6, useRef as useRef3, useState as useState7 } from "react";
10060
10064
  import { Fragment as Fragment5, jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
10061
- function alertBodyFor(channel) {
10062
- const c2 = channel.trim();
10063
- const base = { name: "dataroom alert", threshold: 5, windowSeconds: 60, signal: "any" };
10064
- if (/^https?:\/\//i.test(c2)) return { ...base, slackUrl: c2 };
10065
- if (c2.includes("@")) return { ...base, emails: [c2] };
10066
- return { ...base, telegram: [c2] };
10067
- }
10068
10065
  function SettingsPanel({
10069
10066
  active: active2,
10070
10067
  focused,
@@ -10099,8 +10096,9 @@ function SettingsPanel({
10099
10096
  const whQ = useLoader(() => listAccounts().length ? api.settings.getWebhooks() : Promise.resolve(null));
10100
10097
  const alertQ = useLoader(() => listAccounts().length ? api.settings.getAlerts() : Promise.resolve(null));
10101
10098
  const local = localQ.data;
10102
- const webhooks = whQ.data?.webhooks ?? [];
10103
- const alerts = alertQ.data?.rules ?? [];
10099
+ const [hidden, setHidden] = useState7(/* @__PURE__ */ new Set());
10100
+ const webhooks = (whQ.data?.webhooks ?? []).filter((w) => !hidden.has("wh:" + w.id));
10101
+ const alerts = (alertQ.data?.rules ?? []).filter((r) => !hidden.has("alert:" + r.id));
10104
10102
  const rowsAll = [
10105
10103
  ...accounts.map((acc) => ({ kind: "acct", acc })),
10106
10104
  { kind: "acct-add" },
@@ -10111,7 +10109,8 @@ function SettingsPanel({
10111
10109
  ...webhooks.map((wh) => ({ kind: "wh", wh })),
10112
10110
  { kind: "wh-add" },
10113
10111
  ...alerts.map((rule) => ({ kind: "alert", rule })),
10114
- { kind: "alert-add" }
10112
+ { kind: "alert-add-email" },
10113
+ { kind: "alert-add-tg" }
10115
10114
  ]
10116
10115
  ];
10117
10116
  const selClamped = Math.min(sel, rowsAll.length - 1);
@@ -10196,9 +10195,12 @@ function SettingsPanel({
10196
10195
  setEditing("wh-url");
10197
10196
  } else if (r.kind === "alert") {
10198
10197
  run12(r.rule.enabled ? "alert disabled" : "alert enabled", () => api.settings.setAlertEnabled(r.rule.id, !r.rule.enabled), alertQ.reload);
10198
+ } else if (r.kind === "alert-add-email") {
10199
+ setInput("");
10200
+ setEditing("alert-email");
10199
10201
  } else {
10200
10202
  setInput("");
10201
- setEditing("alert-channel");
10203
+ setEditing("alert-tg");
10202
10204
  }
10203
10205
  };
10204
10206
  const submitInput = () => {
@@ -10211,9 +10213,20 @@ function SettingsPanel({
10211
10213
  } else if (which === "wh-url") {
10212
10214
  if (!v) return;
10213
10215
  run12("webhook added", () => api.settings.createWebhook({ url: v, events: "denials" }), whQ.reload);
10214
- } else if (which === "alert-channel") {
10216
+ } else if (which === "alert-email") {
10217
+ if (!v) return;
10218
+ if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(v)) {
10219
+ setMsg({ text: "\u2717 that does not look like an e-mail address", level: "bad" });
10220
+ return;
10221
+ }
10222
+ run12("email alert added", () => api.settings.createAlert({ ...ALERT_BASE, emails: [v] }), alertQ.reload);
10223
+ } else if (which === "alert-tg") {
10215
10224
  if (!v) return;
10216
- run12("alert rule added", () => api.settings.createAlert(alertBodyFor(v)), alertQ.reload);
10225
+ if (!/^-?\d{5,}$/.test(v)) {
10226
+ setMsg({ text: "\u2717 a telegram chat id is a number \u2014 get yours from @userinfobot", level: "bad" });
10227
+ return;
10228
+ }
10229
+ run12("telegram alert added", () => api.settings.createAlert({ ...ALERT_BASE, telegram: [v] }), alertQ.reload);
10217
10230
  }
10218
10231
  };
10219
10232
  useInput6(
@@ -10233,10 +10246,20 @@ function SettingsPanel({
10233
10246
  setSel((n) => Math.min(rowsAll.length - 1, n + 1));
10234
10247
  setConfirmDel(null);
10235
10248
  } else if (key.return || inp === " ") activate(cur);
10236
- else if (inp === "m" && cur.kind === "acct") {
10237
- const ok = setActiveAccount({ apiKey: cur.acc.apiKey, apiUrl: cur.acc.apiUrl });
10238
- setMsg(ok ? { text: `\u2713 ${acctLabel(cur.acc)} is now the ACTIVE key (guard + logging)`, level: "ok" } : { text: "\u2717 could not set active", level: "bad" });
10239
- refreshAccounts();
10249
+ else if (inp === "m") {
10250
+ if (cur.kind === "acct") {
10251
+ const ok = setActiveAccount({ apiKey: cur.acc.apiKey, apiUrl: cur.acc.apiUrl });
10252
+ setMsg(ok ? { text: `\u2713 ${acctLabel(cur.acc)} is now the ACTIVE key (guard + logging)`, level: "ok" } : { text: "\u2717 could not set active", level: "bad" });
10253
+ refreshAccounts();
10254
+ } else if (cur.kind === "wh" || cur.kind === "alert" || cur.kind === "ll-enabled" || cur.kind === "ll-server") activate(cur);
10255
+ } else if (inp === "t" && cur.kind === "wh") {
10256
+ run12(
10257
+ "test event sent \u2014 check your endpoint",
10258
+ () => api.settings.sendTestWebhook(cur.wh.id).then((r) => {
10259
+ if (!r.delivered) throw new Error("endpoint rejected the test (non-2xx response)");
10260
+ }),
10261
+ whQ.reload
10262
+ );
10240
10263
  } else if (inp === "n") beginLogin();
10241
10264
  else if (inp === "e" && cur.kind === "wh") {
10242
10265
  const next = EVENTS[(EVENTS.indexOf(cur.wh.events) + 1) % EVENTS.length];
@@ -10246,9 +10269,9 @@ function SettingsPanel({
10246
10269
  if (cur.kind === "wh" || cur.kind === "wh-add") {
10247
10270
  setInput("");
10248
10271
  setEditing("wh-url");
10249
- } else if (cur.kind === "alert" || cur.kind === "alert-add") {
10272
+ } else if (cur.kind === "alert" || cur.kind === "alert-add-email" || cur.kind === "alert-add-tg") {
10250
10273
  setInput("");
10251
- setEditing("alert-channel");
10274
+ setEditing("alert-email");
10252
10275
  }
10253
10276
  } else if (inp === "d" && (cur.kind === "wh" || cur.kind === "alert")) {
10254
10277
  const k = keyOf(cur);
@@ -10258,8 +10281,13 @@ function SettingsPanel({
10258
10281
  return;
10259
10282
  }
10260
10283
  setConfirmDel(null);
10261
- if (cur.kind === "wh") run12("webhook deleted", () => api.settings.deleteWebhook(cur.wh.id), whQ.reload);
10262
- else run12("alert deleted", () => api.settings.deleteAlert(cur.rule.id), alertQ.reload);
10284
+ if (cur.kind === "wh") {
10285
+ const id = cur.wh.id;
10286
+ run12("webhook deleted", () => api.settings.deleteWebhook(id).then(() => setHidden((h) => new Set(h).add("wh:" + id))), whQ.reload);
10287
+ } else {
10288
+ const id = cur.rule.id;
10289
+ run12("alert deleted", () => api.settings.deleteAlert(id).then(() => setHidden((h) => new Set(h).add("alert:" + id))), alertQ.reload);
10290
+ }
10263
10291
  } else if (inp === "r") reloadAll();
10264
10292
  },
10265
10293
  { isActive: focused && !editing }
@@ -10288,7 +10316,7 @@ function SettingsPanel({
10288
10316
  const error = locked ? null : localQ.error ?? whQ.error ?? alertQ.error;
10289
10317
  const mark = (r) => keyOf(r) === keyOf(cur) && focused ? "\u25B8 " : " ";
10290
10318
  const onOff = (on) => on ? /* @__PURE__ */ jsx7(Text7, { color: theme.ok, children: "on " }) : /* @__PURE__ */ jsx7(Text7, { color: theme.dim, children: "off" });
10291
- const chanOf = (rule) => [...(rule.slackUrls ?? []).map((u) => "slack " + u), ...rule.emails ?? [], ...(rule.telegram ?? []).map((t) => "tg " + t)].join(", ") || "\u2014";
10319
+ const chanOf = (rule) => [...rule.emails ?? [], ...(rule.telegram ?? []).map((t) => "tg " + t)].join(", ") || "\u2014";
10292
10320
  const listBudget = Math.max(4, rows - 10);
10293
10321
  const start = Math.min(Math.max(0, selClamped - Math.floor(listBudget / 2)), Math.max(0, rowsAll.length - listBudget));
10294
10322
  const inWindow = (r) => {
@@ -10296,9 +10324,9 @@ function SettingsPanel({
10296
10324
  return i >= start && i < start + listBudget;
10297
10325
  };
10298
10326
  return /* @__PURE__ */ jsx7(DataView, { loading, error, children: /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", children: [
10299
- /* @__PURE__ */ jsx7(Text7, { color: theme.dim, children: focused ? "\u2191\u2193 move \xB7 enter view-toggle-edit \xB7 m make active \xB7 n add account \xB7 e events \xB7 d delete \xB7 r refresh" : "press \u2192 to configure" }),
10327
+ /* @__PURE__ */ jsx7(Text7, { color: theme.dim, children: focused ? "\u2191\u2193 move \xB7 enter/m act \xB7 t test webhook \xB7 n add account \xB7 e events \xB7 d delete \xB7 r refresh" : "press \u2192 to configure" }),
10300
10328
  editing ? /* @__PURE__ */ jsxs7(Box7, { children: [
10301
- /* @__PURE__ */ jsx7(Text7, { color: theme.warn, children: editing === "path" ? "local log path: " : editing === "wh-url" ? "webhook url: " : "channel (slack url / email / telegram id): " }),
10329
+ /* @__PURE__ */ jsx7(Text7, { color: theme.warn, children: editing === "path" ? "local log path: " : editing === "wh-url" ? "webhook url: " : editing === "alert-email" ? "e-mail address: " : "telegram chat id (from @userinfobot): " }),
10302
10330
  /* @__PURE__ */ jsx7(TextInput5, { value: input, onChange: setInput, onSubmit: submitInput })
10303
10331
  ] }) : msg ? /* @__PURE__ */ jsx7(Text7, { color: msg.level === "bad" ? theme.bad : theme.ok, children: truncate2(msg.text, cols) }) : login?.msg ? /* @__PURE__ */ jsx7(Text7, { color: login.phase === "error" ? theme.bad : theme.ok, children: login.msg }) : /* @__PURE__ */ jsx7(Text7, { children: " " }),
10304
10332
  /* @__PURE__ */ jsxs7(Box7, { marginTop: 1, flexDirection: "column", children: [
@@ -10391,15 +10419,19 @@ function SettingsPanel({
10391
10419
  /* @__PURE__ */ jsx7(Text7, { children: `\u2265${rule.threshold}/${rule.windowSeconds}s ` }),
10392
10420
  /* @__PURE__ */ jsx7(Text7, { color: theme.accent, children: truncate2(chanOf(rule), cols - 26) })
10393
10421
  ] }, rule.id)),
10394
- inWindow({ kind: "alert-add" }) ? /* @__PURE__ */ jsxs7(Text7, { children: [
10395
- /* @__PURE__ */ jsx7(Text7, { color: cur.kind === "alert-add" && focused ? theme.accentBright : theme.dim, children: mark({ kind: "alert-add" }) }),
10396
- /* @__PURE__ */ jsx7(Text7, { color: theme.dim, children: "+ add alert (enter \u2014 one channel: slack url, email or telegram chat id)" })
10422
+ inWindow({ kind: "alert-add-email" }) ? /* @__PURE__ */ jsxs7(Text7, { children: [
10423
+ /* @__PURE__ */ jsx7(Text7, { color: cur.kind === "alert-add-email" && focused ? theme.accentBright : theme.dim, children: mark({ kind: "alert-add-email" }) }),
10424
+ /* @__PURE__ */ jsx7(Text7, { color: theme.dim, children: "+ add email alert (enter)" })
10425
+ ] }) : null,
10426
+ inWindow({ kind: "alert-add-tg" }) ? /* @__PURE__ */ jsxs7(Text7, { children: [
10427
+ /* @__PURE__ */ jsx7(Text7, { color: cur.kind === "alert-add-tg" && focused ? theme.accentBright : theme.dim, children: mark({ kind: "alert-add-tg" }) }),
10428
+ /* @__PURE__ */ jsx7(Text7, { color: theme.dim, children: "+ add telegram alert (enter \u2014 numeric chat id, get it from @userinfobot)" })
10397
10429
  ] }) : null
10398
10430
  ] })
10399
10431
  ] })
10400
10432
  ] }) });
10401
10433
  }
10402
- var EVENTS, SPIN2, acctLabel;
10434
+ var EVENTS, SPIN2, ALERT_BASE, acctLabel;
10403
10435
  var init_Settings = __esm({
10404
10436
  "src/tui/panels/Settings.tsx"() {
10405
10437
  "use strict";
@@ -10412,6 +10444,7 @@ var init_Settings = __esm({
10412
10444
  init_theme();
10413
10445
  EVENTS = ["denials", "allowed", "all"];
10414
10446
  SPIN2 = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
10447
+ ALERT_BASE = { name: "dataroom alert", threshold: 5, windowSeconds: 60, signal: "any" };
10415
10448
  acctLabel = (a) => a.email || a.user || "account \u2026" + a.apiKey.slice(-4);
10416
10449
  }
10417
10450
  });
package/dist/tui/index.js CHANGED
@@ -550,6 +550,7 @@ __export(settings_exports, {
550
550
  getSecurityLayers: () => getSecurityLayers,
551
551
  getSelfProtection: () => getSelfProtection,
552
552
  getWebhooks: () => getWebhooks,
553
+ sendTestWebhook: () => sendTestWebhook,
553
554
  setAlertEnabled: () => setAlertEnabled,
554
555
  setLocalLogs: () => setLocalLogs,
555
556
  setSecurityLayers: () => setSecurityLayers,
@@ -604,6 +605,9 @@ function createWebhook(body) {
604
605
  function deleteWebhook(id) {
605
606
  return request("DELETE", "/settings/denial-webhook", { query: { id } });
606
607
  }
608
+ function sendTestWebhook(id) {
609
+ return request("POST", "/settings/denial-webhook/send-test", { body: { id } });
610
+ }
607
611
  function updateWebhook(id, patch) {
608
612
  return request("PATCH", "/settings/denial-webhook", { body: { id, ...patch } });
609
613
  }
@@ -3171,13 +3175,7 @@ function stopLogsServerDaemon() {
3171
3175
  import { Fragment as Fragment5, jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
3172
3176
  var EVENTS = ["denials", "allowed", "all"];
3173
3177
  var SPIN2 = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
3174
- function alertBodyFor(channel) {
3175
- const c2 = channel.trim();
3176
- const base = { name: "dataroom alert", threshold: 5, windowSeconds: 60, signal: "any" };
3177
- if (/^https?:\/\//i.test(c2)) return { ...base, slackUrl: c2 };
3178
- if (c2.includes("@")) return { ...base, emails: [c2] };
3179
- return { ...base, telegram: [c2] };
3180
- }
3178
+ var ALERT_BASE = { name: "dataroom alert", threshold: 5, windowSeconds: 60, signal: "any" };
3181
3179
  var acctLabel = (a) => a.email || a.user || "account \u2026" + a.apiKey.slice(-4);
3182
3180
  function SettingsPanel({
3183
3181
  active: active2,
@@ -3213,8 +3211,9 @@ function SettingsPanel({
3213
3211
  const whQ = useLoader(() => listAccounts().length ? api.settings.getWebhooks() : Promise.resolve(null));
3214
3212
  const alertQ = useLoader(() => listAccounts().length ? api.settings.getAlerts() : Promise.resolve(null));
3215
3213
  const local = localQ.data;
3216
- const webhooks = whQ.data?.webhooks ?? [];
3217
- const alerts = alertQ.data?.rules ?? [];
3214
+ const [hidden, setHidden] = useState7(/* @__PURE__ */ new Set());
3215
+ const webhooks = (whQ.data?.webhooks ?? []).filter((w) => !hidden.has("wh:" + w.id));
3216
+ const alerts = (alertQ.data?.rules ?? []).filter((r) => !hidden.has("alert:" + r.id));
3218
3217
  const rowsAll = [
3219
3218
  ...accounts.map((acc) => ({ kind: "acct", acc })),
3220
3219
  { kind: "acct-add" },
@@ -3225,7 +3224,8 @@ function SettingsPanel({
3225
3224
  ...webhooks.map((wh) => ({ kind: "wh", wh })),
3226
3225
  { kind: "wh-add" },
3227
3226
  ...alerts.map((rule) => ({ kind: "alert", rule })),
3228
- { kind: "alert-add" }
3227
+ { kind: "alert-add-email" },
3228
+ { kind: "alert-add-tg" }
3229
3229
  ]
3230
3230
  ];
3231
3231
  const selClamped = Math.min(sel, rowsAll.length - 1);
@@ -3310,9 +3310,12 @@ function SettingsPanel({
3310
3310
  setEditing("wh-url");
3311
3311
  } else if (r.kind === "alert") {
3312
3312
  run(r.rule.enabled ? "alert disabled" : "alert enabled", () => api.settings.setAlertEnabled(r.rule.id, !r.rule.enabled), alertQ.reload);
3313
+ } else if (r.kind === "alert-add-email") {
3314
+ setInput("");
3315
+ setEditing("alert-email");
3313
3316
  } else {
3314
3317
  setInput("");
3315
- setEditing("alert-channel");
3318
+ setEditing("alert-tg");
3316
3319
  }
3317
3320
  };
3318
3321
  const submitInput = () => {
@@ -3325,9 +3328,20 @@ function SettingsPanel({
3325
3328
  } else if (which === "wh-url") {
3326
3329
  if (!v) return;
3327
3330
  run("webhook added", () => api.settings.createWebhook({ url: v, events: "denials" }), whQ.reload);
3328
- } else if (which === "alert-channel") {
3331
+ } else if (which === "alert-email") {
3332
+ if (!v) return;
3333
+ if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(v)) {
3334
+ setMsg({ text: "\u2717 that does not look like an e-mail address", level: "bad" });
3335
+ return;
3336
+ }
3337
+ run("email alert added", () => api.settings.createAlert({ ...ALERT_BASE, emails: [v] }), alertQ.reload);
3338
+ } else if (which === "alert-tg") {
3329
3339
  if (!v) return;
3330
- run("alert rule added", () => api.settings.createAlert(alertBodyFor(v)), alertQ.reload);
3340
+ if (!/^-?\d{5,}$/.test(v)) {
3341
+ setMsg({ text: "\u2717 a telegram chat id is a number \u2014 get yours from @userinfobot", level: "bad" });
3342
+ return;
3343
+ }
3344
+ run("telegram alert added", () => api.settings.createAlert({ ...ALERT_BASE, telegram: [v] }), alertQ.reload);
3331
3345
  }
3332
3346
  };
3333
3347
  useInput6(
@@ -3347,10 +3361,20 @@ function SettingsPanel({
3347
3361
  setSel((n) => Math.min(rowsAll.length - 1, n + 1));
3348
3362
  setConfirmDel(null);
3349
3363
  } else if (key.return || inp === " ") activate(cur);
3350
- else if (inp === "m" && cur.kind === "acct") {
3351
- const ok = setActiveAccount({ apiKey: cur.acc.apiKey, apiUrl: cur.acc.apiUrl });
3352
- setMsg(ok ? { text: `\u2713 ${acctLabel(cur.acc)} is now the ACTIVE key (guard + logging)`, level: "ok" } : { text: "\u2717 could not set active", level: "bad" });
3353
- refreshAccounts();
3364
+ else if (inp === "m") {
3365
+ if (cur.kind === "acct") {
3366
+ const ok = setActiveAccount({ apiKey: cur.acc.apiKey, apiUrl: cur.acc.apiUrl });
3367
+ setMsg(ok ? { text: `\u2713 ${acctLabel(cur.acc)} is now the ACTIVE key (guard + logging)`, level: "ok" } : { text: "\u2717 could not set active", level: "bad" });
3368
+ refreshAccounts();
3369
+ } else if (cur.kind === "wh" || cur.kind === "alert" || cur.kind === "ll-enabled" || cur.kind === "ll-server") activate(cur);
3370
+ } else if (inp === "t" && cur.kind === "wh") {
3371
+ run(
3372
+ "test event sent \u2014 check your endpoint",
3373
+ () => api.settings.sendTestWebhook(cur.wh.id).then((r) => {
3374
+ if (!r.delivered) throw new Error("endpoint rejected the test (non-2xx response)");
3375
+ }),
3376
+ whQ.reload
3377
+ );
3354
3378
  } else if (inp === "n") beginLogin();
3355
3379
  else if (inp === "e" && cur.kind === "wh") {
3356
3380
  const next = EVENTS[(EVENTS.indexOf(cur.wh.events) + 1) % EVENTS.length];
@@ -3360,9 +3384,9 @@ function SettingsPanel({
3360
3384
  if (cur.kind === "wh" || cur.kind === "wh-add") {
3361
3385
  setInput("");
3362
3386
  setEditing("wh-url");
3363
- } else if (cur.kind === "alert" || cur.kind === "alert-add") {
3387
+ } else if (cur.kind === "alert" || cur.kind === "alert-add-email" || cur.kind === "alert-add-tg") {
3364
3388
  setInput("");
3365
- setEditing("alert-channel");
3389
+ setEditing("alert-email");
3366
3390
  }
3367
3391
  } else if (inp === "d" && (cur.kind === "wh" || cur.kind === "alert")) {
3368
3392
  const k = keyOf(cur);
@@ -3372,8 +3396,13 @@ function SettingsPanel({
3372
3396
  return;
3373
3397
  }
3374
3398
  setConfirmDel(null);
3375
- if (cur.kind === "wh") run("webhook deleted", () => api.settings.deleteWebhook(cur.wh.id), whQ.reload);
3376
- else run("alert deleted", () => api.settings.deleteAlert(cur.rule.id), alertQ.reload);
3399
+ if (cur.kind === "wh") {
3400
+ const id = cur.wh.id;
3401
+ run("webhook deleted", () => api.settings.deleteWebhook(id).then(() => setHidden((h) => new Set(h).add("wh:" + id))), whQ.reload);
3402
+ } else {
3403
+ const id = cur.rule.id;
3404
+ run("alert deleted", () => api.settings.deleteAlert(id).then(() => setHidden((h) => new Set(h).add("alert:" + id))), alertQ.reload);
3405
+ }
3377
3406
  } else if (inp === "r") reloadAll();
3378
3407
  },
3379
3408
  { isActive: focused && !editing }
@@ -3402,7 +3431,7 @@ function SettingsPanel({
3402
3431
  const error = locked ? null : localQ.error ?? whQ.error ?? alertQ.error;
3403
3432
  const mark = (r) => keyOf(r) === keyOf(cur) && focused ? "\u25B8 " : " ";
3404
3433
  const onOff = (on) => on ? /* @__PURE__ */ jsx7(Text7, { color: theme.ok, children: "on " }) : /* @__PURE__ */ jsx7(Text7, { color: theme.dim, children: "off" });
3405
- const chanOf = (rule) => [...(rule.slackUrls ?? []).map((u) => "slack " + u), ...rule.emails ?? [], ...(rule.telegram ?? []).map((t) => "tg " + t)].join(", ") || "\u2014";
3434
+ const chanOf = (rule) => [...rule.emails ?? [], ...(rule.telegram ?? []).map((t) => "tg " + t)].join(", ") || "\u2014";
3406
3435
  const listBudget = Math.max(4, rows - 10);
3407
3436
  const start = Math.min(Math.max(0, selClamped - Math.floor(listBudget / 2)), Math.max(0, rowsAll.length - listBudget));
3408
3437
  const inWindow = (r) => {
@@ -3410,9 +3439,9 @@ function SettingsPanel({
3410
3439
  return i >= start && i < start + listBudget;
3411
3440
  };
3412
3441
  return /* @__PURE__ */ jsx7(DataView, { loading, error, children: /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", children: [
3413
- /* @__PURE__ */ jsx7(Text7, { color: theme.dim, children: focused ? "\u2191\u2193 move \xB7 enter view-toggle-edit \xB7 m make active \xB7 n add account \xB7 e events \xB7 d delete \xB7 r refresh" : "press \u2192 to configure" }),
3442
+ /* @__PURE__ */ jsx7(Text7, { color: theme.dim, children: focused ? "\u2191\u2193 move \xB7 enter/m act \xB7 t test webhook \xB7 n add account \xB7 e events \xB7 d delete \xB7 r refresh" : "press \u2192 to configure" }),
3414
3443
  editing ? /* @__PURE__ */ jsxs7(Box7, { children: [
3415
- /* @__PURE__ */ jsx7(Text7, { color: theme.warn, children: editing === "path" ? "local log path: " : editing === "wh-url" ? "webhook url: " : "channel (slack url / email / telegram id): " }),
3444
+ /* @__PURE__ */ jsx7(Text7, { color: theme.warn, children: editing === "path" ? "local log path: " : editing === "wh-url" ? "webhook url: " : editing === "alert-email" ? "e-mail address: " : "telegram chat id (from @userinfobot): " }),
3416
3445
  /* @__PURE__ */ jsx7(TextInput5, { value: input, onChange: setInput, onSubmit: submitInput })
3417
3446
  ] }) : msg ? /* @__PURE__ */ jsx7(Text7, { color: msg.level === "bad" ? theme.bad : theme.ok, children: truncate(msg.text, cols) }) : login?.msg ? /* @__PURE__ */ jsx7(Text7, { color: login.phase === "error" ? theme.bad : theme.ok, children: login.msg }) : /* @__PURE__ */ jsx7(Text7, { children: " " }),
3418
3447
  /* @__PURE__ */ jsxs7(Box7, { marginTop: 1, flexDirection: "column", children: [
@@ -3505,9 +3534,13 @@ function SettingsPanel({
3505
3534
  /* @__PURE__ */ jsx7(Text7, { children: `\u2265${rule.threshold}/${rule.windowSeconds}s ` }),
3506
3535
  /* @__PURE__ */ jsx7(Text7, { color: theme.accent, children: truncate(chanOf(rule), cols - 26) })
3507
3536
  ] }, rule.id)),
3508
- inWindow({ kind: "alert-add" }) ? /* @__PURE__ */ jsxs7(Text7, { children: [
3509
- /* @__PURE__ */ jsx7(Text7, { color: cur.kind === "alert-add" && focused ? theme.accentBright : theme.dim, children: mark({ kind: "alert-add" }) }),
3510
- /* @__PURE__ */ jsx7(Text7, { color: theme.dim, children: "+ add alert (enter \u2014 one channel: slack url, email or telegram chat id)" })
3537
+ inWindow({ kind: "alert-add-email" }) ? /* @__PURE__ */ jsxs7(Text7, { children: [
3538
+ /* @__PURE__ */ jsx7(Text7, { color: cur.kind === "alert-add-email" && focused ? theme.accentBright : theme.dim, children: mark({ kind: "alert-add-email" }) }),
3539
+ /* @__PURE__ */ jsx7(Text7, { color: theme.dim, children: "+ add email alert (enter)" })
3540
+ ] }) : null,
3541
+ inWindow({ kind: "alert-add-tg" }) ? /* @__PURE__ */ jsxs7(Text7, { children: [
3542
+ /* @__PURE__ */ jsx7(Text7, { color: cur.kind === "alert-add-tg" && focused ? theme.accentBright : theme.dim, children: mark({ kind: "alert-add-tg" }) }),
3543
+ /* @__PURE__ */ jsx7(Text7, { color: theme.dim, children: "+ add telegram alert (enter \u2014 numeric chat id, get it from @userinfobot)" })
3511
3544
  ] }) : null
3512
3545
  ] })
3513
3546
  ] })
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@solongate/proxy",
3
- "version": "0.81.52",
3
+ "version": "0.81.54",
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": {