@solongate/proxy 0.81.81 → 0.81.83
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/global-install.d.ts +15 -0
- package/dist/global-install.js +47 -14
- package/dist/index.js +67 -31
- package/dist/login.js +1 -1
- package/dist/tui/index.js +63 -27
- package/package.json +1 -1
package/dist/global-install.d.ts
CHANGED
|
@@ -11,6 +11,13 @@ export declare function globalPaths(): {
|
|
|
11
11
|
};
|
|
12
12
|
export declare function clearGuardUpdateCheck(): boolean;
|
|
13
13
|
export declare function runGlobalRestore(): void;
|
|
14
|
+
/**
|
|
15
|
+
* Delete the guard's cached policy/security config (`~/.solongate/.policy-cache-*.json`)
|
|
16
|
+
* so the next tool call RE-FETCHES it from the API. Fixes a stale cache — e.g. the
|
|
17
|
+
* guard still enforcing DLP `detect` after you switched it to `block` in the
|
|
18
|
+
* dataroom. Best-effort; returns how many cache files it cleared.
|
|
19
|
+
*/
|
|
20
|
+
export declare function clearPolicyCache(): number;
|
|
14
21
|
/**
|
|
15
22
|
* TUI-safe (re)install — the dataroom's one-key "install / update guard" action.
|
|
16
23
|
* Writes the hook files THIS CLI ships (readGuard = the current package's bundle,
|
|
@@ -25,6 +32,14 @@ export declare function installGlobalQuiet(): {
|
|
|
25
32
|
ok: boolean;
|
|
26
33
|
message: string;
|
|
27
34
|
};
|
|
35
|
+
/** HOOK_VERSION of the guard hook currently installed on THIS device (read from
|
|
36
|
+
* the file), or null when not installed. The LOCAL truth — independent of the
|
|
37
|
+
* cloud guard-status (which only knows what the device last REPORTED). */
|
|
38
|
+
export declare function installedGuardVersion(): number | null;
|
|
39
|
+
/** True when the installed guard hook DIFFERS from the one this CLI ships — i.e.
|
|
40
|
+
* a newer hook is available locally (the CLI self-updated). Cloud-independent,
|
|
41
|
+
* so the dataroom can offer/apply an update even when the API is behind. */
|
|
42
|
+
export declare function guardHookOutdated(): boolean;
|
|
28
43
|
/**
|
|
29
44
|
* Are the SolonGate guard hooks currently installed in the global Claude settings
|
|
30
45
|
* on THIS device? Reflects a local install/remove IMMEDIATELY — unlike the cloud
|
package/dist/global-install.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/global-install.ts
|
|
2
|
-
import { readFileSync, writeFileSync, existsSync, mkdirSync, rmSync } from "fs";
|
|
2
|
+
import { readFileSync, writeFileSync, existsSync, mkdirSync, rmSync, readdirSync } from "fs";
|
|
3
3
|
import { resolve, join, dirname } from "path";
|
|
4
4
|
import { homedir } from "os";
|
|
5
5
|
import { fileURLToPath } from "url";
|
|
@@ -137,6 +137,24 @@ function runGlobalRestore() {
|
|
|
137
137
|
}
|
|
138
138
|
console.log(" Global SolonGate enforcement uninstalled. Restart Claude Code.");
|
|
139
139
|
}
|
|
140
|
+
function clearPolicyCache() {
|
|
141
|
+
try {
|
|
142
|
+
const dir = globalPaths().sgDir;
|
|
143
|
+
let n = 0;
|
|
144
|
+
for (const f of readdirSync(dir)) {
|
|
145
|
+
if (f.startsWith(".policy-cache-") && f.endsWith(".json")) {
|
|
146
|
+
try {
|
|
147
|
+
rmSync(join(dir, f), { force: true });
|
|
148
|
+
n++;
|
|
149
|
+
} catch {
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
return n;
|
|
154
|
+
} catch {
|
|
155
|
+
return 0;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
140
158
|
function installGlobalQuiet() {
|
|
141
159
|
try {
|
|
142
160
|
const p = globalPaths();
|
|
@@ -179,12 +197,31 @@ function installGlobalQuiet() {
|
|
|
179
197
|
}
|
|
180
198
|
};
|
|
181
199
|
writeFileSync(p.settingsPath, JSON.stringify(merged, null, 2) + "\n");
|
|
200
|
+
clearPolicyCache();
|
|
182
201
|
if (process.env["SOLONGATE_OS_LOCK"] === "1") lockProtected();
|
|
183
|
-
return { ok: true, message: "guard installed
|
|
202
|
+
return { ok: true, message: "guard installed + policy refreshed (open a new session)" };
|
|
184
203
|
} catch (e) {
|
|
185
204
|
return { ok: false, message: e instanceof Error ? e.message : String(e) };
|
|
186
205
|
}
|
|
187
206
|
}
|
|
207
|
+
function installedGuardVersion() {
|
|
208
|
+
try {
|
|
209
|
+
const p = globalPaths();
|
|
210
|
+
const s = readFileSync(join(p.hooksDir, "guard.mjs"), "utf-8");
|
|
211
|
+
const m = s.match(/HOOK_VERSION\s*=\s*(\d+)/);
|
|
212
|
+
return m ? parseInt(m[1], 10) : null;
|
|
213
|
+
} catch {
|
|
214
|
+
return null;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
function guardHookOutdated() {
|
|
218
|
+
try {
|
|
219
|
+
const p = globalPaths();
|
|
220
|
+
return readFileSync(join(p.hooksDir, "guard.mjs"), "utf-8") !== readGuard();
|
|
221
|
+
} catch {
|
|
222
|
+
return false;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
188
225
|
function isGuardInstalled() {
|
|
189
226
|
try {
|
|
190
227
|
const p = globalPaths();
|
|
@@ -200,18 +237,11 @@ function uninstallGlobalQuiet() {
|
|
|
200
237
|
const p = globalPaths();
|
|
201
238
|
unlockProtected();
|
|
202
239
|
removeClaudeShim();
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
}
|
|
208
|
-
if (existsSync(p.settingsPath)) {
|
|
209
|
-
const s = JSON.parse(readFileSync(p.settingsPath, "utf-8"));
|
|
210
|
-
delete s.hooks;
|
|
211
|
-
writeFileSync(p.settingsPath, JSON.stringify(s, null, 2) + "\n");
|
|
212
|
-
return { ok: true, message: `guard removed \u2014 hooks cleared \xB7 ${applies}` };
|
|
213
|
-
}
|
|
214
|
-
return { ok: true, message: "nothing to remove \u2014 no global Claude Code settings found" };
|
|
240
|
+
if (!existsSync(p.settingsPath)) return { ok: true, message: "guard removed (open a new session)" };
|
|
241
|
+
const s = JSON.parse(readFileSync(p.settingsPath, "utf-8"));
|
|
242
|
+
delete s.hooks;
|
|
243
|
+
writeFileSync(p.settingsPath, JSON.stringify(s, null, 2) + "\n");
|
|
244
|
+
return { ok: true, message: "guard removed (open a new session)" };
|
|
215
245
|
} catch (e) {
|
|
216
246
|
return { ok: false, message: e instanceof Error ? e.message : String(e) };
|
|
217
247
|
}
|
|
@@ -355,10 +385,13 @@ async function installGlobalWithKey(apiKey, apiUrl) {
|
|
|
355
385
|
}
|
|
356
386
|
export {
|
|
357
387
|
clearGuardUpdateCheck,
|
|
388
|
+
clearPolicyCache,
|
|
358
389
|
globalPaths,
|
|
390
|
+
guardHookOutdated,
|
|
359
391
|
installClaudeShim,
|
|
360
392
|
installGlobalQuiet,
|
|
361
393
|
installGlobalWithKey,
|
|
394
|
+
installedGuardVersion,
|
|
362
395
|
isGuardInstalled,
|
|
363
396
|
lockProtected,
|
|
364
397
|
removeClaudeShim,
|
package/dist/index.js
CHANGED
|
@@ -10085,7 +10085,7 @@ var init_Audit = __esm({
|
|
|
10085
10085
|
});
|
|
10086
10086
|
|
|
10087
10087
|
// src/global-install.ts
|
|
10088
|
-
import { readFileSync as readFileSync9, writeFileSync as writeFileSync9, existsSync as existsSync4, mkdirSync as mkdirSync8, rmSync as rmSync2 } from "fs";
|
|
10088
|
+
import { readFileSync as readFileSync9, writeFileSync as writeFileSync9, existsSync as existsSync4, mkdirSync as mkdirSync8, rmSync as rmSync2, readdirSync } from "fs";
|
|
10089
10089
|
import { resolve as resolve4, join as join11, dirname as dirname3 } from "path";
|
|
10090
10090
|
import { homedir as homedir9 } from "os";
|
|
10091
10091
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
@@ -10186,6 +10186,24 @@ function readGuard() {
|
|
|
10186
10186
|
const bundled = join11(HOOKS_DIR, "guard.bundled.mjs");
|
|
10187
10187
|
return existsSync4(bundled) ? readFileSync9(bundled, "utf-8") : readHook("guard.mjs");
|
|
10188
10188
|
}
|
|
10189
|
+
function clearPolicyCache() {
|
|
10190
|
+
try {
|
|
10191
|
+
const dir = globalPaths().sgDir;
|
|
10192
|
+
let n = 0;
|
|
10193
|
+
for (const f of readdirSync(dir)) {
|
|
10194
|
+
if (f.startsWith(".policy-cache-") && f.endsWith(".json")) {
|
|
10195
|
+
try {
|
|
10196
|
+
rmSync2(join11(dir, f), { force: true });
|
|
10197
|
+
n++;
|
|
10198
|
+
} catch {
|
|
10199
|
+
}
|
|
10200
|
+
}
|
|
10201
|
+
}
|
|
10202
|
+
return n;
|
|
10203
|
+
} catch {
|
|
10204
|
+
return 0;
|
|
10205
|
+
}
|
|
10206
|
+
}
|
|
10189
10207
|
function installGlobalQuiet() {
|
|
10190
10208
|
try {
|
|
10191
10209
|
const p = globalPaths();
|
|
@@ -10228,12 +10246,31 @@ function installGlobalQuiet() {
|
|
|
10228
10246
|
}
|
|
10229
10247
|
};
|
|
10230
10248
|
writeFileSync9(p.settingsPath, JSON.stringify(merged, null, 2) + "\n");
|
|
10249
|
+
clearPolicyCache();
|
|
10231
10250
|
if (process.env["SOLONGATE_OS_LOCK"] === "1") lockProtected();
|
|
10232
|
-
return { ok: true, message: "guard installed
|
|
10251
|
+
return { ok: true, message: "guard installed + policy refreshed (open a new session)" };
|
|
10233
10252
|
} catch (e) {
|
|
10234
10253
|
return { ok: false, message: e instanceof Error ? e.message : String(e) };
|
|
10235
10254
|
}
|
|
10236
10255
|
}
|
|
10256
|
+
function installedGuardVersion() {
|
|
10257
|
+
try {
|
|
10258
|
+
const p = globalPaths();
|
|
10259
|
+
const s = readFileSync9(join11(p.hooksDir, "guard.mjs"), "utf-8");
|
|
10260
|
+
const m = s.match(/HOOK_VERSION\s*=\s*(\d+)/);
|
|
10261
|
+
return m ? parseInt(m[1], 10) : null;
|
|
10262
|
+
} catch {
|
|
10263
|
+
return null;
|
|
10264
|
+
}
|
|
10265
|
+
}
|
|
10266
|
+
function guardHookOutdated() {
|
|
10267
|
+
try {
|
|
10268
|
+
const p = globalPaths();
|
|
10269
|
+
return readFileSync9(join11(p.hooksDir, "guard.mjs"), "utf-8") !== readGuard();
|
|
10270
|
+
} catch {
|
|
10271
|
+
return false;
|
|
10272
|
+
}
|
|
10273
|
+
}
|
|
10237
10274
|
function isGuardInstalled() {
|
|
10238
10275
|
try {
|
|
10239
10276
|
const p = globalPaths();
|
|
@@ -10249,18 +10286,11 @@ function uninstallGlobalQuiet() {
|
|
|
10249
10286
|
const p = globalPaths();
|
|
10250
10287
|
unlockProtected();
|
|
10251
10288
|
removeClaudeShim();
|
|
10252
|
-
|
|
10253
|
-
|
|
10254
|
-
|
|
10255
|
-
|
|
10256
|
-
}
|
|
10257
|
-
if (existsSync4(p.settingsPath)) {
|
|
10258
|
-
const s = JSON.parse(readFileSync9(p.settingsPath, "utf-8"));
|
|
10259
|
-
delete s.hooks;
|
|
10260
|
-
writeFileSync9(p.settingsPath, JSON.stringify(s, null, 2) + "\n");
|
|
10261
|
-
return { ok: true, message: `guard removed \u2014 hooks cleared \xB7 ${applies}` };
|
|
10262
|
-
}
|
|
10263
|
-
return { ok: true, message: "nothing to remove \u2014 no global Claude Code settings found" };
|
|
10289
|
+
if (!existsSync4(p.settingsPath)) return { ok: true, message: "guard removed (open a new session)" };
|
|
10290
|
+
const s = JSON.parse(readFileSync9(p.settingsPath, "utf-8"));
|
|
10291
|
+
delete s.hooks;
|
|
10292
|
+
writeFileSync9(p.settingsPath, JSON.stringify(s, null, 2) + "\n");
|
|
10293
|
+
return { ok: true, message: "guard removed (open a new session)" };
|
|
10264
10294
|
} catch (e) {
|
|
10265
10295
|
return { ok: false, message: e instanceof Error ? e.message : String(e) };
|
|
10266
10296
|
}
|
|
@@ -10336,6 +10366,13 @@ function SettingsPanel({
|
|
|
10336
10366
|
const abort = useRef3(false);
|
|
10337
10367
|
const refreshAccounts = () => setAccounts(listAccounts());
|
|
10338
10368
|
const [guardHere, setGuardHere] = useState7(() => isGuardInstalled());
|
|
10369
|
+
const [guardVer, setGuardVer] = useState7(() => installedGuardVersion());
|
|
10370
|
+
const [guardOld, setGuardOld] = useState7(() => guardHookOutdated());
|
|
10371
|
+
const refreshGuard = () => {
|
|
10372
|
+
setGuardHere(isGuardInstalled());
|
|
10373
|
+
setGuardVer(installedGuardVersion());
|
|
10374
|
+
setGuardOld(guardHookOutdated());
|
|
10375
|
+
};
|
|
10339
10376
|
const locked = accounts.length === 0;
|
|
10340
10377
|
const [srv, setSrv] = useState7(() => logsServerStatus());
|
|
10341
10378
|
useEffect6(() => {
|
|
@@ -10353,21 +10390,20 @@ function SettingsPanel({
|
|
|
10353
10390
|
const guardQ = useLoader(() => listAccounts().length ? api.settings.getGuardStatus() : Promise.resolve(null));
|
|
10354
10391
|
const selfQ = useLoader(() => listAccounts().length ? api.settings.getSelfProtection() : Promise.resolve(null));
|
|
10355
10392
|
const local = localQ.data;
|
|
10356
|
-
const guard = guardQ.data;
|
|
10357
10393
|
const selfProt = selfQ.data;
|
|
10358
10394
|
const autoInstalledRef = useRef3(false);
|
|
10359
10395
|
useEffect6(() => {
|
|
10360
10396
|
if (autoInstalledRef.current) return;
|
|
10361
|
-
if (guardHere &&
|
|
10397
|
+
if (guardHere && guardOld) {
|
|
10362
10398
|
autoInstalledRef.current = true;
|
|
10363
10399
|
const res = installGlobalQuiet();
|
|
10364
10400
|
if (res.ok) {
|
|
10365
|
-
|
|
10366
|
-
setMsg({ text: `\u2713 guard
|
|
10401
|
+
refreshGuard();
|
|
10402
|
+
setMsg({ text: `\u2713 guard updated \u2192 v${installedGuardVersion() ?? "?"} (open a new session)`, level: "ok" });
|
|
10367
10403
|
guardQ.reload();
|
|
10368
10404
|
}
|
|
10369
10405
|
}
|
|
10370
|
-
}, [guardHere,
|
|
10406
|
+
}, [guardHere, guardOld]);
|
|
10371
10407
|
const [hidden, setHidden] = useState7(/* @__PURE__ */ new Set());
|
|
10372
10408
|
const webhooks = (whQ.data?.webhooks ?? []).filter((w) => !hidden.has("wh:" + w.id));
|
|
10373
10409
|
const alerts = (alertQ.data?.rules ?? []).filter((r) => !hidden.has("alert:" + r.id));
|
|
@@ -10495,7 +10531,7 @@ function SettingsPanel({
|
|
|
10495
10531
|
} else if (r.kind === "guard") {
|
|
10496
10532
|
const res = installGlobalQuiet();
|
|
10497
10533
|
setMsg({ text: (res.ok ? "\u2713 " : "\u2717 ") + res.message, level: res.ok ? "ok" : "bad" });
|
|
10498
|
-
|
|
10534
|
+
refreshGuard();
|
|
10499
10535
|
guardQ.reload();
|
|
10500
10536
|
} else if (r.kind === "self") {
|
|
10501
10537
|
if (!selfProt) return;
|
|
@@ -10659,7 +10695,7 @@ function SettingsPanel({
|
|
|
10659
10695
|
setConfirmDel(null);
|
|
10660
10696
|
const res = uninstallGlobalQuiet();
|
|
10661
10697
|
setMsg({ text: (res.ok ? "\u2713 " : "\u2717 ") + res.message, level: res.ok ? "ok" : "bad" });
|
|
10662
|
-
|
|
10698
|
+
refreshGuard();
|
|
10663
10699
|
guardQ.reload();
|
|
10664
10700
|
} else if (inp === "d" && (cur.kind === "wh" || cur.kind === "alert")) {
|
|
10665
10701
|
const k = keyOf(cur);
|
|
@@ -10768,13 +10804,13 @@ function SettingsPanel({
|
|
|
10768
10804
|
/* @__PURE__ */ jsx7(Text7, { color: theme.dim, children: "guard".padEnd(11) }),
|
|
10769
10805
|
!guardHere ? /* @__PURE__ */ jsxs7(Fragment4, { children: [
|
|
10770
10806
|
/* @__PURE__ */ jsx7(Text7, { color: theme.bad, bold: true, children: "removed" }),
|
|
10771
|
-
/* @__PURE__ */ jsx7(Text7, { color: theme.dim, children: " \
|
|
10807
|
+
/* @__PURE__ */ jsx7(Text7, { color: theme.dim, children: " \xB7 " }),
|
|
10772
10808
|
/* @__PURE__ */ jsx7(Text7, { color: theme.accentBright, children: "enter to install" })
|
|
10773
|
-
] }) :
|
|
10774
|
-
/* @__PURE__ */ jsx7(Text7, { color:
|
|
10775
|
-
/* @__PURE__ */ jsx7(Text7, { color: theme.dim, children:
|
|
10776
|
-
/* @__PURE__ */ jsx7(Text7, { color: theme.dim, children:
|
|
10777
|
-
] })
|
|
10809
|
+
] }) : /* @__PURE__ */ jsxs7(Fragment4, { children: [
|
|
10810
|
+
/* @__PURE__ */ jsx7(Text7, { color: guardOld ? theme.warn : theme.ok, children: `v${guardVer ?? "?"}` }),
|
|
10811
|
+
/* @__PURE__ */ jsx7(Text7, { color: theme.dim, children: guardOld ? " \xB7 update available \xB7 enter update" : " (latest) \xB7 enter reinstall" }),
|
|
10812
|
+
/* @__PURE__ */ jsx7(Text7, { color: theme.dim, children: " \xB7 d remove" })
|
|
10813
|
+
] })
|
|
10778
10814
|
] });
|
|
10779
10815
|
case "self":
|
|
10780
10816
|
return /* @__PURE__ */ jsxs7(Text7, { wrap: "truncate", children: [
|
|
@@ -12333,7 +12369,7 @@ import { createServer, request as httpRequest } from "http";
|
|
|
12333
12369
|
import { request as httpsRequest } from "https";
|
|
12334
12370
|
import { spawn as spawn5 } from "child_process";
|
|
12335
12371
|
import { URL as URL2 } from "url";
|
|
12336
|
-
import { readFileSync as readFileSync11, existsSync as existsSync7, readdirSync, statSync as statSync4 } from "fs";
|
|
12372
|
+
import { readFileSync as readFileSync11, existsSync as existsSync7, readdirSync as readdirSync2, statSync as statSync4 } from "fs";
|
|
12337
12373
|
import { resolve as resolve5 } from "path";
|
|
12338
12374
|
import { homedir as homedir13 } from "os";
|
|
12339
12375
|
function findCacheFile() {
|
|
@@ -12345,7 +12381,7 @@ function findCacheFile() {
|
|
|
12345
12381
|
}
|
|
12346
12382
|
let best = null, bestTs = -1;
|
|
12347
12383
|
try {
|
|
12348
|
-
for (const name of
|
|
12384
|
+
for (const name of readdirSync2(dir)) {
|
|
12349
12385
|
if (name.startsWith(".policy-cache-") && name.endsWith(".json")) {
|
|
12350
12386
|
const full = resolve5(dir, name);
|
|
12351
12387
|
const ts = statSync4(full).mtimeMs;
|
|
@@ -12655,7 +12691,7 @@ import { createServer as createServer2 } from "http";
|
|
|
12655
12691
|
import { readFileSync as readFileSync12, statSync as statSync5 } from "fs";
|
|
12656
12692
|
import { resolve as resolve6, join as join15, isAbsolute } from "path";
|
|
12657
12693
|
import { homedir as homedir14 } from "os";
|
|
12658
|
-
import { readdirSync as
|
|
12694
|
+
import { readdirSync as readdirSync3 } from "fs";
|
|
12659
12695
|
function allowedOrigins() {
|
|
12660
12696
|
const base = [
|
|
12661
12697
|
"https://dashboard.solongate.com",
|
|
@@ -12676,7 +12712,7 @@ function resolveLocalLogDir(rawPath) {
|
|
|
12676
12712
|
async function findLogDir() {
|
|
12677
12713
|
const base = resolve6(homedir14(), ".solongate");
|
|
12678
12714
|
try {
|
|
12679
|
-
const files =
|
|
12715
|
+
const files = readdirSync3(base).filter((f) => f.startsWith(".policy-cache-") && f.endsWith(".json"));
|
|
12680
12716
|
for (const f of files) {
|
|
12681
12717
|
try {
|
|
12682
12718
|
const c2 = JSON.parse(readFileSync12(join15(base, f), "utf-8"));
|
package/dist/login.js
CHANGED
|
@@ -26,7 +26,7 @@ var c = {
|
|
|
26
26
|
var BANNER_COLORS = [c.blue1, c.blue2, c.blue3, c.blue4, c.blue5, c.blue6];
|
|
27
27
|
|
|
28
28
|
// src/global-install.ts
|
|
29
|
-
import { readFileSync, writeFileSync, existsSync, mkdirSync, rmSync } from "fs";
|
|
29
|
+
import { readFileSync, writeFileSync, existsSync, mkdirSync, rmSync, readdirSync } from "fs";
|
|
30
30
|
import { resolve, join, dirname } from "path";
|
|
31
31
|
import { homedir } from "os";
|
|
32
32
|
import { fileURLToPath } from "url";
|
package/dist/tui/index.js
CHANGED
|
@@ -3140,7 +3140,7 @@ import TextInput5 from "ink-text-input";
|
|
|
3140
3140
|
import { useEffect as useEffect6, useRef as useRef3, useState as useState7 } from "react";
|
|
3141
3141
|
|
|
3142
3142
|
// src/global-install.ts
|
|
3143
|
-
import { readFileSync as readFileSync4, writeFileSync as writeFileSync5, existsSync as existsSync2, mkdirSync as mkdirSync4, rmSync } from "fs";
|
|
3143
|
+
import { readFileSync as readFileSync4, writeFileSync as writeFileSync5, existsSync as existsSync2, mkdirSync as mkdirSync4, rmSync, readdirSync } from "fs";
|
|
3144
3144
|
import { resolve as resolve2, join as join6, dirname } from "path";
|
|
3145
3145
|
import { homedir as homedir6 } from "os";
|
|
3146
3146
|
import { fileURLToPath } from "url";
|
|
@@ -3243,6 +3243,24 @@ function readGuard() {
|
|
|
3243
3243
|
const bundled = join6(HOOKS_DIR, "guard.bundled.mjs");
|
|
3244
3244
|
return existsSync2(bundled) ? readFileSync4(bundled, "utf-8") : readHook("guard.mjs");
|
|
3245
3245
|
}
|
|
3246
|
+
function clearPolicyCache() {
|
|
3247
|
+
try {
|
|
3248
|
+
const dir = globalPaths().sgDir;
|
|
3249
|
+
let n = 0;
|
|
3250
|
+
for (const f of readdirSync(dir)) {
|
|
3251
|
+
if (f.startsWith(".policy-cache-") && f.endsWith(".json")) {
|
|
3252
|
+
try {
|
|
3253
|
+
rmSync(join6(dir, f), { force: true });
|
|
3254
|
+
n++;
|
|
3255
|
+
} catch {
|
|
3256
|
+
}
|
|
3257
|
+
}
|
|
3258
|
+
}
|
|
3259
|
+
return n;
|
|
3260
|
+
} catch {
|
|
3261
|
+
return 0;
|
|
3262
|
+
}
|
|
3263
|
+
}
|
|
3246
3264
|
function installGlobalQuiet() {
|
|
3247
3265
|
try {
|
|
3248
3266
|
const p = globalPaths();
|
|
@@ -3285,12 +3303,31 @@ function installGlobalQuiet() {
|
|
|
3285
3303
|
}
|
|
3286
3304
|
};
|
|
3287
3305
|
writeFileSync5(p.settingsPath, JSON.stringify(merged, null, 2) + "\n");
|
|
3306
|
+
clearPolicyCache();
|
|
3288
3307
|
if (process.env["SOLONGATE_OS_LOCK"] === "1") lockProtected();
|
|
3289
|
-
return { ok: true, message: "guard installed
|
|
3308
|
+
return { ok: true, message: "guard installed + policy refreshed (open a new session)" };
|
|
3290
3309
|
} catch (e) {
|
|
3291
3310
|
return { ok: false, message: e instanceof Error ? e.message : String(e) };
|
|
3292
3311
|
}
|
|
3293
3312
|
}
|
|
3313
|
+
function installedGuardVersion() {
|
|
3314
|
+
try {
|
|
3315
|
+
const p = globalPaths();
|
|
3316
|
+
const s = readFileSync4(join6(p.hooksDir, "guard.mjs"), "utf-8");
|
|
3317
|
+
const m = s.match(/HOOK_VERSION\s*=\s*(\d+)/);
|
|
3318
|
+
return m ? parseInt(m[1], 10) : null;
|
|
3319
|
+
} catch {
|
|
3320
|
+
return null;
|
|
3321
|
+
}
|
|
3322
|
+
}
|
|
3323
|
+
function guardHookOutdated() {
|
|
3324
|
+
try {
|
|
3325
|
+
const p = globalPaths();
|
|
3326
|
+
return readFileSync4(join6(p.hooksDir, "guard.mjs"), "utf-8") !== readGuard();
|
|
3327
|
+
} catch {
|
|
3328
|
+
return false;
|
|
3329
|
+
}
|
|
3330
|
+
}
|
|
3294
3331
|
function isGuardInstalled() {
|
|
3295
3332
|
try {
|
|
3296
3333
|
const p = globalPaths();
|
|
@@ -3306,18 +3343,11 @@ function uninstallGlobalQuiet() {
|
|
|
3306
3343
|
const p = globalPaths();
|
|
3307
3344
|
unlockProtected();
|
|
3308
3345
|
removeClaudeShim();
|
|
3309
|
-
|
|
3310
|
-
|
|
3311
|
-
|
|
3312
|
-
|
|
3313
|
-
}
|
|
3314
|
-
if (existsSync2(p.settingsPath)) {
|
|
3315
|
-
const s = JSON.parse(readFileSync4(p.settingsPath, "utf-8"));
|
|
3316
|
-
delete s.hooks;
|
|
3317
|
-
writeFileSync5(p.settingsPath, JSON.stringify(s, null, 2) + "\n");
|
|
3318
|
-
return { ok: true, message: `guard removed \u2014 hooks cleared \xB7 ${applies}` };
|
|
3319
|
-
}
|
|
3320
|
-
return { ok: true, message: "nothing to remove \u2014 no global Claude Code settings found" };
|
|
3346
|
+
if (!existsSync2(p.settingsPath)) return { ok: true, message: "guard removed (open a new session)" };
|
|
3347
|
+
const s = JSON.parse(readFileSync4(p.settingsPath, "utf-8"));
|
|
3348
|
+
delete s.hooks;
|
|
3349
|
+
writeFileSync5(p.settingsPath, JSON.stringify(s, null, 2) + "\n");
|
|
3350
|
+
return { ok: true, message: "guard removed (open a new session)" };
|
|
3321
3351
|
} catch (e) {
|
|
3322
3352
|
return { ok: false, message: e instanceof Error ? e.message : String(e) };
|
|
3323
3353
|
}
|
|
@@ -3473,6 +3503,13 @@ function SettingsPanel({
|
|
|
3473
3503
|
const abort = useRef3(false);
|
|
3474
3504
|
const refreshAccounts = () => setAccounts(listAccounts());
|
|
3475
3505
|
const [guardHere, setGuardHere] = useState7(() => isGuardInstalled());
|
|
3506
|
+
const [guardVer, setGuardVer] = useState7(() => installedGuardVersion());
|
|
3507
|
+
const [guardOld, setGuardOld] = useState7(() => guardHookOutdated());
|
|
3508
|
+
const refreshGuard = () => {
|
|
3509
|
+
setGuardHere(isGuardInstalled());
|
|
3510
|
+
setGuardVer(installedGuardVersion());
|
|
3511
|
+
setGuardOld(guardHookOutdated());
|
|
3512
|
+
};
|
|
3476
3513
|
const locked = accounts.length === 0;
|
|
3477
3514
|
const [srv, setSrv] = useState7(() => logsServerStatus());
|
|
3478
3515
|
useEffect6(() => {
|
|
@@ -3490,21 +3527,20 @@ function SettingsPanel({
|
|
|
3490
3527
|
const guardQ = useLoader(() => listAccounts().length ? api.settings.getGuardStatus() : Promise.resolve(null));
|
|
3491
3528
|
const selfQ = useLoader(() => listAccounts().length ? api.settings.getSelfProtection() : Promise.resolve(null));
|
|
3492
3529
|
const local = localQ.data;
|
|
3493
|
-
const guard = guardQ.data;
|
|
3494
3530
|
const selfProt = selfQ.data;
|
|
3495
3531
|
const autoInstalledRef = useRef3(false);
|
|
3496
3532
|
useEffect6(() => {
|
|
3497
3533
|
if (autoInstalledRef.current) return;
|
|
3498
|
-
if (guardHere &&
|
|
3534
|
+
if (guardHere && guardOld) {
|
|
3499
3535
|
autoInstalledRef.current = true;
|
|
3500
3536
|
const res = installGlobalQuiet();
|
|
3501
3537
|
if (res.ok) {
|
|
3502
|
-
|
|
3503
|
-
setMsg({ text: `\u2713 guard
|
|
3538
|
+
refreshGuard();
|
|
3539
|
+
setMsg({ text: `\u2713 guard updated \u2192 v${installedGuardVersion() ?? "?"} (open a new session)`, level: "ok" });
|
|
3504
3540
|
guardQ.reload();
|
|
3505
3541
|
}
|
|
3506
3542
|
}
|
|
3507
|
-
}, [guardHere,
|
|
3543
|
+
}, [guardHere, guardOld]);
|
|
3508
3544
|
const [hidden, setHidden] = useState7(/* @__PURE__ */ new Set());
|
|
3509
3545
|
const webhooks = (whQ.data?.webhooks ?? []).filter((w) => !hidden.has("wh:" + w.id));
|
|
3510
3546
|
const alerts = (alertQ.data?.rules ?? []).filter((r) => !hidden.has("alert:" + r.id));
|
|
@@ -3632,7 +3668,7 @@ function SettingsPanel({
|
|
|
3632
3668
|
} else if (r.kind === "guard") {
|
|
3633
3669
|
const res = installGlobalQuiet();
|
|
3634
3670
|
setMsg({ text: (res.ok ? "\u2713 " : "\u2717 ") + res.message, level: res.ok ? "ok" : "bad" });
|
|
3635
|
-
|
|
3671
|
+
refreshGuard();
|
|
3636
3672
|
guardQ.reload();
|
|
3637
3673
|
} else if (r.kind === "self") {
|
|
3638
3674
|
if (!selfProt) return;
|
|
@@ -3796,7 +3832,7 @@ function SettingsPanel({
|
|
|
3796
3832
|
setConfirmDel(null);
|
|
3797
3833
|
const res = uninstallGlobalQuiet();
|
|
3798
3834
|
setMsg({ text: (res.ok ? "\u2713 " : "\u2717 ") + res.message, level: res.ok ? "ok" : "bad" });
|
|
3799
|
-
|
|
3835
|
+
refreshGuard();
|
|
3800
3836
|
guardQ.reload();
|
|
3801
3837
|
} else if (inp === "d" && (cur.kind === "wh" || cur.kind === "alert")) {
|
|
3802
3838
|
const k = keyOf(cur);
|
|
@@ -3905,13 +3941,13 @@ function SettingsPanel({
|
|
|
3905
3941
|
/* @__PURE__ */ jsx7(Text7, { color: theme.dim, children: "guard".padEnd(11) }),
|
|
3906
3942
|
!guardHere ? /* @__PURE__ */ jsxs7(Fragment4, { children: [
|
|
3907
3943
|
/* @__PURE__ */ jsx7(Text7, { color: theme.bad, bold: true, children: "removed" }),
|
|
3908
|
-
/* @__PURE__ */ jsx7(Text7, { color: theme.dim, children: " \
|
|
3944
|
+
/* @__PURE__ */ jsx7(Text7, { color: theme.dim, children: " \xB7 " }),
|
|
3909
3945
|
/* @__PURE__ */ jsx7(Text7, { color: theme.accentBright, children: "enter to install" })
|
|
3910
|
-
] }) :
|
|
3911
|
-
/* @__PURE__ */ jsx7(Text7, { color:
|
|
3912
|
-
/* @__PURE__ */ jsx7(Text7, { color: theme.dim, children:
|
|
3913
|
-
/* @__PURE__ */ jsx7(Text7, { color: theme.dim, children:
|
|
3914
|
-
] })
|
|
3946
|
+
] }) : /* @__PURE__ */ jsxs7(Fragment4, { children: [
|
|
3947
|
+
/* @__PURE__ */ jsx7(Text7, { color: guardOld ? theme.warn : theme.ok, children: `v${guardVer ?? "?"}` }),
|
|
3948
|
+
/* @__PURE__ */ jsx7(Text7, { color: theme.dim, children: guardOld ? " \xB7 update available \xB7 enter update" : " (latest) \xB7 enter reinstall" }),
|
|
3949
|
+
/* @__PURE__ */ jsx7(Text7, { color: theme.dim, children: " \xB7 d remove" })
|
|
3950
|
+
] })
|
|
3915
3951
|
] });
|
|
3916
3952
|
case "self":
|
|
3917
3953
|
return /* @__PURE__ */ jsxs7(Text7, { wrap: "truncate", children: [
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@solongate/proxy",
|
|
3
|
-
"version": "0.81.
|
|
3
|
+
"version": "0.81.83",
|
|
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": {
|