@solongate/proxy 0.83.31 → 0.83.33
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/commands/index.js +6 -4
- package/dist/index.js +62 -9
- package/dist/tui/index.js +2 -0
- package/package.json +7 -7
package/dist/commands/index.js
CHANGED
|
@@ -692,7 +692,7 @@ var USAGE = usage("solongate policy", "manage cloud policies", [
|
|
|
692
692
|
["policy deny <id> [--command|--path|--url <val>]", "append a DENY rule"],
|
|
693
693
|
["policy revoke <id> <ruleId>", "remove a rule"],
|
|
694
694
|
["policy active", "show the resolved active policy"],
|
|
695
|
-
["policy activate <id> | --
|
|
695
|
+
["policy activate <id> | --off", "pin the active policy, or enforce nothing"],
|
|
696
696
|
["policy dry-run <id|file.json> [--limit N] [--mode denylist|whitelist]", "replay recent traffic against rules"]
|
|
697
697
|
], "Add --json to any read command for machine-readable output.");
|
|
698
698
|
async function run(argv) {
|
|
@@ -798,13 +798,15 @@ async function run(argv) {
|
|
|
798
798
|
return 0;
|
|
799
799
|
}
|
|
800
800
|
case "activate": {
|
|
801
|
-
if (flagBool(flags, "clear")) {
|
|
801
|
+
if (flagBool(flags, "off") || flagBool(flags, "clear")) {
|
|
802
802
|
const res2 = await api.policies.setActive(null);
|
|
803
803
|
if (json) return printJson(res2), 0;
|
|
804
|
-
|
|
804
|
+
err(green(" \u2713 Deactivated - this project now enforces no policy."));
|
|
805
|
+
err(dim(" Pin one again with: solongate policy activate <id>"));
|
|
806
|
+
return 0;
|
|
805
807
|
}
|
|
806
808
|
const id = positionals[1];
|
|
807
|
-
if (!id) return err(" Usage: policy activate <id> | policy activate --
|
|
809
|
+
if (!id) return err(" Usage: policy activate <id> | policy activate --off"), 1;
|
|
808
810
|
const res = await api.policies.setActive(id);
|
|
809
811
|
if (json) return printJson(res), 0;
|
|
810
812
|
err(green(` \u2713 Pinned active policy \u2192 ${res.active}`));
|
package/dist/index.js
CHANGED
|
@@ -7125,6 +7125,30 @@ import { access, mkdirSync as mkdirSync4, openSync, readFileSync as readFileSync
|
|
|
7125
7125
|
import { homedir as homedir3 } from "os";
|
|
7126
7126
|
import { dirname as dirname2, join as join5, sep } from "path";
|
|
7127
7127
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
7128
|
+
function lockHeldAt() {
|
|
7129
|
+
try {
|
|
7130
|
+
const ts = Number(readFileSync5(LOCK_FILE, "utf-8").trim().split(/\s+/)[1] ?? 0);
|
|
7131
|
+
if (!Number.isFinite(ts) || Date.now() - ts >= LOCK_STALE_MS) return null;
|
|
7132
|
+
return ts;
|
|
7133
|
+
} catch {
|
|
7134
|
+
return null;
|
|
7135
|
+
}
|
|
7136
|
+
}
|
|
7137
|
+
function takeInstallLock() {
|
|
7138
|
+
try {
|
|
7139
|
+
mkdirSync4(join5(homedir3(), ".solongate"), { recursive: true });
|
|
7140
|
+
writeFileSync4(LOCK_FILE, `${process.pid} ${Date.now()}
|
|
7141
|
+
`);
|
|
7142
|
+
} catch {
|
|
7143
|
+
}
|
|
7144
|
+
}
|
|
7145
|
+
function releaseInstallLock() {
|
|
7146
|
+
try {
|
|
7147
|
+
writeFileSync4(LOCK_FILE, `${process.pid} 0
|
|
7148
|
+
`);
|
|
7149
|
+
} catch {
|
|
7150
|
+
}
|
|
7151
|
+
}
|
|
7128
7152
|
function readState() {
|
|
7129
7153
|
try {
|
|
7130
7154
|
const s = JSON.parse(readFileSync5(STATE_FILE, "utf-8"));
|
|
@@ -7191,8 +7215,10 @@ async function fetchLatest() {
|
|
|
7191
7215
|
}
|
|
7192
7216
|
}
|
|
7193
7217
|
function spawnGlobalInstall(version) {
|
|
7218
|
+
if (lockHeldAt() !== null) return false;
|
|
7194
7219
|
try {
|
|
7195
7220
|
mkdirSync4(join5(homedir3(), ".solongate"), { recursive: true });
|
|
7221
|
+
takeInstallLock();
|
|
7196
7222
|
const log3 = openSync(LOG_FILE, "a");
|
|
7197
7223
|
const p = spawn2("npm", ["install", "-g", `${PKG}@${version}`], {
|
|
7198
7224
|
stdio: ["ignore", log3, log3],
|
|
@@ -7242,7 +7268,7 @@ async function runUpdateCommand() {
|
|
|
7242
7268
|
return 1;
|
|
7243
7269
|
}
|
|
7244
7270
|
out2(` updating ${cur} -> ${latest} ...`);
|
|
7245
|
-
const r = await
|
|
7271
|
+
const r = await installGlobally(latest, out2);
|
|
7246
7272
|
if (!r.ok) {
|
|
7247
7273
|
if (r.needsAdmin) {
|
|
7248
7274
|
writeState({ ...readState(), needsAdmin: latest });
|
|
@@ -7250,7 +7276,8 @@ async function runUpdateCommand() {
|
|
|
7250
7276
|
out2(" Run these two:");
|
|
7251
7277
|
for (const s of adminUpdateSteps()) out2(" " + s);
|
|
7252
7278
|
} else {
|
|
7253
|
-
out2(" update failed
|
|
7279
|
+
out2(" update failed \u2014 the CLI may not be installed right now. Run:");
|
|
7280
|
+
out2(` npm i -g ${PKG}@${latest}`);
|
|
7254
7281
|
}
|
|
7255
7282
|
return 1;
|
|
7256
7283
|
}
|
|
@@ -7300,6 +7327,26 @@ ${output}
|
|
|
7300
7327
|
}
|
|
7301
7328
|
});
|
|
7302
7329
|
}
|
|
7330
|
+
async function installGlobally(version, out2) {
|
|
7331
|
+
const heldSince = lockHeldAt();
|
|
7332
|
+
if (heldSince !== null) {
|
|
7333
|
+
out2(" another install is already running \u2014 waiting for it to finish ...");
|
|
7334
|
+
const until = Date.now() + LOCK_WAIT_MS;
|
|
7335
|
+
while (Date.now() < until && lockHeldAt() !== null) await sleep(1e3);
|
|
7336
|
+
}
|
|
7337
|
+
takeInstallLock();
|
|
7338
|
+
try {
|
|
7339
|
+
let r = await runGlobalInstall2(version);
|
|
7340
|
+
if (!r.ok && !r.needsAdmin) {
|
|
7341
|
+
await sleep(2e3);
|
|
7342
|
+
out2(" install did not take \u2014 retrying once ...");
|
|
7343
|
+
r = await runGlobalInstall2(version);
|
|
7344
|
+
}
|
|
7345
|
+
return r;
|
|
7346
|
+
} finally {
|
|
7347
|
+
releaseInstallLock();
|
|
7348
|
+
}
|
|
7349
|
+
}
|
|
7303
7350
|
function adminInstallCommand() {
|
|
7304
7351
|
return process.platform === "win32" ? `npm i -g ${PKG}@latest (in an Administrator terminal)` : `sudo npm i -g ${PKG}@latest`;
|
|
7305
7352
|
}
|
|
@@ -7443,7 +7490,7 @@ function maybeSelfUpdate(notify = (l) => process.stderr.write(l + "\n")) {
|
|
|
7443
7490
|
}
|
|
7444
7491
|
})();
|
|
7445
7492
|
}
|
|
7446
|
-
var PKG, CHECK_EVERY_MS, ATTEMPT_EVERY_MS, STATE_FILE, LOG_FILE, NEEDS_ADMIN_RE, prefixCheck;
|
|
7493
|
+
var PKG, CHECK_EVERY_MS, ATTEMPT_EVERY_MS, STATE_FILE, LOG_FILE, LOCK_FILE, LOCK_STALE_MS, LOCK_WAIT_MS, sleep, NEEDS_ADMIN_RE, prefixCheck;
|
|
7447
7494
|
var init_self_update = __esm({
|
|
7448
7495
|
"src/self-update.ts"() {
|
|
7449
7496
|
"use strict";
|
|
@@ -7453,6 +7500,10 @@ var init_self_update = __esm({
|
|
|
7453
7500
|
ATTEMPT_EVERY_MS = 6 * 60 * 60 * 1e3;
|
|
7454
7501
|
STATE_FILE = join5(homedir3(), ".solongate", ".self-update.json");
|
|
7455
7502
|
LOG_FILE = join5(homedir3(), ".solongate", "self-update.log");
|
|
7503
|
+
LOCK_FILE = join5(homedir3(), ".solongate", ".update-install.lock");
|
|
7504
|
+
LOCK_STALE_MS = 3 * 6e4;
|
|
7505
|
+
LOCK_WAIT_MS = 9e4;
|
|
7506
|
+
sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
7456
7507
|
NEEDS_ADMIN_RE = /\bEACCES\b|\bEPERM\b|permission denied|operation not permitted/i;
|
|
7457
7508
|
prefixCheck = null;
|
|
7458
7509
|
}
|
|
@@ -13041,13 +13092,15 @@ async function run2(argv) {
|
|
|
13041
13092
|
return 0;
|
|
13042
13093
|
}
|
|
13043
13094
|
case "activate": {
|
|
13044
|
-
if (flagBool(flags, "clear")) {
|
|
13095
|
+
if (flagBool(flags, "off") || flagBool(flags, "clear")) {
|
|
13045
13096
|
const res2 = await api.policies.setActive(null);
|
|
13046
13097
|
if (json) return printJson(res2), 0;
|
|
13047
|
-
|
|
13098
|
+
err(green(" \u2713 Deactivated - this project now enforces no policy."));
|
|
13099
|
+
err(dim(" Pin one again with: solongate policy activate <id>"));
|
|
13100
|
+
return 0;
|
|
13048
13101
|
}
|
|
13049
13102
|
const id = positionals[1];
|
|
13050
|
-
if (!id) return err(" Usage: policy activate <id> | policy activate --
|
|
13103
|
+
if (!id) return err(" Usage: policy activate <id> | policy activate --off"), 1;
|
|
13051
13104
|
const res = await api.policies.setActive(id);
|
|
13052
13105
|
if (json) return printJson(res), 0;
|
|
13053
13106
|
err(green(` \u2713 Pinned active policy \u2192 ${res.active}`));
|
|
@@ -13116,7 +13169,7 @@ var init_policy = __esm({
|
|
|
13116
13169
|
["policy deny <id> [--command|--path|--url <val>]", "append a DENY rule"],
|
|
13117
13170
|
["policy revoke <id> <ruleId>", "remove a rule"],
|
|
13118
13171
|
["policy active", "show the resolved active policy"],
|
|
13119
|
-
["policy activate <id> | --
|
|
13172
|
+
["policy activate <id> | --off", "pin the active policy, or enforce nothing"],
|
|
13120
13173
|
["policy dry-run <id|file.json> [--limit N] [--mode denylist|whitelist]", "replay recent traffic against rules"]
|
|
13121
13174
|
], "Add --json to any read command for machine-readable output.");
|
|
13122
13175
|
}
|
|
@@ -17464,7 +17517,7 @@ function printHelp() {
|
|
|
17464
17517
|
cmd("policy allow <id> [--command|--path|--url <val>]", "add an ALLOW rule");
|
|
17465
17518
|
cmd("policy deny <id> [--command|--path|--url <val>]", "add a DENY rule");
|
|
17466
17519
|
cmd("policy revoke <id> <ruleId>", "remove a rule");
|
|
17467
|
-
cmd("policy activate <id> | --
|
|
17520
|
+
cmd("policy activate <id> | --off", "pin the active policy, or enforce nothing");
|
|
17468
17521
|
cmd("policy active", "show the resolved active policy");
|
|
17469
17522
|
cmd("policy dry-run <id|file.json> [--mode denylist|whitelist]", "replay recent traffic against rules");
|
|
17470
17523
|
head("Rate limits");
|
|
@@ -17553,7 +17606,7 @@ async function main() {
|
|
|
17553
17606
|
}
|
|
17554
17607
|
if (IS_HUMAN_CLI) {
|
|
17555
17608
|
const tuiBound = subcommand === "dataroom" || process.argv.length <= 2 && process.stdout.isTTY && process.stdin.isTTY;
|
|
17556
|
-
if (!tuiBound) {
|
|
17609
|
+
if (!tuiBound && subcommand !== "update") {
|
|
17557
17610
|
const { maybeSelfUpdate: maybeSelfUpdate2 } = await Promise.resolve().then(() => (init_self_update(), self_update_exports));
|
|
17558
17611
|
maybeSelfUpdate2();
|
|
17559
17612
|
}
|
package/dist/tui/index.js
CHANGED
|
@@ -4720,6 +4720,8 @@ var CHECK_EVERY_MS = 30 * 60 * 1e3;
|
|
|
4720
4720
|
var ATTEMPT_EVERY_MS = 6 * 60 * 60 * 1e3;
|
|
4721
4721
|
var STATE_FILE2 = join9(homedir9(), ".solongate", ".self-update.json");
|
|
4722
4722
|
var LOG_FILE2 = join9(homedir9(), ".solongate", "self-update.log");
|
|
4723
|
+
var LOCK_FILE = join9(homedir9(), ".solongate", ".update-install.lock");
|
|
4724
|
+
var LOCK_STALE_MS = 3 * 6e4;
|
|
4723
4725
|
var NEEDS_ADMIN_RE = /\bEACCES\b|\bEPERM\b|permission denied|operation not permitted/i;
|
|
4724
4726
|
function readState2() {
|
|
4725
4727
|
try {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@solongate/proxy",
|
|
3
|
-
"version": "0.83.
|
|
3
|
+
"version": "0.83.33",
|
|
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": {
|
|
@@ -61,12 +61,12 @@
|
|
|
61
61
|
"node": ">=20.0.0"
|
|
62
62
|
},
|
|
63
63
|
"optionalDependencies": {
|
|
64
|
-
"@solongate/guard-linux-x64": "0.83.
|
|
65
|
-
"@solongate/guard-linux-arm64": "0.83.
|
|
66
|
-
"@solongate/guard-darwin-x64": "0.83.
|
|
67
|
-
"@solongate/guard-darwin-arm64": "0.83.
|
|
68
|
-
"@solongate/guard-win32-x64": "0.83.
|
|
69
|
-
"@solongate/guard-win32-arm64": "0.83.
|
|
64
|
+
"@solongate/guard-linux-x64": "0.83.33",
|
|
65
|
+
"@solongate/guard-linux-arm64": "0.83.33",
|
|
66
|
+
"@solongate/guard-darwin-x64": "0.83.33",
|
|
67
|
+
"@solongate/guard-darwin-arm64": "0.83.33",
|
|
68
|
+
"@solongate/guard-win32-x64": "0.83.33",
|
|
69
|
+
"@solongate/guard-win32-arm64": "0.83.33"
|
|
70
70
|
},
|
|
71
71
|
"dependencies": {
|
|
72
72
|
"@modelcontextprotocol/sdk": "^1.26.0",
|