guardian-risk 0.1.0 → 0.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 +23 -4
- package/dist/index.cjs +51 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +46 -2
- package/dist/index.d.ts +46 -2
- package/dist/index.js +50 -2
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -36,12 +36,31 @@ console.log(report.score); // 35
|
|
|
36
36
|
console.log(report.level); // MEDIUM
|
|
37
37
|
```
|
|
38
38
|
|
|
39
|
+
## Plugins
|
|
40
|
+
|
|
41
|
+
```typescript
|
|
42
|
+
import type { Plugin } from 'guardian-risk';
|
|
43
|
+
|
|
44
|
+
const myPlugin: Plugin = {
|
|
45
|
+
name: 'my-plugin',
|
|
46
|
+
install(guardian) {
|
|
47
|
+
guardian.rule({ name: 'Custom', when: () => true, score: 10 });
|
|
48
|
+
},
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
new Guardian().use(myPlugin);
|
|
52
|
+
```
|
|
53
|
+
|
|
39
54
|
## API
|
|
40
55
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
56
|
+
| Method | Description |
|
|
57
|
+
|--------|-------------|
|
|
58
|
+
| `guardian.signal(key, value)` | Add a signal |
|
|
59
|
+
| `guardian.rule({ name, when, score, reason? })` | Register a rule |
|
|
60
|
+
| `guardian.use(plugin)` | Install a plugin (once per name) |
|
|
61
|
+
| `guardian.analyze()` | Run evaluation, returns `RiskReport` |
|
|
62
|
+
| `guardian.reset()` | Clear signals (rules + plugins persist) |
|
|
63
|
+
| `guardian.getInstalledPlugins()` | List installed plugin names |
|
|
45
64
|
|
|
46
65
|
## License
|
|
47
66
|
|
package/dist/index.cjs
CHANGED
|
@@ -177,10 +177,45 @@ var RuleBuilder = class {
|
|
|
177
177
|
}
|
|
178
178
|
};
|
|
179
179
|
|
|
180
|
+
// src/plugins/PluginRegistry.ts
|
|
181
|
+
var PluginAlreadyInstalledError = class extends Error {
|
|
182
|
+
constructor(pluginName) {
|
|
183
|
+
super(`Plugin "${pluginName}" is already installed`);
|
|
184
|
+
this.name = "PluginAlreadyInstalledError";
|
|
185
|
+
}
|
|
186
|
+
};
|
|
187
|
+
var PluginRegistry = class {
|
|
188
|
+
installed = /* @__PURE__ */ new Set();
|
|
189
|
+
/**
|
|
190
|
+
* Install a plugin on the given Guardian instance.
|
|
191
|
+
* Each plugin name may only be installed once per Guardian instance.
|
|
192
|
+
*/
|
|
193
|
+
install(plugin, guardian) {
|
|
194
|
+
if (this.installed.has(plugin.name)) {
|
|
195
|
+
throw new PluginAlreadyInstalledError(plugin.name);
|
|
196
|
+
}
|
|
197
|
+
plugin.install(guardian);
|
|
198
|
+
this.installed.add(plugin.name);
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Check if a plugin is installed by name.
|
|
202
|
+
*/
|
|
203
|
+
has(name) {
|
|
204
|
+
return this.installed.has(name);
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Get names of all installed plugins in registration order.
|
|
208
|
+
*/
|
|
209
|
+
getInstalled() {
|
|
210
|
+
return [...this.installed];
|
|
211
|
+
}
|
|
212
|
+
};
|
|
213
|
+
|
|
180
214
|
// src/engine/Guardian.ts
|
|
181
215
|
var Guardian = class {
|
|
182
216
|
signalStore;
|
|
183
217
|
riskEngine;
|
|
218
|
+
pluginRegistry = new PluginRegistry();
|
|
184
219
|
constructor(config = {}) {
|
|
185
220
|
const thresholds = config.levels ?? DEFAULT_RISK_LEVELS;
|
|
186
221
|
this.signalStore = new SignalStore();
|
|
@@ -207,6 +242,19 @@ var Guardian = class {
|
|
|
207
242
|
this.riskEngine.addRule(rule);
|
|
208
243
|
return this;
|
|
209
244
|
}
|
|
245
|
+
/**
|
|
246
|
+
* Install a plugin. Each plugin name may only be registered once.
|
|
247
|
+
*/
|
|
248
|
+
use(plugin) {
|
|
249
|
+
this.pluginRegistry.install(plugin, this);
|
|
250
|
+
return this;
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* Returns names of installed plugins.
|
|
254
|
+
*/
|
|
255
|
+
getInstalledPlugins() {
|
|
256
|
+
return this.pluginRegistry.getInstalled();
|
|
257
|
+
}
|
|
210
258
|
/**
|
|
211
259
|
* Run risk analysis and return an immutable report.
|
|
212
260
|
*/
|
|
@@ -214,7 +262,7 @@ var Guardian = class {
|
|
|
214
262
|
return this.riskEngine.analyze();
|
|
215
263
|
}
|
|
216
264
|
/**
|
|
217
|
-
* Clear all signals. Rules persist across resets.
|
|
265
|
+
* Clear all signals. Rules and installed plugins persist across resets.
|
|
218
266
|
*/
|
|
219
267
|
reset() {
|
|
220
268
|
this.signalStore.clear();
|
|
@@ -224,6 +272,8 @@ var Guardian = class {
|
|
|
224
272
|
|
|
225
273
|
exports.DEFAULT_RISK_LEVELS = DEFAULT_RISK_LEVELS;
|
|
226
274
|
exports.Guardian = Guardian;
|
|
275
|
+
exports.PluginAlreadyInstalledError = PluginAlreadyInstalledError;
|
|
276
|
+
exports.PluginRegistry = PluginRegistry;
|
|
227
277
|
exports.RiskEngine = RiskEngine;
|
|
228
278
|
exports.RuleBuilder = RuleBuilder;
|
|
229
279
|
exports.RuleEvaluator = RuleEvaluator;
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/constants/defaults.ts","../src/utils/resolveLevel.ts","../src/report/Report.ts","../src/rules/RuleEvaluator.ts","../src/score/ScoreCalculator.ts","../src/utils/validation.ts","../src/signals/SignalStore.ts","../src/engine/RiskEngine.ts","../src/rules/RuleBuilder.ts","../src/engine/Guardian.ts"],"names":["randomUUID"],"mappings":"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","file":"index.cjs","sourcesContent":["import type { RiskLevelThreshold } from '../types/report.js';\n\n/** Default risk level thresholds used when none are configured. */\nexport const DEFAULT_RISK_LEVELS: readonly RiskLevelThreshold[] = [\n { max: 20, level: 'LOW' },\n { max: 40, level: 'MEDIUM' },\n { max: 60, level: 'HIGH' },\n { max: Infinity, level: 'CRITICAL' },\n] as const;\n","import type { RiskLevelThreshold } from '../types/report.js';\nimport { DEFAULT_RISK_LEVELS } from '../constants/defaults.js';\n\n/**\n * Resolves a risk level label from a score using configured thresholds.\n * Thresholds are evaluated in order; the first threshold where score <= max wins.\n */\nexport function resolveLevel(\n score: number,\n thresholds: readonly RiskLevelThreshold[] = DEFAULT_RISK_LEVELS,\n): string {\n for (const threshold of thresholds) {\n if (score <= threshold.max) {\n return threshold.level;\n }\n }\n\n const last = thresholds[thresholds.length - 1];\n return last?.level ?? 'UNKNOWN';\n}\n","import type { MatchedRule } from '../types/rules.js';\nimport type { RiskReport } from '../types/report.js';\nimport { resolveLevel } from '../utils/resolveLevel.js';\nimport type { RiskLevelThreshold } from '../types/report.js';\n\n/**\n * Builds immutable risk reports.\n */\nexport class ReportBuilder {\n /**\n * Build a frozen risk report from evaluation results.\n */\n build(\n score: number,\n matchedRules: readonly MatchedRule[],\n thresholds: readonly RiskLevelThreshold[],\n analyzedAt: string = new Date().toISOString(),\n ): RiskReport {\n const reasons = matchedRules.map((rule) => rule.reason);\n const level = resolveLevel(score, thresholds);\n\n const report: RiskReport = {\n score,\n level,\n reasons: Object.freeze([...reasons]),\n matchedRules: Object.freeze([...matchedRules]),\n analyzedAt,\n };\n\n return Object.freeze(report);\n }\n}\n","import type { MatchedRule, Rule } from '../types/rules.js';\nimport type { SignalMap } from '../types/signals.js';\n\n/**\n * Evaluates rules against a signal map and returns matched rules.\n */\nexport class RuleEvaluator {\n /**\n * Evaluate all rules against the given signals.\n * Rules are evaluated in registration order (exhaustive, no short-circuit).\n */\n evaluate<TSignals extends SignalMap>(\n rules: readonly Rule<TSignals>[],\n signals: TSignals,\n ): MatchedRule[] {\n const matched: MatchedRule[] = [];\n\n for (const rule of rules) {\n if (rule.when(signals)) {\n matched.push({\n id: rule.id,\n name: rule.name,\n score: rule.score,\n reason: rule.reason ?? rule.name,\n });\n }\n }\n\n return matched;\n }\n}\n","import type { MatchedRule } from '../types/rules.js';\n\n/**\n * Calculates risk score from matched rules.\n */\nexport class ScoreCalculator {\n /**\n * Sum scores from all matched rules.\n */\n calculate(matchedRules: readonly MatchedRule[]): number {\n return matchedRules.reduce((total, rule) => total + rule.score, 0);\n }\n}\n","import { randomUUID } from 'node:crypto';\nimport type { SignalValue } from '../types/signals.js';\n\n/**\n * Validates that a value is an allowed signal primitive.\n * Signals must be string, number, boolean, or null — not objects or arrays.\n */\nexport function validateSignalValue(value: unknown): value is SignalValue {\n if (value === null) {\n return true;\n }\n\n const type = typeof value;\n return type === 'string' || type === 'number' || type === 'boolean';\n}\n\n/**\n * Generates a unique identifier for rules.\n */\nexport function generateId(): string {\n return randomUUID();\n}\n","import type { SignalMap, SignalValue } from '../types/signals.js';\nimport { validateSignalValue } from '../utils/validation.js';\n\n/**\n * Stores and retrieves signal values for risk evaluation.\n */\nexport class SignalStore {\n private readonly signals = new Map<string, SignalValue>();\n\n /**\n * Set a signal value. Overwrites any existing value for the key.\n */\n set(key: string, value: SignalValue): this {\n if (!validateSignalValue(value)) {\n throw new TypeError(\n `Invalid signal value for \"${key}\": signals must be string, number, boolean, or null`,\n );\n }\n\n this.signals.set(key, value);\n return this;\n }\n\n /**\n * Get a signal value by key.\n */\n get(key: string): SignalValue | undefined {\n return this.signals.get(key);\n }\n\n /**\n * Check if a signal exists.\n */\n has(key: string): boolean {\n return this.signals.has(key);\n }\n\n /**\n * Returns a frozen snapshot of all signals.\n */\n getAll(): SignalMap {\n const snapshot: Record<string, SignalValue> = {};\n for (const [key, value] of this.signals) {\n snapshot[key] = value;\n }\n return Object.freeze(snapshot);\n }\n\n /**\n * Clear all signals.\n */\n clear(): void {\n this.signals.clear();\n }\n}\n","import { DEFAULT_RISK_LEVELS } from '../constants/defaults.js';\nimport { ReportBuilder } from '../report/Report.js';\nimport { RuleEvaluator } from '../rules/RuleEvaluator.js';\nimport { ScoreCalculator } from '../score/ScoreCalculator.js';\nimport { SignalStore } from '../signals/SignalStore.js';\nimport type { Rule } from '../types/rules.js';\nimport type { RiskReport, RiskLevelThreshold } from '../types/report.js';\nimport type { SignalMap } from '../types/signals.js';\n\n/** Dependencies injected into RiskEngine. */\nexport interface RiskEngineDependencies {\n readonly signalStore: SignalStore;\n readonly ruleEvaluator: RuleEvaluator;\n readonly scoreCalculator: ScoreCalculator;\n readonly reportBuilder: ReportBuilder;\n}\n\n/**\n * Orchestrates signal evaluation, scoring, and report generation.\n */\nexport class RiskEngine {\n private readonly rules: Rule<SignalMap>[] = [];\n private readonly thresholds: readonly RiskLevelThreshold[];\n\n constructor(\n private readonly deps: RiskEngineDependencies,\n thresholds: readonly RiskLevelThreshold[] = DEFAULT_RISK_LEVELS,\n ) {\n this.thresholds = thresholds;\n }\n\n /**\n * Register a rule for evaluation.\n */\n addRule(rule: Rule<SignalMap>): void {\n this.rules.push(rule);\n }\n\n /**\n * Get all registered rules.\n */\n getRules(): readonly Rule<SignalMap>[] {\n return this.rules;\n }\n\n /**\n * Run the full risk analysis pipeline.\n */\n analyze(): RiskReport {\n const signals = this.deps.signalStore.getAll();\n const matchedRules = this.deps.ruleEvaluator.evaluate(this.rules, signals);\n const score = this.deps.scoreCalculator.calculate(matchedRules);\n\n return this.deps.reportBuilder.build(score, matchedRules, this.thresholds);\n }\n}\n","import type { CreateRuleInput, Rule } from '../types/rules.js';\nimport type { SignalMap } from '../types/signals.js';\nimport { generateId } from '../utils/validation.js';\n\n/**\n * Builds immutable rule definitions with auto-generated IDs.\n */\nexport class RuleBuilder {\n /**\n * Create a new rule from input configuration.\n */\n static create<TSignals extends SignalMap = SignalMap>(\n input: CreateRuleInput<TSignals>,\n ): Rule<TSignals> {\n const rule: Rule<TSignals> = {\n id: generateId(),\n name: input.name,\n score: input.score,\n when: input.when,\n ...(input.description !== undefined ? { description: input.description } : {}),\n ...(input.reason !== undefined ? { reason: input.reason } : {}),\n };\n\n return rule;\n }\n}\n","import { DEFAULT_RISK_LEVELS } from '../constants/defaults.js';\nimport { RiskEngine, type RiskEngineDependencies } from './RiskEngine.js';\nimport { ReportBuilder } from '../report/Report.js';\nimport { RuleBuilder } from '../rules/RuleBuilder.js';\nimport { RuleEvaluator } from '../rules/RuleEvaluator.js';\nimport { ScoreCalculator } from '../score/ScoreCalculator.js';\nimport { SignalStore } from '../signals/SignalStore.js';\nimport type { CreateRuleInput } from '../types/rules.js';\nimport type { GuardianConfig, RiskReport } from '../types/report.js';\nimport type { SignalValue } from '../types/signals.js';\n\n/**\n * Fluent public API for risk analysis.\n * Collects signals and rules, then produces an immutable report.\n */\nexport class Guardian {\n private readonly signalStore: SignalStore;\n private readonly riskEngine: RiskEngine;\n\n constructor(config: GuardianConfig = {}) {\n const thresholds = config.levels ?? DEFAULT_RISK_LEVELS;\n this.signalStore = new SignalStore();\n\n const deps: RiskEngineDependencies = {\n signalStore: this.signalStore,\n ruleEvaluator: new RuleEvaluator(),\n scoreCalculator: new ScoreCalculator(),\n reportBuilder: new ReportBuilder(),\n };\n\n this.riskEngine = new RiskEngine(deps, thresholds);\n }\n\n /**\n * Add a signal value for risk evaluation.\n */\n signal(key: string, value: SignalValue): this {\n this.signalStore.set(key, value);\n return this;\n }\n\n /**\n * Register a rule. ID is auto-generated.\n */\n rule(input: CreateRuleInput): this {\n const rule = RuleBuilder.create(input);\n this.riskEngine.addRule(rule);\n return this;\n }\n\n /**\n * Run risk analysis and return an immutable report.\n */\n analyze(): RiskReport {\n return this.riskEngine.analyze();\n }\n\n /**\n * Clear all signals. Rules persist across resets.\n */\n reset(): this {\n this.signalStore.clear();\n return this;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/constants/defaults.ts","../src/utils/resolveLevel.ts","../src/report/Report.ts","../src/rules/RuleEvaluator.ts","../src/score/ScoreCalculator.ts","../src/utils/validation.ts","../src/signals/SignalStore.ts","../src/engine/RiskEngine.ts","../src/rules/RuleBuilder.ts","../src/plugins/PluginRegistry.ts","../src/engine/Guardian.ts"],"names":["randomUUID"],"mappings":"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","file":"index.cjs","sourcesContent":["import type { RiskLevelThreshold } from '../types/report.js';\n\n/** Default risk level thresholds used when none are configured. */\nexport const DEFAULT_RISK_LEVELS: readonly RiskLevelThreshold[] = [\n { max: 20, level: 'LOW' },\n { max: 40, level: 'MEDIUM' },\n { max: 60, level: 'HIGH' },\n { max: Infinity, level: 'CRITICAL' },\n] as const;\n","import type { RiskLevelThreshold } from '../types/report.js';\nimport { DEFAULT_RISK_LEVELS } from '../constants/defaults.js';\n\n/**\n * Resolves a risk level label from a score using configured thresholds.\n * Thresholds are evaluated in order; the first threshold where score <= max wins.\n */\nexport function resolveLevel(\n score: number,\n thresholds: readonly RiskLevelThreshold[] = DEFAULT_RISK_LEVELS,\n): string {\n for (const threshold of thresholds) {\n if (score <= threshold.max) {\n return threshold.level;\n }\n }\n\n const last = thresholds[thresholds.length - 1];\n return last?.level ?? 'UNKNOWN';\n}\n","import type { MatchedRule } from '../types/rules.js';\nimport type { RiskReport } from '../types/report.js';\nimport { resolveLevel } from '../utils/resolveLevel.js';\nimport type { RiskLevelThreshold } from '../types/report.js';\n\n/**\n * Builds immutable risk reports.\n */\nexport class ReportBuilder {\n /**\n * Build a frozen risk report from evaluation results.\n */\n build(\n score: number,\n matchedRules: readonly MatchedRule[],\n thresholds: readonly RiskLevelThreshold[],\n analyzedAt: string = new Date().toISOString(),\n ): RiskReport {\n const reasons = matchedRules.map((rule) => rule.reason);\n const level = resolveLevel(score, thresholds);\n\n const report: RiskReport = {\n score,\n level,\n reasons: Object.freeze([...reasons]),\n matchedRules: Object.freeze([...matchedRules]),\n analyzedAt,\n };\n\n return Object.freeze(report);\n }\n}\n","import type { MatchedRule, Rule } from '../types/rules.js';\nimport type { SignalMap } from '../types/signals.js';\n\n/**\n * Evaluates rules against a signal map and returns matched rules.\n */\nexport class RuleEvaluator {\n /**\n * Evaluate all rules against the given signals.\n * Rules are evaluated in registration order (exhaustive, no short-circuit).\n */\n evaluate<TSignals extends SignalMap>(\n rules: readonly Rule<TSignals>[],\n signals: TSignals,\n ): MatchedRule[] {\n const matched: MatchedRule[] = [];\n\n for (const rule of rules) {\n if (rule.when(signals)) {\n matched.push({\n id: rule.id,\n name: rule.name,\n score: rule.score,\n reason: rule.reason ?? rule.name,\n });\n }\n }\n\n return matched;\n }\n}\n","import type { MatchedRule } from '../types/rules.js';\n\n/**\n * Calculates risk score from matched rules.\n */\nexport class ScoreCalculator {\n /**\n * Sum scores from all matched rules.\n */\n calculate(matchedRules: readonly MatchedRule[]): number {\n return matchedRules.reduce((total, rule) => total + rule.score, 0);\n }\n}\n","import { randomUUID } from 'node:crypto';\nimport type { SignalValue } from '../types/signals.js';\n\n/**\n * Validates that a value is an allowed signal primitive.\n * Signals must be string, number, boolean, or null — not objects or arrays.\n */\nexport function validateSignalValue(value: unknown): value is SignalValue {\n if (value === null) {\n return true;\n }\n\n const type = typeof value;\n return type === 'string' || type === 'number' || type === 'boolean';\n}\n\n/**\n * Generates a unique identifier for rules.\n */\nexport function generateId(): string {\n return randomUUID();\n}\n","import type { SignalMap, SignalValue } from '../types/signals.js';\nimport { validateSignalValue } from '../utils/validation.js';\n\n/**\n * Stores and retrieves signal values for risk evaluation.\n */\nexport class SignalStore {\n private readonly signals = new Map<string, SignalValue>();\n\n /**\n * Set a signal value. Overwrites any existing value for the key.\n */\n set(key: string, value: SignalValue): this {\n if (!validateSignalValue(value)) {\n throw new TypeError(\n `Invalid signal value for \"${key}\": signals must be string, number, boolean, or null`,\n );\n }\n\n this.signals.set(key, value);\n return this;\n }\n\n /**\n * Get a signal value by key.\n */\n get(key: string): SignalValue | undefined {\n return this.signals.get(key);\n }\n\n /**\n * Check if a signal exists.\n */\n has(key: string): boolean {\n return this.signals.has(key);\n }\n\n /**\n * Returns a frozen snapshot of all signals.\n */\n getAll(): SignalMap {\n const snapshot: Record<string, SignalValue> = {};\n for (const [key, value] of this.signals) {\n snapshot[key] = value;\n }\n return Object.freeze(snapshot);\n }\n\n /**\n * Clear all signals.\n */\n clear(): void {\n this.signals.clear();\n }\n}\n","import { DEFAULT_RISK_LEVELS } from '../constants/defaults.js';\nimport { ReportBuilder } from '../report/Report.js';\nimport { RuleEvaluator } from '../rules/RuleEvaluator.js';\nimport { ScoreCalculator } from '../score/ScoreCalculator.js';\nimport { SignalStore } from '../signals/SignalStore.js';\nimport type { Rule } from '../types/rules.js';\nimport type { RiskReport, RiskLevelThreshold } from '../types/report.js';\nimport type { SignalMap } from '../types/signals.js';\n\n/** Dependencies injected into RiskEngine. */\nexport interface RiskEngineDependencies {\n readonly signalStore: SignalStore;\n readonly ruleEvaluator: RuleEvaluator;\n readonly scoreCalculator: ScoreCalculator;\n readonly reportBuilder: ReportBuilder;\n}\n\n/**\n * Orchestrates signal evaluation, scoring, and report generation.\n */\nexport class RiskEngine {\n private readonly rules: Rule<SignalMap>[] = [];\n private readonly thresholds: readonly RiskLevelThreshold[];\n\n constructor(\n private readonly deps: RiskEngineDependencies,\n thresholds: readonly RiskLevelThreshold[] = DEFAULT_RISK_LEVELS,\n ) {\n this.thresholds = thresholds;\n }\n\n /**\n * Register a rule for evaluation.\n */\n addRule(rule: Rule<SignalMap>): void {\n this.rules.push(rule);\n }\n\n /**\n * Get all registered rules.\n */\n getRules(): readonly Rule<SignalMap>[] {\n return this.rules;\n }\n\n /**\n * Run the full risk analysis pipeline.\n */\n analyze(): RiskReport {\n const signals = this.deps.signalStore.getAll();\n const matchedRules = this.deps.ruleEvaluator.evaluate(this.rules, signals);\n const score = this.deps.scoreCalculator.calculate(matchedRules);\n\n return this.deps.reportBuilder.build(score, matchedRules, this.thresholds);\n }\n}\n","import type { CreateRuleInput, Rule } from '../types/rules.js';\nimport type { SignalMap } from '../types/signals.js';\nimport { generateId } from '../utils/validation.js';\n\n/**\n * Builds immutable rule definitions with auto-generated IDs.\n */\nexport class RuleBuilder {\n /**\n * Create a new rule from input configuration.\n */\n static create<TSignals extends SignalMap = SignalMap>(\n input: CreateRuleInput<TSignals>,\n ): Rule<TSignals> {\n const rule: Rule<TSignals> = {\n id: generateId(),\n name: input.name,\n score: input.score,\n when: input.when,\n ...(input.description !== undefined ? { description: input.description } : {}),\n ...(input.reason !== undefined ? { reason: input.reason } : {}),\n };\n\n return rule;\n }\n}\n","import type { Guardian } from '../engine/Guardian.js';\nimport type { Plugin } from './Plugin.js';\n\n/**\n * Thrown when attempting to register a plugin that is already installed.\n */\nexport class PluginAlreadyInstalledError extends Error {\n constructor(pluginName: string) {\n super(`Plugin \"${pluginName}\" is already installed`);\n this.name = 'PluginAlreadyInstalledError';\n }\n}\n\n/**\n * Manages plugin lifecycle: register once, track installed plugins.\n */\nexport class PluginRegistry {\n private readonly installed = new Set<string>();\n\n /**\n * Install a plugin on the given Guardian instance.\n * Each plugin name may only be installed once per Guardian instance.\n */\n install(plugin: Plugin, guardian: Guardian): void {\n if (this.installed.has(plugin.name)) {\n throw new PluginAlreadyInstalledError(plugin.name);\n }\n\n plugin.install(guardian);\n this.installed.add(plugin.name);\n }\n\n /**\n * Check if a plugin is installed by name.\n */\n has(name: string): boolean {\n return this.installed.has(name);\n }\n\n /**\n * Get names of all installed plugins in registration order.\n */\n getInstalled(): readonly string[] {\n return [...this.installed];\n }\n}\n","import { DEFAULT_RISK_LEVELS } from '../constants/defaults.js';\nimport { RiskEngine, type RiskEngineDependencies } from './RiskEngine.js';\nimport { ReportBuilder } from '../report/Report.js';\nimport { RuleBuilder } from '../rules/RuleBuilder.js';\nimport { RuleEvaluator } from '../rules/RuleEvaluator.js';\nimport { ScoreCalculator } from '../score/ScoreCalculator.js';\nimport { SignalStore } from '../signals/SignalStore.js';\nimport { PluginRegistry } from '../plugins/PluginRegistry.js';\nimport type { Plugin } from '../plugins/Plugin.js';\nimport type { CreateRuleInput } from '../types/rules.js';\nimport type { GuardianConfig, RiskReport } from '../types/report.js';\nimport type { SignalValue } from '../types/signals.js';\n\n/**\n * Fluent public API for risk analysis.\n * Collects signals and rules, then produces an immutable report.\n */\nexport class Guardian {\n private readonly signalStore: SignalStore;\n private readonly riskEngine: RiskEngine;\n private readonly pluginRegistry = new PluginRegistry();\n\n constructor(config: GuardianConfig = {}) {\n const thresholds = config.levels ?? DEFAULT_RISK_LEVELS;\n this.signalStore = new SignalStore();\n\n const deps: RiskEngineDependencies = {\n signalStore: this.signalStore,\n ruleEvaluator: new RuleEvaluator(),\n scoreCalculator: new ScoreCalculator(),\n reportBuilder: new ReportBuilder(),\n };\n\n this.riskEngine = new RiskEngine(deps, thresholds);\n }\n\n /**\n * Add a signal value for risk evaluation.\n */\n signal(key: string, value: SignalValue): this {\n this.signalStore.set(key, value);\n return this;\n }\n\n /**\n * Register a rule. ID is auto-generated.\n */\n rule(input: CreateRuleInput): this {\n const rule = RuleBuilder.create(input);\n this.riskEngine.addRule(rule);\n return this;\n }\n\n /**\n * Install a plugin. Each plugin name may only be registered once.\n */\n use(plugin: Plugin): this {\n this.pluginRegistry.install(plugin, this);\n return this;\n }\n\n /**\n * Returns names of installed plugins.\n */\n getInstalledPlugins(): readonly string[] {\n return this.pluginRegistry.getInstalled();\n }\n\n /**\n * Run risk analysis and return an immutable report.\n */\n analyze(): RiskReport {\n return this.riskEngine.analyze();\n }\n\n /**\n * Clear all signals. Rules and installed plugins persist across resets.\n */\n reset(): this {\n this.signalStore.clear();\n return this;\n }\n}\n"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Extension point for adding capabilities to Guardian without modifying core.
|
|
3
|
+
* Plugins may register signals, rules, or helpers during installation.
|
|
4
|
+
*/
|
|
5
|
+
interface Plugin {
|
|
6
|
+
readonly name: string;
|
|
7
|
+
install(guardian: Guardian): void;
|
|
8
|
+
}
|
|
9
|
+
|
|
1
10
|
/** Primitive signal value types supported by Guardian. */
|
|
2
11
|
type SignalValue = string | number | boolean | null;
|
|
3
12
|
/** Read-only map of signal key to value. */
|
|
@@ -58,6 +67,7 @@ interface GuardianConfig {
|
|
|
58
67
|
declare class Guardian {
|
|
59
68
|
private readonly signalStore;
|
|
60
69
|
private readonly riskEngine;
|
|
70
|
+
private readonly pluginRegistry;
|
|
61
71
|
constructor(config?: GuardianConfig);
|
|
62
72
|
/**
|
|
63
73
|
* Add a signal value for risk evaluation.
|
|
@@ -67,12 +77,20 @@ declare class Guardian {
|
|
|
67
77
|
* Register a rule. ID is auto-generated.
|
|
68
78
|
*/
|
|
69
79
|
rule(input: CreateRuleInput): this;
|
|
80
|
+
/**
|
|
81
|
+
* Install a plugin. Each plugin name may only be registered once.
|
|
82
|
+
*/
|
|
83
|
+
use(plugin: Plugin): this;
|
|
84
|
+
/**
|
|
85
|
+
* Returns names of installed plugins.
|
|
86
|
+
*/
|
|
87
|
+
getInstalledPlugins(): readonly string[];
|
|
70
88
|
/**
|
|
71
89
|
* Run risk analysis and return an immutable report.
|
|
72
90
|
*/
|
|
73
91
|
analyze(): RiskReport;
|
|
74
92
|
/**
|
|
75
|
-
* Clear all signals. Rules persist across resets.
|
|
93
|
+
* Clear all signals. Rules and installed plugins persist across resets.
|
|
76
94
|
*/
|
|
77
95
|
reset(): this;
|
|
78
96
|
}
|
|
@@ -164,6 +182,32 @@ declare class RiskEngine {
|
|
|
164
182
|
analyze(): RiskReport;
|
|
165
183
|
}
|
|
166
184
|
|
|
185
|
+
/**
|
|
186
|
+
* Thrown when attempting to register a plugin that is already installed.
|
|
187
|
+
*/
|
|
188
|
+
declare class PluginAlreadyInstalledError extends Error {
|
|
189
|
+
constructor(pluginName: string);
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Manages plugin lifecycle: register once, track installed plugins.
|
|
193
|
+
*/
|
|
194
|
+
declare class PluginRegistry {
|
|
195
|
+
private readonly installed;
|
|
196
|
+
/**
|
|
197
|
+
* Install a plugin on the given Guardian instance.
|
|
198
|
+
* Each plugin name may only be installed once per Guardian instance.
|
|
199
|
+
*/
|
|
200
|
+
install(plugin: Plugin, guardian: Guardian): void;
|
|
201
|
+
/**
|
|
202
|
+
* Check if a plugin is installed by name.
|
|
203
|
+
*/
|
|
204
|
+
has(name: string): boolean;
|
|
205
|
+
/**
|
|
206
|
+
* Get names of all installed plugins in registration order.
|
|
207
|
+
*/
|
|
208
|
+
getInstalled(): readonly string[];
|
|
209
|
+
}
|
|
210
|
+
|
|
167
211
|
/**
|
|
168
212
|
* Builds immutable rule definitions with auto-generated IDs.
|
|
169
213
|
*/
|
|
@@ -183,4 +227,4 @@ declare function resolveLevel(score: number, thresholds?: readonly RiskLevelThre
|
|
|
183
227
|
/** Default risk level thresholds used when none are configured. */
|
|
184
228
|
declare const DEFAULT_RISK_LEVELS: readonly RiskLevelThreshold[];
|
|
185
229
|
|
|
186
|
-
export { type CreateRuleInput, DEFAULT_RISK_LEVELS, Guardian, type GuardianConfig, type MatchedRule, RiskEngine, type RiskEngineDependencies, type RiskLevelThreshold, type RiskReport, type Rule, RuleBuilder, RuleEvaluator, ScoreCalculator, type SignalDefinition, type SignalMap, SignalStore, type SignalValue, resolveLevel };
|
|
230
|
+
export { type CreateRuleInput, DEFAULT_RISK_LEVELS, Guardian, type GuardianConfig, type MatchedRule, type Plugin, PluginAlreadyInstalledError, PluginRegistry, RiskEngine, type RiskEngineDependencies, type RiskLevelThreshold, type RiskReport, type Rule, RuleBuilder, RuleEvaluator, ScoreCalculator, type SignalDefinition, type SignalMap, SignalStore, type SignalValue, resolveLevel };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Extension point for adding capabilities to Guardian without modifying core.
|
|
3
|
+
* Plugins may register signals, rules, or helpers during installation.
|
|
4
|
+
*/
|
|
5
|
+
interface Plugin {
|
|
6
|
+
readonly name: string;
|
|
7
|
+
install(guardian: Guardian): void;
|
|
8
|
+
}
|
|
9
|
+
|
|
1
10
|
/** Primitive signal value types supported by Guardian. */
|
|
2
11
|
type SignalValue = string | number | boolean | null;
|
|
3
12
|
/** Read-only map of signal key to value. */
|
|
@@ -58,6 +67,7 @@ interface GuardianConfig {
|
|
|
58
67
|
declare class Guardian {
|
|
59
68
|
private readonly signalStore;
|
|
60
69
|
private readonly riskEngine;
|
|
70
|
+
private readonly pluginRegistry;
|
|
61
71
|
constructor(config?: GuardianConfig);
|
|
62
72
|
/**
|
|
63
73
|
* Add a signal value for risk evaluation.
|
|
@@ -67,12 +77,20 @@ declare class Guardian {
|
|
|
67
77
|
* Register a rule. ID is auto-generated.
|
|
68
78
|
*/
|
|
69
79
|
rule(input: CreateRuleInput): this;
|
|
80
|
+
/**
|
|
81
|
+
* Install a plugin. Each plugin name may only be registered once.
|
|
82
|
+
*/
|
|
83
|
+
use(plugin: Plugin): this;
|
|
84
|
+
/**
|
|
85
|
+
* Returns names of installed plugins.
|
|
86
|
+
*/
|
|
87
|
+
getInstalledPlugins(): readonly string[];
|
|
70
88
|
/**
|
|
71
89
|
* Run risk analysis and return an immutable report.
|
|
72
90
|
*/
|
|
73
91
|
analyze(): RiskReport;
|
|
74
92
|
/**
|
|
75
|
-
* Clear all signals. Rules persist across resets.
|
|
93
|
+
* Clear all signals. Rules and installed plugins persist across resets.
|
|
76
94
|
*/
|
|
77
95
|
reset(): this;
|
|
78
96
|
}
|
|
@@ -164,6 +182,32 @@ declare class RiskEngine {
|
|
|
164
182
|
analyze(): RiskReport;
|
|
165
183
|
}
|
|
166
184
|
|
|
185
|
+
/**
|
|
186
|
+
* Thrown when attempting to register a plugin that is already installed.
|
|
187
|
+
*/
|
|
188
|
+
declare class PluginAlreadyInstalledError extends Error {
|
|
189
|
+
constructor(pluginName: string);
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Manages plugin lifecycle: register once, track installed plugins.
|
|
193
|
+
*/
|
|
194
|
+
declare class PluginRegistry {
|
|
195
|
+
private readonly installed;
|
|
196
|
+
/**
|
|
197
|
+
* Install a plugin on the given Guardian instance.
|
|
198
|
+
* Each plugin name may only be installed once per Guardian instance.
|
|
199
|
+
*/
|
|
200
|
+
install(plugin: Plugin, guardian: Guardian): void;
|
|
201
|
+
/**
|
|
202
|
+
* Check if a plugin is installed by name.
|
|
203
|
+
*/
|
|
204
|
+
has(name: string): boolean;
|
|
205
|
+
/**
|
|
206
|
+
* Get names of all installed plugins in registration order.
|
|
207
|
+
*/
|
|
208
|
+
getInstalled(): readonly string[];
|
|
209
|
+
}
|
|
210
|
+
|
|
167
211
|
/**
|
|
168
212
|
* Builds immutable rule definitions with auto-generated IDs.
|
|
169
213
|
*/
|
|
@@ -183,4 +227,4 @@ declare function resolveLevel(score: number, thresholds?: readonly RiskLevelThre
|
|
|
183
227
|
/** Default risk level thresholds used when none are configured. */
|
|
184
228
|
declare const DEFAULT_RISK_LEVELS: readonly RiskLevelThreshold[];
|
|
185
229
|
|
|
186
|
-
export { type CreateRuleInput, DEFAULT_RISK_LEVELS, Guardian, type GuardianConfig, type MatchedRule, RiskEngine, type RiskEngineDependencies, type RiskLevelThreshold, type RiskReport, type Rule, RuleBuilder, RuleEvaluator, ScoreCalculator, type SignalDefinition, type SignalMap, SignalStore, type SignalValue, resolveLevel };
|
|
230
|
+
export { type CreateRuleInput, DEFAULT_RISK_LEVELS, Guardian, type GuardianConfig, type MatchedRule, type Plugin, PluginAlreadyInstalledError, PluginRegistry, RiskEngine, type RiskEngineDependencies, type RiskLevelThreshold, type RiskReport, type Rule, RuleBuilder, RuleEvaluator, ScoreCalculator, type SignalDefinition, type SignalMap, SignalStore, type SignalValue, resolveLevel };
|
package/dist/index.js
CHANGED
|
@@ -175,10 +175,45 @@ var RuleBuilder = class {
|
|
|
175
175
|
}
|
|
176
176
|
};
|
|
177
177
|
|
|
178
|
+
// src/plugins/PluginRegistry.ts
|
|
179
|
+
var PluginAlreadyInstalledError = class extends Error {
|
|
180
|
+
constructor(pluginName) {
|
|
181
|
+
super(`Plugin "${pluginName}" is already installed`);
|
|
182
|
+
this.name = "PluginAlreadyInstalledError";
|
|
183
|
+
}
|
|
184
|
+
};
|
|
185
|
+
var PluginRegistry = class {
|
|
186
|
+
installed = /* @__PURE__ */ new Set();
|
|
187
|
+
/**
|
|
188
|
+
* Install a plugin on the given Guardian instance.
|
|
189
|
+
* Each plugin name may only be installed once per Guardian instance.
|
|
190
|
+
*/
|
|
191
|
+
install(plugin, guardian) {
|
|
192
|
+
if (this.installed.has(plugin.name)) {
|
|
193
|
+
throw new PluginAlreadyInstalledError(plugin.name);
|
|
194
|
+
}
|
|
195
|
+
plugin.install(guardian);
|
|
196
|
+
this.installed.add(plugin.name);
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Check if a plugin is installed by name.
|
|
200
|
+
*/
|
|
201
|
+
has(name) {
|
|
202
|
+
return this.installed.has(name);
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Get names of all installed plugins in registration order.
|
|
206
|
+
*/
|
|
207
|
+
getInstalled() {
|
|
208
|
+
return [...this.installed];
|
|
209
|
+
}
|
|
210
|
+
};
|
|
211
|
+
|
|
178
212
|
// src/engine/Guardian.ts
|
|
179
213
|
var Guardian = class {
|
|
180
214
|
signalStore;
|
|
181
215
|
riskEngine;
|
|
216
|
+
pluginRegistry = new PluginRegistry();
|
|
182
217
|
constructor(config = {}) {
|
|
183
218
|
const thresholds = config.levels ?? DEFAULT_RISK_LEVELS;
|
|
184
219
|
this.signalStore = new SignalStore();
|
|
@@ -205,6 +240,19 @@ var Guardian = class {
|
|
|
205
240
|
this.riskEngine.addRule(rule);
|
|
206
241
|
return this;
|
|
207
242
|
}
|
|
243
|
+
/**
|
|
244
|
+
* Install a plugin. Each plugin name may only be registered once.
|
|
245
|
+
*/
|
|
246
|
+
use(plugin) {
|
|
247
|
+
this.pluginRegistry.install(plugin, this);
|
|
248
|
+
return this;
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* Returns names of installed plugins.
|
|
252
|
+
*/
|
|
253
|
+
getInstalledPlugins() {
|
|
254
|
+
return this.pluginRegistry.getInstalled();
|
|
255
|
+
}
|
|
208
256
|
/**
|
|
209
257
|
* Run risk analysis and return an immutable report.
|
|
210
258
|
*/
|
|
@@ -212,7 +260,7 @@ var Guardian = class {
|
|
|
212
260
|
return this.riskEngine.analyze();
|
|
213
261
|
}
|
|
214
262
|
/**
|
|
215
|
-
* Clear all signals. Rules persist across resets.
|
|
263
|
+
* Clear all signals. Rules and installed plugins persist across resets.
|
|
216
264
|
*/
|
|
217
265
|
reset() {
|
|
218
266
|
this.signalStore.clear();
|
|
@@ -220,6 +268,6 @@ var Guardian = class {
|
|
|
220
268
|
}
|
|
221
269
|
};
|
|
222
270
|
|
|
223
|
-
export { DEFAULT_RISK_LEVELS, Guardian, RiskEngine, RuleBuilder, RuleEvaluator, ScoreCalculator, SignalStore, resolveLevel };
|
|
271
|
+
export { DEFAULT_RISK_LEVELS, Guardian, PluginAlreadyInstalledError, PluginRegistry, RiskEngine, RuleBuilder, RuleEvaluator, ScoreCalculator, SignalStore, resolveLevel };
|
|
224
272
|
//# sourceMappingURL=index.js.map
|
|
225
273
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/constants/defaults.ts","../src/utils/resolveLevel.ts","../src/report/Report.ts","../src/rules/RuleEvaluator.ts","../src/score/ScoreCalculator.ts","../src/utils/validation.ts","../src/signals/SignalStore.ts","../src/engine/RiskEngine.ts","../src/rules/RuleBuilder.ts","../src/engine/Guardian.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import type { RiskLevelThreshold } from '../types/report.js';\n\n/** Default risk level thresholds used when none are configured. */\nexport const DEFAULT_RISK_LEVELS: readonly RiskLevelThreshold[] = [\n { max: 20, level: 'LOW' },\n { max: 40, level: 'MEDIUM' },\n { max: 60, level: 'HIGH' },\n { max: Infinity, level: 'CRITICAL' },\n] as const;\n","import type { RiskLevelThreshold } from '../types/report.js';\nimport { DEFAULT_RISK_LEVELS } from '../constants/defaults.js';\n\n/**\n * Resolves a risk level label from a score using configured thresholds.\n * Thresholds are evaluated in order; the first threshold where score <= max wins.\n */\nexport function resolveLevel(\n score: number,\n thresholds: readonly RiskLevelThreshold[] = DEFAULT_RISK_LEVELS,\n): string {\n for (const threshold of thresholds) {\n if (score <= threshold.max) {\n return threshold.level;\n }\n }\n\n const last = thresholds[thresholds.length - 1];\n return last?.level ?? 'UNKNOWN';\n}\n","import type { MatchedRule } from '../types/rules.js';\nimport type { RiskReport } from '../types/report.js';\nimport { resolveLevel } from '../utils/resolveLevel.js';\nimport type { RiskLevelThreshold } from '../types/report.js';\n\n/**\n * Builds immutable risk reports.\n */\nexport class ReportBuilder {\n /**\n * Build a frozen risk report from evaluation results.\n */\n build(\n score: number,\n matchedRules: readonly MatchedRule[],\n thresholds: readonly RiskLevelThreshold[],\n analyzedAt: string = new Date().toISOString(),\n ): RiskReport {\n const reasons = matchedRules.map((rule) => rule.reason);\n const level = resolveLevel(score, thresholds);\n\n const report: RiskReport = {\n score,\n level,\n reasons: Object.freeze([...reasons]),\n matchedRules: Object.freeze([...matchedRules]),\n analyzedAt,\n };\n\n return Object.freeze(report);\n }\n}\n","import type { MatchedRule, Rule } from '../types/rules.js';\nimport type { SignalMap } from '../types/signals.js';\n\n/**\n * Evaluates rules against a signal map and returns matched rules.\n */\nexport class RuleEvaluator {\n /**\n * Evaluate all rules against the given signals.\n * Rules are evaluated in registration order (exhaustive, no short-circuit).\n */\n evaluate<TSignals extends SignalMap>(\n rules: readonly Rule<TSignals>[],\n signals: TSignals,\n ): MatchedRule[] {\n const matched: MatchedRule[] = [];\n\n for (const rule of rules) {\n if (rule.when(signals)) {\n matched.push({\n id: rule.id,\n name: rule.name,\n score: rule.score,\n reason: rule.reason ?? rule.name,\n });\n }\n }\n\n return matched;\n }\n}\n","import type { MatchedRule } from '../types/rules.js';\n\n/**\n * Calculates risk score from matched rules.\n */\nexport class ScoreCalculator {\n /**\n * Sum scores from all matched rules.\n */\n calculate(matchedRules: readonly MatchedRule[]): number {\n return matchedRules.reduce((total, rule) => total + rule.score, 0);\n }\n}\n","import { randomUUID } from 'node:crypto';\nimport type { SignalValue } from '../types/signals.js';\n\n/**\n * Validates that a value is an allowed signal primitive.\n * Signals must be string, number, boolean, or null — not objects or arrays.\n */\nexport function validateSignalValue(value: unknown): value is SignalValue {\n if (value === null) {\n return true;\n }\n\n const type = typeof value;\n return type === 'string' || type === 'number' || type === 'boolean';\n}\n\n/**\n * Generates a unique identifier for rules.\n */\nexport function generateId(): string {\n return randomUUID();\n}\n","import type { SignalMap, SignalValue } from '../types/signals.js';\nimport { validateSignalValue } from '../utils/validation.js';\n\n/**\n * Stores and retrieves signal values for risk evaluation.\n */\nexport class SignalStore {\n private readonly signals = new Map<string, SignalValue>();\n\n /**\n * Set a signal value. Overwrites any existing value for the key.\n */\n set(key: string, value: SignalValue): this {\n if (!validateSignalValue(value)) {\n throw new TypeError(\n `Invalid signal value for \"${key}\": signals must be string, number, boolean, or null`,\n );\n }\n\n this.signals.set(key, value);\n return this;\n }\n\n /**\n * Get a signal value by key.\n */\n get(key: string): SignalValue | undefined {\n return this.signals.get(key);\n }\n\n /**\n * Check if a signal exists.\n */\n has(key: string): boolean {\n return this.signals.has(key);\n }\n\n /**\n * Returns a frozen snapshot of all signals.\n */\n getAll(): SignalMap {\n const snapshot: Record<string, SignalValue> = {};\n for (const [key, value] of this.signals) {\n snapshot[key] = value;\n }\n return Object.freeze(snapshot);\n }\n\n /**\n * Clear all signals.\n */\n clear(): void {\n this.signals.clear();\n }\n}\n","import { DEFAULT_RISK_LEVELS } from '../constants/defaults.js';\nimport { ReportBuilder } from '../report/Report.js';\nimport { RuleEvaluator } from '../rules/RuleEvaluator.js';\nimport { ScoreCalculator } from '../score/ScoreCalculator.js';\nimport { SignalStore } from '../signals/SignalStore.js';\nimport type { Rule } from '../types/rules.js';\nimport type { RiskReport, RiskLevelThreshold } from '../types/report.js';\nimport type { SignalMap } from '../types/signals.js';\n\n/** Dependencies injected into RiskEngine. */\nexport interface RiskEngineDependencies {\n readonly signalStore: SignalStore;\n readonly ruleEvaluator: RuleEvaluator;\n readonly scoreCalculator: ScoreCalculator;\n readonly reportBuilder: ReportBuilder;\n}\n\n/**\n * Orchestrates signal evaluation, scoring, and report generation.\n */\nexport class RiskEngine {\n private readonly rules: Rule<SignalMap>[] = [];\n private readonly thresholds: readonly RiskLevelThreshold[];\n\n constructor(\n private readonly deps: RiskEngineDependencies,\n thresholds: readonly RiskLevelThreshold[] = DEFAULT_RISK_LEVELS,\n ) {\n this.thresholds = thresholds;\n }\n\n /**\n * Register a rule for evaluation.\n */\n addRule(rule: Rule<SignalMap>): void {\n this.rules.push(rule);\n }\n\n /**\n * Get all registered rules.\n */\n getRules(): readonly Rule<SignalMap>[] {\n return this.rules;\n }\n\n /**\n * Run the full risk analysis pipeline.\n */\n analyze(): RiskReport {\n const signals = this.deps.signalStore.getAll();\n const matchedRules = this.deps.ruleEvaluator.evaluate(this.rules, signals);\n const score = this.deps.scoreCalculator.calculate(matchedRules);\n\n return this.deps.reportBuilder.build(score, matchedRules, this.thresholds);\n }\n}\n","import type { CreateRuleInput, Rule } from '../types/rules.js';\nimport type { SignalMap } from '../types/signals.js';\nimport { generateId } from '../utils/validation.js';\n\n/**\n * Builds immutable rule definitions with auto-generated IDs.\n */\nexport class RuleBuilder {\n /**\n * Create a new rule from input configuration.\n */\n static create<TSignals extends SignalMap = SignalMap>(\n input: CreateRuleInput<TSignals>,\n ): Rule<TSignals> {\n const rule: Rule<TSignals> = {\n id: generateId(),\n name: input.name,\n score: input.score,\n when: input.when,\n ...(input.description !== undefined ? { description: input.description } : {}),\n ...(input.reason !== undefined ? { reason: input.reason } : {}),\n };\n\n return rule;\n }\n}\n","import { DEFAULT_RISK_LEVELS } from '../constants/defaults.js';\nimport { RiskEngine, type RiskEngineDependencies } from './RiskEngine.js';\nimport { ReportBuilder } from '../report/Report.js';\nimport { RuleBuilder } from '../rules/RuleBuilder.js';\nimport { RuleEvaluator } from '../rules/RuleEvaluator.js';\nimport { ScoreCalculator } from '../score/ScoreCalculator.js';\nimport { SignalStore } from '../signals/SignalStore.js';\nimport type { CreateRuleInput } from '../types/rules.js';\nimport type { GuardianConfig, RiskReport } from '../types/report.js';\nimport type { SignalValue } from '../types/signals.js';\n\n/**\n * Fluent public API for risk analysis.\n * Collects signals and rules, then produces an immutable report.\n */\nexport class Guardian {\n private readonly signalStore: SignalStore;\n private readonly riskEngine: RiskEngine;\n\n constructor(config: GuardianConfig = {}) {\n const thresholds = config.levels ?? DEFAULT_RISK_LEVELS;\n this.signalStore = new SignalStore();\n\n const deps: RiskEngineDependencies = {\n signalStore: this.signalStore,\n ruleEvaluator: new RuleEvaluator(),\n scoreCalculator: new ScoreCalculator(),\n reportBuilder: new ReportBuilder(),\n };\n\n this.riskEngine = new RiskEngine(deps, thresholds);\n }\n\n /**\n * Add a signal value for risk evaluation.\n */\n signal(key: string, value: SignalValue): this {\n this.signalStore.set(key, value);\n return this;\n }\n\n /**\n * Register a rule. ID is auto-generated.\n */\n rule(input: CreateRuleInput): this {\n const rule = RuleBuilder.create(input);\n this.riskEngine.addRule(rule);\n return this;\n }\n\n /**\n * Run risk analysis and return an immutable report.\n */\n analyze(): RiskReport {\n return this.riskEngine.analyze();\n }\n\n /**\n * Clear all signals. Rules persist across resets.\n */\n reset(): this {\n this.signalStore.clear();\n return this;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/constants/defaults.ts","../src/utils/resolveLevel.ts","../src/report/Report.ts","../src/rules/RuleEvaluator.ts","../src/score/ScoreCalculator.ts","../src/utils/validation.ts","../src/signals/SignalStore.ts","../src/engine/RiskEngine.ts","../src/rules/RuleBuilder.ts","../src/plugins/PluginRegistry.ts","../src/engine/Guardian.ts"],"names":[],"mappings":";;;AAGO,IAAM,mBAAA,GAAqD;AAAA,EAChE,EAAE,GAAA,EAAK,EAAA,EAAI,KAAA,EAAO,KAAA,EAAM;AAAA,EACxB,EAAE,GAAA,EAAK,EAAA,EAAI,KAAA,EAAO,QAAA,EAAS;AAAA,EAC3B,EAAE,GAAA,EAAK,EAAA,EAAI,KAAA,EAAO,MAAA,EAAO;AAAA,EACzB,EAAE,GAAA,EAAK,QAAA,EAAU,KAAA,EAAO,UAAA;AAC1B;;;ACDO,SAAS,YAAA,CACd,KAAA,EACA,UAAA,GAA4C,mBAAA,EACpC;AACR,EAAA,KAAA,MAAW,aAAa,UAAA,EAAY;AAClC,IAAA,IAAI,KAAA,IAAS,UAAU,GAAA,EAAK;AAC1B,MAAA,OAAO,SAAA,CAAU,KAAA;AAAA,IACnB;AAAA,EACF;AAEA,EAAA,MAAM,IAAA,GAAO,UAAA,CAAW,UAAA,CAAW,MAAA,GAAS,CAAC,CAAA;AAC7C,EAAA,OAAO,MAAM,KAAA,IAAS,SAAA;AACxB;;;ACXO,IAAM,gBAAN,MAAoB;AAAA;AAAA;AAAA;AAAA,EAIzB,KAAA,CACE,OACA,YAAA,EACA,UAAA,EACA,8BAAqB,IAAI,IAAA,EAAK,EAAE,WAAA,EAAY,EAChC;AACZ,IAAA,MAAM,UAAU,YAAA,CAAa,GAAA,CAAI,CAAC,IAAA,KAAS,KAAK,MAAM,CAAA;AACtD,IAAA,MAAM,KAAA,GAAQ,YAAA,CAAa,KAAA,EAAO,UAAU,CAAA;AAE5C,IAAA,MAAM,MAAA,GAAqB;AAAA,MACzB,KAAA;AAAA,MACA,KAAA;AAAA,MACA,SAAS,MAAA,CAAO,MAAA,CAAO,CAAC,GAAG,OAAO,CAAC,CAAA;AAAA,MACnC,cAAc,MAAA,CAAO,MAAA,CAAO,CAAC,GAAG,YAAY,CAAC,CAAA;AAAA,MAC7C;AAAA,KACF;AAEA,IAAA,OAAO,MAAA,CAAO,OAAO,MAAM,CAAA;AAAA,EAC7B;AACF,CAAA;;;ACzBO,IAAM,gBAAN,MAAoB;AAAA;AAAA;AAAA;AAAA;AAAA,EAKzB,QAAA,CACE,OACA,OAAA,EACe;AACf,IAAA,MAAM,UAAyB,EAAC;AAEhC,IAAA,KAAA,MAAW,QAAQ,KAAA,EAAO;AACxB,MAAA,IAAI,IAAA,CAAK,IAAA,CAAK,OAAO,CAAA,EAAG;AACtB,QAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,UACX,IAAI,IAAA,CAAK,EAAA;AAAA,UACT,MAAM,IAAA,CAAK,IAAA;AAAA,UACX,OAAO,IAAA,CAAK,KAAA;AAAA,UACZ,MAAA,EAAQ,IAAA,CAAK,MAAA,IAAU,IAAA,CAAK;AAAA,SAC7B,CAAA;AAAA,MACH;AAAA,IACF;AAEA,IAAA,OAAO,OAAA;AAAA,EACT;AACF;;;ACzBO,IAAM,kBAAN,MAAsB;AAAA;AAAA;AAAA;AAAA,EAI3B,UAAU,YAAA,EAA8C;AACtD,IAAA,OAAO,YAAA,CAAa,OAAO,CAAC,KAAA,EAAO,SAAS,KAAA,GAAQ,IAAA,CAAK,OAAO,CAAC,CAAA;AAAA,EACnE;AACF;ACLO,SAAS,oBAAoB,KAAA,EAAsC;AACxE,EAAA,IAAI,UAAU,IAAA,EAAM;AAClB,IAAA,OAAO,IAAA;AAAA,EACT;AAEA,EAAA,MAAM,OAAO,OAAO,KAAA;AACpB,EAAA,OAAO,IAAA,KAAS,QAAA,IAAY,IAAA,KAAS,QAAA,IAAY,IAAA,KAAS,SAAA;AAC5D;AAKO,SAAS,UAAA,GAAqB;AACnC,EAAA,OAAO,UAAA,EAAW;AACpB;;;ACfO,IAAM,cAAN,MAAkB;AAAA,EACN,OAAA,uBAAc,GAAA,EAAyB;AAAA;AAAA;AAAA;AAAA,EAKxD,GAAA,CAAI,KAAa,KAAA,EAA0B;AACzC,IAAA,IAAI,CAAC,mBAAA,CAAoB,KAAK,CAAA,EAAG;AAC/B,MAAA,MAAM,IAAI,SAAA;AAAA,QACR,6BAA6B,GAAG,CAAA,mDAAA;AAAA,OAClC;AAAA,IACF;AAEA,IAAA,IAAA,CAAK,OAAA,CAAQ,GAAA,CAAI,GAAA,EAAK,KAAK,CAAA;AAC3B,IAAA,OAAO,IAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,GAAA,EAAsC;AACxC,IAAA,OAAO,IAAA,CAAK,OAAA,CAAQ,GAAA,CAAI,GAAG,CAAA;AAAA,EAC7B;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,GAAA,EAAsB;AACxB,IAAA,OAAO,IAAA,CAAK,OAAA,CAAQ,GAAA,CAAI,GAAG,CAAA;AAAA,EAC7B;AAAA;AAAA;AAAA;AAAA,EAKA,MAAA,GAAoB;AAClB,IAAA,MAAM,WAAwC,EAAC;AAC/C,IAAA,KAAA,MAAW,CAAC,GAAA,EAAK,KAAK,CAAA,IAAK,KAAK,OAAA,EAAS;AACvC,MAAA,QAAA,CAAS,GAAG,CAAA,GAAI,KAAA;AAAA,IAClB;AACA,IAAA,OAAO,MAAA,CAAO,OAAO,QAAQ,CAAA;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA,EAKA,KAAA,GAAc;AACZ,IAAA,IAAA,CAAK,QAAQ,KAAA,EAAM;AAAA,EACrB;AACF;;;AClCO,IAAM,aAAN,MAAiB;AAAA,EAItB,WAAA,CACmB,IAAA,EACjB,UAAA,GAA4C,mBAAA,EAC5C;AAFiB,IAAA,IAAA,CAAA,IAAA,GAAA,IAAA;AAGjB,IAAA,IAAA,CAAK,UAAA,GAAa,UAAA;AAAA,EACpB;AAAA,EAJmB,IAAA;AAAA,EAJF,QAA2B,EAAC;AAAA,EAC5B,UAAA;AAAA;AAAA;AAAA;AAAA,EAYjB,QAAQ,IAAA,EAA6B;AACnC,IAAA,IAAA,CAAK,KAAA,CAAM,KAAK,IAAI,CAAA;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA,EAKA,QAAA,GAAuC;AACrC,IAAA,OAAO,IAAA,CAAK,KAAA;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAKA,OAAA,GAAsB;AACpB,IAAA,MAAM,OAAA,GAAU,IAAA,CAAK,IAAA,CAAK,WAAA,CAAY,MAAA,EAAO;AAC7C,IAAA,MAAM,eAAe,IAAA,CAAK,IAAA,CAAK,cAAc,QAAA,CAAS,IAAA,CAAK,OAAO,OAAO,CAAA;AACzE,IAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,IAAA,CAAK,eAAA,CAAgB,UAAU,YAAY,CAAA;AAE9D,IAAA,OAAO,KAAK,IAAA,CAAK,aAAA,CAAc,MAAM,KAAA,EAAO,YAAA,EAAc,KAAK,UAAU,CAAA;AAAA,EAC3E;AACF;;;AChDO,IAAM,cAAN,MAAkB;AAAA;AAAA;AAAA;AAAA,EAIvB,OAAO,OACL,KAAA,EACgB;AAChB,IAAA,MAAM,IAAA,GAAuB;AAAA,MAC3B,IAAI,UAAA,EAAW;AAAA,MACf,MAAM,KAAA,CAAM,IAAA;AAAA,MACZ,OAAO,KAAA,CAAM,KAAA;AAAA,MACb,MAAM,KAAA,CAAM,IAAA;AAAA,MACZ,GAAI,MAAM,WAAA,KAAgB,MAAA,GAAY,EAAE,WAAA,EAAa,KAAA,CAAM,WAAA,EAAY,GAAI,EAAC;AAAA,MAC5E,GAAI,MAAM,MAAA,KAAW,MAAA,GAAY,EAAE,MAAA,EAAQ,KAAA,CAAM,MAAA,EAAO,GAAI;AAAC,KAC/D;AAEA,IAAA,OAAO,IAAA;AAAA,EACT;AACF;;;ACnBO,IAAM,2BAAA,GAAN,cAA0C,KAAA,CAAM;AAAA,EACrD,YAAY,UAAA,EAAoB;AAC9B,IAAA,KAAA,CAAM,CAAA,QAAA,EAAW,UAAU,CAAA,sBAAA,CAAwB,CAAA;AACnD,IAAA,IAAA,CAAK,IAAA,GAAO,6BAAA;AAAA,EACd;AACF;AAKO,IAAM,iBAAN,MAAqB;AAAA,EACT,SAAA,uBAAgB,GAAA,EAAY;AAAA;AAAA;AAAA;AAAA;AAAA,EAM7C,OAAA,CAAQ,QAAgB,QAAA,EAA0B;AAChD,IAAA,IAAI,IAAA,CAAK,SAAA,CAAU,GAAA,CAAI,MAAA,CAAO,IAAI,CAAA,EAAG;AACnC,MAAA,MAAM,IAAI,2BAAA,CAA4B,MAAA,CAAO,IAAI,CAAA;AAAA,IACnD;AAEA,IAAA,MAAA,CAAO,QAAQ,QAAQ,CAAA;AACvB,IAAA,IAAA,CAAK,SAAA,CAAU,GAAA,CAAI,MAAA,CAAO,IAAI,CAAA;AAAA,EAChC;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,IAAA,EAAuB;AACzB,IAAA,OAAO,IAAA,CAAK,SAAA,CAAU,GAAA,CAAI,IAAI,CAAA;AAAA,EAChC;AAAA;AAAA;AAAA;AAAA,EAKA,YAAA,GAAkC;AAChC,IAAA,OAAO,CAAC,GAAG,IAAA,CAAK,SAAS,CAAA;AAAA,EAC3B;AACF;;;AC5BO,IAAM,WAAN,MAAe;AAAA,EACH,WAAA;AAAA,EACA,UAAA;AAAA,EACA,cAAA,GAAiB,IAAI,cAAA,EAAe;AAAA,EAErD,WAAA,CAAY,MAAA,GAAyB,EAAC,EAAG;AACvC,IAAA,MAAM,UAAA,GAAa,OAAO,MAAA,IAAU,mBAAA;AACpC,IAAA,IAAA,CAAK,WAAA,GAAc,IAAI,WAAA,EAAY;AAEnC,IAAA,MAAM,IAAA,GAA+B;AAAA,MACnC,aAAa,IAAA,CAAK,WAAA;AAAA,MAClB,aAAA,EAAe,IAAI,aAAA,EAAc;AAAA,MACjC,eAAA,EAAiB,IAAI,eAAA,EAAgB;AAAA,MACrC,aAAA,EAAe,IAAI,aAAA;AAAc,KACnC;AAEA,IAAA,IAAA,CAAK,UAAA,GAAa,IAAI,UAAA,CAAW,IAAA,EAAM,UAAU,CAAA;AAAA,EACnD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAA,CAAO,KAAa,KAAA,EAA0B;AAC5C,IAAA,IAAA,CAAK,WAAA,CAAY,GAAA,CAAI,GAAA,EAAK,KAAK,CAAA;AAC/B,IAAA,OAAO,IAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,KAAK,KAAA,EAA8B;AACjC,IAAA,MAAM,IAAA,GAAO,WAAA,CAAY,MAAA,CAAO,KAAK,CAAA;AACrC,IAAA,IAAA,CAAK,UAAA,CAAW,QAAQ,IAAI,CAAA;AAC5B,IAAA,OAAO,IAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,MAAA,EAAsB;AACxB,IAAA,IAAA,CAAK,cAAA,CAAe,OAAA,CAAQ,MAAA,EAAQ,IAAI,CAAA;AACxC,IAAA,OAAO,IAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,mBAAA,GAAyC;AACvC,IAAA,OAAO,IAAA,CAAK,eAAe,YAAA,EAAa;AAAA,EAC1C;AAAA;AAAA;AAAA;AAAA,EAKA,OAAA,GAAsB;AACpB,IAAA,OAAO,IAAA,CAAK,WAAW,OAAA,EAAQ;AAAA,EACjC;AAAA;AAAA;AAAA;AAAA,EAKA,KAAA,GAAc;AACZ,IAAA,IAAA,CAAK,YAAY,KAAA,EAAM;AACvB,IAAA,OAAO,IAAA;AAAA,EACT;AACF","file":"index.js","sourcesContent":["import type { RiskLevelThreshold } from '../types/report.js';\n\n/** Default risk level thresholds used when none are configured. */\nexport const DEFAULT_RISK_LEVELS: readonly RiskLevelThreshold[] = [\n { max: 20, level: 'LOW' },\n { max: 40, level: 'MEDIUM' },\n { max: 60, level: 'HIGH' },\n { max: Infinity, level: 'CRITICAL' },\n] as const;\n","import type { RiskLevelThreshold } from '../types/report.js';\nimport { DEFAULT_RISK_LEVELS } from '../constants/defaults.js';\n\n/**\n * Resolves a risk level label from a score using configured thresholds.\n * Thresholds are evaluated in order; the first threshold where score <= max wins.\n */\nexport function resolveLevel(\n score: number,\n thresholds: readonly RiskLevelThreshold[] = DEFAULT_RISK_LEVELS,\n): string {\n for (const threshold of thresholds) {\n if (score <= threshold.max) {\n return threshold.level;\n }\n }\n\n const last = thresholds[thresholds.length - 1];\n return last?.level ?? 'UNKNOWN';\n}\n","import type { MatchedRule } from '../types/rules.js';\nimport type { RiskReport } from '../types/report.js';\nimport { resolveLevel } from '../utils/resolveLevel.js';\nimport type { RiskLevelThreshold } from '../types/report.js';\n\n/**\n * Builds immutable risk reports.\n */\nexport class ReportBuilder {\n /**\n * Build a frozen risk report from evaluation results.\n */\n build(\n score: number,\n matchedRules: readonly MatchedRule[],\n thresholds: readonly RiskLevelThreshold[],\n analyzedAt: string = new Date().toISOString(),\n ): RiskReport {\n const reasons = matchedRules.map((rule) => rule.reason);\n const level = resolveLevel(score, thresholds);\n\n const report: RiskReport = {\n score,\n level,\n reasons: Object.freeze([...reasons]),\n matchedRules: Object.freeze([...matchedRules]),\n analyzedAt,\n };\n\n return Object.freeze(report);\n }\n}\n","import type { MatchedRule, Rule } from '../types/rules.js';\nimport type { SignalMap } from '../types/signals.js';\n\n/**\n * Evaluates rules against a signal map and returns matched rules.\n */\nexport class RuleEvaluator {\n /**\n * Evaluate all rules against the given signals.\n * Rules are evaluated in registration order (exhaustive, no short-circuit).\n */\n evaluate<TSignals extends SignalMap>(\n rules: readonly Rule<TSignals>[],\n signals: TSignals,\n ): MatchedRule[] {\n const matched: MatchedRule[] = [];\n\n for (const rule of rules) {\n if (rule.when(signals)) {\n matched.push({\n id: rule.id,\n name: rule.name,\n score: rule.score,\n reason: rule.reason ?? rule.name,\n });\n }\n }\n\n return matched;\n }\n}\n","import type { MatchedRule } from '../types/rules.js';\n\n/**\n * Calculates risk score from matched rules.\n */\nexport class ScoreCalculator {\n /**\n * Sum scores from all matched rules.\n */\n calculate(matchedRules: readonly MatchedRule[]): number {\n return matchedRules.reduce((total, rule) => total + rule.score, 0);\n }\n}\n","import { randomUUID } from 'node:crypto';\nimport type { SignalValue } from '../types/signals.js';\n\n/**\n * Validates that a value is an allowed signal primitive.\n * Signals must be string, number, boolean, or null — not objects or arrays.\n */\nexport function validateSignalValue(value: unknown): value is SignalValue {\n if (value === null) {\n return true;\n }\n\n const type = typeof value;\n return type === 'string' || type === 'number' || type === 'boolean';\n}\n\n/**\n * Generates a unique identifier for rules.\n */\nexport function generateId(): string {\n return randomUUID();\n}\n","import type { SignalMap, SignalValue } from '../types/signals.js';\nimport { validateSignalValue } from '../utils/validation.js';\n\n/**\n * Stores and retrieves signal values for risk evaluation.\n */\nexport class SignalStore {\n private readonly signals = new Map<string, SignalValue>();\n\n /**\n * Set a signal value. Overwrites any existing value for the key.\n */\n set(key: string, value: SignalValue): this {\n if (!validateSignalValue(value)) {\n throw new TypeError(\n `Invalid signal value for \"${key}\": signals must be string, number, boolean, or null`,\n );\n }\n\n this.signals.set(key, value);\n return this;\n }\n\n /**\n * Get a signal value by key.\n */\n get(key: string): SignalValue | undefined {\n return this.signals.get(key);\n }\n\n /**\n * Check if a signal exists.\n */\n has(key: string): boolean {\n return this.signals.has(key);\n }\n\n /**\n * Returns a frozen snapshot of all signals.\n */\n getAll(): SignalMap {\n const snapshot: Record<string, SignalValue> = {};\n for (const [key, value] of this.signals) {\n snapshot[key] = value;\n }\n return Object.freeze(snapshot);\n }\n\n /**\n * Clear all signals.\n */\n clear(): void {\n this.signals.clear();\n }\n}\n","import { DEFAULT_RISK_LEVELS } from '../constants/defaults.js';\nimport { ReportBuilder } from '../report/Report.js';\nimport { RuleEvaluator } from '../rules/RuleEvaluator.js';\nimport { ScoreCalculator } from '../score/ScoreCalculator.js';\nimport { SignalStore } from '../signals/SignalStore.js';\nimport type { Rule } from '../types/rules.js';\nimport type { RiskReport, RiskLevelThreshold } from '../types/report.js';\nimport type { SignalMap } from '../types/signals.js';\n\n/** Dependencies injected into RiskEngine. */\nexport interface RiskEngineDependencies {\n readonly signalStore: SignalStore;\n readonly ruleEvaluator: RuleEvaluator;\n readonly scoreCalculator: ScoreCalculator;\n readonly reportBuilder: ReportBuilder;\n}\n\n/**\n * Orchestrates signal evaluation, scoring, and report generation.\n */\nexport class RiskEngine {\n private readonly rules: Rule<SignalMap>[] = [];\n private readonly thresholds: readonly RiskLevelThreshold[];\n\n constructor(\n private readonly deps: RiskEngineDependencies,\n thresholds: readonly RiskLevelThreshold[] = DEFAULT_RISK_LEVELS,\n ) {\n this.thresholds = thresholds;\n }\n\n /**\n * Register a rule for evaluation.\n */\n addRule(rule: Rule<SignalMap>): void {\n this.rules.push(rule);\n }\n\n /**\n * Get all registered rules.\n */\n getRules(): readonly Rule<SignalMap>[] {\n return this.rules;\n }\n\n /**\n * Run the full risk analysis pipeline.\n */\n analyze(): RiskReport {\n const signals = this.deps.signalStore.getAll();\n const matchedRules = this.deps.ruleEvaluator.evaluate(this.rules, signals);\n const score = this.deps.scoreCalculator.calculate(matchedRules);\n\n return this.deps.reportBuilder.build(score, matchedRules, this.thresholds);\n }\n}\n","import type { CreateRuleInput, Rule } from '../types/rules.js';\nimport type { SignalMap } from '../types/signals.js';\nimport { generateId } from '../utils/validation.js';\n\n/**\n * Builds immutable rule definitions with auto-generated IDs.\n */\nexport class RuleBuilder {\n /**\n * Create a new rule from input configuration.\n */\n static create<TSignals extends SignalMap = SignalMap>(\n input: CreateRuleInput<TSignals>,\n ): Rule<TSignals> {\n const rule: Rule<TSignals> = {\n id: generateId(),\n name: input.name,\n score: input.score,\n when: input.when,\n ...(input.description !== undefined ? { description: input.description } : {}),\n ...(input.reason !== undefined ? { reason: input.reason } : {}),\n };\n\n return rule;\n }\n}\n","import type { Guardian } from '../engine/Guardian.js';\nimport type { Plugin } from './Plugin.js';\n\n/**\n * Thrown when attempting to register a plugin that is already installed.\n */\nexport class PluginAlreadyInstalledError extends Error {\n constructor(pluginName: string) {\n super(`Plugin \"${pluginName}\" is already installed`);\n this.name = 'PluginAlreadyInstalledError';\n }\n}\n\n/**\n * Manages plugin lifecycle: register once, track installed plugins.\n */\nexport class PluginRegistry {\n private readonly installed = new Set<string>();\n\n /**\n * Install a plugin on the given Guardian instance.\n * Each plugin name may only be installed once per Guardian instance.\n */\n install(plugin: Plugin, guardian: Guardian): void {\n if (this.installed.has(plugin.name)) {\n throw new PluginAlreadyInstalledError(plugin.name);\n }\n\n plugin.install(guardian);\n this.installed.add(plugin.name);\n }\n\n /**\n * Check if a plugin is installed by name.\n */\n has(name: string): boolean {\n return this.installed.has(name);\n }\n\n /**\n * Get names of all installed plugins in registration order.\n */\n getInstalled(): readonly string[] {\n return [...this.installed];\n }\n}\n","import { DEFAULT_RISK_LEVELS } from '../constants/defaults.js';\nimport { RiskEngine, type RiskEngineDependencies } from './RiskEngine.js';\nimport { ReportBuilder } from '../report/Report.js';\nimport { RuleBuilder } from '../rules/RuleBuilder.js';\nimport { RuleEvaluator } from '../rules/RuleEvaluator.js';\nimport { ScoreCalculator } from '../score/ScoreCalculator.js';\nimport { SignalStore } from '../signals/SignalStore.js';\nimport { PluginRegistry } from '../plugins/PluginRegistry.js';\nimport type { Plugin } from '../plugins/Plugin.js';\nimport type { CreateRuleInput } from '../types/rules.js';\nimport type { GuardianConfig, RiskReport } from '../types/report.js';\nimport type { SignalValue } from '../types/signals.js';\n\n/**\n * Fluent public API for risk analysis.\n * Collects signals and rules, then produces an immutable report.\n */\nexport class Guardian {\n private readonly signalStore: SignalStore;\n private readonly riskEngine: RiskEngine;\n private readonly pluginRegistry = new PluginRegistry();\n\n constructor(config: GuardianConfig = {}) {\n const thresholds = config.levels ?? DEFAULT_RISK_LEVELS;\n this.signalStore = new SignalStore();\n\n const deps: RiskEngineDependencies = {\n signalStore: this.signalStore,\n ruleEvaluator: new RuleEvaluator(),\n scoreCalculator: new ScoreCalculator(),\n reportBuilder: new ReportBuilder(),\n };\n\n this.riskEngine = new RiskEngine(deps, thresholds);\n }\n\n /**\n * Add a signal value for risk evaluation.\n */\n signal(key: string, value: SignalValue): this {\n this.signalStore.set(key, value);\n return this;\n }\n\n /**\n * Register a rule. ID is auto-generated.\n */\n rule(input: CreateRuleInput): this {\n const rule = RuleBuilder.create(input);\n this.riskEngine.addRule(rule);\n return this;\n }\n\n /**\n * Install a plugin. Each plugin name may only be registered once.\n */\n use(plugin: Plugin): this {\n this.pluginRegistry.install(plugin, this);\n return this;\n }\n\n /**\n * Returns names of installed plugins.\n */\n getInstalledPlugins(): readonly string[] {\n return this.pluginRegistry.getInstalled();\n }\n\n /**\n * Run risk analysis and return an immutable report.\n */\n analyze(): RiskReport {\n return this.riskEngine.analyze();\n }\n\n /**\n * Clear all signals. Rules and installed plugins persist across resets.\n */\n reset(): this {\n this.signalStore.clear();\n return this;\n }\n}\n"]}
|