sourceverity 1.0.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/LICENSE +21 -0
- package/README.md +188 -0
- package/bin/sourceverity.js +12 -0
- package/dist/analysis/controlFlow.d.ts +10 -0
- package/dist/analysis/controlFlow.d.ts.map +1 -0
- package/dist/analysis/controlFlow.js +278 -0
- package/dist/analysis/controlFlow.js.map +1 -0
- package/dist/analysis/frameworks.d.ts +11 -0
- package/dist/analysis/frameworks.d.ts.map +1 -0
- package/dist/analysis/frameworks.js +189 -0
- package/dist/analysis/frameworks.js.map +1 -0
- package/dist/analysis/functions.d.ts +27 -0
- package/dist/analysis/functions.d.ts.map +1 -0
- package/dist/analysis/functions.js +628 -0
- package/dist/analysis/functions.js.map +1 -0
- package/dist/analysis/promiseFlow.d.ts +44 -0
- package/dist/analysis/promiseFlow.d.ts.map +1 -0
- package/dist/analysis/promiseFlow.js +261 -0
- package/dist/analysis/promiseFlow.js.map +1 -0
- package/dist/analysis/values.d.ts +24 -0
- package/dist/analysis/values.d.ts.map +1 -0
- package/dist/analysis/values.js +189 -0
- package/dist/analysis/values.js.map +1 -0
- package/dist/baseline/manager.d.ts +20 -0
- package/dist/baseline/manager.d.ts.map +1 -0
- package/dist/baseline/manager.js +77 -0
- package/dist/baseline/manager.js.map +1 -0
- package/dist/baseline/types.d.ts +20 -0
- package/dist/baseline/types.d.ts.map +1 -0
- package/dist/baseline/types.js +2 -0
- package/dist/baseline/types.js.map +1 -0
- package/dist/cli/args.d.ts +26 -0
- package/dist/cli/args.d.ts.map +1 -0
- package/dist/cli/args.js +126 -0
- package/dist/cli/args.js.map +1 -0
- package/dist/cli/exitCodes.d.ts +8 -0
- package/dist/cli/exitCodes.d.ts.map +1 -0
- package/dist/cli/exitCodes.js +7 -0
- package/dist/cli/exitCodes.js.map +1 -0
- package/dist/cli/help.d.ts +5 -0
- package/dist/cli/help.d.ts.map +1 -0
- package/dist/cli/help.js +46 -0
- package/dist/cli/help.js.map +1 -0
- package/dist/cli/main.d.ts +7 -0
- package/dist/cli/main.d.ts.map +1 -0
- package/dist/cli/main.js +156 -0
- package/dist/cli/main.js.map +1 -0
- package/dist/core/fingerprint.d.ts +18 -0
- package/dist/core/fingerprint.d.ts.map +1 -0
- package/dist/core/fingerprint.js +26 -0
- package/dist/core/fingerprint.js.map +1 -0
- package/dist/core/paths.d.ts +10 -0
- package/dist/core/paths.d.ts.map +1 -0
- package/dist/core/paths.js +30 -0
- package/dist/core/paths.js.map +1 -0
- package/dist/core/suppressions.d.ts +24 -0
- package/dist/core/suppressions.d.ts.map +1 -0
- package/dist/core/suppressions.js +100 -0
- package/dist/core/suppressions.js.map +1 -0
- package/dist/core/terminal.d.ts +18 -0
- package/dist/core/terminal.d.ts.map +1 -0
- package/dist/core/terminal.js +39 -0
- package/dist/core/terminal.js.map +1 -0
- package/dist/core/types.d.ts +119 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/core/types.js +2 -0
- package/dist/core/types.js.map +1 -0
- package/dist/engine/context.d.ts +16 -0
- package/dist/engine/context.d.ts.map +1 -0
- package/dist/engine/context.js +57 -0
- package/dist/engine/context.js.map +1 -0
- package/dist/engine/registry.d.ts +26 -0
- package/dist/engine/registry.d.ts.map +1 -0
- package/dist/engine/registry.js +38 -0
- package/dist/engine/registry.js.map +1 -0
- package/dist/engine/runner.d.ts +14 -0
- package/dist/engine/runner.d.ts.map +1 -0
- package/dist/engine/runner.js +166 -0
- package/dist/engine/runner.js.map +1 -0
- package/dist/engine/symbols.d.ts +46 -0
- package/dist/engine/symbols.d.ts.map +1 -0
- package/dist/engine/symbols.js +278 -0
- package/dist/engine/symbols.js.map +1 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +32 -0
- package/dist/index.js.map +1 -0
- package/dist/reporters/agent.d.ts +45 -0
- package/dist/reporters/agent.d.ts.map +1 -0
- package/dist/reporters/agent.js +40 -0
- package/dist/reporters/agent.js.map +1 -0
- package/dist/reporters/json.d.ts +6 -0
- package/dist/reporters/json.d.ts.map +1 -0
- package/dist/reporters/json.js +7 -0
- package/dist/reporters/json.js.map +1 -0
- package/dist/reporters/sarif.d.ts +6 -0
- package/dist/reporters/sarif.d.ts.map +1 -0
- package/dist/reporters/sarif.js +60 -0
- package/dist/reporters/sarif.js.map +1 -0
- package/dist/reporters/terminal.d.ts +10 -0
- package/dist/reporters/terminal.d.ts.map +1 -0
- package/dist/reporters/terminal.js +105 -0
- package/dist/reporters/terminal.js.map +1 -0
- package/dist/repository/detector.d.ts +6 -0
- package/dist/repository/detector.d.ts.map +1 -0
- package/dist/repository/detector.js +231 -0
- package/dist/repository/detector.js.map +1 -0
- package/dist/repository/fileFilter.d.ts +10 -0
- package/dist/repository/fileFilter.d.ts.map +1 -0
- package/dist/repository/fileFilter.js +78 -0
- package/dist/repository/fileFilter.js.map +1 -0
- package/dist/repository/git.d.ts +7 -0
- package/dist/repository/git.d.ts.map +1 -0
- package/dist/repository/git.js +53 -0
- package/dist/repository/git.js.map +1 -0
- package/dist/repository/tsLoader.d.ts +15 -0
- package/dist/repository/tsLoader.d.ts.map +1 -0
- package/dist/repository/tsLoader.js +27 -0
- package/dist/repository/tsLoader.js.map +1 -0
- package/dist/repository/types.d.ts +38 -0
- package/dist/repository/types.d.ts.map +1 -0
- package/dist/repository/types.js +2 -0
- package/dist/repository/types.js.map +1 -0
- package/dist/rules/async/asyncForeach.d.ts +3 -0
- package/dist/rules/async/asyncForeach.d.ts.map +1 -0
- package/dist/rules/async/asyncForeach.js +76 -0
- package/dist/rules/async/asyncForeach.js.map +1 -0
- package/dist/rules/async/floatingPromise.d.ts +3 -0
- package/dist/rules/async/floatingPromise.d.ts.map +1 -0
- package/dist/rules/async/floatingPromise.js +359 -0
- package/dist/rules/async/floatingPromise.js.map +1 -0
- package/dist/rules/browser/eventListenerCleanup.d.ts +3 -0
- package/dist/rules/browser/eventListenerCleanup.d.ts.map +1 -0
- package/dist/rules/browser/eventListenerCleanup.js +378 -0
- package/dist/rules/browser/eventListenerCleanup.js.map +1 -0
- package/dist/rules/browser/observerCleanup.d.ts +3 -0
- package/dist/rules/browser/observerCleanup.d.ts.map +1 -0
- package/dist/rules/browser/observerCleanup.js +184 -0
- package/dist/rules/browser/observerCleanup.js.map +1 -0
- package/dist/rules/browser/timerCleanup.d.ts +3 -0
- package/dist/rules/browser/timerCleanup.d.ts.map +1 -0
- package/dist/rules/browser/timerCleanup.js +115 -0
- package/dist/rules/browser/timerCleanup.js.map +1 -0
- package/dist/rules/index.d.ts +19 -0
- package/dist/rules/index.d.ts.map +1 -0
- package/dist/rules/index.js +41 -0
- package/dist/rules/index.js.map +1 -0
- package/dist/rules/network/fetchStatusUnchecked.d.ts +3 -0
- package/dist/rules/network/fetchStatusUnchecked.d.ts.map +1 -0
- package/dist/rules/network/fetchStatusUnchecked.js +96 -0
- package/dist/rules/network/fetchStatusUnchecked.js.map +1 -0
- package/dist/rules/react/asyncEffectCallback.d.ts +3 -0
- package/dist/rules/react/asyncEffectCallback.d.ts.map +1 -0
- package/dist/rules/react/asyncEffectCallback.js +62 -0
- package/dist/rules/react/asyncEffectCallback.js.map +1 -0
- package/dist/rules/react/derivedStateEffect.d.ts +3 -0
- package/dist/rules/react/derivedStateEffect.d.ts.map +1 -0
- package/dist/rules/react/derivedStateEffect.js +172 -0
- package/dist/rules/react/derivedStateEffect.js.map +1 -0
- package/dist/rules/react/missingEffectCleanup.d.ts +3 -0
- package/dist/rules/react/missingEffectCleanup.d.ts.map +1 -0
- package/dist/rules/react/missingEffectCleanup.js +86 -0
- package/dist/rules/react/missingEffectCleanup.js.map +1 -0
- package/dist/rules/typescript/nonNullAssertionRisk.d.ts +3 -0
- package/dist/rules/typescript/nonNullAssertionRisk.d.ts.map +1 -0
- package/dist/rules/typescript/nonNullAssertionRisk.js +65 -0
- package/dist/rules/typescript/nonNullAssertionRisk.js.map +1 -0
- package/dist/rules/typescript/uncheckedIndexAccess.d.ts +3 -0
- package/dist/rules/typescript/uncheckedIndexAccess.d.ts.map +1 -0
- package/dist/rules/typescript/uncheckedIndexAccess.js +79 -0
- package/dist/rules/typescript/uncheckedIndexAccess.js.map +1 -0
- package/dist/rules/typescript/unsafeUnvalidatedAssertion.d.ts +3 -0
- package/dist/rules/typescript/unsafeUnvalidatedAssertion.d.ts.map +1 -0
- package/dist/rules/typescript/unsafeUnvalidatedAssertion.js +94 -0
- package/dist/rules/typescript/unsafeUnvalidatedAssertion.js.map +1 -0
- package/dist/strictness/evaluator.d.ts +28 -0
- package/dist/strictness/evaluator.d.ts.map +1 -0
- package/dist/strictness/evaluator.js +141 -0
- package/dist/strictness/evaluator.js.map +1 -0
- package/dist/strictness/matrix.d.ts +8 -0
- package/dist/strictness/matrix.d.ts.map +1 -0
- package/dist/strictness/matrix.js +63 -0
- package/dist/strictness/matrix.js.map +1 -0
- package/dist/typescript/programManager.d.ts +18 -0
- package/dist/typescript/programManager.d.ts.map +1 -0
- package/dist/typescript/programManager.js +46 -0
- package/dist/typescript/programManager.js.map +1 -0
- package/dist/typescript/projectResolver.d.ts +17 -0
- package/dist/typescript/projectResolver.d.ts.map +1 -0
- package/dist/typescript/projectResolver.js +75 -0
- package/dist/typescript/projectResolver.js.map +1 -0
- package/package.json +56 -0
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import fs from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { normalizePath } from "../core/paths.js";
|
|
4
|
+
export const DEFAULT_BASELINE_FILENAME = ".sourceverity-baseline.json";
|
|
5
|
+
/**
|
|
6
|
+
* Creates a BaselineFile structure from a list of audit findings.
|
|
7
|
+
*/
|
|
8
|
+
export function createBaseline(findings, repoRoot) {
|
|
9
|
+
const entriesMap = new Map();
|
|
10
|
+
for (const f of findings) {
|
|
11
|
+
if (!entriesMap.has(f.fingerprint)) {
|
|
12
|
+
entriesMap.set(f.fingerprint, {
|
|
13
|
+
fingerprint: f.fingerprint,
|
|
14
|
+
ruleId: f.ruleId,
|
|
15
|
+
file: normalizePath(f.file, repoRoot),
|
|
16
|
+
message: f.message,
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
const entries = Array.from(entriesMap.values()).sort((a, b) => a.fingerprint.localeCompare(b.fingerprint));
|
|
21
|
+
return {
|
|
22
|
+
version: 1,
|
|
23
|
+
generatedAt: new Date().toISOString(),
|
|
24
|
+
repositoryRoot: normalizePath(repoRoot),
|
|
25
|
+
entries,
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Atomically writes a baseline file to disk.
|
|
30
|
+
*/
|
|
31
|
+
export async function saveBaseline(baseline, filePath) {
|
|
32
|
+
const resolvedPath = path.resolve(filePath);
|
|
33
|
+
const dir = path.dirname(resolvedPath);
|
|
34
|
+
await fs.mkdir(dir, { recursive: true });
|
|
35
|
+
const tempPath = `${resolvedPath}.${Date.now()}.tmp`;
|
|
36
|
+
const serialized = JSON.stringify(baseline, null, 2);
|
|
37
|
+
await fs.writeFile(tempPath, serialized, "utf-8");
|
|
38
|
+
await fs.rename(tempPath, resolvedPath);
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Loads and validates a baseline file from disk. Returns null if missing or malformed.
|
|
42
|
+
*/
|
|
43
|
+
export async function loadBaseline(filePath) {
|
|
44
|
+
try {
|
|
45
|
+
const raw = await fs.readFile(path.resolve(filePath), "utf-8");
|
|
46
|
+
// sourceverity-disable-next-line typescript/unsafe-unvalidated-assertion -- validated by version and entries checks below
|
|
47
|
+
const parsed = JSON.parse(raw);
|
|
48
|
+
if (parsed && parsed.version === 1 && Array.isArray(parsed.entries)) {
|
|
49
|
+
return parsed;
|
|
50
|
+
}
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Compares current audit findings against a baseline to determine new and resolved findings.
|
|
59
|
+
*/
|
|
60
|
+
export function compareWithBaseline(currentFindings, baseline) {
|
|
61
|
+
const baselineFingerprints = new Set(baseline.entries.map((e) => e.fingerprint));
|
|
62
|
+
const currentFingerprints = new Set(currentFindings.map((f) => f.fingerprint));
|
|
63
|
+
const newFindings = currentFindings.filter((f) => !baselineFingerprints.has(f.fingerprint));
|
|
64
|
+
let resolvedCount = 0;
|
|
65
|
+
for (const fp of baselineFingerprints) {
|
|
66
|
+
if (!currentFingerprints.has(fp)) {
|
|
67
|
+
resolvedCount++;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return {
|
|
71
|
+
newFindings,
|
|
72
|
+
baselineCount: baseline.entries.length,
|
|
73
|
+
resolvedCount,
|
|
74
|
+
newCount: newFindings.length,
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manager.js","sourceRoot":"","sources":["../../src/baseline/manager.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { Finding } from "../core/types.ts";
|
|
2
|
+
export interface BaselineEntry {
|
|
3
|
+
readonly fingerprint: string;
|
|
4
|
+
readonly ruleId: string;
|
|
5
|
+
readonly file: string;
|
|
6
|
+
readonly message: string;
|
|
7
|
+
}
|
|
8
|
+
export interface BaselineFile {
|
|
9
|
+
readonly version: 1;
|
|
10
|
+
readonly generatedAt: string;
|
|
11
|
+
readonly repositoryRoot: string;
|
|
12
|
+
readonly entries: readonly BaselineEntry[];
|
|
13
|
+
}
|
|
14
|
+
export interface BaselineDelta {
|
|
15
|
+
readonly newFindings: readonly Finding[];
|
|
16
|
+
readonly baselineCount: number;
|
|
17
|
+
readonly resolvedCount: number;
|
|
18
|
+
readonly newCount: number;
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/baseline/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAEhD,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC;IACpB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,OAAO,EAAE,SAAS,aAAa,EAAE,CAAC;CAC5C;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,WAAW,EAAE,SAAS,OAAO,EAAE,CAAC;IACzC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/baseline/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export type CliCommand = "scan" | "strictness" | "rules" | "explain" | "baseline" | "help" | "version";
|
|
2
|
+
export type OutputFormat = "pretty" | "json" | "agent" | "sarif";
|
|
3
|
+
export type MinConfidence = "high" | "medium" | "low";
|
|
4
|
+
export type FailOnSeverity = "error" | "warning" | "never";
|
|
5
|
+
export interface CliOptions {
|
|
6
|
+
readonly command: CliCommand;
|
|
7
|
+
readonly targetDir: string;
|
|
8
|
+
readonly format: OutputFormat;
|
|
9
|
+
readonly minConfidence: MinConfidence;
|
|
10
|
+
readonly failOn: FailOnSeverity;
|
|
11
|
+
readonly configPath?: string | undefined;
|
|
12
|
+
readonly baselinePath?: string | undefined;
|
|
13
|
+
readonly updateBaseline: boolean;
|
|
14
|
+
readonly changedOnly: boolean;
|
|
15
|
+
readonly verbose: boolean;
|
|
16
|
+
readonly quiet: boolean;
|
|
17
|
+
readonly color?: boolean | undefined;
|
|
18
|
+
readonly ruleArg?: string | undefined;
|
|
19
|
+
readonly baselineSubcommand?: "create" | "check" | undefined;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Parses raw command-line arguments into structured CliOptions.
|
|
23
|
+
* Throws an Error with a descriptive message on invalid input.
|
|
24
|
+
*/
|
|
25
|
+
export declare function parseCliArgs(argv: readonly string[]): CliOptions;
|
|
26
|
+
//# sourceMappingURL=args.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"args.d.ts","sourceRoot":"","sources":["../../src/cli/args.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,YAAY,GAAG,OAAO,GAAG,SAAS,GAAG,UAAU,GAAG,MAAM,GAAG,SAAS,CAAC;AAEvG,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,CAAC;AAEjE,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;AAEtD,MAAM,MAAM,cAAc,GAAG,OAAO,GAAG,SAAS,GAAG,OAAO,CAAC;AAE3D,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAC;IAC7B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC;IAC9B,QAAQ,CAAC,aAAa,EAAE,aAAa,CAAC;IACtC,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAC;IAChC,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACzC,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3C,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAC;IACjC,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC;IAC9B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACrC,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACtC,QAAQ,CAAC,kBAAkB,CAAC,EAAE,QAAQ,GAAG,OAAO,GAAG,SAAS,CAAC;CAC9D;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,UAAU,CAiHhE"}
|
package/dist/cli/args.js
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { parseArgs } from "node:util";
|
|
2
|
+
/**
|
|
3
|
+
* Parses raw command-line arguments into structured CliOptions.
|
|
4
|
+
* Throws an Error with a descriptive message on invalid input.
|
|
5
|
+
*/
|
|
6
|
+
export function parseCliArgs(argv) {
|
|
7
|
+
const optionsConfig = {
|
|
8
|
+
help: { type: "boolean", short: "h" },
|
|
9
|
+
version: { type: "boolean", short: "v" },
|
|
10
|
+
format: { type: "string", short: "f" },
|
|
11
|
+
"min-confidence": { type: "string" },
|
|
12
|
+
"fail-on": { type: "string" },
|
|
13
|
+
config: { type: "string", short: "c" },
|
|
14
|
+
baseline: { type: "string", short: "b" },
|
|
15
|
+
"update-baseline": { type: "boolean", short: "u" },
|
|
16
|
+
changed: { type: "boolean" },
|
|
17
|
+
verbose: { type: "boolean" },
|
|
18
|
+
quiet: { type: "boolean", short: "q" },
|
|
19
|
+
color: { type: "boolean" },
|
|
20
|
+
"no-color": { type: "boolean" },
|
|
21
|
+
};
|
|
22
|
+
const parsed = parseArgs({
|
|
23
|
+
args: [...argv],
|
|
24
|
+
options: optionsConfig,
|
|
25
|
+
allowPositionals: true,
|
|
26
|
+
strict: true,
|
|
27
|
+
});
|
|
28
|
+
if (parsed.values.help) {
|
|
29
|
+
return createDefaultOptions("help");
|
|
30
|
+
}
|
|
31
|
+
if (parsed.values.version) {
|
|
32
|
+
return createDefaultOptions("version");
|
|
33
|
+
}
|
|
34
|
+
const positionals = parsed.positionals;
|
|
35
|
+
let command = "scan";
|
|
36
|
+
let targetDir = ".";
|
|
37
|
+
let ruleArg;
|
|
38
|
+
let baselineSubcommand;
|
|
39
|
+
const first = positionals[0];
|
|
40
|
+
if (first) {
|
|
41
|
+
if (first === "scan" ||
|
|
42
|
+
first === "strictness" ||
|
|
43
|
+
first === "rules" ||
|
|
44
|
+
first === "explain" ||
|
|
45
|
+
first === "baseline" ||
|
|
46
|
+
first === "help" ||
|
|
47
|
+
first === "version") {
|
|
48
|
+
command = first;
|
|
49
|
+
if (command === "explain") {
|
|
50
|
+
ruleArg = positionals[1];
|
|
51
|
+
if (!ruleArg) {
|
|
52
|
+
throw new Error("Missing rule identifier for 'explain' command. Usage: sourceverity explain <rule-id>");
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
else if (command === "baseline") {
|
|
56
|
+
const sub = positionals[1];
|
|
57
|
+
if (sub === "create" || sub === "check") {
|
|
58
|
+
baselineSubcommand = sub;
|
|
59
|
+
targetDir = positionals[2] ?? ".";
|
|
60
|
+
}
|
|
61
|
+
else if (sub) {
|
|
62
|
+
targetDir = sub;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
targetDir = positionals[1] ?? ".";
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
// First positional is targetDir for default 'scan' command
|
|
71
|
+
targetDir = first;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
// Format validation
|
|
75
|
+
const rawFormat = parsed.values.format ?? "pretty";
|
|
76
|
+
if (rawFormat !== "pretty" && rawFormat !== "json" && rawFormat !== "agent" && rawFormat !== "sarif") {
|
|
77
|
+
throw new Error(`Invalid --format '${rawFormat}'. Valid options: pretty, json, agent, sarif`);
|
|
78
|
+
}
|
|
79
|
+
// Min confidence validation
|
|
80
|
+
const rawConfidence = parsed.values["min-confidence"] ?? "medium";
|
|
81
|
+
if (rawConfidence !== "high" && rawConfidence !== "medium" && rawConfidence !== "low") {
|
|
82
|
+
throw new Error(`Invalid --min-confidence '${rawConfidence}'. Valid options: high, medium, low`);
|
|
83
|
+
}
|
|
84
|
+
// Fail on validation
|
|
85
|
+
const rawFailOn = parsed.values["fail-on"] ?? "error";
|
|
86
|
+
if (rawFailOn !== "error" && rawFailOn !== "warning" && rawFailOn !== "never") {
|
|
87
|
+
throw new Error(`Invalid --fail-on '${rawFailOn}'. Valid options: error, warning, never`);
|
|
88
|
+
}
|
|
89
|
+
let colorOption;
|
|
90
|
+
if (parsed.values["no-color"]) {
|
|
91
|
+
colorOption = false;
|
|
92
|
+
}
|
|
93
|
+
else if (parsed.values.color !== undefined) {
|
|
94
|
+
colorOption = parsed.values.color;
|
|
95
|
+
}
|
|
96
|
+
return {
|
|
97
|
+
command,
|
|
98
|
+
targetDir,
|
|
99
|
+
format: rawFormat,
|
|
100
|
+
minConfidence: rawConfidence,
|
|
101
|
+
failOn: rawFailOn,
|
|
102
|
+
configPath: parsed.values.config,
|
|
103
|
+
baselinePath: parsed.values.baseline,
|
|
104
|
+
updateBaseline: Boolean(parsed.values["update-baseline"]),
|
|
105
|
+
changedOnly: Boolean(parsed.values.changed),
|
|
106
|
+
verbose: Boolean(parsed.values.verbose),
|
|
107
|
+
quiet: Boolean(parsed.values.quiet),
|
|
108
|
+
color: colorOption,
|
|
109
|
+
ruleArg,
|
|
110
|
+
baselineSubcommand,
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
function createDefaultOptions(command) {
|
|
114
|
+
return {
|
|
115
|
+
command,
|
|
116
|
+
targetDir: ".",
|
|
117
|
+
format: "pretty",
|
|
118
|
+
minConfidence: "medium",
|
|
119
|
+
failOn: "error",
|
|
120
|
+
updateBaseline: false,
|
|
121
|
+
changedOnly: false,
|
|
122
|
+
verbose: false,
|
|
123
|
+
quiet: false,
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
//# sourceMappingURL=args.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"args.js","sourceRoot":"","sources":["../../src/cli/args.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exitCodes.d.ts","sourceRoot":"","sources":["../../src/cli/exitCodes.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,UAAU;;;;;CAKb,CAAC;AAEX,MAAM,MAAM,QAAQ,GAAG,CAAC,OAAO,UAAU,CAAC,CAAC,MAAM,OAAO,UAAU,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exitCodes.js","sourceRoot":"","sources":["../../src/cli/exitCodes.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,UAAU,GAAG;IACxB,OAAO,EAAE,CAAC;IACV,gBAAgB,EAAE,CAAC;IACnB,UAAU,EAAE,CAAC;IACb,cAAc,EAAE,CAAC;CACT,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"help.d.ts","sourceRoot":"","sources":["../../src/cli/help.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,wBAAgB,WAAW,IAAI,MAAM,CAyCpC"}
|
package/dist/cli/help.js
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Formats help text for the SourceVerity CLI.
|
|
3
|
+
*/
|
|
4
|
+
export function getHelpText() {
|
|
5
|
+
return `SourceVerity - Repository-aware frontend correctness and quality auditor
|
|
6
|
+
|
|
7
|
+
USAGE:
|
|
8
|
+
sourceverity scan [path] [options]
|
|
9
|
+
sourceverity strictness [path] [options]
|
|
10
|
+
sourceverity rules
|
|
11
|
+
sourceverity explain <rule-id>
|
|
12
|
+
sourceverity baseline create [path]
|
|
13
|
+
sourceverity baseline check [path]
|
|
14
|
+
|
|
15
|
+
COMMANDS:
|
|
16
|
+
scan [path] Audit frontend repository for correctness problems (default)
|
|
17
|
+
strictness [path] Analyze TypeScript configuration safety and migration impact
|
|
18
|
+
rules List all available audit rules
|
|
19
|
+
explain <rule-id> Show documentation and examples for a specific rule
|
|
20
|
+
baseline create Generate or update .sourceverity-baseline.json
|
|
21
|
+
baseline check Scan repository and report only new findings against baseline
|
|
22
|
+
help Show this help message
|
|
23
|
+
version Show SourceVerity version
|
|
24
|
+
|
|
25
|
+
OPTIONS:
|
|
26
|
+
-f, --format <type> Output format: pretty (default), json, agent, sarif
|
|
27
|
+
--min-confidence <lvl> Minimum finding confidence to report: medium (default), high, low
|
|
28
|
+
--fail-on <severity> Exit with status 1 on: error (default), warning, never
|
|
29
|
+
-b, --baseline <path> Path to baseline file (default: .sourceverity-baseline.json)
|
|
30
|
+
-u, --update-baseline Update baseline file with current findings
|
|
31
|
+
--changed Analyze only git-changed files in the repository
|
|
32
|
+
-c, --config <path> Path to custom sourceverity.json configuration
|
|
33
|
+
--color / --no-color Force enable or disable ANSI color output
|
|
34
|
+
-q, --quiet Suppress informational messages and progress
|
|
35
|
+
--verbose Show extended diagnostic and framework metadata
|
|
36
|
+
-h, --help Show help
|
|
37
|
+
-v, --version Show version
|
|
38
|
+
|
|
39
|
+
EXIT CODES:
|
|
40
|
+
0 Scan passed or findings within configured thresholds
|
|
41
|
+
1 Findings violated configured failure policy (--fail-on)
|
|
42
|
+
2 Configuration, arguments, or repository input error
|
|
43
|
+
3 Internal analysis or execution error
|
|
44
|
+
`;
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=help.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"help.js","sourceRoot":"","sources":["../../src/cli/help.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,UAAU,WAAW;IACzB,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAuCR,CAAC;AACF,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../../src/cli/main.ts"],"names":[],"mappings":"AAEA,OAAO,EAAc,KAAK,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAoB3D,OAAO,mBAAmB,CAAC;AAE3B;;GAEG;AACH,wBAAsB,MAAM,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAAC,QAAQ,CAAC,CAwJvE"}
|
package/dist/cli/main.js
ADDED
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { parseCliArgs } from "./args.js";
|
|
3
|
+
import { EXIT_CODES } from "./exitCodes.js";
|
|
4
|
+
import { getHelpText } from "./help.js";
|
|
5
|
+
import { runAudit } from "../engine/runner.js";
|
|
6
|
+
import { globalRuleRegistry } from "../engine/registry.js";
|
|
7
|
+
import { discoverRepository } from "../repository/detector.js";
|
|
8
|
+
import { loadRepositoryTypeScript } from "../repository/tsLoader.js";
|
|
9
|
+
import { getChangedFiles } from "../repository/git.js";
|
|
10
|
+
import { evaluateStrictnessGap, renderStrictnessReport } from "../strictness/evaluator.js";
|
|
11
|
+
import { createBaseline, saveBaseline, loadBaseline, compareWithBaseline, DEFAULT_BASELINE_FILENAME, } from "../baseline/manager.js";
|
|
12
|
+
import { renderTerminalReport } from "../reporters/terminal.js";
|
|
13
|
+
import { renderJsonReport } from "../reporters/json.js";
|
|
14
|
+
import { renderAgentReport } from "../reporters/agent.js";
|
|
15
|
+
import { renderSarifReport } from "../reporters/sarif.js";
|
|
16
|
+
import { createStyler } from "../core/terminal.js";
|
|
17
|
+
import "../rules/index.js";
|
|
18
|
+
/**
|
|
19
|
+
* Main CLI execution entry point.
|
|
20
|
+
*/
|
|
21
|
+
export async function runCli(argv) {
|
|
22
|
+
let options;
|
|
23
|
+
try {
|
|
24
|
+
options = parseCliArgs(argv);
|
|
25
|
+
}
|
|
26
|
+
catch (err) {
|
|
27
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
28
|
+
process.stderr.write(`sourceverity: ${msg}\n\n${getHelpText()}\n`);
|
|
29
|
+
return EXIT_CODES.USER_ERROR;
|
|
30
|
+
}
|
|
31
|
+
const styler = createStyler(options.color !== undefined ? { color: options.color } : undefined);
|
|
32
|
+
// 1. Help command
|
|
33
|
+
if (options.command === "help") {
|
|
34
|
+
process.stdout.write(getHelpText() + "\n");
|
|
35
|
+
return EXIT_CODES.SUCCESS;
|
|
36
|
+
}
|
|
37
|
+
// 2. Version command
|
|
38
|
+
if (options.command === "version") {
|
|
39
|
+
process.stdout.write("1.0.0\n");
|
|
40
|
+
return EXIT_CODES.SUCCESS;
|
|
41
|
+
}
|
|
42
|
+
// 3. Rules listing command
|
|
43
|
+
if (options.command === "rules") {
|
|
44
|
+
const rules = globalRuleRegistry.getAll();
|
|
45
|
+
process.stdout.write(styler.bold("SourceVerity Rules\n\n"));
|
|
46
|
+
for (const r of rules) {
|
|
47
|
+
const paddedId = r.meta.id.padEnd(45, " ");
|
|
48
|
+
const sev = r.meta.defaultSeverity.padEnd(8, " ");
|
|
49
|
+
process.stdout.write(` ${styler.bold(paddedId)} ${sev} ${styler.dim(r.meta.description)}\n`);
|
|
50
|
+
}
|
|
51
|
+
process.stdout.write(`\nTotal rules: ${rules.length}\n`);
|
|
52
|
+
return EXIT_CODES.SUCCESS;
|
|
53
|
+
}
|
|
54
|
+
// 4. Explain rule command
|
|
55
|
+
if (options.command === "explain") {
|
|
56
|
+
const ruleId = options.ruleArg;
|
|
57
|
+
const rule = ruleId ? globalRuleRegistry.get(ruleId) : undefined;
|
|
58
|
+
if (!rule) {
|
|
59
|
+
process.stderr.write(`sourceverity: unknown rule '${ruleId}'. Run 'sourceverity rules' to list all rules.\n`);
|
|
60
|
+
return EXIT_CODES.USER_ERROR;
|
|
61
|
+
}
|
|
62
|
+
process.stdout.write(styler.bold(`${rule.meta.id}\n\n`));
|
|
63
|
+
process.stdout.write(`${rule.meta.description}\n\n`);
|
|
64
|
+
process.stdout.write(`Category: ${rule.meta.category}\n`);
|
|
65
|
+
process.stdout.write(`Default Severity: ${rule.meta.defaultSeverity}\n`);
|
|
66
|
+
process.stdout.write(`Confidence: ${rule.meta.defaultConfidence}\n`);
|
|
67
|
+
process.stdout.write(`Type Information: ${rule.meta.requiresTypeInformation ? "required" : "syntax only"}\n`);
|
|
68
|
+
return EXIT_CODES.SUCCESS;
|
|
69
|
+
}
|
|
70
|
+
// 5. Strictness gap analysis command
|
|
71
|
+
if (options.command === "strictness") {
|
|
72
|
+
const targetDir = path.resolve(options.targetDir);
|
|
73
|
+
const repo = await discoverRepository(targetDir);
|
|
74
|
+
const tsInst = loadRepositoryTypeScript(targetDir);
|
|
75
|
+
if (!tsInst) {
|
|
76
|
+
process.stderr.write(`sourceverity: strictness analysis requires a local TypeScript installation in '${targetDir}'.\n`);
|
|
77
|
+
return EXIT_CODES.USER_ERROR;
|
|
78
|
+
}
|
|
79
|
+
const report = evaluateStrictnessGap(repo, tsInst);
|
|
80
|
+
process.stdout.write(renderStrictnessReport(report, options.color !== undefined ? { color: options.color } : undefined));
|
|
81
|
+
return EXIT_CODES.SUCCESS;
|
|
82
|
+
}
|
|
83
|
+
// 6. Baseline generation subcommand
|
|
84
|
+
if (options.command === "baseline" && options.baselineSubcommand === "create") {
|
|
85
|
+
const targetDir = path.resolve(options.targetDir);
|
|
86
|
+
const auditResult = await runAudit({ targetDir, minConfidence: options.minConfidence });
|
|
87
|
+
const baselineFile = options.baselinePath ?? path.join(targetDir, DEFAULT_BASELINE_FILENAME);
|
|
88
|
+
const baseline = createBaseline(auditResult.findings, targetDir);
|
|
89
|
+
await saveBaseline(baseline, baselineFile);
|
|
90
|
+
process.stdout.write(`Generated baseline with ${baseline.entries.length} findings at '${baselineFile}'.\n`);
|
|
91
|
+
return EXIT_CODES.SUCCESS;
|
|
92
|
+
}
|
|
93
|
+
// 7. Audit scan command (default)
|
|
94
|
+
let changedFiles;
|
|
95
|
+
if (options.changedOnly) {
|
|
96
|
+
const foundChanged = await getChangedFiles(options.targetDir);
|
|
97
|
+
if (foundChanged === null) {
|
|
98
|
+
process.stderr.write(`sourceverity: --changed requested but '${options.targetDir}' is not a git repository.\n`);
|
|
99
|
+
return EXIT_CODES.USER_ERROR;
|
|
100
|
+
}
|
|
101
|
+
changedFiles = foundChanged;
|
|
102
|
+
}
|
|
103
|
+
const result = await runAudit({
|
|
104
|
+
targetDir: options.targetDir,
|
|
105
|
+
minConfidence: options.minConfidence,
|
|
106
|
+
changedFiles,
|
|
107
|
+
});
|
|
108
|
+
// Handle baseline comparison if baseline path is provided or checking baseline
|
|
109
|
+
let effectiveResult = result;
|
|
110
|
+
if (options.baselinePath || options.command === "baseline") {
|
|
111
|
+
const baselineFile = options.baselinePath ?? path.join(path.resolve(options.targetDir), DEFAULT_BASELINE_FILENAME);
|
|
112
|
+
const loadedBaseline = await loadBaseline(baselineFile);
|
|
113
|
+
if (loadedBaseline) {
|
|
114
|
+
const delta = compareWithBaseline(result.findings, loadedBaseline);
|
|
115
|
+
effectiveResult = {
|
|
116
|
+
...result,
|
|
117
|
+
findings: delta.newFindings,
|
|
118
|
+
};
|
|
119
|
+
if (!options.quiet && options.format === "pretty") {
|
|
120
|
+
process.stdout.write(`Baseline check against '${baselineFile}': ${delta.baselineCount} baseline, ${delta.newCount} new, ${delta.resolvedCount} resolved.\n\n`);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
if (options.updateBaseline) {
|
|
125
|
+
const baselineFile = options.baselinePath ?? path.join(path.resolve(options.targetDir), DEFAULT_BASELINE_FILENAME);
|
|
126
|
+
const updatedBaseline = createBaseline(result.findings, options.targetDir);
|
|
127
|
+
await saveBaseline(updatedBaseline, baselineFile);
|
|
128
|
+
}
|
|
129
|
+
// Output formatting
|
|
130
|
+
if (options.format === "pretty") {
|
|
131
|
+
process.stdout.write(renderTerminalReport(effectiveResult, { color: options.color, verbose: options.verbose }));
|
|
132
|
+
}
|
|
133
|
+
else if (options.format === "json") {
|
|
134
|
+
process.stdout.write(renderJsonReport(effectiveResult) + "\n");
|
|
135
|
+
}
|
|
136
|
+
else if (options.format === "agent") {
|
|
137
|
+
process.stdout.write(renderAgentReport(effectiveResult) + "\n");
|
|
138
|
+
}
|
|
139
|
+
else if (options.format === "sarif") {
|
|
140
|
+
process.stdout.write(renderSarifReport(effectiveResult) + "\n");
|
|
141
|
+
}
|
|
142
|
+
// Policy exit code evaluation
|
|
143
|
+
if (options.failOn === "never") {
|
|
144
|
+
return EXIT_CODES.SUCCESS;
|
|
145
|
+
}
|
|
146
|
+
const hasErrors = effectiveResult.findings.some((f) => f.severity === "error");
|
|
147
|
+
const hasWarnings = effectiveResult.findings.some((f) => f.severity === "warning");
|
|
148
|
+
if (options.failOn === "error" && hasErrors) {
|
|
149
|
+
return EXIT_CODES.POLICY_VIOLATION;
|
|
150
|
+
}
|
|
151
|
+
if (options.failOn === "warning" && (hasErrors || hasWarnings)) {
|
|
152
|
+
return EXIT_CODES.POLICY_VIOLATION;
|
|
153
|
+
}
|
|
154
|
+
return EXIT_CODES.SUCCESS;
|
|
155
|
+
}
|
|
156
|
+
//# sourceMappingURL=main.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"main.js","sourceRoot":"","sources":["../../src/cli/main.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export interface FingerprintInput {
|
|
2
|
+
readonly ruleId: string;
|
|
3
|
+
readonly filePath: string;
|
|
4
|
+
readonly enclosingScope?: string;
|
|
5
|
+
readonly nodeKind?: string | number;
|
|
6
|
+
readonly symbolName?: string;
|
|
7
|
+
readonly snippet?: string;
|
|
8
|
+
readonly extraKey?: string;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Computes a deterministic, semantic-first finding fingerprint.
|
|
12
|
+
*
|
|
13
|
+
* Uses SHA-256 digest truncated to 16 hex characters prefixed with "sv_".
|
|
14
|
+
* Deliberately excludes volatile source line/column numbers to maintain
|
|
15
|
+
* baseline identity when unrelated code edits occur above the finding.
|
|
16
|
+
*/
|
|
17
|
+
export declare function computeFingerprint(input: FingerprintInput): string;
|
|
18
|
+
//# sourceMappingURL=fingerprint.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fingerprint.d.ts","sourceRoot":"","sources":["../../src/core/fingerprint.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACpC,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,gBAAgB,GAAG,MAAM,CAkBlE"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
/**
|
|
3
|
+
* Computes a deterministic, semantic-first finding fingerprint.
|
|
4
|
+
*
|
|
5
|
+
* Uses SHA-256 digest truncated to 16 hex characters prefixed with "sv_".
|
|
6
|
+
* Deliberately excludes volatile source line/column numbers to maintain
|
|
7
|
+
* baseline identity when unrelated code edits occur above the finding.
|
|
8
|
+
*/
|
|
9
|
+
export function computeFingerprint(input) {
|
|
10
|
+
const normalizedPath = input.filePath.replace(/\\/g, "/");
|
|
11
|
+
const normalizedSnippet = (input.snippet ?? "")
|
|
12
|
+
.replace(/\s+/g, " ")
|
|
13
|
+
.trim();
|
|
14
|
+
const payload = [
|
|
15
|
+
input.ruleId,
|
|
16
|
+
normalizedPath,
|
|
17
|
+
input.enclosingScope ?? "global",
|
|
18
|
+
String(input.nodeKind ?? ""),
|
|
19
|
+
input.symbolName ?? "",
|
|
20
|
+
normalizedSnippet,
|
|
21
|
+
input.extraKey ?? "",
|
|
22
|
+
].join("::");
|
|
23
|
+
const hash = createHash("sha256").update(payload, "utf-8").digest("hex").slice(0, 16);
|
|
24
|
+
return `sv_${hash}`;
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=fingerprint.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fingerprint.js","sourceRoot":"","sources":["../../src/core/fingerprint.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAYzC;;;;;;GAMG;AACH,MAAM,UAAU,kBAAkB,CAAC,KAAuB;IACxD,MAAM,cAAc,GAAG,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IAC1D,MAAM,iBAAiB,GAAG,CAAC,KAAK,CAAC,OAAO,IAAI,EAAE,CAAC;SAC5C,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC;SACpB,IAAI,EAAE,CAAC;IAEV,MAAM,OAAO,GAAG;QACd,KAAK,CAAC,MAAM;QACZ,cAAc;QACd,KAAK,CAAC,cAAc,IAAI,QAAQ;QAChC,MAAM,CAAC,KAAK,CAAC,QAAQ,IAAI,EAAE,CAAC;QAC5B,KAAK,CAAC,UAAU,IAAI,EAAE;QACtB,iBAAiB;QACjB,KAAK,CAAC,QAAQ,IAAI,EAAE;KACrB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAEb,MAAM,IAAI,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACtF,OAAO,MAAM,IAAI,EAAE,CAAC;AACtB,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Normalizes any file system path into a standardized POSIX relative path.
|
|
3
|
+
* Ensures consistent output across Windows and POSIX systems.
|
|
4
|
+
*/
|
|
5
|
+
export declare function normalizePath(filePath: string, relativeTo?: string): string;
|
|
6
|
+
/**
|
|
7
|
+
* Determines whether a file path has an accepted TypeScript or JavaScript extension.
|
|
8
|
+
*/
|
|
9
|
+
export declare function isSourceFile(filePath: string): boolean;
|
|
10
|
+
//# sourceMappingURL=paths.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../src/core/paths.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,CAsB3E;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAEtD"}
|