@solongate/proxy 0.50.0 → 0.52.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/global-install.d.ts +2 -0
- package/dist/global-install.js +79 -0
- package/dist/index.js +408 -145
- package/dist/login.js +68 -0
- package/dist/shield.d.ts +1 -0
- package/dist/shield.js +171 -0
- package/hooks/guard.bundled.mjs +7740 -7740
- package/hooks/shield.mjs +144 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -3412,12 +3412,12 @@ ${ctx.indent}`;
|
|
|
3412
3412
|
for (const {
|
|
3413
3413
|
format,
|
|
3414
3414
|
test,
|
|
3415
|
-
resolve:
|
|
3415
|
+
resolve: resolve8
|
|
3416
3416
|
} of tags) {
|
|
3417
3417
|
if (test) {
|
|
3418
3418
|
const match = str.match(test);
|
|
3419
3419
|
if (match) {
|
|
3420
|
-
let res =
|
|
3420
|
+
let res = resolve8.apply(null, match);
|
|
3421
3421
|
if (!(res instanceof Scalar)) res = new Scalar(res);
|
|
3422
3422
|
if (format) res.format = format;
|
|
3423
3423
|
return res;
|
|
@@ -6572,8 +6572,10 @@ var init_cli_utils = __esm({
|
|
|
6572
6572
|
var global_install_exports = {};
|
|
6573
6573
|
__export(global_install_exports, {
|
|
6574
6574
|
globalPaths: () => globalPaths,
|
|
6575
|
+
installClaudeShim: () => installClaudeShim,
|
|
6575
6576
|
installGlobalWithKey: () => installGlobalWithKey,
|
|
6576
6577
|
lockProtected: () => lockProtected,
|
|
6578
|
+
removeClaudeShim: () => removeClaudeShim,
|
|
6577
6579
|
runGlobalInstall: () => runGlobalInstall,
|
|
6578
6580
|
runGlobalRestore: () => runGlobalRestore,
|
|
6579
6581
|
unlockProtected: () => unlockProtected
|
|
@@ -6646,6 +6648,7 @@ function protectedTargets() {
|
|
|
6646
6648
|
join4(p.hooksDir, "guard.mjs"),
|
|
6647
6649
|
join4(p.hooksDir, "audit.mjs"),
|
|
6648
6650
|
join4(p.hooksDir, "stop.mjs"),
|
|
6651
|
+
join4(p.hooksDir, "shield.mjs"),
|
|
6649
6652
|
p.configPath,
|
|
6650
6653
|
p.settingsPath
|
|
6651
6654
|
];
|
|
@@ -6688,6 +6691,7 @@ function ask(question) {
|
|
|
6688
6691
|
function runGlobalRestore() {
|
|
6689
6692
|
const p = globalPaths();
|
|
6690
6693
|
unlockProtected();
|
|
6694
|
+
removeClaudeShim();
|
|
6691
6695
|
if (existsSync4(p.backupPath)) {
|
|
6692
6696
|
writeFileSync3(p.settingsPath, readFileSync5(p.backupPath, "utf-8"));
|
|
6693
6697
|
console.log(` Restored ${p.settingsPath} from backup.`);
|
|
@@ -6704,6 +6708,77 @@ function runGlobalRestore() {
|
|
|
6704
6708
|
}
|
|
6705
6709
|
console.log(" Global SolonGate enforcement uninstalled. Restart Claude Code.");
|
|
6706
6710
|
}
|
|
6711
|
+
function escapeRe(s) {
|
|
6712
|
+
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
6713
|
+
}
|
|
6714
|
+
function resolveRealClaude() {
|
|
6715
|
+
try {
|
|
6716
|
+
const finder = process.platform === "win32" ? "where" : "which";
|
|
6717
|
+
const out = execFileSync2(finder, ["claude"], { encoding: "utf-8" }).split(/\r?\n/).map((s) => s.trim()).filter(Boolean);
|
|
6718
|
+
return out[0] || null;
|
|
6719
|
+
} catch {
|
|
6720
|
+
return null;
|
|
6721
|
+
}
|
|
6722
|
+
}
|
|
6723
|
+
function shimTargets() {
|
|
6724
|
+
if (process.platform === "win32") {
|
|
6725
|
+
try {
|
|
6726
|
+
const prof = execFileSync2("powershell", ["-NoProfile", "-Command", "$PROFILE.CurrentUserAllHosts"], { encoding: "utf-8" }).trim();
|
|
6727
|
+
return prof ? [prof] : [];
|
|
6728
|
+
} catch {
|
|
6729
|
+
return [];
|
|
6730
|
+
}
|
|
6731
|
+
}
|
|
6732
|
+
return [".bashrc", ".zshrc", ".profile"].map((f) => join4(homedir2(), f)).filter((f) => existsSync4(f));
|
|
6733
|
+
}
|
|
6734
|
+
function writeShimBlock(file, block) {
|
|
6735
|
+
const re = new RegExp(escapeRe(SHIM_BEGIN) + "[\\s\\S]*?" + escapeRe(SHIM_END) + "\\r?\\n?", "g");
|
|
6736
|
+
let content = existsSync4(file) ? readFileSync5(file, "utf-8") : "";
|
|
6737
|
+
content = content.replace(re, "");
|
|
6738
|
+
if (block) {
|
|
6739
|
+
if (content.length && !content.endsWith("\n")) content += "\n";
|
|
6740
|
+
content += block + "\n";
|
|
6741
|
+
}
|
|
6742
|
+
mkdirSync4(dirname2(file), { recursive: true });
|
|
6743
|
+
writeFileSync3(file, content);
|
|
6744
|
+
}
|
|
6745
|
+
function installClaudeShim(shieldPath) {
|
|
6746
|
+
const real = resolveRealClaude();
|
|
6747
|
+
if (!real) {
|
|
6748
|
+
console.log(" (Claude Code not found on PATH \u2014 skipped auto-shield. Install it, then re-run `login`.)");
|
|
6749
|
+
return;
|
|
6750
|
+
}
|
|
6751
|
+
const node = process.execPath.replace(/\\/g, "/");
|
|
6752
|
+
const shield = shieldPath.replace(/\\/g, "/");
|
|
6753
|
+
const win = process.platform === "win32";
|
|
6754
|
+
const block = win ? `${SHIM_BEGIN}
|
|
6755
|
+
function claude { & "${node}" "${shield}" -- "${real}" @args }
|
|
6756
|
+
${SHIM_END}` : `${SHIM_BEGIN}
|
|
6757
|
+
claude() { "${node}" "${shield}" -- "${real}" "$@"; }
|
|
6758
|
+
${SHIM_END}`;
|
|
6759
|
+
const targets = shimTargets();
|
|
6760
|
+
if (targets.length === 0) {
|
|
6761
|
+
console.log(" (No shell profile found for auto-shield; run `claude` via `solongate shield -- claude` manually.)");
|
|
6762
|
+
return;
|
|
6763
|
+
}
|
|
6764
|
+
for (const file of targets) {
|
|
6765
|
+
try {
|
|
6766
|
+
writeShimBlock(file, block);
|
|
6767
|
+
console.log(` Auto-shield on: \`claude\` now masks secrets (${file})`);
|
|
6768
|
+
} catch (e) {
|
|
6769
|
+
console.log(` (Could not enable auto-shield in ${file}: ${e.message})`);
|
|
6770
|
+
}
|
|
6771
|
+
}
|
|
6772
|
+
console.log(" Open a NEW terminal for it to take effect.");
|
|
6773
|
+
}
|
|
6774
|
+
function removeClaudeShim() {
|
|
6775
|
+
for (const file of shimTargets()) {
|
|
6776
|
+
try {
|
|
6777
|
+
writeShimBlock(file, null);
|
|
6778
|
+
} catch {
|
|
6779
|
+
}
|
|
6780
|
+
}
|
|
6781
|
+
}
|
|
6707
6782
|
async function runGlobalInstall(opts = {}) {
|
|
6708
6783
|
const p = globalPaths();
|
|
6709
6784
|
let apiKey = opts.apiKey || process.env["SOLONGATE_API_KEY"] || "";
|
|
@@ -6728,7 +6803,9 @@ async function runGlobalInstall(opts = {}) {
|
|
|
6728
6803
|
writeFileSync3(join4(p.hooksDir, "guard.mjs"), readGuard());
|
|
6729
6804
|
writeFileSync3(join4(p.hooksDir, "audit.mjs"), readHook("audit.mjs"));
|
|
6730
6805
|
writeFileSync3(join4(p.hooksDir, "stop.mjs"), readHook("stop.mjs"));
|
|
6806
|
+
writeFileSync3(join4(p.hooksDir, "shield.mjs"), readHook("shield.mjs"));
|
|
6731
6807
|
console.log(` Installed hooks \u2192 ${p.hooksDir}`);
|
|
6808
|
+
installClaudeShim(join4(p.hooksDir, "shield.mjs"));
|
|
6732
6809
|
writeFileSync3(p.configPath, JSON.stringify({ apiKey, apiUrl }, null, 2) + "\n");
|
|
6733
6810
|
console.log(` Wrote ${p.configPath}`);
|
|
6734
6811
|
let existing = {};
|
|
@@ -6766,12 +6843,14 @@ async function runGlobalInstall(opts = {}) {
|
|
|
6766
6843
|
async function installGlobalWithKey(apiKey, apiUrl) {
|
|
6767
6844
|
await runGlobalInstall({ apiKey, apiUrl });
|
|
6768
6845
|
}
|
|
6769
|
-
var __dirname, HOOKS_DIR;
|
|
6846
|
+
var __dirname, HOOKS_DIR, SHIM_BEGIN, SHIM_END;
|
|
6770
6847
|
var init_global_install = __esm({
|
|
6771
6848
|
"src/global-install.ts"() {
|
|
6772
6849
|
"use strict";
|
|
6773
6850
|
__dirname = dirname2(fileURLToPath(import.meta.url));
|
|
6774
6851
|
HOOKS_DIR = resolve3(__dirname, "..", "hooks");
|
|
6852
|
+
SHIM_BEGIN = "# >>> SolonGate shield (auto secret redaction) >>>";
|
|
6853
|
+
SHIM_END = "# <<< SolonGate shield <<<";
|
|
6775
6854
|
}
|
|
6776
6855
|
});
|
|
6777
6856
|
|
|
@@ -6925,10 +7004,189 @@ var init_login = __esm({
|
|
|
6925
7004
|
}
|
|
6926
7005
|
});
|
|
6927
7006
|
|
|
7007
|
+
// src/shield.ts
|
|
7008
|
+
var shield_exports = {};
|
|
7009
|
+
__export(shield_exports, {
|
|
7010
|
+
runShield: () => runShield
|
|
7011
|
+
});
|
|
7012
|
+
import { createServer, request as httpRequest } from "http";
|
|
7013
|
+
import { request as httpsRequest } from "https";
|
|
7014
|
+
import { spawn as spawn2 } from "child_process";
|
|
7015
|
+
import { URL as URL2 } from "url";
|
|
7016
|
+
import { readFileSync as readFileSync6, existsSync as existsSync5 } from "fs";
|
|
7017
|
+
import { resolve as resolve4 } from "path";
|
|
7018
|
+
import { homedir as homedir3 } from "os";
|
|
7019
|
+
function loadCfg() {
|
|
7020
|
+
try {
|
|
7021
|
+
const sel = (process.env.SOLONGATE_AGENT_ID || "default").replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
7022
|
+
const f = resolve4(homedir3(), ".solongate", ".policy-cache-" + sel + ".json");
|
|
7023
|
+
if (existsSync5(f)) {
|
|
7024
|
+
const c3 = JSON.parse(readFileSync6(f, "utf-8"));
|
|
7025
|
+
const d = c3?.security?.dlpRedact;
|
|
7026
|
+
if (d && Array.isArray(d.patterns)) return { patterns: d.patterns, custom: Array.isArray(d.custom) ? d.custom : [] };
|
|
7027
|
+
}
|
|
7028
|
+
} catch {
|
|
7029
|
+
}
|
|
7030
|
+
return { patterns: DLP_PATTERNS.map((p) => p.name), custom: [] };
|
|
7031
|
+
}
|
|
7032
|
+
function redactString(s, cfg) {
|
|
7033
|
+
if (!cfg || typeof s !== "string" || !s) return s;
|
|
7034
|
+
const allow = new Set(cfg.patterns);
|
|
7035
|
+
let out = s;
|
|
7036
|
+
for (const p of DLP_PATTERNS) if (allow.has(p.name)) out = out.replace(p.re, `[REDACTED: ${p.name}]`);
|
|
7037
|
+
for (const c3 of cfg.custom) {
|
|
7038
|
+
try {
|
|
7039
|
+
out = out.replace(new RegExp(c3.re, "g"), `[REDACTED: ${c3.name || "custom"}]`);
|
|
7040
|
+
} catch {
|
|
7041
|
+
}
|
|
7042
|
+
}
|
|
7043
|
+
return out;
|
|
7044
|
+
}
|
|
7045
|
+
function redactDeep(value, cfg) {
|
|
7046
|
+
if (typeof value === "string") return redactString(value, cfg);
|
|
7047
|
+
if (Array.isArray(value)) return value.map((v) => redactDeep(v, cfg));
|
|
7048
|
+
if (value && typeof value === "object") {
|
|
7049
|
+
const out = {};
|
|
7050
|
+
for (const [k, v] of Object.entries(value)) out[k] = redactDeep(v, cfg);
|
|
7051
|
+
return out;
|
|
7052
|
+
}
|
|
7053
|
+
return value;
|
|
7054
|
+
}
|
|
7055
|
+
function pickUpstream() {
|
|
7056
|
+
const raw = process.env.SOLONGATE_SHIELD_UPSTREAM || process.env.ANTHROPIC_BASE_URL || "https://api.anthropic.com";
|
|
7057
|
+
try {
|
|
7058
|
+
return new URL2(raw);
|
|
7059
|
+
} catch {
|
|
7060
|
+
return new URL2("https://api.anthropic.com");
|
|
7061
|
+
}
|
|
7062
|
+
}
|
|
7063
|
+
function startProxy(upstream) {
|
|
7064
|
+
const cfg = loadCfg();
|
|
7065
|
+
const forward = upstream.protocol === "https:" ? httpsRequest : httpRequest;
|
|
7066
|
+
const server = createServer((req, res) => {
|
|
7067
|
+
const chunks = [];
|
|
7068
|
+
req.on("data", (c3) => chunks.push(c3));
|
|
7069
|
+
req.on("end", () => {
|
|
7070
|
+
let body = Buffer.concat(chunks);
|
|
7071
|
+
try {
|
|
7072
|
+
if (body.length && (req.headers["content-type"] || "").includes("json")) {
|
|
7073
|
+
const parsed = JSON.parse(body.toString("utf-8"));
|
|
7074
|
+
const redacted = redactDeep(parsed, cfg);
|
|
7075
|
+
body = Buffer.from(JSON.stringify(redacted), "utf-8");
|
|
7076
|
+
}
|
|
7077
|
+
} catch {
|
|
7078
|
+
}
|
|
7079
|
+
const headers = { ...req.headers };
|
|
7080
|
+
delete headers["host"];
|
|
7081
|
+
delete headers["content-length"];
|
|
7082
|
+
delete headers["accept-encoding"];
|
|
7083
|
+
headers["content-length"] = String(body.length);
|
|
7084
|
+
const upstreamReq = forward(
|
|
7085
|
+
{
|
|
7086
|
+
protocol: upstream.protocol,
|
|
7087
|
+
hostname: upstream.hostname,
|
|
7088
|
+
port: upstream.port || (upstream.protocol === "https:" ? 443 : 80),
|
|
7089
|
+
method: req.method,
|
|
7090
|
+
path: req.url,
|
|
7091
|
+
headers: { ...headers, host: upstream.host }
|
|
7092
|
+
},
|
|
7093
|
+
(upRes) => {
|
|
7094
|
+
res.writeHead(upRes.statusCode || 502, upRes.headers);
|
|
7095
|
+
upRes.pipe(res);
|
|
7096
|
+
}
|
|
7097
|
+
);
|
|
7098
|
+
upstreamReq.on("error", (e) => {
|
|
7099
|
+
log4("upstream error:", e.message);
|
|
7100
|
+
if (!res.headersSent) res.writeHead(502, { "content-type": "text/plain" });
|
|
7101
|
+
res.end("shield upstream error");
|
|
7102
|
+
});
|
|
7103
|
+
upstreamReq.end(body);
|
|
7104
|
+
});
|
|
7105
|
+
req.on("error", () => {
|
|
7106
|
+
try {
|
|
7107
|
+
res.destroy();
|
|
7108
|
+
} catch {
|
|
7109
|
+
}
|
|
7110
|
+
});
|
|
7111
|
+
});
|
|
7112
|
+
return new Promise((resolveP) => {
|
|
7113
|
+
server.listen(0, "127.0.0.1", () => {
|
|
7114
|
+
const addr = server.address();
|
|
7115
|
+
const port = typeof addr === "object" && addr ? addr.port : 0;
|
|
7116
|
+
resolveP({ port, close: () => server.close() });
|
|
7117
|
+
});
|
|
7118
|
+
});
|
|
7119
|
+
}
|
|
7120
|
+
async function runShield() {
|
|
7121
|
+
const sep = process.argv.indexOf("--");
|
|
7122
|
+
const cmd = sep !== -1 ? process.argv.slice(sep + 1) : [];
|
|
7123
|
+
if (cmd.length === 0) {
|
|
7124
|
+
log4("usage: npx @solongate/proxy shield -- <command> [args...] (e.g. shield -- claude)");
|
|
7125
|
+
process.exit(1);
|
|
7126
|
+
}
|
|
7127
|
+
const upstream = pickUpstream();
|
|
7128
|
+
const { port, close } = await startProxy(upstream);
|
|
7129
|
+
log4(`redacting secrets on the LLM path \u2192 masking before ${upstream.host} (127.0.0.1:${port})`);
|
|
7130
|
+
const child = spawn2(cmd[0], cmd.slice(1), {
|
|
7131
|
+
stdio: "inherit",
|
|
7132
|
+
env: { ...process.env, ANTHROPIC_BASE_URL: `http://127.0.0.1:${port}` },
|
|
7133
|
+
shell: process.platform === "win32"
|
|
7134
|
+
// resolve `claude.cmd` etc. on Windows
|
|
7135
|
+
});
|
|
7136
|
+
const shutdown = () => {
|
|
7137
|
+
try {
|
|
7138
|
+
close();
|
|
7139
|
+
} catch {
|
|
7140
|
+
}
|
|
7141
|
+
};
|
|
7142
|
+
child.on("exit", (code, signal) => {
|
|
7143
|
+
shutdown();
|
|
7144
|
+
if (signal) process.kill(process.pid, signal);
|
|
7145
|
+
else process.exit(code ?? 0);
|
|
7146
|
+
});
|
|
7147
|
+
child.on("error", (e) => {
|
|
7148
|
+
log4("failed to launch command:", e.message);
|
|
7149
|
+
shutdown();
|
|
7150
|
+
process.exit(1);
|
|
7151
|
+
});
|
|
7152
|
+
for (const sig of ["SIGINT", "SIGTERM"]) process.on(sig, () => {
|
|
7153
|
+
try {
|
|
7154
|
+
child.kill(sig);
|
|
7155
|
+
} catch {
|
|
7156
|
+
}
|
|
7157
|
+
});
|
|
7158
|
+
}
|
|
7159
|
+
var log4, DLP_PATTERNS;
|
|
7160
|
+
var init_shield = __esm({
|
|
7161
|
+
"src/shield.ts"() {
|
|
7162
|
+
"use strict";
|
|
7163
|
+
log4 = (...a) => process.stderr.write(`[SolonGate shield] ${a.map(String).join(" ")}
|
|
7164
|
+
`);
|
|
7165
|
+
DLP_PATTERNS = [
|
|
7166
|
+
{ name: "AWS access key", re: /AKIA[0-9A-Z]{16}/g },
|
|
7167
|
+
{ name: "private key block", re: /-----BEGIN [A-Z ]*PRIVATE KEY-----/g },
|
|
7168
|
+
{ name: "Anthropic key", re: /sk-ant-[A-Za-z0-9_-]{20,}/g },
|
|
7169
|
+
{ name: "OpenAI key", re: /sk-(proj-)?[A-Za-z0-9_-]{20,}/g },
|
|
7170
|
+
{ name: "GitHub token", re: /gh[pousr]_[A-Za-z0-9]{20,}/g },
|
|
7171
|
+
{ name: "GitHub fine-grained PAT", re: /github_pat_[A-Za-z0-9_]{20,}/g },
|
|
7172
|
+
{ name: "GitLab token", re: /glpat-[A-Za-z0-9_-]{20,}/g },
|
|
7173
|
+
{ name: "Slack token", re: /xox[baprs]-[A-Za-z0-9-]{10,}/g },
|
|
7174
|
+
{ name: "Google API key", re: /AIza[0-9A-Za-z_-]{35}/g },
|
|
7175
|
+
{ name: "Stripe key", re: /[sr]k_(live|test)_[A-Za-z0-9]{20,}/g },
|
|
7176
|
+
{ name: "SendGrid key", re: /SG\.[A-Za-z0-9_-]{16,}\.[A-Za-z0-9_-]{16,}/g },
|
|
7177
|
+
{ name: "Twilio key", re: /SK[0-9a-fA-F]{32}/g },
|
|
7178
|
+
{ name: "npm token", re: /npm_[A-Za-z0-9]{36}/g },
|
|
7179
|
+
{ name: "JWT", re: /eyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}/g },
|
|
7180
|
+
{ name: "Bearer token", re: /bearer\s+[A-Za-z0-9._-]{20,}/gi },
|
|
7181
|
+
{ name: "secret assignment", re: /(api[_-]?key|secret|token|password|passwd|access[_-]?key)["']?\s*[:=]\s*["']?[A-Za-z0-9/+_.-]{12,}/gi }
|
|
7182
|
+
];
|
|
7183
|
+
}
|
|
7184
|
+
});
|
|
7185
|
+
|
|
6928
7186
|
// src/inject.ts
|
|
6929
7187
|
var inject_exports = {};
|
|
6930
|
-
import { readFileSync as
|
|
6931
|
-
import { resolve as
|
|
7188
|
+
import { readFileSync as readFileSync7, writeFileSync as writeFileSync4, existsSync as existsSync6, copyFileSync } from "fs";
|
|
7189
|
+
import { resolve as resolve5 } from "path";
|
|
6932
7190
|
import { execSync } from "child_process";
|
|
6933
7191
|
function parseInjectArgs(argv) {
|
|
6934
7192
|
const args = argv.slice(2);
|
|
@@ -6985,9 +7243,9 @@ WHAT IT DOES
|
|
|
6985
7243
|
`);
|
|
6986
7244
|
}
|
|
6987
7245
|
function detectProject() {
|
|
6988
|
-
if (!
|
|
7246
|
+
if (!existsSync6(resolve5("package.json"))) return false;
|
|
6989
7247
|
try {
|
|
6990
|
-
const pkg = JSON.parse(
|
|
7248
|
+
const pkg = JSON.parse(readFileSync7(resolve5("package.json"), "utf-8"));
|
|
6991
7249
|
const allDeps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
6992
7250
|
return !!(allDeps["@modelcontextprotocol/sdk"] || allDeps["@modelcontextprotocol/server"]);
|
|
6993
7251
|
} catch {
|
|
@@ -6996,18 +7254,18 @@ function detectProject() {
|
|
|
6996
7254
|
}
|
|
6997
7255
|
function findTsEntryFile() {
|
|
6998
7256
|
try {
|
|
6999
|
-
const pkg = JSON.parse(
|
|
7257
|
+
const pkg = JSON.parse(readFileSync7(resolve5("package.json"), "utf-8"));
|
|
7000
7258
|
if (pkg.bin) {
|
|
7001
7259
|
const binPath = typeof pkg.bin === "string" ? pkg.bin : Object.values(pkg.bin)[0];
|
|
7002
7260
|
if (typeof binPath === "string") {
|
|
7003
7261
|
const srcPath = binPath.replace(/^\.\/dist\//, "./src/").replace(/\.js$/, ".ts");
|
|
7004
|
-
if (
|
|
7005
|
-
if (
|
|
7262
|
+
if (existsSync6(resolve5(srcPath))) return resolve5(srcPath);
|
|
7263
|
+
if (existsSync6(resolve5(binPath))) return resolve5(binPath);
|
|
7006
7264
|
}
|
|
7007
7265
|
}
|
|
7008
7266
|
if (pkg.main) {
|
|
7009
7267
|
const srcPath = pkg.main.replace(/^\.\/dist\//, "./src/").replace(/\.js$/, ".ts");
|
|
7010
|
-
if (
|
|
7268
|
+
if (existsSync6(resolve5(srcPath))) return resolve5(srcPath);
|
|
7011
7269
|
}
|
|
7012
7270
|
} catch {
|
|
7013
7271
|
}
|
|
@@ -7020,10 +7278,10 @@ function findTsEntryFile() {
|
|
|
7020
7278
|
"main.ts"
|
|
7021
7279
|
];
|
|
7022
7280
|
for (const c3 of candidates) {
|
|
7023
|
-
const full =
|
|
7024
|
-
if (
|
|
7281
|
+
const full = resolve5(c3);
|
|
7282
|
+
if (existsSync6(full)) {
|
|
7025
7283
|
try {
|
|
7026
|
-
const content =
|
|
7284
|
+
const content = readFileSync7(full, "utf-8");
|
|
7027
7285
|
if (content.includes("McpServer") || content.includes("McpServer")) {
|
|
7028
7286
|
return full;
|
|
7029
7287
|
}
|
|
@@ -7032,18 +7290,18 @@ function findTsEntryFile() {
|
|
|
7032
7290
|
}
|
|
7033
7291
|
}
|
|
7034
7292
|
for (const c3 of candidates) {
|
|
7035
|
-
if (
|
|
7293
|
+
if (existsSync6(resolve5(c3))) return resolve5(c3);
|
|
7036
7294
|
}
|
|
7037
7295
|
return null;
|
|
7038
7296
|
}
|
|
7039
7297
|
function detectPackageManager() {
|
|
7040
|
-
if (
|
|
7041
|
-
if (
|
|
7298
|
+
if (existsSync6(resolve5("pnpm-lock.yaml"))) return "pnpm";
|
|
7299
|
+
if (existsSync6(resolve5("yarn.lock"))) return "yarn";
|
|
7042
7300
|
return "npm";
|
|
7043
7301
|
}
|
|
7044
7302
|
function installSdk() {
|
|
7045
7303
|
try {
|
|
7046
|
-
const pkg = JSON.parse(
|
|
7304
|
+
const pkg = JSON.parse(readFileSync7(resolve5("package.json"), "utf-8"));
|
|
7047
7305
|
const allDeps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
7048
7306
|
if (allDeps["@solongate/proxy"]) {
|
|
7049
7307
|
log3(" @solongate/proxy already installed");
|
|
@@ -7064,7 +7322,7 @@ function installSdk() {
|
|
|
7064
7322
|
}
|
|
7065
7323
|
}
|
|
7066
7324
|
function injectTypeScript(filePath) {
|
|
7067
|
-
const original =
|
|
7325
|
+
const original = readFileSync7(filePath, "utf-8");
|
|
7068
7326
|
const changes = [];
|
|
7069
7327
|
let modified = original;
|
|
7070
7328
|
if (modified.includes("SecureMcpServer")) {
|
|
@@ -7180,8 +7438,8 @@ async function main2() {
|
|
|
7180
7438
|
process.exit(1);
|
|
7181
7439
|
}
|
|
7182
7440
|
log3(" Language: TypeScript");
|
|
7183
|
-
const entryFile = opts.file ?
|
|
7184
|
-
if (!entryFile || !
|
|
7441
|
+
const entryFile = opts.file ? resolve5(opts.file) : findTsEntryFile();
|
|
7442
|
+
if (!entryFile || !existsSync6(entryFile)) {
|
|
7185
7443
|
log3(` Could not find entry file.${opts.file ? ` File not found: ${opts.file}` : ""}`);
|
|
7186
7444
|
log3("");
|
|
7187
7445
|
log3(" Specify it manually: --file <path>");
|
|
@@ -7194,7 +7452,7 @@ async function main2() {
|
|
|
7194
7452
|
log3("");
|
|
7195
7453
|
const backupPath = entryFile + ".solongate-backup";
|
|
7196
7454
|
if (opts.restore) {
|
|
7197
|
-
if (!
|
|
7455
|
+
if (!existsSync6(backupPath)) {
|
|
7198
7456
|
log3(" No backup found. Nothing to restore.");
|
|
7199
7457
|
process.exit(1);
|
|
7200
7458
|
}
|
|
@@ -7230,7 +7488,7 @@ async function main2() {
|
|
|
7230
7488
|
log3(" To apply: npx @solongate/proxy inject");
|
|
7231
7489
|
process.exit(0);
|
|
7232
7490
|
}
|
|
7233
|
-
if (!
|
|
7491
|
+
if (!existsSync6(backupPath)) {
|
|
7234
7492
|
copyFileSync(entryFile, backupPath);
|
|
7235
7493
|
log3("");
|
|
7236
7494
|
log3(` Backup: ${backupPath}`);
|
|
@@ -7264,8 +7522,8 @@ var init_inject = __esm({
|
|
|
7264
7522
|
|
|
7265
7523
|
// src/create.ts
|
|
7266
7524
|
var create_exports = {};
|
|
7267
|
-
import { mkdirSync as mkdirSync5, writeFileSync as writeFileSync5, existsSync as
|
|
7268
|
-
import { resolve as
|
|
7525
|
+
import { mkdirSync as mkdirSync5, writeFileSync as writeFileSync5, existsSync as existsSync7 } from "fs";
|
|
7526
|
+
import { resolve as resolve6, join as join5 } from "path";
|
|
7269
7527
|
import { execSync as execSync2 } from "child_process";
|
|
7270
7528
|
function withSpinner(message, fn) {
|
|
7271
7529
|
const frames = ["\u28FE", "\u28FD", "\u28FB", "\u28BF", "\u287F", "\u28DF", "\u28EF", "\u28F7"];
|
|
@@ -7474,9 +7732,9 @@ dist/
|
|
|
7474
7732
|
}
|
|
7475
7733
|
async function main3() {
|
|
7476
7734
|
const opts = parseCreateArgs(process.argv);
|
|
7477
|
-
const dir =
|
|
7735
|
+
const dir = resolve6(opts.name);
|
|
7478
7736
|
printBanner("Create MCP Server");
|
|
7479
|
-
if (
|
|
7737
|
+
if (existsSync7(dir)) {
|
|
7480
7738
|
log3(` ${c.red}Error:${c.reset} Directory "${opts.name}" already exists.`);
|
|
7481
7739
|
process.exit(1);
|
|
7482
7740
|
}
|
|
@@ -7555,14 +7813,14 @@ var init_create = __esm({
|
|
|
7555
7813
|
|
|
7556
7814
|
// src/pull-push.ts
|
|
7557
7815
|
var pull_push_exports = {};
|
|
7558
|
-
import { readFileSync as
|
|
7559
|
-
import { resolve as
|
|
7816
|
+
import { readFileSync as readFileSync8, writeFileSync as writeFileSync6, existsSync as existsSync8 } from "fs";
|
|
7817
|
+
import { resolve as resolve7 } from "path";
|
|
7560
7818
|
function loadEnv() {
|
|
7561
7819
|
if (process.env.SOLONGATE_API_KEY) return;
|
|
7562
|
-
const envPath =
|
|
7563
|
-
if (!
|
|
7820
|
+
const envPath = resolve7(".env");
|
|
7821
|
+
if (!existsSync8(envPath)) return;
|
|
7564
7822
|
try {
|
|
7565
|
-
const content =
|
|
7823
|
+
const content = readFileSync8(envPath, "utf-8");
|
|
7566
7824
|
for (const line of content.split("\n")) {
|
|
7567
7825
|
const trimmed = line.trim();
|
|
7568
7826
|
if (!trimmed || trimmed.startsWith("#")) continue;
|
|
@@ -7604,20 +7862,20 @@ function parseCliArgs() {
|
|
|
7604
7862
|
}
|
|
7605
7863
|
}
|
|
7606
7864
|
if (!apiKey) {
|
|
7607
|
-
|
|
7608
|
-
|
|
7609
|
-
|
|
7610
|
-
|
|
7611
|
-
|
|
7612
|
-
|
|
7613
|
-
|
|
7865
|
+
log5(red("ERROR: API key not found."));
|
|
7866
|
+
log5("");
|
|
7867
|
+
log5("Set it in .env file:");
|
|
7868
|
+
log5(" SOLONGATE_API_KEY=sg_live_...");
|
|
7869
|
+
log5("");
|
|
7870
|
+
log5("Or pass via environment:");
|
|
7871
|
+
log5(` SOLONGATE_API_KEY=sg_live_... solongate-proxy ${command}`);
|
|
7614
7872
|
process.exit(1);
|
|
7615
7873
|
}
|
|
7616
7874
|
if (!apiKey.startsWith("sg_live_")) {
|
|
7617
|
-
|
|
7875
|
+
log5(red("ERROR: Pull/push/list requires a live API key (sg_live_...)."));
|
|
7618
7876
|
process.exit(1);
|
|
7619
7877
|
}
|
|
7620
|
-
return { command, apiKey, file:
|
|
7878
|
+
return { command, apiKey, file: resolve7(file), policyId };
|
|
7621
7879
|
}
|
|
7622
7880
|
async function listPolicies(apiKey) {
|
|
7623
7881
|
const res = await fetch(`${API_URL}/api/v1/policies`, {
|
|
@@ -7630,18 +7888,18 @@ async function listPolicies(apiKey) {
|
|
|
7630
7888
|
async function list(apiKey, policyId) {
|
|
7631
7889
|
const policies = await listPolicies(apiKey);
|
|
7632
7890
|
if (policies.length === 0) {
|
|
7633
|
-
|
|
7634
|
-
|
|
7891
|
+
log5(yellow("No policies found. Create one in the dashboard first."));
|
|
7892
|
+
log5(dim(" https://dashboard.solongate.com/policies"));
|
|
7635
7893
|
return;
|
|
7636
7894
|
}
|
|
7637
7895
|
if (policyId) {
|
|
7638
7896
|
const match = policies.find((p) => p.id === policyId);
|
|
7639
7897
|
if (!match) {
|
|
7640
|
-
|
|
7641
|
-
|
|
7642
|
-
|
|
7898
|
+
log5(red(`Policy not found: ${policyId}`));
|
|
7899
|
+
log5("");
|
|
7900
|
+
log5("Available policies:");
|
|
7643
7901
|
for (const p of policies) {
|
|
7644
|
-
|
|
7902
|
+
log5(` ${dim("\u2022")} ${p.id}`);
|
|
7645
7903
|
}
|
|
7646
7904
|
process.exit(1);
|
|
7647
7905
|
}
|
|
@@ -7649,10 +7907,10 @@ async function list(apiKey, policyId) {
|
|
|
7649
7907
|
printPolicyDetail(full);
|
|
7650
7908
|
return;
|
|
7651
7909
|
}
|
|
7652
|
-
|
|
7653
|
-
|
|
7654
|
-
|
|
7655
|
-
|
|
7910
|
+
log5("");
|
|
7911
|
+
log5(bold(` Policies (${policies.length})`));
|
|
7912
|
+
log5(dim(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
7913
|
+
log5("");
|
|
7656
7914
|
const fullPolicies = await Promise.all(
|
|
7657
7915
|
policies.map(
|
|
7658
7916
|
(p) => fetchCloudPolicy(apiKey, API_URL, p.id).then((full) => ({ policy: p, rules: full.rules })).catch(() => ({ policy: p, rules: [] }))
|
|
@@ -7661,136 +7919,136 @@ async function list(apiKey, policyId) {
|
|
|
7661
7919
|
for (const { policy, rules } of fullPolicies) {
|
|
7662
7920
|
printPolicySummary(policy, rules);
|
|
7663
7921
|
}
|
|
7664
|
-
|
|
7665
|
-
|
|
7666
|
-
|
|
7667
|
-
|
|
7668
|
-
|
|
7669
|
-
|
|
7922
|
+
log5(dim(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
7923
|
+
log5("");
|
|
7924
|
+
log5(` ${dim("View details:")} solongate-proxy list --policy-id <ID>`);
|
|
7925
|
+
log5(` ${dim("Pull policy:")} solongate-proxy pull --policy-id <ID>`);
|
|
7926
|
+
log5(` ${dim("Push policy:")} solongate-proxy push --policy-id <ID>`);
|
|
7927
|
+
log5("");
|
|
7670
7928
|
}
|
|
7671
7929
|
function printPolicySummary(p, rules) {
|
|
7672
7930
|
const ruleCount = rules.length;
|
|
7673
7931
|
const allowCount = rules.filter((r) => r.effect === "ALLOW").length;
|
|
7674
7932
|
const denyCount = rules.filter((r) => r.effect === "DENY").length;
|
|
7675
|
-
|
|
7676
|
-
|
|
7677
|
-
|
|
7933
|
+
log5(` ${cyan(p.id)}`);
|
|
7934
|
+
log5(` ${bold(p.name)} ${dim(`v${p.version ?? "?"}`)}`);
|
|
7935
|
+
log5(` ${dim("Rules:")} ${ruleCount} ${green(`${allowCount} ALLOW`)} ${red(`${denyCount} DENY`)}`);
|
|
7678
7936
|
if (p.created_at) {
|
|
7679
|
-
|
|
7937
|
+
log5(` ${dim("Updated:")} ${new Date(p.created_at).toLocaleString()}`);
|
|
7680
7938
|
}
|
|
7681
|
-
|
|
7939
|
+
log5("");
|
|
7682
7940
|
}
|
|
7683
7941
|
function printPolicyDetail(policy) {
|
|
7684
|
-
|
|
7685
|
-
|
|
7686
|
-
|
|
7687
|
-
|
|
7942
|
+
log5("");
|
|
7943
|
+
log5(bold(` ${policy.name}`));
|
|
7944
|
+
log5(` ${dim("ID:")} ${cyan(policy.id)} ${dim("Version:")} ${policy.version} ${dim("Rules:")} ${policy.rules.length}`);
|
|
7945
|
+
log5("");
|
|
7688
7946
|
if (policy.rules.length === 0) {
|
|
7689
|
-
|
|
7690
|
-
|
|
7947
|
+
log5(yellow(" No rules defined."));
|
|
7948
|
+
log5("");
|
|
7691
7949
|
return;
|
|
7692
7950
|
}
|
|
7693
|
-
|
|
7951
|
+
log5(dim(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
7694
7952
|
for (const rule of policy.rules) {
|
|
7695
7953
|
const effectColor = rule.effect === "ALLOW" ? green : red;
|
|
7696
|
-
|
|
7697
|
-
|
|
7954
|
+
log5("");
|
|
7955
|
+
log5(` ${effectColor(rule.effect.padEnd(5))} ${bold(rule.toolPattern)} ${dim(`P:${rule.priority}`)}`);
|
|
7698
7956
|
if (rule.description) {
|
|
7699
|
-
|
|
7957
|
+
log5(` ${dim(rule.description)}`);
|
|
7700
7958
|
}
|
|
7701
|
-
|
|
7959
|
+
log5(` ${dim(`${rule.permission} trust:${rule.minimumTrustLevel || "UNTRUSTED"}`)}`);
|
|
7702
7960
|
if (rule.pathConstraints) {
|
|
7703
7961
|
const pc = rule.pathConstraints;
|
|
7704
|
-
if (pc.rootDirectory)
|
|
7705
|
-
if (pc.allowed?.length)
|
|
7706
|
-
if (pc.denied?.length)
|
|
7962
|
+
if (pc.rootDirectory) log5(` ${magenta("ROOT")} ${pc.rootDirectory}`);
|
|
7963
|
+
if (pc.allowed?.length) log5(` ${green("PATHS")} ${pc.allowed.join(", ")}`);
|
|
7964
|
+
if (pc.denied?.length) log5(` ${red("DENY")} ${pc.denied.join(", ")}`);
|
|
7707
7965
|
}
|
|
7708
7966
|
if (rule.commandConstraints) {
|
|
7709
7967
|
const cc = rule.commandConstraints;
|
|
7710
|
-
if (cc.allowed?.length)
|
|
7711
|
-
if (cc.denied?.length)
|
|
7968
|
+
if (cc.allowed?.length) log5(` ${green("CMDS")} ${cc.allowed.join(", ")}`);
|
|
7969
|
+
if (cc.denied?.length) log5(` ${red("DENY")} ${cc.denied.join(", ")}`);
|
|
7712
7970
|
}
|
|
7713
7971
|
if (rule.filenameConstraints) {
|
|
7714
7972
|
const fc = rule.filenameConstraints;
|
|
7715
|
-
if (fc.allowed?.length)
|
|
7716
|
-
if (fc.denied?.length)
|
|
7973
|
+
if (fc.allowed?.length) log5(` ${green("FILES")} ${fc.allowed.join(", ")}`);
|
|
7974
|
+
if (fc.denied?.length) log5(` ${red("DENY")} ${fc.denied.join(", ")}`);
|
|
7717
7975
|
}
|
|
7718
7976
|
if (rule.urlConstraints) {
|
|
7719
7977
|
const uc = rule.urlConstraints;
|
|
7720
|
-
if (uc.allowed?.length)
|
|
7721
|
-
if (uc.denied?.length)
|
|
7978
|
+
if (uc.allowed?.length) log5(` ${green("URLS")} ${uc.allowed.join(", ")}`);
|
|
7979
|
+
if (uc.denied?.length) log5(` ${red("DENY")} ${uc.denied.join(", ")}`);
|
|
7722
7980
|
}
|
|
7723
7981
|
}
|
|
7724
|
-
|
|
7725
|
-
|
|
7726
|
-
|
|
7982
|
+
log5("");
|
|
7983
|
+
log5(dim(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
7984
|
+
log5("");
|
|
7727
7985
|
}
|
|
7728
7986
|
async function pull(apiKey, file, policyId) {
|
|
7729
7987
|
if (!policyId) {
|
|
7730
7988
|
const policies = await listPolicies(apiKey);
|
|
7731
7989
|
if (policies.length === 0) {
|
|
7732
|
-
|
|
7990
|
+
log5(red("No policies found. Create one in the dashboard first."));
|
|
7733
7991
|
process.exit(1);
|
|
7734
7992
|
}
|
|
7735
7993
|
if (policies.length === 1) {
|
|
7736
7994
|
policyId = policies[0].id;
|
|
7737
|
-
|
|
7995
|
+
log5(dim(`Auto-selecting only policy: ${policyId}`));
|
|
7738
7996
|
} else {
|
|
7739
|
-
|
|
7740
|
-
|
|
7997
|
+
log5(yellow(`Found ${policies.length} policies:`));
|
|
7998
|
+
log5("");
|
|
7741
7999
|
for (const p of policies) {
|
|
7742
|
-
|
|
8000
|
+
log5(` ${cyan(p.id)} ${p.name} ${dim(`v${p.version ?? "?"}`)}`);
|
|
7743
8001
|
}
|
|
7744
|
-
|
|
7745
|
-
|
|
8002
|
+
log5("");
|
|
8003
|
+
log5("Use --policy-id <ID> to specify which one to pull.");
|
|
7746
8004
|
process.exit(1);
|
|
7747
8005
|
}
|
|
7748
8006
|
}
|
|
7749
|
-
|
|
8007
|
+
log5(`Pulling ${cyan(policyId)} from dashboard...`);
|
|
7750
8008
|
const policy = await fetchCloudPolicy(apiKey, API_URL, policyId);
|
|
7751
8009
|
const { id: _id, ...policyWithoutId } = policy;
|
|
7752
8010
|
const json = JSON.stringify(policyWithoutId, null, 2) + "\n";
|
|
7753
8011
|
writeFileSync6(file, json, "utf-8");
|
|
7754
|
-
|
|
7755
|
-
|
|
7756
|
-
|
|
7757
|
-
|
|
7758
|
-
|
|
7759
|
-
|
|
7760
|
-
|
|
7761
|
-
|
|
7762
|
-
|
|
8012
|
+
log5("");
|
|
8013
|
+
log5(green(" Saved to: ") + file);
|
|
8014
|
+
log5(` ${dim("Name:")} ${policy.name}`);
|
|
8015
|
+
log5(` ${dim("Version:")} ${policy.version}`);
|
|
8016
|
+
log5(` ${dim("Rules:")} ${policy.rules.length}`);
|
|
8017
|
+
log5("");
|
|
8018
|
+
log5(dim("The policy file does not contain an ID."));
|
|
8019
|
+
log5(dim("Use --policy-id to specify the target when pushing/pulling."));
|
|
8020
|
+
log5("");
|
|
7763
8021
|
}
|
|
7764
8022
|
async function push(apiKey, file, policyId) {
|
|
7765
|
-
if (!
|
|
7766
|
-
|
|
8023
|
+
if (!existsSync8(file)) {
|
|
8024
|
+
log5(red(`ERROR: File not found: ${file}`));
|
|
7767
8025
|
process.exit(1);
|
|
7768
8026
|
}
|
|
7769
8027
|
if (!policyId) {
|
|
7770
|
-
|
|
7771
|
-
|
|
7772
|
-
|
|
7773
|
-
|
|
7774
|
-
|
|
7775
|
-
|
|
7776
|
-
|
|
7777
|
-
|
|
7778
|
-
|
|
7779
|
-
|
|
8028
|
+
log5(red("ERROR: --policy-id is required for push."));
|
|
8029
|
+
log5("");
|
|
8030
|
+
log5("This determines which cloud policy to update.");
|
|
8031
|
+
log5("");
|
|
8032
|
+
log5("Usage:");
|
|
8033
|
+
log5(" solongate-proxy push --policy-id my-policy");
|
|
8034
|
+
log5(" solongate-proxy push --policy-id my-policy --file custom.json");
|
|
8035
|
+
log5("");
|
|
8036
|
+
log5("List your policies:");
|
|
8037
|
+
log5(" solongate-proxy list");
|
|
7780
8038
|
process.exit(1);
|
|
7781
8039
|
}
|
|
7782
|
-
const content =
|
|
8040
|
+
const content = readFileSync8(file, "utf-8");
|
|
7783
8041
|
let policy;
|
|
7784
8042
|
try {
|
|
7785
8043
|
policy = JSON.parse(content);
|
|
7786
8044
|
} catch {
|
|
7787
|
-
|
|
8045
|
+
log5(red(`ERROR: Invalid JSON in ${file}`));
|
|
7788
8046
|
process.exit(1);
|
|
7789
8047
|
}
|
|
7790
|
-
|
|
7791
|
-
|
|
7792
|
-
|
|
7793
|
-
|
|
8048
|
+
log5(`Pushing to ${cyan(policyId)}...`);
|
|
8049
|
+
log5(` ${dim("File:")} ${file}`);
|
|
8050
|
+
log5(` ${dim("Name:")} ${policy.name || "Unnamed"}`);
|
|
8051
|
+
log5(` ${dim("Rules:")} ${(policy.rules || []).length}`);
|
|
7794
8052
|
const checkRes = await fetch(`${API_URL}/api/v1/policies/${policyId}`, {
|
|
7795
8053
|
headers: { "Authorization": `Bearer ${apiKey}` }
|
|
7796
8054
|
});
|
|
@@ -7812,15 +8070,15 @@ async function push(apiKey, file, policyId) {
|
|
|
7812
8070
|
});
|
|
7813
8071
|
if (!res.ok) {
|
|
7814
8072
|
const body = await res.text().catch(() => "");
|
|
7815
|
-
|
|
8073
|
+
log5(red(`ERROR: Push failed (${res.status}): ${body}`));
|
|
7816
8074
|
process.exit(1);
|
|
7817
8075
|
}
|
|
7818
8076
|
const data = await res.json();
|
|
7819
|
-
|
|
7820
|
-
|
|
7821
|
-
|
|
7822
|
-
|
|
7823
|
-
|
|
8077
|
+
log5("");
|
|
8078
|
+
log5(green(` Pushed to cloud: v${data._version ?? "created"}`));
|
|
8079
|
+
log5(` ${dim("Policy ID:")} ${policyId}`);
|
|
8080
|
+
log5(` ${dim("Method:")} ${method === "PUT" ? "Updated existing" : "Created new"}`);
|
|
8081
|
+
log5("");
|
|
7824
8082
|
}
|
|
7825
8083
|
async function main4() {
|
|
7826
8084
|
const { command, apiKey, file, policyId } = parseCliArgs();
|
|
@@ -7832,32 +8090,32 @@ async function main4() {
|
|
|
7832
8090
|
} else if (command === "list" || command === "ls") {
|
|
7833
8091
|
await list(apiKey, policyId);
|
|
7834
8092
|
} else {
|
|
7835
|
-
|
|
7836
|
-
|
|
7837
|
-
|
|
7838
|
-
|
|
7839
|
-
|
|
7840
|
-
|
|
7841
|
-
|
|
7842
|
-
|
|
7843
|
-
|
|
7844
|
-
|
|
7845
|
-
|
|
7846
|
-
|
|
7847
|
-
|
|
8093
|
+
log5(red(`Unknown command: ${command}`));
|
|
8094
|
+
log5("");
|
|
8095
|
+
log5(bold("Usage:"));
|
|
8096
|
+
log5(" solongate-proxy list List all policies");
|
|
8097
|
+
log5(" solongate-proxy list --policy-id <ID> Show policy details");
|
|
8098
|
+
log5(" solongate-proxy pull --policy-id <ID> Pull policy to local file");
|
|
8099
|
+
log5(" solongate-proxy push --policy-id <ID> Push local file to cloud");
|
|
8100
|
+
log5("");
|
|
8101
|
+
log5(bold("Flags:"));
|
|
8102
|
+
log5(" --policy-id, --id <ID> Cloud policy ID (required for push)");
|
|
8103
|
+
log5(" --file, -f <path> Local file path (default: policy.json)");
|
|
8104
|
+
log5(" --api-key <key> API key (or set SOLONGATE_API_KEY)");
|
|
8105
|
+
log5("");
|
|
7848
8106
|
process.exit(1);
|
|
7849
8107
|
}
|
|
7850
8108
|
} catch (err) {
|
|
7851
|
-
|
|
8109
|
+
log5(red(`ERROR: ${err instanceof Error ? err.message : String(err)}`));
|
|
7852
8110
|
process.exit(1);
|
|
7853
8111
|
}
|
|
7854
8112
|
}
|
|
7855
|
-
var
|
|
8113
|
+
var log5, dim, bold, green, red, yellow, cyan, magenta, API_URL;
|
|
7856
8114
|
var init_pull_push = __esm({
|
|
7857
8115
|
"src/pull-push.ts"() {
|
|
7858
8116
|
"use strict";
|
|
7859
8117
|
init_config();
|
|
7860
|
-
|
|
8118
|
+
log5 = (...args) => process.stderr.write(`${args.map(String).join(" ")}
|
|
7861
8119
|
`);
|
|
7862
8120
|
dim = (s) => `\x1B[2m${s}\x1B[0m`;
|
|
7863
8121
|
bold = (s) => `\x1B[1m${s}\x1B[0m`;
|
|
@@ -10296,7 +10554,7 @@ var Mutex = class {
|
|
|
10296
10554
|
this.locked = true;
|
|
10297
10555
|
return;
|
|
10298
10556
|
}
|
|
10299
|
-
return new Promise((
|
|
10557
|
+
return new Promise((resolve8, reject) => {
|
|
10300
10558
|
const timer = setTimeout(() => {
|
|
10301
10559
|
const idx = this.queue.indexOf(onReady);
|
|
10302
10560
|
if (idx !== -1) this.queue.splice(idx, 1);
|
|
@@ -10304,7 +10562,7 @@ var Mutex = class {
|
|
|
10304
10562
|
}, timeoutMs);
|
|
10305
10563
|
const onReady = () => {
|
|
10306
10564
|
clearTimeout(timer);
|
|
10307
|
-
|
|
10565
|
+
resolve8();
|
|
10308
10566
|
};
|
|
10309
10567
|
this.queue.push(onReady);
|
|
10310
10568
|
});
|
|
@@ -10924,7 +11182,7 @@ ${msg.content.text}`;
|
|
|
10924
11182
|
|
|
10925
11183
|
// src/index.ts
|
|
10926
11184
|
init_cli_utils();
|
|
10927
|
-
var CLI_SUBCOMMANDS = /* @__PURE__ */ new Set(["login", "logout", "create", "inject", "pull", "push", "list", "ls"]);
|
|
11185
|
+
var CLI_SUBCOMMANDS = /* @__PURE__ */ new Set(["login", "logout", "shield", "create", "inject", "pull", "push", "list", "ls"]);
|
|
10928
11186
|
var IS_HUMAN_CLI = process.argv.length <= 2 || CLI_SUBCOMMANDS.has(process.argv[2] ?? "");
|
|
10929
11187
|
if (!IS_HUMAN_CLI) {
|
|
10930
11188
|
console.log = (...args) => {
|
|
@@ -10968,6 +11226,11 @@ async function main5() {
|
|
|
10968
11226
|
runGlobalRestore2();
|
|
10969
11227
|
return;
|
|
10970
11228
|
}
|
|
11229
|
+
if (subcommand === "shield") {
|
|
11230
|
+
const { runShield: runShield2 } = await Promise.resolve().then(() => (init_shield(), shield_exports));
|
|
11231
|
+
await runShield2();
|
|
11232
|
+
return;
|
|
11233
|
+
}
|
|
10971
11234
|
if (subcommand === "inject") {
|
|
10972
11235
|
process.argv.splice(2, 1);
|
|
10973
11236
|
await Promise.resolve().then(() => (init_inject(), inject_exports));
|