@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
|
@@ -22,6 +22,7 @@ function getDependencies(projectDir) {
|
|
|
22
22
|
if (!existsSync(pkgPath)) {
|
|
23
23
|
return { dependencies: {}, devDependencies: {} };
|
|
24
24
|
}
|
|
25
|
+
// @ts-expect-error - readFileSync with encoding returns string
|
|
25
26
|
const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));
|
|
26
27
|
return {
|
|
27
28
|
dependencies: pkg.dependencies || {},
|
|
@@ -32,6 +33,29 @@ function getDependencies(projectDir) {
|
|
|
32
33
|
}
|
|
33
34
|
}
|
|
34
35
|
|
|
36
|
+
/**
|
|
37
|
+
* Helper to traverse dependency tree recursively
|
|
38
|
+
*/
|
|
39
|
+
function traverseDepsHelper(deps, packages, parent = null) {
|
|
40
|
+
if (!deps || typeof deps !== 'object') {
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
for (const [name, info] of Object.entries(deps)) {
|
|
45
|
+
if (info && typeof info === 'object' && info.version) {
|
|
46
|
+
packages.push({
|
|
47
|
+
name,
|
|
48
|
+
version: info.version,
|
|
49
|
+
parent: parent || null
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
if (info.dependencies) {
|
|
53
|
+
traverseDepsHelper(info.dependencies, packages, name);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
35
59
|
/**
|
|
36
60
|
* Get transitive dependencies from node_modules
|
|
37
61
|
*
|
|
@@ -47,37 +71,18 @@ function getTransitiveDependencies(projectDir) {
|
|
|
47
71
|
}
|
|
48
72
|
|
|
49
73
|
try {
|
|
50
|
-
// Use npm ls to get dependency tree
|
|
74
|
+
// Use npm ls to get dependency tree (with timeout to prevent hanging)
|
|
51
75
|
const result = execSync('npm ls --all --json', {
|
|
52
76
|
cwd: projectDir,
|
|
53
77
|
encoding: 'utf-8',
|
|
54
|
-
stdio: ['ignore', 'pipe', 'ignore']
|
|
78
|
+
stdio: ['ignore', 'pipe', 'ignore'],
|
|
79
|
+
timeout: 5000 // 5 second timeout
|
|
55
80
|
});
|
|
56
81
|
|
|
57
82
|
const tree = JSON.parse(result);
|
|
58
83
|
|
|
59
|
-
function traverseDeps(deps, parent = null) {
|
|
60
|
-
if (!deps || typeof deps !== 'object') {
|
|
61
|
-
return;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
for (const [name, info] of Object.entries(deps)) {
|
|
65
|
-
if (info && typeof info === 'object' && info.version) {
|
|
66
|
-
packages.push({
|
|
67
|
-
name,
|
|
68
|
-
version: info.version,
|
|
69
|
-
parent: parent || null
|
|
70
|
-
});
|
|
71
|
-
|
|
72
|
-
if (info.dependencies) {
|
|
73
|
-
traverseDeps(info.dependencies, name);
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
|
|
79
84
|
if (tree.dependencies) {
|
|
80
|
-
|
|
85
|
+
traverseDepsHelper(tree.dependencies, packages);
|
|
81
86
|
}
|
|
82
87
|
} catch {
|
|
83
88
|
// Fallback: scan node_modules directory
|
|
@@ -89,6 +94,7 @@ function getTransitiveDependencies(projectDir) {
|
|
|
89
94
|
const pkgPath = resolve(nodeModulesPath, entry.name, 'package.json');
|
|
90
95
|
if (existsSync(pkgPath)) {
|
|
91
96
|
try {
|
|
97
|
+
// @ts-expect-error - readFileSync with encoding returns string
|
|
92
98
|
const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));
|
|
93
99
|
packages.push({
|
|
94
100
|
name: pkg.name || entry.name,
|
|
@@ -120,6 +126,7 @@ function getPackageLicense(packagePath) {
|
|
|
120
126
|
if (!existsSync(packagePath)) {
|
|
121
127
|
return null;
|
|
122
128
|
}
|
|
129
|
+
// @ts-expect-error - readFileSync with encoding returns string
|
|
123
130
|
const pkg = JSON.parse(readFileSync(packagePath, 'utf-8'));
|
|
124
131
|
if (typeof pkg.license === 'string') {
|
|
125
132
|
return pkg.license;
|
|
@@ -150,6 +157,7 @@ function getPackageIntegrity(projectDir, packageName) {
|
|
|
150
157
|
const pkgPath = resolve(packagePath, 'package.json');
|
|
151
158
|
if (existsSync(pkgPath)) {
|
|
152
159
|
const content = readFileSync(pkgPath);
|
|
160
|
+
// @ts-expect-error - digest returns string
|
|
153
161
|
return createHash('sha256').update(content).digest('hex');
|
|
154
162
|
}
|
|
155
163
|
|
|
@@ -171,6 +179,7 @@ export async function buildSBOM(projectDir) {
|
|
|
171
179
|
throw new Error('Cannot build SBOM: package.json not found');
|
|
172
180
|
}
|
|
173
181
|
|
|
182
|
+
// @ts-expect-error - readFileSync with encoding returns string
|
|
174
183
|
const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));
|
|
175
184
|
const deps = getDependencies(projectDir);
|
|
176
185
|
const transitive = getTransitiveDependencies(projectDir);
|
|
@@ -292,7 +292,9 @@ export function validateReplay(baselinePath, currentPath) {
|
|
|
292
292
|
throw new Error(`Current decisions not found: ${currentPath}`);
|
|
293
293
|
}
|
|
294
294
|
|
|
295
|
+
// @ts-expect-error - readFileSync with encoding returns string
|
|
295
296
|
const baseline = JSON.parse(fs.readFileSync(baselinePath, 'utf-8'));
|
|
297
|
+
// @ts-expect-error - readFileSync with encoding returns string
|
|
296
298
|
const current = JSON.parse(fs.readFileSync(currentPath, 'utf-8'));
|
|
297
299
|
|
|
298
300
|
return compareReplayDecisions(baseline, current);
|
package/src/verax/core/replay.js
CHANGED
|
@@ -32,6 +32,7 @@ export function loadRunArtifacts(runDir) {
|
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
try {
|
|
35
|
+
// @ts-expect-error - readFileSync with encoding returns string
|
|
35
36
|
artifacts.runManifest = JSON.parse(readFileSync(runManifestPath, 'utf-8'));
|
|
36
37
|
} catch (error) {
|
|
37
38
|
throw new Error(`Failed to parse run manifest: ${error.message}`);
|
|
@@ -44,6 +45,7 @@ export function loadRunArtifacts(runDir) {
|
|
|
44
45
|
const tracesPath = join(runDir, 'traces.json');
|
|
45
46
|
if (existsSync(tracesPath)) {
|
|
46
47
|
try {
|
|
48
|
+
// @ts-expect-error - readFileSync with encoding returns string
|
|
47
49
|
artifacts.traces = JSON.parse(readFileSync(tracesPath, 'utf-8'));
|
|
48
50
|
|
|
49
51
|
// Verify hash
|
|
@@ -80,6 +82,7 @@ export function loadRunArtifacts(runDir) {
|
|
|
80
82
|
const findingsPath = join(runDir, 'findings.json');
|
|
81
83
|
if (existsSync(findingsPath)) {
|
|
82
84
|
try {
|
|
85
|
+
// @ts-expect-error - readFileSync with encoding returns string
|
|
83
86
|
artifacts.findings = JSON.parse(readFileSync(findingsPath, 'utf-8'));
|
|
84
87
|
|
|
85
88
|
// Verify hash
|
|
@@ -109,6 +112,7 @@ export function loadRunArtifacts(runDir) {
|
|
|
109
112
|
const manifestPath = join(runDir, 'manifest.json');
|
|
110
113
|
if (existsSync(manifestPath)) {
|
|
111
114
|
try {
|
|
115
|
+
// @ts-expect-error - readFileSync with encoding returns string
|
|
112
116
|
artifacts.manifest = JSON.parse(readFileSync(manifestPath, 'utf-8'));
|
|
113
117
|
|
|
114
118
|
// Verify hash
|
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
* Builds cross-index linking findingId to all related artifacts.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import { readFileSync, existsSync, writeFileSync, readdirSync } from 'fs';
|
|
8
|
-
import { resolve, relative } from 'path';
|
|
7
|
+
import { readFileSync, existsSync, writeFileSync, readdirSync as _readdirSync } from 'fs';
|
|
8
|
+
import { resolve, relative as _relative } from 'path';
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* Build cross-index
|
|
@@ -34,8 +34,9 @@ export function buildCrossIndex(projectDir, runId) {
|
|
|
34
34
|
};
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
+
// @ts-expect-error - readFileSync with encoding returns string
|
|
37
38
|
const findings = JSON.parse(readFileSync(findingsPath, 'utf-8'));
|
|
38
|
-
const
|
|
39
|
+
const _evidenceIndex = loadArtifact(runDir, 'evidence.index.json');
|
|
39
40
|
const decisionTrace = loadArtifact(runDir, 'decisions.trace.json');
|
|
40
41
|
const timeline = loadArtifact(runDir, 'run.timeline.json');
|
|
41
42
|
const failureLedger = loadArtifact(runDir, 'failure.ledger.json');
|
|
@@ -147,6 +148,7 @@ function loadArtifact(runDir, filename) {
|
|
|
147
148
|
return null;
|
|
148
149
|
}
|
|
149
150
|
try {
|
|
151
|
+
// @ts-expect-error - readFileSync with encoding returns string
|
|
150
152
|
return JSON.parse(readFileSync(path, 'utf-8'));
|
|
151
153
|
} catch {
|
|
152
154
|
return null;
|
|
@@ -184,6 +186,7 @@ export function loadCrossIndex(projectDir, runId) {
|
|
|
184
186
|
}
|
|
185
187
|
|
|
186
188
|
try {
|
|
189
|
+
// @ts-expect-error - readFileSync with encoding returns string
|
|
187
190
|
return JSON.parse(readFileSync(indexPath, 'utf-8'));
|
|
188
191
|
} catch {
|
|
189
192
|
return null;
|
|
@@ -17,6 +17,7 @@ function loadArtifact(runDir, filename) {
|
|
|
17
17
|
return null;
|
|
18
18
|
}
|
|
19
19
|
try {
|
|
20
|
+
// @ts-expect-error - readFileSync with encoding returns string
|
|
20
21
|
return JSON.parse(readFileSync(path, 'utf-8'));
|
|
21
22
|
} catch {
|
|
22
23
|
return null;
|
|
@@ -28,7 +29,7 @@ function loadArtifact(runDir, filename) {
|
|
|
28
29
|
*
|
|
29
30
|
* @param {string} projectDir - Project directory
|
|
30
31
|
* @param {string} runId - Run ID
|
|
31
|
-
* @returns {Object} Human summary
|
|
32
|
+
* @returns {Promise<Object>} Human summary
|
|
32
33
|
*/
|
|
33
34
|
export async function generateHumanSummary(projectDir, runId) {
|
|
34
35
|
const runDir = resolve(projectDir, '.verax', 'runs', runId);
|
|
@@ -101,8 +102,10 @@ export async function generateHumanSummary(projectDir, runId) {
|
|
|
101
102
|
let determinismVerdict = 'UNKNOWN';
|
|
102
103
|
if (determinism) {
|
|
103
104
|
try {
|
|
105
|
+
// @ts-expect-error - Dynamic import path
|
|
104
106
|
const { DecisionRecorder } = await import('../../../core/determinism-model.js');
|
|
105
107
|
const recorder = DecisionRecorder.fromExport(determinism);
|
|
108
|
+
// @ts-expect-error - Dynamic import path
|
|
106
109
|
const { computeDeterminismVerdict } = await import('../../../core/determinism/contract.js');
|
|
107
110
|
const verdict = computeDeterminismVerdict(recorder);
|
|
108
111
|
determinismVerdict = verdict.verdict;
|
|
@@ -178,6 +181,101 @@ export async function generateHumanSummary(projectDir, runId) {
|
|
|
178
181
|
};
|
|
179
182
|
}
|
|
180
183
|
|
|
184
|
+
/**
|
|
185
|
+
* Format finding with Human-Readable Report Contract v1
|
|
186
|
+
* Six-line template per finding
|
|
187
|
+
*/
|
|
188
|
+
function formatFinding(finding, index) {
|
|
189
|
+
const lines = [];
|
|
190
|
+
lines.push(`\nFinding #${index + 1}`);
|
|
191
|
+
|
|
192
|
+
// Summary: what the user did (handle both old and new format)
|
|
193
|
+
const summary = finding.what_happened ||
|
|
194
|
+
(finding.interaction ? `User interacted with ${finding.interaction.target || 'element'}` : '') ||
|
|
195
|
+
(finding.promise ? `Expected ${finding.promise.kind}: ${finding.promise.value}` : '') ||
|
|
196
|
+
'Interaction occurred';
|
|
197
|
+
lines.push(` Summary: ${summary}`);
|
|
198
|
+
|
|
199
|
+
// Expected: what user expected (handle both old and new format)
|
|
200
|
+
const expected = finding.what_was_expected ||
|
|
201
|
+
(finding.promise ? `${finding.promise.kind} ${finding.promise.value}` : '') ||
|
|
202
|
+
'Expected behavior not specified';
|
|
203
|
+
lines.push(` Expected: ${expected}`);
|
|
204
|
+
|
|
205
|
+
// Observed: what actually happened (handle both old and new format)
|
|
206
|
+
const observed = finding.what_was_observed ||
|
|
207
|
+
finding.reason ||
|
|
208
|
+
(finding.classification ? `${finding.classification}` : '') ||
|
|
209
|
+
'Actual behavior not specified';
|
|
210
|
+
lines.push(` Observed: ${observed}`);
|
|
211
|
+
|
|
212
|
+
// Evidence (before) - Use interaction ID or finding ID as stable reference
|
|
213
|
+
const beforeId = finding.interaction?.sequenceId
|
|
214
|
+
? `UI#${finding.interaction.sequenceId}`
|
|
215
|
+
: finding.id ? `REF#${finding.id}`
|
|
216
|
+
: 'UI#?';
|
|
217
|
+
lines.push(` Evidence (before): ${beforeId}`);
|
|
218
|
+
|
|
219
|
+
// Evidence (after) - Use evidence package references if available
|
|
220
|
+
const afterIds = [];
|
|
221
|
+
if (finding.evidencePackage?.evidence?.dom) afterIds.push('DOM#' + (finding.interaction?.sequenceId || finding.id || '?'));
|
|
222
|
+
if (finding.evidencePackage?.evidence?.network) afterIds.push('NET#' + (finding.interaction?.sequenceId || finding.id || '?'));
|
|
223
|
+
if (finding.evidencePackage?.evidence?.console) afterIds.push('LOG#' + (finding.interaction?.sequenceId || finding.id || '?'));
|
|
224
|
+
const afterId = afterIds.length > 0
|
|
225
|
+
? afterIds.join(', ')
|
|
226
|
+
: finding.id ? `REF#${finding.id}`
|
|
227
|
+
: 'UI#?';
|
|
228
|
+
lines.push(` Evidence (after): ${afterId}`);
|
|
229
|
+
|
|
230
|
+
// Why this matters - Neutral impact statement
|
|
231
|
+
const impact = finding.signals?.impact || finding.impact || 'UNKNOWN';
|
|
232
|
+
const userRisk = finding.signals?.userRisk || 'affects user workflow';
|
|
233
|
+
lines.push(` Why this matters: ${impact} impact, ${userRisk}`);
|
|
234
|
+
|
|
235
|
+
return lines.join('\n');
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* Format coverage transparency block
|
|
240
|
+
*/
|
|
241
|
+
function formatCoverage(summary) {
|
|
242
|
+
const lines = [];
|
|
243
|
+
lines.push('\n' + '='.repeat(80));
|
|
244
|
+
lines.push('COVERAGE');
|
|
245
|
+
lines.push('='.repeat(80));
|
|
246
|
+
|
|
247
|
+
// Tested interactions (confirmed + suspected findings)
|
|
248
|
+
const testedCount = summary.whatWeKnow.confident.findings + summary.whatWeKnow.notConfident.findings;
|
|
249
|
+
lines.push(`\nTested interactions: ${testedCount}`);
|
|
250
|
+
if (testedCount > 0) {
|
|
251
|
+
lines.push(` ${summary.whatWeKnow.confident.findings} with complete evidence`);
|
|
252
|
+
lines.push(` ${summary.whatWeKnow.notConfident.findings} with incomplete evidence`);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// Skipped interactions (aggregated by canonical enum)
|
|
256
|
+
if (summary.whatWeKnow.skips && summary.whatWeKnow.skips.canonicalReasons) {
|
|
257
|
+
lines.push(`\nSkipped interactions: ${summary.whatWeKnow.skips.total}`);
|
|
258
|
+
for (const skip of summary.whatWeKnow.skips.canonicalReasons) {
|
|
259
|
+
lines.push(` ${skip.canonical}: ${skip.count}`);
|
|
260
|
+
}
|
|
261
|
+
} else if (summary.whatWeKnow.skips) {
|
|
262
|
+
// Backward compatibility: use raw reasons if canonical not available
|
|
263
|
+
lines.push(`\nSkipped interactions: ${summary.whatWeKnow.skips.total}`);
|
|
264
|
+
for (const skip of summary.whatWeKnow.skips.reasons) {
|
|
265
|
+
lines.push(` ${skip.code || skip.reason}: ${skip.count}`);
|
|
266
|
+
}
|
|
267
|
+
} else {
|
|
268
|
+
lines.push(`\nSkipped interactions: 0`);
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
// Coverage disclaimer
|
|
272
|
+
lines.push('');
|
|
273
|
+
lines.push('Coverage indicates what was observed in this run; it does not guarantee absence of issues.');
|
|
274
|
+
lines.push('='.repeat(80));
|
|
275
|
+
|
|
276
|
+
return lines.join('\n');
|
|
277
|
+
}
|
|
278
|
+
|
|
181
279
|
/**
|
|
182
280
|
* Format human summary for CLI display
|
|
183
281
|
*
|
|
@@ -220,3 +318,45 @@ export function formatHumanSummary(summary) {
|
|
|
220
318
|
return lines.join('\n');
|
|
221
319
|
}
|
|
222
320
|
|
|
321
|
+
/**
|
|
322
|
+
* Format detailed findings report with Human-Readable Report Contract v1
|
|
323
|
+
* Adds six-line finding summaries + coverage transparency
|
|
324
|
+
*
|
|
325
|
+
* @param {string} projectDir - Project directory
|
|
326
|
+
* @param {string} runId - Run ID
|
|
327
|
+
* @returns {Promise<string>} Formatted report
|
|
328
|
+
*/
|
|
329
|
+
export async function formatFindingsReport(projectDir, runId) {
|
|
330
|
+
const runDir = resolve(projectDir, '.verax', 'runs', runId);
|
|
331
|
+
const findings = loadArtifact(runDir, 'findings.json');
|
|
332
|
+
const summary = await generateHumanSummary(projectDir, runId);
|
|
333
|
+
|
|
334
|
+
if (!findings || !summary) {
|
|
335
|
+
return 'Findings report not available';
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
const lines = [];
|
|
339
|
+
lines.push('\n' + '='.repeat(80));
|
|
340
|
+
lines.push('FINDINGS REPORT (Human-Readable Contract v1)');
|
|
341
|
+
lines.push('='.repeat(80));
|
|
342
|
+
|
|
343
|
+
const findingsArray = findings.findings || [];
|
|
344
|
+
|
|
345
|
+
if (findingsArray.length === 0) {
|
|
346
|
+
lines.push('\nNo findings detected');
|
|
347
|
+
} else {
|
|
348
|
+
lines.push(`\nTotal findings: ${findingsArray.length}`);
|
|
349
|
+
|
|
350
|
+
// Format each finding with 6-line template
|
|
351
|
+
for (let i = 0; i < findingsArray.length; i++) {
|
|
352
|
+
lines.push(formatFinding(findingsArray[i], i));
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
// Add coverage transparency block
|
|
357
|
+
lines.push(formatCoverage(summary));
|
|
358
|
+
lines.push('='.repeat(80) + '\n');
|
|
359
|
+
|
|
360
|
+
return lines.join('\n');
|
|
361
|
+
}
|
|
362
|
+
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* - Provides evidence for route-related findings
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
-
import { normalizeDynamicRoute, isDynamicPath, normalizeNavigationTarget } from '../shared/dynamic-route-utils.js';
|
|
11
|
+
import { normalizeDynamicRoute as _normalizeDynamicRoute, isDynamicPath, normalizeNavigationTarget } from '../shared/dynamic-route-utils.js';
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
14
|
* Route Taxonomy
|
|
@@ -392,10 +392,11 @@ export function buildRouteEvidence(correlation, navigationPromise, evaluation, t
|
|
|
392
392
|
* PHASE 12: Check if route change is false positive
|
|
393
393
|
*
|
|
394
394
|
* @param {Object} trace - Interaction trace
|
|
395
|
-
* @param {Object}
|
|
395
|
+
* @param {Object} _correlation - Route correlation
|
|
396
|
+
* @ts-expect-error - JSDoc param documented but unused
|
|
396
397
|
* @returns {boolean} True if should be ignored (false positive)
|
|
397
398
|
*/
|
|
398
|
-
export function isRouteChangeFalsePositive(trace,
|
|
399
|
+
export function isRouteChangeFalsePositive(trace, _correlation) {
|
|
399
400
|
const sensors = trace.sensors || {};
|
|
400
401
|
const navSensor = sensors.navigation || {};
|
|
401
402
|
|
package/src/verax/core/run-id.js
CHANGED
|
@@ -20,6 +20,7 @@ const __dirname = dirname(__filename);
|
|
|
20
20
|
export function getVeraxVersion() {
|
|
21
21
|
try {
|
|
22
22
|
const packagePath = join(__dirname, '..', '..', '..', 'package.json');
|
|
23
|
+
// @ts-expect-error - readFileSync with encoding returns string
|
|
23
24
|
const pkg = JSON.parse(readFileSync(packagePath, 'utf-8'));
|
|
24
25
|
return pkg.version || '0.1.0';
|
|
25
26
|
} catch (error) {
|
|
@@ -35,7 +36,7 @@ export function getVeraxVersion() {
|
|
|
35
36
|
*
|
|
36
37
|
* @param {Object} params - Run parameters
|
|
37
38
|
* @param {string} params.url - Target URL
|
|
38
|
-
* @param {Object} params.safetyFlags - Safety flags (
|
|
39
|
+
* @param {Object} params.safetyFlags - Safety flags (allowRiskyActions, allowCrossOrigin)
|
|
39
40
|
* @param {string} params.baseOrigin - Base origin
|
|
40
41
|
* @param {Object} params.scanBudget - Scan budget configuration
|
|
41
42
|
* @param {string} params.manifestPath - Optional manifest path
|
|
@@ -44,11 +45,11 @@ export function getVeraxVersion() {
|
|
|
44
45
|
export function generateRunId(params) {
|
|
45
46
|
const { url, safetyFlags = {}, baseOrigin, scanBudget, manifestPath = null } = params;
|
|
46
47
|
|
|
47
|
-
// Sort flags deterministically
|
|
48
|
+
// Sort flags deterministically (allowWrites permanently false - constitutional)
|
|
48
49
|
const sortedFlags = {
|
|
49
50
|
allowCrossOrigin: safetyFlags.allowCrossOrigin || false,
|
|
50
51
|
allowRiskyActions: safetyFlags.allowRiskyActions || false,
|
|
51
|
-
allowWrites:
|
|
52
|
+
allowWrites: false // CONSTITUTIONAL: Always false (read-only mode)
|
|
52
53
|
};
|
|
53
54
|
|
|
54
55
|
// Create deterministic representation
|
|
@@ -81,6 +82,7 @@ export function generateRunId(params) {
|
|
|
81
82
|
const hash = createHash('sha256').update(configString).digest('hex');
|
|
82
83
|
|
|
83
84
|
// Return first 16 chars for readability (still collision-resistant)
|
|
85
|
+
// @ts-expect-error - digest returns string
|
|
84
86
|
return hash.substring(0, 16);
|
|
85
87
|
}
|
|
86
88
|
|
|
@@ -146,6 +148,7 @@ export function getExpectedArtifacts(projectDir, runId) {
|
|
|
146
148
|
export function computeFileHash(filePath) {
|
|
147
149
|
try {
|
|
148
150
|
const content = readFileSync(filePath);
|
|
151
|
+
// @ts-expect-error - digest returns string
|
|
149
152
|
return createHash('sha256').update(content).digest('hex');
|
|
150
153
|
} catch (error) {
|
|
151
154
|
return null;
|
|
@@ -34,13 +34,13 @@ export function createRunManifest(projectDir, runId, params) {
|
|
|
34
34
|
url,
|
|
35
35
|
baseOrigin,
|
|
36
36
|
flags: {
|
|
37
|
-
allowWrites:
|
|
37
|
+
allowWrites: false, // CONSTITUTIONAL: Always false (read-only mode)
|
|
38
38
|
allowRiskyActions: safetyFlags.allowRiskyActions || false,
|
|
39
39
|
allowCrossOrigin: safetyFlags.allowCrossOrigin || false
|
|
40
40
|
},
|
|
41
41
|
safeMode: {
|
|
42
|
-
enabled:
|
|
43
|
-
writesBlocked:
|
|
42
|
+
enabled: true, // Always enabled (constitutional enforcement)
|
|
43
|
+
writesBlocked: true, // CONSTITUTIONAL: Always blocked
|
|
44
44
|
riskyActionsBlocked: !safetyFlags.allowRiskyActions,
|
|
45
45
|
crossOriginBlocked: !safetyFlags.allowCrossOrigin
|
|
46
46
|
},
|
|
@@ -89,6 +89,7 @@ export function updateRunManifestHashes(projectDir, runId, hashes) {
|
|
|
89
89
|
const runManifestPath = `${runDir}/run-manifest.json`;
|
|
90
90
|
|
|
91
91
|
try {
|
|
92
|
+
// @ts-expect-error - readFileSync with encoding returns string
|
|
92
93
|
const runManifest = JSON.parse(readFileSync(runManifestPath, 'utf-8'));
|
|
93
94
|
runManifest.artifactHashes = hashes;
|
|
94
95
|
runManifest.endTime = new Date().toISOString();
|
|
@@ -15,13 +15,13 @@ import { createHash } from 'crypto';
|
|
|
15
15
|
*/
|
|
16
16
|
const SECRET_PATTERNS = [
|
|
17
17
|
// API Keys
|
|
18
|
-
{ pattern: /(?:api[_-]?key|apikey)\s*[:=]\s*['"]?([a-zA-Z0-9_
|
|
19
|
-
{ pattern: /(?:api[_-]?token|api_token)\s*[:=]\s*['"]?([a-zA-Z0-9_
|
|
18
|
+
{ pattern: /(?:api[_-]?key|apikey)\s*[:=]\s*['"]?([a-zA-Z0-9_-]{20,})['"]?/gi, type: 'API_KEY', severity: 'CRITICAL' },
|
|
19
|
+
{ pattern: /(?:api[_-]?token|api_token)\s*[:=]\s*['"]?([a-zA-Z0-9_-]{20,})['"]?/gi, type: 'API_TOKEN', severity: 'CRITICAL' },
|
|
20
20
|
|
|
21
21
|
// Tokens
|
|
22
|
-
{ pattern: /(?:bearer|token)\s+([a-zA-Z0-
|
|
23
|
-
{ pattern: /(?:access[_-]?token|access_token)\s*[:=]\s*['"]?([a-zA-Z0-9_
|
|
24
|
-
{ pattern: /(?:refresh[_-]?token|refresh_token)\s*[:=]\s*['"]?([a-zA-Z0-9_
|
|
22
|
+
{ pattern: /(?:bearer|token)\s+([a-zA-Z0-9._-]{20,})/gi, type: 'BEARER_TOKEN', severity: 'CRITICAL' },
|
|
23
|
+
{ pattern: /(?:access[_-]?token|access_token)\s*[:=]\s*['"]?([a-zA-Z0-9_-]{20,})['"]?/gi, type: 'ACCESS_TOKEN', severity: 'CRITICAL' },
|
|
24
|
+
{ pattern: /(?:refresh[_-]?token|refresh_token)\s*[:=]\s*['"]?([a-zA-Z0-9_-]{20,})['"]?/gi, type: 'REFRESH_TOKEN', severity: 'HIGH' },
|
|
25
25
|
|
|
26
26
|
// Private Keys
|
|
27
27
|
{ pattern: /-----BEGIN\s+(?:RSA\s+)?PRIVATE\s+KEY-----/gi, type: 'PRIVATE_KEY', severity: 'CRITICAL' },
|
|
@@ -34,10 +34,10 @@ const SECRET_PATTERNS = [
|
|
|
34
34
|
|
|
35
35
|
// GitHub
|
|
36
36
|
{ pattern: /ghp_[a-zA-Z0-9]{36}/gi, type: 'GITHUB_TOKEN', severity: 'CRITICAL' },
|
|
37
|
-
{ pattern: /github[_-]?token\s*[:=]\s*['"]?([a-zA-Z0-9_
|
|
37
|
+
{ pattern: /github[_-]?token\s*[:=]\s*['"]?([a-zA-Z0-9_-]{20,})['"]?/gi, type: 'GITHUB_TOKEN', severity: 'CRITICAL' },
|
|
38
38
|
|
|
39
39
|
// Generic secrets
|
|
40
|
-
{ pattern: /(?:secret|password|pwd|passwd)\s*[:=]\s*['"]?([a-zA-Z0-
|
|
40
|
+
{ pattern: /(?:secret|password|pwd|passwd)\s*[:=]\s*['"]?([a-zA-Z0-9._@-]{12,})['"]?/gi, type: 'SECRET', severity: 'HIGH' },
|
|
41
41
|
|
|
42
42
|
// .env files
|
|
43
43
|
{ pattern: /\.env/, type: 'ENV_FILE', severity: 'HIGH', fileOnly: true }
|
|
@@ -119,6 +119,7 @@ function scanFileContent(content, filePath, projectDir) {
|
|
|
119
119
|
file: relPath,
|
|
120
120
|
line: content.substring(0, match.index).split('\n').length,
|
|
121
121
|
match: match[0].substring(0, 50), // Truncate for safety
|
|
122
|
+
// @ts-expect-error - digest returns string
|
|
122
123
|
hash: createHash('sha256').update(match[0]).digest('hex').substring(0, 16)
|
|
123
124
|
});
|
|
124
125
|
}
|
|
@@ -196,6 +197,7 @@ function scanGitHistory(projectDir) {
|
|
|
196
197
|
|
|
197
198
|
const fileFindings = scanFileContent(content, resolve(projectDir, file), projectDir);
|
|
198
199
|
for (const finding of fileFindings) {
|
|
200
|
+
// @ts-expect-error - Dynamic finding property
|
|
199
201
|
finding.source = 'git_history';
|
|
200
202
|
}
|
|
201
203
|
findings.push(...fileFindings);
|
|
@@ -235,6 +237,7 @@ function scanArtifacts(projectDir) {
|
|
|
235
237
|
const content = readFileSync(fullPath, 'utf-8');
|
|
236
238
|
const fileFindings = scanFileContent(content, fullPath, projectDir);
|
|
237
239
|
for (const finding of fileFindings) {
|
|
240
|
+
// @ts-expect-error - Dynamic finding property
|
|
238
241
|
finding.source = 'artifacts';
|
|
239
242
|
}
|
|
240
243
|
findings.push(...fileFindings);
|
|
@@ -27,6 +27,7 @@ export function checkSecurityStatus(projectDir) {
|
|
|
27
27
|
|
|
28
28
|
if (existsSync(unifiedPath)) {
|
|
29
29
|
try {
|
|
30
|
+
// @ts-expect-error - readFileSync with encoding returns string
|
|
30
31
|
const unifiedReport = JSON.parse(readFileSync(unifiedPath, 'utf-8'));
|
|
31
32
|
status.exists = true;
|
|
32
33
|
status.ok = unifiedReport.securityOk || false;
|
|
@@ -63,18 +64,21 @@ export function checkSecurityStatus(projectDir) {
|
|
|
63
64
|
|
|
64
65
|
try {
|
|
65
66
|
// Check secrets
|
|
67
|
+
// @ts-expect-error - readFileSync with encoding returns string
|
|
66
68
|
const secretsReport = JSON.parse(readFileSync(secretsPath, 'utf-8'));
|
|
67
69
|
if (secretsReport.hasSecrets) {
|
|
68
70
|
status.blockers.push(`Secrets detected: ${secretsReport.summary.total} finding(s)`);
|
|
69
71
|
}
|
|
70
72
|
|
|
71
73
|
// Check vulnerabilities
|
|
74
|
+
// @ts-expect-error - readFileSync with encoding returns string
|
|
72
75
|
const vulnReport = JSON.parse(readFileSync(vulnPath, 'utf-8'));
|
|
73
76
|
if (vulnReport.blocking) {
|
|
74
77
|
status.blockers.push(`Critical/High vulnerabilities: ${vulnReport.summary.critical + vulnReport.summary.high} total`);
|
|
75
78
|
}
|
|
76
79
|
|
|
77
80
|
// Check supply-chain
|
|
81
|
+
// @ts-expect-error - readFileSync with encoding returns string
|
|
78
82
|
const supplyChainReport = JSON.parse(readFileSync(supplyChainPath, 'utf-8'));
|
|
79
83
|
if (!supplyChainReport.ok) {
|
|
80
84
|
status.blockers.push(`Supply-chain violations: ${supplyChainReport.summary.totalViolations} violation(s)`);
|
|
@@ -9,7 +9,10 @@
|
|
|
9
9
|
|
|
10
10
|
import { readFileSync, existsSync, writeFileSync, mkdirSync } from 'fs';
|
|
11
11
|
import { resolve } from 'path';
|
|
12
|
-
|
|
12
|
+
|
|
13
|
+
const DEFAULT_POLICY = JSON.parse(
|
|
14
|
+
readFileSync(new URL('./supplychain.defaults.json', import.meta.url), 'utf-8')
|
|
15
|
+
);
|
|
13
16
|
|
|
14
17
|
/**
|
|
15
18
|
* Load supply-chain policy
|
|
@@ -22,6 +25,7 @@ export function loadSupplyChainPolicy(projectDir) {
|
|
|
22
25
|
|
|
23
26
|
if (existsSync(customPath)) {
|
|
24
27
|
try {
|
|
28
|
+
// @ts-expect-error - readFileSync with encoding returns string
|
|
25
29
|
const custom = JSON.parse(readFileSync(customPath, 'utf-8'));
|
|
26
30
|
// Merge with defaults (custom overrides)
|
|
27
31
|
return {
|
|
@@ -64,6 +68,7 @@ function getDependencies(projectDir) {
|
|
|
64
68
|
if (!existsSync(pkgPath)) {
|
|
65
69
|
return { dependencies: {}, devDependencies: {} };
|
|
66
70
|
}
|
|
71
|
+
// @ts-expect-error - readFileSync with encoding returns string
|
|
67
72
|
const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));
|
|
68
73
|
return {
|
|
69
74
|
dependencies: pkg.dependencies || {},
|
|
@@ -87,6 +92,7 @@ function getPackageLicense(projectDir, packageName) {
|
|
|
87
92
|
if (!existsSync(pkgPath)) {
|
|
88
93
|
return null;
|
|
89
94
|
}
|
|
95
|
+
// @ts-expect-error - readFileSync with encoding returns string
|
|
90
96
|
const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));
|
|
91
97
|
|
|
92
98
|
if (typeof pkg.license === 'string') {
|
|
@@ -118,6 +124,7 @@ function checkIntegrityHashes(projectDir) {
|
|
|
118
124
|
}
|
|
119
125
|
|
|
120
126
|
try {
|
|
127
|
+
// @ts-expect-error - readFileSync with encoding returns string
|
|
121
128
|
const lock = JSON.parse(readFileSync(lockPath, 'utf-8'));
|
|
122
129
|
const packages = lock.packages || {};
|
|
123
130
|
let total = 0;
|
|
@@ -164,6 +171,7 @@ function checkPostinstallScripts(projectDir) {
|
|
|
164
171
|
const pkgPath = resolve(nodeModulesPath, entry.name, 'package.json');
|
|
165
172
|
if (existsSync(pkgPath)) {
|
|
166
173
|
try {
|
|
174
|
+
// @ts-expect-error - readFileSync with encoding returns string
|
|
167
175
|
const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));
|
|
168
176
|
if (pkg.scripts) {
|
|
169
177
|
if (pkg.scripts.postinstall || pkg.scripts.preinstall || pkg.scripts.install) {
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* HIGH/CRITICAL = BLOCKING, MEDIUM = WARNING (configurable).
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import { readFileSync, existsSync, writeFileSync, mkdirSync } from 'fs';
|
|
8
|
+
import { readFileSync as _readFileSync, existsSync, writeFileSync, mkdirSync } from 'fs';
|
|
9
9
|
import { resolve } from 'path';
|
|
10
10
|
import { execSync } from 'child_process';
|
|
11
11
|
|
|
@@ -110,7 +110,7 @@ function parseVulnerabilities(auditResults) {
|
|
|
110
110
|
* @param {boolean} options.requireOSV - Require OSV scanner (default: false)
|
|
111
111
|
* @returns {Promise<Object>} Scan results
|
|
112
112
|
*/
|
|
113
|
-
export async function scanVulnerabilities(projectDir, options = {}) {
|
|
113
|
+
export async function scanVulnerabilities(projectDir, options = { blockMedium: false, requireOSV: false }) {
|
|
114
114
|
const { blockMedium = false, requireOSV = false } = options;
|
|
115
115
|
|
|
116
116
|
// Check OSV availability
|
|
@@ -18,6 +18,7 @@ function loadArtifact(runDir, filename) {
|
|
|
18
18
|
return null;
|
|
19
19
|
}
|
|
20
20
|
try {
|
|
21
|
+
// @ts-expect-error - readFileSync with encoding returns string
|
|
21
22
|
return JSON.parse(readFileSync(path, 'utf-8'));
|
|
22
23
|
} catch {
|
|
23
24
|
return null;
|
|
@@ -29,7 +30,7 @@ function loadArtifact(runDir, filename) {
|
|
|
29
30
|
*
|
|
30
31
|
* @param {string} projectDir - Project directory
|
|
31
32
|
* @param {string} runId - Run ID
|
|
32
|
-
* @returns {Object} Truth certificate
|
|
33
|
+
* @returns {Promise<Object>} Truth certificate
|
|
33
34
|
*/
|
|
34
35
|
export async function generateTruthCertificate(projectDir, runId) {
|
|
35
36
|
const runDir = resolve(projectDir, '.verax', 'runs', runId);
|
|
@@ -242,6 +243,7 @@ export function loadTruthCertificate(projectDir, runId) {
|
|
|
242
243
|
}
|
|
243
244
|
|
|
244
245
|
try {
|
|
246
|
+
// @ts-expect-error - readFileSync with encoding returns string
|
|
245
247
|
return JSON.parse(readFileSync(certPath, 'utf-8'));
|
|
246
248
|
} catch {
|
|
247
249
|
return null;
|