@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
@@ -0,0 +1,323 @@
1
+ /**
2
+ * CODE INTELLIGENCE v1 — Vue Router Route Extraction (AST-based)
3
+ *
4
+ * Extracts routes from Vue Router configuration using AST analysis.
5
+ * Includes dynamic routes with example paths.
6
+ *
7
+ * Supported patterns:
8
+ * - createRouter({ routes: [...] })
9
+ * - const routes = [...]
10
+ * - export const routes = [...]
11
+ * - export default { routes: [...] }
12
+ * - Dynamic routes: /users/:id → /users/1
13
+ */
14
+
15
+ import ts from 'typescript';
16
+ import { resolve } from 'path';
17
+ import { existsSync, readFileSync } from 'fs';
18
+ import { parseFile, findNodes, getStringLiteral, getNodeLocation } from './ts-program.js';
19
+ import { normalizeDynamicRoute } from '../shared/dynamic-route-utils.js';
20
+
21
+ const INTERNAL_PATH_PATTERNS = [
22
+ /^\/admin/,
23
+ /^\/dashboard/,
24
+ /^\/account/,
25
+ /^\/settings/,
26
+ /\/internal/,
27
+ /\/private/
28
+ ];
29
+
30
+ function isInternalRoute(path) {
31
+ return INTERNAL_PATH_PATTERNS.some(pattern => pattern.test(path));
32
+ }
33
+
34
+ /**
35
+ * Extract routes from Vue Router configuration.
36
+ *
37
+ * @param {string} projectRoot - Project root
38
+ * @param {Object} program - TypeScript program
39
+ * @returns {Array} - Array of route objects with sourceRef
40
+ */
41
+ export function extractVueRoutes(projectRoot, program) {
42
+ const routes = [];
43
+
44
+ if (!program || !program.program) return routes;
45
+
46
+ // Look for router files in common locations
47
+ const routerFilePatterns = [
48
+ 'src/router/index.ts',
49
+ 'src/router/index.js',
50
+ 'src/router.ts',
51
+ 'src/router.js',
52
+ 'router/index.ts',
53
+ 'router/index.js',
54
+ 'router.ts',
55
+ 'router.js'
56
+ ];
57
+
58
+ let routerFiles = [];
59
+
60
+ // First, try to find router files by pattern
61
+ for (const pattern of routerFilePatterns) {
62
+ const filePath = resolve(projectRoot, pattern);
63
+ if (existsSync(filePath)) {
64
+ routerFiles.push(filePath);
65
+ }
66
+ }
67
+
68
+ // If no router files found by pattern, search in source files
69
+ if (routerFiles.length === 0 && program.sourceFiles) {
70
+ for (const sourceFile of program.sourceFiles) {
71
+ // sourceFiles is an array of file paths (strings) from createTSProgram
72
+ const filePath = typeof sourceFile === 'string' ? sourceFile : sourceFile.fileName;
73
+ try {
74
+ const content = readFileSync(filePath, 'utf-8');
75
+ if (content.includes('createRouter') ||
76
+ content.includes('routes:') ||
77
+ content.includes('const routes') ||
78
+ content.includes('export const routes')) {
79
+ routerFiles.push(filePath);
80
+ }
81
+ } catch (err) {
82
+ // Skip if file can't be read
83
+ }
84
+ }
85
+ }
86
+
87
+ // Extract routes from each router file
88
+ for (const filePath of routerFiles) {
89
+ const ast = parseFile(filePath, true);
90
+ if (!ast) continue;
91
+
92
+ const fileRoutes = extractRoutesFromAST(ast, projectRoot);
93
+ routes.push(...fileRoutes);
94
+ }
95
+
96
+ // Deduplicate by path
97
+ const seen = new Set();
98
+ const uniqueRoutes = [];
99
+ for (const route of routes) {
100
+ const key = route.path;
101
+ if (!seen.has(key)) {
102
+ seen.add(key);
103
+ uniqueRoutes.push(route);
104
+ }
105
+ }
106
+
107
+ return uniqueRoutes;
108
+ }
109
+
110
+ /**
111
+ * Extract routes from AST.
112
+ *
113
+ * @param {ts.SourceFile} ast - Parsed source file
114
+ * @param {string} projectRoot - Project root
115
+ * @returns {Array} - Route objects
116
+ */
117
+ function extractRoutesFromAST(ast, projectRoot) {
118
+ const routes = [];
119
+
120
+ // Find route array definitions
121
+ const routeArrays = findRouteArrays(ast);
122
+
123
+ for (const routeArray of routeArrays) {
124
+ const extracted = extractRoutesFromArray(routeArray, ast, projectRoot, '');
125
+ routes.push(...extracted);
126
+ }
127
+
128
+ return routes;
129
+ }
130
+
131
+ /**
132
+ * Find route array definitions in AST.
133
+ *
134
+ * @param {ts.SourceFile} ast - Source file
135
+ * @returns {Array} - Array literal nodes
136
+ */
137
+ function findRouteArrays(ast) {
138
+ const arrays = [];
139
+
140
+ // Pattern 1: createRouter({ routes: [...] })
141
+ const createRouterCalls = findNodes(ast, node => {
142
+ if (!ts.isCallExpression(node)) return false;
143
+ const expr = node.expression;
144
+ if (!ts.isIdentifier(expr)) return false;
145
+ return expr.text === 'createRouter';
146
+ });
147
+
148
+ for (const call of createRouterCalls) {
149
+ if (call.arguments.length === 0) continue;
150
+ const arg = call.arguments[0];
151
+ if (!ts.isObjectLiteralExpression(arg)) continue;
152
+
153
+ for (const prop of arg.properties) {
154
+ if (!ts.isPropertyAssignment(prop)) continue;
155
+ const name = prop.name;
156
+ if (!ts.isIdentifier(name)) continue;
157
+ if (name.text !== 'routes') continue;
158
+
159
+ const init = prop.initializer;
160
+ if (ts.isArrayLiteralExpression(init)) {
161
+ arrays.push(init);
162
+ }
163
+ }
164
+ }
165
+
166
+ // Pattern 2: const routes = [...] or export const routes = [...]
167
+ const routeVariables = findNodes(ast, node => {
168
+ if (!ts.isVariableDeclaration(node)) return false;
169
+ if (!ts.isIdentifier(node.name)) return false;
170
+ return node.name.text === 'routes';
171
+ });
172
+
173
+ for (const decl of routeVariables) {
174
+ if (decl.initializer && ts.isArrayLiteralExpression(decl.initializer)) {
175
+ arrays.push(decl.initializer);
176
+ }
177
+ }
178
+
179
+ // Pattern 3: export default { routes: [...] }
180
+ const defaultExports = findNodes(ast, node => {
181
+ if (!ts.isExportAssignment(node)) return false;
182
+ return node.isExportEquals === false;
183
+ });
184
+
185
+ for (const exportNode of defaultExports) {
186
+ const expr = exportNode.expression;
187
+ if (!ts.isObjectLiteralExpression(expr)) continue;
188
+
189
+ for (const prop of expr.properties) {
190
+ if (!ts.isPropertyAssignment(prop)) continue;
191
+ const name = prop.name;
192
+ if (!ts.isIdentifier(name)) continue;
193
+ if (name.text !== 'routes') continue;
194
+
195
+ const init = prop.initializer;
196
+ if (ts.isArrayLiteralExpression(init)) {
197
+ arrays.push(init);
198
+ }
199
+ }
200
+ }
201
+
202
+ return arrays;
203
+ }
204
+
205
+ /**
206
+ * Extract routes from array literal.
207
+ *
208
+ * @param {ts.ArrayLiteralExpression} arrayNode - Array literal node
209
+ * @param {ts.SourceFile} ast - Source file
210
+ * @param {string} projectRoot - Project root
211
+ * @param {string} parentPath - Parent route path for nested routes
212
+ * @returns {Array} - Route objects
213
+ */
214
+ function extractRoutesFromArray(arrayNode, ast, projectRoot, parentPath) {
215
+ const routes = [];
216
+
217
+ for (const element of arrayNode.elements) {
218
+ if (!ts.isObjectLiteralExpression(element)) continue;
219
+
220
+ const routeObj = extractRouteFromObject(element, ast, projectRoot, parentPath);
221
+ if (routeObj) {
222
+ routes.push(routeObj);
223
+
224
+ // Handle nested children
225
+ if (routeObj.children) {
226
+ for (const child of routeObj.children) {
227
+ routes.push(child);
228
+ }
229
+ delete routeObj.children;
230
+ }
231
+ }
232
+ }
233
+
234
+ return routes;
235
+ }
236
+
237
+ /**
238
+ * Extract route from object literal.
239
+ *
240
+ * @param {ts.ObjectLiteralExpression} objNode - Object literal node
241
+ * @param {ts.SourceFile} ast - Source file
242
+ * @param {string} projectRoot - Project root
243
+ * @param {string} parentPath - Parent route path
244
+ * @returns {Object|null} - Route object or null
245
+ */
246
+ function extractRouteFromObject(objNode, ast, projectRoot, parentPath) {
247
+ let path = null;
248
+ let children = null;
249
+
250
+ for (const prop of objNode.properties) {
251
+ if (!ts.isPropertyAssignment(prop)) continue;
252
+ const name = prop.name;
253
+ if (!ts.isIdentifier(name)) continue;
254
+
255
+ if (name.text === 'path') {
256
+ const pathValue = getStringLiteral(prop.initializer);
257
+ if (pathValue) {
258
+ path = pathValue;
259
+ }
260
+ } else if (name.text === 'children') {
261
+ const init = prop.initializer;
262
+ if (ts.isArrayLiteralExpression(init)) {
263
+ children = init;
264
+ }
265
+ }
266
+ }
267
+
268
+ // Skip if path is wildcard
269
+ if (!path || path.includes('*')) {
270
+ return null;
271
+ }
272
+
273
+ // Build full path
274
+ let fullPath = path;
275
+ if (parentPath) {
276
+ if (path.startsWith('/')) {
277
+ fullPath = path;
278
+ } else {
279
+ // Relative path: join parent + child
280
+ const parentNormalized = parentPath.endsWith('/') ? parentPath.slice(0, -1) : parentPath;
281
+ fullPath = `${parentNormalized}/${path}`.replace(/\/+/g, '/');
282
+ }
283
+ }
284
+
285
+ // Normalize dynamic routes to example paths
286
+ const normalized = normalizeDynamicRoute(fullPath);
287
+ const location = getNodeLocation(ast, objNode, projectRoot);
288
+
289
+ let route;
290
+ if (normalized) {
291
+ // Dynamic route - use example path
292
+ route = {
293
+ path: normalized.examplePath,
294
+ originalPattern: normalized.originalPattern,
295
+ isDynamic: true,
296
+ exampleExecution: true,
297
+ sourceRef: location.sourceRef,
298
+ file: location.file,
299
+ line: location.line,
300
+ framework: 'vue-router',
301
+ public: !isInternalRoute(normalized.examplePath)
302
+ };
303
+ } else {
304
+ // Static route
305
+ route = {
306
+ path: fullPath,
307
+ sourceRef: location.sourceRef,
308
+ file: location.file,
309
+ line: location.line,
310
+ framework: 'vue-router',
311
+ public: !isInternalRoute(fullPath)
312
+ };
313
+ }
314
+
315
+ // Extract nested children
316
+ if (children) {
317
+ const parentPathForChildren = normalized ? normalized.examplePath : fullPath;
318
+ const childRoutes = extractRoutesFromArray(children, ast, projectRoot, parentPathForChildren);
319
+ route.children = childRoutes;
320
+ }
321
+
322
+ return route;
323
+ }