@vibecheckai/cli 3.2.6 → 3.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/bin/registry.js +192 -5
- package/bin/runners/lib/agent-firewall/change-packet/builder.js +280 -6
- package/bin/runners/lib/agent-firewall/critic/index.js +151 -0
- package/bin/runners/lib/agent-firewall/critic/judge.js +432 -0
- package/bin/runners/lib/agent-firewall/critic/prompts.js +305 -0
- package/bin/runners/lib/agent-firewall/lawbook/distributor.js +465 -0
- package/bin/runners/lib/agent-firewall/lawbook/evaluator.js +604 -0
- package/bin/runners/lib/agent-firewall/lawbook/index.js +304 -0
- package/bin/runners/lib/agent-firewall/lawbook/registry.js +514 -0
- package/bin/runners/lib/agent-firewall/lawbook/schema.js +420 -0
- package/bin/runners/lib/agent-firewall/logger.js +141 -0
- package/bin/runners/lib/agent-firewall/policy/loader.js +312 -4
- package/bin/runners/lib/agent-firewall/policy/rules/ghost-env.js +113 -1
- package/bin/runners/lib/agent-firewall/policy/rules/ghost-route.js +133 -6
- package/bin/runners/lib/agent-firewall/proposal/extractor.js +394 -0
- package/bin/runners/lib/agent-firewall/proposal/index.js +212 -0
- package/bin/runners/lib/agent-firewall/proposal/schema.js +251 -0
- package/bin/runners/lib/agent-firewall/proposal/validator.js +386 -0
- package/bin/runners/lib/agent-firewall/reality/index.js +332 -0
- package/bin/runners/lib/agent-firewall/reality/state.js +625 -0
- package/bin/runners/lib/agent-firewall/reality/watcher.js +322 -0
- package/bin/runners/lib/agent-firewall/risk/index.js +173 -0
- package/bin/runners/lib/agent-firewall/risk/scorer.js +328 -0
- package/bin/runners/lib/agent-firewall/risk/thresholds.js +321 -0
- package/bin/runners/lib/agent-firewall/risk/vectors.js +421 -0
- package/bin/runners/lib/agent-firewall/simulator/diff-simulator.js +472 -0
- package/bin/runners/lib/agent-firewall/simulator/import-resolver.js +346 -0
- package/bin/runners/lib/agent-firewall/simulator/index.js +181 -0
- package/bin/runners/lib/agent-firewall/simulator/route-validator.js +380 -0
- package/bin/runners/lib/agent-firewall/time-machine/incident-correlator.js +661 -0
- package/bin/runners/lib/agent-firewall/time-machine/index.js +267 -0
- package/bin/runners/lib/agent-firewall/time-machine/replay-engine.js +436 -0
- package/bin/runners/lib/agent-firewall/time-machine/state-reconstructor.js +490 -0
- package/bin/runners/lib/agent-firewall/time-machine/timeline-builder.js +530 -0
- package/bin/runners/lib/analyzers.js +81 -18
- package/bin/runners/lib/authority-badge.js +425 -0
- package/bin/runners/lib/cli-output.js +7 -1
- package/bin/runners/lib/error-handler.js +16 -9
- package/bin/runners/lib/exit-codes.js +275 -0
- package/bin/runners/lib/global-flags.js +37 -0
- package/bin/runners/lib/help-formatter.js +413 -0
- package/bin/runners/lib/logger.js +38 -0
- package/bin/runners/lib/unified-cli-output.js +604 -0
- package/bin/runners/lib/upsell.js +148 -0
- package/bin/runners/runApprove.js +1200 -0
- package/bin/runners/runAuth.js +324 -95
- package/bin/runners/runCheckpoint.js +39 -21
- package/bin/runners/runClassify.js +859 -0
- package/bin/runners/runContext.js +136 -24
- package/bin/runners/runDoctor.js +108 -68
- package/bin/runners/runFix.js +6 -5
- package/bin/runners/runGuard.js +212 -118
- package/bin/runners/runInit.js +3 -2
- package/bin/runners/runMcp.js +130 -52
- package/bin/runners/runPolish.js +43 -20
- package/bin/runners/runProve.js +1 -2
- package/bin/runners/runReport.js +3 -2
- package/bin/runners/runScan.js +63 -44
- package/bin/runners/runShip.js +3 -4
- package/bin/runners/runValidate.js +19 -2
- package/bin/runners/runWatch.js +104 -53
- package/bin/vibecheck.js +106 -19
- package/mcp-server/HARDENING_SUMMARY.md +299 -0
- package/mcp-server/agent-firewall-interceptor.js +367 -31
- package/mcp-server/authority-tools.js +569 -0
- package/mcp-server/conductor/conflict-resolver.js +588 -0
- package/mcp-server/conductor/execution-planner.js +544 -0
- package/mcp-server/conductor/index.js +377 -0
- package/mcp-server/conductor/lock-manager.js +615 -0
- package/mcp-server/conductor/request-queue.js +550 -0
- package/mcp-server/conductor/session-manager.js +500 -0
- package/mcp-server/conductor/tools.js +510 -0
- package/mcp-server/index.js +1149 -243
- package/mcp-server/lib/{api-client.js → api-client.cjs} +40 -4
- package/mcp-server/lib/logger.cjs +30 -0
- package/mcp-server/logger.js +173 -0
- package/mcp-server/package.json +2 -2
- package/mcp-server/premium-tools.js +2 -2
- package/mcp-server/tier-auth.js +245 -35
- package/mcp-server/truth-firewall-tools.js +145 -15
- package/mcp-server/vibecheck-tools.js +2 -2
- package/package.json +2 -3
- package/mcp-server/index.old.js +0 -4137
- package/mcp-server/package-lock.json +0 -165
|
@@ -0,0 +1,322 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reality State Watcher
|
|
3
|
+
*
|
|
4
|
+
* Watches for file system changes and incrementally updates the reality state.
|
|
5
|
+
* Uses chokidar for efficient file watching.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
"use strict";
|
|
9
|
+
|
|
10
|
+
const fs = require("fs");
|
|
11
|
+
const path = require("path");
|
|
12
|
+
const { EventEmitter } = require("events");
|
|
13
|
+
const { getRealityState, invalidateCache, hashFile, classifyFileDomain } = require("./state");
|
|
14
|
+
|
|
15
|
+
// Try to load chokidar if available
|
|
16
|
+
let chokidar = null;
|
|
17
|
+
try {
|
|
18
|
+
chokidar = require("chokidar");
|
|
19
|
+
} catch {
|
|
20
|
+
// chokidar not available, fall back to polling
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Reality State Watcher
|
|
25
|
+
* Emits events when reality state changes
|
|
26
|
+
*/
|
|
27
|
+
class RealityWatcher extends EventEmitter {
|
|
28
|
+
constructor(projectRoot, options = {}) {
|
|
29
|
+
super();
|
|
30
|
+
|
|
31
|
+
this.projectRoot = projectRoot;
|
|
32
|
+
this.options = {
|
|
33
|
+
debounceMs: options.debounceMs || 500,
|
|
34
|
+
watchPatterns: options.watchPatterns || [
|
|
35
|
+
"**/*.ts",
|
|
36
|
+
"**/*.tsx",
|
|
37
|
+
"**/*.js",
|
|
38
|
+
"**/*.jsx",
|
|
39
|
+
".env*",
|
|
40
|
+
".guardrail/**/*.json",
|
|
41
|
+
".vibecheck/**/*.json",
|
|
42
|
+
],
|
|
43
|
+
ignorePatterns: options.ignorePatterns || [
|
|
44
|
+
"**/node_modules/**",
|
|
45
|
+
"**/dist/**",
|
|
46
|
+
"**/build/**",
|
|
47
|
+
"**/.git/**",
|
|
48
|
+
"**/coverage/**",
|
|
49
|
+
],
|
|
50
|
+
...options,
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
this.watcher = null;
|
|
54
|
+
this.debounceTimer = null;
|
|
55
|
+
this.pendingChanges = new Set();
|
|
56
|
+
this.isRunning = false;
|
|
57
|
+
this.lastState = null;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Start watching for changes
|
|
62
|
+
*/
|
|
63
|
+
start() {
|
|
64
|
+
if (this.isRunning) {
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
this.isRunning = true;
|
|
69
|
+
|
|
70
|
+
// Get initial state
|
|
71
|
+
this.lastState = getRealityState(this.projectRoot);
|
|
72
|
+
this.emit("ready", this.lastState);
|
|
73
|
+
|
|
74
|
+
if (chokidar) {
|
|
75
|
+
this._startChokidarWatch();
|
|
76
|
+
} else {
|
|
77
|
+
this._startPollingWatch();
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Stop watching
|
|
83
|
+
*/
|
|
84
|
+
stop() {
|
|
85
|
+
this.isRunning = false;
|
|
86
|
+
|
|
87
|
+
if (this.watcher) {
|
|
88
|
+
if (typeof this.watcher.close === "function") {
|
|
89
|
+
this.watcher.close();
|
|
90
|
+
}
|
|
91
|
+
this.watcher = null;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
if (this.debounceTimer) {
|
|
95
|
+
clearTimeout(this.debounceTimer);
|
|
96
|
+
this.debounceTimer = null;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
if (this.pollInterval) {
|
|
100
|
+
clearInterval(this.pollInterval);
|
|
101
|
+
this.pollInterval = null;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
this.emit("stopped");
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Force refresh of reality state
|
|
109
|
+
*/
|
|
110
|
+
refresh() {
|
|
111
|
+
invalidateCache();
|
|
112
|
+
this.lastState = getRealityState(this.projectRoot, { forceRefresh: true });
|
|
113
|
+
this.emit("refresh", this.lastState);
|
|
114
|
+
return this.lastState;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Get current state
|
|
119
|
+
*/
|
|
120
|
+
getState() {
|
|
121
|
+
return this.lastState || getRealityState(this.projectRoot);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Start chokidar-based watching
|
|
126
|
+
*/
|
|
127
|
+
_startChokidarWatch() {
|
|
128
|
+
this.watcher = chokidar.watch(this.options.watchPatterns, {
|
|
129
|
+
cwd: this.projectRoot,
|
|
130
|
+
ignored: this.options.ignorePatterns,
|
|
131
|
+
persistent: true,
|
|
132
|
+
ignoreInitial: true,
|
|
133
|
+
awaitWriteFinish: {
|
|
134
|
+
stabilityThreshold: 200,
|
|
135
|
+
pollInterval: 100,
|
|
136
|
+
},
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
this.watcher
|
|
140
|
+
.on("add", (filePath) => this._handleChange("add", filePath))
|
|
141
|
+
.on("change", (filePath) => this._handleChange("change", filePath))
|
|
142
|
+
.on("unlink", (filePath) => this._handleChange("delete", filePath))
|
|
143
|
+
.on("error", (error) => this.emit("error", error));
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Start polling-based watching (fallback)
|
|
148
|
+
*/
|
|
149
|
+
_startPollingWatch() {
|
|
150
|
+
let lastCheck = new Map();
|
|
151
|
+
|
|
152
|
+
// Initial scan
|
|
153
|
+
this._scanFiles(lastCheck);
|
|
154
|
+
|
|
155
|
+
// Poll every 2 seconds
|
|
156
|
+
this.pollInterval = setInterval(() => {
|
|
157
|
+
const currentFiles = new Map();
|
|
158
|
+
this._scanFiles(currentFiles);
|
|
159
|
+
|
|
160
|
+
// Detect changes
|
|
161
|
+
for (const [filePath, hash] of currentFiles) {
|
|
162
|
+
if (!lastCheck.has(filePath)) {
|
|
163
|
+
this._handleChange("add", filePath);
|
|
164
|
+
} else if (lastCheck.get(filePath) !== hash) {
|
|
165
|
+
this._handleChange("change", filePath);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// Detect deletions
|
|
170
|
+
for (const [filePath] of lastCheck) {
|
|
171
|
+
if (!currentFiles.has(filePath)) {
|
|
172
|
+
this._handleChange("delete", filePath);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
lastCheck = currentFiles;
|
|
177
|
+
}, 2000);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Scan files for polling mode
|
|
182
|
+
*/
|
|
183
|
+
_scanFiles(fileMap) {
|
|
184
|
+
const extensions = [".ts", ".tsx", ".js", ".jsx", ".json"];
|
|
185
|
+
const ignoreDirs = ["node_modules", ".git", "dist", "build"];
|
|
186
|
+
|
|
187
|
+
const scan = (dir, depth = 0) => {
|
|
188
|
+
if (depth > 5) return;
|
|
189
|
+
|
|
190
|
+
try {
|
|
191
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
192
|
+
for (const entry of entries) {
|
|
193
|
+
const fullPath = path.join(dir, entry.name);
|
|
194
|
+
const relativePath = path.relative(this.projectRoot, fullPath);
|
|
195
|
+
|
|
196
|
+
if (entry.isDirectory()) {
|
|
197
|
+
if (!entry.name.startsWith(".") && !ignoreDirs.includes(entry.name)) {
|
|
198
|
+
scan(fullPath, depth + 1);
|
|
199
|
+
}
|
|
200
|
+
} else if (entry.isFile()) {
|
|
201
|
+
const ext = path.extname(entry.name);
|
|
202
|
+
if (extensions.includes(ext) || entry.name.startsWith(".env")) {
|
|
203
|
+
const hash = hashFile(fullPath);
|
|
204
|
+
if (hash) {
|
|
205
|
+
fileMap.set(relativePath, hash);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
} catch {
|
|
211
|
+
// Ignore errors
|
|
212
|
+
}
|
|
213
|
+
};
|
|
214
|
+
|
|
215
|
+
scan(this.projectRoot);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Handle file change
|
|
220
|
+
*/
|
|
221
|
+
_handleChange(type, filePath) {
|
|
222
|
+
this.pendingChanges.add({ type, filePath, timestamp: Date.now() });
|
|
223
|
+
|
|
224
|
+
// Debounce updates
|
|
225
|
+
if (this.debounceTimer) {
|
|
226
|
+
clearTimeout(this.debounceTimer);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
this.debounceTimer = setTimeout(() => {
|
|
230
|
+
this._processChanges();
|
|
231
|
+
}, this.options.debounceMs);
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* Process pending changes
|
|
236
|
+
*/
|
|
237
|
+
_processChanges() {
|
|
238
|
+
if (this.pendingChanges.size === 0) return;
|
|
239
|
+
|
|
240
|
+
const changes = Array.from(this.pendingChanges);
|
|
241
|
+
this.pendingChanges.clear();
|
|
242
|
+
|
|
243
|
+
// Determine if we need to refresh reality state
|
|
244
|
+
const significantChange = changes.some(c =>
|
|
245
|
+
c.filePath.includes(".guardrail") ||
|
|
246
|
+
c.filePath.includes(".vibecheck") ||
|
|
247
|
+
c.filePath.includes(".env") ||
|
|
248
|
+
c.filePath.includes("routes") ||
|
|
249
|
+
c.filePath.includes("api")
|
|
250
|
+
);
|
|
251
|
+
|
|
252
|
+
if (significantChange) {
|
|
253
|
+
// Full refresh for significant changes
|
|
254
|
+
invalidateCache();
|
|
255
|
+
this.lastState = getRealityState(this.projectRoot, { forceRefresh: true });
|
|
256
|
+
} else {
|
|
257
|
+
// Incremental update for minor changes
|
|
258
|
+
this._incrementalUpdate(changes);
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
// Emit change event
|
|
262
|
+
this.emit("change", {
|
|
263
|
+
changes,
|
|
264
|
+
state: this.lastState,
|
|
265
|
+
significantChange,
|
|
266
|
+
});
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
/**
|
|
270
|
+
* Incremental update for minor file changes
|
|
271
|
+
*/
|
|
272
|
+
_incrementalUpdate(changes) {
|
|
273
|
+
if (!this.lastState) {
|
|
274
|
+
this.lastState = getRealityState(this.projectRoot);
|
|
275
|
+
return;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
for (const change of changes) {
|
|
279
|
+
const relativePath = change.filePath.replace(/\\/g, "/");
|
|
280
|
+
|
|
281
|
+
switch (change.type) {
|
|
282
|
+
case "add":
|
|
283
|
+
case "change": {
|
|
284
|
+
const fullPath = path.join(this.projectRoot, change.filePath);
|
|
285
|
+
if (fs.existsSync(fullPath)) {
|
|
286
|
+
try {
|
|
287
|
+
const stat = fs.statSync(fullPath);
|
|
288
|
+
this.lastState.files.set(relativePath, {
|
|
289
|
+
hash: hashFile(fullPath),
|
|
290
|
+
modified: stat.mtime,
|
|
291
|
+
size: stat.size,
|
|
292
|
+
domain: classifyFileDomain(relativePath),
|
|
293
|
+
});
|
|
294
|
+
} catch {
|
|
295
|
+
// Ignore stat errors
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
break;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
case "delete":
|
|
302
|
+
this.lastState.files.delete(relativePath);
|
|
303
|
+
break;
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
// Update timestamp
|
|
308
|
+
this.lastState.lastUpdated = new Date();
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
/**
|
|
313
|
+
* Create a watcher instance
|
|
314
|
+
*/
|
|
315
|
+
function createWatcher(projectRoot, options) {
|
|
316
|
+
return new RealityWatcher(projectRoot, options);
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
module.exports = {
|
|
320
|
+
RealityWatcher,
|
|
321
|
+
createWatcher,
|
|
322
|
+
};
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Risk Scoring Module
|
|
3
|
+
*
|
|
4
|
+
* Entry point for the risk scoring engine.
|
|
5
|
+
* Provides risk assessment for change proposals.
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* const { risk } = require('./risk');
|
|
9
|
+
*
|
|
10
|
+
* const score = risk.calculate({
|
|
11
|
+
* files: [{ path: 'src/auth.ts' }],
|
|
12
|
+
* operations: [{ type: 'modify', path: 'src/auth.ts' }],
|
|
13
|
+
* claims: [...],
|
|
14
|
+
* evidence: [...],
|
|
15
|
+
* });
|
|
16
|
+
*
|
|
17
|
+
* console.log(score.total, score.level, score.decision);
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
"use strict";
|
|
21
|
+
|
|
22
|
+
const {
|
|
23
|
+
calculateRiskScore,
|
|
24
|
+
quickAssess,
|
|
25
|
+
buildContext,
|
|
26
|
+
getDomainBreakdown,
|
|
27
|
+
formatRiskScore,
|
|
28
|
+
compareScores,
|
|
29
|
+
RISK_VECTORS,
|
|
30
|
+
RISK_LEVELS,
|
|
31
|
+
} = require("./scorer");
|
|
32
|
+
|
|
33
|
+
const {
|
|
34
|
+
DEFAULT_THRESHOLDS,
|
|
35
|
+
THRESHOLD_PROFILES,
|
|
36
|
+
loadThresholds,
|
|
37
|
+
getDecision,
|
|
38
|
+
} = require("./thresholds");
|
|
39
|
+
|
|
40
|
+
const { getRiskLevel, getVectorIds, getVector } = require("./vectors");
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Risk scoring singleton
|
|
44
|
+
*/
|
|
45
|
+
const risk = {
|
|
46
|
+
/**
|
|
47
|
+
* Calculate full risk score
|
|
48
|
+
* @param {Object} params - Score parameters
|
|
49
|
+
* @returns {Object} Risk score result
|
|
50
|
+
*/
|
|
51
|
+
calculate(params) {
|
|
52
|
+
return calculateRiskScore(params);
|
|
53
|
+
},
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Quick risk assessment
|
|
57
|
+
* @param {Object} params - Basic parameters
|
|
58
|
+
* @returns {Object} Quick assessment
|
|
59
|
+
*/
|
|
60
|
+
quick(params) {
|
|
61
|
+
return quickAssess(params);
|
|
62
|
+
},
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Get risk level from score
|
|
66
|
+
* @param {number} score - Numeric score
|
|
67
|
+
* @returns {Object} Risk level
|
|
68
|
+
*/
|
|
69
|
+
getLevel(score) {
|
|
70
|
+
return getRiskLevel(score);
|
|
71
|
+
},
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Format risk score for display
|
|
75
|
+
* @param {Object} score - Risk score
|
|
76
|
+
* @returns {string} Formatted string
|
|
77
|
+
*/
|
|
78
|
+
format(score) {
|
|
79
|
+
return formatRiskScore(score);
|
|
80
|
+
},
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Compare two scores
|
|
84
|
+
* @param {Object} current - Current score
|
|
85
|
+
* @param {Object} previous - Previous score
|
|
86
|
+
* @returns {Object} Comparison
|
|
87
|
+
*/
|
|
88
|
+
compare(current, previous) {
|
|
89
|
+
return compareScores(current, previous);
|
|
90
|
+
},
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Get domain breakdown
|
|
94
|
+
* @param {Object} score - Risk score
|
|
95
|
+
* @returns {Object} Domain breakdown
|
|
96
|
+
*/
|
|
97
|
+
breakdown(score) {
|
|
98
|
+
return getDomainBreakdown(score);
|
|
99
|
+
},
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Load thresholds from policy
|
|
103
|
+
* @param {Object} policy - Policy configuration
|
|
104
|
+
* @returns {Object} Thresholds
|
|
105
|
+
*/
|
|
106
|
+
loadThresholds(policy) {
|
|
107
|
+
return loadThresholds(policy);
|
|
108
|
+
},
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Get decision for score
|
|
112
|
+
* @param {number} score - Risk score
|
|
113
|
+
* @param {Object} thresholds - Thresholds
|
|
114
|
+
* @param {string[]} domains - Affected domains
|
|
115
|
+
* @returns {Object} Decision
|
|
116
|
+
*/
|
|
117
|
+
decide(score, thresholds, domains) {
|
|
118
|
+
return getDecision(score, thresholds, domains);
|
|
119
|
+
},
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Get all available vectors
|
|
123
|
+
* @returns {Object} Vector definitions
|
|
124
|
+
*/
|
|
125
|
+
getVectors() {
|
|
126
|
+
return RISK_VECTORS;
|
|
127
|
+
},
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Get all risk levels
|
|
131
|
+
* @returns {Object} Level definitions
|
|
132
|
+
*/
|
|
133
|
+
getLevels() {
|
|
134
|
+
return RISK_LEVELS;
|
|
135
|
+
},
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Get threshold profiles
|
|
139
|
+
* @returns {Object} Profile definitions
|
|
140
|
+
*/
|
|
141
|
+
getProfiles() {
|
|
142
|
+
return THRESHOLD_PROFILES;
|
|
143
|
+
},
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Get default thresholds
|
|
147
|
+
* @returns {Object} Default thresholds
|
|
148
|
+
*/
|
|
149
|
+
getDefaults() {
|
|
150
|
+
return DEFAULT_THRESHOLDS;
|
|
151
|
+
},
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
module.exports = {
|
|
155
|
+
risk,
|
|
156
|
+
// Direct exports
|
|
157
|
+
calculateRiskScore,
|
|
158
|
+
quickAssess,
|
|
159
|
+
buildContext,
|
|
160
|
+
getDomainBreakdown,
|
|
161
|
+
formatRiskScore,
|
|
162
|
+
compareScores,
|
|
163
|
+
loadThresholds,
|
|
164
|
+
getDecision,
|
|
165
|
+
getRiskLevel,
|
|
166
|
+
getVectorIds,
|
|
167
|
+
getVector,
|
|
168
|
+
// Constants
|
|
169
|
+
RISK_VECTORS,
|
|
170
|
+
RISK_LEVELS,
|
|
171
|
+
DEFAULT_THRESHOLDS,
|
|
172
|
+
THRESHOLD_PROFILES,
|
|
173
|
+
};
|