@veraxhq/verax 0.2.1 → 0.3.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 (152) hide show
  1. package/README.md +14 -18
  2. package/bin/verax.js +7 -0
  3. package/package.json +3 -3
  4. package/src/cli/commands/baseline.js +104 -0
  5. package/src/cli/commands/default.js +79 -25
  6. package/src/cli/commands/ga.js +243 -0
  7. package/src/cli/commands/gates.js +95 -0
  8. package/src/cli/commands/inspect.js +131 -2
  9. package/src/cli/commands/release-check.js +213 -0
  10. package/src/cli/commands/run.js +246 -35
  11. package/src/cli/commands/security-check.js +211 -0
  12. package/src/cli/commands/truth.js +114 -0
  13. package/src/cli/entry.js +304 -67
  14. package/src/cli/util/angular-component-extractor.js +179 -0
  15. package/src/cli/util/angular-navigation-detector.js +141 -0
  16. package/src/cli/util/angular-network-detector.js +161 -0
  17. package/src/cli/util/angular-state-detector.js +162 -0
  18. package/src/cli/util/ast-interactive-detector.js +546 -0
  19. package/src/cli/util/ast-network-detector.js +603 -0
  20. package/src/cli/util/ast-usestate-detector.js +602 -0
  21. package/src/cli/util/bootstrap-guard.js +86 -0
  22. package/src/cli/util/determinism-runner.js +123 -0
  23. package/src/cli/util/determinism-writer.js +129 -0
  24. package/src/cli/util/env-url.js +4 -0
  25. package/src/cli/util/expectation-extractor.js +369 -73
  26. package/src/cli/util/findings-writer.js +126 -16
  27. package/src/cli/util/learn-writer.js +3 -1
  28. package/src/cli/util/observe-writer.js +3 -1
  29. package/src/cli/util/paths.js +3 -12
  30. package/src/cli/util/project-discovery.js +3 -0
  31. package/src/cli/util/project-writer.js +3 -1
  32. package/src/cli/util/run-resolver.js +64 -0
  33. package/src/cli/util/source-requirement.js +55 -0
  34. package/src/cli/util/summary-writer.js +1 -0
  35. package/src/cli/util/svelte-navigation-detector.js +163 -0
  36. package/src/cli/util/svelte-network-detector.js +80 -0
  37. package/src/cli/util/svelte-sfc-extractor.js +147 -0
  38. package/src/cli/util/svelte-state-detector.js +243 -0
  39. package/src/cli/util/vue-navigation-detector.js +177 -0
  40. package/src/cli/util/vue-sfc-extractor.js +162 -0
  41. package/src/cli/util/vue-state-detector.js +215 -0
  42. package/src/verax/cli/finding-explainer.js +56 -3
  43. package/src/verax/core/artifacts/registry.js +154 -0
  44. package/src/verax/core/artifacts/verifier.js +980 -0
  45. package/src/verax/core/baseline/baseline.enforcer.js +137 -0
  46. package/src/verax/core/baseline/baseline.snapshot.js +231 -0
  47. package/src/verax/core/capabilities/gates.js +499 -0
  48. package/src/verax/core/capabilities/registry.js +475 -0
  49. package/src/verax/core/confidence/confidence-compute.js +137 -0
  50. package/src/verax/core/confidence/confidence-invariants.js +234 -0
  51. package/src/verax/core/confidence/confidence-report-writer.js +112 -0
  52. package/src/verax/core/confidence/confidence-weights.js +44 -0
  53. package/src/verax/core/confidence/confidence.defaults.js +65 -0
  54. package/src/verax/core/confidence/confidence.loader.js +79 -0
  55. package/src/verax/core/confidence/confidence.schema.js +94 -0
  56. package/src/verax/core/confidence-engine-refactor.js +484 -0
  57. package/src/verax/core/confidence-engine.js +486 -0
  58. package/src/verax/core/confidence-engine.js.backup +471 -0
  59. package/src/verax/core/contracts/index.js +29 -0
  60. package/src/verax/core/contracts/types.js +185 -0
  61. package/src/verax/core/contracts/validators.js +381 -0
  62. package/src/verax/core/decision-snapshot.js +30 -3
  63. package/src/verax/core/decisions/decision.trace.js +276 -0
  64. package/src/verax/core/determinism/contract-writer.js +89 -0
  65. package/src/verax/core/determinism/contract.js +139 -0
  66. package/src/verax/core/determinism/diff.js +364 -0
  67. package/src/verax/core/determinism/engine.js +221 -0
  68. package/src/verax/core/determinism/finding-identity.js +148 -0
  69. package/src/verax/core/determinism/normalize.js +438 -0
  70. package/src/verax/core/determinism/report-writer.js +92 -0
  71. package/src/verax/core/determinism/run-fingerprint.js +118 -0
  72. package/src/verax/core/dynamic-route-intelligence.js +528 -0
  73. package/src/verax/core/evidence/evidence-capture-service.js +307 -0
  74. package/src/verax/core/evidence/evidence-intent-ledger.js +165 -0
  75. package/src/verax/core/evidence-builder.js +487 -0
  76. package/src/verax/core/execution-mode-context.js +77 -0
  77. package/src/verax/core/execution-mode-detector.js +190 -0
  78. package/src/verax/core/failures/exit-codes.js +86 -0
  79. package/src/verax/core/failures/failure-summary.js +76 -0
  80. package/src/verax/core/failures/failure.factory.js +225 -0
  81. package/src/verax/core/failures/failure.ledger.js +132 -0
  82. package/src/verax/core/failures/failure.types.js +196 -0
  83. package/src/verax/core/failures/index.js +10 -0
  84. package/src/verax/core/ga/ga-report-writer.js +43 -0
  85. package/src/verax/core/ga/ga.artifact.js +49 -0
  86. package/src/verax/core/ga/ga.contract.js +434 -0
  87. package/src/verax/core/ga/ga.enforcer.js +86 -0
  88. package/src/verax/core/guardrails/guardrails-report-writer.js +109 -0
  89. package/src/verax/core/guardrails/policy.defaults.js +210 -0
  90. package/src/verax/core/guardrails/policy.loader.js +83 -0
  91. package/src/verax/core/guardrails/policy.schema.js +110 -0
  92. package/src/verax/core/guardrails/truth-reconciliation.js +136 -0
  93. package/src/verax/core/guardrails-engine.js +505 -0
  94. package/src/verax/core/observe/run-timeline.js +316 -0
  95. package/src/verax/core/perf/perf.contract.js +186 -0
  96. package/src/verax/core/perf/perf.display.js +65 -0
  97. package/src/verax/core/perf/perf.enforcer.js +91 -0
  98. package/src/verax/core/perf/perf.monitor.js +209 -0
  99. package/src/verax/core/perf/perf.report.js +198 -0
  100. package/src/verax/core/pipeline-tracker.js +238 -0
  101. package/src/verax/core/product-definition.js +127 -0
  102. package/src/verax/core/release/provenance.builder.js +271 -0
  103. package/src/verax/core/release/release-report-writer.js +40 -0
  104. package/src/verax/core/release/release.enforcer.js +159 -0
  105. package/src/verax/core/release/reproducibility.check.js +221 -0
  106. package/src/verax/core/release/sbom.builder.js +283 -0
  107. package/src/verax/core/report/cross-index.js +192 -0
  108. package/src/verax/core/report/human-summary.js +222 -0
  109. package/src/verax/core/route-intelligence.js +419 -0
  110. package/src/verax/core/security/secrets.scan.js +326 -0
  111. package/src/verax/core/security/security-report.js +50 -0
  112. package/src/verax/core/security/security.enforcer.js +124 -0
  113. package/src/verax/core/security/supplychain.defaults.json +38 -0
  114. package/src/verax/core/security/supplychain.policy.js +326 -0
  115. package/src/verax/core/security/vuln.scan.js +265 -0
  116. package/src/verax/core/truth/truth.certificate.js +250 -0
  117. package/src/verax/core/ui-feedback-intelligence.js +515 -0
  118. package/src/verax/detect/confidence-engine.js +628 -40
  119. package/src/verax/detect/confidence-helper.js +33 -0
  120. package/src/verax/detect/detection-engine.js +18 -1
  121. package/src/verax/detect/dynamic-route-findings.js +335 -0
  122. package/src/verax/detect/expectation-chain-detector.js +417 -0
  123. package/src/verax/detect/expectation-model.js +3 -1
  124. package/src/verax/detect/findings-writer.js +141 -5
  125. package/src/verax/detect/index.js +229 -5
  126. package/src/verax/detect/journey-stall-detector.js +558 -0
  127. package/src/verax/detect/route-findings.js +218 -0
  128. package/src/verax/detect/ui-feedback-findings.js +207 -0
  129. package/src/verax/detect/verdict-engine.js +57 -3
  130. package/src/verax/detect/view-switch-correlator.js +242 -0
  131. package/src/verax/index.js +413 -45
  132. package/src/verax/learn/action-contract-extractor.js +682 -64
  133. package/src/verax/learn/route-validator.js +4 -1
  134. package/src/verax/observe/index.js +88 -843
  135. package/src/verax/observe/interaction-runner.js +25 -8
  136. package/src/verax/observe/observe-context.js +205 -0
  137. package/src/verax/observe/observe-helpers.js +191 -0
  138. package/src/verax/observe/observe-runner.js +226 -0
  139. package/src/verax/observe/observers/budget-observer.js +185 -0
  140. package/src/verax/observe/observers/console-observer.js +102 -0
  141. package/src/verax/observe/observers/coverage-observer.js +107 -0
  142. package/src/verax/observe/observers/interaction-observer.js +471 -0
  143. package/src/verax/observe/observers/navigation-observer.js +132 -0
  144. package/src/verax/observe/observers/network-observer.js +87 -0
  145. package/src/verax/observe/observers/safety-observer.js +82 -0
  146. package/src/verax/observe/observers/ui-feedback-observer.js +99 -0
  147. package/src/verax/observe/ui-feedback-detector.js +742 -0
  148. package/src/verax/observe/ui-signal-sensor.js +148 -2
  149. package/src/verax/scan-summary-writer.js +42 -8
  150. package/src/verax/shared/artifact-manager.js +8 -5
  151. package/src/verax/shared/css-spinner-rules.js +204 -0
  152. package/src/verax/shared/view-switch-rules.js +208 -0
