@way_marks/server 1.0.0 → 2.0.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.
@@ -1,482 +0,0 @@
1
- "use strict";
2
- /**
3
- * Risk Assessment Engine Tests — Phase 4A
4
- *
5
- * Test suite covering:
6
- * - Operation type risk calculation
7
- * - Scale risk calculation
8
- * - Error pattern risk calculation
9
- * - Time risk calculation
10
- * - System state risk calculation
11
- * - Overall risk assessment
12
- * - Risk level determination
13
- * - Recommendation generation
14
- */
15
- Object.defineProperty(exports, "__esModule", { value: true });
16
- const analyzer_1 = require("./analyzer");
17
- describe('Risk Assessment Engine', () => {
18
- // Helper functions to create test data
19
- function createAction(toolName, status = 'success', errorMessage) {
20
- return {
21
- action_id: `action-${Date.now()}`,
22
- session_id: 'sess-test',
23
- tool_name: toolName,
24
- event_type: 'execution',
25
- status,
26
- created_at: new Date().toISOString(),
27
- error_message: errorMessage,
28
- };
29
- }
30
- function createSession(actionCount, minutesOld = 0) {
31
- const now = new Date();
32
- const createdTime = new Date(now.getTime() - minutesOld * 60 * 1000);
33
- return {
34
- session_id: 'sess-test',
35
- created_at: createdTime.toISOString(),
36
- action_count: actionCount,
37
- tool_names: [],
38
- };
39
- }
40
- describe('Operation Type Risk', () => {
41
- it('should return low risk for read-only operations', () => {
42
- const actions = [createAction('read_file'), createAction('grep'), createAction('find_files')];
43
- const risk = (0, analyzer_1.calculateOperationTypeRisk)(actions);
44
- expect(risk.weight).toBeLessThan(0.5);
45
- expect(risk.reason).toContain('read');
46
- });
47
- it('should return medium risk for write operations', () => {
48
- const actions = [createAction('write_file'), createAction('write_file')];
49
- const risk = (0, analyzer_1.calculateOperationTypeRisk)(actions);
50
- expect(risk.weight).toBeGreaterThanOrEqual(1.0);
51
- expect(risk.weight).toBeLessThan(2.0);
52
- });
53
- it('should return high risk for delete operations', () => {
54
- const actions = [createAction('delete_file')];
55
- const risk = (0, analyzer_1.calculateOperationTypeRisk)(actions);
56
- expect(risk.weight).toBeGreaterThanOrEqual(2.0);
57
- expect(risk.reason).toContain('delete');
58
- });
59
- it('should return high risk for bash commands', () => {
60
- const actions = [createAction('bash')];
61
- const risk = (0, analyzer_1.calculateOperationTypeRisk)(actions);
62
- expect(risk.weight).toBeGreaterThanOrEqual(1.5);
63
- });
64
- it('should average risk for mixed operations', () => {
65
- const actions = [
66
- createAction('read_file'),
67
- createAction('write_file'),
68
- createAction('delete_file'),
69
- ];
70
- const risk = (0, analyzer_1.calculateOperationTypeRisk)(actions);
71
- // Average of 0, 2.0, 2.5 = 1.5
72
- expect(risk.weight).toBeGreaterThan(1.0);
73
- expect(risk.weight).toBeLessThan(2.0);
74
- });
75
- it('should handle empty action list', () => {
76
- const risk = (0, analyzer_1.calculateOperationTypeRisk)([]);
77
- expect(risk.weight).toBe(0);
78
- });
79
- });
80
- describe('Scale Risk', () => {
81
- it('should return no risk for single action', () => {
82
- const actions = [createAction('write_file')];
83
- const risk = (0, analyzer_1.calculateScaleRisk)(actions);
84
- expect(risk.weight).toBe(0);
85
- expect(risk.reason).toContain('single operation');
86
- });
87
- it('should return low risk for 2-5 actions', () => {
88
- const actions = [
89
- createAction('write_file'),
90
- createAction('write_file'),
91
- createAction('write_file'),
92
- ];
93
- const risk = (0, analyzer_1.calculateScaleRisk)(actions);
94
- expect(risk.weight).toBe(0.5);
95
- expect(risk.reason).toContain('small batch');
96
- });
97
- it('should return medium risk for 6-20 actions', () => {
98
- const actions = Array(10).fill(null).map(() => createAction('write_file'));
99
- const risk = (0, analyzer_1.calculateScaleRisk)(actions);
100
- expect(risk.weight).toBe(1.5);
101
- expect(risk.reason).toContain('large batch');
102
- });
103
- it('should return high risk for 20+ actions', () => {
104
- const actions = Array(25).fill(null).map(() => createAction('write_file'));
105
- const risk = (0, analyzer_1.calculateScaleRisk)(actions);
106
- expect(risk.weight).toBe(3.0);
107
- expect(risk.reason).toContain('very large batch');
108
- });
109
- });
110
- describe('Error Pattern Risk', () => {
111
- it('should return no risk when no errors', () => {
112
- const actions = [
113
- createAction('write_file', 'success'),
114
- createAction('read_file', 'success'),
115
- ];
116
- const risk = (0, analyzer_1.calculateErrorPatternRisk)(actions);
117
- expect(risk.weight).toBe(0);
118
- expect(risk.reason).toContain('No errors');
119
- });
120
- it('should return low risk for transient errors', () => {
121
- const actions = [
122
- createAction('bash', 'error', 'Connection timeout'),
123
- createAction('bash', 'error', 'Network unreachable'),
124
- ];
125
- const risk = (0, analyzer_1.calculateErrorPatternRisk)(actions);
126
- expect(risk.weight).toBeGreaterThan(0);
127
- expect(risk.weight).toBeLessThan(1.0);
128
- });
129
- it('should return medium risk for permission errors', () => {
130
- const actions = [createAction('write_file', 'error', 'Permission denied')];
131
- const risk = (0, analyzer_1.calculateErrorPatternRisk)(actions);
132
- expect(risk.weight).toBeGreaterThanOrEqual(1.5);
133
- });
134
- it('should return medium-high risk for data validation errors', () => {
135
- const actions = [createAction('write_file', 'error', 'Invalid JSON format')];
136
- const risk = (0, analyzer_1.calculateErrorPatternRisk)(actions);
137
- expect(risk.weight).toBe(2.0);
138
- });
139
- it('should return critical risk for system errors', () => {
140
- const actions = [createAction('bash', 'error', 'Segmentation fault')];
141
- const risk = (0, analyzer_1.calculateErrorPatternRisk)(actions);
142
- expect(risk.weight).toBe(3.0);
143
- expect(risk.reason).toContain('system errors');
144
- });
145
- it('should handle mixed error types', () => {
146
- const actions = [
147
- createAction('bash', 'error', 'Timeout'),
148
- createAction('write_file', 'error', 'Permission denied'),
149
- createAction('bash', 'error', 'Segmentation fault'),
150
- ];
151
- const risk = (0, analyzer_1.calculateErrorPatternRisk)(actions);
152
- // Average of 0.5, 1.5, 3.0 = 1.67
153
- expect(risk.weight).toBeGreaterThan(1.0);
154
- expect(risk.weight).toBeLessThan(2.5);
155
- });
156
- });
157
- describe('Time Risk', () => {
158
- it('should return no risk for very recent actions (<5 minutes)', () => {
159
- const session = createSession(1, 2);
160
- const risk = (0, analyzer_1.calculateTimeRisk)(session);
161
- expect(risk.weight).toBe(0);
162
- expect(risk.reason).toContain('very fresh');
163
- });
164
- it('should return low risk for recent actions (5-60 minutes)', () => {
165
- const session = createSession(1, 30);
166
- const risk = (0, analyzer_1.calculateTimeRisk)(session);
167
- expect(risk.weight).toBe(0.5);
168
- expect(risk.reason).toContain('recent');
169
- });
170
- it('should return medium risk for older actions (1-6 hours)', () => {
171
- const session = createSession(1, 180); // 3 hours
172
- const risk = (0, analyzer_1.calculateTimeRisk)(session);
173
- expect(risk.weight).toBe(1.5);
174
- expect(risk.reason).toContain('older');
175
- });
176
- it('should return high risk for very old actions (6-24 hours)', () => {
177
- const session = createSession(1, 12 * 60); // 12 hours
178
- const risk = (0, analyzer_1.calculateTimeRisk)(session);
179
- expect(risk.weight).toBe(2.0);
180
- expect(risk.reason).toContain('very old');
181
- });
182
- it('should return critical risk for ancient actions (24+ hours)', () => {
183
- const session = createSession(1, 48 * 60); // 48 hours
184
- const risk = (0, analyzer_1.calculateTimeRisk)(session);
185
- expect(risk.weight).toBe(3.0);
186
- expect(risk.reason).toContain('ancient');
187
- });
188
- });
189
- describe('System State Risk', () => {
190
- it('should return no risk for idle system', () => {
191
- const systemState = {
192
- cpu_usage: 10,
193
- memory_usage: 20,
194
- load_average: 0.5,
195
- active_users: 5,
196
- request_rate: 100,
197
- };
198
- const risk = (0, analyzer_1.calculateSystemStateRisk)(systemState);
199
- expect(risk.weight).toBe(0);
200
- expect(risk.reason).toContain('Idle');
201
- });
202
- it('should return medium risk for moderate load', () => {
203
- const systemState = {
204
- cpu_usage: 60,
205
- memory_usage: 55,
206
- load_average: 2.0,
207
- active_users: 20,
208
- request_rate: 500,
209
- };
210
- const risk = (0, analyzer_1.calculateSystemStateRisk)(systemState);
211
- expect(risk.weight).toBe(1.0);
212
- expect(risk.reason).toContain('Moderate');
213
- });
214
- it('should return high risk for high load', () => {
215
- const systemState = {
216
- cpu_usage: 80,
217
- memory_usage: 75,
218
- load_average: 3.0,
219
- active_users: 50,
220
- request_rate: 1500,
221
- };
222
- const risk = (0, analyzer_1.calculateSystemStateRisk)(systemState);
223
- expect(risk.weight).toBeGreaterThanOrEqual(2.0);
224
- expect(risk.reason).toContain('High');
225
- });
226
- it('should return critical risk for critical load', () => {
227
- const systemState = {
228
- cpu_usage: 95,
229
- memory_usage: 92,
230
- load_average: 8.0,
231
- active_users: 200,
232
- request_rate: 5000,
233
- };
234
- const risk = (0, analyzer_1.calculateSystemStateRisk)(systemState);
235
- expect(risk.weight).toBe(3.0);
236
- expect(risk.reason).toContain('Critical');
237
- });
238
- it('should handle missing system state gracefully', () => {
239
- const risk = (0, analyzer_1.calculateSystemStateRisk)(undefined);
240
- expect(risk.weight).toBe(1.0);
241
- expect(risk.reason).toContain('unknown');
242
- });
243
- it('should increase weight for very high request rate', () => {
244
- const systemState = {
245
- cpu_usage: 40,
246
- memory_usage: 40,
247
- load_average: 1.0,
248
- active_users: 10,
249
- request_rate: 2000, // Very high
250
- };
251
- const risk = (0, analyzer_1.calculateSystemStateRisk)(systemState);
252
- expect(risk.weight).toBeGreaterThan(1.0);
253
- });
254
- });
255
- describe('Overall Risk Assessment', () => {
256
- it('should calculate low risk for safe operations', () => {
257
- const actions = [
258
- createAction('read_file'),
259
- createAction('grep'),
260
- ];
261
- const session = createSession(2, 2); // Very recent, 2 actions
262
- const assessment = (0, analyzer_1.assessRisk)(session, actions);
263
- expect(assessment.score).toBeLessThan(2);
264
- expect(assessment.level).toBe('low');
265
- expect(assessment.factors.length).toBe(5);
266
- });
267
- it('should calculate medium risk for moderate operations', () => {
268
- const actions = Array(10).fill(null).map(() => createAction('write_file'));
269
- const session = createSession(10, 60); // 1 hour old
270
- const assessment = (0, analyzer_1.assessRisk)(session, actions);
271
- expect(assessment.score).toBeGreaterThan(2);
272
- expect(assessment.score).toBeLessThan(5);
273
- expect(assessment.level).toBe('medium');
274
- });
275
- it('should calculate high risk for risky operations', () => {
276
- const actions = [
277
- createAction('delete_file'),
278
- createAction('bash'),
279
- createAction('write_file'),
280
- ];
281
- const session = createSession(3, 240); // 4 hours old
282
- const assessment = (0, analyzer_1.assessRisk)(session, actions);
283
- expect(assessment.score).toBeGreaterThan(4);
284
- expect(assessment.score).toBeLessThan(8);
285
- expect(assessment.level).toBe('high');
286
- });
287
- it('should calculate critical risk for very risky operations', () => {
288
- const actions = Array(30).fill(null).map(() => createAction('delete_file'));
289
- const session = createSession(30, 1440); // 1 day old
290
- const systemState = {
291
- cpu_usage: 85,
292
- memory_usage: 80,
293
- load_average: 5.0,
294
- active_users: 100,
295
- request_rate: 2000,
296
- };
297
- const assessment = (0, analyzer_1.assessRisk)(session, actions, systemState);
298
- expect(assessment.score).toBeGreaterThanOrEqual(8);
299
- expect(assessment.level).toBe('critical');
300
- });
301
- it('should include all risk factors', () => {
302
- const actions = [createAction('write_file')];
303
- const session = createSession(1, 30);
304
- const assessment = (0, analyzer_1.assessRisk)(session, actions);
305
- const factorCategories = assessment.factors.map(f => f.category);
306
- expect(factorCategories).toContain('operation_type');
307
- expect(factorCategories).toContain('scale');
308
- expect(factorCategories).toContain('error_pattern');
309
- expect(factorCategories).toContain('time');
310
- expect(factorCategories).toContain('system_state');
311
- });
312
- it('should include timestamp', () => {
313
- const actions = [createAction('read_file')];
314
- const session = createSession(1, 0);
315
- const assessment = (0, analyzer_1.assessRisk)(session, actions);
316
- expect(assessment.timestamp).toBeTruthy();
317
- expect(new Date(assessment.timestamp).getTime()).toBeLessThanOrEqual(Date.now());
318
- });
319
- it('should generate recommendations', () => {
320
- const actions = Array(20).fill(null).map(() => createAction('delete_file'));
321
- const session = createSession(20, 0);
322
- const assessment = (0, analyzer_1.assessRisk)(session, actions);
323
- expect(assessment.recommendations.length).toBeGreaterThan(0);
324
- expect(assessment.recommendations[0]).toBeTruthy();
325
- });
326
- });
327
- describe('Risk Level Determination', () => {
328
- it('should classify 0 as none', () => {
329
- expect((0, analyzer_1.getRiskLevel)(0)).toBe('none');
330
- });
331
- it('should classify 1-2 as low', () => {
332
- expect((0, analyzer_1.getRiskLevel)(1)).toBe('low');
333
- expect((0, analyzer_1.getRiskLevel)(2)).toBe('low');
334
- });
335
- it('should classify 3-4 as medium', () => {
336
- expect((0, analyzer_1.getRiskLevel)(3)).toBe('medium');
337
- expect((0, analyzer_1.getRiskLevel)(4)).toBe('medium');
338
- });
339
- it('should classify 5-7 as high', () => {
340
- expect((0, analyzer_1.getRiskLevel)(5)).toBe('high');
341
- expect((0, analyzer_1.getRiskLevel)(6.5)).toBe('high');
342
- expect((0, analyzer_1.getRiskLevel)(7)).toBe('high');
343
- });
344
- it('should classify 8+ as critical', () => {
345
- expect((0, analyzer_1.getRiskLevel)(8)).toBe('critical');
346
- expect((0, analyzer_1.getRiskLevel)(10)).toBe('critical');
347
- });
348
- });
349
- describe('Recommendation Generation', () => {
350
- it('should recommend safe approval for low risk', () => {
351
- const factors = [
352
- { category: 'operation_type', weight: 0, reason: 'read-only' },
353
- ];
354
- const recommendations = (0, analyzer_1.generateRecommendations)(1.0, 'low', factors, []);
355
- expect(recommendations.some(r => r.includes('Safe to proceed'))).toBe(true);
356
- });
357
- it('should recommend escalation for high risk', () => {
358
- const factors = [
359
- { category: 'operation_type', weight: 2.5, reason: 'delete operations' },
360
- ];
361
- const recommendations = (0, analyzer_1.generateRecommendations)(6.0, 'high', factors, []);
362
- expect(recommendations.some(r => r.includes('escalation') || r.includes('manager'))).toBe(true);
363
- });
364
- it('should recommend partial rollback for large scale', () => {
365
- const actions = Array(25).fill(null).map(() => createAction('write_file'));
366
- const factors = [
367
- { category: 'scale', weight: 3, reason: '25 actions' },
368
- ];
369
- const recommendations = (0, analyzer_1.generateRecommendations)(5.0, 'high', factors, actions);
370
- expect(recommendations.some(r => r.includes('partial') || r.includes('selective'))).toBe(true);
371
- });
372
- it('should recommend review for multiple errors', () => {
373
- const actions = [
374
- createAction('bash', 'error', 'Error 1'),
375
- createAction('bash', 'error', 'Error 2'),
376
- ];
377
- const factors = [
378
- { category: 'error_pattern', weight: 1.5, reason: 'multiple errors' },
379
- ];
380
- const recommendations = (0, analyzer_1.generateRecommendations)(4.0, 'medium', factors, actions);
381
- expect(recommendations.some(r => r.includes('review'))).toBe(true);
382
- });
383
- it('should warn about old operations', () => {
384
- const factors = [
385
- { category: 'time', weight: 3, reason: '48 hours old' },
386
- ];
387
- const recommendations = (0, analyzer_1.generateRecommendations)(5.0, 'high', factors, []);
388
- expect(recommendations.some(r => r.includes('old') || r.includes('dependencies'))).toBe(true);
389
- });
390
- it('should warn about system load', () => {
391
- const factors = [
392
- { category: 'system_state', weight: 3, reason: 'critical load' },
393
- ];
394
- const recommendations = (0, analyzer_1.generateRecommendations)(5.0, 'high', factors, []);
395
- expect(recommendations.some(r => r.includes('load') || r.includes('off-peak'))).toBe(true);
396
- });
397
- });
398
- describe('Auto-Block Logic', () => {
399
- it('should not block below threshold', () => {
400
- expect((0, analyzer_1.shouldAutoBlock)(5.0, 7.0)).toBe(false);
401
- expect((0, analyzer_1.shouldAutoBlock)(6.9, 7.0)).toBe(false);
402
- });
403
- it('should block at threshold', () => {
404
- expect((0, analyzer_1.shouldAutoBlock)(7.0, 7.0)).toBe(true);
405
- expect((0, analyzer_1.shouldAutoBlock)(8.0, 7.0)).toBe(true);
406
- });
407
- it('should use custom threshold', () => {
408
- expect((0, analyzer_1.shouldAutoBlock)(6.0, 6.0)).toBe(true);
409
- expect((0, analyzer_1.shouldAutoBlock)(5.9, 6.0)).toBe(false);
410
- });
411
- it('should use default threshold of 7.0', () => {
412
- expect((0, analyzer_1.shouldAutoBlock)(7.0)).toBe(true);
413
- expect((0, analyzer_1.shouldAutoBlock)(6.9)).toBe(false);
414
- });
415
- });
416
- describe('Risk Summary', () => {
417
- it('should include score and level', () => {
418
- const actions = [createAction('write_file')];
419
- const session = createSession(1, 30);
420
- const assessment = (0, analyzer_1.assessRisk)(session, actions);
421
- const summary = (0, analyzer_1.getRiskSummary)(assessment);
422
- expect(summary).toContain('Risk Level');
423
- expect(summary).toContain('/10');
424
- });
425
- it('should include all factors', () => {
426
- const actions = [createAction('delete_file')];
427
- const session = createSession(1, 60);
428
- const assessment = (0, analyzer_1.assessRisk)(session, actions);
429
- const summary = (0, analyzer_1.getRiskSummary)(assessment);
430
- expect(summary).toContain('operation_type');
431
- expect(summary).toContain('scale');
432
- expect(summary).toContain('error_pattern');
433
- expect(summary).toContain('time');
434
- expect(summary).toContain('system_state');
435
- });
436
- it('should include recommendations', () => {
437
- const actions = Array(25).fill(null).map(() => createAction('delete_file'));
438
- const session = createSession(25, 0);
439
- const assessment = (0, analyzer_1.assessRisk)(session, actions);
440
- const summary = (0, analyzer_1.getRiskSummary)(assessment);
441
- expect(summary).toContain('Recommendations');
442
- expect(summary).toContain('→');
443
- });
444
- });
445
- describe('Integration Scenarios', () => {
446
- it('should assess safe database read script as low risk', () => {
447
- const actions = [
448
- createAction('read_file', 'success'), // Open script
449
- createAction('bash', 'success'), // Run script
450
- ];
451
- const session = createSession(2, 5);
452
- const assessment = (0, analyzer_1.assessRisk)(session, actions);
453
- expect(assessment.score).toBeLessThan(3);
454
- expect(assessment.level).toBe('low');
455
- });
456
- it('should assess production data deletion as critical risk', () => {
457
- const actions = Array(15).fill(null).map(() => createAction('delete_file', 'success'));
458
- const session = createSession(15, 1440); // 1 day old
459
- const systemState = {
460
- cpu_usage: 75,
461
- memory_usage: 70,
462
- load_average: 3.0,
463
- active_users: 150,
464
- request_rate: 1500,
465
- };
466
- const assessment = (0, analyzer_1.assessRisk)(session, actions, systemState);
467
- expect(assessment.score).toBeGreaterThan(7);
468
- expect(assessment.level).toBe('critical');
469
- });
470
- it('should assess failed migration with errors as high risk', () => {
471
- const actions = [
472
- createAction('bash', 'success'), // Setup
473
- createAction('bash', 'error', 'Database validation error'),
474
- createAction('write_file', 'error', 'Schema migration failed'),
475
- ];
476
- const session = createSession(3, 60);
477
- const assessment = (0, analyzer_1.assessRisk)(session, actions);
478
- expect(assessment.score).toBeGreaterThan(4);
479
- expect(assessment.level).toBe('high');
480
- });
481
- });
482
- });