@veraxhq/verax 0.1.0 → 0.2.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.
Files changed (135) hide show
  1. package/README.md +123 -88
  2. package/bin/verax.js +11 -452
  3. package/package.json +24 -36
  4. package/src/cli/commands/default.js +681 -0
  5. package/src/cli/commands/doctor.js +197 -0
  6. package/src/cli/commands/inspect.js +109 -0
  7. package/src/cli/commands/run.js +586 -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 +297 -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 +110 -0
  14. package/src/cli/util/expectation-extractor.js +388 -0
  15. package/src/cli/util/findings-writer.js +32 -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 +412 -0
  19. package/src/cli/util/observe-writer.js +25 -0
  20. package/src/cli/util/paths.js +30 -0
  21. package/src/cli/util/project-discovery.js +297 -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/runtime-budget.js +147 -0
  26. package/src/cli/util/summary-writer.js +43 -0
  27. package/src/types/global.d.ts +28 -0
  28. package/src/types/ts-ast.d.ts +24 -0
  29. package/src/verax/cli/ci-summary.js +35 -0
  30. package/src/verax/cli/context-explanation.js +89 -0
  31. package/src/verax/cli/doctor.js +277 -0
  32. package/src/verax/cli/error-normalizer.js +154 -0
  33. package/src/verax/cli/explain-output.js +105 -0
  34. package/src/verax/cli/finding-explainer.js +130 -0
  35. package/src/verax/cli/init.js +237 -0
  36. package/src/verax/cli/run-overview.js +163 -0
  37. package/src/verax/cli/url-safety.js +111 -0
  38. package/src/verax/cli/wizard.js +109 -0
  39. package/src/verax/cli/zero-findings-explainer.js +57 -0
  40. package/src/verax/cli/zero-interaction-explainer.js +127 -0
  41. package/src/verax/core/action-classifier.js +86 -0
  42. package/src/verax/core/budget-engine.js +218 -0
  43. package/src/verax/core/canonical-outcomes.js +157 -0
  44. package/src/verax/core/decision-snapshot.js +335 -0
  45. package/src/verax/core/determinism-model.js +432 -0
  46. package/src/verax/core/incremental-store.js +245 -0
  47. package/src/verax/core/invariants.js +356 -0
  48. package/src/verax/core/promise-model.js +230 -0
  49. package/src/verax/core/replay-validator.js +350 -0
  50. package/src/verax/core/replay.js +222 -0
  51. package/src/verax/core/run-id.js +175 -0
  52. package/src/verax/core/run-manifest.js +99 -0
  53. package/src/verax/core/silence-impact.js +369 -0
  54. package/src/verax/core/silence-model.js +523 -0
  55. package/src/verax/detect/comparison.js +7 -34
  56. package/src/verax/detect/confidence-engine.js +764 -329
  57. package/src/verax/detect/detection-engine.js +293 -0
  58. package/src/verax/detect/evidence-index.js +127 -0
  59. package/src/verax/detect/expectation-model.js +241 -168
  60. package/src/verax/detect/explanation-helpers.js +187 -0
  61. package/src/verax/detect/finding-detector.js +450 -0
  62. package/src/verax/detect/findings-writer.js +41 -12
  63. package/src/verax/detect/flow-detector.js +366 -0
  64. package/src/verax/detect/index.js +200 -288
  65. package/src/verax/detect/interactive-findings.js +612 -0
  66. package/src/verax/detect/signal-mapper.js +308 -0
  67. package/src/verax/detect/skip-classifier.js +4 -4
  68. package/src/verax/detect/verdict-engine.js +561 -0
  69. package/src/verax/evidence-index-writer.js +61 -0
  70. package/src/verax/flow/flow-engine.js +3 -2
  71. package/src/verax/flow/flow-spec.js +1 -2
  72. package/src/verax/index.js +103 -15
  73. package/src/verax/intel/effect-detector.js +368 -0
  74. package/src/verax/intel/handler-mapper.js +249 -0
  75. package/src/verax/intel/index.js +281 -0
  76. package/src/verax/intel/route-extractor.js +280 -0
  77. package/src/verax/intel/ts-program.js +256 -0
  78. package/src/verax/intel/vue-navigation-extractor.js +642 -0
  79. package/src/verax/intel/vue-router-extractor.js +325 -0
  80. package/src/verax/learn/action-contract-extractor.js +338 -104
  81. package/src/verax/learn/ast-contract-extractor.js +148 -6
  82. package/src/verax/learn/flow-extractor.js +172 -0
  83. package/src/verax/learn/index.js +36 -2
  84. package/src/verax/learn/manifest-writer.js +122 -58
  85. package/src/verax/learn/project-detector.js +40 -0
  86. package/src/verax/learn/route-extractor.js +28 -97
  87. package/src/verax/learn/route-validator.js +8 -7
  88. package/src/verax/learn/state-extractor.js +212 -0
  89. package/src/verax/learn/static-extractor-navigation.js +114 -0
  90. package/src/verax/learn/static-extractor-validation.js +88 -0
  91. package/src/verax/learn/static-extractor.js +119 -10
  92. package/src/verax/learn/truth-assessor.js +24 -21
  93. package/src/verax/learn/ts-contract-resolver.js +14 -12
  94. package/src/verax/observe/aria-sensor.js +211 -0
  95. package/src/verax/observe/browser.js +30 -6
  96. package/src/verax/observe/console-sensor.js +2 -18
  97. package/src/verax/observe/domain-boundary.js +10 -1
  98. package/src/verax/observe/expectation-executor.js +513 -0
  99. package/src/verax/observe/flow-matcher.js +143 -0
  100. package/src/verax/observe/focus-sensor.js +196 -0
  101. package/src/verax/observe/human-driver.js +660 -273
  102. package/src/verax/observe/index.js +910 -26
  103. package/src/verax/observe/interaction-discovery.js +378 -15
  104. package/src/verax/observe/interaction-runner.js +562 -197
  105. package/src/verax/observe/loading-sensor.js +145 -0
  106. package/src/verax/observe/navigation-sensor.js +255 -0
  107. package/src/verax/observe/network-sensor.js +55 -7
  108. package/src/verax/observe/observed-expectation-deriver.js +186 -0
  109. package/src/verax/observe/observed-expectation.js +305 -0
  110. package/src/verax/observe/page-frontier.js +234 -0
  111. package/src/verax/observe/settle.js +38 -17
  112. package/src/verax/observe/state-sensor.js +393 -0
  113. package/src/verax/observe/state-ui-sensor.js +7 -1
  114. package/src/verax/observe/timing-sensor.js +228 -0
  115. package/src/verax/observe/traces-writer.js +73 -21
  116. package/src/verax/observe/ui-signal-sensor.js +143 -17
  117. package/src/verax/scan-summary-writer.js +80 -15
  118. package/src/verax/shared/artifact-manager.js +111 -9
  119. package/src/verax/shared/budget-profiles.js +136 -0
  120. package/src/verax/shared/caching.js +1 -1
  121. package/src/verax/shared/ci-detection.js +39 -0
  122. package/src/verax/shared/config-loader.js +169 -0
  123. package/src/verax/shared/dynamic-route-utils.js +224 -0
  124. package/src/verax/shared/expectation-coverage.js +44 -0
  125. package/src/verax/shared/expectation-prover.js +81 -0
  126. package/src/verax/shared/expectation-tracker.js +201 -0
  127. package/src/verax/shared/expectations-writer.js +60 -0
  128. package/src/verax/shared/first-run.js +44 -0
  129. package/src/verax/shared/progress-reporter.js +171 -0
  130. package/src/verax/shared/retry-policy.js +9 -1
  131. package/src/verax/shared/root-artifacts.js +49 -0
  132. package/src/verax/shared/scan-budget.js +86 -0
  133. package/src/verax/shared/url-normalizer.js +162 -0
  134. package/src/verax/shared/zip-artifacts.js +66 -0
  135. package/src/verax/validate/context-validator.js +244 -0
@@ -0,0 +1,325 @@
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
+ children: null // Will be set below if children exist
303
+ };
304
+ } else {
305
+ // Static route
306
+ route = {
307
+ path: fullPath,
308
+ sourceRef: location.sourceRef,
309
+ file: location.file,
310
+ line: location.line,
311
+ framework: 'vue-router',
312
+ public: !isInternalRoute(fullPath),
313
+ children: null // Will be set below if children exist
314
+ };
315
+ }
316
+
317
+ // Extract nested children
318
+ if (children) {
319
+ const parentPathForChildren = normalized ? normalized.examplePath : fullPath;
320
+ const childRoutes = extractRoutesFromArray(children, ast, projectRoot, parentPathForChildren);
321
+ route.children = childRoutes;
322
+ }
323
+
324
+ return route;
325
+ }