@solongate/proxy 0.82.45 → 0.82.47

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.
@@ -24,6 +24,13 @@ export declare function runGlobalRestore(): void;
24
24
  * The auto-shield shell shim is left to `solongate` login (it can print), so this
25
25
  * touches only the guard/audit/stop hooks — the primary protection.
26
26
  */
27
+ /**
28
+ * `solongate repair` — restore the guard after tampering/deletion. Reports what
29
+ * was missing, then rewrites every protection file (guard/audit/stop/shield hooks
30
+ * + cloud config) and re-registers the hooks in Claude Code and Antigravity, then
31
+ * re-locks. Reuses the logged-in account, so no re-login. Human-only (gated).
32
+ */
33
+ export declare function runRepair(): Promise<number>;
27
34
  export declare function installGlobalQuiet(): {
28
35
  ok: boolean;
29
36
  message: string;
@@ -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, chmodSync } from "fs";
3
3
  import { resolve, join, dirname } from "path";
4
4
  import { homedir } from "os";
5
5
  import { fileURLToPath } from "url";
@@ -12,7 +12,11 @@ function lockFile(file) {
12
12
  try {
13
13
  if (process.platform === "win32") {
14
14
  try {
15
- execFileSync("icacls", [file, "/deny", "*S-1-1-0:(WD,AD,DC,DE)"], { stdio: "ignore" });
15
+ execFileSync("icacls", [file, "/deny", "*S-1-1-0:(WD,AD,DC,DE,WDAC,WO)"], { stdio: "ignore" });
16
+ } catch {
17
+ }
18
+ try {
19
+ execFileSync("icacls", [file, "/grant", "*S-1-3-4:(RX)"], { stdio: "ignore" });
16
20
  } catch {
17
21
  }
18
22
  try {
@@ -29,6 +33,10 @@ function lockFile(file) {
29
33
  execFileSync("chattr", ["+i", file], { stdio: "ignore" });
30
34
  } catch {
31
35
  }
36
+ try {
37
+ chmodSync(file, 292);
38
+ } catch {
39
+ }
32
40
  }
33
41
  } catch {
34
42
  }
@@ -37,6 +45,10 @@ function unlockFile(file) {
37
45
  if (!existsSync(file)) return;
38
46
  try {
39
47
  if (process.platform === "win32") {
48
+ try {
49
+ execFileSync("icacls", [file, "/remove:g", "*S-1-3-4"], { stdio: "ignore" });
50
+ } catch {
51
+ }
40
52
  try {
41
53
  execFileSync("icacls", [file, "/remove:d", "*S-1-1-0"], { stdio: "ignore" });
42
54
  } catch {
@@ -59,6 +71,10 @@ function unlockFile(file) {
59
71
  execFileSync("chattr", ["-i", file], { stdio: "ignore" });
60
72
  } catch {
61
73
  }
74
+ try {
75
+ chmodSync(file, 420);
76
+ } catch {
77
+ }
62
78
  }
63
79
  } catch {
64
80
  }
@@ -193,6 +209,34 @@ function runGlobalRestore() {
193
209
  }
194
210
  console.log(" Global SolonGate enforcement uninstalled. Restart Claude Code.");
195
211
  }
212
+ async function runRepair() {
213
+ const p = globalPaths();
214
+ const out = (s) => void process.stderr.write(s + "\n");
215
+ const has = (f) => existsSync(f);
216
+ const guardFile = join(p.hooksDir, "guard.mjs");
217
+ out("");
218
+ out(" SolonGate repair");
219
+ out("");
220
+ out(" before:");
221
+ out(` guard hook file ${has(guardFile) ? "present" : "MISSING"}`);
222
+ out(` cloud credential ${has(p.configPath) ? "present" : "MISSING"}`);
223
+ out(` Claude Code settings ${isGuardInstalled() ? "guard registered" : "guard NOT registered"}`);
224
+ out(` Antigravity hooks ${has(p.antigravityHooksPath) ? "present" : "MISSING"}`);
225
+ out("");
226
+ const r = installGlobalQuiet();
227
+ if (!r.ok) {
228
+ out(` \u2717 ${r.message}`);
229
+ return 1;
230
+ }
231
+ out(" restored:");
232
+ out(` guard hook file present (v${installedGuardVersion() ?? "?"})`);
233
+ out(` Claude Code settings ${isGuardInstalled() ? "guard registered" : "NOT registered"}`);
234
+ out(` Antigravity hooks ${has(p.antigravityHooksPath) ? "present" : "MISSING"}`);
235
+ out("");
236
+ out(" \u2713 guard repaired. Open a new AI session for it to take effect.");
237
+ out("");
238
+ return 0;
239
+ }
196
240
  function installGlobalQuiet() {
197
241
  try {
198
242
  const p = globalPaths();
@@ -246,7 +290,7 @@ function installGlobalQuiet() {
246
290
  installAntigravityGuard(p, join(p.hooksDir, "guard.mjs").replace(/\\/g, "/"));
247
291
  } catch {
248
292
  }
249
- if (process.env["SOLONGATE_OS_LOCK"] === "1") lockProtected();
293
+ if (process.env["SOLONGATE_NO_OS_LOCK"] !== "1") lockProtected();
250
294
  return { ok: true, message: "guard installed (open a new session)" };
251
295
  } catch (e) {
252
296
  return { ok: false, message: e instanceof Error ? e.message : String(e) };
@@ -436,7 +480,7 @@ async function runGlobalInstall(opts = {}) {
436
480
  console.log(` Registered Antigravity CLI guard \u2192 ${p.antigravityHooksPath}`);
437
481
  } catch {
438
482
  }
439
- if (process.env["SOLONGATE_OS_LOCK"] === "1") {
483
+ if (process.env["SOLONGATE_NO_OS_LOCK"] !== "1") {
440
484
  lockProtected();
441
485
  console.log(" Locked protection files (OS-level read-only/immutable).");
442
486
  }
@@ -457,6 +501,7 @@ export {
457
501
  removeClaudeShim,
458
502
  runGlobalInstall,
459
503
  runGlobalRestore,
504
+ runRepair,
460
505
  uninstallGlobalQuiet,
461
506
  unlockProtected
462
507
  };
package/dist/index.js CHANGED
@@ -6202,10 +6202,11 @@ __export(global_install_exports, {
6202
6202
  removeClaudeShim: () => removeClaudeShim,
6203
6203
  runGlobalInstall: () => runGlobalInstall,
6204
6204
  runGlobalRestore: () => runGlobalRestore,
6205
+ runRepair: () => runRepair,
6205
6206
  uninstallGlobalQuiet: () => uninstallGlobalQuiet,
6206
6207
  unlockProtected: () => unlockProtected
6207
6208
  });
6208
- import { readFileSync as readFileSync4, writeFileSync as writeFileSync3, existsSync as existsSync3, mkdirSync as mkdirSync3, rmSync as rmSync2 } from "fs";
6209
+ import { readFileSync as readFileSync4, writeFileSync as writeFileSync3, existsSync as existsSync3, mkdirSync as mkdirSync3, rmSync as rmSync2, chmodSync } from "fs";
6209
6210
  import { resolve as resolve3, join as join4, dirname } from "path";
6210
6211
  import { homedir as homedir2 } from "os";
6211
6212
  import { fileURLToPath } from "url";
@@ -6216,7 +6217,11 @@ function lockFile(file) {
6216
6217
  try {
6217
6218
  if (process.platform === "win32") {
6218
6219
  try {
6219
- execFileSync2("icacls", [file, "/deny", "*S-1-1-0:(WD,AD,DC,DE)"], { stdio: "ignore" });
6220
+ execFileSync2("icacls", [file, "/deny", "*S-1-1-0:(WD,AD,DC,DE,WDAC,WO)"], { stdio: "ignore" });
6221
+ } catch {
6222
+ }
6223
+ try {
6224
+ execFileSync2("icacls", [file, "/grant", "*S-1-3-4:(RX)"], { stdio: "ignore" });
6220
6225
  } catch {
6221
6226
  }
6222
6227
  try {
@@ -6233,6 +6238,10 @@ function lockFile(file) {
6233
6238
  execFileSync2("chattr", ["+i", file], { stdio: "ignore" });
6234
6239
  } catch {
6235
6240
  }
6241
+ try {
6242
+ chmodSync(file, 292);
6243
+ } catch {
6244
+ }
6236
6245
  }
6237
6246
  } catch {
6238
6247
  }
@@ -6241,6 +6250,10 @@ function unlockFile(file) {
6241
6250
  if (!existsSync3(file)) return;
6242
6251
  try {
6243
6252
  if (process.platform === "win32") {
6253
+ try {
6254
+ execFileSync2("icacls", [file, "/remove:g", "*S-1-3-4"], { stdio: "ignore" });
6255
+ } catch {
6256
+ }
6244
6257
  try {
6245
6258
  execFileSync2("icacls", [file, "/remove:d", "*S-1-1-0"], { stdio: "ignore" });
6246
6259
  } catch {
@@ -6263,6 +6276,10 @@ function unlockFile(file) {
6263
6276
  execFileSync2("chattr", ["-i", file], { stdio: "ignore" });
6264
6277
  } catch {
6265
6278
  }
6279
+ try {
6280
+ chmodSync(file, 420);
6281
+ } catch {
6282
+ }
6266
6283
  }
6267
6284
  } catch {
6268
6285
  }
@@ -6396,6 +6413,34 @@ function runGlobalRestore() {
6396
6413
  }
6397
6414
  console.log(" Global SolonGate enforcement uninstalled. Restart Claude Code.");
6398
6415
  }
6416
+ async function runRepair() {
6417
+ const p = globalPaths();
6418
+ const out2 = (s) => void process.stderr.write(s + "\n");
6419
+ const has = (f) => existsSync3(f);
6420
+ const guardFile = join4(p.hooksDir, "guard.mjs");
6421
+ out2("");
6422
+ out2(" SolonGate repair");
6423
+ out2("");
6424
+ out2(" before:");
6425
+ out2(` guard hook file ${has(guardFile) ? "present" : "MISSING"}`);
6426
+ out2(` cloud credential ${has(p.configPath) ? "present" : "MISSING"}`);
6427
+ out2(` Claude Code settings ${isGuardInstalled() ? "guard registered" : "guard NOT registered"}`);
6428
+ out2(` Antigravity hooks ${has(p.antigravityHooksPath) ? "present" : "MISSING"}`);
6429
+ out2("");
6430
+ const r = installGlobalQuiet();
6431
+ if (!r.ok) {
6432
+ out2(` \u2717 ${r.message}`);
6433
+ return 1;
6434
+ }
6435
+ out2(" restored:");
6436
+ out2(` guard hook file present (v${installedGuardVersion() ?? "?"})`);
6437
+ out2(` Claude Code settings ${isGuardInstalled() ? "guard registered" : "NOT registered"}`);
6438
+ out2(` Antigravity hooks ${has(p.antigravityHooksPath) ? "present" : "MISSING"}`);
6439
+ out2("");
6440
+ out2(" \u2713 guard repaired. Open a new AI session for it to take effect.");
6441
+ out2("");
6442
+ return 0;
6443
+ }
6399
6444
  function installGlobalQuiet() {
6400
6445
  try {
6401
6446
  const p = globalPaths();
@@ -6449,7 +6494,7 @@ function installGlobalQuiet() {
6449
6494
  installAntigravityGuard(p, join4(p.hooksDir, "guard.mjs").replace(/\\/g, "/"));
6450
6495
  } catch {
6451
6496
  }
6452
- if (process.env["SOLONGATE_OS_LOCK"] === "1") lockProtected();
6497
+ if (process.env["SOLONGATE_NO_OS_LOCK"] !== "1") lockProtected();
6453
6498
  return { ok: true, message: "guard installed (open a new session)" };
6454
6499
  } catch (e) {
6455
6500
  return { ok: false, message: e instanceof Error ? e.message : String(e) };
@@ -6637,7 +6682,7 @@ async function runGlobalInstall(opts = {}) {
6637
6682
  console.log(` Registered Antigravity CLI guard \u2192 ${p.antigravityHooksPath}`);
6638
6683
  } catch {
6639
6684
  }
6640
- if (process.env["SOLONGATE_OS_LOCK"] === "1") {
6685
+ if (process.env["SOLONGATE_NO_OS_LOCK"] !== "1") {
6641
6686
  lockProtected();
6642
6687
  console.log(" Locked protection files (OS-level read-only/immutable).");
6643
6688
  }
@@ -16058,7 +16103,7 @@ ${msg.content.text}`;
16058
16103
 
16059
16104
  // src/index.ts
16060
16105
  init_cli_utils();
16061
- var CLI_SUBCOMMANDS = /* @__PURE__ */ new Set(["update", "logs-server", "local-logs", "policy", "ratelimit", "dlp", "stats", "audit", "sessions", "session", "doctor", "watch", "alerts", "webhooks", "dataroom"]);
16106
+ var CLI_SUBCOMMANDS = /* @__PURE__ */ new Set(["update", "repair", "logs-server", "local-logs", "policy", "ratelimit", "dlp", "stats", "audit", "sessions", "session", "doctor", "watch", "alerts", "webhooks", "dataroom"]);
16062
16107
  var CLI_INFO_ARGS = /* @__PURE__ */ new Set(["login", "help", "--help", "-h", "--version", "-v", "version"]);
16063
16108
  var IS_HUMAN_CLI = process.argv.length <= 2 || CLI_SUBCOMMANDS.has(process.argv[2] ?? "") || CLI_INFO_ARGS.has(process.argv[2] ?? "");
16064
16109
  if (!IS_HUMAN_CLI) {
@@ -16120,6 +16165,7 @@ function printHelp() {
16120
16165
  head("Setup & status");
16121
16166
  cmd("solongate", "open the dataroom UI (login, policies, audit, settings)");
16122
16167
  cmd("update", "update SolonGate to the newest version and refresh the guard");
16168
+ cmd("repair", "restore the guard + hook + settings files if they were deleted or disarmed");
16123
16169
  cmd("doctor", "health check: login, policy, guard, local logs");
16124
16170
  cmd("doctor --json", "the same health check as machine-readable JSON");
16125
16171
  cmd("logs-server start", "start the local audit-log service for the dashboard (background)");
@@ -16262,6 +16308,10 @@ async function main() {
16262
16308
  const { runUpdateCommand: runUpdateCommand2 } = await Promise.resolve().then(() => (init_self_update(), self_update_exports));
16263
16309
  process.exit(await runUpdateCommand2());
16264
16310
  }
16311
+ if (subcommand === "repair") {
16312
+ const { runRepair: runRepair2 } = await Promise.resolve().then(() => (init_global_install(), global_install_exports));
16313
+ process.exit(await runRepair2());
16314
+ }
16265
16315
  if (subcommand === "logs-server" || subcommand === "local-logs") {
16266
16316
  const { runLogsServer: runLogsServer2 } = await Promise.resolve().then(() => (init_logs_server(), logs_server_exports));
16267
16317
  await runLogsServer2();
package/dist/tui/index.js CHANGED
@@ -9,7 +9,7 @@ var __export = (target, all) => {
9
9
  };
10
10
 
11
11
  // src/global-install.ts
12
- import { readFileSync as readFileSync4, writeFileSync as writeFileSync5, existsSync as existsSync2, mkdirSync as mkdirSync4, rmSync } from "fs";
12
+ import { readFileSync as readFileSync4, writeFileSync as writeFileSync5, existsSync as existsSync2, mkdirSync as mkdirSync4, rmSync, chmodSync } from "fs";
13
13
  import { resolve as resolve2, join as join6, dirname } from "path";
14
14
  import { homedir as homedir6 } from "os";
15
15
  import { fileURLToPath } from "url";
@@ -20,7 +20,11 @@ function lockFile(file) {
20
20
  try {
21
21
  if (process.platform === "win32") {
22
22
  try {
23
- execFileSync("icacls", [file, "/deny", "*S-1-1-0:(WD,AD,DC,DE)"], { stdio: "ignore" });
23
+ execFileSync("icacls", [file, "/deny", "*S-1-1-0:(WD,AD,DC,DE,WDAC,WO)"], { stdio: "ignore" });
24
+ } catch {
25
+ }
26
+ try {
27
+ execFileSync("icacls", [file, "/grant", "*S-1-3-4:(RX)"], { stdio: "ignore" });
24
28
  } catch {
25
29
  }
26
30
  try {
@@ -37,6 +41,10 @@ function lockFile(file) {
37
41
  execFileSync("chattr", ["+i", file], { stdio: "ignore" });
38
42
  } catch {
39
43
  }
44
+ try {
45
+ chmodSync(file, 292);
46
+ } catch {
47
+ }
40
48
  }
41
49
  } catch {
42
50
  }
@@ -45,6 +53,10 @@ function unlockFile(file) {
45
53
  if (!existsSync2(file)) return;
46
54
  try {
47
55
  if (process.platform === "win32") {
56
+ try {
57
+ execFileSync("icacls", [file, "/remove:g", "*S-1-3-4"], { stdio: "ignore" });
58
+ } catch {
59
+ }
48
60
  try {
49
61
  execFileSync("icacls", [file, "/remove:d", "*S-1-1-0"], { stdio: "ignore" });
50
62
  } catch {
@@ -67,6 +79,10 @@ function unlockFile(file) {
67
79
  execFileSync("chattr", ["-i", file], { stdio: "ignore" });
68
80
  } catch {
69
81
  }
82
+ try {
83
+ chmodSync(file, 420);
84
+ } catch {
85
+ }
70
86
  }
71
87
  } catch {
72
88
  }
@@ -217,7 +233,7 @@ function installGlobalQuiet() {
217
233
  installAntigravityGuard(p, join6(p.hooksDir, "guard.mjs").replace(/\\/g, "/"));
218
234
  } catch {
219
235
  }
220
- if (process.env["SOLONGATE_OS_LOCK"] === "1") lockProtected();
236
+ if (process.env["SOLONGATE_NO_OS_LOCK"] !== "1") lockProtected();
221
237
  return { ok: true, message: "guard installed (open a new session)" };
222
238
  } catch (e) {
223
239
  return { ok: false, message: e instanceof Error ? e.message : String(e) };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@solongate/proxy",
3
- "version": "0.82.45",
3
+ "version": "0.82.47",
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": {