@tracehound/core 1.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/README.md +125 -0
- package/dist/core/agent.d.ts +89 -0
- package/dist/core/agent.d.ts.map +1 -0
- package/dist/core/agent.js +141 -0
- package/dist/core/agent.js.map +1 -0
- package/dist/core/audit-chain.d.ts +39 -0
- package/dist/core/audit-chain.d.ts.map +1 -0
- package/dist/core/audit-chain.js +87 -0
- package/dist/core/audit-chain.js.map +1 -0
- package/dist/core/cold-storage.d.ts +87 -0
- package/dist/core/cold-storage.d.ts.map +1 -0
- package/dist/core/cold-storage.js +53 -0
- package/dist/core/cold-storage.js.map +1 -0
- package/dist/core/evidence-factory.d.ts +85 -0
- package/dist/core/evidence-factory.d.ts.map +1 -0
- package/dist/core/evidence-factory.js +96 -0
- package/dist/core/evidence-factory.js.map +1 -0
- package/dist/core/evidence.d.ts +48 -0
- package/dist/core/evidence.d.ts.map +1 -0
- package/dist/core/evidence.js +135 -0
- package/dist/core/evidence.js.map +1 -0
- package/dist/core/fail-safe.d.ts +149 -0
- package/dist/core/fail-safe.d.ts.map +1 -0
- package/dist/core/fail-safe.js +217 -0
- package/dist/core/fail-safe.js.map +1 -0
- package/dist/core/hound-ipc.d.ts +91 -0
- package/dist/core/hound-ipc.d.ts.map +1 -0
- package/dist/core/hound-ipc.js +196 -0
- package/dist/core/hound-ipc.js.map +1 -0
- package/dist/core/hound-pool.d.ts +157 -0
- package/dist/core/hound-pool.d.ts.map +1 -0
- package/dist/core/hound-pool.js +337 -0
- package/dist/core/hound-pool.js.map +1 -0
- package/dist/core/hound-process.d.ts +14 -0
- package/dist/core/hound-process.d.ts.map +1 -0
- package/dist/core/hound-process.js +112 -0
- package/dist/core/hound-process.js.map +1 -0
- package/dist/core/hound-worker.d.ts +14 -0
- package/dist/core/hound-worker.d.ts.map +1 -0
- package/dist/core/hound-worker.js +112 -0
- package/dist/core/hound-worker.js.map +1 -0
- package/dist/core/lane-queue.d.ts +121 -0
- package/dist/core/lane-queue.d.ts.map +1 -0
- package/dist/core/lane-queue.js +181 -0
- package/dist/core/lane-queue.js.map +1 -0
- package/dist/core/license-manager.d.ts +128 -0
- package/dist/core/license-manager.d.ts.map +1 -0
- package/dist/core/license-manager.js +219 -0
- package/dist/core/license-manager.js.map +1 -0
- package/dist/core/notification-emitter.d.ts +140 -0
- package/dist/core/notification-emitter.d.ts.map +1 -0
- package/dist/core/notification-emitter.js +197 -0
- package/dist/core/notification-emitter.js.map +1 -0
- package/dist/core/process-adapter.d.ts +146 -0
- package/dist/core/process-adapter.d.ts.map +1 -0
- package/dist/core/process-adapter.js +174 -0
- package/dist/core/process-adapter.js.map +1 -0
- package/dist/core/quarantine.d.ts +95 -0
- package/dist/core/quarantine.d.ts.map +1 -0
- package/dist/core/quarantine.js +221 -0
- package/dist/core/quarantine.js.map +1 -0
- package/dist/core/rate-limiter.d.ts +94 -0
- package/dist/core/rate-limiter.d.ts.map +1 -0
- package/dist/core/rate-limiter.js +156 -0
- package/dist/core/rate-limiter.js.map +1 -0
- package/dist/core/s3-cold-storage.d.ts +116 -0
- package/dist/core/s3-cold-storage.d.ts.map +1 -0
- package/dist/core/s3-cold-storage.js +198 -0
- package/dist/core/s3-cold-storage.js.map +1 -0
- package/dist/core/scheduler.d.ts +126 -0
- package/dist/core/scheduler.d.ts.map +1 -0
- package/dist/core/scheduler.js +138 -0
- package/dist/core/scheduler.js.map +1 -0
- package/dist/core/security-state.d.ts +170 -0
- package/dist/core/security-state.d.ts.map +1 -0
- package/dist/core/security-state.js +156 -0
- package/dist/core/security-state.js.map +1 -0
- package/dist/core/tier-capacity.d.ts +58 -0
- package/dist/core/tier-capacity.d.ts.map +1 -0
- package/dist/core/tier-capacity.js +89 -0
- package/dist/core/tier-capacity.js.map +1 -0
- package/dist/core/tracehound.d.ts +85 -0
- package/dist/core/tracehound.d.ts.map +1 -0
- package/dist/core/tracehound.js +90 -0
- package/dist/core/tracehound.js.map +1 -0
- package/dist/core/trust-boundary.d.ts +85 -0
- package/dist/core/trust-boundary.d.ts.map +1 -0
- package/dist/core/trust-boundary.js +71 -0
- package/dist/core/trust-boundary.js.map +1 -0
- package/dist/core/watcher.d.ts +153 -0
- package/dist/core/watcher.d.ts.map +1 -0
- package/dist/core/watcher.js +141 -0
- package/dist/core/watcher.js.map +1 -0
- package/dist/index.d.ts +53 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +112 -0
- package/dist/index.js.map +1 -0
- package/dist/types/audit.d.ts +45 -0
- package/dist/types/audit.d.ts.map +1 -0
- package/dist/types/audit.js +5 -0
- package/dist/types/audit.js.map +1 -0
- package/dist/types/common.d.ts +12 -0
- package/dist/types/common.d.ts.map +1 -0
- package/dist/types/common.js +5 -0
- package/dist/types/common.js.map +1 -0
- package/dist/types/config.d.ts +98 -0
- package/dist/types/config.d.ts.map +1 -0
- package/dist/types/config.js +58 -0
- package/dist/types/config.js.map +1 -0
- package/dist/types/errors.d.ts +118 -0
- package/dist/types/errors.d.ts.map +1 -0
- package/dist/types/errors.js +266 -0
- package/dist/types/errors.js.map +1 -0
- package/dist/types/evidence.d.ts +102 -0
- package/dist/types/evidence.d.ts.map +1 -0
- package/dist/types/evidence.js +5 -0
- package/dist/types/evidence.js.map +1 -0
- package/dist/types/index.d.ts +18 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +9 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/result.d.ts +62 -0
- package/dist/types/result.d.ts.map +1 -0
- package/dist/types/result.js +34 -0
- package/dist/types/result.js.map +1 -0
- package/dist/types/scent.d.ts +55 -0
- package/dist/types/scent.d.ts.map +1 -0
- package/dist/types/scent.js +5 -0
- package/dist/types/scent.js.map +1 -0
- package/dist/types/signature.d.ts +47 -0
- package/dist/types/signature.d.ts.map +1 -0
- package/dist/types/signature.js +68 -0
- package/dist/types/signature.js.map +1 -0
- package/dist/types/threat.d.ts +38 -0
- package/dist/types/threat.d.ts.map +1 -0
- package/dist/types/threat.js +18 -0
- package/dist/types/threat.js.map +1 -0
- package/dist/utils/binary-codec.d.ts +225 -0
- package/dist/utils/binary-codec.d.ts.map +1 -0
- package/dist/utils/binary-codec.js +266 -0
- package/dist/utils/binary-codec.js.map +1 -0
- package/dist/utils/compare.d.ts +26 -0
- package/dist/utils/compare.d.ts.map +1 -0
- package/dist/utils/compare.js +44 -0
- package/dist/utils/compare.js.map +1 -0
- package/dist/utils/encode.d.ts +39 -0
- package/dist/utils/encode.d.ts.map +1 -0
- package/dist/utils/encode.js +124 -0
- package/dist/utils/encode.js.map +1 -0
- package/dist/utils/hash.d.ts +19 -0
- package/dist/utils/hash.d.ts.map +1 -0
- package/dist/utils/hash.js +25 -0
- package/dist/utils/hash.js.map +1 -0
- package/dist/utils/id.d.ts +20 -0
- package/dist/utils/id.d.ts.map +1 -0
- package/dist/utils/id.js +47 -0
- package/dist/utils/id.js.map +1 -0
- package/dist/utils/runtime.d.ts +24 -0
- package/dist/utils/runtime.d.ts.map +1 -0
- package/dist/utils/runtime.js +68 -0
- package/dist/utils/runtime.js.map +1 -0
- package/dist/utils/serialize.d.ts +14 -0
- package/dist/utils/serialize.d.ts.map +1 -0
- package/dist/utils/serialize.js +27 -0
- package/dist/utils/serialize.js.map +1 -0
- package/package.json +54 -0
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lane Queue - Priority-based alert delivery queue.
|
|
3
|
+
*
|
|
4
|
+
* Lanes allow segregating alerts by criticality level with different
|
|
5
|
+
* processing rates and capacity limits.
|
|
6
|
+
*
|
|
7
|
+
* DESIGN:
|
|
8
|
+
* - 4 lanes: critical, high, medium, low
|
|
9
|
+
* - Each lane has independent capacity and rate limits
|
|
10
|
+
* - Higher priority lanes are processed first
|
|
11
|
+
* - Overflow behavior: oldest low-priority alerts are dropped
|
|
12
|
+
*/
|
|
13
|
+
import type { Severity } from '../types/common.js';
|
|
14
|
+
/**
|
|
15
|
+
* Alert payload structure.
|
|
16
|
+
*/
|
|
17
|
+
export interface Alert {
|
|
18
|
+
/** Unique alert ID */
|
|
19
|
+
id: string;
|
|
20
|
+
/** Alert severity (determines lane) */
|
|
21
|
+
severity: Severity;
|
|
22
|
+
/** Alert type */
|
|
23
|
+
type: 'quarantined' | 'rate_limited' | 'evicted' | 'purged' | 'threshold';
|
|
24
|
+
/** Alert message */
|
|
25
|
+
message: string;
|
|
26
|
+
/** Additional context */
|
|
27
|
+
context?: Record<string, unknown>;
|
|
28
|
+
/** Creation timestamp */
|
|
29
|
+
timestamp: number;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Lane configuration.
|
|
33
|
+
*/
|
|
34
|
+
export interface LaneConfig {
|
|
35
|
+
/** Maximum alerts in this lane */
|
|
36
|
+
maxSize: number;
|
|
37
|
+
/** Maximum alerts per second (0 = unlimited) */
|
|
38
|
+
rateLimit: number;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Full queue configuration.
|
|
42
|
+
*/
|
|
43
|
+
export interface LaneQueueConfig {
|
|
44
|
+
/** Lane configurations by severity */
|
|
45
|
+
lanes: Record<Severity, LaneConfig>;
|
|
46
|
+
/** What to do when queue is full */
|
|
47
|
+
overflow: 'drop_oldest' | 'drop_lowest' | 'reject';
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Lane statistics.
|
|
51
|
+
*/
|
|
52
|
+
export interface LaneStats {
|
|
53
|
+
/** Current count per severity */
|
|
54
|
+
counts: Record<Severity, number>;
|
|
55
|
+
/** Total dropped alerts */
|
|
56
|
+
dropped: number;
|
|
57
|
+
/** Total processed alerts */
|
|
58
|
+
processed: number;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Default configuration.
|
|
62
|
+
*/
|
|
63
|
+
export declare const DEFAULT_LANE_CONFIG: LaneQueueConfig;
|
|
64
|
+
/**
|
|
65
|
+
* Lane Queue implementation.
|
|
66
|
+
*/
|
|
67
|
+
export declare class LaneQueue {
|
|
68
|
+
private config;
|
|
69
|
+
private lanes;
|
|
70
|
+
private droppedCount;
|
|
71
|
+
private processedCount;
|
|
72
|
+
private handlers;
|
|
73
|
+
constructor(config?: LaneQueueConfig);
|
|
74
|
+
/**
|
|
75
|
+
* Add an alert to the appropriate lane.
|
|
76
|
+
*
|
|
77
|
+
* @param alert - Alert to enqueue
|
|
78
|
+
* @returns true if enqueued, false if dropped
|
|
79
|
+
*/
|
|
80
|
+
enqueue(alert: Alert): boolean;
|
|
81
|
+
/**
|
|
82
|
+
* Dequeue the next highest priority alert.
|
|
83
|
+
*
|
|
84
|
+
* @returns Next alert or undefined if empty
|
|
85
|
+
*/
|
|
86
|
+
dequeue(): Alert | undefined;
|
|
87
|
+
/**
|
|
88
|
+
* Register an alert handler.
|
|
89
|
+
*
|
|
90
|
+
* @param handler - Function to call for each alert
|
|
91
|
+
*/
|
|
92
|
+
onAlert(handler: (alert: Alert) => void): void;
|
|
93
|
+
/**
|
|
94
|
+
* Process all pending alerts through handlers.
|
|
95
|
+
*
|
|
96
|
+
* @returns Number of alerts processed
|
|
97
|
+
*/
|
|
98
|
+
flush(): number;
|
|
99
|
+
/**
|
|
100
|
+
* Get current statistics.
|
|
101
|
+
*/
|
|
102
|
+
get stats(): LaneStats;
|
|
103
|
+
/**
|
|
104
|
+
* Get total pending alerts.
|
|
105
|
+
*/
|
|
106
|
+
get size(): number;
|
|
107
|
+
/**
|
|
108
|
+
* Handle overflow based on configuration.
|
|
109
|
+
*
|
|
110
|
+
* @returns true if space was made, false otherwise
|
|
111
|
+
*/
|
|
112
|
+
private handleOverflow;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Create a lane queue.
|
|
116
|
+
*
|
|
117
|
+
* @param config - Optional configuration
|
|
118
|
+
* @returns LaneQueue instance
|
|
119
|
+
*/
|
|
120
|
+
export declare function createLaneQueue(config?: Partial<LaneQueueConfig>): LaneQueue;
|
|
121
|
+
//# sourceMappingURL=lane-queue.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lane-queue.d.ts","sourceRoot":"","sources":["../../src/core/lane-queue.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAMH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAA;AAElD;;GAEG;AACH,MAAM,WAAW,KAAK;IACpB,sBAAsB;IACtB,EAAE,EAAE,MAAM,CAAA;IACV,uCAAuC;IACvC,QAAQ,EAAE,QAAQ,CAAA;IAClB,iBAAiB;IACjB,IAAI,EAAE,aAAa,GAAG,cAAc,GAAG,SAAS,GAAG,QAAQ,GAAG,WAAW,CAAA;IACzE,oBAAoB;IACpB,OAAO,EAAE,MAAM,CAAA;IACf,yBAAyB;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACjC,yBAAyB;IACzB,SAAS,EAAE,MAAM,CAAA;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,kCAAkC;IAClC,OAAO,EAAE,MAAM,CAAA;IACf,gDAAgD;IAChD,SAAS,EAAE,MAAM,CAAA;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,sCAAsC;IACtC,KAAK,EAAE,MAAM,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAA;IACnC,oCAAoC;IACpC,QAAQ,EAAE,aAAa,GAAG,aAAa,GAAG,QAAQ,CAAA;CACnD;AAED;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,iCAAiC;IACjC,MAAM,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAA;IAChC,2BAA2B;IAC3B,OAAO,EAAE,MAAM,CAAA;IACf,6BAA6B;IAC7B,SAAS,EAAE,MAAM,CAAA;CAClB;AAED;;GAEG;AACH,eAAO,MAAM,mBAAmB,EAAE,eAQjC,CAAA;AAMD;;GAEG;AACH,qBAAa,SAAS;IAaR,OAAO,CAAC,MAAM;IAZ1B,OAAO,CAAC,KAAK,CAKX;IAEF,OAAO,CAAC,YAAY,CAAI;IACxB,OAAO,CAAC,cAAc,CAAI;IAE1B,OAAO,CAAC,QAAQ,CAAiC;gBAE7B,MAAM,GAAE,eAAqC;IAEjE;;;;;OAKG;IACH,OAAO,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO;IAgB9B;;;;OAIG;IACH,OAAO,IAAI,KAAK,GAAG,SAAS;IAgB5B;;;;OAIG;IACH,OAAO,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,GAAG,IAAI;IAI9C;;;;OAIG;IACH,KAAK,IAAI,MAAM;IAcf;;OAEG;IACH,IAAI,KAAK,IAAI,SAAS,CAWrB;IAED;;OAEG;IACH,IAAI,IAAI,IAAI,MAAM,CAOjB;IAED;;;;OAIG;IACH,OAAO,CAAC,cAAc;CA8BvB;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,eAAe,CAAC,GAAG,SAAS,CAW5E"}
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lane Queue - Priority-based alert delivery queue.
|
|
3
|
+
*
|
|
4
|
+
* Lanes allow segregating alerts by criticality level with different
|
|
5
|
+
* processing rates and capacity limits.
|
|
6
|
+
*
|
|
7
|
+
* DESIGN:
|
|
8
|
+
* - 4 lanes: critical, high, medium, low
|
|
9
|
+
* - Each lane has independent capacity and rate limits
|
|
10
|
+
* - Higher priority lanes are processed first
|
|
11
|
+
* - Overflow behavior: oldest low-priority alerts are dropped
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* Default configuration.
|
|
15
|
+
*/
|
|
16
|
+
export const DEFAULT_LANE_CONFIG = {
|
|
17
|
+
lanes: {
|
|
18
|
+
critical: { maxSize: 1000, rateLimit: 0 }, // Unlimited rate for critical
|
|
19
|
+
high: { maxSize: 500, rateLimit: 100 },
|
|
20
|
+
medium: { maxSize: 200, rateLimit: 50 },
|
|
21
|
+
low: { maxSize: 100, rateLimit: 20 },
|
|
22
|
+
},
|
|
23
|
+
overflow: 'drop_oldest',
|
|
24
|
+
};
|
|
25
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
26
|
+
// Implementation
|
|
27
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
28
|
+
/**
|
|
29
|
+
* Lane Queue implementation.
|
|
30
|
+
*/
|
|
31
|
+
export class LaneQueue {
|
|
32
|
+
config;
|
|
33
|
+
lanes = new Map([
|
|
34
|
+
['critical', []],
|
|
35
|
+
['high', []],
|
|
36
|
+
['medium', []],
|
|
37
|
+
['low', []],
|
|
38
|
+
]);
|
|
39
|
+
droppedCount = 0;
|
|
40
|
+
processedCount = 0;
|
|
41
|
+
handlers = [];
|
|
42
|
+
constructor(config = DEFAULT_LANE_CONFIG) {
|
|
43
|
+
this.config = config;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Add an alert to the appropriate lane.
|
|
47
|
+
*
|
|
48
|
+
* @param alert - Alert to enqueue
|
|
49
|
+
* @returns true if enqueued, false if dropped
|
|
50
|
+
*/
|
|
51
|
+
enqueue(alert) {
|
|
52
|
+
const lane = this.lanes.get(alert.severity);
|
|
53
|
+
const laneConfig = this.config.lanes[alert.severity];
|
|
54
|
+
// Check capacity
|
|
55
|
+
if (lane.length >= laneConfig.maxSize) {
|
|
56
|
+
if (!this.handleOverflow(alert.severity)) {
|
|
57
|
+
this.droppedCount++;
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
lane.push(alert);
|
|
62
|
+
return true;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Dequeue the next highest priority alert.
|
|
66
|
+
*
|
|
67
|
+
* @returns Next alert or undefined if empty
|
|
68
|
+
*/
|
|
69
|
+
dequeue() {
|
|
70
|
+
// Process in priority order: critical → high → medium → low
|
|
71
|
+
const priorities = ['critical', 'high', 'medium', 'low'];
|
|
72
|
+
for (const severity of priorities) {
|
|
73
|
+
const lane = this.lanes.get(severity);
|
|
74
|
+
if (lane.length > 0) {
|
|
75
|
+
const alert = lane.shift();
|
|
76
|
+
this.processedCount++;
|
|
77
|
+
return alert;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return undefined;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Register an alert handler.
|
|
84
|
+
*
|
|
85
|
+
* @param handler - Function to call for each alert
|
|
86
|
+
*/
|
|
87
|
+
onAlert(handler) {
|
|
88
|
+
this.handlers.push(handler);
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Process all pending alerts through handlers.
|
|
92
|
+
*
|
|
93
|
+
* @returns Number of alerts processed
|
|
94
|
+
*/
|
|
95
|
+
flush() {
|
|
96
|
+
let count = 0;
|
|
97
|
+
let alert;
|
|
98
|
+
while ((alert = this.dequeue())) {
|
|
99
|
+
for (const handler of this.handlers) {
|
|
100
|
+
handler(alert);
|
|
101
|
+
}
|
|
102
|
+
count++;
|
|
103
|
+
}
|
|
104
|
+
return count;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Get current statistics.
|
|
108
|
+
*/
|
|
109
|
+
get stats() {
|
|
110
|
+
return {
|
|
111
|
+
counts: {
|
|
112
|
+
critical: this.lanes.get('critical').length,
|
|
113
|
+
high: this.lanes.get('high').length,
|
|
114
|
+
medium: this.lanes.get('medium').length,
|
|
115
|
+
low: this.lanes.get('low').length,
|
|
116
|
+
},
|
|
117
|
+
dropped: this.droppedCount,
|
|
118
|
+
processed: this.processedCount,
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Get total pending alerts.
|
|
123
|
+
*/
|
|
124
|
+
get size() {
|
|
125
|
+
return (this.lanes.get('critical').length +
|
|
126
|
+
this.lanes.get('high').length +
|
|
127
|
+
this.lanes.get('medium').length +
|
|
128
|
+
this.lanes.get('low').length);
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Handle overflow based on configuration.
|
|
132
|
+
*
|
|
133
|
+
* @returns true if space was made, false otherwise
|
|
134
|
+
*/
|
|
135
|
+
handleOverflow(severity) {
|
|
136
|
+
switch (this.config.overflow) {
|
|
137
|
+
case 'drop_oldest': {
|
|
138
|
+
const lane = this.lanes.get(severity);
|
|
139
|
+
if (lane.length > 0) {
|
|
140
|
+
lane.shift();
|
|
141
|
+
this.droppedCount++;
|
|
142
|
+
return true;
|
|
143
|
+
}
|
|
144
|
+
return false;
|
|
145
|
+
}
|
|
146
|
+
case 'drop_lowest': {
|
|
147
|
+
// Drop from lowest non-empty lane
|
|
148
|
+
const priorities = ['low', 'medium', 'high', 'critical'];
|
|
149
|
+
for (const p of priorities) {
|
|
150
|
+
const lane = this.lanes.get(p);
|
|
151
|
+
if (lane.length > 0) {
|
|
152
|
+
lane.shift();
|
|
153
|
+
this.droppedCount++;
|
|
154
|
+
return true;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
return false;
|
|
158
|
+
}
|
|
159
|
+
case 'reject':
|
|
160
|
+
return false;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Create a lane queue.
|
|
166
|
+
*
|
|
167
|
+
* @param config - Optional configuration
|
|
168
|
+
* @returns LaneQueue instance
|
|
169
|
+
*/
|
|
170
|
+
export function createLaneQueue(config) {
|
|
171
|
+
const mergedConfig = {
|
|
172
|
+
...DEFAULT_LANE_CONFIG,
|
|
173
|
+
...config,
|
|
174
|
+
lanes: {
|
|
175
|
+
...DEFAULT_LANE_CONFIG.lanes,
|
|
176
|
+
...config?.lanes,
|
|
177
|
+
},
|
|
178
|
+
};
|
|
179
|
+
return new LaneQueue(mergedConfig);
|
|
180
|
+
}
|
|
181
|
+
//# sourceMappingURL=lane-queue.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lane-queue.js","sourceRoot":"","sources":["../../src/core/lane-queue.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* License Manager - JWT-based license validation for commercial tiers.
|
|
3
|
+
*
|
|
4
|
+
* CRITICAL INVARIANTS:
|
|
5
|
+
* - Soft Lock: Never crash or block production due to license issues
|
|
6
|
+
* - Offline: Public key embedded, no network required
|
|
7
|
+
* - Grace Period: 7 days tolerance for expired licenses
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* License tiers.
|
|
11
|
+
*/
|
|
12
|
+
export type LicenseTier = 'starter' | 'pro' | 'enterprise';
|
|
13
|
+
/**
|
|
14
|
+
* License validation status.
|
|
15
|
+
*/
|
|
16
|
+
export type LicenseStatus = 'valid' | 'expired' | 'grace' | 'invalid' | 'none';
|
|
17
|
+
/**
|
|
18
|
+
* JWT payload for Tracehound licenses.
|
|
19
|
+
*/
|
|
20
|
+
export interface LicensePayload {
|
|
21
|
+
/** Licensee ID (customer identifier) */
|
|
22
|
+
sub: string;
|
|
23
|
+
/** Issuer (must be "tracehound.io") */
|
|
24
|
+
iss: string;
|
|
25
|
+
/** Audience (product identifier) */
|
|
26
|
+
aud: string;
|
|
27
|
+
/** Expiration timestamp (Unix seconds) */
|
|
28
|
+
exp: number;
|
|
29
|
+
/** Issued at timestamp (Unix seconds) */
|
|
30
|
+
iat: number;
|
|
31
|
+
/** License tier */
|
|
32
|
+
tier: LicenseTier;
|
|
33
|
+
/** Enabled features */
|
|
34
|
+
features: string[];
|
|
35
|
+
/**
|
|
36
|
+
* Maximum concurrent instances allowed.
|
|
37
|
+
* - Pro: 1 (single instance, trust-based)
|
|
38
|
+
* - Enterprise: unlimited (-1) or specific count
|
|
39
|
+
*/
|
|
40
|
+
maxInstances?: number;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* License validation result.
|
|
44
|
+
*/
|
|
45
|
+
export interface LicenseValidationResult {
|
|
46
|
+
/** Whether validation succeeded */
|
|
47
|
+
valid: boolean;
|
|
48
|
+
/** Resulting tier */
|
|
49
|
+
tier: LicenseTier;
|
|
50
|
+
/** Validation status */
|
|
51
|
+
status: LicenseStatus;
|
|
52
|
+
/** Error message if invalid */
|
|
53
|
+
error?: string;
|
|
54
|
+
/** Days until expiration (negative if expired) */
|
|
55
|
+
daysRemaining?: number;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* License Manager configuration.
|
|
59
|
+
*/
|
|
60
|
+
export interface LicenseManagerConfig {
|
|
61
|
+
/** Public key for signature verification (PEM format) */
|
|
62
|
+
publicKey: string;
|
|
63
|
+
/** Expected issuer */
|
|
64
|
+
issuer?: string;
|
|
65
|
+
/** Expected audience */
|
|
66
|
+
audience?: string;
|
|
67
|
+
/** Grace period in days for expired licenses */
|
|
68
|
+
gracePeriodDays?: number;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* License Manager interface.
|
|
72
|
+
*/
|
|
73
|
+
export interface ILicenseManager {
|
|
74
|
+
/**
|
|
75
|
+
* Validate a license key.
|
|
76
|
+
* @param key - JWT license key
|
|
77
|
+
*/
|
|
78
|
+
validate(key: string): LicenseValidationResult;
|
|
79
|
+
/**
|
|
80
|
+
* Check if a feature is enabled.
|
|
81
|
+
* @param feature - Feature name
|
|
82
|
+
*/
|
|
83
|
+
isFeatureEnabled(feature: string): boolean;
|
|
84
|
+
/**
|
|
85
|
+
* Current license tier.
|
|
86
|
+
*/
|
|
87
|
+
readonly tier: LicenseTier;
|
|
88
|
+
/**
|
|
89
|
+
* Current license status.
|
|
90
|
+
*/
|
|
91
|
+
readonly status: LicenseStatus;
|
|
92
|
+
/**
|
|
93
|
+
* Current license payload (if valid).
|
|
94
|
+
*/
|
|
95
|
+
readonly payload: LicensePayload | null;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Features available per tier.
|
|
99
|
+
*/
|
|
100
|
+
export declare const TIER_FEATURES: Record<LicenseTier, readonly string[]>;
|
|
101
|
+
/**
|
|
102
|
+
* License Manager implementation.
|
|
103
|
+
*/
|
|
104
|
+
export declare class LicenseManager implements ILicenseManager {
|
|
105
|
+
private readonly config;
|
|
106
|
+
private _tier;
|
|
107
|
+
private _status;
|
|
108
|
+
private _payload;
|
|
109
|
+
private _features;
|
|
110
|
+
constructor(config: LicenseManagerConfig);
|
|
111
|
+
get tier(): LicenseTier;
|
|
112
|
+
get status(): LicenseStatus;
|
|
113
|
+
get payload(): LicensePayload | null;
|
|
114
|
+
validate(key: string): LicenseValidationResult;
|
|
115
|
+
isFeatureEnabled(feature: string): boolean;
|
|
116
|
+
private verifySignature;
|
|
117
|
+
private decodePayload;
|
|
118
|
+
private base64UrlDecode;
|
|
119
|
+
private setCommunity;
|
|
120
|
+
private setValid;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Create a License Manager instance.
|
|
124
|
+
*
|
|
125
|
+
* @param config - License manager configuration
|
|
126
|
+
*/
|
|
127
|
+
export declare function createLicenseManager(config: LicenseManagerConfig): ILicenseManager;
|
|
128
|
+
//# sourceMappingURL=license-manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"license-manager.d.ts","sourceRoot":"","sources":["../../src/core/license-manager.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAQH;;GAEG;AACH,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG,KAAK,GAAG,YAAY,CAAA;AAE1D;;GAEG;AACH,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG,SAAS,GAAG,OAAO,GAAG,SAAS,GAAG,MAAM,CAAA;AAE9E;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,wCAAwC;IACxC,GAAG,EAAE,MAAM,CAAA;IACX,uCAAuC;IACvC,GAAG,EAAE,MAAM,CAAA;IACX,oCAAoC;IACpC,GAAG,EAAE,MAAM,CAAA;IACX,0CAA0C;IAC1C,GAAG,EAAE,MAAM,CAAA;IACX,yCAAyC;IACzC,GAAG,EAAE,MAAM,CAAA;IACX,mBAAmB;IACnB,IAAI,EAAE,WAAW,CAAA;IACjB,uBAAuB;IACvB,QAAQ,EAAE,MAAM,EAAE,CAAA;IAClB;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB;AAED;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACtC,mCAAmC;IACnC,KAAK,EAAE,OAAO,CAAA;IACd,qBAAqB;IACrB,IAAI,EAAE,WAAW,CAAA;IACjB,wBAAwB;IACxB,MAAM,EAAE,aAAa,CAAA;IACrB,+BAA+B;IAC/B,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,kDAAkD;IAClD,aAAa,CAAC,EAAE,MAAM,CAAA;CACvB;AAED;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,yDAAyD;IACzD,SAAS,EAAE,MAAM,CAAA;IACjB,sBAAsB;IACtB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,wBAAwB;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,gDAAgD;IAChD,eAAe,CAAC,EAAE,MAAM,CAAA;CACzB;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B;;;OAGG;IACH,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,uBAAuB,CAAA;IAE9C;;;OAGG;IACH,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAA;IAE1C;;OAEG;IACH,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAA;IAE1B;;OAEG;IACH,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAA;IAE9B;;OAEG;IACH,QAAQ,CAAC,OAAO,EAAE,cAAc,GAAG,IAAI,CAAA;CACxC;AAWD;;GAEG;AACH,eAAO,MAAM,aAAa,EAAE,MAAM,CAAC,WAAW,EAAE,SAAS,MAAM,EAAE,CAyBvD,CAAA;AAMV;;GAEG;AACH,qBAAa,cAAe,YAAW,eAAe;IACpD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAgC;IACvD,OAAO,CAAC,KAAK,CAAyB;IACtC,OAAO,CAAC,OAAO,CAAwB;IACvC,OAAO,CAAC,QAAQ,CAA8B;IAC9C,OAAO,CAAC,SAAS,CAA8C;gBAEnD,MAAM,EAAE,oBAAoB;IASxC,IAAI,IAAI,IAAI,WAAW,CAEtB;IAED,IAAI,MAAM,IAAI,aAAa,CAE1B;IAED,IAAI,OAAO,IAAI,cAAc,GAAG,IAAI,CAEnC;IAED,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,uBAAuB;IA6D9C,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO;IAM1C,OAAO,CAAC,eAAe;IAcvB,OAAO,CAAC,aAAa;IA6BrB,OAAO,CAAC,eAAe;IAavB,OAAO,CAAC,YAAY;IAmBpB,OAAO,CAAC,QAAQ;CAoBjB;AAMD;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,oBAAoB,GAAG,eAAe,CAElF"}
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* License Manager - JWT-based license validation for commercial tiers.
|
|
3
|
+
*
|
|
4
|
+
* CRITICAL INVARIANTS:
|
|
5
|
+
* - Soft Lock: Never crash or block production due to license issues
|
|
6
|
+
* - Offline: Public key embedded, no network required
|
|
7
|
+
* - Grace Period: 7 days tolerance for expired licenses
|
|
8
|
+
*/
|
|
9
|
+
import { createVerify } from 'node:crypto';
|
|
10
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
11
|
+
// Constants
|
|
12
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
13
|
+
const DEFAULT_ISSUER = 'tracehound.io';
|
|
14
|
+
const DEFAULT_AUDIENCE = 'tracehound-core';
|
|
15
|
+
const DEFAULT_GRACE_PERIOD_DAYS = 7;
|
|
16
|
+
const MS_PER_DAY = 24 * 60 * 60 * 1000;
|
|
17
|
+
/**
|
|
18
|
+
* Features available per tier.
|
|
19
|
+
*/
|
|
20
|
+
export const TIER_FEATURES = {
|
|
21
|
+
starter: ['agent', 'quarantine', 'rate-limiter', 'watcher', 'scheduler'],
|
|
22
|
+
pro: [
|
|
23
|
+
'agent',
|
|
24
|
+
'quarantine',
|
|
25
|
+
'rate-limiter',
|
|
26
|
+
'watcher',
|
|
27
|
+
'scheduler',
|
|
28
|
+
'cold-storage',
|
|
29
|
+
'notification-api',
|
|
30
|
+
'async-codec',
|
|
31
|
+
],
|
|
32
|
+
enterprise: [
|
|
33
|
+
'agent',
|
|
34
|
+
'quarantine',
|
|
35
|
+
'rate-limiter',
|
|
36
|
+
'watcher',
|
|
37
|
+
'scheduler',
|
|
38
|
+
'cold-storage',
|
|
39
|
+
'notification-api',
|
|
40
|
+
'async-codec',
|
|
41
|
+
'redis',
|
|
42
|
+
'siem-export',
|
|
43
|
+
'compliance-reports',
|
|
44
|
+
],
|
|
45
|
+
};
|
|
46
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
47
|
+
// Implementation
|
|
48
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
49
|
+
/**
|
|
50
|
+
* License Manager implementation.
|
|
51
|
+
*/
|
|
52
|
+
export class LicenseManager {
|
|
53
|
+
config;
|
|
54
|
+
_tier = 'starter';
|
|
55
|
+
_status = 'none';
|
|
56
|
+
_payload = null;
|
|
57
|
+
_features = new Set(TIER_FEATURES.starter);
|
|
58
|
+
constructor(config) {
|
|
59
|
+
this.config = {
|
|
60
|
+
publicKey: config.publicKey,
|
|
61
|
+
issuer: config.issuer ?? DEFAULT_ISSUER,
|
|
62
|
+
audience: config.audience ?? DEFAULT_AUDIENCE,
|
|
63
|
+
gracePeriodDays: config.gracePeriodDays ?? DEFAULT_GRACE_PERIOD_DAYS,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
get tier() {
|
|
67
|
+
return this._tier;
|
|
68
|
+
}
|
|
69
|
+
get status() {
|
|
70
|
+
return this._status;
|
|
71
|
+
}
|
|
72
|
+
get payload() {
|
|
73
|
+
return this._payload;
|
|
74
|
+
}
|
|
75
|
+
validate(key) {
|
|
76
|
+
// Empty key = community mode
|
|
77
|
+
if (!key || key.trim() === '') {
|
|
78
|
+
return this.setCommunity('none');
|
|
79
|
+
}
|
|
80
|
+
try {
|
|
81
|
+
// Parse JWT
|
|
82
|
+
const parts = key.split('.');
|
|
83
|
+
if (parts.length !== 3) {
|
|
84
|
+
return this.setCommunity('invalid', 'Invalid JWT format');
|
|
85
|
+
}
|
|
86
|
+
const [headerB64, payloadB64, signatureB64] = parts;
|
|
87
|
+
// Verify signature
|
|
88
|
+
if (!this.verifySignature(headerB64, payloadB64, signatureB64)) {
|
|
89
|
+
return this.setCommunity('invalid', 'Invalid signature');
|
|
90
|
+
}
|
|
91
|
+
// Decode payload
|
|
92
|
+
const payload = this.decodePayload(payloadB64);
|
|
93
|
+
if (!payload) {
|
|
94
|
+
return this.setCommunity('invalid', 'Invalid payload');
|
|
95
|
+
}
|
|
96
|
+
// Validate issuer
|
|
97
|
+
if (payload.iss !== this.config.issuer) {
|
|
98
|
+
return this.setCommunity('invalid', `Invalid issuer: ${payload.iss}`);
|
|
99
|
+
}
|
|
100
|
+
// Validate audience
|
|
101
|
+
if (payload.aud !== this.config.audience) {
|
|
102
|
+
return this.setCommunity('invalid', `Invalid audience: ${payload.aud}`);
|
|
103
|
+
}
|
|
104
|
+
// Check expiration
|
|
105
|
+
const now = Date.now();
|
|
106
|
+
const expMs = payload.exp * 1000;
|
|
107
|
+
const daysRemaining = Math.floor((expMs - now) / MS_PER_DAY);
|
|
108
|
+
if (now > expMs) {
|
|
109
|
+
// Expired - check grace period
|
|
110
|
+
const daysSinceExpiry = Math.floor((now - expMs) / MS_PER_DAY);
|
|
111
|
+
if (daysSinceExpiry <= this.config.gracePeriodDays) {
|
|
112
|
+
// Grace period - still allow full features
|
|
113
|
+
return this.setValid(payload, 'grace', daysRemaining);
|
|
114
|
+
}
|
|
115
|
+
else {
|
|
116
|
+
// Beyond grace period - community mode
|
|
117
|
+
return this.setCommunity('expired', 'License expired beyond grace period');
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
// Valid license
|
|
121
|
+
return this.setValid(payload, 'valid', daysRemaining);
|
|
122
|
+
}
|
|
123
|
+
catch (err) {
|
|
124
|
+
const message = err instanceof Error ? err.message : 'Unknown error';
|
|
125
|
+
return this.setCommunity('invalid', message);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
isFeatureEnabled(feature) {
|
|
129
|
+
return this._features.has(feature);
|
|
130
|
+
}
|
|
131
|
+
// ─── Private Methods ─────────────────────────────────────────────────────────
|
|
132
|
+
verifySignature(headerB64, payloadB64, signatureB64) {
|
|
133
|
+
try {
|
|
134
|
+
const signatureInput = `${headerB64}.${payloadB64}`;
|
|
135
|
+
const signature = Buffer.from(this.base64UrlDecode(signatureB64), 'base64');
|
|
136
|
+
const verifier = createVerify('RSA-SHA256');
|
|
137
|
+
verifier.update(signatureInput);
|
|
138
|
+
return verifier.verify(this.config.publicKey, signature);
|
|
139
|
+
}
|
|
140
|
+
catch {
|
|
141
|
+
return false;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
decodePayload(payloadB64) {
|
|
145
|
+
try {
|
|
146
|
+
const json = Buffer.from(this.base64UrlDecode(payloadB64), 'base64').toString('utf8');
|
|
147
|
+
const payload = JSON.parse(json);
|
|
148
|
+
// Validate required fields
|
|
149
|
+
if (typeof payload.sub !== 'string' ||
|
|
150
|
+
typeof payload.iss !== 'string' ||
|
|
151
|
+
typeof payload.aud !== 'string' ||
|
|
152
|
+
typeof payload.exp !== 'number' ||
|
|
153
|
+
typeof payload.iat !== 'number' ||
|
|
154
|
+
typeof payload.tier !== 'string' ||
|
|
155
|
+
!Array.isArray(payload.features)) {
|
|
156
|
+
return null;
|
|
157
|
+
}
|
|
158
|
+
// Validate tier
|
|
159
|
+
if (!['starter', 'pro', 'enterprise'].includes(payload.tier)) {
|
|
160
|
+
return null;
|
|
161
|
+
}
|
|
162
|
+
return payload;
|
|
163
|
+
}
|
|
164
|
+
catch {
|
|
165
|
+
return null;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
base64UrlDecode(str) {
|
|
169
|
+
// Convert base64url to base64
|
|
170
|
+
let base64 = str.replace(/-/g, '+').replace(/_/g, '/');
|
|
171
|
+
// Add padding if needed
|
|
172
|
+
const padding = 4 - (base64.length % 4);
|
|
173
|
+
if (padding !== 4) {
|
|
174
|
+
base64 += '='.repeat(padding);
|
|
175
|
+
}
|
|
176
|
+
return base64;
|
|
177
|
+
}
|
|
178
|
+
setCommunity(status, error) {
|
|
179
|
+
this._tier = 'starter';
|
|
180
|
+
this._status = status;
|
|
181
|
+
this._payload = null;
|
|
182
|
+
this._features = new Set(TIER_FEATURES.starter);
|
|
183
|
+
const result = {
|
|
184
|
+
valid: false,
|
|
185
|
+
tier: 'starter',
|
|
186
|
+
status,
|
|
187
|
+
};
|
|
188
|
+
if (error !== undefined) {
|
|
189
|
+
result.error = error;
|
|
190
|
+
}
|
|
191
|
+
return result;
|
|
192
|
+
}
|
|
193
|
+
setValid(payload, status, daysRemaining) {
|
|
194
|
+
this._tier = payload.tier;
|
|
195
|
+
this._status = status;
|
|
196
|
+
this._payload = payload;
|
|
197
|
+
// Set features from tier + any additional from payload
|
|
198
|
+
const tierFeatures = TIER_FEATURES[payload.tier] ?? TIER_FEATURES.starter;
|
|
199
|
+
this._features = new Set([...tierFeatures, ...payload.features]);
|
|
200
|
+
return {
|
|
201
|
+
valid: true,
|
|
202
|
+
tier: payload.tier,
|
|
203
|
+
status,
|
|
204
|
+
daysRemaining,
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
209
|
+
// Factory
|
|
210
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
211
|
+
/**
|
|
212
|
+
* Create a License Manager instance.
|
|
213
|
+
*
|
|
214
|
+
* @param config - License manager configuration
|
|
215
|
+
*/
|
|
216
|
+
export function createLicenseManager(config) {
|
|
217
|
+
return new LicenseManager(config);
|
|
218
|
+
}
|
|
219
|
+
//# sourceMappingURL=license-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"license-manager.js","sourceRoot":"","sources":["../../src/core/license-manager.ts"],"names":[],"mappings":"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"}
|