@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/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: Dialog, ctx: DetectContext) => Promise<Finding | null>;
136
+ onDialog?: (dialog: unknown, ctx: DetectContext) => Promise<Finding | null>;
569
137
  /** Called on console.log/warn/error */
570
- onConsoleMessage?: (msg: ConsoleMessage, ctx: DetectContext) => Promise<Finding | null>;
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: Request, ctx: DetectContext) => Promise<Finding | null>;
142
+ onNetworkRequest?: (request: unknown, ctx: DetectContext) => Promise<Finding | null>;
573
143
  /** Called on network response */
574
- onNetworkResponse?: (response: Response, ctx: DetectContext) => Promise<Finding | null>;
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
- /** Starting URL */
614
- startUrl: string;
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 page instance */
627
- page: 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
- * Recorder - captures browser interactions as a replayable session
787
- * v0.2.0: Plugin hooks for recording customization
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
- * Configuration for the recorder
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 RecorderConfig {
794
- /** Plugin manager to use (defaults to shared instance) */
795
- pluginManager?: PluginManager;
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
- * Active recording session handle
468
+ * Handle returned by RecorderDriver.start()
799
469
  */
800
- interface RecordingSession {
470
+ interface RecordingHandle {
801
471
  /** Stop recording and return the session */
802
472
  stop(): Promise<Session>;
803
- /** Get current recorded steps */
473
+ /** Abort recording without saving */
474
+ abort(): Promise<void>;
475
+ /** Get current steps (during recording) */
804
476
  getSteps(): Step[];
805
- /** Get the Playwright page (for advanced use) */
806
- getPage(): Page;
477
+ /** Manually add a step */
478
+ addStep(step: Omit<Step, "id" | "timestamp">): void;
807
479
  }
808
480
  /**
809
- * Recorder - captures browser interactions as a replayable session
481
+ * Runner Driver Interface
810
482
  *
811
- * Uses plugin hooks for:
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
- declare class Recorder {
817
- /**
818
- * Start a new recording session
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
- * Runner - replays sessions with security payloads
833
- * v0.2.0: Plugin-based architecture for extensibility
490
+ * Complete driver definition
834
491
  */
835
-
836
- interface RunnerConfig {
837
- /** Plugin manager to use (defaults to shared instance) */
838
- pluginManager?: PluginManager;
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
- * Runner - replays sessions with security payloads
523
+ * Vulcn Driver Manager
842
524
  *
843
- * Uses plugin hooks for:
844
- * - Payload loading (onInit)
845
- * - Payload transformation (onBeforePayload)
846
- * - Vulnerability detection (onAfterPayload, onDialog, onConsoleMessage, etc.)
847
- * - Results processing (onRunEnd)
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 Runner {
532
+ declare class DriverManager {
533
+ private drivers;
534
+ private defaultDriver;
850
535
  /**
851
- * Execute a session with security payloads from plugins
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
- * @param session - The recorded session to replay
854
- * @param options - Runner configuration
855
- * @param config - Plugin manager configuration
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
- static execute(session: Session, options?: RunnerOptions, config?: RunnerConfig): Promise<RunResult>;
578
+ parseSession(yaml: string, defaultDriver?: string): Session;
858
579
  /**
859
- * Execute with explicit payloads (legacy API, for backwards compatibility)
580
+ * Start recording with a driver
860
581
  */
861
- static executeWithPayloads(session: Session, payloads: RuntimePayload[], options?: RunnerOptions): Promise<RunResult>;
582
+ startRecording(driverName: string, config: Record<string, unknown>, options?: RecordOptions): Promise<RecordingHandle>;
862
583
  /**
863
- * Replay session steps with payload injected at target step
584
+ * Execute a session
585
+ * Invokes plugin hooks (onRunStart, onRunEnd) around the driver runner.
864
586
  */
865
- private static replayWithPayload;
587
+ execute(session: Session, pluginManager: PluginManager, options?: RunOptions): Promise<RunResult>;
866
588
  /**
867
- * Basic reflection check - fallback when no detection plugin is loaded
589
+ * Validate driver structure
868
590
  */
869
- private static checkReflection;
591
+ private validateDriver;
870
592
  /**
871
- * Determine severity based on vulnerability category
593
+ * Create a scoped logger for a driver
872
594
  */
873
- private static getSeverity;
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
- * Launch a browser with smart fallback:
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 function checkBrowsers(): Promise<{
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 BrowserLaunchResult, BrowserNotFoundError, type BrowserType, type CustomPayload, type CustomPayloadFile, type DetectContext, type EngineInfo, type Finding, type LaunchOptions, type LoadedPlugin, PLUGIN_API_VERSION, type PayloadCategory, type PayloadSource, type PluginConfig, type PluginContext, type PluginHooks, type PluginLogger, PluginManager, type PluginSource, type RecordContext, Recorder, type RecorderOptions, type RecordingSession, type RunContext, type RunResult, Runner, type RunnerOptions, type RuntimePayload, type Session, SessionSchema, type Step, StepSchema, type VulcnConfig, type VulcnPlugin, checkBrowsers, createSession, installBrowsers, launchBrowser, parseSession, pluginManager, serializeSession };
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 };