@veraxhq/verax 0.1.0 → 0.2.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.
Files changed (126) hide show
  1. package/README.md +123 -88
  2. package/bin/verax.js +11 -452
  3. package/package.json +14 -36
  4. package/src/cli/commands/default.js +523 -0
  5. package/src/cli/commands/doctor.js +165 -0
  6. package/src/cli/commands/inspect.js +109 -0
  7. package/src/cli/commands/run.js +402 -0
  8. package/src/cli/entry.js +196 -0
  9. package/src/cli/util/atomic-write.js +37 -0
  10. package/src/cli/util/detection-engine.js +296 -0
  11. package/src/cli/util/env-url.js +33 -0
  12. package/src/cli/util/errors.js +44 -0
  13. package/src/cli/util/events.js +34 -0
  14. package/src/cli/util/expectation-extractor.js +378 -0
  15. package/src/cli/util/findings-writer.js +31 -0
  16. package/src/cli/util/idgen.js +87 -0
  17. package/src/cli/util/learn-writer.js +39 -0
  18. package/src/cli/util/observation-engine.js +366 -0
  19. package/src/cli/util/observe-writer.js +25 -0
  20. package/src/cli/util/paths.js +29 -0
  21. package/src/cli/util/project-discovery.js +277 -0
  22. package/src/cli/util/project-writer.js +26 -0
  23. package/src/cli/util/redact.js +128 -0
  24. package/src/cli/util/run-id.js +30 -0
  25. package/src/cli/util/summary-writer.js +32 -0
  26. package/src/verax/cli/ci-summary.js +35 -0
  27. package/src/verax/cli/context-explanation.js +89 -0
  28. package/src/verax/cli/doctor.js +277 -0
  29. package/src/verax/cli/error-normalizer.js +154 -0
  30. package/src/verax/cli/explain-output.js +105 -0
  31. package/src/verax/cli/finding-explainer.js +130 -0
  32. package/src/verax/cli/init.js +237 -0
  33. package/src/verax/cli/run-overview.js +163 -0
  34. package/src/verax/cli/url-safety.js +101 -0
  35. package/src/verax/cli/wizard.js +98 -0
  36. package/src/verax/cli/zero-findings-explainer.js +57 -0
  37. package/src/verax/cli/zero-interaction-explainer.js +127 -0
  38. package/src/verax/core/action-classifier.js +86 -0
  39. package/src/verax/core/budget-engine.js +218 -0
  40. package/src/verax/core/canonical-outcomes.js +157 -0
  41. package/src/verax/core/decision-snapshot.js +335 -0
  42. package/src/verax/core/determinism-model.js +403 -0
  43. package/src/verax/core/incremental-store.js +237 -0
  44. package/src/verax/core/invariants.js +356 -0
  45. package/src/verax/core/promise-model.js +230 -0
  46. package/src/verax/core/replay-validator.js +350 -0
  47. package/src/verax/core/replay.js +222 -0
  48. package/src/verax/core/run-id.js +175 -0
  49. package/src/verax/core/run-manifest.js +99 -0
  50. package/src/verax/core/silence-impact.js +369 -0
  51. package/src/verax/core/silence-model.js +521 -0
  52. package/src/verax/detect/comparison.js +2 -34
  53. package/src/verax/detect/confidence-engine.js +764 -329
  54. package/src/verax/detect/detection-engine.js +293 -0
  55. package/src/verax/detect/evidence-index.js +177 -0
  56. package/src/verax/detect/expectation-model.js +194 -172
  57. package/src/verax/detect/explanation-helpers.js +187 -0
  58. package/src/verax/detect/finding-detector.js +450 -0
  59. package/src/verax/detect/findings-writer.js +44 -8
  60. package/src/verax/detect/flow-detector.js +366 -0
  61. package/src/verax/detect/index.js +172 -286
  62. package/src/verax/detect/interactive-findings.js +613 -0
  63. package/src/verax/detect/signal-mapper.js +308 -0
  64. package/src/verax/detect/verdict-engine.js +563 -0
  65. package/src/verax/evidence-index-writer.js +61 -0
  66. package/src/verax/index.js +90 -14
  67. package/src/verax/intel/effect-detector.js +368 -0
  68. package/src/verax/intel/handler-mapper.js +249 -0
  69. package/src/verax/intel/index.js +281 -0
  70. package/src/verax/intel/route-extractor.js +280 -0
  71. package/src/verax/intel/ts-program.js +256 -0
  72. package/src/verax/intel/vue-navigation-extractor.js +579 -0
  73. package/src/verax/intel/vue-router-extractor.js +323 -0
  74. package/src/verax/learn/action-contract-extractor.js +335 -101
  75. package/src/verax/learn/ast-contract-extractor.js +95 -5
  76. package/src/verax/learn/flow-extractor.js +172 -0
  77. package/src/verax/learn/manifest-writer.js +97 -47
  78. package/src/verax/learn/project-detector.js +40 -0
  79. package/src/verax/learn/route-extractor.js +27 -96
  80. package/src/verax/learn/state-extractor.js +212 -0
  81. package/src/verax/learn/static-extractor-navigation.js +114 -0
  82. package/src/verax/learn/static-extractor-validation.js +88 -0
  83. package/src/verax/learn/static-extractor.js +112 -4
  84. package/src/verax/learn/truth-assessor.js +24 -21
  85. package/src/verax/observe/aria-sensor.js +211 -0
  86. package/src/verax/observe/browser.js +10 -5
  87. package/src/verax/observe/console-sensor.js +1 -17
  88. package/src/verax/observe/domain-boundary.js +10 -1
  89. package/src/verax/observe/expectation-executor.js +512 -0
  90. package/src/verax/observe/flow-matcher.js +143 -0
  91. package/src/verax/observe/focus-sensor.js +196 -0
  92. package/src/verax/observe/human-driver.js +643 -275
  93. package/src/verax/observe/index.js +908 -27
  94. package/src/verax/observe/index.js.backup +1 -0
  95. package/src/verax/observe/interaction-discovery.js +365 -14
  96. package/src/verax/observe/interaction-runner.js +563 -198
  97. package/src/verax/observe/loading-sensor.js +139 -0
  98. package/src/verax/observe/navigation-sensor.js +255 -0
  99. package/src/verax/observe/network-sensor.js +55 -7
  100. package/src/verax/observe/observed-expectation-deriver.js +186 -0
  101. package/src/verax/observe/observed-expectation.js +305 -0
  102. package/src/verax/observe/page-frontier.js +234 -0
  103. package/src/verax/observe/settle.js +37 -17
  104. package/src/verax/observe/state-sensor.js +389 -0
  105. package/src/verax/observe/timing-sensor.js +228 -0
  106. package/src/verax/observe/traces-writer.js +61 -20
  107. package/src/verax/observe/ui-signal-sensor.js +136 -17
  108. package/src/verax/scan-summary-writer.js +77 -15
  109. package/src/verax/shared/artifact-manager.js +110 -8
  110. package/src/verax/shared/budget-profiles.js +136 -0
  111. package/src/verax/shared/ci-detection.js +39 -0
  112. package/src/verax/shared/config-loader.js +170 -0
  113. package/src/verax/shared/dynamic-route-utils.js +218 -0
  114. package/src/verax/shared/expectation-coverage.js +44 -0
  115. package/src/verax/shared/expectation-prover.js +81 -0
  116. package/src/verax/shared/expectation-tracker.js +201 -0
  117. package/src/verax/shared/expectations-writer.js +60 -0
  118. package/src/verax/shared/first-run.js +44 -0
  119. package/src/verax/shared/progress-reporter.js +171 -0
  120. package/src/verax/shared/retry-policy.js +14 -1
  121. package/src/verax/shared/root-artifacts.js +49 -0
  122. package/src/verax/shared/scan-budget.js +86 -0
  123. package/src/verax/shared/url-normalizer.js +162 -0
  124. package/src/verax/shared/zip-artifacts.js +65 -0
  125. package/src/verax/validate/context-validator.js +244 -0
  126. package/src/verax/validate/context-validator.js.bak +0 -0
