@solongate/proxy 0.1.24 → 0.1.25
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/index.js +97 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -3084,6 +3084,7 @@ var SolonGate = class {
|
|
|
3084
3084
|
});
|
|
3085
3085
|
if (!options.policySet && !config.policySet && apiKey.startsWith("sg_live_")) {
|
|
3086
3086
|
this.fetchCloudPolicyOnce();
|
|
3087
|
+
this.startPolicyPolling();
|
|
3087
3088
|
}
|
|
3088
3089
|
this.tokenIssuer = config.tokenSecret ? new TokenIssuer({
|
|
3089
3090
|
secret: config.tokenSecret,
|
|
@@ -3153,6 +3154,40 @@ var SolonGate = class {
|
|
|
3153
3154
|
}).catch(() => {
|
|
3154
3155
|
});
|
|
3155
3156
|
}
|
|
3157
|
+
/**
|
|
3158
|
+
* Poll for policy updates from dashboard every 60 seconds.
|
|
3159
|
+
*/
|
|
3160
|
+
startPolicyPolling() {
|
|
3161
|
+
const apiUrl = this.config.apiUrl ?? "https://api.solongate.com";
|
|
3162
|
+
let currentVersion = 0;
|
|
3163
|
+
setInterval(async () => {
|
|
3164
|
+
try {
|
|
3165
|
+
const res = await fetch(`${apiUrl}/api/v1/policies/default`, {
|
|
3166
|
+
headers: { "Authorization": `Bearer ${this.apiKey}` },
|
|
3167
|
+
signal: AbortSignal.timeout(1e4)
|
|
3168
|
+
});
|
|
3169
|
+
if (!res.ok) return;
|
|
3170
|
+
const data = await res.json();
|
|
3171
|
+
const version = Number(data._version ?? 0);
|
|
3172
|
+
const rulesCount = Array.isArray(data.rules) ? data.rules.length : 0;
|
|
3173
|
+
if (version !== currentVersion && version > 0) {
|
|
3174
|
+
const policySet = {
|
|
3175
|
+
id: String(data.id ?? "cloud"),
|
|
3176
|
+
name: String(data.name ?? "Cloud Policy"),
|
|
3177
|
+
description: String(data.description ?? ""),
|
|
3178
|
+
version,
|
|
3179
|
+
rules: data.rules ?? [],
|
|
3180
|
+
createdAt: String(data._created_at ?? ""),
|
|
3181
|
+
updatedAt: ""
|
|
3182
|
+
};
|
|
3183
|
+
this.policyEngine.loadPolicySet(policySet);
|
|
3184
|
+
currentVersion = version;
|
|
3185
|
+
console.warn(`[SolonGate] Policy updated from dashboard: ${policySet.name} v${version} (${rulesCount} rules)`);
|
|
3186
|
+
}
|
|
3187
|
+
} catch {
|
|
3188
|
+
}
|
|
3189
|
+
}, 6e4);
|
|
3190
|
+
}
|
|
3156
3191
|
/**
|
|
3157
3192
|
* Send audit log to SolonGate Cloud API (fire-and-forget).
|
|
3158
3193
|
*/
|
|
@@ -3327,6 +3362,7 @@ var SolonGateProxy = class {
|
|
|
3327
3362
|
}
|
|
3328
3363
|
}
|
|
3329
3364
|
}
|
|
3365
|
+
this.gate.loadPolicy(this.config.policy);
|
|
3330
3366
|
log(`Policy: ${this.config.policy.name} (${this.config.policy.rules.length} rules)`);
|
|
3331
3367
|
const transport = this.config.upstream.transport ?? "stdio";
|
|
3332
3368
|
if (transport === "stdio") {
|
|
@@ -3336,8 +3372,10 @@ var SolonGateProxy = class {
|
|
|
3336
3372
|
}
|
|
3337
3373
|
await this.connectUpstream();
|
|
3338
3374
|
await this.discoverTools();
|
|
3375
|
+
this.registerToolsToCloud();
|
|
3339
3376
|
this.createServer();
|
|
3340
3377
|
await this.serve();
|
|
3378
|
+
this.startPolicyPolling();
|
|
3341
3379
|
}
|
|
3342
3380
|
/**
|
|
3343
3381
|
* Connect to the upstream MCP server.
|
|
@@ -3497,6 +3535,65 @@ var SolonGateProxy = class {
|
|
|
3497
3535
|
});
|
|
3498
3536
|
});
|
|
3499
3537
|
}
|
|
3538
|
+
/**
|
|
3539
|
+
* Register discovered tools to the SolonGate Cloud API.
|
|
3540
|
+
* This makes tools visible on the Dashboard (/tools page).
|
|
3541
|
+
*/
|
|
3542
|
+
registerToolsToCloud() {
|
|
3543
|
+
if (!this.config.apiKey || this.config.apiKey.startsWith("sg_test_")) return;
|
|
3544
|
+
const apiUrl = this.config.apiUrl ?? "https://api.solongate.com";
|
|
3545
|
+
for (const tool of this.upstreamTools) {
|
|
3546
|
+
fetch(`${apiUrl}/api/v1/tools`, {
|
|
3547
|
+
method: "POST",
|
|
3548
|
+
headers: {
|
|
3549
|
+
"Authorization": `Bearer ${this.config.apiKey}`,
|
|
3550
|
+
"Content-Type": "application/json"
|
|
3551
|
+
},
|
|
3552
|
+
body: JSON.stringify({
|
|
3553
|
+
name: tool.name,
|
|
3554
|
+
description: tool.description ?? "",
|
|
3555
|
+
input_schema: tool.inputSchema,
|
|
3556
|
+
permissions: this.guessPermissions(tool.name),
|
|
3557
|
+
enabled: true
|
|
3558
|
+
})
|
|
3559
|
+
}).catch(() => {
|
|
3560
|
+
});
|
|
3561
|
+
}
|
|
3562
|
+
log(`Registered ${this.upstreamTools.length} tools to dashboard`);
|
|
3563
|
+
}
|
|
3564
|
+
/**
|
|
3565
|
+
* Guess tool permissions from tool name.
|
|
3566
|
+
*/
|
|
3567
|
+
guessPermissions(toolName) {
|
|
3568
|
+
const name = toolName.toLowerCase();
|
|
3569
|
+
if (name.includes("exec") || name.includes("shell") || name.includes("run") || name.includes("eval")) {
|
|
3570
|
+
return ["EXECUTE"];
|
|
3571
|
+
}
|
|
3572
|
+
if (name.includes("write") || name.includes("create") || name.includes("delete") || name.includes("update") || name.includes("set")) {
|
|
3573
|
+
return ["WRITE"];
|
|
3574
|
+
}
|
|
3575
|
+
return ["READ"];
|
|
3576
|
+
}
|
|
3577
|
+
/**
|
|
3578
|
+
* Poll for policy updates from dashboard every 60 seconds.
|
|
3579
|
+
* When user changes policy in dashboard, proxy picks it up automatically.
|
|
3580
|
+
*/
|
|
3581
|
+
startPolicyPolling() {
|
|
3582
|
+
if (!this.config.apiKey || this.config.apiKey.startsWith("sg_test_")) return;
|
|
3583
|
+
const apiUrl = this.config.apiUrl ?? "https://api.solongate.com";
|
|
3584
|
+
const POLL_INTERVAL = 6e4;
|
|
3585
|
+
setInterval(async () => {
|
|
3586
|
+
try {
|
|
3587
|
+
const newPolicy = await fetchCloudPolicy(this.config.apiKey, apiUrl);
|
|
3588
|
+
if (newPolicy.version !== this.config.policy.version || newPolicy.rules.length !== this.config.policy.rules.length) {
|
|
3589
|
+
this.config.policy = newPolicy;
|
|
3590
|
+
this.gate.loadPolicy(newPolicy);
|
|
3591
|
+
log(`Policy updated from dashboard: ${newPolicy.name} v${newPolicy.version} (${newPolicy.rules.length} rules)`);
|
|
3592
|
+
}
|
|
3593
|
+
} catch {
|
|
3594
|
+
}
|
|
3595
|
+
}, POLL_INTERVAL);
|
|
3596
|
+
}
|
|
3500
3597
|
/**
|
|
3501
3598
|
* Start serving downstream.
|
|
3502
3599
|
* If --port is set, serves via StreamableHTTP on that port.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@solongate/proxy",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.25",
|
|
4
4
|
"description": "MCP security proxy \u00e2\u20ac\u201d protect any MCP server with policies, input validation, rate limiting, and audit logging. Zero code changes required.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|