@sovr/engine 3.0.0 → 3.2.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/index.d.mts CHANGED
@@ -151,34 +151,6 @@ interface AuditEvent {
151
151
  * Users can extend or override these.
152
152
  */
153
153
  declare const DEFAULT_RULES: PolicyRule[];
154
- /**
155
- * The SOVR Policy Engine.
156
- *
157
- * Evaluates actions from any proxy channel against a unified rule set.
158
- * All four proxy types (MCP, HTTP, SQL, Exec) feed into this same engine.
159
- *
160
- * @example
161
- * ```ts
162
- * import { PolicyEngine, DEFAULT_RULES } from '@sovr/engine';
163
- *
164
- * const engine = new PolicyEngine({
165
- * rules: DEFAULT_RULES,
166
- * audit_log: true,
167
- * on_audit: (event) => console.log(event),
168
- * });
169
- *
170
- * const result = engine.evaluate({
171
- * channel: 'http',
172
- * action: 'POST',
173
- * resource: 'api.stripe.com/v1/charges',
174
- * context: { method: 'POST', host: 'api.stripe.com', url: '...', path: '/v1/charges' },
175
- * });
176
- *
177
- * if (!result.allowed) {
178
- * console.log(`Blocked: ${result.reason}`);
179
- * }
180
- * ```
181
- */
182
154
  type EngineTier = 'free' | 'personal' | 'starter' | 'pro' | 'enterprise';
183
155
  interface EngineTierLimits {
184
156
  evaluationsPerMonth: number;
@@ -191,9 +163,14 @@ declare class PolicyEngine {
191
163
  private onAudit?;
192
164
  private _tier;
193
165
  private _usage;
166
+ private _apiKey;
167
+ private _versionChecked;
194
168
  constructor(config: EngineConfig & {
195
169
  tier?: EngineTier;
170
+ apiKey?: string;
196
171
  });
172
+ /** v3.1.0: Async version check — blocks evaluate() on first call if deprecated */
173
+ private _asyncVersionCheck;
197
174
  /** Set the current tier (e.g., after API key verification) */
198
175
  setTier(tier: EngineTier): void;
199
176
  /** Get current tier */
package/dist/index.d.ts CHANGED
@@ -151,34 +151,6 @@ interface AuditEvent {
151
151
  * Users can extend or override these.
152
152
  */
153
153
  declare const DEFAULT_RULES: PolicyRule[];
154
- /**
155
- * The SOVR Policy Engine.
156
- *
157
- * Evaluates actions from any proxy channel against a unified rule set.
158
- * All four proxy types (MCP, HTTP, SQL, Exec) feed into this same engine.
159
- *
160
- * @example
161
- * ```ts
162
- * import { PolicyEngine, DEFAULT_RULES } from '@sovr/engine';
163
- *
164
- * const engine = new PolicyEngine({
165
- * rules: DEFAULT_RULES,
166
- * audit_log: true,
167
- * on_audit: (event) => console.log(event),
168
- * });
169
- *
170
- * const result = engine.evaluate({
171
- * channel: 'http',
172
- * action: 'POST',
173
- * resource: 'api.stripe.com/v1/charges',
174
- * context: { method: 'POST', host: 'api.stripe.com', url: '...', path: '/v1/charges' },
175
- * });
176
- *
177
- * if (!result.allowed) {
178
- * console.log(`Blocked: ${result.reason}`);
179
- * }
180
- * ```
181
- */
182
154
  type EngineTier = 'free' | 'personal' | 'starter' | 'pro' | 'enterprise';
183
155
  interface EngineTierLimits {
184
156
  evaluationsPerMonth: number;
@@ -191,9 +163,14 @@ declare class PolicyEngine {
191
163
  private onAudit?;
192
164
  private _tier;
193
165
  private _usage;
166
+ private _apiKey;
167
+ private _versionChecked;
194
168
  constructor(config: EngineConfig & {
195
169
  tier?: EngineTier;
170
+ apiKey?: string;
196
171
  });
172
+ /** v3.1.0: Async version check — blocks evaluate() on first call if deprecated */
173
+ private _asyncVersionCheck;
197
174
  /** Set the current tier (e.g., after API key verification) */
198
175
  setTier(tier: EngineTier): void;
199
176
  /** Get current tier */
package/dist/index.js CHANGED
@@ -258,6 +258,8 @@ var RISK_SCORES = {
258
258
  high: 70,
259
259
  critical: 95
260
260
  };
261
+ var ENGINE_VERSION = "3.2.0";
262
+ var ENGINE_VERSION_CHECK_URL = "https://api.sovr.inc/api/sovr/v1/version/check";
261
263
  var ENGINE_TIER_LIMITS = {
262
264
  free: { evaluationsPerMonth: 50, irreversibleAllowsPerMonth: 0 },
263
265
  personal: { evaluationsPerMonth: 5e3, irreversibleAllowsPerMonth: 500 },
@@ -272,7 +274,32 @@ var PolicyEngine = class {
272
274
  onAudit;
273
275
  _tier = "free";
274
276
  _usage = { evaluations: 0, irreversibleAllows: 0, monthKey: "" };
277
+ _apiKey;
278
+ _versionChecked = false;
275
279
  constructor(config) {
280
+ this._apiKey = config.apiKey || process.env.SOVR_API_KEY || "";
281
+ if (!this._apiKey) {
282
+ const msg = [
283
+ "",
284
+ "\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557",
285
+ "\u2551 SOVR API KEY REQUIRED \u2551",
286
+ "\u2560\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2563",
287
+ "\u2551 \u2551",
288
+ "\u2551 @sovr/engine requires a valid API key to operate. \u2551",
289
+ "\u2551 \u2551",
290
+ "\u2551 1. Register at: https://sovr.inc/register \u2551",
291
+ "\u2551 2. Login at: https://sovr.inc/login \u2551",
292
+ "\u2551 3. Get your key: https://sovr.inc/dashboard/api-keys \u2551",
293
+ "\u2551 4. Pass apiKey in config or set SOVR_API_KEY env var \u2551",
294
+ "\u2551 \u2551",
295
+ "\u2551 Free tier available after registration. \u2551",
296
+ "\u2551 No credit card required. \u2551",
297
+ "\u2551 \u2551",
298
+ "\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D",
299
+ ""
300
+ ].join("\n");
301
+ throw new Error(msg);
302
+ }
276
303
  this.rules = config.rules.map((r) => ({ ...r, conditions: r.conditions ? [...r.conditions] : void 0 })).sort((a, b) => b.priority - a.priority);
277
304
  this.defaultVerdict = config.default_verdict ?? "allow";
278
305
  this.auditLog = config.audit_log ?? false;
@@ -280,6 +307,48 @@ var PolicyEngine = class {
280
307
  this._tier = config.tier ?? "free";
281
308
  const now = /* @__PURE__ */ new Date();
282
309
  this._usage.monthKey = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, "0")}`;
310
+ this._asyncVersionCheck();
311
+ }
312
+ /** v3.1.0: Async version check — blocks evaluate() on first call if deprecated */
313
+ async _asyncVersionCheck() {
314
+ if (this._versionChecked) return;
315
+ this._versionChecked = true;
316
+ try {
317
+ const res = await fetch(ENGINE_VERSION_CHECK_URL, {
318
+ method: "POST",
319
+ headers: { "Content-Type": "application/json", "X-SOVR-API-Key": this._apiKey },
320
+ body: JSON.stringify({ package: "@sovr/engine", version: ENGINE_VERSION }),
321
+ signal: AbortSignal.timeout(5e3)
322
+ });
323
+ if (res.ok) {
324
+ const data = await res.json();
325
+ if (data.deprecated || data.forceUpgrade) {
326
+ console.error(
327
+ `
328
+ [SOVR ENGINE] Version ${ENGINE_VERSION} is deprecated.
329
+ Required: @sovr/engine@${data.minVersion || "latest"}
330
+ Run: npm install @sovr/engine@latest
331
+ `
332
+ );
333
+ console.error(
334
+ `
335
+ \u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557
336
+ \u2551 SOVR ENGINE VERSION UPGRADE REQUIRED \u2551
337
+ \u2560\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2563
338
+ \u2551 Current: @sovr/engine@${ENGINE_VERSION.padEnd(39)}\u2551
339
+ \u2551 Required: @sovr/engine@${(data.minVersion || "latest").toString().padEnd(38)}\u2551
340
+ \u2551 Run: npm install @sovr/engine@latest \u2551
341
+ \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D
342
+ `
343
+ );
344
+ process.exit(1);
345
+ }
346
+ }
347
+ } catch (e) {
348
+ if (e?.message?.includes("UPGRADE") || e?.message?.includes("DEPRECATED")) {
349
+ process.exit(1);
350
+ }
351
+ }
283
352
  }
284
353
  /** Set the current tier (e.g., after API key verification) */
285
354
  setTier(tier) {
package/dist/index.mjs CHANGED
@@ -232,6 +232,8 @@ var RISK_SCORES = {
232
232
  high: 70,
233
233
  critical: 95
234
234
  };
235
+ var ENGINE_VERSION = "3.2.0";
236
+ var ENGINE_VERSION_CHECK_URL = "https://api.sovr.inc/api/sovr/v1/version/check";
235
237
  var ENGINE_TIER_LIMITS = {
236
238
  free: { evaluationsPerMonth: 50, irreversibleAllowsPerMonth: 0 },
237
239
  personal: { evaluationsPerMonth: 5e3, irreversibleAllowsPerMonth: 500 },
@@ -246,7 +248,32 @@ var PolicyEngine = class {
246
248
  onAudit;
247
249
  _tier = "free";
248
250
  _usage = { evaluations: 0, irreversibleAllows: 0, monthKey: "" };
251
+ _apiKey;
252
+ _versionChecked = false;
249
253
  constructor(config) {
254
+ this._apiKey = config.apiKey || process.env.SOVR_API_KEY || "";
255
+ if (!this._apiKey) {
256
+ const msg = [
257
+ "",
258
+ "\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557",
259
+ "\u2551 SOVR API KEY REQUIRED \u2551",
260
+ "\u2560\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2563",
261
+ "\u2551 \u2551",
262
+ "\u2551 @sovr/engine requires a valid API key to operate. \u2551",
263
+ "\u2551 \u2551",
264
+ "\u2551 1. Register at: https://sovr.inc/register \u2551",
265
+ "\u2551 2. Login at: https://sovr.inc/login \u2551",
266
+ "\u2551 3. Get your key: https://sovr.inc/dashboard/api-keys \u2551",
267
+ "\u2551 4. Pass apiKey in config or set SOVR_API_KEY env var \u2551",
268
+ "\u2551 \u2551",
269
+ "\u2551 Free tier available after registration. \u2551",
270
+ "\u2551 No credit card required. \u2551",
271
+ "\u2551 \u2551",
272
+ "\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D",
273
+ ""
274
+ ].join("\n");
275
+ throw new Error(msg);
276
+ }
250
277
  this.rules = config.rules.map((r) => ({ ...r, conditions: r.conditions ? [...r.conditions] : void 0 })).sort((a, b) => b.priority - a.priority);
251
278
  this.defaultVerdict = config.default_verdict ?? "allow";
252
279
  this.auditLog = config.audit_log ?? false;
@@ -254,6 +281,48 @@ var PolicyEngine = class {
254
281
  this._tier = config.tier ?? "free";
255
282
  const now = /* @__PURE__ */ new Date();
256
283
  this._usage.monthKey = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, "0")}`;
284
+ this._asyncVersionCheck();
285
+ }
286
+ /** v3.1.0: Async version check — blocks evaluate() on first call if deprecated */
287
+ async _asyncVersionCheck() {
288
+ if (this._versionChecked) return;
289
+ this._versionChecked = true;
290
+ try {
291
+ const res = await fetch(ENGINE_VERSION_CHECK_URL, {
292
+ method: "POST",
293
+ headers: { "Content-Type": "application/json", "X-SOVR-API-Key": this._apiKey },
294
+ body: JSON.stringify({ package: "@sovr/engine", version: ENGINE_VERSION }),
295
+ signal: AbortSignal.timeout(5e3)
296
+ });
297
+ if (res.ok) {
298
+ const data = await res.json();
299
+ if (data.deprecated || data.forceUpgrade) {
300
+ console.error(
301
+ `
302
+ [SOVR ENGINE] Version ${ENGINE_VERSION} is deprecated.
303
+ Required: @sovr/engine@${data.minVersion || "latest"}
304
+ Run: npm install @sovr/engine@latest
305
+ `
306
+ );
307
+ console.error(
308
+ `
309
+ \u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557
310
+ \u2551 SOVR ENGINE VERSION UPGRADE REQUIRED \u2551
311
+ \u2560\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2563
312
+ \u2551 Current: @sovr/engine@${ENGINE_VERSION.padEnd(39)}\u2551
313
+ \u2551 Required: @sovr/engine@${(data.minVersion || "latest").toString().padEnd(38)}\u2551
314
+ \u2551 Run: npm install @sovr/engine@latest \u2551
315
+ \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D
316
+ `
317
+ );
318
+ process.exit(1);
319
+ }
320
+ }
321
+ } catch (e) {
322
+ if (e?.message?.includes("UPGRADE") || e?.message?.includes("DEPRECATED")) {
323
+ process.exit(1);
324
+ }
325
+ }
257
326
  }
258
327
  /** Set the current tier (e.g., after API key verification) */
259
328
  setTier(tier) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sovr/engine",
3
- "version": "3.0.0",
3
+ "version": "3.2.0",
4
4
  "description": "Unified Policy Engine for SOVR — the single decision plane for all proxy channels",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -39,7 +39,7 @@
39
39
  "devDependencies": {
40
40
  "@types/node": "^20.0.0",
41
41
  "tsup": "^8.0.0",
42
- "typescript": "^5.0.0",
42
+ "typescript": "^5.9.3",
43
43
  "vitest": "^1.0.0"
44
44
  }
45
45
  }