@vibe-validate/extractors 0.16.1 → 0.17.0-rc.10

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.
Files changed (167) hide show
  1. package/dist/extractor-registry.d.ts +103 -0
  2. package/dist/extractor-registry.d.ts.map +1 -0
  3. package/dist/extractor-registry.js +278 -0
  4. package/dist/extractor-registry.js.map +1 -0
  5. package/dist/extractors/ava/index.d.ts +23 -0
  6. package/dist/extractors/ava/index.d.ts.map +1 -0
  7. package/dist/extractors/ava/index.js +507 -0
  8. package/dist/extractors/ava/index.js.map +1 -0
  9. package/dist/extractors/ava/index.test.d.ts +7 -0
  10. package/dist/extractors/ava/index.test.d.ts.map +1 -0
  11. package/dist/extractors/ava/index.test.js +408 -0
  12. package/dist/extractors/ava/index.test.js.map +1 -0
  13. package/dist/extractors/eslint/index.d.ts +18 -0
  14. package/dist/extractors/eslint/index.d.ts.map +1 -0
  15. package/dist/extractors/eslint/index.js +206 -0
  16. package/dist/extractors/eslint/index.js.map +1 -0
  17. package/dist/extractors/eslint/index.test.d.ts +9 -0
  18. package/dist/extractors/eslint/index.test.d.ts.map +1 -0
  19. package/dist/extractors/eslint/index.test.js +191 -0
  20. package/dist/extractors/eslint/index.test.js.map +1 -0
  21. package/dist/extractors/generic/index.d.ts +30 -0
  22. package/dist/extractors/generic/index.d.ts.map +1 -0
  23. package/dist/extractors/generic/index.js +140 -0
  24. package/dist/extractors/generic/index.js.map +1 -0
  25. package/dist/extractors/generic/index.test.d.ts +7 -0
  26. package/dist/extractors/generic/index.test.d.ts.map +1 -0
  27. package/dist/extractors/generic/index.test.js +61 -0
  28. package/dist/extractors/generic/index.test.js.map +1 -0
  29. package/dist/extractors/jasmine/index.d.ts +17 -0
  30. package/dist/extractors/jasmine/index.d.ts.map +1 -0
  31. package/dist/extractors/jasmine/index.js +254 -0
  32. package/dist/extractors/jasmine/index.js.map +1 -0
  33. package/dist/extractors/jasmine/index.test.d.ts +7 -0
  34. package/dist/extractors/jasmine/index.test.d.ts.map +1 -0
  35. package/dist/extractors/jasmine/index.test.js +345 -0
  36. package/dist/extractors/jasmine/index.test.js.map +1 -0
  37. package/dist/extractors/jest/index.d.ts +17 -0
  38. package/dist/extractors/jest/index.d.ts.map +1 -0
  39. package/dist/extractors/jest/index.js +278 -0
  40. package/dist/extractors/jest/index.js.map +1 -0
  41. package/dist/extractors/jest/index.test.d.ts +9 -0
  42. package/dist/extractors/jest/index.test.d.ts.map +1 -0
  43. package/dist/extractors/jest/index.test.js +353 -0
  44. package/dist/extractors/jest/index.test.js.map +1 -0
  45. package/dist/extractors/junit/index.d.ts +18 -0
  46. package/dist/extractors/junit/index.d.ts.map +1 -0
  47. package/dist/extractors/junit/index.js +259 -0
  48. package/dist/extractors/junit/index.js.map +1 -0
  49. package/dist/extractors/junit/index.test.d.ts +7 -0
  50. package/dist/extractors/junit/index.test.d.ts.map +1 -0
  51. package/dist/extractors/junit/index.test.js +341 -0
  52. package/dist/extractors/junit/index.test.js.map +1 -0
  53. package/dist/extractors/maven-checkstyle/index.d.ts +23 -0
  54. package/dist/extractors/maven-checkstyle/index.d.ts.map +1 -0
  55. package/dist/extractors/maven-checkstyle/index.js +263 -0
  56. package/dist/extractors/maven-checkstyle/index.js.map +1 -0
  57. package/dist/extractors/maven-checkstyle/index.test.d.ts +2 -0
  58. package/dist/extractors/maven-checkstyle/index.test.d.ts.map +1 -0
  59. package/dist/extractors/maven-checkstyle/index.test.js +197 -0
  60. package/dist/extractors/maven-checkstyle/index.test.js.map +1 -0
  61. package/dist/extractors/maven-compiler/index.d.ts +23 -0
  62. package/dist/extractors/maven-compiler/index.d.ts.map +1 -0
  63. package/dist/extractors/maven-compiler/index.js +271 -0
  64. package/dist/extractors/maven-compiler/index.js.map +1 -0
  65. package/dist/extractors/maven-compiler/index.test.d.ts +2 -0
  66. package/dist/extractors/maven-compiler/index.test.d.ts.map +1 -0
  67. package/dist/extractors/maven-compiler/index.test.js +189 -0
  68. package/dist/extractors/maven-compiler/index.test.js.map +1 -0
  69. package/dist/extractors/maven-surefire/index.d.ts +23 -0
  70. package/dist/extractors/maven-surefire/index.d.ts.map +1 -0
  71. package/dist/extractors/maven-surefire/index.js +292 -0
  72. package/dist/extractors/maven-surefire/index.js.map +1 -0
  73. package/dist/extractors/maven-surefire/index.test.d.ts +2 -0
  74. package/dist/extractors/maven-surefire/index.test.d.ts.map +1 -0
  75. package/dist/extractors/maven-surefire/index.test.js +169 -0
  76. package/dist/extractors/maven-surefire/index.test.js.map +1 -0
  77. package/dist/extractors/mocha/index.d.ts +17 -0
  78. package/dist/extractors/mocha/index.d.ts.map +1 -0
  79. package/dist/extractors/mocha/index.js +241 -0
  80. package/dist/extractors/mocha/index.js.map +1 -0
  81. package/dist/extractors/mocha/index.test.d.ts +7 -0
  82. package/dist/extractors/mocha/index.test.d.ts.map +1 -0
  83. package/dist/extractors/mocha/index.test.js +300 -0
  84. package/dist/extractors/mocha/index.test.js.map +1 -0
  85. package/dist/extractors/playwright/index.d.ts +17 -0
  86. package/dist/extractors/playwright/index.d.ts.map +1 -0
  87. package/dist/extractors/playwright/index.js +320 -0
  88. package/dist/extractors/playwright/index.js.map +1 -0
  89. package/dist/extractors/playwright/index.test.d.ts +7 -0
  90. package/dist/extractors/playwright/index.test.d.ts.map +1 -0
  91. package/dist/extractors/playwright/index.test.js +274 -0
  92. package/dist/extractors/playwright/index.test.js.map +1 -0
  93. package/dist/extractors/tap/index.d.ts +23 -0
  94. package/dist/extractors/tap/index.d.ts.map +1 -0
  95. package/dist/extractors/tap/index.js +352 -0
  96. package/dist/extractors/tap/index.js.map +1 -0
  97. package/dist/extractors/tap/index.test.d.ts +7 -0
  98. package/dist/extractors/tap/index.test.d.ts.map +1 -0
  99. package/dist/extractors/tap/index.test.js +100 -0
  100. package/dist/extractors/tap/index.test.js.map +1 -0
  101. package/dist/extractors/typescript/index.d.ts +17 -0
  102. package/dist/extractors/typescript/index.d.ts.map +1 -0
  103. package/dist/extractors/typescript/index.js +150 -0
  104. package/dist/extractors/typescript/index.js.map +1 -0
  105. package/dist/extractors/typescript/index.test.d.ts +9 -0
  106. package/dist/extractors/typescript/index.test.d.ts.map +1 -0
  107. package/dist/extractors/typescript/index.test.js +177 -0
  108. package/dist/extractors/typescript/index.test.js.map +1 -0
  109. package/dist/extractors/vitest/index.d.ts +17 -0
  110. package/dist/extractors/vitest/index.d.ts.map +1 -0
  111. package/dist/extractors/vitest/index.js +564 -0
  112. package/dist/extractors/vitest/index.js.map +1 -0
  113. package/dist/extractors/vitest/index.test.d.ts +9 -0
  114. package/dist/extractors/vitest/index.test.d.ts.map +1 -0
  115. package/dist/extractors/vitest/index.test.js +373 -0
  116. package/dist/extractors/vitest/index.test.js.map +1 -0
  117. package/dist/index.d.ts +27 -11
  118. package/dist/index.d.ts.map +1 -1
  119. package/dist/index.js +27 -11
  120. package/dist/index.js.map +1 -1
  121. package/dist/maven-checkstyle-extractor.d.ts +20 -0
  122. package/dist/maven-checkstyle-extractor.d.ts.map +1 -0
  123. package/dist/maven-checkstyle-extractor.js +208 -0
  124. package/dist/maven-checkstyle-extractor.js.map +1 -0
  125. package/dist/maven-compiler-extractor.d.ts +20 -0
  126. package/dist/maven-compiler-extractor.d.ts.map +1 -0
  127. package/dist/maven-compiler-extractor.js +218 -0
  128. package/dist/maven-compiler-extractor.js.map +1 -0
  129. package/dist/maven-surefire-extractor.d.ts +20 -0
  130. package/dist/maven-surefire-extractor.d.ts.map +1 -0
  131. package/dist/maven-surefire-extractor.js +228 -0
  132. package/dist/maven-surefire-extractor.js.map +1 -0
  133. package/dist/maven-utils.d.ts +24 -0
  134. package/dist/maven-utils.d.ts.map +1 -0
  135. package/dist/maven-utils.js +36 -0
  136. package/dist/maven-utils.js.map +1 -0
  137. package/dist/plugin-loader.d.ts +82 -0
  138. package/dist/plugin-loader.d.ts.map +1 -0
  139. package/dist/plugin-loader.js +201 -0
  140. package/dist/plugin-loader.js.map +1 -0
  141. package/dist/result-schema.d.ts +59 -9
  142. package/dist/result-schema.d.ts.map +1 -1
  143. package/dist/result-schema.js +3 -19
  144. package/dist/result-schema.js.map +1 -1
  145. package/dist/sandbox.d.ts +161 -0
  146. package/dist/sandbox.d.ts.map +1 -0
  147. package/dist/sandbox.js +254 -0
  148. package/dist/sandbox.js.map +1 -0
  149. package/dist/sandbox.test.d.ts +8 -0
  150. package/dist/sandbox.test.d.ts.map +1 -0
  151. package/dist/sandbox.test.js +395 -0
  152. package/dist/sandbox.test.js.map +1 -0
  153. package/dist/sandboxed-extractor.d.ts +46 -0
  154. package/dist/sandboxed-extractor.d.ts.map +1 -0
  155. package/dist/sandboxed-extractor.js +172 -0
  156. package/dist/sandboxed-extractor.js.map +1 -0
  157. package/dist/sandboxed-extractor.test.d.ts +5 -0
  158. package/dist/sandboxed-extractor.test.d.ts.map +1 -0
  159. package/dist/sandboxed-extractor.test.js +346 -0
  160. package/dist/sandboxed-extractor.test.js.map +1 -0
  161. package/dist/smart-extractor.d.ts +22 -10
  162. package/dist/smart-extractor.d.ts.map +1 -1
  163. package/dist/smart-extractor.js +116 -163
  164. package/dist/smart-extractor.js.map +1 -1
  165. package/dist/types.d.ts +94 -0
  166. package/dist/types.d.ts.map +1 -1
  167. package/package.json +3 -2
