tryassay 0.33.1 → 0.34.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +20 -0
- package/dist/cli.js.map +1 -1
- package/dist/commands/hunt.d.ts +2 -0
- package/dist/commands/hunt.js +58 -7
- package/dist/commands/hunt.js.map +1 -1
- package/dist/commands/mcp.d.ts +14 -0
- package/dist/commands/mcp.js +18 -0
- package/dist/commands/mcp.js.map +1 -0
- package/dist/commands/watch.d.ts +19 -0
- package/dist/commands/watch.js +158 -0
- package/dist/commands/watch.js.map +1 -0
- package/dist/hunt/__tests__/finding-to-template.test.d.ts +1 -0
- package/dist/hunt/__tests__/finding-to-template.test.js +213 -0
- package/dist/hunt/__tests__/finding-to-template.test.js.map +1 -0
- package/dist/hunt/__tests__/parse-utils.test.js +28 -1
- package/dist/hunt/__tests__/parse-utils.test.js.map +1 -1
- package/dist/hunt/__tests__/taint-analysis.test.d.ts +1 -0
- package/dist/hunt/__tests__/taint-analysis.test.js +556 -0
- package/dist/hunt/__tests__/taint-analysis.test.js.map +1 -0
- package/dist/hunt/__tests__/templates.test.js +2 -2
- package/dist/hunt/__tests__/templates.test.js.map +1 -1
- package/dist/hunt/deep-dive.d.ts +2 -2
- package/dist/hunt/deep-dive.js +4 -4
- package/dist/hunt/deep-dive.js.map +1 -1
- package/dist/hunt/discovery.js +2 -2
- package/dist/hunt/discovery.js.map +1 -1
- package/dist/hunt/finding-to-template.d.ts +47 -0
- package/dist/hunt/finding-to-template.js +288 -0
- package/dist/hunt/finding-to-template.js.map +1 -0
- package/dist/hunt/orchestrator.d.ts +3 -0
- package/dist/hunt/orchestrator.js +20 -5
- package/dist/hunt/orchestrator.js.map +1 -1
- package/dist/hunt/taint-analysis.d.ts +49 -0
- package/dist/hunt/taint-analysis.js +429 -0
- package/dist/hunt/taint-analysis.js.map +1 -0
- package/dist/hunt/templates/csv-injection.d.ts +2 -0
- package/dist/hunt/templates/csv-injection.js +148 -0
- package/dist/hunt/templates/csv-injection.js.map +1 -0
- package/dist/hunt/templates/django-misconfig.d.ts +2 -0
- package/dist/hunt/templates/django-misconfig.js +172 -0
- package/dist/hunt/templates/django-misconfig.js.map +1 -0
- package/dist/hunt/templates/express-misconfig.d.ts +2 -0
- package/dist/hunt/templates/express-misconfig.js +156 -0
- package/dist/hunt/templates/express-misconfig.js.map +1 -0
- package/dist/hunt/templates/file-upload.d.ts +2 -0
- package/dist/hunt/templates/file-upload.js +131 -0
- package/dist/hunt/templates/file-upload.js.map +1 -0
- package/dist/hunt/templates/graphql-abuse.d.ts +2 -0
- package/dist/hunt/templates/graphql-abuse.js +161 -0
- package/dist/hunt/templates/graphql-abuse.js.map +1 -0
- package/dist/hunt/templates/hardcoded-credentials.d.ts +2 -0
- package/dist/hunt/templates/hardcoded-credentials.js +109 -0
- package/dist/hunt/templates/hardcoded-credentials.js.map +1 -0
- package/dist/hunt/templates/idor.d.ts +2 -0
- package/dist/hunt/templates/idor.js +102 -0
- package/dist/hunt/templates/idor.js.map +1 -0
- package/dist/hunt/templates/index.d.ts +2 -2
- package/dist/hunt/templates/index.js +38 -5
- package/dist/hunt/templates/index.js.map +1 -1
- package/dist/hunt/templates/insecure-deserialization.d.ts +2 -0
- package/dist/hunt/templates/insecure-deserialization.js +131 -0
- package/dist/hunt/templates/insecure-deserialization.js.map +1 -0
- package/dist/hunt/templates/mass-assignment.d.ts +2 -0
- package/dist/hunt/templates/mass-assignment.js +101 -0
- package/dist/hunt/templates/mass-assignment.js.map +1 -0
- package/dist/hunt/templates/nextjs-misconfig.d.ts +2 -0
- package/dist/hunt/templates/nextjs-misconfig.js +127 -0
- package/dist/hunt/templates/nextjs-misconfig.js.map +1 -0
- package/dist/hunt/templates/postmessage.d.ts +2 -0
- package/dist/hunt/templates/postmessage.js +180 -0
- package/dist/hunt/templates/postmessage.js.map +1 -0
- package/dist/hunt/templates/race-condition.d.ts +2 -0
- package/dist/hunt/templates/race-condition.js +138 -0
- package/dist/hunt/templates/race-condition.js.map +1 -0
- package/dist/hunt/templates/spring-misconfig.d.ts +2 -0
- package/dist/hunt/templates/spring-misconfig.js +177 -0
- package/dist/hunt/templates/spring-misconfig.js.map +1 -0
- package/dist/hunt/templates/xxe.d.ts +2 -0
- package/dist/hunt/templates/xxe.js +187 -0
- package/dist/hunt/templates/xxe.js.map +1 -0
- package/dist/hunt/triage.d.ts +2 -2
- package/dist/hunt/triage.js +4 -4
- package/dist/hunt/triage.js.map +1 -1
- package/dist/realtime/__tests__/catch-real-bugs.test.d.ts +9 -0
- package/dist/realtime/__tests__/catch-real-bugs.test.js +205 -0
- package/dist/realtime/__tests__/catch-real-bugs.test.js.map +1 -0
- package/dist/realtime/__tests__/code-buffer.test.d.ts +1 -0
- package/dist/realtime/__tests__/code-buffer.test.js +202 -0
- package/dist/realtime/__tests__/code-buffer.test.js.map +1 -0
- package/dist/realtime/__tests__/correction-injector.test.d.ts +1 -0
- package/dist/realtime/__tests__/correction-injector.test.js +168 -0
- package/dist/realtime/__tests__/correction-injector.test.js.map +1 -0
- package/dist/realtime/__tests__/stream-interceptor.test.d.ts +1 -0
- package/dist/realtime/__tests__/stream-interceptor.test.js +193 -0
- package/dist/realtime/__tests__/stream-interceptor.test.js.map +1 -0
- package/dist/realtime/__tests__/streaming-checks.test.d.ts +1 -0
- package/dist/realtime/__tests__/streaming-checks.test.js +479 -0
- package/dist/realtime/__tests__/streaming-checks.test.js.map +1 -0
- package/dist/realtime/__tests__/streaming-verifier.test.d.ts +1 -0
- package/dist/realtime/__tests__/streaming-verifier.test.js +157 -0
- package/dist/realtime/__tests__/streaming-verifier.test.js.map +1 -0
- package/dist/realtime/code-buffer.d.ts +52 -0
- package/dist/realtime/code-buffer.js +276 -0
- package/dist/realtime/code-buffer.js.map +1 -0
- package/dist/realtime/correction-injector.d.ts +56 -0
- package/dist/realtime/correction-injector.js +96 -0
- package/dist/realtime/correction-injector.js.map +1 -0
- package/dist/realtime/index.d.ts +14 -0
- package/dist/realtime/index.js +11 -0
- package/dist/realtime/index.js.map +1 -0
- package/dist/realtime/mcp-server.d.ts +14 -0
- package/dist/realtime/mcp-server.js +200 -0
- package/dist/realtime/mcp-server.js.map +1 -0
- package/dist/realtime/stream-interceptor.d.ts +65 -0
- package/dist/realtime/stream-interceptor.js +174 -0
- package/dist/realtime/stream-interceptor.js.map +1 -0
- package/dist/realtime/streaming-checks.d.ts +55 -0
- package/dist/realtime/streaming-checks.js +452 -0
- package/dist/realtime/streaming-checks.js.map +1 -0
- package/dist/realtime/streaming-verifier.d.ts +57 -0
- package/dist/realtime/streaming-verifier.js +134 -0
- package/dist/realtime/streaming-verifier.js.map +1 -0
- package/dist/realtime/types.d.ts +99 -0
- package/dist/realtime/types.js +8 -0
- package/dist/realtime/types.js.map +1 -0
- package/package.json +2 -1
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { CodeBuffer } from '../code-buffer.js';
|
|
3
|
+
describe('CodeBuffer', () => {
|
|
4
|
+
// -----------------------------------------------------------------------
|
|
5
|
+
// 1. Simple statement
|
|
6
|
+
// -----------------------------------------------------------------------
|
|
7
|
+
it('emits a statement unit for a simple const with semicolon', () => {
|
|
8
|
+
const buf = new CodeBuffer('typescript');
|
|
9
|
+
const units = buf.push('const x = 1;');
|
|
10
|
+
expect(units).toHaveLength(1);
|
|
11
|
+
expect(units[0].kind).toBe('statement');
|
|
12
|
+
expect(units[0].text).toBe('const x = 1;');
|
|
13
|
+
expect(units[0].language).toBe('typescript');
|
|
14
|
+
});
|
|
15
|
+
// -----------------------------------------------------------------------
|
|
16
|
+
// 2. Function block
|
|
17
|
+
// -----------------------------------------------------------------------
|
|
18
|
+
it('emits a function unit for a named function declaration', () => {
|
|
19
|
+
const buf = new CodeBuffer('typescript');
|
|
20
|
+
const units = buf.push('function foo() { return 1; }');
|
|
21
|
+
expect(units).toHaveLength(1);
|
|
22
|
+
expect(units[0].kind).toBe('function');
|
|
23
|
+
expect(units[0].text).toBe('function foo() { return 1; }');
|
|
24
|
+
});
|
|
25
|
+
// -----------------------------------------------------------------------
|
|
26
|
+
// 3. Nested blocks — outermost only
|
|
27
|
+
// -----------------------------------------------------------------------
|
|
28
|
+
it('emits one block unit for nested braces', () => {
|
|
29
|
+
const buf = new CodeBuffer('typescript');
|
|
30
|
+
const units = buf.push('if (x) { if (y) { z(); } }');
|
|
31
|
+
expect(units).toHaveLength(1);
|
|
32
|
+
expect(units[0].kind).toBe('block');
|
|
33
|
+
expect(units[0].text).toBe('if (x) { if (y) { z(); } }');
|
|
34
|
+
});
|
|
35
|
+
// -----------------------------------------------------------------------
|
|
36
|
+
// 4. String with braces — braces inside strings don't count
|
|
37
|
+
// -----------------------------------------------------------------------
|
|
38
|
+
it('ignores braces inside double-quoted strings', () => {
|
|
39
|
+
const buf = new CodeBuffer('typescript');
|
|
40
|
+
const units = buf.push('const s = "hello { world }";');
|
|
41
|
+
expect(units).toHaveLength(1);
|
|
42
|
+
expect(units[0].kind).toBe('statement');
|
|
43
|
+
expect(units[0].text).toBe('const s = "hello { world }";');
|
|
44
|
+
});
|
|
45
|
+
it('ignores braces inside single-quoted strings', () => {
|
|
46
|
+
const buf = new CodeBuffer('typescript');
|
|
47
|
+
const units = buf.push("const s = 'hello { world }';");
|
|
48
|
+
expect(units).toHaveLength(1);
|
|
49
|
+
expect(units[0].kind).toBe('statement');
|
|
50
|
+
});
|
|
51
|
+
// -----------------------------------------------------------------------
|
|
52
|
+
// 5. Template literal with expression
|
|
53
|
+
// -----------------------------------------------------------------------
|
|
54
|
+
it('handles template literals with ${} expressions', () => {
|
|
55
|
+
const buf = new CodeBuffer('typescript');
|
|
56
|
+
const units = buf.push('const s = `${a + b}`;');
|
|
57
|
+
expect(units).toHaveLength(1);
|
|
58
|
+
expect(units[0].kind).toBe('statement');
|
|
59
|
+
expect(units[0].text).toBe('const s = `${a + b}`;');
|
|
60
|
+
});
|
|
61
|
+
it('handles template literals with nested braces in expressions', () => {
|
|
62
|
+
const buf = new CodeBuffer('typescript');
|
|
63
|
+
const units = buf.push('const s = `${fn({a: 1})}`;');
|
|
64
|
+
expect(units).toHaveLength(1);
|
|
65
|
+
expect(units[0].kind).toBe('statement');
|
|
66
|
+
});
|
|
67
|
+
// -----------------------------------------------------------------------
|
|
68
|
+
// 6. Multi-push assembly — same result as single push
|
|
69
|
+
// -----------------------------------------------------------------------
|
|
70
|
+
it('assembles the same unit across multiple pushes', () => {
|
|
71
|
+
const buf = new CodeBuffer('typescript');
|
|
72
|
+
const allUnits = [];
|
|
73
|
+
for (const token of ['const ', 'x ', '= ', '1', ';']) {
|
|
74
|
+
allUnits.push(...buf.push(token));
|
|
75
|
+
}
|
|
76
|
+
expect(allUnits).toHaveLength(1);
|
|
77
|
+
expect(allUnits[0].kind).toBe('statement');
|
|
78
|
+
expect(allUnits[0].text).toBe('const x = 1;');
|
|
79
|
+
});
|
|
80
|
+
it('assembles a function across many small pushes', () => {
|
|
81
|
+
const buf = new CodeBuffer('typescript');
|
|
82
|
+
const code = 'function foo() { return 1; }';
|
|
83
|
+
const allUnits = [];
|
|
84
|
+
for (const ch of code) {
|
|
85
|
+
allUnits.push(...buf.push(ch));
|
|
86
|
+
}
|
|
87
|
+
expect(allUnits).toHaveLength(1);
|
|
88
|
+
expect(allUnits[0].kind).toBe('function');
|
|
89
|
+
expect(allUnits[0].text).toBe(code);
|
|
90
|
+
});
|
|
91
|
+
// -----------------------------------------------------------------------
|
|
92
|
+
// 7. Line comment handling
|
|
93
|
+
// -----------------------------------------------------------------------
|
|
94
|
+
it('ignores braces inside line comments', () => {
|
|
95
|
+
const buf = new CodeBuffer('typescript');
|
|
96
|
+
const units = buf.push('// const x = {\nconst y = 1;');
|
|
97
|
+
// The line comment should be emitted as a line (or skipped),
|
|
98
|
+
// and the real statement comes after
|
|
99
|
+
const statements = units.filter((u) => u.kind === 'statement');
|
|
100
|
+
expect(statements).toHaveLength(1);
|
|
101
|
+
expect(statements[0].text).toBe('const y = 1;');
|
|
102
|
+
});
|
|
103
|
+
it('does not open a brace from a line comment', () => {
|
|
104
|
+
const buf = new CodeBuffer('typescript');
|
|
105
|
+
buf.push('// {\n');
|
|
106
|
+
// Brace depth should still be 0 — push a normal statement
|
|
107
|
+
const units = buf.push('const a = 2;');
|
|
108
|
+
expect(units).toHaveLength(1);
|
|
109
|
+
expect(units[0].kind).toBe('statement');
|
|
110
|
+
});
|
|
111
|
+
// -----------------------------------------------------------------------
|
|
112
|
+
// 8. Block comment handling
|
|
113
|
+
// -----------------------------------------------------------------------
|
|
114
|
+
it('ignores braces inside block comments', () => {
|
|
115
|
+
const buf = new CodeBuffer('typescript');
|
|
116
|
+
const units = buf.push('/* { */ const y = 1;');
|
|
117
|
+
expect(units).toHaveLength(1);
|
|
118
|
+
expect(units[0].kind).toBe('statement');
|
|
119
|
+
expect(units[0].text).toBe('/* { */ const y = 1;');
|
|
120
|
+
});
|
|
121
|
+
it('handles multi-line block comments', () => {
|
|
122
|
+
const buf = new CodeBuffer('typescript');
|
|
123
|
+
buf.push('/* start\n');
|
|
124
|
+
buf.push('{ not a brace\n');
|
|
125
|
+
const units = buf.push('*/ const z = 3;');
|
|
126
|
+
expect(units).toHaveLength(1);
|
|
127
|
+
expect(units[0].kind).toBe('statement');
|
|
128
|
+
});
|
|
129
|
+
// -----------------------------------------------------------------------
|
|
130
|
+
// 9. Arrow function with trailing semicolon
|
|
131
|
+
// -----------------------------------------------------------------------
|
|
132
|
+
it('emits arrow function as a statement (const assignment)', () => {
|
|
133
|
+
const buf = new CodeBuffer('typescript');
|
|
134
|
+
const units = buf.push('const fn = () => { return 1; };');
|
|
135
|
+
expect(units).toHaveLength(1);
|
|
136
|
+
expect(units[0].kind).toBe('statement');
|
|
137
|
+
expect(units[0].text).toBe('const fn = () => { return 1; };');
|
|
138
|
+
});
|
|
139
|
+
// -----------------------------------------------------------------------
|
|
140
|
+
// 10. Class with methods
|
|
141
|
+
// -----------------------------------------------------------------------
|
|
142
|
+
it('emits a whole class as one function unit', () => {
|
|
143
|
+
const buf = new CodeBuffer('typescript');
|
|
144
|
+
const code = 'class Foo { bar() { return 1; } baz() { return 2; } }';
|
|
145
|
+
const units = buf.push(code);
|
|
146
|
+
expect(units).toHaveLength(1);
|
|
147
|
+
expect(units[0].kind).toBe('function');
|
|
148
|
+
expect(units[0].text).toBe(code);
|
|
149
|
+
});
|
|
150
|
+
// -----------------------------------------------------------------------
|
|
151
|
+
// Additional edge cases
|
|
152
|
+
// -----------------------------------------------------------------------
|
|
153
|
+
it('returns empty array for empty push', () => {
|
|
154
|
+
const buf = new CodeBuffer('typescript');
|
|
155
|
+
expect(buf.push('')).toHaveLength(0);
|
|
156
|
+
});
|
|
157
|
+
it('tracks offsets correctly across multiple units', () => {
|
|
158
|
+
const buf = new CodeBuffer('typescript');
|
|
159
|
+
const units = buf.push('const a = 1; const b = 2;');
|
|
160
|
+
expect(units).toHaveLength(2);
|
|
161
|
+
expect(units[0].startOffset).toBe(0);
|
|
162
|
+
expect(units[1].text).toBe('const b = 2;');
|
|
163
|
+
});
|
|
164
|
+
it('getFullBuffer returns all accumulated text', () => {
|
|
165
|
+
const buf = new CodeBuffer('typescript');
|
|
166
|
+
buf.push('hello ');
|
|
167
|
+
buf.push('world');
|
|
168
|
+
expect(buf.getFullBuffer()).toBe('hello world');
|
|
169
|
+
});
|
|
170
|
+
it('getLanguage returns configured language', () => {
|
|
171
|
+
const buf = new CodeBuffer('python');
|
|
172
|
+
expect(buf.getLanguage()).toBe('python');
|
|
173
|
+
});
|
|
174
|
+
it('reset clears all state', () => {
|
|
175
|
+
const buf = new CodeBuffer('typescript');
|
|
176
|
+
buf.push('const x = 1;');
|
|
177
|
+
buf.reset();
|
|
178
|
+
expect(buf.getFullBuffer()).toBe('');
|
|
179
|
+
const units = buf.push('const y = 2;');
|
|
180
|
+
expect(units).toHaveLength(1);
|
|
181
|
+
expect(units[0].startOffset).toBe(0);
|
|
182
|
+
});
|
|
183
|
+
it('handles escaped quotes inside strings', () => {
|
|
184
|
+
const buf = new CodeBuffer('typescript');
|
|
185
|
+
const units = buf.push('const s = "hello \\" world { }";');
|
|
186
|
+
expect(units).toHaveLength(1);
|
|
187
|
+
expect(units[0].kind).toBe('statement');
|
|
188
|
+
});
|
|
189
|
+
it('handles export async function', () => {
|
|
190
|
+
const buf = new CodeBuffer('typescript');
|
|
191
|
+
const units = buf.push('export async function handler() { await db.query(); }');
|
|
192
|
+
expect(units).toHaveLength(1);
|
|
193
|
+
expect(units[0].kind).toBe('function');
|
|
194
|
+
});
|
|
195
|
+
it('handles export default class', () => {
|
|
196
|
+
const buf = new CodeBuffer('typescript');
|
|
197
|
+
const units = buf.push('export default class App { render() { return null; } }');
|
|
198
|
+
expect(units).toHaveLength(1);
|
|
199
|
+
expect(units[0].kind).toBe('function');
|
|
200
|
+
});
|
|
201
|
+
});
|
|
202
|
+
//# sourceMappingURL=code-buffer.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"code-buffer.test.js","sourceRoot":"","sources":["../../../src/realtime/__tests__/code-buffer.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach } from 'vitest';
|
|
2
|
+
import { CorrectionInjector, SEVERITY_RANK } from '../correction-injector.js';
|
|
3
|
+
// ── Helpers ─────────────────────────────────────────────────────
|
|
4
|
+
function makeCodeUnit(text = 'db.query(sql)') {
|
|
5
|
+
return {
|
|
6
|
+
text,
|
|
7
|
+
kind: 'statement',
|
|
8
|
+
startOffset: 0,
|
|
9
|
+
endOffset: text.length,
|
|
10
|
+
language: 'typescript',
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
function makeEvent(overrides = {}) {
|
|
14
|
+
return {
|
|
15
|
+
type: 'finding',
|
|
16
|
+
codeUnit: makeCodeUnit(),
|
|
17
|
+
checkId: 'sql_parameterized',
|
|
18
|
+
checkName: 'SQL Parameterization',
|
|
19
|
+
verdict: 'FAIL',
|
|
20
|
+
severity: 'critical',
|
|
21
|
+
evidence: 'Raw SQL string concatenation detected',
|
|
22
|
+
suggestion: 'Use parameterized queries instead',
|
|
23
|
+
latencyMs: 2,
|
|
24
|
+
...overrides,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
// ── shouldCorrect ───────────────────────────────────────────────
|
|
28
|
+
describe('CorrectionInjector', () => {
|
|
29
|
+
let injector;
|
|
30
|
+
beforeEach(() => {
|
|
31
|
+
injector = new CorrectionInjector();
|
|
32
|
+
});
|
|
33
|
+
describe('shouldCorrect', () => {
|
|
34
|
+
it('returns true for critical finding when minSeverity is high (default)', () => {
|
|
35
|
+
const event = makeEvent({ severity: 'critical' });
|
|
36
|
+
expect(injector.shouldCorrect(event)).toBe(true);
|
|
37
|
+
});
|
|
38
|
+
it('returns true for high finding when minSeverity is high', () => {
|
|
39
|
+
const event = makeEvent({ severity: 'high' });
|
|
40
|
+
expect(injector.shouldCorrect(event)).toBe(true);
|
|
41
|
+
});
|
|
42
|
+
it('returns false for medium finding when minSeverity is high', () => {
|
|
43
|
+
const event = makeEvent({ severity: 'medium' });
|
|
44
|
+
expect(injector.shouldCorrect(event)).toBe(false);
|
|
45
|
+
});
|
|
46
|
+
it('returns false for low finding when minSeverity is high', () => {
|
|
47
|
+
const event = makeEvent({ severity: 'low' });
|
|
48
|
+
expect(injector.shouldCorrect(event)).toBe(false);
|
|
49
|
+
});
|
|
50
|
+
it('returns false for PASS events', () => {
|
|
51
|
+
const event = makeEvent({ verdict: 'PASS', type: 'pass' });
|
|
52
|
+
expect(injector.shouldCorrect(event)).toBe(false);
|
|
53
|
+
});
|
|
54
|
+
it('returns false after maxCorrections reached', () => {
|
|
55
|
+
const limited = new CorrectionInjector({ maxCorrections: 2 });
|
|
56
|
+
const event = makeEvent();
|
|
57
|
+
expect(limited.shouldCorrect(event)).toBe(true);
|
|
58
|
+
limited.recordCorrection(event);
|
|
59
|
+
expect(limited.shouldCorrect(event)).toBe(true);
|
|
60
|
+
limited.recordCorrection(event);
|
|
61
|
+
// Now at 2/2 — should reject
|
|
62
|
+
expect(limited.shouldCorrect(event)).toBe(false);
|
|
63
|
+
});
|
|
64
|
+
it('respects custom minSeverity of medium', () => {
|
|
65
|
+
const relaxed = new CorrectionInjector({ minSeverity: 'medium' });
|
|
66
|
+
expect(relaxed.shouldCorrect(makeEvent({ severity: 'medium' }))).toBe(true);
|
|
67
|
+
expect(relaxed.shouldCorrect(makeEvent({ severity: 'low' }))).toBe(false);
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
// ── buildCorrectionMessages ─────────────────────────────────────
|
|
71
|
+
describe('buildCorrectionMessages', () => {
|
|
72
|
+
it('includes the generated-so-far as assistant prefill', () => {
|
|
73
|
+
const generatedSoFar = 'function getData() {\n const sql = "SELECT * FROM users WHERE id=" + id;';
|
|
74
|
+
const msgs = injector.buildCorrectionMessages(generatedSoFar, makeEvent(), 'You are a code generator.', 'Write a function to get user data.');
|
|
75
|
+
// Second message should be assistant prefill
|
|
76
|
+
expect(msgs[1].role).toBe('assistant');
|
|
77
|
+
expect(msgs[1].content).toBe(generatedSoFar);
|
|
78
|
+
});
|
|
79
|
+
it('includes evidence and suggestion from the finding', () => {
|
|
80
|
+
const event = makeEvent({
|
|
81
|
+
checkName: 'SQL Parameterization',
|
|
82
|
+
evidence: 'Raw SQL string concatenation detected',
|
|
83
|
+
suggestion: 'Use parameterized queries instead',
|
|
84
|
+
});
|
|
85
|
+
const msgs = injector.buildCorrectionMessages('some code', event, 'system prompt', 'user prompt');
|
|
86
|
+
const correctionMsg = msgs[2].content;
|
|
87
|
+
expect(correctionMsg).toContain('SQL Parameterization');
|
|
88
|
+
expect(correctionMsg).toContain('Raw SQL string concatenation detected');
|
|
89
|
+
expect(correctionMsg).toContain('Use parameterized queries instead');
|
|
90
|
+
});
|
|
91
|
+
it('builds correction message without suggestion when none provided', () => {
|
|
92
|
+
const event = makeEvent({ suggestion: undefined });
|
|
93
|
+
const msgs = injector.buildCorrectionMessages('some code', event, 'system prompt', 'user prompt');
|
|
94
|
+
const correctionMsg = msgs[2].content;
|
|
95
|
+
expect(correctionMsg).toContain(event.checkName);
|
|
96
|
+
expect(correctionMsg).toContain(event.evidence);
|
|
97
|
+
expect(correctionMsg).toContain('continue generating code');
|
|
98
|
+
});
|
|
99
|
+
it('returns exactly 3 messages in user/assistant/user order', () => {
|
|
100
|
+
const msgs = injector.buildCorrectionMessages('code so far', makeEvent(), 'system', 'user request');
|
|
101
|
+
expect(msgs).toHaveLength(3);
|
|
102
|
+
expect(msgs[0].role).toBe('user');
|
|
103
|
+
expect(msgs[1].role).toBe('assistant');
|
|
104
|
+
expect(msgs[2].role).toBe('user');
|
|
105
|
+
});
|
|
106
|
+
it('uses the original user prompt as the first message', () => {
|
|
107
|
+
const userPrompt = 'Write a secure authentication handler.';
|
|
108
|
+
const msgs = injector.buildCorrectionMessages('code', makeEvent(), 'system', userPrompt);
|
|
109
|
+
expect(msgs[0].content).toBe(userPrompt);
|
|
110
|
+
});
|
|
111
|
+
});
|
|
112
|
+
// ── recordCorrection / getCorrectionCount / reset ───────────────
|
|
113
|
+
describe('recordCorrection', () => {
|
|
114
|
+
it('increments the counter', () => {
|
|
115
|
+
expect(injector.getCorrectionCount()).toBe(0);
|
|
116
|
+
injector.recordCorrection(makeEvent());
|
|
117
|
+
expect(injector.getCorrectionCount()).toBe(1);
|
|
118
|
+
injector.recordCorrection(makeEvent());
|
|
119
|
+
expect(injector.getCorrectionCount()).toBe(2);
|
|
120
|
+
});
|
|
121
|
+
});
|
|
122
|
+
describe('reset', () => {
|
|
123
|
+
it('clears the counter', () => {
|
|
124
|
+
injector.recordCorrection(makeEvent());
|
|
125
|
+
injector.recordCorrection(makeEvent());
|
|
126
|
+
expect(injector.getCorrectionCount()).toBe(2);
|
|
127
|
+
injector.reset();
|
|
128
|
+
expect(injector.getCorrectionCount()).toBe(0);
|
|
129
|
+
});
|
|
130
|
+
it('allows corrections again after reset', () => {
|
|
131
|
+
const limited = new CorrectionInjector({ maxCorrections: 1 });
|
|
132
|
+
const event = makeEvent();
|
|
133
|
+
limited.recordCorrection(event);
|
|
134
|
+
expect(limited.shouldCorrect(event)).toBe(false);
|
|
135
|
+
limited.reset();
|
|
136
|
+
expect(limited.shouldCorrect(event)).toBe(true);
|
|
137
|
+
});
|
|
138
|
+
});
|
|
139
|
+
// ── Severity ordering ──────────────────────────────────────────
|
|
140
|
+
describe('severity ordering', () => {
|
|
141
|
+
it('ranks critical > high > medium > low', () => {
|
|
142
|
+
expect(SEVERITY_RANK['critical']).toBeGreaterThan(SEVERITY_RANK['high']);
|
|
143
|
+
expect(SEVERITY_RANK['high']).toBeGreaterThan(SEVERITY_RANK['medium']);
|
|
144
|
+
expect(SEVERITY_RANK['medium']).toBeGreaterThan(SEVERITY_RANK['low']);
|
|
145
|
+
});
|
|
146
|
+
});
|
|
147
|
+
// ── Default options ────────────────────────────────────────────
|
|
148
|
+
describe('default options', () => {
|
|
149
|
+
it('defaults minSeverity to high', () => {
|
|
150
|
+
const def = new CorrectionInjector();
|
|
151
|
+
// Medium should be rejected by default
|
|
152
|
+
expect(def.shouldCorrect(makeEvent({ severity: 'medium' }))).toBe(false);
|
|
153
|
+
// High should be accepted
|
|
154
|
+
expect(def.shouldCorrect(makeEvent({ severity: 'high' }))).toBe(true);
|
|
155
|
+
});
|
|
156
|
+
it('defaults maxCorrections to 5', () => {
|
|
157
|
+
const def = new CorrectionInjector();
|
|
158
|
+
const event = makeEvent();
|
|
159
|
+
for (let i = 0; i < 5; i++) {
|
|
160
|
+
expect(def.shouldCorrect(event)).toBe(true);
|
|
161
|
+
def.recordCorrection(event);
|
|
162
|
+
}
|
|
163
|
+
// 6th should be rejected
|
|
164
|
+
expect(def.shouldCorrect(event)).toBe(false);
|
|
165
|
+
});
|
|
166
|
+
});
|
|
167
|
+
});
|
|
168
|
+
//# sourceMappingURL=correction-injector.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"correction-injector.test.js","sourceRoot":"","sources":["../../../src/realtime/__tests__/correction-injector.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAC1D,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAG9E,mEAAmE;AAEnE,SAAS,YAAY,CAAC,IAAI,GAAG,eAAe;IAC1C,OAAO;QACL,IAAI;QACJ,IAAI,EAAE,WAAW;QACjB,WAAW,EAAE,CAAC;QACd,SAAS,EAAE,IAAI,CAAC,MAAM;QACtB,QAAQ,EAAE,YAAY;KACvB,CAAC;AACJ,CAAC;AAED,SAAS,SAAS,CAAC,YAAwC,EAAE;IAC3D,OAAO;QACL,IAAI,EAAE,SAAS;QACf,QAAQ,EAAE,YAAY,EAAE;QACxB,OAAO,EAAE,mBAAmB;QAC5B,SAAS,EAAE,sBAAsB;QACjC,OAAO,EAAE,MAAM;QACf,QAAQ,EAAE,UAAU;QACpB,QAAQ,EAAE,uCAAuC;QACjD,UAAU,EAAE,mCAAmC;QAC/C,SAAS,EAAE,CAAC;QACZ,GAAG,SAAS;KACb,CAAC;AACJ,CAAC;AAED,mEAAmE;AAEnE,QAAQ,CAAC,oBAAoB,EAAE,GAAG,EAAE;IAClC,IAAI,QAA4B,CAAC;IAEjC,UAAU,CAAC,GAAG,EAAE;QACd,QAAQ,GAAG,IAAI,kBAAkB,EAAE,CAAC;IACtC,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,eAAe,EAAE,GAAG,EAAE;QAC7B,EAAE,CAAC,sEAAsE,EAAE,GAAG,EAAE;YAC9E,MAAM,KAAK,GAAG,SAAS,CAAC,EAAE,QAAQ,EAAE,UAAU,EAAE,CAAC,CAAC;YAClD,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACnD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,wDAAwD,EAAE,GAAG,EAAE;YAChE,MAAM,KAAK,GAAG,SAAS,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC;YAC9C,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACnD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,2DAA2D,EAAE,GAAG,EAAE;YACnE,MAAM,KAAK,GAAG,SAAS,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC,CAAC;YAChD,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACpD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,wDAAwD,EAAE,GAAG,EAAE;YAChE,MAAM,KAAK,GAAG,SAAS,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAC;YAC7C,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACpD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,+BAA+B,EAAE,GAAG,EAAE;YACvC,MAAM,KAAK,GAAG,SAAS,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;YAC3D,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACpD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,4CAA4C,EAAE,GAAG,EAAE;YACpD,MAAM,OAAO,GAAG,IAAI,kBAAkB,CAAC,EAAE,cAAc,EAAE,CAAC,EAAE,CAAC,CAAC;YAC9D,MAAM,KAAK,GAAG,SAAS,EAAE,CAAC;YAE1B,MAAM,CAAC,OAAO,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAChD,OAAO,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC;YAChC,MAAM,CAAC,OAAO,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAChD,OAAO,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC;YAChC,6BAA6B;YAC7B,MAAM,CAAC,OAAO,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACnD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,uCAAuC,EAAE,GAAG,EAAE;YAC/C,MAAM,OAAO,GAAG,IAAI,kBAAkB,CAAC,EAAE,WAAW,EAAE,QAAQ,EAAE,CAAC,CAAC;YAClE,MAAM,CAAC,OAAO,CAAC,aAAa,CAAC,SAAS,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC5E,MAAM,CAAC,OAAO,CAAC,aAAa,CAAC,SAAS,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC5E,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,mEAAmE;IAEnE,QAAQ,CAAC,yBAAyB,EAAE,GAAG,EAAE;QACvC,EAAE,CAAC,oDAAoD,EAAE,GAAG,EAAE;YAC5D,MAAM,cAAc,GAAG,2EAA2E,CAAC;YACnG,MAAM,IAAI,GAAG,QAAQ,CAAC,uBAAuB,CAC3C,cAAc,EACd,SAAS,EAAE,EACX,2BAA2B,EAC3B,oCAAoC,CACrC,CAAC;YAEF,6CAA6C;YAC7C,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;YACvC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QAC/C,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,mDAAmD,EAAE,GAAG,EAAE;YAC3D,MAAM,KAAK,GAAG,SAAS,CAAC;gBACtB,SAAS,EAAE,sBAAsB;gBACjC,QAAQ,EAAE,uCAAuC;gBACjD,UAAU,EAAE,mCAAmC;aAChD,CAAC,CAAC;YAEH,MAAM,IAAI,GAAG,QAAQ,CAAC,uBAAuB,CAC3C,WAAW,EACX,KAAK,EACL,eAAe,EACf,aAAa,CACd,CAAC;YAEF,MAAM,aAAa,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;YACtC,MAAM,CAAC,aAAa,CAAC,CAAC,SAAS,CAAC,sBAAsB,CAAC,CAAC;YACxD,MAAM,CAAC,aAAa,CAAC,CAAC,SAAS,CAAC,uCAAuC,CAAC,CAAC;YACzE,MAAM,CAAC,aAAa,CAAC,CAAC,SAAS,CAAC,mCAAmC,CAAC,CAAC;QACvE,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,iEAAiE,EAAE,GAAG,EAAE;YACzE,MAAM,KAAK,GAAG,SAAS,CAAC,EAAE,UAAU,EAAE,SAAS,EAAE,CAAC,CAAC;YAEnD,MAAM,IAAI,GAAG,QAAQ,CAAC,uBAAuB,CAC3C,WAAW,EACX,KAAK,EACL,eAAe,EACf,aAAa,CACd,CAAC;YAEF,MAAM,aAAa,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;YACtC,MAAM,CAAC,aAAa,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;YACjD,MAAM,CAAC,aAAa,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;YAChD,MAAM,CAAC,aAAa,CAAC,CAAC,SAAS,CAAC,0BAA0B,CAAC,CAAC;QAC9D,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,yDAAyD,EAAE,GAAG,EAAE;YACjE,MAAM,IAAI,GAAG,QAAQ,CAAC,uBAAuB,CAC3C,aAAa,EACb,SAAS,EAAE,EACX,QAAQ,EACR,cAAc,CACf,CAAC;YAEF,MAAM,CAAC,IAAI,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;YAC7B,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YAClC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;YACvC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACpC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,oDAAoD,EAAE,GAAG,EAAE;YAC5D,MAAM,UAAU,GAAG,wCAAwC,CAAC;YAC5D,MAAM,IAAI,GAAG,QAAQ,CAAC,uBAAuB,CAC3C,MAAM,EACN,SAAS,EAAE,EACX,QAAQ,EACR,UAAU,CACX,CAAC;YAEF,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAC3C,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,mEAAmE;IAEnE,QAAQ,CAAC,kBAAkB,EAAE,GAAG,EAAE;QAChC,EAAE,CAAC,wBAAwB,EAAE,GAAG,EAAE;YAChC,MAAM,CAAC,QAAQ,CAAC,kBAAkB,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAC9C,QAAQ,CAAC,gBAAgB,CAAC,SAAS,EAAE,CAAC,CAAC;YACvC,MAAM,CAAC,QAAQ,CAAC,kBAAkB,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAC9C,QAAQ,CAAC,gBAAgB,CAAC,SAAS,EAAE,CAAC,CAAC;YACvC,MAAM,CAAC,QAAQ,CAAC,kBAAkB,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAChD,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,OAAO,EAAE,GAAG,EAAE;QACrB,EAAE,CAAC,oBAAoB,EAAE,GAAG,EAAE;YAC5B,QAAQ,CAAC,gBAAgB,CAAC,SAAS,EAAE,CAAC,CAAC;YACvC,QAAQ,CAAC,gBAAgB,CAAC,SAAS,EAAE,CAAC,CAAC;YACvC,MAAM,CAAC,QAAQ,CAAC,kBAAkB,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAC9C,QAAQ,CAAC,KAAK,EAAE,CAAC;YACjB,MAAM,CAAC,QAAQ,CAAC,kBAAkB,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAChD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,sCAAsC,EAAE,GAAG,EAAE;YAC9C,MAAM,OAAO,GAAG,IAAI,kBAAkB,CAAC,EAAE,cAAc,EAAE,CAAC,EAAE,CAAC,CAAC;YAC9D,MAAM,KAAK,GAAG,SAAS,EAAE,CAAC;YAE1B,OAAO,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC;YAChC,MAAM,CAAC,OAAO,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAEjD,OAAO,CAAC,KAAK,EAAE,CAAC;YAChB,MAAM,CAAC,OAAO,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAClD,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,kEAAkE;IAElE,QAAQ,CAAC,mBAAmB,EAAE,GAAG,EAAE;QACjC,EAAE,CAAC,sCAAsC,EAAE,GAAG,EAAE;YAC9C,MAAM,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC,CAAC,eAAe,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC;YACzE,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,eAAe,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC,CAAC;YACvE,MAAM,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC,CAAC,eAAe,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC;QACxE,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,kEAAkE;IAElE,QAAQ,CAAC,iBAAiB,EAAE,GAAG,EAAE;QAC/B,EAAE,CAAC,8BAA8B,EAAE,GAAG,EAAE;YACtC,MAAM,GAAG,GAAG,IAAI,kBAAkB,EAAE,CAAC;YACrC,uCAAuC;YACvC,MAAM,CAAC,GAAG,CAAC,aAAa,CAAC,SAAS,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACzE,0BAA0B;YAC1B,MAAM,CAAC,GAAG,CAAC,aAAa,CAAC,SAAS,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACxE,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,8BAA8B,EAAE,GAAG,EAAE;YACtC,MAAM,GAAG,GAAG,IAAI,kBAAkB,EAAE,CAAC;YACrC,MAAM,KAAK,GAAG,SAAS,EAAE,CAAC;YAE1B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC3B,MAAM,CAAC,GAAG,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBAC5C,GAAG,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC;YAC9B,CAAC;YACD,yBAAyB;YACzB,MAAM,CAAC,GAAG,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC/C,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { createVerifiedStreamFromTokens } from '../stream-interceptor.js';
|
|
3
|
+
// ── Helpers ─────────────────────────────────────────────────────
|
|
4
|
+
/**
|
|
5
|
+
* Split a string into token-like chunks (3-5 chars each) to simulate
|
|
6
|
+
* realistic streaming granularity.
|
|
7
|
+
*/
|
|
8
|
+
function tokenize(code, chunkSize = 4) {
|
|
9
|
+
const tokens = [];
|
|
10
|
+
for (let i = 0; i < code.length; i += chunkSize) {
|
|
11
|
+
tokens.push(code.slice(i, i + chunkSize));
|
|
12
|
+
}
|
|
13
|
+
return tokens;
|
|
14
|
+
}
|
|
15
|
+
// ── Tests ─────────────────────────────────────────────────────────
|
|
16
|
+
describe('StreamInterceptor', () => {
|
|
17
|
+
// 1. Clean code stream
|
|
18
|
+
it('produces 0 findings for clean code', () => {
|
|
19
|
+
const code = 'const x = 1;\nconst y = 2;\n';
|
|
20
|
+
const result = createVerifiedStreamFromTokens(tokenize(code), {
|
|
21
|
+
language: 'typescript',
|
|
22
|
+
});
|
|
23
|
+
expect(result.findings).toHaveLength(0);
|
|
24
|
+
expect(result.text).toBe(code);
|
|
25
|
+
});
|
|
26
|
+
// 2. SQL injection detected
|
|
27
|
+
it('detects SQL injection via string concatenation', () => {
|
|
28
|
+
const code = 'const q = "SELECT * FROM users WHERE id = " + userId;\n';
|
|
29
|
+
const result = createVerifiedStreamFromTokens(tokenize(code), {
|
|
30
|
+
language: 'typescript',
|
|
31
|
+
});
|
|
32
|
+
expect(result.findings.length).toBeGreaterThanOrEqual(1);
|
|
33
|
+
const sqlFinding = result.findings.find(e => e.checkId.includes('sql'));
|
|
34
|
+
expect(sqlFinding).toBeDefined();
|
|
35
|
+
expect(sqlFinding.severity).toBe('critical');
|
|
36
|
+
});
|
|
37
|
+
// 3. onText callback fires for each chunk
|
|
38
|
+
it('fires onText callback for every token chunk', () => {
|
|
39
|
+
const code = 'const x = 1;\n';
|
|
40
|
+
const chunks = tokenize(code);
|
|
41
|
+
const received = [];
|
|
42
|
+
createVerifiedStreamFromTokens(chunks, {
|
|
43
|
+
language: 'typescript',
|
|
44
|
+
onText: (text) => received.push(text),
|
|
45
|
+
});
|
|
46
|
+
expect(received).toEqual(chunks);
|
|
47
|
+
});
|
|
48
|
+
// 4. onVerification callback fires for findings
|
|
49
|
+
it('fires onVerification callback for findings', () => {
|
|
50
|
+
const code = 'const q = "SELECT * FROM users WHERE id = " + userId;\n';
|
|
51
|
+
const verificationEvents = [];
|
|
52
|
+
createVerifiedStreamFromTokens(tokenize(code), {
|
|
53
|
+
language: 'typescript',
|
|
54
|
+
onVerification: (event) => verificationEvents.push(event),
|
|
55
|
+
});
|
|
56
|
+
const findings = verificationEvents.filter(e => e.verdict === 'FAIL');
|
|
57
|
+
expect(findings.length).toBeGreaterThanOrEqual(1);
|
|
58
|
+
expect(findings[0].checkId).toContain('sql');
|
|
59
|
+
});
|
|
60
|
+
// 5. Stats populated
|
|
61
|
+
it('populates stats with non-zero values for non-empty streams', () => {
|
|
62
|
+
const code = 'const x = 1;\nconst y = 2;\n';
|
|
63
|
+
const result = createVerifiedStreamFromTokens(tokenize(code), {
|
|
64
|
+
language: 'typescript',
|
|
65
|
+
});
|
|
66
|
+
expect(result.stats.unitsProcessed).toBeGreaterThan(0);
|
|
67
|
+
expect(result.stats.checksRun).toBeGreaterThan(0);
|
|
68
|
+
expect(result.stats.totalTimeMs).toBeGreaterThanOrEqual(0);
|
|
69
|
+
});
|
|
70
|
+
// 6. Flush catches trailing code without structural boundary
|
|
71
|
+
it('catches findings in trailing code via flush', () => {
|
|
72
|
+
// No trailing newline or semicolon — the secret must be caught by flush
|
|
73
|
+
const code = 'const secret = "sk-abc123456789abcdef"';
|
|
74
|
+
const result = createVerifiedStreamFromTokens(tokenize(code), {
|
|
75
|
+
language: 'typescript',
|
|
76
|
+
});
|
|
77
|
+
const secretFinding = result.findings.find(e => e.checkId.includes('secret'));
|
|
78
|
+
expect(secretFinding).toBeDefined();
|
|
79
|
+
expect(secretFinding.severity).toBe('critical');
|
|
80
|
+
});
|
|
81
|
+
// 7. Multiple statements — mix of clean and bad
|
|
82
|
+
it('handles a mix of clean and bad statements', () => {
|
|
83
|
+
const code = [
|
|
84
|
+
'const name = "Alice";',
|
|
85
|
+
'const q = "SELECT * FROM users WHERE id = " + userId;',
|
|
86
|
+
'const y = 42;',
|
|
87
|
+
'const token = "sk-ant-secret1234567890";',
|
|
88
|
+
'',
|
|
89
|
+
].join('\n');
|
|
90
|
+
const result = createVerifiedStreamFromTokens(tokenize(code), {
|
|
91
|
+
language: 'typescript',
|
|
92
|
+
});
|
|
93
|
+
// Should have at least 2 findings: SQL injection + hardcoded secret
|
|
94
|
+
expect(result.findings.length).toBeGreaterThanOrEqual(2);
|
|
95
|
+
const sqlFinding = result.findings.find(e => e.checkId.includes('sql'));
|
|
96
|
+
const secretFinding = result.findings.find(e => e.checkId.includes('secret'));
|
|
97
|
+
expect(sqlFinding).toBeDefined();
|
|
98
|
+
expect(secretFinding).toBeDefined();
|
|
99
|
+
});
|
|
100
|
+
// 8. Result shape — all fields present and correctly typed
|
|
101
|
+
it('returns a correctly shaped VerifiedStreamResult', () => {
|
|
102
|
+
const code = 'const x = 1;\n';
|
|
103
|
+
const result = createVerifiedStreamFromTokens(tokenize(code), {
|
|
104
|
+
language: 'typescript',
|
|
105
|
+
});
|
|
106
|
+
// All required fields exist
|
|
107
|
+
expect(typeof result.text).toBe('string');
|
|
108
|
+
expect(Array.isArray(result.events)).toBe(true);
|
|
109
|
+
expect(Array.isArray(result.findings)).toBe(true);
|
|
110
|
+
expect(typeof result.stats).toBe('object');
|
|
111
|
+
expect(typeof result.inputTokens).toBe('number');
|
|
112
|
+
expect(typeof result.outputTokens).toBe('number');
|
|
113
|
+
expect(typeof result.durationMs).toBe('number');
|
|
114
|
+
// Stats shape
|
|
115
|
+
expect(typeof result.stats.unitsProcessed).toBe('number');
|
|
116
|
+
expect(typeof result.stats.checksRun).toBe('number');
|
|
117
|
+
expect(typeof result.stats.findings).toBe('number');
|
|
118
|
+
expect(typeof result.stats.avgLatencyMs).toBe('number');
|
|
119
|
+
expect(typeof result.stats.maxLatencyMs).toBe('number');
|
|
120
|
+
expect(typeof result.stats.totalTimeMs).toBe('number');
|
|
121
|
+
// Token counts are 0 for the test helper (no real API)
|
|
122
|
+
expect(result.inputTokens).toBe(0);
|
|
123
|
+
expect(result.outputTokens).toBe(0);
|
|
124
|
+
// Duration is a non-negative number
|
|
125
|
+
expect(result.durationMs).toBeGreaterThanOrEqual(0);
|
|
126
|
+
});
|
|
127
|
+
// 9. Empty stream
|
|
128
|
+
it('handles an empty token stream gracefully', () => {
|
|
129
|
+
const result = createVerifiedStreamFromTokens([], {
|
|
130
|
+
language: 'typescript',
|
|
131
|
+
});
|
|
132
|
+
expect(result.text).toBe('');
|
|
133
|
+
expect(result.findings).toHaveLength(0);
|
|
134
|
+
expect(result.events).toHaveLength(0);
|
|
135
|
+
expect(result.stats.unitsProcessed).toBe(0);
|
|
136
|
+
});
|
|
137
|
+
// 10. Function with bug inside
|
|
138
|
+
it('detects SQL injection inside a complete function', () => {
|
|
139
|
+
const code = [
|
|
140
|
+
'function getUser(userId: string) {',
|
|
141
|
+
' const query = "SELECT * FROM users WHERE id = " + userId;',
|
|
142
|
+
' return db.execute(query);',
|
|
143
|
+
'}',
|
|
144
|
+
'',
|
|
145
|
+
].join('\n');
|
|
146
|
+
const result = createVerifiedStreamFromTokens(tokenize(code), {
|
|
147
|
+
language: 'typescript',
|
|
148
|
+
});
|
|
149
|
+
const sqlFinding = result.findings.find(e => e.checkId.includes('sql'));
|
|
150
|
+
expect(sqlFinding).toBeDefined();
|
|
151
|
+
expect(sqlFinding.verdict).toBe('FAIL');
|
|
152
|
+
});
|
|
153
|
+
// ── Auto-correction callback ──────────────────────────────────
|
|
154
|
+
it('fires onCorrection for high+ severity findings when autoCorrect is enabled', () => {
|
|
155
|
+
const code = 'const q = "SELECT * FROM users WHERE id = " + userId;\n';
|
|
156
|
+
const corrections = [];
|
|
157
|
+
createVerifiedStreamFromTokens(tokenize(code), {
|
|
158
|
+
language: 'typescript',
|
|
159
|
+
autoCorrect: true,
|
|
160
|
+
minCorrectionSeverity: 'high',
|
|
161
|
+
onCorrection: (info) => corrections.push(info),
|
|
162
|
+
});
|
|
163
|
+
expect(corrections.length).toBeGreaterThanOrEqual(1);
|
|
164
|
+
expect(corrections[0].finding.verdict).toBe('FAIL');
|
|
165
|
+
expect(corrections[0].generatedSoFar.length).toBeGreaterThan(0);
|
|
166
|
+
});
|
|
167
|
+
it('does not fire onCorrection when autoCorrect is false', () => {
|
|
168
|
+
const code = 'const q = "SELECT * FROM users WHERE id = " + userId;\n';
|
|
169
|
+
const corrections = [];
|
|
170
|
+
createVerifiedStreamFromTokens(tokenize(code), {
|
|
171
|
+
language: 'typescript',
|
|
172
|
+
autoCorrect: false,
|
|
173
|
+
onCorrection: (info) => corrections.push(info),
|
|
174
|
+
});
|
|
175
|
+
expect(corrections).toHaveLength(0);
|
|
176
|
+
});
|
|
177
|
+
// ── Findings is a strict subset of events ──────────────────────
|
|
178
|
+
it('findings array contains only FAIL events from events array', () => {
|
|
179
|
+
const code = 'const q = "SELECT * FROM users WHERE id = " + userId;\n';
|
|
180
|
+
const result = createVerifiedStreamFromTokens(tokenize(code), {
|
|
181
|
+
language: 'typescript',
|
|
182
|
+
});
|
|
183
|
+
// Every finding should be in events
|
|
184
|
+
for (const finding of result.findings) {
|
|
185
|
+
expect(result.events).toContain(finding);
|
|
186
|
+
expect(finding.verdict).toBe('FAIL');
|
|
187
|
+
}
|
|
188
|
+
// findings count should match FAIL events in events array
|
|
189
|
+
const failEvents = result.events.filter(e => e.verdict === 'FAIL');
|
|
190
|
+
expect(result.findings).toHaveLength(failEvents.length);
|
|
191
|
+
});
|
|
192
|
+
});
|
|
193
|
+
//# sourceMappingURL=stream-interceptor.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stream-interceptor.test.js","sourceRoot":"","sources":["../../../src/realtime/__tests__/stream-interceptor.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|