guardian-risk 0.2.1 → 0.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.d.cts CHANGED
@@ -27,6 +27,7 @@ interface Rule<TSignals extends SignalMap = SignalMap> {
27
27
  readonly score: number;
28
28
  readonly when: (signals: TSignals) => boolean;
29
29
  readonly reason?: string;
30
+ readonly group?: string;
30
31
  }
31
32
  /** Input for creating a new rule (id is auto-generated). */
32
33
  interface CreateRuleInput<TSignals extends SignalMap = SignalMap> {
@@ -35,6 +36,7 @@ interface CreateRuleInput<TSignals extends SignalMap = SignalMap> {
35
36
  readonly score: number;
36
37
  readonly when: (signals: TSignals) => boolean;
37
38
  readonly reason?: string;
39
+ readonly group?: string;
38
40
  }
39
41
  /** A rule that matched during evaluation. */
40
42
  interface MatchedRule {
@@ -42,6 +44,18 @@ interface MatchedRule {
42
44
  readonly name: string;
43
45
  readonly score: number;
44
46
  readonly reason: string;
47
+ readonly group?: string;
48
+ }
49
+ /** Cap applied to the sum of matched rules in a named group. */
50
+ interface RuleGroupCap {
51
+ readonly name: string;
52
+ readonly maxScore: number;
53
+ }
54
+ /** Input for registering a group of related rules with an optional score cap. */
55
+ interface RuleGroupInput<TSignals extends SignalMap = SignalMap> {
56
+ readonly name: string;
57
+ readonly maxScore?: number;
58
+ readonly rules: readonly CreateRuleInput<TSignals>[];
45
59
  }
46
60
 
47
61
  /** Immutable risk analysis report. */
@@ -62,40 +76,137 @@ interface GuardianConfig {
62
76
  readonly levels?: readonly RiskLevelThreshold[];
63
77
  }
64
78
 
79
+ /** Context passed to analyze lifecycle hooks. */
80
+ interface AnalyzeContext<TContext = unknown> {
81
+ /** Caller-provided context (e.g. Express `req`). */
82
+ readonly data: TContext;
83
+ /** Guardian instance being analyzed. */
84
+ readonly guardian: Guardian;
85
+ }
86
+ /** Context passed to afterAnalyze hooks. */
87
+ interface AfterAnalyzeContext<TContext = unknown> extends AnalyzeContext<TContext> {
88
+ readonly report: RiskReport;
89
+ }
90
+ /** Runs before signals are evaluated. May be sync or async. */
91
+ type BeforeAnalyzeHook<TContext = unknown> = (context: AnalyzeContext<TContext>) => void | Promise<void>;
92
+ /** Runs after the risk report is built. May be sync or async. */
93
+ type AfterAnalyzeHook<TContext = unknown> = (context: AfterAnalyzeContext<TContext>) => void | Promise<void>;
94
+
65
95
  /**
66
96
  * Fluent public API for risk analysis.
67
97
  * Collects signals and rules, then produces an immutable report.
98
+ *
99
+ * For concurrent workloads (e.g. HTTP), configure one template instance
100
+ * and call {@link fork} per request.
68
101
  */
69
102
  declare class Guardian {
70
103
  private readonly signalStore;
71
104
  private readonly riskEngine;
72
105
  private readonly pluginRegistry;
106
+ private readonly plugins;
107
+ private readonly beforeHooks;
108
+ private readonly afterHooks;
109
+ private readonly thresholds;
110
+ private analyzing;
73
111
  constructor(config?: GuardianConfig);
74
112
  /**
75
113
  * Add a signal value for risk evaluation.
76
114
  */
77
115
  signal(key: string, value: SignalValue): this;
116
+ /**
117
+ * Read a signal value without modifying state.
118
+ */
119
+ getSignal(key: string): SignalValue | undefined;
78
120
  /**
79
121
  * Register a rule. ID is auto-generated.
80
122
  */
81
123
  rule(input: CreateRuleInput): this;
124
+ /**
125
+ * Register a named group of rules with an optional combined score cap.
126
+ */
127
+ ruleGroup(input: RuleGroupInput): this;
82
128
  /**
83
129
  * Install a plugin. Each plugin name may only be registered once.
84
130
  */
85
131
  use(plugin: Plugin): this;
132
+ /**
133
+ * Register a hook that runs before rule evaluation.
134
+ * Use for loading signals from requests, Redis, IP lookups, etc.
135
+ */
136
+ beforeAnalyze<TContext = unknown>(hook: BeforeAnalyzeHook<TContext>): this;
137
+ /**
138
+ * Register a hook that runs after the report is built.
139
+ * Use for audit logging, metrics, or blocking responses.
140
+ */
141
+ afterAnalyze<TContext = unknown>(hook: AfterAnalyzeHook<TContext>): this;
86
142
  /**
87
143
  * Returns names of installed plugins.
88
144
  */
89
145
  getInstalledPlugins(): readonly string[];
90
146
  /**
91
- * Run risk analysis and return an immutable report.
147
+ * Run risk analysis synchronously (skips lifecycle hooks).
148
+ * Prefer {@link analyzeAsync} when hooks are registered.
92
149
  */
93
150
  analyze(): RiskReport;
94
151
  /**
95
- * Clear all signals. Rules and installed plugins persist across resets.
152
+ * Run lifecycle hooks, evaluate rules, and return an immutable report.
153
+ *
154
+ * @param context Optional caller context passed to hooks (e.g. Express `req`).
155
+ */
156
+ analyzeAsync<TContext = unknown>(context?: TContext): Promise<RiskReport>;
157
+ /**
158
+ * Create an isolated copy sharing rules, plugins, and hooks.
159
+ * Each fork has its own signal store for safe concurrent use.
160
+ */
161
+ fork(): Guardian;
162
+ /**
163
+ * Clear all signals. Rules, plugins, and hooks persist across resets.
96
164
  */
97
165
  reset(): this;
166
+ private assertNotAnalyzing;
167
+ }
168
+
169
+ /** Guardian with typed signal keys and rule predicates. */
170
+ type TypedGuardian<TSignals extends SignalMap> = Guardian & {
171
+ signal<K extends keyof TSignals & string>(key: K, value: TSignals[K]): TypedGuardian<TSignals>;
172
+ rule(input: CreateRuleInput<TSignals>): TypedGuardian<TSignals>;
173
+ };
174
+ /**
175
+ * Define a typed signal schema for compile-time key/value checking.
176
+ *
177
+ * @example
178
+ * ```typescript
179
+ * const botSignals = defineSignals<{
180
+ * mouseLinearity: number;
181
+ * headlessUA: boolean;
182
+ * }>();
183
+ *
184
+ * const guardian = botSignals.create()
185
+ * .signal('mouseLinearity', 0.95) // typed
186
+ * .rule({ name: 'Linear', when: (s) => s.mouseLinearity > 0.9, score: 20 });
187
+ * ```
188
+ */
189
+ declare function defineSignals<TSignals extends SignalMap>(): {
190
+ create(config?: GuardianConfig): TypedGuardian<TSignals>;
191
+ };
192
+
193
+ /**
194
+ * Register a list of preset rules on a Guardian instance.
195
+ */
196
+ declare function applyRules<TSignals extends SignalMap = SignalMap>(guardian: Guardian, rules: readonly CreateRuleInput<TSignals>[]): Guardian;
197
+
198
+ /** Common bot-detection signal keys. */
199
+ interface BotDetectionSignals extends Record<string, SignalValue> {
200
+ mouseLinearity: number;
201
+ requestBurst: number;
202
+ headlessUA: boolean;
203
+ sessionAgeSeconds: number;
204
+ requestsPerMinute: number;
98
205
  }
206
+ /** Ready-to-use bot detection rules (customize scores for your app). */
207
+ declare const botDetectionRules: readonly CreateRuleInput<BotDetectionSignals>[];
208
+ /** Login brute-force rules — use with redis plugin signals. */
209
+ declare const loginProtectionRules: readonly CreateRuleInput[];
99
210
 
100
211
  /**
101
212
  * Builds immutable risk reports.
@@ -119,13 +230,13 @@ declare class RuleEvaluator {
119
230
  }
120
231
 
121
232
  /**
122
- * Calculates risk score from matched rules.
233
+ * Calculates risk score from matched rules with optional per-group caps.
123
234
  */
124
235
  declare class ScoreCalculator {
125
236
  /**
126
- * Sum scores from all matched rules, clamped to a safe maximum.
237
+ * Sum scores from matched rules, applying group caps when configured.
127
238
  */
128
- calculate(matchedRules: readonly MatchedRule[]): number;
239
+ calculate(matchedRules: readonly MatchedRule[], groupCaps?: readonly RuleGroupCap[]): number;
129
240
  }
130
241
 
131
242
  /**
@@ -168,6 +279,7 @@ interface RiskEngineDependencies {
168
279
  declare class RiskEngine {
169
280
  private readonly deps;
170
281
  private readonly rules;
282
+ private readonly groupCaps;
171
283
  private readonly thresholds;
172
284
  constructor(deps: RiskEngineDependencies, thresholds?: readonly RiskLevelThreshold[]);
173
285
  /**
@@ -178,6 +290,14 @@ declare class RiskEngine {
178
290
  * Get all registered rules.
179
291
  */
180
292
  getRules(): readonly Rule<SignalMap>[];
293
+ /**
294
+ * Get configured per-group score caps.
295
+ */
296
+ getGroupCaps(): readonly RuleGroupCap[];
297
+ /**
298
+ * Cap the combined score of matched rules in a group.
299
+ */
300
+ setGroupCap(name: string, maxScore: number): void;
181
301
  /**
182
302
  * Run the full risk analysis pipeline.
183
303
  */
@@ -210,6 +330,11 @@ declare class PluginRegistry {
210
330
  * Check if a plugin is installed by name.
211
331
  */
212
332
  has(name: string): boolean;
333
+ /**
334
+ * Copy installed plugin names from a template (used by Guardian.fork).
335
+ * Does not call install() — rules and hooks are copied separately.
336
+ */
337
+ adoptInstalled(names: readonly string[]): void;
213
338
  /**
214
339
  * Get names of all installed plugins in registration order.
215
340
  */
@@ -232,7 +357,25 @@ declare class RuleBuilder {
232
357
  */
233
358
  declare function resolveLevel(score: number, thresholds?: readonly RiskLevelThreshold[]): string;
234
359
 
360
+ /**
361
+ * Parse and validate an IP address (v4 or v6). Returns null if invalid.
362
+ */
363
+ declare function parseIpAddress(value: string): string | null;
364
+ /**
365
+ * Whether an IP is private, loopback, link-local, or CGNAT (skip external lookup).
366
+ */
367
+ declare function isPrivateIp(ip: string): boolean;
368
+ /**
369
+ * Validate a session identifier (length + charset).
370
+ */
371
+ declare function sanitizeSessionId(value: string): string | null;
372
+
373
+ /** Maximum length for string signal values. */
374
+ declare const MAX_SIGNAL_STRING_LENGTH = 4096;
375
+ /** Default timeout for analyze lifecycle hooks (ms). */
376
+ declare const HOOK_TIMEOUT_MS = 10000;
377
+
235
378
  /** Default risk level thresholds used when none are configured. */
236
379
  declare const DEFAULT_RISK_LEVELS: readonly RiskLevelThreshold[];
237
380
 
238
- export { type CreateRuleInput, DEFAULT_RISK_LEVELS, Guardian, type GuardianConfig, type GuardianPlugin, type MatchedRule, type Plugin, PluginAlreadyInstalledError, PluginInstallError, PluginRegistry, RiskEngine, type RiskEngineDependencies, type RiskLevelThreshold, type RiskReport, type Rule, RuleBuilder, RuleEvaluator, ScoreCalculator, type SignalDefinition, type SignalMap, SignalStore, type SignalValue, resolveLevel };
381
+ export { type AfterAnalyzeContext, type AfterAnalyzeHook, type AnalyzeContext, type BeforeAnalyzeHook, type BotDetectionSignals, type CreateRuleInput, DEFAULT_RISK_LEVELS, Guardian, type GuardianConfig, type GuardianPlugin, HOOK_TIMEOUT_MS, MAX_SIGNAL_STRING_LENGTH, type MatchedRule, type Plugin, PluginAlreadyInstalledError, PluginInstallError, PluginRegistry, RiskEngine, type RiskEngineDependencies, type RiskLevelThreshold, type RiskReport, type Rule, RuleBuilder, RuleEvaluator, type RuleGroupCap, type RuleGroupInput, ScoreCalculator, type SignalDefinition, type SignalMap, SignalStore, type SignalValue, type TypedGuardian, applyRules, botDetectionRules, defineSignals, isPrivateIp, loginProtectionRules, parseIpAddress, resolveLevel, sanitizeSessionId };
package/dist/index.d.ts CHANGED
@@ -27,6 +27,7 @@ interface Rule<TSignals extends SignalMap = SignalMap> {
27
27
  readonly score: number;
28
28
  readonly when: (signals: TSignals) => boolean;
29
29
  readonly reason?: string;
30
+ readonly group?: string;
30
31
  }
31
32
  /** Input for creating a new rule (id is auto-generated). */
32
33
  interface CreateRuleInput<TSignals extends SignalMap = SignalMap> {
@@ -35,6 +36,7 @@ interface CreateRuleInput<TSignals extends SignalMap = SignalMap> {
35
36
  readonly score: number;
36
37
  readonly when: (signals: TSignals) => boolean;
37
38
  readonly reason?: string;
39
+ readonly group?: string;
38
40
  }
39
41
  /** A rule that matched during evaluation. */
40
42
  interface MatchedRule {
@@ -42,6 +44,18 @@ interface MatchedRule {
42
44
  readonly name: string;
43
45
  readonly score: number;
44
46
  readonly reason: string;
47
+ readonly group?: string;
48
+ }
49
+ /** Cap applied to the sum of matched rules in a named group. */
50
+ interface RuleGroupCap {
51
+ readonly name: string;
52
+ readonly maxScore: number;
53
+ }
54
+ /** Input for registering a group of related rules with an optional score cap. */
55
+ interface RuleGroupInput<TSignals extends SignalMap = SignalMap> {
56
+ readonly name: string;
57
+ readonly maxScore?: number;
58
+ readonly rules: readonly CreateRuleInput<TSignals>[];
45
59
  }
46
60
 
47
61
  /** Immutable risk analysis report. */
@@ -62,40 +76,137 @@ interface GuardianConfig {
62
76
  readonly levels?: readonly RiskLevelThreshold[];
63
77
  }
64
78
 
79
+ /** Context passed to analyze lifecycle hooks. */
80
+ interface AnalyzeContext<TContext = unknown> {
81
+ /** Caller-provided context (e.g. Express `req`). */
82
+ readonly data: TContext;
83
+ /** Guardian instance being analyzed. */
84
+ readonly guardian: Guardian;
85
+ }
86
+ /** Context passed to afterAnalyze hooks. */
87
+ interface AfterAnalyzeContext<TContext = unknown> extends AnalyzeContext<TContext> {
88
+ readonly report: RiskReport;
89
+ }
90
+ /** Runs before signals are evaluated. May be sync or async. */
91
+ type BeforeAnalyzeHook<TContext = unknown> = (context: AnalyzeContext<TContext>) => void | Promise<void>;
92
+ /** Runs after the risk report is built. May be sync or async. */
93
+ type AfterAnalyzeHook<TContext = unknown> = (context: AfterAnalyzeContext<TContext>) => void | Promise<void>;
94
+
65
95
  /**
66
96
  * Fluent public API for risk analysis.
67
97
  * Collects signals and rules, then produces an immutable report.
98
+ *
99
+ * For concurrent workloads (e.g. HTTP), configure one template instance
100
+ * and call {@link fork} per request.
68
101
  */
69
102
  declare class Guardian {
70
103
  private readonly signalStore;
71
104
  private readonly riskEngine;
72
105
  private readonly pluginRegistry;
106
+ private readonly plugins;
107
+ private readonly beforeHooks;
108
+ private readonly afterHooks;
109
+ private readonly thresholds;
110
+ private analyzing;
73
111
  constructor(config?: GuardianConfig);
74
112
  /**
75
113
  * Add a signal value for risk evaluation.
76
114
  */
77
115
  signal(key: string, value: SignalValue): this;
116
+ /**
117
+ * Read a signal value without modifying state.
118
+ */
119
+ getSignal(key: string): SignalValue | undefined;
78
120
  /**
79
121
  * Register a rule. ID is auto-generated.
80
122
  */
81
123
  rule(input: CreateRuleInput): this;
124
+ /**
125
+ * Register a named group of rules with an optional combined score cap.
126
+ */
127
+ ruleGroup(input: RuleGroupInput): this;
82
128
  /**
83
129
  * Install a plugin. Each plugin name may only be registered once.
84
130
  */
85
131
  use(plugin: Plugin): this;
132
+ /**
133
+ * Register a hook that runs before rule evaluation.
134
+ * Use for loading signals from requests, Redis, IP lookups, etc.
135
+ */
136
+ beforeAnalyze<TContext = unknown>(hook: BeforeAnalyzeHook<TContext>): this;
137
+ /**
138
+ * Register a hook that runs after the report is built.
139
+ * Use for audit logging, metrics, or blocking responses.
140
+ */
141
+ afterAnalyze<TContext = unknown>(hook: AfterAnalyzeHook<TContext>): this;
86
142
  /**
87
143
  * Returns names of installed plugins.
88
144
  */
89
145
  getInstalledPlugins(): readonly string[];
90
146
  /**
91
- * Run risk analysis and return an immutable report.
147
+ * Run risk analysis synchronously (skips lifecycle hooks).
148
+ * Prefer {@link analyzeAsync} when hooks are registered.
92
149
  */
93
150
  analyze(): RiskReport;
94
151
  /**
95
- * Clear all signals. Rules and installed plugins persist across resets.
152
+ * Run lifecycle hooks, evaluate rules, and return an immutable report.
153
+ *
154
+ * @param context Optional caller context passed to hooks (e.g. Express `req`).
155
+ */
156
+ analyzeAsync<TContext = unknown>(context?: TContext): Promise<RiskReport>;
157
+ /**
158
+ * Create an isolated copy sharing rules, plugins, and hooks.
159
+ * Each fork has its own signal store for safe concurrent use.
160
+ */
161
+ fork(): Guardian;
162
+ /**
163
+ * Clear all signals. Rules, plugins, and hooks persist across resets.
96
164
  */
97
165
  reset(): this;
166
+ private assertNotAnalyzing;
167
+ }
168
+
169
+ /** Guardian with typed signal keys and rule predicates. */
170
+ type TypedGuardian<TSignals extends SignalMap> = Guardian & {
171
+ signal<K extends keyof TSignals & string>(key: K, value: TSignals[K]): TypedGuardian<TSignals>;
172
+ rule(input: CreateRuleInput<TSignals>): TypedGuardian<TSignals>;
173
+ };
174
+ /**
175
+ * Define a typed signal schema for compile-time key/value checking.
176
+ *
177
+ * @example
178
+ * ```typescript
179
+ * const botSignals = defineSignals<{
180
+ * mouseLinearity: number;
181
+ * headlessUA: boolean;
182
+ * }>();
183
+ *
184
+ * const guardian = botSignals.create()
185
+ * .signal('mouseLinearity', 0.95) // typed
186
+ * .rule({ name: 'Linear', when: (s) => s.mouseLinearity > 0.9, score: 20 });
187
+ * ```
188
+ */
189
+ declare function defineSignals<TSignals extends SignalMap>(): {
190
+ create(config?: GuardianConfig): TypedGuardian<TSignals>;
191
+ };
192
+
193
+ /**
194
+ * Register a list of preset rules on a Guardian instance.
195
+ */
196
+ declare function applyRules<TSignals extends SignalMap = SignalMap>(guardian: Guardian, rules: readonly CreateRuleInput<TSignals>[]): Guardian;
197
+
198
+ /** Common bot-detection signal keys. */
199
+ interface BotDetectionSignals extends Record<string, SignalValue> {
200
+ mouseLinearity: number;
201
+ requestBurst: number;
202
+ headlessUA: boolean;
203
+ sessionAgeSeconds: number;
204
+ requestsPerMinute: number;
98
205
  }
206
+ /** Ready-to-use bot detection rules (customize scores for your app). */
207
+ declare const botDetectionRules: readonly CreateRuleInput<BotDetectionSignals>[];
208
+ /** Login brute-force rules — use with redis plugin signals. */
209
+ declare const loginProtectionRules: readonly CreateRuleInput[];
99
210
 
100
211
  /**
101
212
  * Builds immutable risk reports.
@@ -119,13 +230,13 @@ declare class RuleEvaluator {
119
230
  }
120
231
 
121
232
  /**
122
- * Calculates risk score from matched rules.
233
+ * Calculates risk score from matched rules with optional per-group caps.
123
234
  */
124
235
  declare class ScoreCalculator {
125
236
  /**
126
- * Sum scores from all matched rules, clamped to a safe maximum.
237
+ * Sum scores from matched rules, applying group caps when configured.
127
238
  */
128
- calculate(matchedRules: readonly MatchedRule[]): number;
239
+ calculate(matchedRules: readonly MatchedRule[], groupCaps?: readonly RuleGroupCap[]): number;
129
240
  }
130
241
 
131
242
  /**
@@ -168,6 +279,7 @@ interface RiskEngineDependencies {
168
279
  declare class RiskEngine {
169
280
  private readonly deps;
170
281
  private readonly rules;
282
+ private readonly groupCaps;
171
283
  private readonly thresholds;
172
284
  constructor(deps: RiskEngineDependencies, thresholds?: readonly RiskLevelThreshold[]);
173
285
  /**
@@ -178,6 +290,14 @@ declare class RiskEngine {
178
290
  * Get all registered rules.
179
291
  */
180
292
  getRules(): readonly Rule<SignalMap>[];
293
+ /**
294
+ * Get configured per-group score caps.
295
+ */
296
+ getGroupCaps(): readonly RuleGroupCap[];
297
+ /**
298
+ * Cap the combined score of matched rules in a group.
299
+ */
300
+ setGroupCap(name: string, maxScore: number): void;
181
301
  /**
182
302
  * Run the full risk analysis pipeline.
183
303
  */
@@ -210,6 +330,11 @@ declare class PluginRegistry {
210
330
  * Check if a plugin is installed by name.
211
331
  */
212
332
  has(name: string): boolean;
333
+ /**
334
+ * Copy installed plugin names from a template (used by Guardian.fork).
335
+ * Does not call install() — rules and hooks are copied separately.
336
+ */
337
+ adoptInstalled(names: readonly string[]): void;
213
338
  /**
214
339
  * Get names of all installed plugins in registration order.
215
340
  */
@@ -232,7 +357,25 @@ declare class RuleBuilder {
232
357
  */
233
358
  declare function resolveLevel(score: number, thresholds?: readonly RiskLevelThreshold[]): string;
234
359
 
360
+ /**
361
+ * Parse and validate an IP address (v4 or v6). Returns null if invalid.
362
+ */
363
+ declare function parseIpAddress(value: string): string | null;
364
+ /**
365
+ * Whether an IP is private, loopback, link-local, or CGNAT (skip external lookup).
366
+ */
367
+ declare function isPrivateIp(ip: string): boolean;
368
+ /**
369
+ * Validate a session identifier (length + charset).
370
+ */
371
+ declare function sanitizeSessionId(value: string): string | null;
372
+
373
+ /** Maximum length for string signal values. */
374
+ declare const MAX_SIGNAL_STRING_LENGTH = 4096;
375
+ /** Default timeout for analyze lifecycle hooks (ms). */
376
+ declare const HOOK_TIMEOUT_MS = 10000;
377
+
235
378
  /** Default risk level thresholds used when none are configured. */
236
379
  declare const DEFAULT_RISK_LEVELS: readonly RiskLevelThreshold[];
237
380
 
238
- export { type CreateRuleInput, DEFAULT_RISK_LEVELS, Guardian, type GuardianConfig, type GuardianPlugin, type MatchedRule, type Plugin, PluginAlreadyInstalledError, PluginInstallError, PluginRegistry, RiskEngine, type RiskEngineDependencies, type RiskLevelThreshold, type RiskReport, type Rule, RuleBuilder, RuleEvaluator, ScoreCalculator, type SignalDefinition, type SignalMap, SignalStore, type SignalValue, resolveLevel };
381
+ export { type AfterAnalyzeContext, type AfterAnalyzeHook, type AnalyzeContext, type BeforeAnalyzeHook, type BotDetectionSignals, type CreateRuleInput, DEFAULT_RISK_LEVELS, Guardian, type GuardianConfig, type GuardianPlugin, HOOK_TIMEOUT_MS, MAX_SIGNAL_STRING_LENGTH, type MatchedRule, type Plugin, PluginAlreadyInstalledError, PluginInstallError, PluginRegistry, RiskEngine, type RiskEngineDependencies, type RiskLevelThreshold, type RiskReport, type Rule, RuleBuilder, RuleEvaluator, type RuleGroupCap, type RuleGroupInput, ScoreCalculator, type SignalDefinition, type SignalMap, SignalStore, type SignalValue, type TypedGuardian, applyRules, botDetectionRules, defineSignals, isPrivateIp, loginProtectionRules, parseIpAddress, resolveLevel, sanitizeSessionId };