@veraxhq/verax 0.3.0 → 0.4.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.
- package/README.md +28 -20
- package/bin/verax.js +11 -18
- package/package.json +28 -7
- package/src/cli/commands/baseline.js +1 -2
- package/src/cli/commands/default.js +72 -81
- package/src/cli/commands/doctor.js +29 -0
- package/src/cli/commands/ga.js +3 -0
- package/src/cli/commands/gates.js +1 -1
- package/src/cli/commands/inspect.js +6 -133
- package/src/cli/commands/release-check.js +2 -0
- package/src/cli/commands/run.js +74 -246
- package/src/cli/commands/security-check.js +2 -1
- package/src/cli/commands/truth.js +0 -1
- package/src/cli/entry.js +82 -309
- package/src/cli/util/angular-component-extractor.js +2 -2
- package/src/cli/util/angular-navigation-detector.js +2 -2
- package/src/cli/util/ast-interactive-detector.js +4 -6
- package/src/cli/util/ast-network-detector.js +3 -3
- package/src/cli/util/ast-promise-extractor.js +581 -0
- package/src/cli/util/ast-usestate-detector.js +3 -3
- package/src/cli/util/atomic-write.js +12 -1
- package/src/cli/util/console-reporter.js +72 -0
- package/src/cli/util/detection-engine.js +105 -41
- package/src/cli/util/determinism-runner.js +2 -1
- package/src/cli/util/determinism-writer.js +1 -1
- package/src/cli/util/digest-engine.js +359 -0
- package/src/cli/util/dom-diff.js +226 -0
- package/src/cli/util/env-url.js +0 -4
- package/src/cli/util/evidence-engine.js +287 -0
- package/src/cli/util/expectation-extractor.js +217 -367
- package/src/cli/util/findings-writer.js +19 -126
- package/src/cli/util/framework-detector.js +572 -0
- package/src/cli/util/idgen.js +1 -1
- package/src/cli/util/interaction-planner.js +529 -0
- package/src/cli/util/learn-writer.js +2 -2
- package/src/cli/util/ledger-writer.js +110 -0
- package/src/cli/util/monorepo-resolver.js +162 -0
- package/src/cli/util/observation-engine.js +127 -278
- package/src/cli/util/observe-writer.js +2 -2
- package/src/cli/util/paths.js +12 -3
- package/src/cli/util/project-discovery.js +284 -3
- package/src/cli/util/project-writer.js +2 -2
- package/src/cli/util/run-id.js +23 -27
- package/src/cli/util/run-result.js +778 -0
- package/src/cli/util/selector-resolver.js +235 -0
- package/src/cli/util/summary-writer.js +2 -1
- package/src/cli/util/svelte-navigation-detector.js +3 -3
- package/src/cli/util/svelte-sfc-extractor.js +0 -1
- package/src/cli/util/svelte-state-detector.js +1 -2
- package/src/cli/util/trust-activation-integration.js +496 -0
- package/src/cli/util/trust-activation-wrapper.js +85 -0
- package/src/cli/util/trust-integration-hooks.js +164 -0
- package/src/cli/util/types.js +153 -0
- package/src/cli/util/url-validation.js +40 -0
- package/src/cli/util/vue-navigation-detector.js +4 -3
- package/src/cli/util/vue-sfc-extractor.js +1 -2
- package/src/cli/util/vue-state-detector.js +1 -1
- package/src/types/fs-augment.d.ts +23 -0
- package/src/types/global.d.ts +137 -0
- package/src/types/internal-types.d.ts +35 -0
- package/src/verax/cli/finding-explainer.js +3 -56
- package/src/verax/cli/init.js +4 -18
- package/src/verax/core/action-classifier.js +4 -3
- package/src/verax/core/artifacts/registry.js +0 -15
- package/src/verax/core/artifacts/verifier.js +18 -8
- package/src/verax/core/baseline/baseline.snapshot.js +2 -0
- package/src/verax/core/capabilities/gates.js +7 -1
- package/src/verax/core/confidence/confidence-compute.js +14 -7
- package/src/verax/core/confidence/confidence.loader.js +1 -0
- package/src/verax/core/confidence-engine-refactor.js +8 -3
- package/src/verax/core/confidence-engine.js +162 -23
- package/src/verax/core/contracts/types.js +1 -0
- package/src/verax/core/contracts/validators.js +79 -4
- package/src/verax/core/decision-snapshot.js +3 -30
- package/src/verax/core/decisions/decision.trace.js +2 -0
- package/src/verax/core/determinism/contract-writer.js +2 -2
- package/src/verax/core/determinism/contract.js +1 -1
- package/src/verax/core/determinism/diff.js +42 -1
- package/src/verax/core/determinism/engine.js +7 -6
- package/src/verax/core/determinism/finding-identity.js +3 -2
- package/src/verax/core/determinism/normalize.js +32 -4
- package/src/verax/core/determinism/report-writer.js +1 -0
- package/src/verax/core/determinism/run-fingerprint.js +7 -2
- package/src/verax/core/dynamic-route-intelligence.js +8 -7
- package/src/verax/core/evidence/evidence-capture-service.js +1 -0
- package/src/verax/core/evidence/evidence-intent-ledger.js +2 -1
- package/src/verax/core/evidence-builder.js +2 -2
- package/src/verax/core/execution-mode-context.js +1 -1
- package/src/verax/core/execution-mode-detector.js +5 -3
- package/src/verax/core/failures/exit-codes.js +39 -37
- package/src/verax/core/failures/failure-summary.js +1 -1
- package/src/verax/core/failures/failure.factory.js +3 -3
- package/src/verax/core/failures/failure.ledger.js +3 -2
- package/src/verax/core/ga/ga.artifact.js +1 -1
- package/src/verax/core/ga/ga.contract.js +3 -2
- package/src/verax/core/ga/ga.enforcer.js +1 -0
- package/src/verax/core/guardrails/policy.loader.js +1 -0
- package/src/verax/core/guardrails/truth-reconciliation.js +1 -1
- package/src/verax/core/guardrails-engine.js +2 -2
- package/src/verax/core/incremental-store.js +1 -0
- package/src/verax/core/integrity/budget.js +138 -0
- package/src/verax/core/integrity/determinism.js +342 -0
- package/src/verax/core/integrity/integrity.js +208 -0
- package/src/verax/core/integrity/poisoning.js +108 -0
- package/src/verax/core/integrity/transaction.js +140 -0
- package/src/verax/core/observe/run-timeline.js +2 -0
- package/src/verax/core/perf/perf.report.js +2 -0
- package/src/verax/core/pipeline-tracker.js +5 -0
- package/src/verax/core/release/provenance.builder.js +73 -214
- package/src/verax/core/release/release.enforcer.js +14 -9
- package/src/verax/core/release/reproducibility.check.js +1 -0
- package/src/verax/core/release/sbom.builder.js +32 -23
- package/src/verax/core/replay-validator.js +2 -0
- package/src/verax/core/replay.js +4 -0
- package/src/verax/core/report/cross-index.js +6 -3
- package/src/verax/core/report/human-summary.js +141 -1
- package/src/verax/core/route-intelligence.js +4 -3
- package/src/verax/core/run-id.js +6 -3
- package/src/verax/core/run-manifest.js +4 -3
- package/src/verax/core/security/secrets.scan.js +10 -7
- package/src/verax/core/security/security.enforcer.js +4 -0
- package/src/verax/core/security/supplychain.policy.js +9 -1
- package/src/verax/core/security/vuln.scan.js +2 -2
- package/src/verax/core/truth/truth.certificate.js +3 -1
- package/src/verax/core/ui-feedback-intelligence.js +12 -46
- package/src/verax/detect/conditional-ui-silent-failure.js +84 -0
- package/src/verax/detect/confidence-engine.js +100 -660
- package/src/verax/detect/confidence-helper.js +1 -0
- package/src/verax/detect/detection-engine.js +1 -18
- package/src/verax/detect/dynamic-route-findings.js +17 -14
- package/src/verax/detect/expectation-chain-detector.js +1 -1
- package/src/verax/detect/expectation-model.js +3 -5
- package/src/verax/detect/failure-cause-inference.js +293 -0
- package/src/verax/detect/findings-writer.js +126 -166
- package/src/verax/detect/flow-detector.js +2 -2
- package/src/verax/detect/form-silent-failure.js +98 -0
- package/src/verax/detect/index.js +51 -234
- package/src/verax/detect/invariants-enforcer.js +147 -0
- package/src/verax/detect/journey-stall-detector.js +4 -4
- package/src/verax/detect/navigation-silent-failure.js +82 -0
- package/src/verax/detect/problem-aggregator.js +361 -0
- package/src/verax/detect/route-findings.js +7 -6
- package/src/verax/detect/summary-writer.js +477 -0
- package/src/verax/detect/test-failure-cause-inference.js +314 -0
- package/src/verax/detect/ui-feedback-findings.js +18 -18
- package/src/verax/detect/verdict-engine.js +3 -57
- package/src/verax/detect/view-switch-correlator.js +2 -2
- package/src/verax/flow/flow-engine.js +2 -1
- package/src/verax/flow/flow-spec.js +0 -6
- package/src/verax/index.js +48 -412
- package/src/verax/intel/ts-program.js +1 -0
- package/src/verax/intel/vue-navigation-extractor.js +3 -0
- package/src/verax/learn/action-contract-extractor.js +67 -682
- package/src/verax/learn/ast-contract-extractor.js +1 -1
- package/src/verax/learn/flow-extractor.js +1 -0
- package/src/verax/learn/project-detector.js +5 -0
- package/src/verax/learn/react-router-extractor.js +2 -0
- package/src/verax/learn/route-validator.js +1 -4
- package/src/verax/learn/source-instrumenter.js +1 -0
- package/src/verax/learn/state-extractor.js +2 -1
- package/src/verax/learn/static-extractor.js +1 -0
- package/src/verax/observe/coverage-gaps.js +132 -0
- package/src/verax/observe/expectation-handler.js +126 -0
- package/src/verax/observe/incremental-skip.js +46 -0
- package/src/verax/observe/index.js +735 -84
- package/src/verax/observe/interaction-executor.js +192 -0
- package/src/verax/observe/interaction-runner.js +782 -530
- package/src/verax/observe/network-firewall.js +86 -0
- package/src/verax/observe/observation-builder.js +169 -0
- package/src/verax/observe/observe-context.js +1 -1
- package/src/verax/observe/observe-helpers.js +2 -1
- package/src/verax/observe/observe-runner.js +28 -24
- package/src/verax/observe/observers/budget-observer.js +3 -3
- package/src/verax/observe/observers/console-observer.js +4 -4
- package/src/verax/observe/observers/coverage-observer.js +4 -4
- package/src/verax/observe/observers/interaction-observer.js +3 -3
- package/src/verax/observe/observers/navigation-observer.js +4 -4
- package/src/verax/observe/observers/network-observer.js +4 -4
- package/src/verax/observe/observers/safety-observer.js +1 -1
- package/src/verax/observe/observers/ui-feedback-observer.js +4 -4
- package/src/verax/observe/page-traversal.js +138 -0
- package/src/verax/observe/snapshot-ops.js +94 -0
- package/src/verax/observe/ui-signal-sensor.js +2 -148
- package/src/verax/scan-summary-writer.js +10 -42
- package/src/verax/shared/artifact-manager.js +30 -13
- package/src/verax/shared/caching.js +1 -0
- package/src/verax/shared/expectation-tracker.js +1 -0
- package/src/verax/shared/zip-artifacts.js +6 -0
- package/src/verax/core/confidence-engine.js.backup +0 -471
- package/src/verax/shared/config-loader.js +0 -169
- /package/src/verax/shared/{expectation-proof.js → expectation-validation.js} +0 -0
|
@@ -1,41 +1,13 @@
|
|
|
1
|
-
import { resolve
|
|
1
|
+
import { resolve } from 'path';
|
|
2
2
|
import { existsSync, readFileSync, readdirSync } from 'fs';
|
|
3
3
|
import { DataError } from '../util/errors.js';
|
|
4
|
-
import { displayPerformanceInInspect } from '../../verax/core/perf/perf.display.js';
|
|
5
|
-
import { loadRunTimeline } from '../../verax/core/observe/run-timeline.js';
|
|
6
|
-
import { loadDecisionTrace } from '../../verax/core/decisions/decision.trace.js';
|
|
7
|
-
import { loadCrossIndex } from '../../verax/core/report/cross-index.js';
|
|
8
|
-
import { generateHumanSummary, formatHumanSummary } from '../../verax/core/report/human-summary.js';
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Extract runId from runPath
|
|
12
|
-
*/
|
|
13
|
-
function extractRunId(runPath) {
|
|
14
|
-
const fullPath = resolve(runPath);
|
|
15
|
-
const runDirBasename = basename(fullPath);
|
|
16
|
-
const parentDir = basename(dirname(fullPath));
|
|
17
|
-
|
|
18
|
-
// Check if path is .verax/runs/<runId>
|
|
19
|
-
if (parentDir === 'runs') {
|
|
20
|
-
return runDirBasename;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
return runDirBasename;
|
|
24
|
-
}
|
|
25
4
|
|
|
26
5
|
/**
|
|
27
6
|
* `verax inspect` command
|
|
28
7
|
* Read an existing run folder and display summary
|
|
29
8
|
*/
|
|
30
9
|
export async function inspectCommand(runPath, options = {}) {
|
|
31
|
-
const {
|
|
32
|
-
json = false,
|
|
33
|
-
timeline = false,
|
|
34
|
-
decisions = false,
|
|
35
|
-
failures = false,
|
|
36
|
-
performance = false,
|
|
37
|
-
evidence = false
|
|
38
|
-
} = options;
|
|
10
|
+
const { json = false } = options;
|
|
39
11
|
|
|
40
12
|
const fullPath = resolve(runPath);
|
|
41
13
|
|
|
@@ -65,13 +37,15 @@ export async function inspectCommand(runPath, options = {}) {
|
|
|
65
37
|
let summary, findings;
|
|
66
38
|
|
|
67
39
|
try {
|
|
68
|
-
|
|
40
|
+
// @ts-expect-error - readFileSync with encoding returns string
|
|
41
|
+
summary = JSON.parse(readFileSync(`${fullPath}/summary.json`, 'utf-8'));
|
|
69
42
|
} catch (error) {
|
|
70
43
|
throw new DataError(`Failed to parse summary.json: ${error.message}`);
|
|
71
44
|
}
|
|
72
45
|
|
|
73
46
|
try {
|
|
74
|
-
|
|
47
|
+
// @ts-expect-error - readFileSync with encoding returns string
|
|
48
|
+
findings = JSON.parse(readFileSync(`${fullPath}/findings.json`, 'utf-8'));
|
|
75
49
|
} catch (error) {
|
|
76
50
|
throw new DataError(`Failed to parse findings.json: ${error.message}`);
|
|
77
51
|
}
|
|
@@ -130,108 +104,7 @@ export async function inspectCommand(runPath, options = {}) {
|
|
|
130
104
|
console.log(`Evidence: not found`);
|
|
131
105
|
}
|
|
132
106
|
|
|
133
|
-
// PHASE 21.9: Display performance metrics
|
|
134
|
-
const runId = output.runId;
|
|
135
|
-
const projectDir = resolve(process.cwd());
|
|
136
|
-
|
|
137
|
-
// PHASE 21.10: Handle specific flags
|
|
138
|
-
if (timeline) {
|
|
139
|
-
const timelineData = loadRunTimeline(projectDir, runId);
|
|
140
|
-
if (timelineData) {
|
|
141
|
-
if (json) {
|
|
142
|
-
console.log(JSON.stringify(timelineData, null, 2));
|
|
143
|
-
} else {
|
|
144
|
-
console.log('\n=== Timeline ===\n');
|
|
145
|
-
for (const event of timelineData.events) {
|
|
146
|
-
console.log(`${event.timestamp || 'N/A'} [${event.phase}] ${event.event}`);
|
|
147
|
-
if (event.data) {
|
|
148
|
-
console.log(` ${JSON.stringify(event.data)}`);
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
console.log('');
|
|
152
|
-
}
|
|
153
|
-
return output;
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
if (decisions) {
|
|
158
|
-
const decisionTrace = loadDecisionTrace(projectDir, runId);
|
|
159
|
-
if (decisionTrace) {
|
|
160
|
-
if (json) {
|
|
161
|
-
console.log(JSON.stringify(decisionTrace, null, 2));
|
|
162
|
-
} else {
|
|
163
|
-
console.log('\n=== Decision Trace ===\n');
|
|
164
|
-
for (const trace of decisionTrace.findings) {
|
|
165
|
-
console.log(`Finding: ${trace.findingId}`);
|
|
166
|
-
console.log(` Status: ${trace.status.value}`);
|
|
167
|
-
console.log(` Confidence: ${trace.confidence.level || 'UNKNOWN'}`);
|
|
168
|
-
console.log(` Why detected: ${trace.detection.why.map(w => w.reason).join('; ')}`);
|
|
169
|
-
console.log(` Why status: ${trace.status.why.map(w => w.reason).join('; ')}`);
|
|
170
|
-
console.log('');
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
return output;
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
if (failures) {
|
|
178
|
-
const failureLedgerPath = resolve(fullPath, 'failure.ledger.json');
|
|
179
|
-
if (existsSync(failureLedgerPath)) {
|
|
180
|
-
const failureLedger = JSON.parse(readFileSync(failureLedgerPath, 'utf-8'));
|
|
181
|
-
if (json) {
|
|
182
|
-
console.log(JSON.stringify(failureLedger, null, 2));
|
|
183
|
-
} else {
|
|
184
|
-
console.log('\n=== Failures ===\n');
|
|
185
|
-
console.log(`Total: ${failureLedger.summary?.total || 0}`);
|
|
186
|
-
if (failureLedger.failures) {
|
|
187
|
-
for (const failure of failureLedger.failures) {
|
|
188
|
-
console.log(`[${failure.severity || 'UNKNOWN'}] ${failure.code}: ${failure.message}`);
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
console.log('');
|
|
192
|
-
}
|
|
193
|
-
return output;
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
if (performance) {
|
|
198
|
-
displayPerformanceInInspect(projectDir, runId);
|
|
199
107
|
console.log('');
|
|
200
|
-
return output;
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
if (evidence) {
|
|
204
|
-
const crossIndex = loadCrossIndex(projectDir, runId);
|
|
205
|
-
if (crossIndex) {
|
|
206
|
-
if (json) {
|
|
207
|
-
console.log(JSON.stringify(crossIndex, null, 2));
|
|
208
|
-
} else {
|
|
209
|
-
console.log('\n=== Evidence Cross-Index ===\n');
|
|
210
|
-
for (const [findingId, entry] of Object.entries(crossIndex.findings)) {
|
|
211
|
-
console.log(`Finding: ${findingId}`);
|
|
212
|
-
console.log(` Evidence files: ${entry.evidence.files.length}`);
|
|
213
|
-
console.log(` Evidence complete: ${entry.evidence.isComplete}`);
|
|
214
|
-
console.log(` Confidence: ${entry.confidence.level || 'UNKNOWN'}`);
|
|
215
|
-
console.log(` Guardrails: ${entry.guardrails.applied.length} rule(s) applied`);
|
|
216
|
-
console.log('');
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
return output;
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
// Default: show summary + human summary
|
|
224
|
-
displayPerformanceInInspect(projectDir, runId);
|
|
225
|
-
|
|
226
|
-
// PHASE 21.10: Display human summary
|
|
227
|
-
const humanSummary = await generateHumanSummary(projectDir, runId);
|
|
228
|
-
if (humanSummary && !json) {
|
|
229
|
-
console.log(formatHumanSummary(humanSummary));
|
|
230
|
-
} else if (humanSummary && json) {
|
|
231
|
-
output.humanSummary = humanSummary;
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
console.log('');
|
|
235
108
|
}
|
|
236
109
|
|
|
237
110
|
return output;
|
|
@@ -53,6 +53,7 @@ export async function releaseCheckCommand(options = {}) {
|
|
|
53
53
|
const provenancePath = resolve(projectDir, 'release', 'release.provenance.json');
|
|
54
54
|
if (existsSync(provenancePath)) {
|
|
55
55
|
status.provenance.exists = true;
|
|
56
|
+
// @ts-expect-error - readFileSync with encoding returns string
|
|
56
57
|
const provenance = JSON.parse(readFileSync(provenancePath, 'utf-8'));
|
|
57
58
|
|
|
58
59
|
// Validate provenance structure
|
|
@@ -85,6 +86,7 @@ export async function releaseCheckCommand(options = {}) {
|
|
|
85
86
|
const sbomPath = resolve(projectDir, 'release', 'sbom.json');
|
|
86
87
|
if (existsSync(sbomPath)) {
|
|
87
88
|
status.sbom.exists = true;
|
|
89
|
+
// @ts-expect-error - readFileSync with encoding returns string
|
|
88
90
|
const sbom = JSON.parse(readFileSync(sbomPath, 'utf-8'));
|
|
89
91
|
|
|
90
92
|
// Validate SBOM structure
|
package/src/cli/commands/run.js
CHANGED
|
@@ -17,9 +17,8 @@ import { detectFindings } from '../util/detection-engine.js';
|
|
|
17
17
|
import { writeFindingsJson } from '../util/findings-writer.js';
|
|
18
18
|
import { writeSummaryJson } from '../util/summary-writer.js';
|
|
19
19
|
import { computeRuntimeBudget, withTimeout } from '../util/runtime-budget.js';
|
|
20
|
-
import {
|
|
21
|
-
import {
|
|
22
|
-
import { runDeterminismCheck } from '../../verax/core/determinism/engine.js';
|
|
20
|
+
import { saveDigest } from '../util/digest-engine.js';
|
|
21
|
+
import { ARTIFACT_REGISTRY, getArtifactVersions } from '../../verax/core/artifacts/registry.js';
|
|
23
22
|
|
|
24
23
|
const __filename = fileURLToPath(import.meta.url);
|
|
25
24
|
const __dirname = dirname(__filename);
|
|
@@ -27,10 +26,11 @@ const __dirname = dirname(__filename);
|
|
|
27
26
|
function getVersion() {
|
|
28
27
|
try {
|
|
29
28
|
const pkgPath = resolve(__dirname, '../../../package.json');
|
|
30
|
-
|
|
29
|
+
// @ts-expect-error - readFileSync with encoding returns string
|
|
30
|
+
const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));
|
|
31
31
|
return pkg.version;
|
|
32
32
|
} catch {
|
|
33
|
-
return '0.
|
|
33
|
+
return '0.2.0';
|
|
34
34
|
}
|
|
35
35
|
}
|
|
36
36
|
|
|
@@ -39,68 +39,17 @@ function getVersion() {
|
|
|
39
39
|
* Strict, non-interactive CLI mode with explicit flags
|
|
40
40
|
*/
|
|
41
41
|
export async function runCommand(options) {
|
|
42
|
-
return await runCommandInternal(options);
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* Internal run command implementation
|
|
47
|
-
*/
|
|
48
|
-
async function runCommandInternal(options) {
|
|
49
42
|
const {
|
|
50
43
|
url,
|
|
51
|
-
fixture,
|
|
52
44
|
src = '.',
|
|
53
45
|
out = '.verax',
|
|
54
46
|
json = false,
|
|
55
47
|
verbose = false,
|
|
56
|
-
determinism = false,
|
|
57
|
-
determinismRuns = 2,
|
|
58
48
|
} = options;
|
|
59
49
|
|
|
60
|
-
// PHASE 25: Support fixture mode for determinism
|
|
61
|
-
let resolvedUrl = url;
|
|
62
|
-
let fixtureId = null;
|
|
63
|
-
|
|
64
|
-
if (fixture && !url) {
|
|
65
|
-
// Extract URL from fixture
|
|
66
|
-
const { resolve } = await import('path');
|
|
67
|
-
const { existsSync, readFileSync } = await import('fs');
|
|
68
|
-
const { fileURLToPath } = await import('url');
|
|
69
|
-
const { dirname } = await import('path');
|
|
70
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
71
|
-
const __dirname = dirname(__filename);
|
|
72
|
-
|
|
73
|
-
const fixturePath = resolve(__dirname, '..', '..', '..', 'test', 'fixtures', 'realistic', fixture);
|
|
74
|
-
if (existsSync(fixturePath)) {
|
|
75
|
-
// Try to read package.json or index.html to extract URL
|
|
76
|
-
const packagePath = resolve(fixturePath, 'package.json');
|
|
77
|
-
const indexPath = resolve(fixturePath, 'index.html');
|
|
78
|
-
|
|
79
|
-
if (existsSync(packagePath)) {
|
|
80
|
-
try {
|
|
81
|
-
const pkg = JSON.parse(readFileSync(packagePath, 'utf-8'));
|
|
82
|
-
if (pkg.verax && pkg.verax.url) {
|
|
83
|
-
resolvedUrl = pkg.verax.url;
|
|
84
|
-
fixtureId = fixture;
|
|
85
|
-
}
|
|
86
|
-
} catch {
|
|
87
|
-
// Ignore parse errors
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
// If no URL found, use default localhost URL for fixture
|
|
92
|
-
if (!resolvedUrl) {
|
|
93
|
-
resolvedUrl = `http://localhost:5173`; // Default Vite dev server
|
|
94
|
-
fixtureId = fixture;
|
|
95
|
-
}
|
|
96
|
-
} else {
|
|
97
|
-
throw new DataError(`Fixture not found: ${fixture}`);
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
|
|
101
50
|
// Validate required arguments
|
|
102
|
-
if (!
|
|
103
|
-
throw new UsageError('Missing required argument: --url <url>
|
|
51
|
+
if (!url) {
|
|
52
|
+
throw new UsageError('Missing required argument: --url <url>');
|
|
104
53
|
}
|
|
105
54
|
|
|
106
55
|
const projectRoot = resolve(process.cwd());
|
|
@@ -110,9 +59,6 @@ async function runCommandInternal(options) {
|
|
|
110
59
|
if (!existsSync(srcPath)) {
|
|
111
60
|
throw new DataError(`Source directory not found: ${srcPath}`);
|
|
112
61
|
}
|
|
113
|
-
|
|
114
|
-
// Enforce local source availability (no URL-only scans)
|
|
115
|
-
assertHasLocalSource(srcPath);
|
|
116
62
|
|
|
117
63
|
// Create event emitter
|
|
118
64
|
const events = new RunEventEmitter();
|
|
@@ -150,7 +96,7 @@ async function runCommandInternal(options) {
|
|
|
150
96
|
const failedAt = new Date().toISOString();
|
|
151
97
|
atomicWriteJson(paths.runStatusJson, {
|
|
152
98
|
contractVersion: 1,
|
|
153
|
-
artifactVersions:
|
|
99
|
+
artifactVersions: getArtifactVersions(),
|
|
154
100
|
status: 'FAILED',
|
|
155
101
|
runId,
|
|
156
102
|
startedAt,
|
|
@@ -159,8 +105,7 @@ async function runCommandInternal(options) {
|
|
|
159
105
|
});
|
|
160
106
|
|
|
161
107
|
atomicWriteJson(paths.runMetaJson, {
|
|
162
|
-
contractVersion:
|
|
163
|
-
artifactVersions: paths.artifactVersions,
|
|
108
|
+
contractVersion: ARTIFACT_REGISTRY.runMeta.contractVersion,
|
|
164
109
|
veraxVersion: getVersion(),
|
|
165
110
|
nodeVersion: process.version,
|
|
166
111
|
platform: process.platform,
|
|
@@ -181,7 +126,7 @@ async function runCommandInternal(options) {
|
|
|
181
126
|
startedAt,
|
|
182
127
|
completedAt: failedAt,
|
|
183
128
|
command: 'run',
|
|
184
|
-
url
|
|
129
|
+
url,
|
|
185
130
|
notes: `Run timed out: ${reason}`,
|
|
186
131
|
}, {
|
|
187
132
|
expectationsTotal: 0,
|
|
@@ -206,73 +151,9 @@ async function runCommandInternal(options) {
|
|
|
206
151
|
});
|
|
207
152
|
};
|
|
208
153
|
|
|
209
|
-
// PHASE 25: If determinism mode, wrap execution
|
|
210
|
-
if (determinism) {
|
|
211
|
-
const scanFn = async (runConfig) => {
|
|
212
|
-
// Execute a single scan run
|
|
213
|
-
const singleRunId = generateRunId();
|
|
214
|
-
const singlePaths = getRunPaths(projectRoot, out, singleRunId);
|
|
215
|
-
ensureRunDirectories(singlePaths);
|
|
216
|
-
|
|
217
|
-
// Execute scan (reuse existing logic but with single run)
|
|
218
|
-
// This is a simplified version - in production, you'd extract the scan logic
|
|
219
|
-
const { scan } = await import('../../verax/index.js');
|
|
220
|
-
const scanResult = await scan(
|
|
221
|
-
projectRoot,
|
|
222
|
-
resolvedUrl,
|
|
223
|
-
null, // manifestPath
|
|
224
|
-
null, // scanBudgetOverride
|
|
225
|
-
{}, // safetyFlags
|
|
226
|
-
singleRunId
|
|
227
|
-
);
|
|
228
|
-
|
|
229
|
-
return {
|
|
230
|
-
runId: singleRunId,
|
|
231
|
-
artifactPaths: {
|
|
232
|
-
findings: singlePaths.findingsJson,
|
|
233
|
-
runStatus: singlePaths.runStatusJson,
|
|
234
|
-
summary: singlePaths.summaryJson,
|
|
235
|
-
learn: singlePaths.learnJson,
|
|
236
|
-
observe: singlePaths.observeJson,
|
|
237
|
-
runDir: singlePaths.baseDir
|
|
238
|
-
}
|
|
239
|
-
};
|
|
240
|
-
};
|
|
241
|
-
|
|
242
|
-
const determinismResult = await runWithDeterminism(scanFn, {
|
|
243
|
-
runs: determinismRuns,
|
|
244
|
-
out,
|
|
245
|
-
url: resolvedUrl,
|
|
246
|
-
fixture: fixtureId,
|
|
247
|
-
src,
|
|
248
|
-
verbose,
|
|
249
|
-
json
|
|
250
|
-
});
|
|
251
|
-
|
|
252
|
-
// PHASE 25: Output determinism report path
|
|
253
|
-
if (!json) {
|
|
254
|
-
console.log(`\nDeterminism check complete.`);
|
|
255
|
-
console.log(`Verdict: ${determinismResult.verdict}`);
|
|
256
|
-
console.log(`Report: ${determinismResult.reportPath}`);
|
|
257
|
-
} else {
|
|
258
|
-
console.log(JSON.stringify({
|
|
259
|
-
type: 'determinism:complete',
|
|
260
|
-
verdict: determinismResult.verdict,
|
|
261
|
-
reportPath: determinismResult.reportPath,
|
|
262
|
-
summary: determinismResult.summary
|
|
263
|
-
}));
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
return {
|
|
267
|
-
success: determinismResult.verdict === 'DETERMINISTIC' || determinismResult.verdict === 'NON_DETERMINISTIC_EXPECTED',
|
|
268
|
-
verdict: determinismResult.verdict,
|
|
269
|
-
reportPath: determinismResult.reportPath
|
|
270
|
-
};
|
|
271
|
-
}
|
|
272
|
-
|
|
273
154
|
try {
|
|
274
155
|
// Generate run ID
|
|
275
|
-
runId = generateRunId();
|
|
156
|
+
runId = generateRunId(url);
|
|
276
157
|
if (verbose && !json) console.log(`Run ID: ${runId}`);
|
|
277
158
|
|
|
278
159
|
paths = getRunPaths(projectRoot, out, runId);
|
|
@@ -323,7 +204,7 @@ async function runCommandInternal(options) {
|
|
|
323
204
|
|
|
324
205
|
atomicWriteJson(paths.runStatusJson, {
|
|
325
206
|
contractVersion: 1,
|
|
326
|
-
artifactVersions:
|
|
207
|
+
artifactVersions: getArtifactVersions(),
|
|
327
208
|
status: 'RUNNING',
|
|
328
209
|
runId,
|
|
329
210
|
startedAt,
|
|
@@ -331,16 +212,14 @@ async function runCommandInternal(options) {
|
|
|
331
212
|
|
|
332
213
|
// Write metadata
|
|
333
214
|
atomicWriteJson(paths.runMetaJson, {
|
|
334
|
-
contractVersion:
|
|
335
|
-
artifactVersions: paths.artifactVersions,
|
|
215
|
+
contractVersion: ARTIFACT_REGISTRY.runMeta.contractVersion,
|
|
336
216
|
veraxVersion: getVersion(),
|
|
337
217
|
nodeVersion: process.version,
|
|
338
218
|
platform: process.platform,
|
|
339
219
|
cwd: projectRoot,
|
|
340
220
|
command: 'run',
|
|
341
|
-
args: { url
|
|
342
|
-
url
|
|
343
|
-
fixtureId: fixtureId,
|
|
221
|
+
args: { url, src, out },
|
|
222
|
+
url,
|
|
344
223
|
src: srcPath,
|
|
345
224
|
startedAt,
|
|
346
225
|
completedAt: null,
|
|
@@ -421,7 +300,8 @@ async function runCommandInternal(options) {
|
|
|
421
300
|
paths.evidenceDir,
|
|
422
301
|
(progress) => {
|
|
423
302
|
events.emit(progress.event, progress);
|
|
424
|
-
}
|
|
303
|
+
},
|
|
304
|
+
{}
|
|
425
305
|
),
|
|
426
306
|
'Observe'
|
|
427
307
|
);
|
|
@@ -532,6 +412,32 @@ async function runCommandInternal(options) {
|
|
|
532
412
|
|
|
533
413
|
const completedAt = new Date().toISOString();
|
|
534
414
|
|
|
415
|
+
// Write completed status
|
|
416
|
+
atomicWriteJson(paths.runStatusJson, {
|
|
417
|
+
contractVersion: 1,
|
|
418
|
+
artifactVersions: getArtifactVersions(),
|
|
419
|
+
status: 'COMPLETE',
|
|
420
|
+
runId,
|
|
421
|
+
startedAt,
|
|
422
|
+
completedAt,
|
|
423
|
+
});
|
|
424
|
+
|
|
425
|
+
// Update metadata with completion time
|
|
426
|
+
atomicWriteJson(paths.runMetaJson, {
|
|
427
|
+
contractVersion: ARTIFACT_REGISTRY.runMeta.contractVersion,
|
|
428
|
+
veraxVersion: getVersion(),
|
|
429
|
+
nodeVersion: process.version,
|
|
430
|
+
platform: process.platform,
|
|
431
|
+
cwd: projectRoot,
|
|
432
|
+
command: 'run',
|
|
433
|
+
args: { url, src, out },
|
|
434
|
+
url,
|
|
435
|
+
src: srcPath,
|
|
436
|
+
startedAt,
|
|
437
|
+
completedAt,
|
|
438
|
+
error: null,
|
|
439
|
+
});
|
|
440
|
+
|
|
535
441
|
const runDurationMs = completedAt && startedAt ? (Date.parse(completedAt) - Date.parse(startedAt)) : 0;
|
|
536
442
|
const metrics = {
|
|
537
443
|
learnMs: observeData?.timings?.learnMs || 0,
|
|
@@ -546,9 +452,6 @@ async function runCommandInternal(options) {
|
|
|
546
452
|
UNKNOWN: 0,
|
|
547
453
|
};
|
|
548
454
|
|
|
549
|
-
// Write detect results (or empty if detection failed)
|
|
550
|
-
const findingsResult = writeFindingsJson(paths.baseDir, detectData);
|
|
551
|
-
|
|
552
455
|
// Write summary with stable digest
|
|
553
456
|
writeSummaryJson(paths.summaryJson, {
|
|
554
457
|
runId,
|
|
@@ -572,6 +475,9 @@ async function runCommandInternal(options) {
|
|
|
572
475
|
...findingsCounts,
|
|
573
476
|
});
|
|
574
477
|
|
|
478
|
+
// Write detect results (or empty if detection failed)
|
|
479
|
+
writeFindingsJson(paths.baseDir, detectData);
|
|
480
|
+
|
|
575
481
|
// Write traces (include all events including heartbeats)
|
|
576
482
|
const allEvents = events.getEvents();
|
|
577
483
|
const tracesContent = allEvents
|
|
@@ -587,78 +493,12 @@ async function runCommandInternal(options) {
|
|
|
587
493
|
|
|
588
494
|
// Write observe results
|
|
589
495
|
writeObserveJson(paths.baseDir, observeData);
|
|
590
|
-
|
|
591
|
-
// PHASE 6: Verify artifacts after all writers finish
|
|
592
|
-
const { verifyRun } = await import('../../verax/core/artifacts/verifier.js');
|
|
593
|
-
const verification = verifyRun(paths.baseDir, paths.artifactVersions);
|
|
594
|
-
|
|
595
|
-
// Determine final status based on verification
|
|
596
|
-
let finalStatus = 'COMPLETE';
|
|
597
|
-
if (!verification.ok) {
|
|
598
|
-
finalStatus = 'INVALID';
|
|
599
|
-
} else if (verification.warnings.length > 0) {
|
|
600
|
-
finalStatus = 'VALID_WITH_WARNINGS';
|
|
601
|
-
}
|
|
602
496
|
|
|
603
|
-
//
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
const decisionsPath = resolve(paths.baseDir, 'decisions.json');
|
|
607
|
-
if (existsSync(decisionsPath)) {
|
|
608
|
-
const decisions = JSON.parse(readFileSync(decisionsPath, 'utf-8'));
|
|
609
|
-
const { DecisionRecorder } = await import('../../verax/core/determinism-model.js');
|
|
610
|
-
const recorder = DecisionRecorder.fromExport(decisions);
|
|
611
|
-
const { computeDeterminismVerdict } = await import('../../verax/core/determinism/contract.js');
|
|
612
|
-
const verdict = computeDeterminismVerdict(recorder);
|
|
613
|
-
|
|
614
|
-
determinismSummary = {
|
|
615
|
-
verdict: verdict.verdict, // DETERMINISTIC or NON_DETERMINISTIC
|
|
616
|
-
message: verdict.message,
|
|
617
|
-
adaptiveEventsCount: verdict.adaptiveEvents.length
|
|
618
|
-
};
|
|
619
|
-
}
|
|
620
|
-
} catch (error) {
|
|
621
|
-
// Ignore errors - determinism summary is optional
|
|
497
|
+
// H5: Write deterministic digest for reproducibility proof
|
|
498
|
+
if (observeData && observeData.digest) {
|
|
499
|
+
saveDigest(resolve(paths.baseDir, 'run.digest.json'), observeData.digest);
|
|
622
500
|
}
|
|
623
501
|
|
|
624
|
-
// Write completed status with contract + enforcement snapshot + verification + determinism
|
|
625
|
-
atomicWriteJson(paths.runStatusJson, {
|
|
626
|
-
contractVersion: 1,
|
|
627
|
-
artifactVersions: paths.artifactVersions,
|
|
628
|
-
status: finalStatus,
|
|
629
|
-
runId,
|
|
630
|
-
startedAt,
|
|
631
|
-
completedAt,
|
|
632
|
-
enforcement: findingsResult?.payload?.enforcement || null,
|
|
633
|
-
verification: {
|
|
634
|
-
ok: verification.ok,
|
|
635
|
-
status: finalStatus,
|
|
636
|
-
errorsCount: verification.errors.length,
|
|
637
|
-
warningsCount: verification.warnings.length,
|
|
638
|
-
verifiedAt: verification.verifiedAt
|
|
639
|
-
},
|
|
640
|
-
// PHASE 21.2: Determinism summary
|
|
641
|
-
determinismSummary: determinismSummary
|
|
642
|
-
});
|
|
643
|
-
|
|
644
|
-
// Update metadata with completion time
|
|
645
|
-
atomicWriteJson(paths.runMetaJson, {
|
|
646
|
-
contractVersion: 1,
|
|
647
|
-
artifactVersions: paths.artifactVersions,
|
|
648
|
-
veraxVersion: getVersion(),
|
|
649
|
-
nodeVersion: process.version,
|
|
650
|
-
platform: process.platform,
|
|
651
|
-
cwd: projectRoot,
|
|
652
|
-
command: 'run',
|
|
653
|
-
args: { url: resolvedUrl, fixture: fixtureId, src, out },
|
|
654
|
-
url: resolvedUrl,
|
|
655
|
-
fixtureId: fixtureId,
|
|
656
|
-
src: srcPath,
|
|
657
|
-
startedAt,
|
|
658
|
-
completedAt,
|
|
659
|
-
error: null,
|
|
660
|
-
});
|
|
661
|
-
|
|
662
502
|
events.emit('phase:completed', {
|
|
663
503
|
phase: 'Finalize Artifacts',
|
|
664
504
|
message: 'Run artifacts written',
|
|
@@ -686,37 +526,27 @@ async function runCommandInternal(options) {
|
|
|
686
526
|
|
|
687
527
|
// Print summary if not JSON mode
|
|
688
528
|
if (!json) {
|
|
689
|
-
|
|
690
|
-
console.log(
|
|
691
|
-
console.log(
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
}
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
529
|
+
const relativePath = paths.baseDir.replace(/\\/g, '/').split('/').slice(-1)[0];
|
|
530
|
+
console.log('');
|
|
531
|
+
console.log('VERAX — Silent Failure Detection');
|
|
532
|
+
console.log('');
|
|
533
|
+
console.log(`✔ URL: ${url}`);
|
|
534
|
+
console.log('');
|
|
535
|
+
console.log('Learn phase:');
|
|
536
|
+
console.log(` → Extracted ${expectations.length} promises`);
|
|
537
|
+
console.log('');
|
|
538
|
+
console.log('Observe phase:');
|
|
539
|
+
console.log(` → Executed ${observeData.stats?.attempted || 0} interactions`);
|
|
540
|
+
console.log(` → Observed: ${observeData.stats?.observed || 0}/${observeData.stats?.attempted || 0}`);
|
|
541
|
+
console.log('');
|
|
542
|
+
console.log('Detect phase:');
|
|
543
|
+
console.log(` → Silent failures: ${detectData.stats?.silentFailures || 0}`);
|
|
544
|
+
console.log(` → Unproven: ${detectData.stats?.unproven || 0}`);
|
|
545
|
+
console.log(` → Coverage gaps: ${detectData.stats?.coverageGaps || 0}`);
|
|
546
|
+
console.log('');
|
|
547
|
+
console.log('Artifacts written to:');
|
|
548
|
+
console.log(` .verax/runs/${relativePath}/`);
|
|
709
549
|
console.log('');
|
|
710
|
-
console.log(verificationOutput);
|
|
711
|
-
|
|
712
|
-
// PHASE 21.9: Display performance metrics
|
|
713
|
-
const { loadPerformanceReport } = await import('../../verax/core/perf/perf.report.js');
|
|
714
|
-
const { formatPerformanceMetrics } = await import('../../verax/core/perf/perf.display.js');
|
|
715
|
-
const perfReport = loadPerformanceReport(projectRoot, runId);
|
|
716
|
-
if (perfReport) {
|
|
717
|
-
console.log('');
|
|
718
|
-
console.log(formatPerformanceMetrics(perfReport));
|
|
719
|
-
}
|
|
720
550
|
}
|
|
721
551
|
|
|
722
552
|
return { runId, paths, success: true };
|
|
@@ -735,7 +565,7 @@ async function runCommandInternal(options) {
|
|
|
735
565
|
const failedAt = new Date().toISOString();
|
|
736
566
|
atomicWriteJson(paths.runStatusJson, {
|
|
737
567
|
contractVersion: 1,
|
|
738
|
-
artifactVersions:
|
|
568
|
+
artifactVersions: getArtifactVersions(),
|
|
739
569
|
status: 'FAILED',
|
|
740
570
|
runId,
|
|
741
571
|
startedAt,
|
|
@@ -745,16 +575,14 @@ async function runCommandInternal(options) {
|
|
|
745
575
|
|
|
746
576
|
// Update metadata
|
|
747
577
|
atomicWriteJson(paths.runMetaJson, {
|
|
748
|
-
contractVersion:
|
|
749
|
-
artifactVersions: paths.artifactVersions,
|
|
578
|
+
contractVersion: ARTIFACT_REGISTRY.runMeta.contractVersion,
|
|
750
579
|
veraxVersion: getVersion(),
|
|
751
580
|
nodeVersion: process.version,
|
|
752
581
|
platform: process.platform,
|
|
753
582
|
cwd: projectRoot,
|
|
754
583
|
command: 'run',
|
|
755
|
-
args: { url
|
|
756
|
-
url
|
|
757
|
-
fixtureId: fixtureId,
|
|
584
|
+
args: { url, src, out },
|
|
585
|
+
url,
|
|
758
586
|
src: srcPath,
|
|
759
587
|
startedAt,
|
|
760
588
|
completedAt: failedAt,
|
|
@@ -769,7 +597,7 @@ async function runCommandInternal(options) {
|
|
|
769
597
|
startedAt,
|
|
770
598
|
completedAt: failedAt,
|
|
771
599
|
command: 'run',
|
|
772
|
-
url
|
|
600
|
+
url,
|
|
773
601
|
notes: `Run failed: ${error.message}`,
|
|
774
602
|
}, {
|
|
775
603
|
expectationsTotal: 0,
|
|
@@ -10,7 +10,7 @@ import { scanVulnerabilities, writeVulnReport } from '../../verax/core/security/
|
|
|
10
10
|
import { evaluateSupplyChainPolicy, writeSupplyChainReport } from '../../verax/core/security/supplychain.policy.js';
|
|
11
11
|
import { writeSecurityReport } from '../../verax/core/security/security-report.js';
|
|
12
12
|
import { resolve } from 'path';
|
|
13
|
-
import { mkdirSync, existsSync } from 'fs';
|
|
13
|
+
import { mkdirSync as _mkdirSync, existsSync } from 'fs';
|
|
14
14
|
|
|
15
15
|
/**
|
|
16
16
|
* Security check command
|
|
@@ -116,6 +116,7 @@ export async function securityCheckCommand(options = {}) {
|
|
|
116
116
|
const secretsPath = resolve(projectDir, 'release', 'security.secrets.report.json');
|
|
117
117
|
if (existsSync(secretsPath)) {
|
|
118
118
|
const { readFileSync } = await import('fs');
|
|
119
|
+
// @ts-expect-error - readFileSync with encoding returns string
|
|
119
120
|
secretsReport = JSON.parse(readFileSync(secretsPath, 'utf-8'));
|
|
120
121
|
}
|
|
121
122
|
} catch {
|