@solongate/proxy 0.1.15 → 0.1.17

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 CHANGED
@@ -278,6 +278,35 @@ async function main() {
278
278
  console.error(" \u2502 To undo: solongate-init --restore \u2502");
279
279
  console.error(" \u2514\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\u2500\u2518");
280
280
  console.error("");
281
+ const envPath = resolve2(".env");
282
+ if (!existsSync2(envPath)) {
283
+ const envContent = `# SolonGate API Keys
284
+ # Get your keys from the dashboard: https://solongate.com
285
+ # IMPORTANT: Never commit this file to git!
286
+
287
+ # Live key \u2014 enables cloud policy sync + audit logging to dashboard
288
+ SOLONGATE_API_KEY=sg_live_your_key_here
289
+
290
+ # Test key \u2014 local-only, no cloud connection (for development)
291
+ # SOLONGATE_API_KEY=sg_test_your_key_here
292
+ `;
293
+ writeFileSync(envPath, envContent);
294
+ console.error(` Created .env with placeholder API keys`);
295
+ console.error(` \u2192 Edit .env and replace with your real keys from https://solongate.com`);
296
+ console.error("");
297
+ }
298
+ const gitignorePath = resolve2(".gitignore");
299
+ if (existsSync2(gitignorePath)) {
300
+ const gitignore = readFileSync2(gitignorePath, "utf-8");
301
+ if (!gitignore.includes(".env")) {
302
+ writeFileSync(gitignorePath, gitignore.trimEnd() + "\n.env\n.env.local\n");
303
+ console.error(` Added .env to .gitignore`);
304
+ }
305
+ } else {
306
+ writeFileSync(gitignorePath, ".env\n.env.local\nnode_modules/\n");
307
+ console.error(` Created .gitignore (with .env excluded)`);
308
+ }
309
+ console.error("");
281
310
  for (const name of toProtect) {
282
311
  console.error(` \u2713 ${name} \u2014 protected (${options.policy})`);
283
312
  }
@@ -3149,35 +3178,41 @@ var SolonGateProxy = class {
3149
3178
  log("Starting SolonGate Proxy...");
3150
3179
  const apiUrl = this.config.apiUrl ?? "https://api.solongate.com";
3151
3180
  if (this.config.apiKey) {
3152
- log(`Validating license with ${apiUrl}...`);
3153
- try {
3154
- const res = await fetch(`${apiUrl}/api/v1/auth/me`, {
3155
- headers: {
3156
- "X-API-Key": this.config.apiKey,
3157
- "Authorization": `Bearer ${this.config.apiKey}`
3158
- },
3159
- signal: AbortSignal.timeout(1e4)
3160
- });
3161
- if (res.status === 401) {
3162
- log("ERROR: Invalid or expired API key.");
3163
- process.exit(1);
3164
- }
3165
- if (res.status === 403) {
3166
- log("ERROR: Your subscription is inactive. Renew at https://solongate.com");
3181
+ if (this.config.apiKey.startsWith("sg_test_")) {
3182
+ log("Using test API key \u2014 skipping online validation.");
3183
+ } else {
3184
+ log(`Validating license with ${apiUrl}...`);
3185
+ try {
3186
+ const res = await fetch(`${apiUrl}/api/v1/auth/me`, {
3187
+ headers: {
3188
+ "X-API-Key": this.config.apiKey,
3189
+ "Authorization": `Bearer ${this.config.apiKey}`
3190
+ },
3191
+ signal: AbortSignal.timeout(1e4)
3192
+ });
3193
+ if (res.status === 401) {
3194
+ log("ERROR: Invalid or expired API key.");
3195
+ process.exit(1);
3196
+ }
3197
+ if (res.status === 403) {
3198
+ log("ERROR: Your subscription is inactive. Renew at https://solongate.com");
3199
+ process.exit(1);
3200
+ }
3201
+ log("License validated.");
3202
+ } catch (err) {
3203
+ log(`ERROR: Unable to reach SolonGate license server. Check your internet connection.`);
3204
+ log(`Details: ${err instanceof Error ? err.message : String(err)}`);
3167
3205
  process.exit(1);
3168
3206
  }
3169
- log("License validated.");
3170
- } catch (err) {
3171
- log(`ERROR: Unable to reach SolonGate license server. Check your internet connection.`);
3172
- log(`Details: ${err instanceof Error ? err.message : String(err)}`);
3173
- process.exit(1);
3174
3207
  }
3175
- try {
3176
- const cloudPolicy = await fetchCloudPolicy(this.config.apiKey, apiUrl);
3177
- this.config.policy = cloudPolicy;
3178
- log(`Loaded cloud policy: ${cloudPolicy.name} (${cloudPolicy.rules.length} rules)`);
3179
- } catch (err) {
3180
- log(`Cloud policy fetch failed, using local policy: ${err instanceof Error ? err.message : String(err)}`);
3208
+ if (!this.config.apiKey.startsWith("sg_test_")) {
3209
+ try {
3210
+ const cloudPolicy = await fetchCloudPolicy(this.config.apiKey, apiUrl);
3211
+ this.config.policy = cloudPolicy;
3212
+ log(`Loaded cloud policy: ${cloudPolicy.name} (${cloudPolicy.rules.length} rules)`);
3213
+ } catch (err) {
3214
+ log(`Cloud policy fetch failed, using local policy: ${err instanceof Error ? err.message : String(err)}`);
3215
+ }
3181
3216
  }
3182
3217
  }
3183
3218
  log(`Policy: ${this.config.policy.name} (${this.config.policy.rules.length} rules)`);
@@ -3296,7 +3331,7 @@ var SolonGateProxy = class {
3296
3331
  const decision = result.isError ? "DENY" : "ALLOW";
3297
3332
  const evaluationTimeMs = Date.now() - startTime;
3298
3333
  log(`Result: ${decision} (${evaluationTimeMs}ms)`);
3299
- if (this.config.apiKey) {
3334
+ if (this.config.apiKey && !this.config.apiKey.startsWith("sg_test_")) {
3300
3335
  const apiUrl = this.config.apiUrl ?? "https://api.solongate.com";
3301
3336
  sendAuditLog(this.config.apiKey, apiUrl, {
3302
3337
  tool: name,
package/dist/init.js CHANGED
@@ -280,6 +280,35 @@ async function main() {
280
280
  console.error(" \u2502 To undo: solongate-init --restore \u2502");
281
281
  console.error(" \u2514\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\u2500\u2518");
282
282
  console.error("");
283
+ const envPath = resolve(".env");
284
+ if (!existsSync(envPath)) {
285
+ const envContent = `# SolonGate API Keys
286
+ # Get your keys from the dashboard: https://solongate.com
287
+ # IMPORTANT: Never commit this file to git!
288
+
289
+ # Live key \u2014 enables cloud policy sync + audit logging to dashboard
290
+ SOLONGATE_API_KEY=sg_live_your_key_here
291
+
292
+ # Test key \u2014 local-only, no cloud connection (for development)
293
+ # SOLONGATE_API_KEY=sg_test_your_key_here
294
+ `;
295
+ writeFileSync(envPath, envContent);
296
+ console.error(` Created .env with placeholder API keys`);
297
+ console.error(` \u2192 Edit .env and replace with your real keys from https://solongate.com`);
298
+ console.error("");
299
+ }
300
+ const gitignorePath = resolve(".gitignore");
301
+ if (existsSync(gitignorePath)) {
302
+ const gitignore = readFileSync(gitignorePath, "utf-8");
303
+ if (!gitignore.includes(".env")) {
304
+ writeFileSync(gitignorePath, gitignore.trimEnd() + "\n.env\n.env.local\n");
305
+ console.error(` Added .env to .gitignore`);
306
+ }
307
+ } else {
308
+ writeFileSync(gitignorePath, ".env\n.env.local\nnode_modules/\n");
309
+ console.error(` Created .gitignore (with .env excluded)`);
310
+ }
311
+ console.error("");
283
312
  for (const name of toProtect) {
284
313
  console.error(` \u2713 ${name} \u2014 protected (${options.policy})`);
285
314
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@solongate/proxy",
3
- "version": "0.1.15",
4
- "description": "MCP security proxy protect any MCP server with policies, input validation, rate limiting, and audit logging. Zero code changes required.",
3
+ "version": "0.1.17",
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": {
7
7
  "solongate-proxy": "./dist/index.js",