package/bin/verax.js CHANGED
@@ -1,452 +1,11 @@
1
- #!/usr/bin/env node
2
-
3
- import { fileURLToPath } from 'url';
4
- import { dirname, resolve } from 'path';
5
- import { existsSync, readFileSync, writeFileSync, mkdirSync, appendFileSync } from 'fs';
6
- import inquirer from 'inquirer';
7
- import { learn } from '../src/verax/index.js';
8
- import { resolveWorkspaceRoot } from '../src/verax/resolve-workspace-root.js';
9
- import { initArtifactPaths, writeSummary, writeFindings, appendTrace } from '../src/verax/shared/artifact-manager.js';
10
- import { redactFinding, redactTrace } from '../src/verax/shared/redaction.js';
11
- import { initMetrics, recordMetric, getMetrics } from '../src/verax/shared/timing-metrics.js';
12
-
13
- const __filename = fileURLToPath(import.meta.url);
14
- const __dirname = dirname(__filename);
15
-
16
- async function main() {
17
- const args = process.argv.slice(2);
18
- const command = args[0];
19
-
20
- // Handle Wave 9 CLI commands
21
- if (command === 'scan') {
22
- await handleScan(args.slice(1));
23
- return;
24
- }
25
-
26
- if (command === 'flow') {
27
- await handleFlow(args.slice(1));
28
- return;
29
- }
30
-
31
- if (['--help', '-h', 'help'].includes(command)) {
32
- printHelp();
33
- process.exit(0);
34
- }
35
-
36
- // Default: interactive mode (existing behavior)
37
- console.log('VERAX\n');
38
-
39
- // Reuse parsed args from above for optional flags
40
- let projectDir = null;
41
- let url = null;
42
- let manifestPath = null;
43
-
44
- const projectDirIndex = args.indexOf('--project-dir');
45
- const projectDirArg = projectDirIndex !== -1 && args[projectDirIndex + 1] ? args[projectDirIndex + 1] : null;
46
-
47
- const urlIndex = args.indexOf('--url');
48
- if (urlIndex !== -1 && urlIndex + 1 < args.length) {
49
- url = args[urlIndex + 1];
50
- }
51
-
52
- const manifestIndex = args.indexOf('--manifest');
53
- if (manifestIndex !== -1 && manifestIndex + 1 < args.length) {
54
- manifestPath = resolve(args[manifestIndex + 1]);
55
- }
56
-
57
- // Resolve workspace root using the new function
58
- try {
59
- const resolved = resolveWorkspaceRoot(projectDirArg, process.cwd());
60
- projectDir = resolved.workspaceRoot;
61
-
62
- if (resolved.isRepoRoot) {
63
- console.error(
64
- 'VERAX: Refusing to write artifacts in repository root.\n' +
65
- 'Use --project-dir to specify the target project directory.'
66
- );
67
- process.exit(2);
68
- }
69
- } catch (error) {
70
- console.error(`Error: ${error.message}`);
71
- process.exit(2);
72
- }
73
-
74
- const actions = ['Scan my website'];
75
- let action;
76
-
77
- if (actions.length === 1) {
78
- action = actions[0];
79
- } else {
80
- const result = await inquirer.prompt([
81
- {
82
- type: 'list',
83
- name: 'action',
84
- message: 'What would you like to do?',
85
- choices: actions,
86
- default: actions[0]
87
- }
88
- ]);
89
- action = result.action;
90
- }
91
-
92
- if (action === 'Scan my website') {
93
- try {
94
- console.log('Understanding your website...');
95
- const manifest = await learn(projectDir);
96
-
97
- console.log(`\nProject type: ${manifest.projectType}`);
98
- console.log(`Total routes: ${manifest.routes.length}`);
99
- console.log(`Public routes: ${manifest.publicRoutes.length}`);
100
- console.log(`Internal routes: ${manifest.internalRoutes.length}`);
101
-
102
- if (url) {
103
- const { scan } = await import('../src/verax/index.js');
104
- const result = await scan(projectDir, url, manifestPath);
105
- const { observation, findings, scanSummary } = result;
106
-
107
- console.log('\nObserving real user interactions...');
108
- console.log('Comparing expectations with reality...');
109
-
110
- console.log('\nScan complete.\n');
111
- console.log(`Total interactions observed: ${observation.traces.length}`);
112
- console.log(`Silent failures detected: ${findings.findings.length}`);
113
-
114
- if (findings.findings.length > 0) {
115
- console.log(`\nFindings report: ${findings.findingsPath}\n`);
116
- } else {
117
- console.log('\nNo silent user failures were detected.');
118
- console.log(`\nFindings report: ${findings.findingsPath}\n`);
119
- }
120
-
121
- if (scanSummary) {
122
- const truth = scanSummary.truth;
123
- console.log('Truth Summary:');
124
- console.log(`- Learn: routes=${truth.learn.routesDiscovered} (confidence: ${truth.learn.routesConfidence}, source: ${truth.learn.routesSource}), expectations=${truth.learn.expectationsDiscovered} (strong=${truth.learn.expectationsStrong}, weak=${truth.learn.expectationsWeak})`);
125
- if (truth.learn.validation) {
126
- console.log(`- Learn validation: validated=${truth.learn.validation.routesValidated}, reachable=${truth.learn.validation.routesReachable}, unreachable=${truth.learn.validation.routesUnreachable}`);
127
- }
128
- const coverage = truth.observe.coverage;
129
- const coverageLine = coverage
130
- ? `Coverage: selected=${coverage.candidatesSelected}/${coverage.candidatesDiscovered} (cap=${coverage.cap})${coverage.capped ? ' — capped' : ''}`
131
- : null;
132
- console.log(`- Observe: interactions=${truth.observe.interactionsObserved}, external-blocked=${truth.observe.externalNavigationBlockedCount}, timeouts=${truth.observe.timeoutsCount}`);
133
- if (coverageLine) {
134
- console.log(` - ${coverageLine}`);
135
- }
136
- console.log(`- Detect: analyzed=${truth.detect.interactionsAnalyzed}, skipped(no expectation)=${truth.detect.interactionsSkippedNoExpectation}, findings=${truth.detect.findingsCount}`);
137
- if (truth.detect.skips && truth.detect.skips.total > 0) {
138
- const topReasons = truth.detect.skips.reasons.slice(0, 3).map(r => `${r.code}=${r.count}`).join(', ');
139
- console.log(`- Detect skips: ${truth.detect.skips.total} (top: ${topReasons})`);
140
- }
141
- console.log(`- Scan summary: ${scanSummary.summaryPath}\n`);
142
- }
143
- } else {
144
- console.log('\nNote: Provide --url to observe website interactions\n');
145
- }
146
-
147
- process.exit(0);
148
- } catch (error) {
149
- console.error(`\nError: ${error.message}`);
150
- if (error.stack && process.env.DEBUG) {
151
- console.error(error.stack);
152
- }
153
- process.exit(2);
154
- }
155
- }
156
- }
157
-
158
- /**
159
- * Parse command-line arguments into key-value object
160
- */
161
- function parseArgs(argArray) {
162
- const opts = {};
163
- for (let i = 0; i < argArray.length; i++) {
164
- if (argArray[i].startsWith('--')) {
165
- const key = argArray[i].substring(2);
166
- if (i + 1 < argArray.length && !argArray[i + 1].startsWith('--')) {
167
- opts[key] = argArray[i + 1];
168
- i++;
169
- } else {
170
- opts[key] = true;
171
- }
172
- }
173
- }
174
- return opts;
175
- }
176
-
177
- /**
178
- * Print help message
179
- */
180
- function printHelp() {
181
- console.log(`
182
- VERAX — Web Application Verification Platform
183
-
184
- Usage:
185
- verax [interactive] Interactive mode
186
- verax scan --url <url> [--projectRoot <path>] [--json] [--out <dir>]
187
- verax flow --flow <path> [--url <url>] [--json] [--out <dir>]
188
- verax --help Show this message
189
-
190
- Commands:
191
- scan Run full scan on a live URL
192
- flow Execute a user flow against a URL
193
-
194
- Options:
195
- --url <url> Target URL
196
- --flow <path> Path to flow definition file
197
- --projectRoot <p> Project root directory (defaults to cwd)
198
- --json Output machine-readable JSON
199
- --out <dir> Output directory (defaults to .verax/runs)
200
- --help, -h Show this help
201
-
202
- Exit Codes:
203
- 0 No HIGH findings
204
- 1 MEDIUM/LOW findings only
205
- 2 At least one HIGH finding
206
- 3 Fatal error
207
- `);
208
- }
209
-
210
- /**
211
- * Handle 'verax scan' command - integrated with main pipeline
212
- */
213
- async function handleScan(scanArgs) {
214
- const opts = parseArgs(scanArgs);
215
-
216
- if (!opts.url) {
217
- console.error('Error: --url is required');
218
- process.exit(3);
219
- }
220
-
221
- const projectRoot = opts.projectRoot || process.cwd();
222
- const url = opts.url;
223
- const jsonOutput = opts.json === true || opts.json === 'true';
224
- const outDir = opts.out;
225
-
226
- try {
227
- initMetrics();
228
- const startTime = Date.now();
229
-
230
- // Initialize artifact paths
231
- const artifactPaths = outDir
232
- ? { runDir: outDir, summary: `${outDir}/summary.json`, findings: `${outDir}/findings.json`, traces: `${outDir}/traces.jsonl` }
233
- : initArtifactPaths(projectRoot);
234
-
235
- // Ensure artifact directories exist
236
- mkdirSync(artifactPaths.runDir, { recursive: true });
237
-
238
- // Run the full VERAX pipeline using the scan() orchestrator
239
- console.error(`[VERAX] Starting scan for ${url}`);
240
- const resolvedRootResult = await resolveWorkspaceRoot(projectRoot);
241
- const resolvedRoot = resolvedRootResult.workspaceRoot;
242
-
243
- const scanStart = Date.now();
244
- const { scan } = await import('../src/verax/index.js');
245
- const result = await scan(resolvedRoot, url, null, artifactPaths.runId);
246
- recordMetric('totalMs', Date.now() - scanStart);
247
-
248
- const manifest = result.manifest;
249
- const observation = result.observation;
250
- const findings = result.findings;
251
-
252
- const metrics = getMetrics();
253
- metrics.totalMs = Date.now() - startTime;
254
-
255
- // Count findings by level
256
- const findingsList = findings?.findings || [];
257
- const findingsCounts = {
258
- HIGH: findingsList.filter(f => f.confidence?.level === 'HIGH').length,
259
- MEDIUM: findingsList.filter(f => f.confidence?.level === 'MEDIUM').length,
260
- LOW: findingsList.filter(f => f.confidence?.level === 'LOW').length,
261
- UNKNOWN: findingsList.filter(f => !f.confidence?.level || f.confidence?.level === 'UNKNOWN').length
262
- };
263
-
264
- // Get top findings
265
- const topFindings = findingsList
266
- .slice(0, 3)
267
- .map(f => ({
268
- type: f.type,
269
- reason: f.reason,
270
- confidence: f.confidence?.score || 0
271
- }));
272
-
273
- // Write summary with metrics to artifact paths
274
- writeSummary(artifactPaths, {
275
- url,
276
- projectRoot: resolvedRoot,
277
- metrics,
278
- findingsCounts,
279
- topFindings
280
- });
281
-
282
- // Determine exit code
283
- const HIGH_COUNT = findingsCounts.HIGH;
284
- const hasAny = Object.values(findingsCounts).reduce((a, b) => a + b, 0) > 0;
285
-
286
- if (jsonOutput) {
287
- const summary = {
288
- runId: artifactPaths.runId,
289
- url,
290
- metrics,
291
- findingsCounts,
292
- topFindings,
293
- total: findingsList.length
294
- };
295
- console.log(JSON.stringify(summary, null, 2));
296
- } else {
297
- console.error(`[VERAX] Scan complete in ${(metrics.totalMs / 1000).toFixed(2)}s`);
298
- console.error(`[VERAX] Findings: HIGH=${HIGH_COUNT}, MEDIUM=${findingsCounts.MEDIUM}, LOW=${findingsCounts.LOW}`);
299
- if (topFindings.length > 0) {
300
- console.error(`[VERAX] Top findings:`);
301
- topFindings.forEach(f => {
302
- console.error(` - [${f.confidence}%] ${f.type}: ${f.reason}`);
303
- });
304
- }
305
- }
306
-
307
- // Exit with appropriate code
308
- if (HIGH_COUNT > 0) {
309
- process.exit(2);
310
- } else if (hasAny) {
311
- process.exit(1);
312
- } else {
313
- process.exit(0);
314
- }
315
- } catch (error) {
316
- if (!jsonOutput) {
317
- console.error(`[VERAX] Scan failed: ${error.message}`);
318
- }
319
- process.exit(3);
320
- }
321
- }
322
-
323
- /**
324
- * Handle 'verax flow' command - execute a user flow
325
- */
326
- async function handleFlow(flowArgs) {
327
- const opts = parseArgs(flowArgs);
328
-
329
- if (!opts.flow) {
330
- console.error('Error: --flow is required');
331
- process.exit(3);
332
- }
333
-
334
- const flowPath = resolve(opts.flow);
335
- if (!existsSync(flowPath)) {
336
- console.error(`Error: Flow file not found: ${flowPath}`);
337
- process.exit(3);
338
- }
339
-
340
- const url = opts.url;
341
-
342
- const jsonOutput = opts.json === true || opts.json === 'true';
343
- const projectRoot = opts.projectRoot || process.cwd();
344
- const outDir = opts.out;
345
-
346
- try {
347
- initMetrics();
348
- const startTime = Date.now();
349
-
350
- // Initialize artifact paths
351
- const artifactPaths = outDir
352
- ? { runDir: outDir, flows: `${outDir}/flows` }
353
- : initArtifactPaths(projectRoot);
354
- mkdirSync(artifactPaths.runDir, { recursive: true });
355
- if (artifactPaths.flows) {
356
- mkdirSync(artifactPaths.flows, { recursive: true });
357
- }
358
-
359
- // Load and validate flow spec
360
- const { readFileSync } = await import('fs');
361
- const flowContent = readFileSync(flowPath, 'utf-8');
362
- const flowSpec = JSON.parse(flowContent);
363
-
364
- // Override baseUrl with --url if provided
365
- if (url) {
366
- flowSpec.baseUrl = url;
367
- }
368
-
369
- const { validateFlowSpec } = await import('../src/verax/flow/flow-spec.js');
370
- const validatedSpec = validateFlowSpec(flowSpec);
371
-
372
- // Use baseUrl from spec for navigation
373
- const targetUrl = validatedSpec.baseUrl;
374
-
375
- // Create browser and sensors
376
- const { createBrowser, navigateToUrl, closeBrowser } = await import('../src/verax/observe/browser.js');
377
- const { NetworkSensor } = await import('../src/verax/observe/network-sensor.js');
378
- const { ConsoleSensor } = await import('../src/verax/observe/console-sensor.js');
379
- const { UISignalSensor } = await import('../src/verax/observe/ui-signal-sensor.js');
380
-
381
- const { browser, page } = await createBrowser();
382
- const sensors = {
383
- network: new NetworkSensor(),
384
- console: new ConsoleSensor(),
385
- uiSignals: new UISignalSensor()
386
- };
387
-
388
- try {
389
- await navigateToUrl(page, targetUrl);
390
-
391
- // Execute flow
392
- const { executeFlow } = await import('../src/verax/flow/flow-engine.js');
393
- const flowResult = await executeFlow(page, validatedSpec, sensors);
394
-
395
- await closeBrowser(browser);
396
-
397
- recordMetric('totalMs', Date.now() - startTime);
398
- const metrics = getMetrics();
399
-
400
- // Write flow results
401
- const flowResultsPath = resolve(artifactPaths.flows || artifactPaths.runDir, 'flow-results.json');
402
- writeFileSync(flowResultsPath, JSON.stringify({
403
- flow: validatedSpec.name,
404
- url: targetUrl,
405
- success: flowResult.success,
406
- findings: flowResult.findings,
407
- stepResults: flowResult.stepResults,
408
- metrics
409
- }, null, 2) + '\n');
410
-
411
- if (jsonOutput) {
412
- console.log(JSON.stringify({
413
- flow: validatedSpec.name,
414
- url: targetUrl,
415
- success: flowResult.success,
416
- findingsCount: flowResult.findings.length,
417
- metrics
418
- }, null, 2));
419
- } else {
420
- console.error(`[VERAX] Flow execution complete in ${(metrics.totalMs / 1000).toFixed(2)}s`);
421
- console.error(`[VERAX] Flow: ${validatedSpec.name}`);
422
- console.error(`[VERAX] Success: ${flowResult.success}`);
423
- console.error(`[VERAX] Findings: ${flowResult.findings.length}`);
424
- if (flowResult.findings.length > 0) {
425
- flowResult.findings.forEach((f, i) => {
426
- console.error(` ${i + 1}. [Step ${f.stepIndex}] ${f.type}: ${f.reason}`);
427
- });
428
- }
429
- }
430
-
431
- // Exit code: 0 if success, 2 if findings, 3 if error
432
- if (!flowResult.success) {
433
- process.exit(2);
434
- } else {
435
- process.exit(0);
436
- }
437
- } catch (error) {
438
- await closeBrowser(browser);
439
- throw error;
440
- }
441
- } catch (error) {
442
- if (!jsonOutput) {
443
- console.error(`[VERAX] Flow execution failed: ${error.message}`);
444
- }
445
- process.exit(3);
446
- }
447
- }
448
-
449
- main().catch((error) => {
450
- console.error(`Fatal error: ${error.message}`);
451
- process.exit(2);
452
- });
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * VERAX CLI Shim
5
+ * Delegates to src/cli/entry.js
6
+ */
7
+
8
+ import('../src/cli/entry.js').catch((error) => {
9
+ console.error(`Failed to load CLI: ${error.message}`);
10
+ process.exit(2);
11
+ });
package/package.json CHANGED
@@ -1,57 +1,35 @@
1
1
  {
2
2
  "name": "@veraxhq/verax",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "VERAX - Silent failure detection for websites",
5
+ "license": "MIT",
5
6
  "type": "module",
6
- "main": "./src/verax/index.js",
7
7
  "bin": {
8
- "verax": "bin/verax.js"
8
+ "verax": "./bin/verax.js"
9
9
  },
10
10
  "files": [
11
- "bin",
12
- "src",
11
+ "bin/",
12
+ "src/",
13
+ "README.md",
13
14
  "LICENSE"
14
15
  ],
15
- "exports": {
16
- ".": {
17
- "import": "./src/verax/index.js"
18
- },
19
- "./learn": {
20
- "import": "./src/verax/learn/index.js"
21
- },
22
- "./observe": {
23
- "import": "./src/verax/observe/index.js"
24
- },
25
- "./detect": {
26
- "import": "./src/verax/detect/index.js"
27
- }
28
- },
29
- "publishConfig": {
30
- "access": "public"
31
- },
32
16
  "scripts": {
33
- "test": "node --test test/learn.test.js test/observe.test.js test/detect.test.js test/static-learn.test.js test/static-detect.test.js test/observe-boundary.test.js test/static-buttons-detect.test.js test/spa-support.test.js test/scan-summary.test.js test/route-validation.test.js test/skip-reasons.test.js test/observe-stabilization.test.js test/observe-coverage.test.js test/ast-extraction.test.js test/spa-ast-integration.test.js test/wave2-human-driver.test.js test/wave4-confidence.test.js test/wave5-action-contracts.test.js test/wave6-action-contracts.test.js test/wave7-auth-flows.test.js test/wave8-state-contracts.test.js test/wave9-hardening.test.js test/wave10-ci-summary.test.js test/cli-scan.test.js test/final-gate.test.js"
17
+ "test": "node --test",
18
+ "test:pack": "node scripts/test-pack.js"
34
19
  },
35
20
  "dependencies": {
36
- "@babel/generator": "^7.28.5",
37
- "@babel/parser": "^7.28.5",
38
- "@babel/traverse": "^7.28.5",
39
- "@babel/types": "^7.28.5",
40
21
  "glob": "^10.3.10",
41
22
  "inquirer": "^9.2.15",
42
23
  "node-html-parser": "^7.0.1",
43
24
  "playwright": "^1.40.0",
44
- "typescript": "^5.4.0"
25
+ "typescript": "^5.9.3"
45
26
  },
46
27
  "engines": {
47
28
  "node": ">=18.0.0"
48
29
  },
49
- "keywords": [
50
- "testing",
51
- "qa",
52
- "website",
53
- "silent-failures",
54
- "verification"
55
- ],
56
- "license": "MIT"
30
+ "devDependencies": {
31
+ "@babel/parser": "^7.28.5",
32
+ "@babel/traverse": "^7.28.5",
33
+ "@veraxhq/verax": "file:veraxhq-verax-0.2.0.tgz"
34
+ }
57
35
  }