@ik-firewall/core 2.3.7 → 2.4.1
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.cjs +81 -42
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +81 -42
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -90,10 +90,10 @@ var Registry = class _Registry {
|
|
|
90
90
|
/**
|
|
91
91
|
* Loads instance configurations with Hook support
|
|
92
92
|
*/
|
|
93
|
-
load() {
|
|
93
|
+
async load() {
|
|
94
94
|
if (this.hooks?.loadState) {
|
|
95
95
|
try {
|
|
96
|
-
const hookData = this.hooks.loadState("ik_registry");
|
|
96
|
+
const hookData = await this.hooks.loadState("ik_registry");
|
|
97
97
|
if (hookData) return JSON.parse(hookData);
|
|
98
98
|
} catch (e) {
|
|
99
99
|
console.warn("[IK_REGISTRY] Registry load via hook failed, falling back...");
|
|
@@ -114,10 +114,10 @@ var Registry = class _Registry {
|
|
|
114
114
|
}
|
|
115
115
|
return {};
|
|
116
116
|
}
|
|
117
|
-
save(data) {
|
|
117
|
+
async save(data) {
|
|
118
118
|
const jsonStr = JSON.stringify(data, null, 2);
|
|
119
119
|
if (this.hooks?.persistState) {
|
|
120
|
-
this.hooks.persistState("ik_registry", jsonStr);
|
|
120
|
+
await this.hooks.persistState("ik_registry", jsonStr);
|
|
121
121
|
}
|
|
122
122
|
if (fs && this.registryPath) {
|
|
123
123
|
try {
|
|
@@ -132,10 +132,10 @@ var Registry = class _Registry {
|
|
|
132
132
|
}
|
|
133
133
|
}
|
|
134
134
|
}
|
|
135
|
-
updateInstance(instanceId, config) {
|
|
136
|
-
const all = this.load();
|
|
135
|
+
async updateInstance(instanceId, config) {
|
|
136
|
+
const all = await this.load();
|
|
137
137
|
all[instanceId] = { ...all[instanceId] || {}, ...config, updatedAt: (/* @__PURE__ */ new Date()).toISOString() };
|
|
138
|
-
this.save(all);
|
|
138
|
+
await this.save(all);
|
|
139
139
|
}
|
|
140
140
|
getUsageFilePath() {
|
|
141
141
|
return this.usagePath;
|
|
@@ -158,13 +158,25 @@ var Registry = class _Registry {
|
|
|
158
158
|
} catch (e) {
|
|
159
159
|
}
|
|
160
160
|
}
|
|
161
|
-
clearUsage() {
|
|
161
|
+
async clearUsage() {
|
|
162
162
|
if (!fs || !this.usagePath) return;
|
|
163
163
|
try {
|
|
164
164
|
if (fs.existsSync(this.usagePath)) fs.unlinkSync(this.usagePath);
|
|
165
165
|
} catch (e) {
|
|
166
166
|
}
|
|
167
167
|
}
|
|
168
|
+
async getLastFlushTime() {
|
|
169
|
+
if (this.hooks?.loadState) {
|
|
170
|
+
const val = await this.hooks.loadState("ik_last_flush");
|
|
171
|
+
if (val) return parseInt(val, 10);
|
|
172
|
+
}
|
|
173
|
+
return null;
|
|
174
|
+
}
|
|
175
|
+
async setLastFlushTime(time) {
|
|
176
|
+
if (this.hooks?.persistState) {
|
|
177
|
+
await this.hooks.persistState("ik_last_flush", time.toString());
|
|
178
|
+
}
|
|
179
|
+
}
|
|
168
180
|
};
|
|
169
181
|
|
|
170
182
|
// src/lib/hmac.ts
|
|
@@ -202,6 +214,7 @@ var ConfigManager = class {
|
|
|
202
214
|
config;
|
|
203
215
|
registry;
|
|
204
216
|
hooks;
|
|
217
|
+
blockedInstances = /* @__PURE__ */ new Set();
|
|
205
218
|
constructor(initialConfig, hooks) {
|
|
206
219
|
this.config = initialConfig;
|
|
207
220
|
this.hooks = hooks;
|
|
@@ -209,7 +222,6 @@ var ConfigManager = class {
|
|
|
209
222
|
if (hooks) {
|
|
210
223
|
this.registry.setHooks(hooks);
|
|
211
224
|
}
|
|
212
|
-
this.loadFromRegistry();
|
|
213
225
|
}
|
|
214
226
|
getRegistry() {
|
|
215
227
|
return this.registry;
|
|
@@ -225,16 +237,16 @@ var ConfigManager = class {
|
|
|
225
237
|
if (state) {
|
|
226
238
|
const parsed = JSON.parse(state);
|
|
227
239
|
const registry = this.registry;
|
|
228
|
-
registry.save(parsed);
|
|
229
|
-
this.loadFromRegistry();
|
|
240
|
+
await registry.save(parsed);
|
|
241
|
+
await this.loadFromRegistry();
|
|
230
242
|
}
|
|
231
243
|
} catch (e) {
|
|
232
244
|
console.warn("[IK_CONFIG] Hydration from hooks failed:", e);
|
|
233
245
|
}
|
|
234
246
|
}
|
|
235
247
|
}
|
|
236
|
-
loadFromRegistry() {
|
|
237
|
-
const instanceConfigs = this.registry.load();
|
|
248
|
+
async loadFromRegistry() {
|
|
249
|
+
const instanceConfigs = await this.registry.load();
|
|
238
250
|
this.config.instanceConfigs = {
|
|
239
251
|
...this.config.instanceConfigs || {},
|
|
240
252
|
...instanceConfigs
|
|
@@ -276,7 +288,7 @@ var ConfigManager = class {
|
|
|
276
288
|
return;
|
|
277
289
|
}
|
|
278
290
|
}
|
|
279
|
-
this.setInstanceConfig(instanceId, {
|
|
291
|
+
await this.setInstanceConfig(instanceId, {
|
|
280
292
|
billingStatus: data.billingStatus,
|
|
281
293
|
isVerified: data.isVerified,
|
|
282
294
|
pricing: data.pricing,
|
|
@@ -288,7 +300,7 @@ var ConfigManager = class {
|
|
|
288
300
|
}
|
|
289
301
|
} catch (error) {
|
|
290
302
|
console.error(`[IK_CONFIG] Remote sync failed (${error.message}). Falling open (Fail-Open mode).`);
|
|
291
|
-
this.setInstanceConfig(instanceId, {
|
|
303
|
+
await this.setInstanceConfig(instanceId, {
|
|
292
304
|
isVerified: true,
|
|
293
305
|
lastSyncDate: now.toISOString()
|
|
294
306
|
});
|
|
@@ -308,11 +320,27 @@ var ConfigManager = class {
|
|
|
308
320
|
if (instanceId && this.config.instanceConfigs?.[instanceId]) {
|
|
309
321
|
merged = { ...merged, ...this.config.instanceConfigs[instanceId] };
|
|
310
322
|
}
|
|
323
|
+
if (instanceId && this.blockedInstances.has(instanceId)) {
|
|
324
|
+
merged.billingStatus = "blocked";
|
|
325
|
+
}
|
|
311
326
|
if (override) {
|
|
312
327
|
merged = { ...merged, ...override };
|
|
313
328
|
}
|
|
314
329
|
return merged;
|
|
315
330
|
}
|
|
331
|
+
/**
|
|
332
|
+
* Updates the live blocked status for an instance (Kill-Switch).
|
|
333
|
+
* This is used by UsageTracker when it receives a response from the central server.
|
|
334
|
+
*/
|
|
335
|
+
async setBlockedStatus(instanceId, blocked) {
|
|
336
|
+
if (blocked) {
|
|
337
|
+
this.blockedInstances.add(instanceId);
|
|
338
|
+
await this.setInstanceConfig(instanceId, { billingStatus: "blocked" });
|
|
339
|
+
} else {
|
|
340
|
+
this.blockedInstances.delete(instanceId);
|
|
341
|
+
await this.setInstanceConfig(instanceId, { billingStatus: "active" });
|
|
342
|
+
}
|
|
343
|
+
}
|
|
316
344
|
updateConfig(newConfig) {
|
|
317
345
|
this.config = {
|
|
318
346
|
...this.config,
|
|
@@ -351,7 +379,7 @@ var ConfigManager = class {
|
|
|
351
379
|
return false;
|
|
352
380
|
}
|
|
353
381
|
}
|
|
354
|
-
this.setInstanceConfig(instanceId, {
|
|
382
|
+
await this.setInstanceConfig(instanceId, {
|
|
355
383
|
licenseKey: data.licenseKey,
|
|
356
384
|
billingStatus: data.status.toLowerCase(),
|
|
357
385
|
isVerified: true,
|
|
@@ -367,10 +395,10 @@ var ConfigManager = class {
|
|
|
367
395
|
return false;
|
|
368
396
|
}
|
|
369
397
|
}
|
|
370
|
-
ensureInstanceConfig(instanceId) {
|
|
371
|
-
const all = this.registry.load();
|
|
398
|
+
async ensureInstanceConfig(instanceId) {
|
|
399
|
+
const all = await this.registry.load();
|
|
372
400
|
if (!all[instanceId]) {
|
|
373
|
-
this.registry.updateInstance(instanceId, {
|
|
401
|
+
await this.registry.updateInstance(instanceId, {
|
|
374
402
|
balance: this.config.balance || 0.5,
|
|
375
403
|
aggressiveness: this.config.aggressiveness || 0.5,
|
|
376
404
|
isEnabled: true,
|
|
@@ -378,15 +406,15 @@ var ConfigManager = class {
|
|
|
378
406
|
ownerEmail: this.config.ownerEmail
|
|
379
407
|
// Inherit from global if not specific
|
|
380
408
|
});
|
|
381
|
-
this.loadFromRegistry();
|
|
409
|
+
await this.loadFromRegistry();
|
|
382
410
|
}
|
|
383
411
|
}
|
|
384
|
-
getInstanceConfigs() {
|
|
412
|
+
async getInstanceConfigs() {
|
|
385
413
|
return this.registry.load();
|
|
386
414
|
}
|
|
387
|
-
setInstanceConfig(instanceId, config) {
|
|
388
|
-
this.registry.updateInstance(instanceId, config);
|
|
389
|
-
this.loadFromRegistry();
|
|
415
|
+
async setInstanceConfig(instanceId, config) {
|
|
416
|
+
await this.registry.updateInstance(instanceId, config);
|
|
417
|
+
await this.loadFromRegistry();
|
|
390
418
|
}
|
|
391
419
|
};
|
|
392
420
|
|
|
@@ -1505,11 +1533,14 @@ var UsageTracker = class {
|
|
|
1505
1533
|
}
|
|
1506
1534
|
async checkFlushConditions(instanceId) {
|
|
1507
1535
|
const now = Date.now();
|
|
1536
|
+
if (this.lastFlushTime === 0) {
|
|
1537
|
+
const persisted = await this.config.getRegistry().getLastFlushTime();
|
|
1538
|
+
if (persisted) this.lastFlushTime = persisted;
|
|
1539
|
+
else this.lastFlushTime = now;
|
|
1540
|
+
}
|
|
1508
1541
|
const timeSinceFlush = now - this.lastFlushTime;
|
|
1509
1542
|
if (this.aggregationMap.size >= this.BATCH_SIZE_THRESHOLD || timeSinceFlush >= this.TIME_THRESHOLD_MS) {
|
|
1510
|
-
this.performAsyncFlush(instanceId)
|
|
1511
|
-
console.error("[IK_TRACKER] Background flush failed:", err);
|
|
1512
|
-
});
|
|
1543
|
+
await this.performAsyncFlush(instanceId);
|
|
1513
1544
|
}
|
|
1514
1545
|
}
|
|
1515
1546
|
async performAsyncFlush(instanceId) {
|
|
@@ -1518,7 +1549,8 @@ var UsageTracker = class {
|
|
|
1518
1549
|
const reports = Array.from(this.aggregationMap.values());
|
|
1519
1550
|
this.aggregationMap.clear();
|
|
1520
1551
|
this.lastFlushTime = Date.now();
|
|
1521
|
-
const
|
|
1552
|
+
const instanceConfigs = await this.config.getInstanceConfigs();
|
|
1553
|
+
const licenseKey = instanceConfigs[instanceId]?.licenseKey || this.config.get("licenseKey");
|
|
1522
1554
|
const payload = {
|
|
1523
1555
|
licenseKey: licenseKey || "TRIAL-KEY",
|
|
1524
1556
|
instanceId,
|
|
@@ -1551,7 +1583,8 @@ var UsageTracker = class {
|
|
|
1551
1583
|
try {
|
|
1552
1584
|
const crypto = typeof window === "undefined" ? (await import("crypto")).default : null;
|
|
1553
1585
|
if (crypto && crypto.createHmac) {
|
|
1554
|
-
|
|
1586
|
+
const { signature: _sig, ...signablePayload } = payload;
|
|
1587
|
+
payload.signature = crypto.createHmac("sha256", hmacSecret).update(JSON.stringify(signablePayload)).digest("hex");
|
|
1555
1588
|
}
|
|
1556
1589
|
} catch (e) {
|
|
1557
1590
|
}
|
|
@@ -1567,6 +1600,17 @@ var UsageTracker = class {
|
|
|
1567
1600
|
if (!response.ok) {
|
|
1568
1601
|
throw new Error(`HTTP Error: ${response.status} ${response.statusText}`);
|
|
1569
1602
|
}
|
|
1603
|
+
try {
|
|
1604
|
+
const data = await response.json();
|
|
1605
|
+
if (data && (data.status === "blocked" || data.billingStatus === "blocked")) {
|
|
1606
|
+
this.config.setBlockedStatus(payload.instanceId, true);
|
|
1607
|
+
console.warn(`[IK_TRACKER] \u{1F6E1}\uFE0F Kill-Switch triggered for ${payload.instanceId}: Subscription inactive/blocked.`);
|
|
1608
|
+
} else if (data && (data.status === "active" || data.billingStatus === "active" || data.status === "trial")) {
|
|
1609
|
+
this.config.setBlockedStatus(payload.instanceId, false);
|
|
1610
|
+
}
|
|
1611
|
+
} catch (e) {
|
|
1612
|
+
}
|
|
1613
|
+
await this.config.getRegistry().setLastFlushTime(this.lastFlushTime);
|
|
1570
1614
|
this.hooks?.onFlushSuccess?.(payload);
|
|
1571
1615
|
}
|
|
1572
1616
|
async handleFailure(payload) {
|
|
@@ -1780,11 +1824,11 @@ var IKFirewallCore = class _IKFirewallCore {
|
|
|
1780
1824
|
getSessionDNA() {
|
|
1781
1825
|
return this.sessionDNA;
|
|
1782
1826
|
}
|
|
1783
|
-
getInstanceConfigs() {
|
|
1827
|
+
async getInstanceConfigs() {
|
|
1784
1828
|
return this.configManager.getInstanceConfigs();
|
|
1785
1829
|
}
|
|
1786
|
-
setInstanceConfig(instanceId, config) {
|
|
1787
|
-
this.configManager.setInstanceConfig(instanceId, config);
|
|
1830
|
+
async setInstanceConfig(instanceId, config) {
|
|
1831
|
+
await this.configManager.setInstanceConfig(instanceId, config);
|
|
1788
1832
|
}
|
|
1789
1833
|
/**
|
|
1790
1834
|
* Discovers available providers by checking environment variables and local health.
|
|
@@ -1868,17 +1912,12 @@ var IKFirewallCore = class _IKFirewallCore {
|
|
|
1868
1912
|
this.hydrated = true;
|
|
1869
1913
|
}
|
|
1870
1914
|
if (instanceId) {
|
|
1871
|
-
this.configManager.ensureInstanceConfig(instanceId);
|
|
1872
|
-
this.configManager.syncRemoteConfig(instanceId).catch((err) => {
|
|
1873
|
-
console.warn("[IK_CORE] Heartbeat sync failed:", err);
|
|
1874
|
-
});
|
|
1915
|
+
await this.configManager.ensureInstanceConfig(instanceId);
|
|
1875
1916
|
}
|
|
1876
1917
|
const mergedConfig = this.configManager.getMergedConfig(instanceId);
|
|
1877
|
-
if (instanceId && mergedConfig?.
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
return this.getEmptyMetrics();
|
|
1881
|
-
}
|
|
1918
|
+
if (instanceId && mergedConfig?.billingStatus === "blocked") {
|
|
1919
|
+
this.hooks?.onStatus?.("\u26A0\uFE0F [IK_FIREWALL] Subscription inactive. Optimization bypassed (Fail-Safe mode).");
|
|
1920
|
+
return this.getEmptyMetrics();
|
|
1882
1921
|
}
|
|
1883
1922
|
let auditProvider = this.localProvider;
|
|
1884
1923
|
let overrideProvider = null;
|
|
@@ -2008,7 +2047,7 @@ var IKFirewallCore = class _IKFirewallCore {
|
|
|
2008
2047
|
}
|
|
2009
2048
|
async analyzeAIAssisted(input, provider, personaName = "professional", instanceId, configOverride) {
|
|
2010
2049
|
if (instanceId) {
|
|
2011
|
-
this.configManager.ensureInstanceConfig(instanceId);
|
|
2050
|
+
await this.configManager.ensureInstanceConfig(instanceId);
|
|
2012
2051
|
}
|
|
2013
2052
|
const activeConfig = this.configManager.getMergedConfig(instanceId, configOverride);
|
|
2014
2053
|
const locale = activeConfig?.locale || "en";
|
package/dist/index.d.cts
CHANGED
|
@@ -340,8 +340,8 @@ declare class IKFirewallCore {
|
|
|
340
340
|
getConfig(): IKConfig;
|
|
341
341
|
getPlugins(): IKPluginInfo[];
|
|
342
342
|
getSessionDNA(): number;
|
|
343
|
-
getInstanceConfigs(): Record<string, Partial<IKConfig
|
|
344
|
-
setInstanceConfig(instanceId: string, config: Partial<IKConfig>): void
|
|
343
|
+
getInstanceConfigs(): Promise<Record<string, Partial<IKConfig>>>;
|
|
344
|
+
setInstanceConfig(instanceId: string, config: Partial<IKConfig>): Promise<void>;
|
|
345
345
|
/**
|
|
346
346
|
* Discovers available providers by checking environment variables and local health.
|
|
347
347
|
*/
|
package/dist/index.d.ts
CHANGED
|
@@ -340,8 +340,8 @@ declare class IKFirewallCore {
|
|
|
340
340
|
getConfig(): IKConfig;
|
|
341
341
|
getPlugins(): IKPluginInfo[];
|
|
342
342
|
getSessionDNA(): number;
|
|
343
|
-
getInstanceConfigs(): Record<string, Partial<IKConfig
|
|
344
|
-
setInstanceConfig(instanceId: string, config: Partial<IKConfig>): void
|
|
343
|
+
getInstanceConfigs(): Promise<Record<string, Partial<IKConfig>>>;
|
|
344
|
+
setInstanceConfig(instanceId: string, config: Partial<IKConfig>): Promise<void>;
|
|
345
345
|
/**
|
|
346
346
|
* Discovers available providers by checking environment variables and local health.
|
|
347
347
|
*/
|
package/dist/index.js
CHANGED
|
@@ -48,10 +48,10 @@ var Registry = class _Registry {
|
|
|
48
48
|
/**
|
|
49
49
|
* Loads instance configurations with Hook support
|
|
50
50
|
*/
|
|
51
|
-
load() {
|
|
51
|
+
async load() {
|
|
52
52
|
if (this.hooks?.loadState) {
|
|
53
53
|
try {
|
|
54
|
-
const hookData = this.hooks.loadState("ik_registry");
|
|
54
|
+
const hookData = await this.hooks.loadState("ik_registry");
|
|
55
55
|
if (hookData) return JSON.parse(hookData);
|
|
56
56
|
} catch (e) {
|
|
57
57
|
console.warn("[IK_REGISTRY] Registry load via hook failed, falling back...");
|
|
@@ -72,10 +72,10 @@ var Registry = class _Registry {
|
|
|
72
72
|
}
|
|
73
73
|
return {};
|
|
74
74
|
}
|
|
75
|
-
save(data) {
|
|
75
|
+
async save(data) {
|
|
76
76
|
const jsonStr = JSON.stringify(data, null, 2);
|
|
77
77
|
if (this.hooks?.persistState) {
|
|
78
|
-
this.hooks.persistState("ik_registry", jsonStr);
|
|
78
|
+
await this.hooks.persistState("ik_registry", jsonStr);
|
|
79
79
|
}
|
|
80
80
|
if (fs && this.registryPath) {
|
|
81
81
|
try {
|
|
@@ -90,10 +90,10 @@ var Registry = class _Registry {
|
|
|
90
90
|
}
|
|
91
91
|
}
|
|
92
92
|
}
|
|
93
|
-
updateInstance(instanceId, config) {
|
|
94
|
-
const all = this.load();
|
|
93
|
+
async updateInstance(instanceId, config) {
|
|
94
|
+
const all = await this.load();
|
|
95
95
|
all[instanceId] = { ...all[instanceId] || {}, ...config, updatedAt: (/* @__PURE__ */ new Date()).toISOString() };
|
|
96
|
-
this.save(all);
|
|
96
|
+
await this.save(all);
|
|
97
97
|
}
|
|
98
98
|
getUsageFilePath() {
|
|
99
99
|
return this.usagePath;
|
|
@@ -116,13 +116,25 @@ var Registry = class _Registry {
|
|
|
116
116
|
} catch (e) {
|
|
117
117
|
}
|
|
118
118
|
}
|
|
119
|
-
clearUsage() {
|
|
119
|
+
async clearUsage() {
|
|
120
120
|
if (!fs || !this.usagePath) return;
|
|
121
121
|
try {
|
|
122
122
|
if (fs.existsSync(this.usagePath)) fs.unlinkSync(this.usagePath);
|
|
123
123
|
} catch (e) {
|
|
124
124
|
}
|
|
125
125
|
}
|
|
126
|
+
async getLastFlushTime() {
|
|
127
|
+
if (this.hooks?.loadState) {
|
|
128
|
+
const val = await this.hooks.loadState("ik_last_flush");
|
|
129
|
+
if (val) return parseInt(val, 10);
|
|
130
|
+
}
|
|
131
|
+
return null;
|
|
132
|
+
}
|
|
133
|
+
async setLastFlushTime(time) {
|
|
134
|
+
if (this.hooks?.persistState) {
|
|
135
|
+
await this.hooks.persistState("ik_last_flush", time.toString());
|
|
136
|
+
}
|
|
137
|
+
}
|
|
126
138
|
};
|
|
127
139
|
|
|
128
140
|
// src/lib/hmac.ts
|
|
@@ -160,6 +172,7 @@ var ConfigManager = class {
|
|
|
160
172
|
config;
|
|
161
173
|
registry;
|
|
162
174
|
hooks;
|
|
175
|
+
blockedInstances = /* @__PURE__ */ new Set();
|
|
163
176
|
constructor(initialConfig, hooks) {
|
|
164
177
|
this.config = initialConfig;
|
|
165
178
|
this.hooks = hooks;
|
|
@@ -167,7 +180,6 @@ var ConfigManager = class {
|
|
|
167
180
|
if (hooks) {
|
|
168
181
|
this.registry.setHooks(hooks);
|
|
169
182
|
}
|
|
170
|
-
this.loadFromRegistry();
|
|
171
183
|
}
|
|
172
184
|
getRegistry() {
|
|
173
185
|
return this.registry;
|
|
@@ -183,16 +195,16 @@ var ConfigManager = class {
|
|
|
183
195
|
if (state) {
|
|
184
196
|
const parsed = JSON.parse(state);
|
|
185
197
|
const registry = this.registry;
|
|
186
|
-
registry.save(parsed);
|
|
187
|
-
this.loadFromRegistry();
|
|
198
|
+
await registry.save(parsed);
|
|
199
|
+
await this.loadFromRegistry();
|
|
188
200
|
}
|
|
189
201
|
} catch (e) {
|
|
190
202
|
console.warn("[IK_CONFIG] Hydration from hooks failed:", e);
|
|
191
203
|
}
|
|
192
204
|
}
|
|
193
205
|
}
|
|
194
|
-
loadFromRegistry() {
|
|
195
|
-
const instanceConfigs = this.registry.load();
|
|
206
|
+
async loadFromRegistry() {
|
|
207
|
+
const instanceConfigs = await this.registry.load();
|
|
196
208
|
this.config.instanceConfigs = {
|
|
197
209
|
...this.config.instanceConfigs || {},
|
|
198
210
|
...instanceConfigs
|
|
@@ -234,7 +246,7 @@ var ConfigManager = class {
|
|
|
234
246
|
return;
|
|
235
247
|
}
|
|
236
248
|
}
|
|
237
|
-
this.setInstanceConfig(instanceId, {
|
|
249
|
+
await this.setInstanceConfig(instanceId, {
|
|
238
250
|
billingStatus: data.billingStatus,
|
|
239
251
|
isVerified: data.isVerified,
|
|
240
252
|
pricing: data.pricing,
|
|
@@ -246,7 +258,7 @@ var ConfigManager = class {
|
|
|
246
258
|
}
|
|
247
259
|
} catch (error) {
|
|
248
260
|
console.error(`[IK_CONFIG] Remote sync failed (${error.message}). Falling open (Fail-Open mode).`);
|
|
249
|
-
this.setInstanceConfig(instanceId, {
|
|
261
|
+
await this.setInstanceConfig(instanceId, {
|
|
250
262
|
isVerified: true,
|
|
251
263
|
lastSyncDate: now.toISOString()
|
|
252
264
|
});
|
|
@@ -266,11 +278,27 @@ var ConfigManager = class {
|
|
|
266
278
|
if (instanceId && this.config.instanceConfigs?.[instanceId]) {
|
|
267
279
|
merged = { ...merged, ...this.config.instanceConfigs[instanceId] };
|
|
268
280
|
}
|
|
281
|
+
if (instanceId && this.blockedInstances.has(instanceId)) {
|
|
282
|
+
merged.billingStatus = "blocked";
|
|
283
|
+
}
|
|
269
284
|
if (override) {
|
|
270
285
|
merged = { ...merged, ...override };
|
|
271
286
|
}
|
|
272
287
|
return merged;
|
|
273
288
|
}
|
|
289
|
+
/**
|
|
290
|
+
* Updates the live blocked status for an instance (Kill-Switch).
|
|
291
|
+
* This is used by UsageTracker when it receives a response from the central server.
|
|
292
|
+
*/
|
|
293
|
+
async setBlockedStatus(instanceId, blocked) {
|
|
294
|
+
if (blocked) {
|
|
295
|
+
this.blockedInstances.add(instanceId);
|
|
296
|
+
await this.setInstanceConfig(instanceId, { billingStatus: "blocked" });
|
|
297
|
+
} else {
|
|
298
|
+
this.blockedInstances.delete(instanceId);
|
|
299
|
+
await this.setInstanceConfig(instanceId, { billingStatus: "active" });
|
|
300
|
+
}
|
|
301
|
+
}
|
|
274
302
|
updateConfig(newConfig) {
|
|
275
303
|
this.config = {
|
|
276
304
|
...this.config,
|
|
@@ -309,7 +337,7 @@ var ConfigManager = class {
|
|
|
309
337
|
return false;
|
|
310
338
|
}
|
|
311
339
|
}
|
|
312
|
-
this.setInstanceConfig(instanceId, {
|
|
340
|
+
await this.setInstanceConfig(instanceId, {
|
|
313
341
|
licenseKey: data.licenseKey,
|
|
314
342
|
billingStatus: data.status.toLowerCase(),
|
|
315
343
|
isVerified: true,
|
|
@@ -325,10 +353,10 @@ var ConfigManager = class {
|
|
|
325
353
|
return false;
|
|
326
354
|
}
|
|
327
355
|
}
|
|
328
|
-
ensureInstanceConfig(instanceId) {
|
|
329
|
-
const all = this.registry.load();
|
|
356
|
+
async ensureInstanceConfig(instanceId) {
|
|
357
|
+
const all = await this.registry.load();
|
|
330
358
|
if (!all[instanceId]) {
|
|
331
|
-
this.registry.updateInstance(instanceId, {
|
|
359
|
+
await this.registry.updateInstance(instanceId, {
|
|
332
360
|
balance: this.config.balance || 0.5,
|
|
333
361
|
aggressiveness: this.config.aggressiveness || 0.5,
|
|
334
362
|
isEnabled: true,
|
|
@@ -336,15 +364,15 @@ var ConfigManager = class {
|
|
|
336
364
|
ownerEmail: this.config.ownerEmail
|
|
337
365
|
// Inherit from global if not specific
|
|
338
366
|
});
|
|
339
|
-
this.loadFromRegistry();
|
|
367
|
+
await this.loadFromRegistry();
|
|
340
368
|
}
|
|
341
369
|
}
|
|
342
|
-
getInstanceConfigs() {
|
|
370
|
+
async getInstanceConfigs() {
|
|
343
371
|
return this.registry.load();
|
|
344
372
|
}
|
|
345
|
-
setInstanceConfig(instanceId, config) {
|
|
346
|
-
this.registry.updateInstance(instanceId, config);
|
|
347
|
-
this.loadFromRegistry();
|
|
373
|
+
async setInstanceConfig(instanceId, config) {
|
|
374
|
+
await this.registry.updateInstance(instanceId, config);
|
|
375
|
+
await this.loadFromRegistry();
|
|
348
376
|
}
|
|
349
377
|
};
|
|
350
378
|
|
|
@@ -1463,11 +1491,14 @@ var UsageTracker = class {
|
|
|
1463
1491
|
}
|
|
1464
1492
|
async checkFlushConditions(instanceId) {
|
|
1465
1493
|
const now = Date.now();
|
|
1494
|
+
if (this.lastFlushTime === 0) {
|
|
1495
|
+
const persisted = await this.config.getRegistry().getLastFlushTime();
|
|
1496
|
+
if (persisted) this.lastFlushTime = persisted;
|
|
1497
|
+
else this.lastFlushTime = now;
|
|
1498
|
+
}
|
|
1466
1499
|
const timeSinceFlush = now - this.lastFlushTime;
|
|
1467
1500
|
if (this.aggregationMap.size >= this.BATCH_SIZE_THRESHOLD || timeSinceFlush >= this.TIME_THRESHOLD_MS) {
|
|
1468
|
-
this.performAsyncFlush(instanceId)
|
|
1469
|
-
console.error("[IK_TRACKER] Background flush failed:", err);
|
|
1470
|
-
});
|
|
1501
|
+
await this.performAsyncFlush(instanceId);
|
|
1471
1502
|
}
|
|
1472
1503
|
}
|
|
1473
1504
|
async performAsyncFlush(instanceId) {
|
|
@@ -1476,7 +1507,8 @@ var UsageTracker = class {
|
|
|
1476
1507
|
const reports = Array.from(this.aggregationMap.values());
|
|
1477
1508
|
this.aggregationMap.clear();
|
|
1478
1509
|
this.lastFlushTime = Date.now();
|
|
1479
|
-
const
|
|
1510
|
+
const instanceConfigs = await this.config.getInstanceConfigs();
|
|
1511
|
+
const licenseKey = instanceConfigs[instanceId]?.licenseKey || this.config.get("licenseKey");
|
|
1480
1512
|
const payload = {
|
|
1481
1513
|
licenseKey: licenseKey || "TRIAL-KEY",
|
|
1482
1514
|
instanceId,
|
|
@@ -1509,7 +1541,8 @@ var UsageTracker = class {
|
|
|
1509
1541
|
try {
|
|
1510
1542
|
const crypto = typeof window === "undefined" ? (await import("crypto")).default : null;
|
|
1511
1543
|
if (crypto && crypto.createHmac) {
|
|
1512
|
-
|
|
1544
|
+
const { signature: _sig, ...signablePayload } = payload;
|
|
1545
|
+
payload.signature = crypto.createHmac("sha256", hmacSecret).update(JSON.stringify(signablePayload)).digest("hex");
|
|
1513
1546
|
}
|
|
1514
1547
|
} catch (e) {
|
|
1515
1548
|
}
|
|
@@ -1525,6 +1558,17 @@ var UsageTracker = class {
|
|
|
1525
1558
|
if (!response.ok) {
|
|
1526
1559
|
throw new Error(`HTTP Error: ${response.status} ${response.statusText}`);
|
|
1527
1560
|
}
|
|
1561
|
+
try {
|
|
1562
|
+
const data = await response.json();
|
|
1563
|
+
if (data && (data.status === "blocked" || data.billingStatus === "blocked")) {
|
|
1564
|
+
this.config.setBlockedStatus(payload.instanceId, true);
|
|
1565
|
+
console.warn(`[IK_TRACKER] \u{1F6E1}\uFE0F Kill-Switch triggered for ${payload.instanceId}: Subscription inactive/blocked.`);
|
|
1566
|
+
} else if (data && (data.status === "active" || data.billingStatus === "active" || data.status === "trial")) {
|
|
1567
|
+
this.config.setBlockedStatus(payload.instanceId, false);
|
|
1568
|
+
}
|
|
1569
|
+
} catch (e) {
|
|
1570
|
+
}
|
|
1571
|
+
await this.config.getRegistry().setLastFlushTime(this.lastFlushTime);
|
|
1528
1572
|
this.hooks?.onFlushSuccess?.(payload);
|
|
1529
1573
|
}
|
|
1530
1574
|
async handleFailure(payload) {
|
|
@@ -1738,11 +1782,11 @@ var IKFirewallCore = class _IKFirewallCore {
|
|
|
1738
1782
|
getSessionDNA() {
|
|
1739
1783
|
return this.sessionDNA;
|
|
1740
1784
|
}
|
|
1741
|
-
getInstanceConfigs() {
|
|
1785
|
+
async getInstanceConfigs() {
|
|
1742
1786
|
return this.configManager.getInstanceConfigs();
|
|
1743
1787
|
}
|
|
1744
|
-
setInstanceConfig(instanceId, config) {
|
|
1745
|
-
this.configManager.setInstanceConfig(instanceId, config);
|
|
1788
|
+
async setInstanceConfig(instanceId, config) {
|
|
1789
|
+
await this.configManager.setInstanceConfig(instanceId, config);
|
|
1746
1790
|
}
|
|
1747
1791
|
/**
|
|
1748
1792
|
* Discovers available providers by checking environment variables and local health.
|
|
@@ -1826,17 +1870,12 @@ var IKFirewallCore = class _IKFirewallCore {
|
|
|
1826
1870
|
this.hydrated = true;
|
|
1827
1871
|
}
|
|
1828
1872
|
if (instanceId) {
|
|
1829
|
-
this.configManager.ensureInstanceConfig(instanceId);
|
|
1830
|
-
this.configManager.syncRemoteConfig(instanceId).catch((err) => {
|
|
1831
|
-
console.warn("[IK_CORE] Heartbeat sync failed:", err);
|
|
1832
|
-
});
|
|
1873
|
+
await this.configManager.ensureInstanceConfig(instanceId);
|
|
1833
1874
|
}
|
|
1834
1875
|
const mergedConfig = this.configManager.getMergedConfig(instanceId);
|
|
1835
|
-
if (instanceId && mergedConfig?.
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
return this.getEmptyMetrics();
|
|
1839
|
-
}
|
|
1876
|
+
if (instanceId && mergedConfig?.billingStatus === "blocked") {
|
|
1877
|
+
this.hooks?.onStatus?.("\u26A0\uFE0F [IK_FIREWALL] Subscription inactive. Optimization bypassed (Fail-Safe mode).");
|
|
1878
|
+
return this.getEmptyMetrics();
|
|
1840
1879
|
}
|
|
1841
1880
|
let auditProvider = this.localProvider;
|
|
1842
1881
|
let overrideProvider = null;
|
|
@@ -1966,7 +2005,7 @@ var IKFirewallCore = class _IKFirewallCore {
|
|
|
1966
2005
|
}
|
|
1967
2006
|
async analyzeAIAssisted(input, provider, personaName = "professional", instanceId, configOverride) {
|
|
1968
2007
|
if (instanceId) {
|
|
1969
|
-
this.configManager.ensureInstanceConfig(instanceId);
|
|
2008
|
+
await this.configManager.ensureInstanceConfig(instanceId);
|
|
1970
2009
|
}
|
|
1971
2010
|
const activeConfig = this.configManager.getMergedConfig(instanceId, configOverride);
|
|
1972
2011
|
const locale = activeConfig?.locale || "en";
|