@@ -0,0 +1,242 @@
1
+ /**
2
+ * VIEW SWITCH CORRELATOR
3
+ *
4
+ * Correlates view switch promises with observed UI changes (no URL change).
5
+ * Requires at least 2 independent signals for CONFIRMED.
6
+ *
7
+ * TRUTH BOUNDARY:
8
+ * - CONFIRMED: 2+ independent signals (DOM signature + landmark/focus/aria-live)
9
+ * - SUSPECTED: 1 signal only
10
+ * - INFORMATIONAL: Interaction blocked/disabled/prevented
11
+ */
12
+
13
+ /**
14
+ * Reason codes for correlation decisions
15
+ */
16
+ export const VIEW_SWITCH_REASON_CODES = {
17
+ CONFIRMED_TWO_SIGNALS: 'CONFIRMED_TWO_SIGNALS',
18
+ CONFIRMED_THREE_SIGNALS: 'CONFIRMED_THREE_SIGNALS',
19
+ SUSPECTED_ONE_SIGNAL: 'SUSPECTED_ONE_SIGNAL',
20
+ INFORMATIONAL_BLOCKED: 'INFORMATIONAL_BLOCKED',
21
+ INFORMATIONAL_DISABLED: 'INFORMATIONAL_DISABLED',
22
+ INFORMATIONAL_PREVENTED: 'INFORMATIONAL_PREVENTED',
23
+ NO_SIGNALS: 'NO_SIGNALS'
24
+ };
25
+
26
+ /**
27
+ * Correlate view switch promise with observed UI changes.
28
+ *
29
+ * @param {Object} expectation - View switch promise expectation
30
+ * @param {Object} trace - Interaction trace with sensors
31
+ * @param {string} beforeUrl - URL before interaction
32
+ * @param {string} afterUrl - URL after interaction
33
+ * @returns {Object} - { outcome, severity, reasonCode, signals }
34
+ */
35
+ export function correlateViewSwitch(expectation, trace, beforeUrl, afterUrl) {
36
+ if (!expectation || expectation.kind !== 'VIEW_SWITCH_PROMISE') {
37
+ return { outcome: null, severity: null, reasonCode: null, signals: [] };
38
+ }
39
+
40
+ const sensors = trace.sensors || {};
41
+ const navigation = sensors.navigation || {};
42
+ const uiSignals = sensors.uiSignals || {};
43
+ const stateUi = sensors.stateUi || {};
44
+ const uiFeedback = sensors.uiFeedback || {};
45
+
46
+ // Check if URL changed (if so, this is not a state-driven navigation)
47
+ const urlChanged = navigation.urlChanged === true || (beforeUrl !== afterUrl);
48
+ if (urlChanged) {
49
+ return { outcome: null, severity: null, reasonCode: 'URL_CHANGED', signals: [] };
50
+ }
51
+
52
+ // Check if interaction was blocked/disabled/prevented
53
+ const interaction = trace.interaction || {};
54
+ const isDisabled = interaction.disabled === true;
55
+ const isBlocked = interaction.blocked === true;
56
+ const isPrevented = interaction.prevented === true;
57
+
58
+ if (isDisabled) {
59
+ return {
60
+ outcome: 'INFORMATIONAL',
61
+ severity: 'INFORMATIONAL',
62
+ reasonCode: VIEW_SWITCH_REASON_CODES.INFORMATIONAL_DISABLED,
63
+ signals: []
64
+ };
65
+ }
66
+
67
+ if (isBlocked) {
68
+ return {
69
+ outcome: 'INFORMATIONAL',
70
+ severity: 'INFORMATIONAL',
71
+ reasonCode: VIEW_SWITCH_REASON_CODES.INFORMATIONAL_BLOCKED,
72
+ signals: []
73
+ };
74
+ }
75
+
76
+ if (isPrevented) {
77
+ return {
78
+ outcome: 'INFORMATIONAL',
79
+ severity: 'INFORMATIONAL',
80
+ reasonCode: VIEW_SWITCH_REASON_CODES.INFORMATIONAL_PREVENTED,
81
+ signals: []
82
+ };
83
+ }
84
+
85
+ // Collect independent signals
86
+ const signals = [];
87
+
88
+ // Signal 1: DOM signature change (stable hash)
89
+ const beforeDom = trace.before?.domSignature || trace.before?.domHash;
90
+ const afterDom = trace.after?.domSignature || trace.after?.domHash;
91
+ if (beforeDom && afterDom && beforeDom !== afterDom) {
92
+ signals.push({
93
+ type: 'DOM_SIGNATURE_CHANGE',
94
+ before: beforeDom,
95
+ after: afterDom
96
+ });
97
+ }
98
+
99
+ // Signal 2: Visible landmark change (heading/main role change)
100
+ const beforeLandmarks = extractLandmarks(trace.before);
101
+ const afterLandmarks = extractLandmarks(trace.after);
102
+ if (beforeLandmarks.length > 0 && afterLandmarks.length > 0) {
103
+ const landmarksChanged = JSON.stringify(beforeLandmarks) !== JSON.stringify(afterLandmarks);
104
+ if (landmarksChanged) {
105
+ signals.push({
106
+ type: 'LANDMARK_CHANGE',
107
+ before: beforeLandmarks,
108
+ after: afterLandmarks
109
+ });
110
+ }
111
+ }
112
+
113
+ // Signal 3: Focus moved to new container
114
+ const beforeFocus = trace.before?.focus || {};
115
+ const afterFocus = trace.after?.focus || {};
116
+ if (beforeFocus.selector && afterFocus.selector && beforeFocus.selector !== afterFocus.selector) {
117
+ const beforeContainer = getContainerSelector(beforeFocus.selector);
118
+ const afterContainer = getContainerSelector(afterFocus.selector);
119
+ if (beforeContainer !== afterContainer) {
120
+ signals.push({
121
+ type: 'FOCUS_CONTAINER_CHANGE',
122
+ before: beforeContainer,
123
+ after: afterContainer
124
+ });
125
+ }
126
+ }
127
+
128
+ // Signal 4: aria-live message
129
+ const ariaLiveBefore = extractAriaLive(trace.before);
130
+ const ariaLiveAfter = extractAriaLive(trace.after);
131
+ if (ariaLiveAfter.length > ariaLiveBefore.length) {
132
+ signals.push({
133
+ type: 'ARIA_LIVE_MESSAGE',
134
+ messages: ariaLiveAfter.slice(ariaLiveBefore.length)
135
+ });
136
+ }
137
+
138
+ // Signal 5: UI feedback signals (optional but counts)
139
+ if (uiFeedback.signals) {
140
+ const feedbackSignals = uiFeedback.signals;
141
+ if (feedbackSignals.domChange?.happened === true) {
142
+ signals.push({
143
+ type: 'UI_FEEDBACK_DOM_CHANGE',
144
+ details: feedbackSignals.domChange
145
+ });
146
+ }
147
+ if (feedbackSignals.focusChange?.happened === true) {
148
+ signals.push({
149
+ type: 'UI_FEEDBACK_FOCUS_CHANGE',
150
+ details: feedbackSignals.focusChange
151
+ });
152
+ }
153
+ }
154
+
155
+ // Determine outcome based on signal count
156
+ if (signals.length >= 2) {
157
+ return {
158
+ outcome: 'CONFIRMED',
159
+ severity: 'CONFIRMED',
160
+ reasonCode: signals.length >= 3
161
+ ? VIEW_SWITCH_REASON_CODES.CONFIRMED_THREE_SIGNALS
162
+ : VIEW_SWITCH_REASON_CODES.CONFIRMED_TWO_SIGNALS,
163
+ signals
164
+ };
165
+ } else if (signals.length === 1) {
166
+ return {
167
+ outcome: 'SUSPECTED',
168
+ severity: 'SUSPECTED',
169
+ reasonCode: VIEW_SWITCH_REASON_CODES.SUSPECTED_ONE_SIGNAL,
170
+ signals
171
+ };
172
+ } else {
173
+ return {
174
+ outcome: 'NO_SIGNALS',
175
+ severity: 'SUSPECTED',
176
+ reasonCode: VIEW_SWITCH_REASON_CODES.NO_SIGNALS,
177
+ signals: []
178
+ };
179
+ }
180
+ }
181
+
182
+ /**
183
+ * Extract landmarks (headings, main role) from trace snapshot
184
+ */
185
+ function extractLandmarks(snapshot) {
186
+ if (!snapshot) return [];
187
+
188
+ const landmarks = [];
189
+
190
+ // Extract headings (h1-h6)
191
+ if (snapshot.headings) {
192
+ landmarks.push(...snapshot.headings.map(h => ({ type: 'heading', level: h.level, text: h.text?.slice(0, 50) })));
193
+ }
194
+
195
+ // Extract main role elements
196
+ if (snapshot.mainElements) {
197
+ landmarks.push(...snapshot.mainElements.map(m => ({ type: 'main', text: m.text?.slice(0, 50) })));
198
+ }
199
+
200
+ return landmarks;
201
+ }
202
+
203
+ /**
204
+ * Get container selector from element selector
205
+ */
206
+ function getContainerSelector(selector) {
207
+ if (!selector) return null;
208
+
209
+ // Extract parent container (simplified - assumes common patterns)
210
+ const parts = selector.split(' > ');
211
+ if (parts.length > 1) {
212
+ return parts[parts.length - 2]; // Second to last part
213
+ }
214
+
215
+ // Try to extract container from selector
216
+ const match = selector.match(/([^>]+) > [^>]+$/);
217
+ if (match) {
218
+ return match[1].trim();
219
+ }
220
+
221
+ return selector; // Fallback to full selector
222
+ }
223
+
224
+ /**
225
+ * Extract aria-live messages from trace snapshot
226
+ */
227
+ function extractAriaLive(snapshot) {
228
+ if (!snapshot) return [];
229
+
230
+ const messages = [];
231
+
232
+ if (snapshot.ariaLiveRegions) {
233
+ snapshot.ariaLiveRegions.forEach(region => {
234
+ if (region.text) {
235
+ messages.push(region.text.slice(0, 100));
236
+ }
237
+ });
238
+ }
239
+
240
+ return messages;
241
+ }
242
+