@@ -0,0 +1,395 @@
1
+ /**
2
+ * Sandbox Module Tests
3
+ *
4
+ * Tests secure extractor execution using isolated-vm.
5
+ * These tests validate the sandbox can execute real extractor code safely.
6
+ */
7
+ import { describe, it, expect } from 'vitest';
8
+ import { runInSandbox, createSandboxedCode, SandboxStatsCollector, } from './sandbox.js';
9
+ describe('Sandbox Module', () => {
10
+ describe('runInSandbox', () => {
11
+ it('should execute simple extractor code successfully', async () => {
12
+ const code = `
13
+ function extract(content) {
14
+ return [
15
+ { message: 'Test error', severity: 'error' }
16
+ ];
17
+ }
18
+ `;
19
+ const result = await runInSandbox({
20
+ code,
21
+ input: 'test input',
22
+ extractorName: 'test'
23
+ });
24
+ expect(result.success).toBe(true);
25
+ expect(result.errors).toHaveLength(1);
26
+ expect(result.errors?.[0].message).toBe('Test error');
27
+ expect(result.stats.durationMs).toBeGreaterThan(0);
28
+ });
29
+ it('should handle extractor that throws an error', async () => {
30
+ const code = `
31
+ function extract(content) {
32
+ throw new Error('Intentional failure');
33
+ }
34
+ `;
35
+ const result = await runInSandbox({
36
+ code,
37
+ input: 'test input',
38
+ extractorName: 'test'
39
+ });
40
+ expect(result.success).toBe(false);
41
+ expect(result.error).toContain('Intentional failure');
42
+ });
43
+ it('should enforce memory limits', async () => {
44
+ const code = `
45
+ function extract(content) {
46
+ // Try to allocate memory and fill it
47
+ const arrays = [];
48
+ try {
49
+ while (true) {
50
+ // Allocate 1MB chunks
51
+ arrays.push(new Array(256 * 1024).fill(1));
52
+ }
53
+ } catch (e) {
54
+ // Memory exhausted - this is expected
55
+ throw new Error('Out of memory');
56
+ }
57
+ return [];
58
+ }
59
+ `;
60
+ const result = await runInSandbox({
61
+ code,
62
+ input: 'test',
63
+ extractorName: 'memory-hog',
64
+ memoryLimitMB: 10, // Very low limit
65
+ timeoutMs: 1000 // Also set timeout to prevent hanging
66
+ });
67
+ // Should fail either due to memory limit or timeout
68
+ expect(result.success).toBe(false);
69
+ expect(result.error).toBeDefined();
70
+ });
71
+ it('should enforce timeout limits', async () => {
72
+ const code = `
73
+ function extract(content) {
74
+ // Infinite loop
75
+ while (true) {}
76
+ return [];
77
+ }
78
+ `;
79
+ const result = await runInSandbox({
80
+ code,
81
+ input: 'test',
82
+ extractorName: 'infinite-loop',
83
+ timeoutMs: 100 // Short timeout
84
+ });
85
+ expect(result.success).toBe(false);
86
+ expect(result.error).toContain('timed out');
87
+ });
88
+ it('should execute real extractor code (TypeScript-like)', async () => {
89
+ const code = String.raw `
90
+ function extract(content) {
91
+ const errors = [];
92
+ const pattern = /error TS(\d+):\s*(.+)/g;
93
+
94
+ let match;
95
+ while ((match = pattern.exec(content)) !== null) {
96
+ errors.push({
97
+ message: match[2].trim(),
98
+ code: 'TS' + match[1],
99
+ severity: 'error'
100
+ });
101
+ }
102
+
103
+ return errors;
104
+ }
105
+ `;
106
+ const input = `
107
+ src/test.ts:10:15 - error TS2322: Type 'string' is not assignable to type 'number'.
108
+ src/test.ts:20:5 - error TS2304: Cannot find name 'undefined'.
109
+ `;
110
+ const result = await runInSandbox({
111
+ code,
112
+ input,
113
+ extractorName: 'typescript'
114
+ });
115
+ expect(result.success).toBe(true);
116
+ expect(result.errors).toHaveLength(2);
117
+ expect(result.errors?.[0].code).toBe('TS2322');
118
+ expect(result.errors?.[1].code).toBe('TS2304');
119
+ });
120
+ it('should execute real extractor code (Maven-like)', async () => {
121
+ const code = String.raw `
122
+ function extract(content) {
123
+ const errors = [];
124
+ const pattern = /\[ERROR\]\s+([^:]+):\[(\d+),(\d+)\]\s+(.+)/g;
125
+
126
+ let match;
127
+ while ((match = pattern.exec(content)) !== null) {
128
+ errors.push({
129
+ file: match[1].trim(),
130
+ line: parseInt(match[2], 10),
131
+ column: parseInt(match[3], 10),
132
+ message: match[4].trim(),
133
+ severity: 'error'
134
+ });
135
+ }
136
+
137
+ return errors;
138
+ }
139
+ `;
140
+ const input = `
141
+ [ERROR] /src/main/java/App.java:[15,20] cannot find symbol
142
+ [ERROR] /src/main/java/Utils.java:[42,8] incompatible types
143
+ `;
144
+ const result = await runInSandbox({
145
+ code,
146
+ input,
147
+ extractorName: 'maven-compiler'
148
+ });
149
+ expect(result.success).toBe(true);
150
+ expect(result.errors).toHaveLength(2);
151
+ expect(result.errors?.[0].file).toContain('App.java');
152
+ expect(result.errors?.[0].line).toBe(15);
153
+ expect(result.errors?.[1].file).toContain('Utils.java');
154
+ expect(result.errors?.[1].line).toBe(42);
155
+ });
156
+ it('should provide accurate performance statistics', async () => {
157
+ const code = `
158
+ function extract(content) {
159
+ // Do some work
160
+ let result = [];
161
+ for (let i = 0; i < 1000; i++) {
162
+ result.push({ message: 'Error ' + i, severity: 'error' });
163
+ }
164
+ return result;
165
+ }
166
+ `;
167
+ const result = await runInSandbox({
168
+ code,
169
+ input: 'test',
170
+ extractorName: 'perf-test'
171
+ });
172
+ expect(result.success).toBe(true);
173
+ expect(result.stats.durationMs).toBeGreaterThan(0);
174
+ expect(result.stats.durationMs).toBeLessThan(1000); // Should be fast
175
+ expect(result.stats.memoryUsedMB).toBeGreaterThan(0);
176
+ });
177
+ it('should handle extractors that return empty arrays', async () => {
178
+ const code = `
179
+ function extract(content) {
180
+ return [];
181
+ }
182
+ `;
183
+ const result = await runInSandbox({
184
+ code,
185
+ input: 'no errors here',
186
+ extractorName: 'clean'
187
+ });
188
+ expect(result.success).toBe(true);
189
+ expect(result.errors).toHaveLength(0);
190
+ });
191
+ it('should handle extractors with complex logic', async () => {
192
+ const code = String.raw `
193
+ function extract(content) {
194
+ const errors = [];
195
+ const lines = content.split('\n');
196
+
197
+ for (let i = 0; i < lines.length; i++) {
198
+ const line = lines[i];
199
+
200
+ // Skip empty lines
201
+ if (!line.trim()) continue;
202
+
203
+ // Parse error format
204
+ if (line.includes('ERROR:')) {
205
+ const parts = line.split('ERROR:');
206
+ if (parts.length === 2) {
207
+ errors.push({
208
+ message: parts[1].trim(),
209
+ line: i + 1,
210
+ severity: 'error'
211
+ });
212
+ }
213
+ }
214
+ }
215
+
216
+ return errors;
217
+ }
218
+ `;
219
+ const input = `
220
+ Line 1: Some output
221
+ Line 2: ERROR: First error
222
+ Line 3: More output
223
+ Line 4: ERROR: Second error
224
+ `;
225
+ const result = await runInSandbox({
226
+ code,
227
+ input,
228
+ extractorName: 'complex'
229
+ });
230
+ expect(result.success).toBe(true);
231
+ expect(result.errors).toHaveLength(2);
232
+ expect(result.errors?.[0].message).toBe('First error');
233
+ expect(result.errors?.[1].message).toBe('Second error');
234
+ });
235
+ });
236
+ describe('createSandboxedCode', () => {
237
+ it('should handle named function declarations', () => {
238
+ function extract(content) {
239
+ return [{ message: content, severity: 'error' }];
240
+ }
241
+ const code = createSandboxedCode(extract);
242
+ expect(code).toContain('function extract(');
243
+ expect(code).toContain('return [');
244
+ });
245
+ it('should handle arrow functions', () => {
246
+ const extract = (content) => {
247
+ return [{ message: content, severity: 'error' }];
248
+ };
249
+ const code = createSandboxedCode(extract);
250
+ expect(code).toContain('function extract(content)');
251
+ });
252
+ });
253
+ describe('SandboxStatsCollector', () => {
254
+ it('should collect execution statistics', async () => {
255
+ const collector = new SandboxStatsCollector();
256
+ const code = `
257
+ function extract(content) {
258
+ return [{ message: 'Test', severity: 'error' }];
259
+ }
260
+ `;
261
+ // Execute multiple times
262
+ for (let i = 0; i < 3; i++) {
263
+ const result = await runInSandbox({
264
+ code,
265
+ input: 'test',
266
+ extractorName: 'stats-test'
267
+ });
268
+ collector.record(result);
269
+ }
270
+ const stats = collector.getStats();
271
+ expect(stats.totalExecutions).toBe(3);
272
+ expect(stats.successfulExecutions).toBe(3);
273
+ expect(stats.failedExecutions).toBe(0);
274
+ expect(stats.averageDurationMs).toBeGreaterThan(0);
275
+ expect(stats.averageMemoryUsedMB).toBeGreaterThan(0);
276
+ });
277
+ it('should track both successful and failed executions', async () => {
278
+ const collector = new SandboxStatsCollector();
279
+ // Successful execution
280
+ const successCode = `
281
+ function extract(content) {
282
+ return [];
283
+ }
284
+ `;
285
+ const successResult = await runInSandbox({
286
+ code: successCode,
287
+ input: 'test',
288
+ extractorName: 'success'
289
+ });
290
+ collector.record(successResult);
291
+ // Failed execution
292
+ const failCode = `
293
+ function extract(content) {
294
+ throw new Error('Fail');
295
+ }
296
+ `;
297
+ const failResult = await runInSandbox({
298
+ code: failCode,
299
+ input: 'test',
300
+ extractorName: 'fail'
301
+ });
302
+ collector.record(failResult);
303
+ const stats = collector.getStats();
304
+ expect(stats.totalExecutions).toBe(2);
305
+ expect(stats.successfulExecutions).toBe(1);
306
+ expect(stats.failedExecutions).toBe(1);
307
+ });
308
+ it('should reset statistics', async () => {
309
+ const collector = new SandboxStatsCollector();
310
+ const code = `
311
+ function extract(content) {
312
+ return [];
313
+ }
314
+ `;
315
+ const result = await runInSandbox({
316
+ code,
317
+ input: 'test',
318
+ extractorName: 'reset-test'
319
+ });
320
+ collector.record(result);
321
+ expect(collector.getStats().totalExecutions).toBe(1);
322
+ collector.reset();
323
+ expect(collector.getStats().totalExecutions).toBe(0);
324
+ expect(collector.getStats().successfulExecutions).toBe(0);
325
+ expect(collector.getStats().failedExecutions).toBe(0);
326
+ });
327
+ });
328
+ describe('Security Tests', () => {
329
+ it('should block access to Node.js process', async () => {
330
+ const code = `
331
+ function extract(content) {
332
+ // Try to access process
333
+ if (typeof process !== 'undefined') {
334
+ return [{ message: 'Process accessible!', severity: 'error' }];
335
+ }
336
+ return [];
337
+ }
338
+ `;
339
+ const result = await runInSandbox({
340
+ code,
341
+ input: 'test',
342
+ extractorName: 'process-test'
343
+ });
344
+ expect(result.success).toBe(true);
345
+ expect(result.errors).toHaveLength(0); // process should be undefined
346
+ });
347
+ it('should block access to require', async () => {
348
+ const code = `
349
+ function extract(content) {
350
+ // Try to use require
351
+ try {
352
+ require('fs');
353
+ return [{ message: 'require accessible!', severity: 'error' }];
354
+ } catch (e) {
355
+ return [];
356
+ }
357
+ }
358
+ `;
359
+ const result = await runInSandbox({
360
+ code,
361
+ input: 'test',
362
+ extractorName: 'require-test'
363
+ });
364
+ expect(result.success).toBe(true);
365
+ expect(result.errors).toHaveLength(0); // require should fail
366
+ });
367
+ it('should allow safe operations (String, Array, Object, JSON)', async () => {
368
+ const code = String.raw `
369
+ function extract(content) {
370
+ // Use safe APIs
371
+ const lines = content.split('\n');
372
+ const mapped = lines.map(l => l.trim());
373
+ const filtered = mapped.filter(l => l.length > 0);
374
+ const obj = { count: filtered.length };
375
+ const json = JSON.stringify(obj);
376
+ const parsed = JSON.parse(json);
377
+
378
+ return [{
379
+ message: 'Count: ' + parsed.count,
380
+ severity: 'info'
381
+ }];
382
+ }
383
+ `;
384
+ const result = await runInSandbox({
385
+ code,
386
+ input: 'line1\nline2\n\nline3',
387
+ extractorName: 'safe-api-test'
388
+ });
389
+ expect(result.success).toBe(true);
390
+ expect(result.errors).toHaveLength(1);
391
+ expect(result.errors?.[0].message).toBe('Count: 3');
392
+ });
393
+ });
394
+ });
395
+ //# sourceMappingURL=sandbox.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sandbox.test.js","sourceRoot":"","sources":["../src/sandbox.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Sandboxed Extractor Wrapper
3
+ *
4
+ * Wraps extractor plugins to execute in a secure sandbox when configured with 'sandbox' trust level.
5
+ * For 'full' trust, extractors run directly without sandboxing for maximum performance.
6
+ *
7
+ * @package @vibe-validate/extractors
8
+ */
9
+ import type { ExtractorPlugin, ErrorExtractorResult } from './types.js';
10
+ import type { ExtractorTrustLevel } from './extractor-registry.js';
11
+ /**
12
+ * Options for sandboxed extractor creation
13
+ */
14
+ export interface SandboxedExtractorOptions {
15
+ /** Trust level (default: 'sandbox') */
16
+ trust?: ExtractorTrustLevel;
17
+ /** Memory limit in MB for sandboxed execution (default: 128) */
18
+ memoryLimitMB?: number;
19
+ /** Timeout in milliseconds for sandboxed execution (default: 5000) */
20
+ timeoutMs?: number;
21
+ }
22
+ /**
23
+ * Wrap an extractor plugin to run in a sandbox based on trust level
24
+ *
25
+ * This function returns a wrapped extract function that:
26
+ * - If trust='full': Runs the original extract function directly (no sandbox)
27
+ * - If trust='sandbox': Runs the extract function in an isolated V8 context
28
+ *
29
+ * @param plugin - The extractor plugin to wrap
30
+ * @param options - Sandbox configuration options
31
+ * @returns Wrapped extract function that respects trust level
32
+ *
33
+ * @example Trusted execution (no sandbox)
34
+ * ```typescript
35
+ * const wrappedExtract = createSandboxedExtractor(plugin, { trust: 'full' });
36
+ * const result = wrappedExtract('error output');
37
+ * ```
38
+ *
39
+ * @example Sandboxed execution (secure)
40
+ * ```typescript
41
+ * const wrappedExtract = createSandboxedExtractor(plugin, { trust: 'sandbox' });
42
+ * const result = await wrappedExtract('error output');
43
+ * ```
44
+ */
45
+ export declare function createSandboxedExtractor(plugin: ExtractorPlugin, options?: SandboxedExtractorOptions): (output: string, command?: string) => Promise<ErrorExtractorResult>;
46
+ //# sourceMappingURL=sandboxed-extractor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sandboxed-extractor.d.ts","sourceRoot":"","sources":["../src/sandboxed-extractor.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,KAAK,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AACxE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAEnE;;GAEG;AACH,MAAM,WAAW,yBAAyB;IACxC,uCAAuC;IACvC,KAAK,CAAC,EAAE,mBAAmB,CAAC;IAE5B,gEAAgE;IAChE,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB,sEAAsE;IACtE,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,eAAe,EACvB,OAAO,GAAE,yBAA8B,GAEtC,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,oBAAoB,CAAC,CAsJrE"}
@@ -0,0 +1,172 @@
1
+ /**
2
+ * Sandboxed Extractor Wrapper
3
+ *
4
+ * Wraps extractor plugins to execute in a secure sandbox when configured with 'sandbox' trust level.
5
+ * For 'full' trust, extractors run directly without sandboxing for maximum performance.
6
+ *
7
+ * @package @vibe-validate/extractors
8
+ */
9
+ import { runInSandbox } from './sandbox.js';
10
+ /**
11
+ * Wrap an extractor plugin to run in a sandbox based on trust level
12
+ *
13
+ * This function returns a wrapped extract function that:
14
+ * - If trust='full': Runs the original extract function directly (no sandbox)
15
+ * - If trust='sandbox': Runs the extract function in an isolated V8 context
16
+ *
17
+ * @param plugin - The extractor plugin to wrap
18
+ * @param options - Sandbox configuration options
19
+ * @returns Wrapped extract function that respects trust level
20
+ *
21
+ * @example Trusted execution (no sandbox)
22
+ * ```typescript
23
+ * const wrappedExtract = createSandboxedExtractor(plugin, { trust: 'full' });
24
+ * const result = wrappedExtract('error output');
25
+ * ```
26
+ *
27
+ * @example Sandboxed execution (secure)
28
+ * ```typescript
29
+ * const wrappedExtract = createSandboxedExtractor(plugin, { trust: 'sandbox' });
30
+ * const result = await wrappedExtract('error output');
31
+ * ```
32
+ */
33
+ export function createSandboxedExtractor(plugin, options = {}
34
+ // eslint-disable-next-line no-unused-vars
35
+ ) {
36
+ const trust = options.trust ?? 'sandbox';
37
+ const memoryLimitMB = options.memoryLimitMB ?? 128;
38
+ const timeoutMs = options.timeoutMs ?? 5000;
39
+ // If trusted, return the original extract function (wrapped in Promise for consistency)
40
+ if (trust === 'full') {
41
+ return async (_output, _command) => {
42
+ return plugin.extract(_output, _command);
43
+ };
44
+ }
45
+ // Otherwise, wrap with sandbox execution
46
+ return async (output, command) => {
47
+ try {
48
+ // Serialize the extract function to string for sandbox execution
49
+ const extractFnCode = plugin.extract.toString();
50
+ // Create wrapped code that returns the full ErrorExtractorResult
51
+ // The sandbox's wrapper expects 'extract' to return 'errors', so we need to return the whole result
52
+ const sandboxCode = `
53
+ // Extract function from plugin
54
+ const extractFn = ${extractFnCode};
55
+
56
+ // Wrapper that calls the extract function and returns the full result
57
+ function extract(input) {
58
+ const command = ${command ? JSON.stringify(command) : 'undefined'};
59
+ const result = extractFn(input, command);
60
+
61
+ // If result is a Promise, throw error (sandbox doesn't support async)
62
+ if (result && typeof result.then === 'function') {
63
+ throw new Error('Async extractors cannot be sandboxed (use trust: "full")');
64
+ }
65
+
66
+ // Return the full ErrorExtractorResult object
67
+ // The sandbox wrapper will JSON.stringify this as { success: true, errors: <result> }
68
+ return result;
69
+ }
70
+ `;
71
+ // Execute in sandbox
72
+ const sandboxResult = await runInSandbox({
73
+ code: sandboxCode,
74
+ input: output,
75
+ extractorName: plugin.metadata.name,
76
+ memoryLimitMB,
77
+ timeoutMs,
78
+ });
79
+ // Check if sandbox execution succeeded
80
+ if (!sandboxResult.success) {
81
+ console.error(`[vibe-validate] Sandbox execution failed for extractor "${plugin.metadata.name}": ${sandboxResult.error}`);
82
+ // Return empty result with error metadata
83
+ return {
84
+ errors: [],
85
+ totalErrors: 0,
86
+ summary: `Sandbox execution failed: ${sandboxResult.error}`,
87
+ guidance: 'Check extractor code for syntax errors or unsafe operations',
88
+ metadata: {
89
+ detection: {
90
+ extractor: plugin.metadata.name,
91
+ confidence: 0,
92
+ patterns: [],
93
+ reason: `Sandbox execution error: ${sandboxResult.error}`,
94
+ },
95
+ confidence: 0,
96
+ completeness: 0,
97
+ issues: [`Sandbox execution failed: ${sandboxResult.error}`],
98
+ },
99
+ };
100
+ }
101
+ // Sandbox returns the full ErrorExtractorResult in the 'errors' field
102
+ // (The sandbox's wrapper puts the return value of extract() into the 'errors' field)
103
+ if (!sandboxResult.errors) {
104
+ return {
105
+ errors: [],
106
+ totalErrors: 0,
107
+ summary: 'Invalid sandbox result structure',
108
+ guidance: 'Extractor must return ErrorExtractorResult object',
109
+ metadata: {
110
+ detection: {
111
+ extractor: plugin.metadata.name,
112
+ confidence: 0,
113
+ patterns: [],
114
+ reason: 'Invalid result structure from sandbox',
115
+ },
116
+ confidence: 0,
117
+ completeness: 0,
118
+ issues: ['Sandbox returned invalid result structure'],
119
+ },
120
+ };
121
+ }
122
+ // Validate that sandboxResult.errors is a valid ErrorExtractorResult
123
+ const extractorResult = sandboxResult.errors;
124
+ // Check for required fields
125
+ if (!extractorResult.errors || !Array.isArray(extractorResult.errors)) {
126
+ return {
127
+ errors: [],
128
+ totalErrors: 0,
129
+ summary: 'Invalid extractor result: missing or invalid errors array',
130
+ guidance: 'Extractor must return ErrorExtractorResult with errors array',
131
+ metadata: {
132
+ detection: {
133
+ extractor: plugin.metadata.name,
134
+ confidence: 0,
135
+ patterns: [],
136
+ reason: 'Invalid ErrorExtractorResult structure',
137
+ },
138
+ confidence: 0,
139
+ completeness: 0,
140
+ issues: ['Extractor returned invalid ErrorExtractorResult (missing errors array)'],
141
+ },
142
+ };
143
+ }
144
+ // sandboxResult.errors is the full ErrorExtractorResult from the plugin
145
+ return extractorResult;
146
+ }
147
+ catch (error) {
148
+ // Handle unexpected errors
149
+ const errorMessage = error instanceof Error ? error.message : String(error);
150
+ console.error(`[vibe-validate] Unexpected error wrapping extractor "${plugin.metadata.name}": ${errorMessage}`);
151
+ // Return empty result with error metadata
152
+ return {
153
+ errors: [],
154
+ totalErrors: 0,
155
+ summary: `Extractor wrapper error: ${errorMessage}`,
156
+ guidance: 'Check extractor code and sandbox configuration',
157
+ metadata: {
158
+ detection: {
159
+ extractor: plugin.metadata.name,
160
+ confidence: 0,
161
+ patterns: [],
162
+ reason: `Wrapper error: ${errorMessage}`,
163
+ },
164
+ confidence: 0,
165
+ completeness: 0,
166
+ issues: [`Wrapper error: ${errorMessage}`],
167
+ },
168
+ };
169
+ }
170
+ };
171
+ }
172
+ //# sourceMappingURL=sandboxed-extractor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sandboxed-extractor.js","sourceRoot":"","sources":["../src/sandboxed-extractor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Tests for Sandboxed Extractor Wrapper
3
+ */
4
+ export {};
5
+ //# sourceMappingURL=sandboxed-extractor.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sandboxed-extractor.test.d.ts","sourceRoot":"","sources":["../src/sandboxed-extractor.test.ts"],"names":[],"mappings":"AAAA;;GAEG"}