@vulcn/engine 0.2.0 → 0.3.1
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/CHANGELOG.md +98 -0
- package/README.md +40 -174
- package/dist/index.cjs +247 -798
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +241 -547
- package/dist/index.d.ts +241 -547
- package/dist/index.js +243 -786
- package/dist/index.js.map +1 -1
- package/package.json +46 -24
package/dist/index.d.ts
CHANGED
|
@@ -1,422 +1,5 @@
|
|
|
1
|
-
import { Page, Dialog, ConsoleMessage, Request, Response, Browser } from 'playwright';
|
|
2
1
|
import { z } from 'zod';
|
|
3
2
|
|
|
4
|
-
declare const StepSchema: z.ZodDiscriminatedUnion<"type", [z.ZodObject<{
|
|
5
|
-
id: z.ZodString;
|
|
6
|
-
type: z.ZodLiteral<"navigate">;
|
|
7
|
-
url: z.ZodString;
|
|
8
|
-
timestamp: z.ZodNumber;
|
|
9
|
-
}, "strip", z.ZodTypeAny, {
|
|
10
|
-
type: "navigate";
|
|
11
|
-
id: string;
|
|
12
|
-
url: string;
|
|
13
|
-
timestamp: number;
|
|
14
|
-
}, {
|
|
15
|
-
type: "navigate";
|
|
16
|
-
id: string;
|
|
17
|
-
url: string;
|
|
18
|
-
timestamp: number;
|
|
19
|
-
}>, z.ZodObject<{
|
|
20
|
-
id: z.ZodString;
|
|
21
|
-
type: z.ZodLiteral<"click">;
|
|
22
|
-
selector: z.ZodString;
|
|
23
|
-
position: z.ZodOptional<z.ZodObject<{
|
|
24
|
-
x: z.ZodNumber;
|
|
25
|
-
y: z.ZodNumber;
|
|
26
|
-
}, "strip", z.ZodTypeAny, {
|
|
27
|
-
x: number;
|
|
28
|
-
y: number;
|
|
29
|
-
}, {
|
|
30
|
-
x: number;
|
|
31
|
-
y: number;
|
|
32
|
-
}>>;
|
|
33
|
-
timestamp: z.ZodNumber;
|
|
34
|
-
}, "strip", z.ZodTypeAny, {
|
|
35
|
-
type: "click";
|
|
36
|
-
id: string;
|
|
37
|
-
timestamp: number;
|
|
38
|
-
selector: string;
|
|
39
|
-
position?: {
|
|
40
|
-
x: number;
|
|
41
|
-
y: number;
|
|
42
|
-
} | undefined;
|
|
43
|
-
}, {
|
|
44
|
-
type: "click";
|
|
45
|
-
id: string;
|
|
46
|
-
timestamp: number;
|
|
47
|
-
selector: string;
|
|
48
|
-
position?: {
|
|
49
|
-
x: number;
|
|
50
|
-
y: number;
|
|
51
|
-
} | undefined;
|
|
52
|
-
}>, z.ZodObject<{
|
|
53
|
-
id: z.ZodString;
|
|
54
|
-
type: z.ZodLiteral<"input">;
|
|
55
|
-
selector: z.ZodString;
|
|
56
|
-
value: z.ZodString;
|
|
57
|
-
injectable: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
58
|
-
timestamp: z.ZodNumber;
|
|
59
|
-
}, "strip", z.ZodTypeAny, {
|
|
60
|
-
type: "input";
|
|
61
|
-
value: string;
|
|
62
|
-
id: string;
|
|
63
|
-
timestamp: number;
|
|
64
|
-
selector: string;
|
|
65
|
-
injectable: boolean;
|
|
66
|
-
}, {
|
|
67
|
-
type: "input";
|
|
68
|
-
value: string;
|
|
69
|
-
id: string;
|
|
70
|
-
timestamp: number;
|
|
71
|
-
selector: string;
|
|
72
|
-
injectable?: boolean | undefined;
|
|
73
|
-
}>, z.ZodObject<{
|
|
74
|
-
id: z.ZodString;
|
|
75
|
-
type: z.ZodLiteral<"keypress">;
|
|
76
|
-
key: z.ZodString;
|
|
77
|
-
modifiers: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
78
|
-
timestamp: z.ZodNumber;
|
|
79
|
-
}, "strip", z.ZodTypeAny, {
|
|
80
|
-
type: "keypress";
|
|
81
|
-
id: string;
|
|
82
|
-
timestamp: number;
|
|
83
|
-
key: string;
|
|
84
|
-
modifiers?: string[] | undefined;
|
|
85
|
-
}, {
|
|
86
|
-
type: "keypress";
|
|
87
|
-
id: string;
|
|
88
|
-
timestamp: number;
|
|
89
|
-
key: string;
|
|
90
|
-
modifiers?: string[] | undefined;
|
|
91
|
-
}>, z.ZodObject<{
|
|
92
|
-
id: z.ZodString;
|
|
93
|
-
type: z.ZodLiteral<"scroll">;
|
|
94
|
-
selector: z.ZodOptional<z.ZodString>;
|
|
95
|
-
position: z.ZodObject<{
|
|
96
|
-
x: z.ZodNumber;
|
|
97
|
-
y: z.ZodNumber;
|
|
98
|
-
}, "strip", z.ZodTypeAny, {
|
|
99
|
-
x: number;
|
|
100
|
-
y: number;
|
|
101
|
-
}, {
|
|
102
|
-
x: number;
|
|
103
|
-
y: number;
|
|
104
|
-
}>;
|
|
105
|
-
timestamp: z.ZodNumber;
|
|
106
|
-
}, "strip", z.ZodTypeAny, {
|
|
107
|
-
type: "scroll";
|
|
108
|
-
id: string;
|
|
109
|
-
timestamp: number;
|
|
110
|
-
position: {
|
|
111
|
-
x: number;
|
|
112
|
-
y: number;
|
|
113
|
-
};
|
|
114
|
-
selector?: string | undefined;
|
|
115
|
-
}, {
|
|
116
|
-
type: "scroll";
|
|
117
|
-
id: string;
|
|
118
|
-
timestamp: number;
|
|
119
|
-
position: {
|
|
120
|
-
x: number;
|
|
121
|
-
y: number;
|
|
122
|
-
};
|
|
123
|
-
selector?: string | undefined;
|
|
124
|
-
}>, z.ZodObject<{
|
|
125
|
-
id: z.ZodString;
|
|
126
|
-
type: z.ZodLiteral<"wait">;
|
|
127
|
-
duration: z.ZodNumber;
|
|
128
|
-
timestamp: z.ZodNumber;
|
|
129
|
-
}, "strip", z.ZodTypeAny, {
|
|
130
|
-
type: "wait";
|
|
131
|
-
id: string;
|
|
132
|
-
timestamp: number;
|
|
133
|
-
duration: number;
|
|
134
|
-
}, {
|
|
135
|
-
type: "wait";
|
|
136
|
-
id: string;
|
|
137
|
-
timestamp: number;
|
|
138
|
-
duration: number;
|
|
139
|
-
}>]>;
|
|
140
|
-
type Step = z.infer<typeof StepSchema>;
|
|
141
|
-
declare const SessionSchema: z.ZodObject<{
|
|
142
|
-
version: z.ZodDefault<z.ZodString>;
|
|
143
|
-
name: z.ZodString;
|
|
144
|
-
recordedAt: z.ZodString;
|
|
145
|
-
browser: z.ZodDefault<z.ZodEnum<["chromium", "firefox", "webkit"]>>;
|
|
146
|
-
viewport: z.ZodObject<{
|
|
147
|
-
width: z.ZodNumber;
|
|
148
|
-
height: z.ZodNumber;
|
|
149
|
-
}, "strip", z.ZodTypeAny, {
|
|
150
|
-
width: number;
|
|
151
|
-
height: number;
|
|
152
|
-
}, {
|
|
153
|
-
width: number;
|
|
154
|
-
height: number;
|
|
155
|
-
}>;
|
|
156
|
-
startUrl: z.ZodString;
|
|
157
|
-
steps: z.ZodArray<z.ZodDiscriminatedUnion<"type", [z.ZodObject<{
|
|
158
|
-
id: z.ZodString;
|
|
159
|
-
type: z.ZodLiteral<"navigate">;
|
|
160
|
-
url: z.ZodString;
|
|
161
|
-
timestamp: z.ZodNumber;
|
|
162
|
-
}, "strip", z.ZodTypeAny, {
|
|
163
|
-
type: "navigate";
|
|
164
|
-
id: string;
|
|
165
|
-
url: string;
|
|
166
|
-
timestamp: number;
|
|
167
|
-
}, {
|
|
168
|
-
type: "navigate";
|
|
169
|
-
id: string;
|
|
170
|
-
url: string;
|
|
171
|
-
timestamp: number;
|
|
172
|
-
}>, z.ZodObject<{
|
|
173
|
-
id: z.ZodString;
|
|
174
|
-
type: z.ZodLiteral<"click">;
|
|
175
|
-
selector: z.ZodString;
|
|
176
|
-
position: z.ZodOptional<z.ZodObject<{
|
|
177
|
-
x: z.ZodNumber;
|
|
178
|
-
y: z.ZodNumber;
|
|
179
|
-
}, "strip", z.ZodTypeAny, {
|
|
180
|
-
x: number;
|
|
181
|
-
y: number;
|
|
182
|
-
}, {
|
|
183
|
-
x: number;
|
|
184
|
-
y: number;
|
|
185
|
-
}>>;
|
|
186
|
-
timestamp: z.ZodNumber;
|
|
187
|
-
}, "strip", z.ZodTypeAny, {
|
|
188
|
-
type: "click";
|
|
189
|
-
id: string;
|
|
190
|
-
timestamp: number;
|
|
191
|
-
selector: string;
|
|
192
|
-
position?: {
|
|
193
|
-
x: number;
|
|
194
|
-
y: number;
|
|
195
|
-
} | undefined;
|
|
196
|
-
}, {
|
|
197
|
-
type: "click";
|
|
198
|
-
id: string;
|
|
199
|
-
timestamp: number;
|
|
200
|
-
selector: string;
|
|
201
|
-
position?: {
|
|
202
|
-
x: number;
|
|
203
|
-
y: number;
|
|
204
|
-
} | undefined;
|
|
205
|
-
}>, z.ZodObject<{
|
|
206
|
-
id: z.ZodString;
|
|
207
|
-
type: z.ZodLiteral<"input">;
|
|
208
|
-
selector: z.ZodString;
|
|
209
|
-
value: z.ZodString;
|
|
210
|
-
injectable: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
211
|
-
timestamp: z.ZodNumber;
|
|
212
|
-
}, "strip", z.ZodTypeAny, {
|
|
213
|
-
type: "input";
|
|
214
|
-
value: string;
|
|
215
|
-
id: string;
|
|
216
|
-
timestamp: number;
|
|
217
|
-
selector: string;
|
|
218
|
-
injectable: boolean;
|
|
219
|
-
}, {
|
|
220
|
-
type: "input";
|
|
221
|
-
value: string;
|
|
222
|
-
id: string;
|
|
223
|
-
timestamp: number;
|
|
224
|
-
selector: string;
|
|
225
|
-
injectable?: boolean | undefined;
|
|
226
|
-
}>, z.ZodObject<{
|
|
227
|
-
id: z.ZodString;
|
|
228
|
-
type: z.ZodLiteral<"keypress">;
|
|
229
|
-
key: z.ZodString;
|
|
230
|
-
modifiers: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
231
|
-
timestamp: z.ZodNumber;
|
|
232
|
-
}, "strip", z.ZodTypeAny, {
|
|
233
|
-
type: "keypress";
|
|
234
|
-
id: string;
|
|
235
|
-
timestamp: number;
|
|
236
|
-
key: string;
|
|
237
|
-
modifiers?: string[] | undefined;
|
|
238
|
-
}, {
|
|
239
|
-
type: "keypress";
|
|
240
|
-
id: string;
|
|
241
|
-
timestamp: number;
|
|
242
|
-
key: string;
|
|
243
|
-
modifiers?: string[] | undefined;
|
|
244
|
-
}>, z.ZodObject<{
|
|
245
|
-
id: z.ZodString;
|
|
246
|
-
type: z.ZodLiteral<"scroll">;
|
|
247
|
-
selector: z.ZodOptional<z.ZodString>;
|
|
248
|
-
position: z.ZodObject<{
|
|
249
|
-
x: z.ZodNumber;
|
|
250
|
-
y: z.ZodNumber;
|
|
251
|
-
}, "strip", z.ZodTypeAny, {
|
|
252
|
-
x: number;
|
|
253
|
-
y: number;
|
|
254
|
-
}, {
|
|
255
|
-
x: number;
|
|
256
|
-
y: number;
|
|
257
|
-
}>;
|
|
258
|
-
timestamp: z.ZodNumber;
|
|
259
|
-
}, "strip", z.ZodTypeAny, {
|
|
260
|
-
type: "scroll";
|
|
261
|
-
id: string;
|
|
262
|
-
timestamp: number;
|
|
263
|
-
position: {
|
|
264
|
-
x: number;
|
|
265
|
-
y: number;
|
|
266
|
-
};
|
|
267
|
-
selector?: string | undefined;
|
|
268
|
-
}, {
|
|
269
|
-
type: "scroll";
|
|
270
|
-
id: string;
|
|
271
|
-
timestamp: number;
|
|
272
|
-
position: {
|
|
273
|
-
x: number;
|
|
274
|
-
y: number;
|
|
275
|
-
};
|
|
276
|
-
selector?: string | undefined;
|
|
277
|
-
}>, z.ZodObject<{
|
|
278
|
-
id: z.ZodString;
|
|
279
|
-
type: z.ZodLiteral<"wait">;
|
|
280
|
-
duration: z.ZodNumber;
|
|
281
|
-
timestamp: z.ZodNumber;
|
|
282
|
-
}, "strip", z.ZodTypeAny, {
|
|
283
|
-
type: "wait";
|
|
284
|
-
id: string;
|
|
285
|
-
timestamp: number;
|
|
286
|
-
duration: number;
|
|
287
|
-
}, {
|
|
288
|
-
type: "wait";
|
|
289
|
-
id: string;
|
|
290
|
-
timestamp: number;
|
|
291
|
-
duration: number;
|
|
292
|
-
}>]>, "many">;
|
|
293
|
-
}, "strip", z.ZodTypeAny, {
|
|
294
|
-
version: string;
|
|
295
|
-
name: string;
|
|
296
|
-
recordedAt: string;
|
|
297
|
-
browser: "chromium" | "firefox" | "webkit";
|
|
298
|
-
viewport: {
|
|
299
|
-
width: number;
|
|
300
|
-
height: number;
|
|
301
|
-
};
|
|
302
|
-
startUrl: string;
|
|
303
|
-
steps: ({
|
|
304
|
-
type: "navigate";
|
|
305
|
-
id: string;
|
|
306
|
-
url: string;
|
|
307
|
-
timestamp: number;
|
|
308
|
-
} | {
|
|
309
|
-
type: "click";
|
|
310
|
-
id: string;
|
|
311
|
-
timestamp: number;
|
|
312
|
-
selector: string;
|
|
313
|
-
position?: {
|
|
314
|
-
x: number;
|
|
315
|
-
y: number;
|
|
316
|
-
} | undefined;
|
|
317
|
-
} | {
|
|
318
|
-
type: "input";
|
|
319
|
-
value: string;
|
|
320
|
-
id: string;
|
|
321
|
-
timestamp: number;
|
|
322
|
-
selector: string;
|
|
323
|
-
injectable: boolean;
|
|
324
|
-
} | {
|
|
325
|
-
type: "keypress";
|
|
326
|
-
id: string;
|
|
327
|
-
timestamp: number;
|
|
328
|
-
key: string;
|
|
329
|
-
modifiers?: string[] | undefined;
|
|
330
|
-
} | {
|
|
331
|
-
type: "scroll";
|
|
332
|
-
id: string;
|
|
333
|
-
timestamp: number;
|
|
334
|
-
position: {
|
|
335
|
-
x: number;
|
|
336
|
-
y: number;
|
|
337
|
-
};
|
|
338
|
-
selector?: string | undefined;
|
|
339
|
-
} | {
|
|
340
|
-
type: "wait";
|
|
341
|
-
id: string;
|
|
342
|
-
timestamp: number;
|
|
343
|
-
duration: number;
|
|
344
|
-
})[];
|
|
345
|
-
}, {
|
|
346
|
-
name: string;
|
|
347
|
-
recordedAt: string;
|
|
348
|
-
viewport: {
|
|
349
|
-
width: number;
|
|
350
|
-
height: number;
|
|
351
|
-
};
|
|
352
|
-
startUrl: string;
|
|
353
|
-
steps: ({
|
|
354
|
-
type: "navigate";
|
|
355
|
-
id: string;
|
|
356
|
-
url: string;
|
|
357
|
-
timestamp: number;
|
|
358
|
-
} | {
|
|
359
|
-
type: "click";
|
|
360
|
-
id: string;
|
|
361
|
-
timestamp: number;
|
|
362
|
-
selector: string;
|
|
363
|
-
position?: {
|
|
364
|
-
x: number;
|
|
365
|
-
y: number;
|
|
366
|
-
} | undefined;
|
|
367
|
-
} | {
|
|
368
|
-
type: "input";
|
|
369
|
-
value: string;
|
|
370
|
-
id: string;
|
|
371
|
-
timestamp: number;
|
|
372
|
-
selector: string;
|
|
373
|
-
injectable?: boolean | undefined;
|
|
374
|
-
} | {
|
|
375
|
-
type: "keypress";
|
|
376
|
-
id: string;
|
|
377
|
-
timestamp: number;
|
|
378
|
-
key: string;
|
|
379
|
-
modifiers?: string[] | undefined;
|
|
380
|
-
} | {
|
|
381
|
-
type: "scroll";
|
|
382
|
-
id: string;
|
|
383
|
-
timestamp: number;
|
|
384
|
-
position: {
|
|
385
|
-
x: number;
|
|
386
|
-
y: number;
|
|
387
|
-
};
|
|
388
|
-
selector?: string | undefined;
|
|
389
|
-
} | {
|
|
390
|
-
type: "wait";
|
|
391
|
-
id: string;
|
|
392
|
-
timestamp: number;
|
|
393
|
-
duration: number;
|
|
394
|
-
})[];
|
|
395
|
-
version?: string | undefined;
|
|
396
|
-
browser?: "chromium" | "firefox" | "webkit" | undefined;
|
|
397
|
-
}>;
|
|
398
|
-
type Session = z.infer<typeof SessionSchema>;
|
|
399
|
-
/**
|
|
400
|
-
* Create a new session object
|
|
401
|
-
*/
|
|
402
|
-
declare function createSession(options: {
|
|
403
|
-
name: string;
|
|
404
|
-
startUrl: string;
|
|
405
|
-
browser?: "chromium" | "firefox" | "webkit";
|
|
406
|
-
viewport?: {
|
|
407
|
-
width: number;
|
|
408
|
-
height: number;
|
|
409
|
-
};
|
|
410
|
-
}): Session;
|
|
411
|
-
/**
|
|
412
|
-
* Parse a session from YAML string
|
|
413
|
-
*/
|
|
414
|
-
declare function parseSession(yaml: string): Session;
|
|
415
|
-
/**
|
|
416
|
-
* Serialize a session to YAML string
|
|
417
|
-
*/
|
|
418
|
-
declare function serializeSession(session: Session): string;
|
|
419
|
-
|
|
420
3
|
/**
|
|
421
4
|
* Payload Types for Vulcn
|
|
422
5
|
* Core types used by the engine and plugins
|
|
@@ -464,20 +47,6 @@ interface CustomPayloadFile {
|
|
|
464
47
|
payloads: CustomPayload[];
|
|
465
48
|
}
|
|
466
49
|
|
|
467
|
-
type BrowserType = "chromium" | "firefox" | "webkit";
|
|
468
|
-
interface RecorderOptions {
|
|
469
|
-
browser?: BrowserType;
|
|
470
|
-
viewport?: {
|
|
471
|
-
width: number;
|
|
472
|
-
height: number;
|
|
473
|
-
};
|
|
474
|
-
headless?: boolean;
|
|
475
|
-
}
|
|
476
|
-
interface RunnerOptions {
|
|
477
|
-
browser?: BrowserType;
|
|
478
|
-
headless?: boolean;
|
|
479
|
-
onFinding?: (finding: Finding) => void;
|
|
480
|
-
}
|
|
481
50
|
interface Finding {
|
|
482
51
|
type: PayloadCategory;
|
|
483
52
|
severity: "critical" | "high" | "medium" | "low" | "info";
|
|
@@ -490,17 +59,14 @@ interface Finding {
|
|
|
490
59
|
/** Plugin-specific metadata */
|
|
491
60
|
metadata?: Record<string, unknown>;
|
|
492
61
|
}
|
|
493
|
-
interface RunResult {
|
|
494
|
-
findings: Finding[];
|
|
495
|
-
stepsExecuted: number;
|
|
496
|
-
payloadsTested: number;
|
|
497
|
-
duration: number;
|
|
498
|
-
errors: string[];
|
|
499
|
-
}
|
|
500
62
|
|
|
501
63
|
/**
|
|
502
64
|
* Vulcn Plugin System Types
|
|
503
65
|
* @module @vulcn/engine/plugin
|
|
66
|
+
*
|
|
67
|
+
* The plugin system is driver-agnostic. Detection plugins receive
|
|
68
|
+
* a generic page interface rather than Playwright types directly.
|
|
69
|
+
* This allows the same plugin to work across different driver types.
|
|
504
70
|
*/
|
|
505
71
|
|
|
506
72
|
/**
|
|
@@ -537,6 +103,10 @@ interface VulcnPlugin {
|
|
|
537
103
|
}
|
|
538
104
|
/**
|
|
539
105
|
* Plugin lifecycle hooks
|
|
106
|
+
*
|
|
107
|
+
* Detection hooks (onDialog, onConsoleMessage, etc.) receive
|
|
108
|
+
* Playwright types from the driver. Plugins that use these
|
|
109
|
+
* should declare playwright as a peer/dev dependency.
|
|
540
110
|
*/
|
|
541
111
|
interface PluginHooks {
|
|
542
112
|
/**
|
|
@@ -555,23 +125,23 @@ interface PluginHooks {
|
|
|
555
125
|
/** Called when recording ends, can transform session */
|
|
556
126
|
onRecordEnd?: (session: Session, ctx: RecordContext) => Promise<Session>;
|
|
557
127
|
/** Called when run starts */
|
|
558
|
-
onRunStart?: (ctx: RunContext) => Promise<void>;
|
|
128
|
+
onRunStart?: (ctx: RunContext$1) => Promise<void>;
|
|
559
129
|
/** Called before each payload is injected, can transform payload */
|
|
560
|
-
onBeforePayload?: (payload: string, step: Step, ctx: RunContext) => Promise<string>;
|
|
130
|
+
onBeforePayload?: (payload: string, step: Step, ctx: RunContext$1) => Promise<string>;
|
|
561
131
|
/** Called after payload injection, for detection */
|
|
562
132
|
onAfterPayload?: (ctx: DetectContext) => Promise<Finding[]>;
|
|
563
133
|
/** Called when run ends, can transform results */
|
|
564
|
-
onRunEnd?: (result: RunResult, ctx: RunContext) => Promise<RunResult>;
|
|
565
|
-
/** Called on page load/navigation */
|
|
566
|
-
onPageLoad?: (page: Page, ctx: DetectContext) => Promise<Finding[]>;
|
|
134
|
+
onRunEnd?: (result: RunResult, ctx: RunContext$1) => Promise<RunResult>;
|
|
567
135
|
/** Called when JavaScript alert/confirm/prompt appears */
|
|
568
|
-
onDialog?: (dialog:
|
|
136
|
+
onDialog?: (dialog: unknown, ctx: DetectContext) => Promise<Finding | null>;
|
|
569
137
|
/** Called on console.log/warn/error */
|
|
570
|
-
onConsoleMessage?: (msg:
|
|
138
|
+
onConsoleMessage?: (msg: unknown, ctx: DetectContext) => Promise<Finding | null>;
|
|
139
|
+
/** Called on page load/navigation */
|
|
140
|
+
onPageLoad?: (page: unknown, ctx: DetectContext) => Promise<Finding[]>;
|
|
571
141
|
/** Called on network request */
|
|
572
|
-
onNetworkRequest?: (request:
|
|
142
|
+
onNetworkRequest?: (request: unknown, ctx: DetectContext) => Promise<Finding | null>;
|
|
573
143
|
/** Called on network response */
|
|
574
|
-
onNetworkResponse?: (response:
|
|
144
|
+
onNetworkResponse?: (response: unknown, ctx: DetectContext) => Promise<Finding | null>;
|
|
575
145
|
}
|
|
576
146
|
/**
|
|
577
147
|
* Logger interface for plugins
|
|
@@ -610,30 +180,24 @@ interface PluginContext {
|
|
|
610
180
|
* Context for recording phase hooks
|
|
611
181
|
*/
|
|
612
182
|
interface RecordContext extends PluginContext {
|
|
613
|
-
/**
|
|
614
|
-
|
|
615
|
-
/** Browser type being used */
|
|
616
|
-
browser: BrowserType;
|
|
617
|
-
/** Playwright page instance */
|
|
618
|
-
page: Page;
|
|
183
|
+
/** Page interface (driver-specific, e.g. Playwright Page) */
|
|
184
|
+
page: unknown;
|
|
619
185
|
}
|
|
620
186
|
/**
|
|
621
187
|
* Context for running phase hooks
|
|
622
188
|
*/
|
|
623
|
-
interface RunContext extends PluginContext {
|
|
189
|
+
interface RunContext$1 extends PluginContext {
|
|
624
190
|
/** Session being executed */
|
|
625
191
|
session: Session;
|
|
626
|
-
/** Playwright
|
|
627
|
-
page:
|
|
628
|
-
/** Browser type being used */
|
|
629
|
-
browser: BrowserType;
|
|
192
|
+
/** Page interface (driver-specific, e.g. Playwright Page) */
|
|
193
|
+
page: unknown;
|
|
630
194
|
/** Whether running headless */
|
|
631
195
|
headless: boolean;
|
|
632
196
|
}
|
|
633
197
|
/**
|
|
634
198
|
* Context for detection hooks
|
|
635
199
|
*/
|
|
636
|
-
interface DetectContext extends RunContext {
|
|
200
|
+
interface DetectContext extends RunContext$1 {
|
|
637
201
|
/** Current step being tested */
|
|
638
202
|
step: Step;
|
|
639
203
|
/** Current payload set being tested */
|
|
@@ -664,7 +228,6 @@ interface VulcnConfig {
|
|
|
664
228
|
plugins?: PluginConfig[];
|
|
665
229
|
/** Global settings */
|
|
666
230
|
settings?: {
|
|
667
|
-
browser?: BrowserType;
|
|
668
231
|
headless?: boolean;
|
|
669
232
|
timeout?: number;
|
|
670
233
|
};
|
|
@@ -783,126 +346,257 @@ declare class PluginManager {
|
|
|
783
346
|
declare const pluginManager: PluginManager;
|
|
784
347
|
|
|
785
348
|
/**
|
|
786
|
-
*
|
|
787
|
-
*
|
|
349
|
+
* Vulcn Driver System
|
|
350
|
+
*
|
|
351
|
+
* Drivers handle recording and running sessions for different targets:
|
|
352
|
+
* - browser: Web applications (Playwright)
|
|
353
|
+
* - api: REST/HTTP APIs
|
|
354
|
+
* - cli: Command-line tools
|
|
355
|
+
*
|
|
356
|
+
* Each driver implements RecorderDriver and RunnerDriver interfaces.
|
|
788
357
|
*/
|
|
789
358
|
|
|
790
359
|
/**
|
|
791
|
-
*
|
|
360
|
+
* Current driver API version
|
|
361
|
+
*/
|
|
362
|
+
declare const DRIVER_API_VERSION = 1;
|
|
363
|
+
/**
|
|
364
|
+
* Generic step - drivers define their own step types
|
|
365
|
+
*/
|
|
366
|
+
interface Step {
|
|
367
|
+
/** Unique step ID */
|
|
368
|
+
id: string;
|
|
369
|
+
/** Step type (namespaced, e.g., "browser.click", "api.request") */
|
|
370
|
+
type: string;
|
|
371
|
+
/** Timestamp when step was recorded */
|
|
372
|
+
timestamp: number;
|
|
373
|
+
/** Step-specific data */
|
|
374
|
+
[key: string]: unknown;
|
|
375
|
+
}
|
|
376
|
+
/**
|
|
377
|
+
* Generic session format
|
|
378
|
+
*/
|
|
379
|
+
interface Session {
|
|
380
|
+
/** Session name */
|
|
381
|
+
name: string;
|
|
382
|
+
/** Driver that recorded this session */
|
|
383
|
+
driver: string;
|
|
384
|
+
/** Driver-specific configuration */
|
|
385
|
+
driverConfig: Record<string, unknown>;
|
|
386
|
+
/** Recorded steps */
|
|
387
|
+
steps: Step[];
|
|
388
|
+
/** Session metadata */
|
|
389
|
+
metadata?: {
|
|
390
|
+
recordedAt?: string;
|
|
391
|
+
version?: string;
|
|
392
|
+
[key: string]: unknown;
|
|
393
|
+
};
|
|
394
|
+
}
|
|
395
|
+
/**
|
|
396
|
+
* Running context passed to drivers
|
|
397
|
+
*/
|
|
398
|
+
interface RunContext {
|
|
399
|
+
/** Session being executed */
|
|
400
|
+
session: Session;
|
|
401
|
+
/** Plugin manager for calling hooks */
|
|
402
|
+
pluginManager: PluginManager;
|
|
403
|
+
/** Available payloads */
|
|
404
|
+
payloads: RuntimePayload[];
|
|
405
|
+
/** Collected findings */
|
|
406
|
+
findings: Finding[];
|
|
407
|
+
/** Add a finding */
|
|
408
|
+
addFinding(finding: Finding): void;
|
|
409
|
+
/** Logger */
|
|
410
|
+
logger: DriverLogger;
|
|
411
|
+
/** Running options */
|
|
412
|
+
options: RunOptions;
|
|
413
|
+
}
|
|
414
|
+
/**
|
|
415
|
+
* Options for recording
|
|
416
|
+
*/
|
|
417
|
+
interface RecordOptions {
|
|
418
|
+
/** Driver-specific options */
|
|
419
|
+
[key: string]: unknown;
|
|
420
|
+
}
|
|
421
|
+
/**
|
|
422
|
+
* Options for running
|
|
423
|
+
*/
|
|
424
|
+
interface RunOptions {
|
|
425
|
+
/** Run headless (for visual drivers) */
|
|
426
|
+
headless?: boolean;
|
|
427
|
+
/** Callback for findings */
|
|
428
|
+
onFinding?: (finding: Finding) => void;
|
|
429
|
+
/** Callback for step completion */
|
|
430
|
+
onStepComplete?: (stepId: string, payloadCount: number) => void;
|
|
431
|
+
/** Driver-specific options */
|
|
432
|
+
[key: string]: unknown;
|
|
433
|
+
}
|
|
434
|
+
/**
|
|
435
|
+
* Run result
|
|
436
|
+
*/
|
|
437
|
+
interface RunResult {
|
|
438
|
+
/** All findings */
|
|
439
|
+
findings: Finding[];
|
|
440
|
+
/** Steps executed */
|
|
441
|
+
stepsExecuted: number;
|
|
442
|
+
/** Payloads tested */
|
|
443
|
+
payloadsTested: number;
|
|
444
|
+
/** Duration in milliseconds */
|
|
445
|
+
duration: number;
|
|
446
|
+
/** Errors encountered */
|
|
447
|
+
errors: string[];
|
|
448
|
+
}
|
|
449
|
+
/**
|
|
450
|
+
* Driver logger
|
|
451
|
+
*/
|
|
452
|
+
interface DriverLogger {
|
|
453
|
+
debug(msg: string, ...args: unknown[]): void;
|
|
454
|
+
info(msg: string, ...args: unknown[]): void;
|
|
455
|
+
warn(msg: string, ...args: unknown[]): void;
|
|
456
|
+
error(msg: string, ...args: unknown[]): void;
|
|
457
|
+
}
|
|
458
|
+
/**
|
|
459
|
+
* Recorder Driver Interface
|
|
460
|
+
*
|
|
461
|
+
* Implement this to add recording support for a target type.
|
|
792
462
|
*/
|
|
793
|
-
interface
|
|
794
|
-
/**
|
|
795
|
-
|
|
463
|
+
interface RecorderDriver {
|
|
464
|
+
/** Start recording and return control handle */
|
|
465
|
+
start(config: Record<string, unknown>, options: RecordOptions): Promise<RecordingHandle>;
|
|
796
466
|
}
|
|
797
467
|
/**
|
|
798
|
-
*
|
|
468
|
+
* Handle returned by RecorderDriver.start()
|
|
799
469
|
*/
|
|
800
|
-
interface
|
|
470
|
+
interface RecordingHandle {
|
|
801
471
|
/** Stop recording and return the session */
|
|
802
472
|
stop(): Promise<Session>;
|
|
803
|
-
/**
|
|
473
|
+
/** Abort recording without saving */
|
|
474
|
+
abort(): Promise<void>;
|
|
475
|
+
/** Get current steps (during recording) */
|
|
804
476
|
getSteps(): Step[];
|
|
805
|
-
/**
|
|
806
|
-
|
|
477
|
+
/** Manually add a step */
|
|
478
|
+
addStep(step: Omit<Step, "id" | "timestamp">): void;
|
|
807
479
|
}
|
|
808
480
|
/**
|
|
809
|
-
*
|
|
481
|
+
* Runner Driver Interface
|
|
810
482
|
*
|
|
811
|
-
*
|
|
812
|
-
* - onRecordStart: Called when recording starts
|
|
813
|
-
* - onRecordStep: Called for each step, can transform
|
|
814
|
-
* - onRecordEnd: Called when recording ends, can transform session
|
|
483
|
+
* Implement this to add running/replay support for a target type.
|
|
815
484
|
*/
|
|
816
|
-
|
|
817
|
-
/**
|
|
818
|
-
|
|
819
|
-
* Opens a browser window for the user to interact with
|
|
820
|
-
*/
|
|
821
|
-
static start(startUrl: string, options?: RecorderOptions, config?: RecorderConfig): Promise<RecordingSession>;
|
|
822
|
-
/**
|
|
823
|
-
* Transform a step through plugin hooks
|
|
824
|
-
* Returns null if the step should be filtered out
|
|
825
|
-
*/
|
|
826
|
-
private static transformStep;
|
|
827
|
-
private static attachListeners;
|
|
828
|
-
private static injectRecordingScript;
|
|
485
|
+
interface RunnerDriver {
|
|
486
|
+
/** Execute a session with payloads */
|
|
487
|
+
execute(session: Session, ctx: RunContext): Promise<RunResult>;
|
|
829
488
|
}
|
|
830
|
-
|
|
831
489
|
/**
|
|
832
|
-
*
|
|
833
|
-
* v0.2.0: Plugin-based architecture for extensibility
|
|
490
|
+
* Complete driver definition
|
|
834
491
|
*/
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
492
|
+
interface VulcnDriver {
|
|
493
|
+
/** Unique driver name (e.g., "browser", "api", "cli") */
|
|
494
|
+
name: string;
|
|
495
|
+
/** Driver version */
|
|
496
|
+
version: string;
|
|
497
|
+
/** Driver API version */
|
|
498
|
+
apiVersion?: number;
|
|
499
|
+
/** Human-readable description */
|
|
500
|
+
description?: string;
|
|
501
|
+
/** Configuration schema (Zod) */
|
|
502
|
+
configSchema?: z.ZodSchema;
|
|
503
|
+
/** Step types this driver handles */
|
|
504
|
+
stepTypes: string[];
|
|
505
|
+
/** Recorder implementation */
|
|
506
|
+
recorder: RecorderDriver;
|
|
507
|
+
/** Runner implementation */
|
|
508
|
+
runner: RunnerDriver;
|
|
509
|
+
}
|
|
510
|
+
/**
|
|
511
|
+
* Driver source for loading
|
|
512
|
+
*/
|
|
513
|
+
type DriverSource = "npm" | "local" | "builtin";
|
|
514
|
+
/**
|
|
515
|
+
* Loaded driver with metadata
|
|
516
|
+
*/
|
|
517
|
+
interface LoadedDriver {
|
|
518
|
+
driver: VulcnDriver;
|
|
519
|
+
source: DriverSource;
|
|
839
520
|
}
|
|
521
|
+
|
|
840
522
|
/**
|
|
841
|
-
*
|
|
523
|
+
* Vulcn Driver Manager
|
|
842
524
|
*
|
|
843
|
-
*
|
|
844
|
-
*
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
525
|
+
* Handles driver loading, registration, and lifecycle.
|
|
526
|
+
* Drivers are loaded from npm packages or local files.
|
|
527
|
+
*/
|
|
528
|
+
|
|
529
|
+
/**
|
|
530
|
+
* Driver Manager - loads and manages recording/running drivers
|
|
848
531
|
*/
|
|
849
|
-
declare class
|
|
532
|
+
declare class DriverManager {
|
|
533
|
+
private drivers;
|
|
534
|
+
private defaultDriver;
|
|
850
535
|
/**
|
|
851
|
-
*
|
|
536
|
+
* Register a driver
|
|
537
|
+
*/
|
|
538
|
+
register(driver: VulcnDriver, source?: DriverSource): void;
|
|
539
|
+
/**
|
|
540
|
+
* Load a driver from npm or local path
|
|
541
|
+
*/
|
|
542
|
+
load(nameOrPath: string): Promise<void>;
|
|
543
|
+
/**
|
|
544
|
+
* Get a loaded driver by name
|
|
545
|
+
*/
|
|
546
|
+
get(name: string): VulcnDriver | undefined;
|
|
547
|
+
/**
|
|
548
|
+
* Get the default driver
|
|
549
|
+
*/
|
|
550
|
+
getDefault(): VulcnDriver | undefined;
|
|
551
|
+
/**
|
|
552
|
+
* Set the default driver
|
|
553
|
+
*/
|
|
554
|
+
setDefault(name: string): void;
|
|
555
|
+
/**
|
|
556
|
+
* Check if a driver is registered
|
|
557
|
+
*/
|
|
558
|
+
has(name: string): boolean;
|
|
559
|
+
/**
|
|
560
|
+
* Get all registered drivers
|
|
561
|
+
*/
|
|
562
|
+
list(): LoadedDriver[];
|
|
563
|
+
/**
|
|
564
|
+
* Get driver for a session
|
|
565
|
+
*/
|
|
566
|
+
getForSession(session: Session): VulcnDriver;
|
|
567
|
+
/**
|
|
568
|
+
* Parse a YAML session string into a Session object.
|
|
852
569
|
*
|
|
853
|
-
*
|
|
854
|
-
*
|
|
855
|
-
*
|
|
570
|
+
* Handles both new driver-format sessions and legacy v1 sessions.
|
|
571
|
+
* Legacy sessions (those with non-namespaced step types like "click",
|
|
572
|
+
* "input", "navigate") are automatically converted to the driver format
|
|
573
|
+
* (e.g., "browser.click", "browser.input", "browser.navigate").
|
|
574
|
+
*
|
|
575
|
+
* @param yaml - Raw YAML string
|
|
576
|
+
* @param defaultDriver - Driver to assign for legacy sessions (default: "browser")
|
|
856
577
|
*/
|
|
857
|
-
|
|
578
|
+
parseSession(yaml: string, defaultDriver?: string): Session;
|
|
858
579
|
/**
|
|
859
|
-
*
|
|
580
|
+
* Start recording with a driver
|
|
860
581
|
*/
|
|
861
|
-
|
|
582
|
+
startRecording(driverName: string, config: Record<string, unknown>, options?: RecordOptions): Promise<RecordingHandle>;
|
|
862
583
|
/**
|
|
863
|
-
*
|
|
584
|
+
* Execute a session
|
|
585
|
+
* Invokes plugin hooks (onRunStart, onRunEnd) around the driver runner.
|
|
864
586
|
*/
|
|
865
|
-
|
|
587
|
+
execute(session: Session, pluginManager: PluginManager, options?: RunOptions): Promise<RunResult>;
|
|
866
588
|
/**
|
|
867
|
-
*
|
|
589
|
+
* Validate driver structure
|
|
868
590
|
*/
|
|
869
|
-
private
|
|
591
|
+
private validateDriver;
|
|
870
592
|
/**
|
|
871
|
-
*
|
|
593
|
+
* Create a scoped logger for a driver
|
|
872
594
|
*/
|
|
873
|
-
private
|
|
874
|
-
}
|
|
875
|
-
|
|
876
|
-
interface LaunchOptions {
|
|
877
|
-
browser?: BrowserType;
|
|
878
|
-
headless?: boolean;
|
|
879
|
-
}
|
|
880
|
-
interface BrowserLaunchResult {
|
|
881
|
-
browser: Browser;
|
|
882
|
-
channel?: string;
|
|
883
|
-
}
|
|
884
|
-
declare class BrowserNotFoundError extends Error {
|
|
885
|
-
constructor(message: string);
|
|
595
|
+
private createLogger;
|
|
886
596
|
}
|
|
887
597
|
/**
|
|
888
|
-
*
|
|
889
|
-
* 1. Try system Chrome/Edge first (zero-install experience)
|
|
890
|
-
* 2. Fall back to Playwright's bundled browsers
|
|
891
|
-
*/
|
|
892
|
-
declare function launchBrowser(options?: LaunchOptions): Promise<BrowserLaunchResult>;
|
|
893
|
-
/**
|
|
894
|
-
* Install Playwright browsers
|
|
895
|
-
*/
|
|
896
|
-
declare function installBrowsers(browsers?: BrowserType[]): Promise<void>;
|
|
897
|
-
/**
|
|
898
|
-
* Check which browsers are available
|
|
598
|
+
* Default driver manager instance
|
|
899
599
|
*/
|
|
900
|
-
declare
|
|
901
|
-
systemChrome: boolean;
|
|
902
|
-
systemEdge: boolean;
|
|
903
|
-
playwrightChromium: boolean;
|
|
904
|
-
playwrightFirefox: boolean;
|
|
905
|
-
playwrightWebkit: boolean;
|
|
906
|
-
}>;
|
|
600
|
+
declare const driverManager: DriverManager;
|
|
907
601
|
|
|
908
|
-
export { type
|
|
602
|
+
export { type CustomPayload, type CustomPayloadFile, DRIVER_API_VERSION, type DetectContext, type DriverLogger, DriverManager, type DriverSource, type EngineInfo, type Finding, type LoadedDriver, type LoadedPlugin as LoadedPluginInfo, PLUGIN_API_VERSION, type PayloadCategory, type PayloadSource, type PluginConfig, type PluginContext, type PluginHooks, type PluginLogger, PluginManager, type RunContext$1 as PluginRunContext, type PluginSource, type RecordContext, type RecordOptions, type RecorderDriver, type RecordingHandle, type RunContext, type RunOptions, type RunResult, type RunnerDriver, type RuntimePayload, type Session, type Step, type VulcnConfig, type VulcnDriver, type VulcnPlugin, driverManager, pluginManager };
|