@ik-firewall/core 1.0.2 → 2.3.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.js CHANGED
@@ -16,15 +16,18 @@ if (typeof window === "undefined") {
16
16
  var Registry = class _Registry {
17
17
  static instance;
18
18
  registryPath;
19
+ usagePath;
19
20
  hasWarnedNoFs = false;
20
21
  hasWarnedSaveError = false;
21
22
  constructor() {
22
23
  this.registryPath = "";
24
+ this.usagePath = "";
23
25
  if (typeof process !== "undefined" && process.versions && process.versions.node) {
24
26
  try {
25
27
  fs = __require("fs");
26
28
  path = __require("path");
27
29
  this.registryPath = path.join(process.cwd(), ".ik-adapter", "registry.json");
30
+ this.usagePath = path.join(process.cwd(), ".ik-adapter", "usage.json");
28
31
  this.ensureDirectory();
29
32
  } catch (e) {
30
33
  if (!this.hasWarnedNoFs) {
@@ -59,8 +62,13 @@ var Registry = class _Registry {
59
62
  if (!fs || !this.registryPath) return {};
60
63
  try {
61
64
  if (fs.existsSync(this.registryPath)) {
62
- const data = fs.readFileSync(this.registryPath, "utf8");
63
- return JSON.parse(data);
65
+ const rawData = fs.readFileSync(this.registryPath, "utf8");
66
+ try {
67
+ const decoded = Buffer.from(rawData, "base64").toString("utf8");
68
+ return JSON.parse(decoded);
69
+ } catch (e) {
70
+ return JSON.parse(rawData);
71
+ }
64
72
  }
65
73
  } catch (error) {
66
74
  console.error("[IK_REGISTRY] Load error:", error);
@@ -80,7 +88,9 @@ var Registry = class _Registry {
80
88
  }
81
89
  try {
82
90
  this.ensureDirectory();
83
- fs.writeFileSync(this.registryPath, JSON.stringify(data, null, 2), "utf8");
91
+ const jsonStr = JSON.stringify(data, null, 2);
92
+ const obfuscated = Buffer.from(jsonStr).toString("base64");
93
+ fs.writeFileSync(this.registryPath, obfuscated, "utf8");
84
94
  } catch (error) {
85
95
  if (!this.hasWarnedSaveError) {
86
96
  console.error("\n[IK_REGISTRY] \u{1F6A8} ERROR saving registry.json. Your environment likely has a read-only filesystem (e.g. Vercel Serverless).");
@@ -111,17 +121,76 @@ var Registry = class _Registry {
111
121
  delete all[instanceId];
112
122
  this.save(all);
113
123
  }
124
+ getUsageFilePath() {
125
+ return this.usagePath;
126
+ }
127
+ exists(filePath) {
128
+ return fs && fs.existsSync(filePath);
129
+ }
130
+ loadUsage() {
131
+ if (!fs || !this.usagePath || !fs.existsSync(this.usagePath)) return [];
132
+ try {
133
+ const raw = fs.readFileSync(this.usagePath, "utf8");
134
+ return JSON.parse(raw);
135
+ } catch (e) {
136
+ return [];
137
+ }
138
+ }
139
+ saveUsage(data) {
140
+ if (!fs || !this.usagePath) return;
141
+ try {
142
+ fs.writeFileSync(this.usagePath, JSON.stringify(data, null, 2), "utf8");
143
+ } catch (e) {
144
+ console.error("[IK_REGISTRY] Failed to save usage:", e);
145
+ }
146
+ }
147
+ clearUsage() {
148
+ if (!fs || !this.usagePath) return;
149
+ try {
150
+ if (fs.existsSync(this.usagePath)) {
151
+ fs.unlinkSync(this.usagePath);
152
+ }
153
+ } catch (e) {
154
+ }
155
+ }
156
+ };
157
+
158
+ // src/lib/hmac.ts
159
+ import crypto from "crypto";
160
+ var IKHmac = class {
161
+ secret;
162
+ constructor(secret) {
163
+ this.secret = secret;
164
+ }
165
+ /**
166
+ * Verifies that a response from the IK-Firewall server is authentic.
167
+ */
168
+ verify(data) {
169
+ if (!data || !data.signature) return false;
170
+ const { signature, ...rest } = data;
171
+ const payload = JSON.stringify(rest);
172
+ const expectedSignature = crypto.createHmac("sha256", this.secret).update(payload).digest("hex");
173
+ return signature === expectedSignature;
174
+ }
114
175
  };
115
176
 
116
177
  // src/ConfigManager.ts
117
178
  var ConfigManager = class {
118
179
  config;
119
180
  registry;
120
- constructor(initialConfig) {
181
+ hooks;
182
+ constructor(initialConfig, hooks) {
121
183
  this.config = initialConfig;
184
+ this.hooks = hooks;
122
185
  this.registry = Registry.getInstance();
123
186
  this.loadFromRegistry();
124
187
  }
188
+ getRegistry() {
189
+ return this.registry;
190
+ }
191
+ setHooks(hooks) {
192
+ this.hooks = hooks;
193
+ }
125
194
  loadFromRegistry() {
126
195
  const instanceConfigs = this.registry.load();
127
196
  this.config.instanceConfigs = {
@@ -129,6 +198,76 @@ var ConfigManager = class {
129
198
  ...instanceConfigs
130
199
  };
131
200
  }
201
+ /**
202
+ * Syncs remote configuration (pricing, license status) from the Vercel API.
203
+ * Runs once every 24 hours (Heartbeat).
204
+ */
205
+ async syncRemoteConfig(instanceId) {
206
+ const now = /* @__PURE__ */ new Date();
207
+ const instanceConfig = this.config.instanceConfigs?.[instanceId];
208
+ if (instanceConfig?.lastSyncDate) {
209
+ const lastSync = new Date(instanceConfig.lastSyncDate);
210
+ const hoursSinceSync = (now.getTime() - lastSync.getTime()) / (1e3 * 60 * 60);
211
+ if (hoursSinceSync < 24) {
212
+ return;
213
+ }
214
+ }
215
+ try {
216
+ const endpoint = this.config.centralReportEndpoint || "https://ik-firewall.vercel.app/api/v1/sync";
217
+ const instanceConfig2 = this.config.instanceConfigs?.[instanceId];
218
+ const registrationEmail = instanceConfig2?.ownerEmail || this.config.ownerEmail;
219
+ if ((!instanceConfig2?.licenseKey || instanceConfig2.licenseKey.startsWith("TRIAL-")) && registrationEmail) {
220
+ const success = await this.registerInstance(instanceId, registrationEmail);
221
+ if (success) {
222
+ this.hooks?.onStatus?.("\u2728 IK_SYNC: Zero-Config registration successful. License issued.");
223
+ return;
224
+ } else {
225
+ this.hooks?.onStatus?.("\u26A0\uFE0F IK_SYNC: Auto-registration failed. Continuing with local trial.");
226
+ }
227
+ }
228
+ this.hooks?.onStatus?.(`\u{1F4E1} IK_SYNC: Heartbeat to ${endpoint}...`);
229
+ const response = await fetch(`${endpoint}?licenseKey=${instanceConfig2?.licenseKey || ""}&instanceId=${instanceId}&version=2.2.0`);
230
+ if (response.ok) {
231
+ const data = await response.json();
232
+ if (this.config.hmacSecret) {
233
+ const verifier = new IKHmac(this.config.hmacSecret);
234
+ if (!verifier.verify(data)) {
235
+ console.error("[IK_SYNC] \u{1F6A8} Signature verification failed! Remote config rejected.");
236
+ return;
237
+ }
238
+ }
239
+ this.setInstanceConfig(instanceId, {
240
+ billingStatus: data.billingStatus,
241
+ isVerified: data.isVerified,
242
+ pricing: data.pricing,
243
+ lastSyncDate: now.toISOString()
244
+ });
245
+ this.hooks?.onStatus?.("\u2705 IK_SYNC: Remote configuration updated and verified.");
246
+ } else {
247
+ throw new Error(`Server responded with ${response.status}`);
248
+ }
249
+ if (!instanceConfig2?.firstUseDate) {
250
+ this.setInstanceConfig(instanceId, { firstUseDate: now.toISOString() });
251
+ }
252
+ } catch (error) {
253
+ console.error(`[IK_CONFIG] Remote sync failed (${error.message}). Falling open (Fail-Open mode).`);
254
+ this.setInstanceConfig(instanceId, {
255
+ isVerified: true,
256
+ lastSyncDate: now.toISOString()
257
+ });
258
+ }
259
+ try {
260
+ const registry = this.registry;
261
+ if (registry.exists(registry.getUsageFilePath())) {
262
+ const aggregatedUsage = registry.loadUsage();
263
+ if (aggregatedUsage.length > 0) {
264
+ this.hooks?.onStatus?.(`\u{1F4CA} IK_SYNC: Found ${aggregatedUsage.length} pending usage reports. Preparation for Daily Flush...`);
265
+ this._pendingUsage = aggregatedUsage;
266
+ }
267
+ }
268
+ } catch (e) {
269
+ }
270
+ }
132
271
  getConfig() {
133
272
  return { ...this.config };
134
273
  }
@@ -168,6 +307,40 @@ var ConfigManager = class {
168
307
  }
169
308
  this.updateConfig({ plugins });
170
309
  }
310
+ async registerInstance(instanceId, email) {
311
+ try {
312
+ const endpoint = (this.config.centralReportEndpoint || "https://ik-firewall.vercel.app/api/v1").replace(/\/sync$/, "") + "/register";
313
+ this.hooks?.onStatus?.(`\u{1F680} IK_REGISTRY: Registering new instance for ${email}...`);
314
+ const response = await fetch(endpoint, {
315
+ method: "POST",
316
+ headers: { "Content-Type": "application/json" },
317
+ body: JSON.stringify({ email, instanceId })
318
+ });
319
+ if (response.ok) {
320
+ const data = await response.json();
321
+ if (this.config.hmacSecret) {
322
+ const verifier = new IKHmac(this.config.hmacSecret);
323
+ if (!verifier.verify(data)) {
324
+ console.error("[IK_REGISTRY] \u{1F6A8} Registration signature mismatch. Data rejected!");
325
+ return false;
326
+ }
327
+ }
328
+ this.setInstanceConfig(instanceId, {
329
+ licenseKey: data.licenseKey,
330
+ billingStatus: data.status.toLowerCase(),
331
+ isVerified: true,
332
+ firstUseDate: (/* @__PURE__ */ new Date()).toISOString(),
333
+ pricing: data.pricing
334
+ });
335
+ this.hooks?.onStatus?.("\u2728 IK_REGISTRY: Instance registered successfully and license issued.");
336
+ return true;
337
+ }
338
+ return false;
339
+ } catch (error) {
340
+ console.error("[IK_REGISTRY] Registration failed:", error);
341
+ return false;
342
+ }
343
+ }
171
344
  ensureInstanceConfig(instanceId) {
172
345
  const all = this.registry.load();
173
346
  if (!all[instanceId]) {
@@ -175,7 +348,9 @@ var ConfigManager = class {
175
348
  balance: this.config.balance || 0.5,
176
349
  aggressiveness: this.config.aggressiveness || 0.5,
177
350
  isEnabled: true,
178
- contextMode: "FIRST_MESSAGE"
351
+ contextMode: "FIRST_MESSAGE",
352
+ ownerEmail: this.config.ownerEmail
353
+ // Inherit from global if not specific
179
354
  });
180
355
  this.loadFromRegistry();
181
356
  }
@@ -1248,18 +1423,12 @@ var Orchestrator = class {
1248
1423
  };
1249
1424
 
1250
1425
  // src/UsageTracker.ts
1251
- var UsageTracker = class _UsageTracker {
1426
+ var UsageTracker = class {
1252
1427
  buffer = [];
1253
1428
  MAX_BUFFER_SIZE = 1;
1254
1429
  // Immediate reporting for Edge/Stateless environments
1255
1430
  hooks;
1256
1431
  config;
1257
- // Static pricing benchmarks (cost per 1k tokens in USD)
1258
- static PRICING = {
1259
- "gpt-4o": { input: 5e-3, output: 0.015 },
1260
- "gpt-4o-mini": { input: 15e-5, output: 6e-4 },
1261
- "local": { input: 0, output: 0 }
1262
- };
1263
1432
  constructor(config, hooks) {
1264
1433
  this.config = config;
1265
1434
  this.hooks = hooks;
@@ -1270,8 +1439,10 @@ var UsageTracker = class _UsageTracker {
1270
1439
  async logInteraction(params) {
1271
1440
  const { instanceId, model, inputTokens, outputTokens, optimizedTokens = 0, cqScore, routingPath, clientOrigin, trace } = params;
1272
1441
  const tokensSaved = optimizedTokens > 0 ? inputTokens - optimizedTokens : 0;
1273
- const modelPricing = _UsageTracker.PRICING[model] || _UsageTracker.PRICING["gpt-4o-mini"];
1274
- const costSaved = tokensSaved / 1e3 * modelPricing.input;
1442
+ const instanceConfig = this.config.getConfig().instanceConfigs?.[instanceId];
1443
+ const remotePricing = instanceConfig?.pricing?.[model] || { input: 5e-3, output: 0.015 };
1444
+ const costSaved = tokensSaved / 1e3 * remotePricing.input;
1445
+ const commissionDue = costSaved * 0.2;
1275
1446
  const data = {
1276
1447
  instanceId,
1277
1448
  model_used: model,
@@ -1281,6 +1452,7 @@ var UsageTracker = class _UsageTracker {
1281
1452
  optimized_tokens: optimizedTokens,
1282
1453
  tokens_saved: tokensSaved,
1283
1454
  cost_saved: Number(costSaved.toFixed(6)),
1455
+ commission_due: Number(commissionDue.toFixed(6)),
1284
1456
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
1285
1457
  is_local: model === "local",
1286
1458
  cq_score: cqScore,
@@ -1289,40 +1461,71 @@ var UsageTracker = class _UsageTracker {
1289
1461
  };
1290
1462
  this.buffer.push(data);
1291
1463
  this.hooks?.onUsageReported?.(data);
1292
- if (this.buffer.length >= this.MAX_BUFFER_SIZE) {
1293
- await this.flush();
1464
+ await this.persistToLocalBuffer(data);
1465
+ }
1466
+ /**
1467
+ * Appends usage data to the local .ik-adapter/usage.json file
1468
+ */
1469
+ async persistToLocalBuffer(data) {
1470
+ try {
1471
+ const registry = this.config.getRegistry();
1472
+ const usageFile = registry.getUsageFilePath();
1473
+ let existingUsage = [];
1474
+ if (registry.exists(usageFile)) {
1475
+ existingUsage = registry.loadUsage();
1476
+ }
1477
+ existingUsage.push(data);
1478
+ registry.saveUsage(existingUsage);
1479
+ } catch (e) {
1480
+ console.error("[IK_TRACKER] Failed to persist usage to local buffer:", e);
1294
1481
  }
1295
1482
  }
1296
1483
  /**
1297
1484
  * Send buffered usage data to the central IK billing service
1298
1485
  */
1299
- async flush() {
1300
- if (this.buffer.length === 0) return;
1301
- const endpoint = this.config.get("centralReportEndpoint");
1302
- if (!endpoint) {
1303
- console.warn("[IK_TRACKER] No centralReportEndpoint defined. Clearing buffer to prevent memory leak.");
1304
- this.buffer = [];
1305
- return;
1306
- }
1486
+ async flush(aggregatedData) {
1487
+ const usageToFlush = aggregatedData || this.buffer;
1488
+ if (usageToFlush.length === 0) return;
1489
+ const endpoint = this.config.get("centralReportEndpoint") || "https://ik-firewall.vercel.app/api/v1/report";
1490
+ const hmacSecret = this.config.get("hmacSecret");
1307
1491
  try {
1308
- for (const report of this.buffer) {
1309
- await fetch(endpoint, {
1492
+ this.hooks?.onStatus?.(`\u{1F4E4} IK_TRACKER: Flushing ${usageToFlush.length} interactions to ${endpoint}...`);
1493
+ const reportsByInstance = {};
1494
+ for (const report of usageToFlush) {
1495
+ if (!reportsByInstance[report.instanceId]) reportsByInstance[report.instanceId] = [];
1496
+ reportsByInstance[report.instanceId].push(report);
1497
+ }
1498
+ for (const [instanceId, reports] of Object.entries(reportsByInstance)) {
1499
+ const instanceConfig = this.config.getConfig().instanceConfigs?.[instanceId];
1500
+ const payload = {
1501
+ licenseKey: instanceConfig?.licenseKey || "",
1502
+ instanceId,
1503
+ reports: reports.map((r) => ({
1504
+ modelName: r.model_used,
1505
+ tokensIn: r.input_tokens,
1506
+ tokensOut: r.output_tokens,
1507
+ tokensSaved: r.tokens_saved,
1508
+ date: r.timestamp
1509
+ }))
1510
+ };
1511
+ if (hmacSecret) {
1512
+ const jsonStr = JSON.stringify(payload);
1513
+ const crypto2 = await import("crypto");
1514
+ payload.signature = crypto2.createHmac("sha256", hmacSecret).update(jsonStr).digest("hex");
1515
+ }
1516
+ const response = await fetch(endpoint, {
1310
1517
  method: "POST",
1311
1518
  headers: { "Content-Type": "application/json" },
1312
- body: JSON.stringify({
1313
- instanceId: report.instanceId,
1314
- model: report.model_used,
1315
- inputTokens: report.input_tokens,
1316
- outputTokens: report.output_tokens,
1317
- optimizedTokens: report.optimized_tokens,
1318
- cqScore: report.cq_score,
1319
- routingPath: report.routingPath,
1320
- clientOrigin: report.clientOrigin,
1321
- trace: report.trace
1322
- })
1519
+ body: JSON.stringify(payload)
1323
1520
  });
1521
+ if (!response.ok) {
1522
+ console.error(`[IK_TRACKER] Failed to send aggregate for ${instanceId}: ${response.statusText}`);
1523
+ }
1324
1524
  }
1325
1525
  this.buffer = [];
1526
+ if (aggregatedData) {
1527
+ this.config.getRegistry().clearUsage();
1528
+ }
1326
1529
  } catch (error) {
1327
1530
  console.error("[IK_TRACKER] Failed to flush usage data:", error);
1328
1531
  }
@@ -1332,6 +1535,49 @@ var UsageTracker = class _UsageTracker {
1332
1535
  }
1333
1536
  };
1334
1537
 
1538
+ // src/CognitiveEngine.ts
1539
+ var CognitiveEngine = class {
1540
+ /**
1541
+ * Sniff Cognitive DNA (CQ Score: 0-100)
1542
+ * Higher score = higher quality, human-like, structured content.
1543
+ */
1544
+ static sniffDNA(input) {
1545
+ if (!input || input.trim().length === 0) return 0;
1546
+ const length = input.length;
1547
+ const words = input.split(/\s+/).filter((w) => w.length > 0);
1548
+ const wordCount = words.length;
1549
+ const sentences = input.split(/[.!?]+/).filter((s) => s.trim().length > 0);
1550
+ const avgSentenceLength = sentences.length > 0 ? wordCount / sentences.length : 0;
1551
+ const sentenceVariety = sentences.length > 1 ? 10 : 0;
1552
+ const uniqueWords = new Set(words.map((w) => w.toLowerCase())).size;
1553
+ const lexicalBreadth = wordCount > 0 ? uniqueWords / wordCount * 40 : 0;
1554
+ const markers = (input.match(/[,;:"'()\[\]]/g) || []).length;
1555
+ const structuralHealth = Math.min(markers / wordCount * 100, 20);
1556
+ const repetitivePenalty = this.calculateRepetitivePenalty(input);
1557
+ let score = lexicalBreadth + structuralHealth + sentenceVariety + (avgSentenceLength > 5 ? 20 : 0);
1558
+ score -= repetitivePenalty;
1559
+ return Math.max(0, Math.min(100, score));
1560
+ }
1561
+ /**
1562
+ * Calculate Crystallization Threshold
1563
+ * Logic:
1564
+ * Low CQ (Noise) -> Aggressive optimization (Lower threshold, e.g. 0.6)
1565
+ * High CQ (Quality) -> Conservative optimization (Higher threshold, e.g. 0.9)
1566
+ */
1567
+ static calculateThreshold(cqScore) {
1568
+ if (cqScore < 30) return 0.65;
1569
+ if (cqScore < 60) return 0.78;
1570
+ if (cqScore < 85) return 0.88;
1571
+ return 0.95;
1572
+ }
1573
+ static calculateRepetitivePenalty(input) {
1574
+ const chunks = input.match(/.{1,10}/g) || [];
1575
+ const uniqueChunks = new Set(chunks).size;
1576
+ const ratio = chunks.length > 10 ? uniqueChunks / chunks.length : 1;
1577
+ return ratio < 0.5 ? (1 - ratio) * 50 : 0;
1578
+ }
1579
+ };
1580
+
1335
1581
  // src/core.ts
1336
1582
  var IKFirewallCore = class _IKFirewallCore {
1337
1583
  static instance;
@@ -1386,55 +1632,75 @@ var IKFirewallCore = class _IKFirewallCore {
1386
1632
  FLUID_THRESHOLD: 4
1387
1633
  }
1388
1634
  };
1389
- gatekeeper = new HeuristicGatekeeper();
1635
+ gatekeeper;
1390
1636
  configManager;
1391
1637
  sessionDNA = 0;
1392
- hooks;
1393
1638
  cloudProvider;
1394
1639
  localProvider;
1395
1640
  orchestrator;
1396
1641
  usageTracker;
1642
+ _hooks;
1643
+ defaultConfig;
1397
1644
  constructor(config, hooks, cloudProvider) {
1398
- const defaultConfig = {
1645
+ this.defaultConfig = {
1399
1646
  aggressiveness: 0.15,
1400
1647
  forcedEfficiency: false,
1401
1648
  precisionBias: _IKFirewallCore.CONSTANTS.PRECISION.BIAS_DEFAULT,
1402
1649
  balance: _IKFirewallCore.CONSTANTS.TONE.STABLE_VAL,
1403
1650
  gatekeeperEnabled: true,
1404
1651
  locale: "en",
1405
- providerMode: "hybrid",
1652
+ providerMode: process.env.IK_FIREWALL_MODE || "hybrid",
1406
1653
  runtimeStrategy: "internal",
1407
- localAuditEndpoint: "http://127.0.0.1:8085/v1/chat/completions",
1408
- fallbackToCloudAudit: false,
1654
+ localAuditEndpoint: process.env.IK_FIREWALL_LOCAL_ENDPOINT || "http://127.0.0.1:8085/v1/chat/completions",
1655
+ centralReportEndpoint: process.env.IK_FIREWALL_CENTRAL_ENDPOINT || "https://ik-firewall.vercel.app/api/v1/sync",
1656
+ ownerEmail: process.env.IK_FIREWALL_EMAIL,
1657
+ hmacSecret: process.env.IK_FIREWALL_SECRET,
1658
+ fallbackToCloudAudit: process.env.IK_FIREWALL_FALLBACK === "true" || false,
1409
1659
  modelConfig: {
1410
1660
  modelType: "1b"
1411
1661
  },
1412
1662
  plugins: []
1413
1663
  };
1414
- this.configManager = new ConfigManager({ ...defaultConfig, ...config });
1415
- if (hooks) this.hooks = hooks;
1664
+ this._hooks = hooks;
1665
+ this.configManager = new ConfigManager({ ...this.defaultConfig, ...config }, hooks);
1666
+ this.gatekeeper = new HeuristicGatekeeper();
1667
+ this.sessionDNA = _IKFirewallCore.CONSTANTS.DNA.MIN;
1416
1668
  const activeConfig = this.configManager.getConfig();
1417
1669
  this.localProvider = new LocalProvider(activeConfig.localAuditEndpoint);
1418
1670
  if (cloudProvider) {
1419
- if (cloudProvider instanceof BaseProvider) {
1420
- this.cloudProvider = cloudProvider;
1421
- } else {
1422
- const mode = activeConfig.providerMode;
1423
- if (mode === "anthropic") {
1424
- this.cloudProvider = new AnthropicProvider(cloudProvider);
1425
- } else if (mode === "deepseek") {
1426
- this.cloudProvider = new DeepSeekProvider(cloudProvider);
1427
- } else if (mode === "gemini") {
1428
- this.cloudProvider = new GeminiProvider(cloudProvider);
1429
- } else if (mode === "perplexity") {
1430
- this.cloudProvider = new PerplexityProvider(cloudProvider);
1431
- } else {
1432
- this.cloudProvider = new OpenAIProvider(cloudProvider);
1433
- }
1434
- }
1671
+ this.cloudProvider = cloudProvider instanceof BaseProvider ? cloudProvider : new OpenAIProvider(cloudProvider);
1672
+ } else if (process.env.OPENAI_API_KEY) {
1673
+ this.cloudProvider = new OpenAIProvider(async (prompt, role) => {
1674
+ const response = await fetch("https://api.openai.com/v1/chat/completions", {
1675
+ method: "POST",
1676
+ headers: {
1677
+ "Authorization": `Bearer ${process.env.OPENAI_API_KEY}`,
1678
+ "Content-Type": "application/json"
1679
+ },
1680
+ body: JSON.stringify({
1681
+ model: role === "audit_layer" ? "gpt-4o-mini" : "gpt-4o",
1682
+ messages: [{ role: "user", content: prompt }],
1683
+ temperature: 0.1
1684
+ })
1685
+ });
1686
+ if (!response.ok) throw new Error(`OpenAI API Error: ${response.statusText}`);
1687
+ const data = await response.json();
1688
+ return {
1689
+ content: data.choices[0].message.content,
1690
+ usage: data.usage
1691
+ };
1692
+ });
1435
1693
  }
1436
1694
  this.orchestrator = new Orchestrator(this.configManager);
1437
- this.usageTracker = new UsageTracker(this.configManager, this.hooks);
1695
+ this.usageTracker = new UsageTracker(this.configManager, this._hooks);
1696
+ }
1697
+ get hooks() {
1698
+ return this._hooks;
1699
+ }
1700
+ set hooks(newHooks) {
1701
+ this._hooks = newHooks;
1702
+ this.configManager.setHooks(newHooks);
1703
+ this.usageTracker.hooks = newHooks;
1438
1704
  }
1439
1705
  static getInstance(config, hooks) {
1440
1706
  if (!_IKFirewallCore.instance) {
@@ -1546,6 +1812,21 @@ var IKFirewallCore = class _IKFirewallCore {
1546
1812
  async analyze(input, provider, personaName = "professional", locale, instanceId) {
1547
1813
  if (instanceId) {
1548
1814
  this.configManager.ensureInstanceConfig(instanceId);
1815
+ const syncPromise = this.configManager.syncRemoteConfig(instanceId).then(async () => {
1816
+ const pendingUsage = this.configManager._pendingUsage;
1817
+ if (pendingUsage && pendingUsage.length > 0) {
1818
+ await this.usageTracker.flush(pendingUsage);
1819
+ this.configManager._pendingUsage = null;
1820
+ }
1821
+ });
1822
+ await syncPromise;
1823
+ }
1824
+ const mergedConfig = this.configManager.getMergedConfig(instanceId);
1825
+ if (instanceId && mergedConfig?.isVerified === false) {
1826
+ if (mergedConfig?.billingStatus === "blocked") {
1827
+ this.hooks?.onStatus?.("\u26A0\uFE0F [IK_FIREWALL] Subscription inactive. Optimization bypassed (Fail-Safe mode).");
1828
+ return this.getEmptyMetrics();
1829
+ }
1549
1830
  }
1550
1831
  let auditProvider = this.localProvider;
1551
1832
  let overrideProvider = null;
@@ -1580,18 +1861,20 @@ var IKFirewallCore = class _IKFirewallCore {
1580
1861
  const ei = (input.match(/[,;.:-]/g) || []).length / (input.split(" ").length || 1);
1581
1862
  let requiresAuditOverride = false;
1582
1863
  let boundaryMetrics = { boundaryScore: 0, requiresHumanIntervention: false };
1583
- if (this.getConfig().safeMode) {
1584
- boundaryMetrics = this.gatekeeper.evaluateBoundaryCommunication(input, this.getConfig().customBoundaryKeywords);
1585
- if (boundaryMetrics.requiresHumanIntervention) {
1864
+ if (this.getConfig()?.safeMode) {
1865
+ boundaryMetrics = this.gatekeeper.evaluateBoundaryCommunication(input, this.getConfig()?.customBoundaryKeywords);
1866
+ if (boundaryMetrics?.requiresHumanIntervention) {
1586
1867
  requiresAuditOverride = true;
1587
1868
  }
1588
1869
  }
1589
1870
  const skipAudit = !requiresAuditOverride && this.getConfig().gatekeeperEnabled && localInsight.complexityScore < _IKFirewallCore.CONSTANTS.HEURISTICS.COMPLEXITY_SKIP_THRESHOLD;
1590
1871
  if (skipAudit) {
1591
1872
  this.hooks?.onStatus?.("\u26A1 IK_GATEKEEPER: Simple request detected. Skipping Deep Audit.");
1592
- const metrics2 = this.createHeuristicMetrics(input, dm, ei, uniqueWords, localInsight.intentMode);
1593
- metrics2.semanticInsights.boundaryScore = boundaryMetrics.boundaryScore;
1594
- metrics2.semanticInsights.requiresHumanIntervention = boundaryMetrics.requiresHumanIntervention;
1873
+ const metrics2 = this.createHeuristicMetrics(input, dm, ei, uniqueWords, localInsight?.intentMode);
1874
+ if (metrics2.semanticInsights) {
1875
+ metrics2.semanticInsights.boundaryScore = boundaryMetrics.boundaryScore;
1876
+ metrics2.semanticInsights.requiresHumanIntervention = boundaryMetrics.requiresHumanIntervention;
1877
+ }
1595
1878
  this.hooks?.onAuditComplete?.(metrics2);
1596
1879
  return metrics2;
1597
1880
  }
@@ -1606,10 +1889,17 @@ var IKFirewallCore = class _IKFirewallCore {
1606
1889
  throw e;
1607
1890
  }
1608
1891
  }
1609
- this.sniffDNA(input, metrics, activeLocale);
1892
+ const cqScore = CognitiveEngine.sniffDNA(input);
1893
+ metrics.dm = Math.max(metrics.dm, cqScore / 10);
1894
+ this.applyHardening(input, metrics, activeLocale);
1610
1895
  this.hooks?.onAuditComplete?.(metrics);
1611
1896
  return metrics;
1612
1897
  }
1898
+ applyHardening(input, metrics, locale = "en") {
1899
+ const archetype = metrics.semanticInsights?.archetype || "DYNAMIC";
1900
+ const domain = metrics.semanticInsights?.detectedDomain || "GENERAL";
1901
+ this.setSessionDNA(this.sessionDNA + 5);
1902
+ }
1613
1903
  getEmptyMetrics() {
1614
1904
  return {
1615
1905
  dm: 0,
@@ -1661,39 +1951,17 @@ var IKFirewallCore = class _IKFirewallCore {
1661
1951
  inputLength: input.length
1662
1952
  };
1663
1953
  }
1664
- sniffDNA(input, metrics, locale = "en") {
1665
- const archetype = metrics.semanticInsights?.archetype || "DYNAMIC";
1666
- const domain = metrics.semanticInsights?.detectedDomain || "GENERAL";
1667
- const meta = Dictionaries.meta[locale] || Dictionaries.meta.en;
1668
- const patterns = (meta.system_prompt_patterns || "").split(",").map((p) => p.trim()).filter((p) => p.length > 0);
1669
- const isSystemPrompt = patterns.some((kw) => input.toLowerCase().includes(kw));
1670
- let dnaShift = 0;
1671
- if (archetype === "CRYSTAL") {
1672
- dnaShift += _IKFirewallCore.CONSTANTS.DNA.HARDENING_MODERATE;
1673
- } else if (archetype === "FLUID") {
1674
- dnaShift -= _IKFirewallCore.CONSTANTS.DNA.SOFTENING_STEP;
1675
- } else if (archetype === "NEURAL") {
1676
- dnaShift -= _IKFirewallCore.CONSTANTS.DNA.SOFTENING_STEP / 2;
1677
- }
1678
- if (["LEGAL", "MEDICAL", "FINANCE", "CONSTRUCTION", "ENGINEERING"].includes(domain)) {
1679
- dnaShift += _IKFirewallCore.CONSTANTS.DNA.HARDENING_DOMAIN;
1680
- }
1681
- if (isSystemPrompt) {
1682
- dnaShift += _IKFirewallCore.CONSTANTS.DNA.HARDENING_MODERATE;
1683
- }
1684
- this.setSessionDNA(this.sessionDNA + dnaShift);
1685
- }
1686
1954
  async analyzeAIAssisted(input, provider, personaName = "professional", instanceId, configOverride) {
1687
1955
  if (instanceId) {
1688
1956
  this.configManager.ensureInstanceConfig(instanceId);
1689
1957
  }
1690
1958
  const activeConfig = this.configManager.getMergedConfig(instanceId, configOverride);
1691
- const locale = activeConfig.locale || "en";
1959
+ const locale = activeConfig?.locale || "en";
1692
1960
  const cqScore = this.orchestrator.calculateCQ(input);
1693
1961
  let isAuditTask = false;
1694
- if (activeConfig.safeMode) {
1695
- const boundaryResult = this.gatekeeper.evaluateBoundaryCommunication(input, activeConfig.customBoundaryKeywords);
1696
- if (boundaryResult.requiresHumanIntervention) {
1962
+ if (activeConfig?.safeMode) {
1963
+ const boundaryResult = this.gatekeeper.evaluateBoundaryCommunication(input, activeConfig?.customBoundaryKeywords);
1964
+ if (boundaryResult?.requiresHumanIntervention) {
1697
1965
  isAuditTask = true;
1698
1966
  }
1699
1967
  }
@@ -1915,7 +2183,11 @@ Any action outside this scope MUST be rejected and flagged as a boundary violati
1915
2183
  inputLength
1916
2184
  };
1917
2185
  }
1918
- crystallize(input, metrics, locale = "en") {
2186
+ crystallize(input, metrics, locale = "en", instanceId) {
2187
+ const mergedConfig = this.configManager.getMergedConfig(instanceId);
2188
+ if (instanceId && mergedConfig?.isVerified === false) {
2189
+ return input;
2190
+ }
1919
2191
  const archetype = metrics?.semanticInsights?.archetype || "DYNAMIC";
1920
2192
  const tolerance = metrics?.semanticInsights?.ambiguityTolerance || 0.5;
1921
2193
  const blueprint = metrics?.semanticInsights?.conceptualBlueprint;
@@ -1929,11 +2201,13 @@ Any action outside this scope MUST be rejected and flagged as a boundary violati
1929
2201
  this.hooks?.onStatus?.(`\u{1F6E1}\uFE0F IK_CRYSTALLIZE: Precision domain detected (${domain}). Relaxing noise reduction...`);
1930
2202
  archetypeModifier = -0.3;
1931
2203
  }
2204
+ const cqScore = CognitiveEngine.sniffDNA(input);
2205
+ const cognitiveThreshold = CognitiveEngine.calculateThreshold(cqScore);
1932
2206
  const threshold = Math.min(
1933
2207
  _IKFirewallCore.CONSTANTS.AI.THRESHOLD_MAX,
1934
2208
  Math.max(
1935
2209
  _IKFirewallCore.CONSTANTS.AI.THRESHOLD_MIN,
1936
- dm / _IKFirewallCore.CONSTANTS.AI.DM_THRESHOLD_DIVISOR + basePreference - aggModifier + archetypeModifier - tolerance * 0.1
2210
+ cognitiveThreshold + archetypeModifier - tolerance * 0.1
1937
2211
  )
1938
2212
  );
1939
2213
  const lengthRatio = blueprint ? blueprint.length / input.length : 1;