@vyuhlabs/dxkit 2.4.8 → 2.5.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/CHANGELOG.md +235 -0
- package/README.md +360 -439
- package/dist/analyzers/security/aggregator.d.ts.map +1 -1
- package/dist/analyzers/security/aggregator.js +4 -46
- package/dist/analyzers/security/aggregator.js.map +1 -1
- package/dist/analyzers/tools/fingerprint.d.ts +91 -26
- package/dist/analyzers/tools/fingerprint.d.ts.map +1 -1
- package/dist/analyzers/tools/fingerprint.js +111 -22
- package/dist/analyzers/tools/fingerprint.js.map +1 -1
- package/dist/analyzers/tools/generic.d.ts.map +1 -1
- package/dist/analyzers/tools/generic.js +6 -1
- package/dist/analyzers/tools/generic.js.map +1 -1
- package/dist/analyzers/tools/gitleaks.d.ts +24 -1
- package/dist/analyzers/tools/gitleaks.d.ts.map +1 -1
- package/dist/analyzers/tools/gitleaks.js +20 -11
- package/dist/analyzers/tools/gitleaks.js.map +1 -1
- package/dist/analyzers/types.d.ts +6 -4
- package/dist/analyzers/types.d.ts.map +1 -1
- package/dist/baseline/baseline-file.d.ts +104 -0
- package/dist/baseline/baseline-file.d.ts.map +1 -0
- package/dist/baseline/baseline-file.js +110 -0
- package/dist/baseline/baseline-file.js.map +1 -0
- package/dist/baseline/check-renderers.d.ts +108 -0
- package/dist/baseline/check-renderers.d.ts.map +1 -0
- package/dist/baseline/check-renderers.js +379 -0
- package/dist/baseline/check-renderers.js.map +1 -0
- package/dist/baseline/check.d.ts +127 -0
- package/dist/baseline/check.d.ts.map +1 -0
- package/dist/baseline/check.js +462 -0
- package/dist/baseline/check.js.map +1 -0
- package/dist/baseline/content-hash.d.ts +83 -0
- package/dist/baseline/content-hash.d.ts.map +1 -0
- package/dist/baseline/content-hash.js +131 -0
- package/dist/baseline/content-hash.js.map +1 -0
- package/dist/baseline/create.d.ts +96 -0
- package/dist/baseline/create.d.ts.map +1 -0
- package/dist/baseline/create.js +339 -0
- package/dist/baseline/create.js.map +1 -0
- package/dist/baseline/entry-to-located.d.ts +35 -0
- package/dist/baseline/entry-to-located.d.ts.map +1 -0
- package/dist/baseline/entry-to-located.js +72 -0
- package/dist/baseline/entry-to-located.js.map +1 -0
- package/dist/baseline/finding-identity.d.ts +47 -0
- package/dist/baseline/finding-identity.d.ts.map +1 -0
- package/dist/baseline/finding-identity.js +292 -0
- package/dist/baseline/finding-identity.js.map +1 -0
- package/dist/baseline/git-aware-match.d.ts +146 -0
- package/dist/baseline/git-aware-match.d.ts.map +1 -0
- package/dist/baseline/git-aware-match.js +439 -0
- package/dist/baseline/git-aware-match.js.map +1 -0
- package/dist/baseline/policy.d.ts +171 -0
- package/dist/baseline/policy.d.ts.map +1 -0
- package/dist/baseline/policy.js +206 -0
- package/dist/baseline/policy.js.map +1 -0
- package/dist/baseline/producers/health.d.ts +30 -0
- package/dist/baseline/producers/health.d.ts.map +1 -0
- package/dist/baseline/producers/health.js +42 -0
- package/dist/baseline/producers/health.js.map +1 -0
- package/dist/baseline/producers/index.d.ts +164 -0
- package/dist/baseline/producers/index.d.ts.map +1 -0
- package/dist/baseline/producers/index.js +200 -0
- package/dist/baseline/producers/index.js.map +1 -0
- package/dist/baseline/producers/licenses.d.ts +23 -0
- package/dist/baseline/producers/licenses.d.ts.map +1 -0
- package/dist/baseline/producers/licenses.js +46 -0
- package/dist/baseline/producers/licenses.js.map +1 -0
- package/dist/baseline/producers/quality.d.ts +39 -0
- package/dist/baseline/producers/quality.d.ts.map +1 -0
- package/dist/baseline/producers/quality.js +84 -0
- package/dist/baseline/producers/quality.js.map +1 -0
- package/dist/baseline/producers/secret-hmac.d.ts +45 -0
- package/dist/baseline/producers/secret-hmac.d.ts.map +1 -0
- package/dist/baseline/producers/secret-hmac.js +70 -0
- package/dist/baseline/producers/secret-hmac.js.map +1 -0
- package/dist/baseline/producers/security.d.ts +59 -0
- package/dist/baseline/producers/security.d.ts.map +1 -0
- package/dist/baseline/producers/security.js +135 -0
- package/dist/baseline/producers/security.js.map +1 -0
- package/dist/baseline/producers/tests.d.ts +36 -0
- package/dist/baseline/producers/tests.d.ts.map +1 -0
- package/dist/baseline/producers/tests.js +69 -0
- package/dist/baseline/producers/tests.js.map +1 -0
- package/dist/baseline/salt.d.ts +45 -0
- package/dist/baseline/salt.d.ts.map +1 -0
- package/dist/baseline/salt.js +113 -0
- package/dist/baseline/salt.js.map +1 -0
- package/dist/baseline/show.d.ts +79 -0
- package/dist/baseline/show.d.ts.map +1 -0
- package/dist/baseline/show.js +233 -0
- package/dist/baseline/show.js.map +1 -0
- package/dist/baseline/types.d.ts +482 -0
- package/dist/baseline/types.d.ts.map +1 -0
- package/dist/baseline/types.js +53 -0
- package/dist/baseline/types.js.map +1 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +360 -81
- package/dist/cli.js.map +1 -1
- package/dist/codebase-scanner.d.ts.map +1 -1
- package/dist/codebase-scanner.js +0 -1
- package/dist/codebase-scanner.js.map +1 -1
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +0 -4
- package/dist/constants.js.map +1 -1
- package/dist/doctor.d.ts.map +1 -1
- package/dist/doctor.js +22 -25
- package/dist/doctor.js.map +1 -1
- package/dist/fail-on.d.ts +84 -0
- package/dist/fail-on.d.ts.map +1 -0
- package/dist/fail-on.js +128 -0
- package/dist/fail-on.js.map +1 -0
- package/dist/generator.d.ts.map +1 -1
- package/dist/generator.js +2 -141
- package/dist/generator.js.map +1 -1
- package/dist/languages/csharp.d.ts.map +1 -1
- package/dist/languages/csharp.js +0 -9
- package/dist/languages/csharp.js.map +1 -1
- package/dist/languages/go.d.ts.map +1 -1
- package/dist/languages/go.js +0 -15
- package/dist/languages/go.js.map +1 -1
- package/dist/languages/index.d.ts +1 -1
- package/dist/languages/index.d.ts.map +1 -1
- package/dist/languages/index.js.map +1 -1
- package/dist/languages/java.d.ts.map +1 -1
- package/dist/languages/java.js +0 -6
- package/dist/languages/java.js.map +1 -1
- package/dist/languages/kotlin.d.ts.map +1 -1
- package/dist/languages/kotlin.js +0 -11
- package/dist/languages/kotlin.js.map +1 -1
- package/dist/languages/python.d.ts.map +1 -1
- package/dist/languages/python.js +0 -15
- package/dist/languages/python.js.map +1 -1
- package/dist/languages/ruby.d.ts.map +1 -1
- package/dist/languages/ruby.js +0 -6
- package/dist/languages/ruby.js.map +1 -1
- package/dist/languages/rust.d.ts.map +1 -1
- package/dist/languages/rust.js +0 -4
- package/dist/languages/rust.js.map +1 -1
- package/dist/languages/types.d.ts +2 -28
- package/dist/languages/types.d.ts.map +1 -1
- package/dist/languages/typescript.d.ts.map +1 -1
- package/dist/languages/typescript.js +26 -4
- package/dist/languages/typescript.js.map +1 -1
- package/dist/lib.d.ts +2 -3
- package/dist/lib.d.ts.map +1 -1
- package/dist/lib.js +3 -6
- package/dist/lib.js.map +1 -1
- package/dist/prompts.d.ts.map +1 -1
- package/dist/prompts.js +0 -10
- package/dist/prompts.js.map +1 -1
- package/dist/report-schema.d.ts +42 -0
- package/dist/report-schema.d.ts.map +1 -0
- package/dist/report-schema.js +54 -0
- package/dist/report-schema.js.map +1 -0
- package/dist/ship-installers.d.ts +106 -0
- package/dist/ship-installers.d.ts.map +1 -0
- package/dist/ship-installers.js +415 -0
- package/dist/ship-installers.js.map +1 -0
- package/dist/types.d.ts +0 -4
- package/dist/types.d.ts.map +1 -1
- package/dist/update.d.ts.map +1 -1
- package/dist/update.js +0 -4
- package/dist/update.js.map +1 -1
- package/package.json +17 -11
- package/templates/.claude/agents/onboarding.md +5 -4
- package/templates/.claude/agents-available/codebase-explorer.md +1 -1
- package/templates/.claude/agents-available/debugger.md +2 -2
- package/templates/.claude/agents-available/health-auditor.md +2 -2
- package/templates/.claude/commands/doctor.md +20 -12
- package/templates/.claude/skills/build/SKILL.md.template +22 -30
- package/templates/.claude/skills/deploy/SKILL.md.template +5 -25
- package/templates/.claude/skills/doctor/SKILL.md +24 -47
- package/templates/.claude/skills/gcloud/SKILL.md +5 -5
- package/templates/.claude/skills/learned/SKILL.md +1 -1
- package/templates/.claude/skills/pulumi/SKILL.md +2 -2
- package/templates/.claude/skills/quality/SKILL.md.template +4 -23
- package/templates/.claude/skills/review/SKILL.md.template +4 -3
- package/templates/.claude/skills/scaffold/SKILL.md.template +5 -15
- package/templates/.claude/skills/secrets/SKILL.md +20 -21
- package/templates/.claude/skills/session/SKILL.md +20 -31
- package/templates/.claude/skills/test/SKILL.md.template +1 -7
- package/templates/.devcontainer/devcontainer.json +81 -0
- package/templates/.devcontainer/install-agent-clis.sh +42 -0
- package/templates/.devcontainer/post-create.sh +67 -0
- package/templates/.githooks/pre-commit +55 -0
- package/templates/.githooks/pre-push +63 -0
- package/templates/.github/workflows/dxkit-baseline-refresh.yml +78 -0
- package/templates/.github/workflows/dxkit-guardrails.yml +98 -0
- package/templates/CLAUDE.md.template +62 -196
- package/dist/project-yaml.d.ts +0 -13
- package/dist/project-yaml.d.ts.map +0 -1
- package/dist/project-yaml.js +0 -188
- package/dist/project-yaml.js.map +0 -1
- package/templates/.ai/README.md +0 -117
- package/templates/.ai/prompts/execution-prompt.md +0 -9
- package/templates/.ai/prompts/planning-prompt.md +0 -18
- package/templates/.ai/prompts/session-end-template.md +0 -182
- package/templates/.ai/prompts/session-end.md +0 -132
- package/templates/.ai/prompts/session-start.md +0 -109
- package/templates/.ai/prompts/step-by-step.md +0 -113
- package/templates/.ai/sessions/.gitkeep +0 -0
- package/templates/.claude/commands/setup-pr-review.md +0 -72
- package/templates/.devcontainer/Dockerfile.dev.template +0 -89
- package/templates/.devcontainer/devcontainer.json.template +0 -184
- package/templates/.devcontainer/docker-compose.yml.template +0 -105
- package/templates/.devcontainer/init-scripts/01-init.sql.template +0 -12
- package/templates/.devcontainer/post-create.sh.template +0 -298
- package/templates/.github/workflows/ci.yml.template +0 -399
- package/templates/.github/workflows/quality.yml.template +0 -376
- package/templates/.pre-commit-config.yaml.template +0 -106
- package/templates/.project/config/edit_config.py +0 -275
- package/templates/.project/config/project_config.py +0 -894
- package/templates/.project/scripts/codegen/generate-all.sh +0 -20
- package/templates/.project/scripts/codegen/validate-all.sh +0 -17
- package/templates/.project/scripts/docs/generate-all.sh +0 -30
- package/templates/.project/scripts/docs/serve.sh +0 -20
- package/templates/.project/scripts/quality/fix-all.sh +0 -138
- package/templates/.project/scripts/quality/lint-go.sh +0 -34
- package/templates/.project/scripts/quality/lint-python.sh +0 -54
- package/templates/.project/scripts/quality/run-all.sh +0 -497
- package/templates/.project/scripts/session/commit.sh +0 -70
- package/templates/.project/scripts/session/create-pr.sh +0 -165
- package/templates/.project/scripts/session/end.sh +0 -207
- package/templates/.project/scripts/session/start.sh +0 -233
- package/templates/.project/scripts/setup/doctor.sh +0 -404
- package/templates/.project/scripts/setup/interactive-setup.sh +0 -585
- package/templates/.project/scripts/sync/sync-template.sh +0 -328
- package/templates/.project/scripts/test/run-all.sh +0 -179
- package/templates/.project/scripts/test/run-quick.sh +0 -25
- package/templates/Makefile +0 -514
- package/templates/config/versions.yaml +0 -57
- package/templates/configs/go/.golangci.yml.template +0 -172
- package/templates/configs/go/go.mod.template +0 -15
- package/templates/configs/java/README.md +0 -6
- package/templates/configs/kotlin/README.md +0 -6
- package/templates/configs/node/package.json.template +0 -67
- package/templates/configs/node/tsconfig.json.template +0 -53
- package/templates/configs/python/pyproject.toml.template +0 -92
- package/templates/configs/python/pytest.ini.template +0 -64
- package/templates/configs/python/ruff.toml.template +0 -79
- package/templates/configs/ruby/README.md +0 -6
- package/templates/configs/rust/Cargo.toml.template +0 -51
- package/templates/configs/shared/.editorconfig +0 -67
- package/templates/scripts/validate-templates.sh +0 -449
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Content-hash identity — drift-tolerant matching via the actual
|
|
4
|
+
* source code around a finding rather than its line position.
|
|
5
|
+
*
|
|
6
|
+
* The line-bucket identity scheme tolerates ±2 lines of drift; the
|
|
7
|
+
* git-aware matcher tolerates any line shift git can describe.
|
|
8
|
+
* Neither helps when git history is unavailable (shallow clone,
|
|
9
|
+
* force-pushed baseline commit) or when the line-bucket boundary
|
|
10
|
+
* straddles a context-stable region. The content-hash layer is the
|
|
11
|
+
* third fallback: pair findings whose surrounding code is byte-
|
|
12
|
+
* identical, regardless of where in the file they live.
|
|
13
|
+
*
|
|
14
|
+
* Pipeline:
|
|
15
|
+
*
|
|
16
|
+
* 1. The producer (Phase 3 baseline-create) reads each finding's
|
|
17
|
+
* surrounding context lines, normalizes whitespace, and
|
|
18
|
+
* computes a SHA-1[0:16] hash. The hash is stamped on the
|
|
19
|
+
* finding entry in the baseline file.
|
|
20
|
+
* 2. At guardrail-check time, the current scan computes content
|
|
21
|
+
* hashes the same way for its own findings.
|
|
22
|
+
* 3. The matcher's content-hash pass pairs prior + current
|
|
23
|
+
* findings with matching `(canonical-rule, contentHash)` after
|
|
24
|
+
* location-based pairing has exhausted what git can do.
|
|
25
|
+
*
|
|
26
|
+
* Trade-offs vs. line-bucket / git-aware match:
|
|
27
|
+
*
|
|
28
|
+
* - Survives any vertical drift (the line number is irrelevant).
|
|
29
|
+
* - Survives file rename + reformat + cross-file refactor when
|
|
30
|
+
* the immediate context survives.
|
|
31
|
+
* - Fails when the surrounding context changes — even a single
|
|
32
|
+
* adjacent variable rename invalidates the hash.
|
|
33
|
+
* - Vulnerable to collisions when two findings have identical
|
|
34
|
+
* context (rare for code-pattern findings, more likely for
|
|
35
|
+
* hygiene markers in similar boilerplate).
|
|
36
|
+
*
|
|
37
|
+
* The matcher tags content-hash matches with confidence 0.80 — below
|
|
38
|
+
* git-line-fuzz (0.88) so the brownfield policy's per-severity
|
|
39
|
+
* thresholds naturally distinguish them. For low-severity findings
|
|
40
|
+
* (threshold 0.90 by default), a content-hash match demotes to
|
|
41
|
+
* `'uncertain'` rather than silently pairing; for critical findings
|
|
42
|
+
* (threshold 0.75), the same match passes through cleanly.
|
|
43
|
+
*/
|
|
44
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
45
|
+
exports.CONTENT_HASH_CONTEXT_LINES = void 0;
|
|
46
|
+
exports.computeContentHash = computeContentHash;
|
|
47
|
+
exports.readFileFromCommit = readFileFromCommit;
|
|
48
|
+
exports.computeContentHashFromCommit = computeContentHashFromCommit;
|
|
49
|
+
const crypto_1 = require("crypto");
|
|
50
|
+
const child_process_1 = require("child_process");
|
|
51
|
+
/**
|
|
52
|
+
* Width of the context window read on each side of the finding's
|
|
53
|
+
* reported line. Three lines above + three lines below + the line
|
|
54
|
+
* itself = a seven-line window that captures the immediate
|
|
55
|
+
* surrounding code without being so wide that unrelated edits
|
|
56
|
+
* invalidate the hash.
|
|
57
|
+
*/
|
|
58
|
+
exports.CONTENT_HASH_CONTEXT_LINES = 3;
|
|
59
|
+
/**
|
|
60
|
+
* Pure function: compute the content hash for a finding at `line`
|
|
61
|
+
* inside `fileContent`. Whitespace is normalized — trailing
|
|
62
|
+
* whitespace stripped, internal runs collapsed to a single space,
|
|
63
|
+
* empty lines preserved as empty — so reformat-only edits don't
|
|
64
|
+
* churn the hash.
|
|
65
|
+
*
|
|
66
|
+
* `line` is 1-based to match every other dxkit line-number contract.
|
|
67
|
+
* `contextLines` defaults to `CONTENT_HASH_CONTEXT_LINES`. Lines
|
|
68
|
+
* before the start of the file or past the end are clamped (the
|
|
69
|
+
* window is smaller near the file edges; that's fine — hashing a
|
|
70
|
+
* shorter window is still deterministic).
|
|
71
|
+
*/
|
|
72
|
+
function computeContentHash(fileContent, line, contextLines = exports.CONTENT_HASH_CONTEXT_LINES) {
|
|
73
|
+
const lines = fileContent.split('\n');
|
|
74
|
+
const startIdx = Math.max(0, line - 1 - contextLines);
|
|
75
|
+
const endIdx = Math.min(lines.length, line + contextLines);
|
|
76
|
+
const window = lines.slice(startIdx, endIdx);
|
|
77
|
+
const normalized = window.map(normalizeLine).join('\n');
|
|
78
|
+
return (0, crypto_1.createHash)('sha1').update(normalized).digest('hex').slice(0, 16);
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Collapse internal whitespace runs to a single space + strip
|
|
82
|
+
* leading / trailing whitespace. Tab vs spaces, mixed indentation,
|
|
83
|
+
* and trailing whitespace become equivalent. Empty lines pass
|
|
84
|
+
* through as empty (no normalization needed) so they preserve their
|
|
85
|
+
* position-information in the window.
|
|
86
|
+
*/
|
|
87
|
+
function normalizeLine(line) {
|
|
88
|
+
return line.replace(/\s+/g, ' ').trim();
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Read a file's content at a specific commit. Returns null when git
|
|
92
|
+
* can't resolve the path-at-commit pair — file didn't exist at
|
|
93
|
+
* `sha`, file is binary, sha is unreachable. Callers treat null
|
|
94
|
+
* the same as "content-hash unavailable for this path."
|
|
95
|
+
*
|
|
96
|
+
* Uses `git show <sha>:<path>` which does not require checking out
|
|
97
|
+
* the commit — safe to call repeatedly in a tight loop without
|
|
98
|
+
* touching the working tree.
|
|
99
|
+
*/
|
|
100
|
+
function readFileFromCommit(cwd, sha, file) {
|
|
101
|
+
try {
|
|
102
|
+
return (0, child_process_1.execFileSync)('git', ['show', `${sha}:${file}`], {
|
|
103
|
+
cwd,
|
|
104
|
+
encoding: 'utf8',
|
|
105
|
+
// Cap output size — git show on a 100MB committed binary would
|
|
106
|
+
// otherwise blow the default stdio buffer. 10MB is generous for
|
|
107
|
+
// any real source file.
|
|
108
|
+
maxBuffer: 10 * 1024 * 1024,
|
|
109
|
+
// Silence the "fatal: path X does not exist" message git emits
|
|
110
|
+
// to stderr when the file/sha pair doesn't resolve. Callers
|
|
111
|
+
// expect a null return, not a stderr message bleeding through.
|
|
112
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
catch {
|
|
116
|
+
return null;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Combined helper: read the file at a commit and compute its
|
|
121
|
+
* content hash at the given line. Returns null when the file
|
|
122
|
+
* couldn't be read. Used by the producer (Phase 3 baseline-create)
|
|
123
|
+
* to stamp content hashes on baseline entries.
|
|
124
|
+
*/
|
|
125
|
+
function computeContentHashFromCommit(cwd, sha, file, line, contextLines = exports.CONTENT_HASH_CONTEXT_LINES) {
|
|
126
|
+
const content = readFileFromCommit(cwd, sha, file);
|
|
127
|
+
if (content === null)
|
|
128
|
+
return null;
|
|
129
|
+
return computeContentHash(content, line, contextLines);
|
|
130
|
+
}
|
|
131
|
+
//# sourceMappingURL=content-hash.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"content-hash.js","sourceRoot":"","sources":["../../src/baseline/content-hash.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;;;AA2BH,gDAWC;AAuBD,gDAiBC;AAQD,oEAUC;AA9FD,mCAAoC;AACpC,iDAA6C;AAE7C;;;;;;GAMG;AACU,QAAA,0BAA0B,GAAG,CAAC,CAAC;AAE5C;;;;;;;;;;;;GAYG;AACH,SAAgB,kBAAkB,CAChC,WAAmB,EACnB,IAAY,EACZ,eAAuB,kCAA0B;IAEjD,MAAM,KAAK,GAAG,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACtC,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,GAAG,CAAC,GAAG,YAAY,CAAC,CAAC;IACtD,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,EAAE,IAAI,GAAG,YAAY,CAAC,CAAC;IAC3D,MAAM,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IAC7C,MAAM,UAAU,GAAG,MAAM,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACxD,OAAO,IAAA,mBAAU,EAAC,MAAM,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AAC1E,CAAC;AAED;;;;;;GAMG;AACH,SAAS,aAAa,CAAC,IAAY;IACjC,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;AAC1C,CAAC;AAED;;;;;;;;;GASG;AACH,SAAgB,kBAAkB,CAAC,GAAW,EAAE,GAAW,EAAE,IAAY;IACvE,IAAI,CAAC;QACH,OAAO,IAAA,4BAAY,EAAC,KAAK,EAAE,CAAC,MAAM,EAAE,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC,EAAE;YACrD,GAAG;YACH,QAAQ,EAAE,MAAM;YAChB,+DAA+D;YAC/D,gEAAgE;YAChE,wBAAwB;YACxB,SAAS,EAAE,EAAE,GAAG,IAAI,GAAG,IAAI;YAC3B,+DAA+D;YAC/D,4DAA4D;YAC5D,+DAA+D;YAC/D,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC;SAClC,CAAC,CAAC;IACL,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,SAAgB,4BAA4B,CAC1C,GAAW,EACX,GAAW,EACX,IAAY,EACZ,IAAY,EACZ,eAAuB,kCAA0B;IAEjD,MAAM,OAAO,GAAG,kBAAkB,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;IACnD,IAAI,OAAO,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IAClC,OAAO,kBAAkB,CAAC,OAAO,EAAE,IAAI,EAAE,YAAY,CAAC,CAAC;AACzD,CAAC"}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `dxkit baseline create` orchestrator.
|
|
3
|
+
*
|
|
4
|
+
* Builds the shared producer context (runs every analyzer once),
|
|
5
|
+
* dispatches through the canonical producer registry (CLAUDE.md
|
|
6
|
+
* Rule 10), captures repo + analysis-environment metadata, and
|
|
7
|
+
* writes the result to `.dxkit/baselines/<name>.json`. The on-disk
|
|
8
|
+
* file is the durable record subsequent `guardrail check` runs diff
|
|
9
|
+
* against.
|
|
10
|
+
*
|
|
11
|
+
* This module is the producer side; the matcher + classifier on the
|
|
12
|
+
* consumer side already exist in `git-aware-match.ts` and
|
|
13
|
+
* `policy.ts`. The two are connected by the file format defined in
|
|
14
|
+
* `baseline-file.ts`.
|
|
15
|
+
*
|
|
16
|
+
* Per-kind producer coverage + deferral rationale live in the
|
|
17
|
+
* registry index (`./producers/index.ts`) — the single discovery
|
|
18
|
+
* surface. Adding a new identity kind or analyzer means
|
|
19
|
+
* registering a producer there, never an edit here.
|
|
20
|
+
*/
|
|
21
|
+
import type { BaselineAnalysisMeta, BaselineFile, BaselineRepoState } from './baseline-file';
|
|
22
|
+
import type { ProducerContext } from './producers';
|
|
23
|
+
import type { SaltMode } from './salt';
|
|
24
|
+
import type { BaselineEntry } from './types';
|
|
25
|
+
import type { SecurityAggregate } from '../analyzers/security/aggregator';
|
|
26
|
+
export interface CreateBaselineOptions {
|
|
27
|
+
/** Repo root to baseline. Caller should pass an absolute path. */
|
|
28
|
+
readonly cwd: string;
|
|
29
|
+
/** Baseline name (becomes the filename stem under `.dxkit/baselines/`).
|
|
30
|
+
* Defaults to `'main'`. Different names allow per-branch / per-
|
|
31
|
+
* environment baselines to coexist on disk. */
|
|
32
|
+
readonly name?: string;
|
|
33
|
+
/** When true, overwrite an existing baseline file at the same path.
|
|
34
|
+
* When false (default), an existing file makes `createBaseline`
|
|
35
|
+
* throw — guards against accidentally clobbering a committed
|
|
36
|
+
* baseline with a fresh capture. */
|
|
37
|
+
readonly force?: boolean;
|
|
38
|
+
/** Forwarded to the underlying analyzer for per-tool timing logs. */
|
|
39
|
+
readonly verbose?: boolean;
|
|
40
|
+
}
|
|
41
|
+
export interface CreateBaselineResult {
|
|
42
|
+
readonly path: string;
|
|
43
|
+
readonly file: BaselineFile;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Test seam: clear the version cache between test runs so per-test
|
|
47
|
+
* fixtures don't leak resolutions into one another. Production
|
|
48
|
+
* callers never use this — the cache lives for the entire CLI
|
|
49
|
+
* invocation and dies with the process.
|
|
50
|
+
*/
|
|
51
|
+
export declare function clearToolVersionCache(): void;
|
|
52
|
+
/**
|
|
53
|
+
* Snapshot of one analyzer run, in the exact shape the baseline file
|
|
54
|
+
* and the guardrail-check both need. Built by `gatherCurrentScan`
|
|
55
|
+
* once and consumed by either path.
|
|
56
|
+
*
|
|
57
|
+
* Why this is shared: the guardrail check re-runs every analyzer to
|
|
58
|
+
* produce the "current" side of the diff. Without a shared step, the
|
|
59
|
+
* gather + producer-dispatch logic would have to be duplicated in
|
|
60
|
+
* `check.ts` — exactly the class of duplication CLAUDE.md Rule 2
|
|
61
|
+
* forbids for tool invocation, and the same hazard applies here.
|
|
62
|
+
*/
|
|
63
|
+
export interface CurrentScan {
|
|
64
|
+
readonly findings: ReadonlyArray<BaselineEntry>;
|
|
65
|
+
readonly aggregate: SecurityAggregate;
|
|
66
|
+
readonly repoState: BaselineRepoState;
|
|
67
|
+
readonly saltMode: SaltMode;
|
|
68
|
+
/** Per-tool name → version map for the run that just completed. */
|
|
69
|
+
readonly tools: Readonly<Record<string, string>>;
|
|
70
|
+
/** Envelope metadata for the run. `toolchainHash` is already
|
|
71
|
+
* resolved from `tools`. */
|
|
72
|
+
readonly analysisMeta: BaselineAnalysisMeta;
|
|
73
|
+
/** Echoed back so the guardrail check can attribute per-pair
|
|
74
|
+
* severity, overlap, and reachable signals without re-gathering. */
|
|
75
|
+
readonly producerCtx: ProducerContext;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Run every analyzer once, dispatch through the producer registry,
|
|
79
|
+
* and return the assembled `CurrentScan`. Used by `createBaseline`
|
|
80
|
+
* to capture today's state and by `runGuardrailCheck` to gather the
|
|
81
|
+
* current side of the cross-run diff.
|
|
82
|
+
*
|
|
83
|
+
* Pure-orchestrator: each step has a single responsibility (analyze
|
|
84
|
+
* → produce entries → resolve envelope metadata).
|
|
85
|
+
*/
|
|
86
|
+
export declare function gatherCurrentScan(options: {
|
|
87
|
+
readonly cwd: string;
|
|
88
|
+
readonly verbose?: boolean;
|
|
89
|
+
}): Promise<CurrentScan>;
|
|
90
|
+
/**
|
|
91
|
+
* Run the baseline-create pipeline. Pure-orchestrator: gather the
|
|
92
|
+
* current scan via the shared step, then write it to disk under the
|
|
93
|
+
* given name.
|
|
94
|
+
*/
|
|
95
|
+
export declare function createBaseline(options: CreateBaselineOptions): Promise<CreateBaselineResult>;
|
|
96
|
+
//# sourceMappingURL=create.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create.d.ts","sourceRoot":"","sources":["../../src/baseline/create.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAoBH,OAAO,KAAK,EAAE,oBAAoB,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAG7F,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEnD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AACvC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC7C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;AAE1E,MAAM,WAAW,qBAAqB;IACpC,kEAAkE;IAClE,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB;;oDAEgD;IAChD,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB;;;yCAGqC;IACrC,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;IACzB,qEAAqE;IACrE,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;CAC7B;AA6JD;;;;;GAKG;AACH,wBAAgB,qBAAqB,IAAI,IAAI,CAE5C;AAED;;;;;;;;;;GAUG;AACH,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,QAAQ,EAAE,aAAa,CAAC,aAAa,CAAC,CAAC;IAChD,QAAQ,CAAC,SAAS,EAAE,iBAAiB,CAAC;IACtC,QAAQ,CAAC,SAAS,EAAE,iBAAiB,CAAC;IACtC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAC5B,mEAAmE;IACnE,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACjD;iCAC6B;IAC7B,QAAQ,CAAC,YAAY,EAAE,oBAAoB,CAAC;IAC5C;yEACqE;IACrE,QAAQ,CAAC,WAAW,EAAE,eAAe,CAAC;CACvC;AAED;;;;;;;;GAQG;AACH,wBAAsB,iBAAiB,CAAC,OAAO,EAAE;IAC/C,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;CAC5B,GAAG,OAAO,CAAC,WAAW,CAAC,CA0EvB;AAED;;;;GAIG;AACH,wBAAsB,cAAc,CAClC,OAAO,EAAE,qBAAqB,GAC7B,OAAO,CAAC,oBAAoB,CAAC,CA0B/B"}
|
|
@@ -0,0 +1,339 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* `dxkit baseline create` orchestrator.
|
|
4
|
+
*
|
|
5
|
+
* Builds the shared producer context (runs every analyzer once),
|
|
6
|
+
* dispatches through the canonical producer registry (CLAUDE.md
|
|
7
|
+
* Rule 10), captures repo + analysis-environment metadata, and
|
|
8
|
+
* writes the result to `.dxkit/baselines/<name>.json`. The on-disk
|
|
9
|
+
* file is the durable record subsequent `guardrail check` runs diff
|
|
10
|
+
* against.
|
|
11
|
+
*
|
|
12
|
+
* This module is the producer side; the matcher + classifier on the
|
|
13
|
+
* consumer side already exist in `git-aware-match.ts` and
|
|
14
|
+
* `policy.ts`. The two are connected by the file format defined in
|
|
15
|
+
* `baseline-file.ts`.
|
|
16
|
+
*
|
|
17
|
+
* Per-kind producer coverage + deferral rationale live in the
|
|
18
|
+
* registry index (`./producers/index.ts`) — the single discovery
|
|
19
|
+
* surface. Adding a new identity kind or analyzer means
|
|
20
|
+
* registering a producer there, never an edit here.
|
|
21
|
+
*/
|
|
22
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
23
|
+
if (k2 === undefined) k2 = k;
|
|
24
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
25
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
26
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
27
|
+
}
|
|
28
|
+
Object.defineProperty(o, k2, desc);
|
|
29
|
+
}) : (function(o, m, k, k2) {
|
|
30
|
+
if (k2 === undefined) k2 = k;
|
|
31
|
+
o[k2] = m[k];
|
|
32
|
+
}));
|
|
33
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
34
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
35
|
+
}) : function(o, v) {
|
|
36
|
+
o["default"] = v;
|
|
37
|
+
});
|
|
38
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
39
|
+
var ownKeys = function(o) {
|
|
40
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
41
|
+
var ar = [];
|
|
42
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
43
|
+
return ar;
|
|
44
|
+
};
|
|
45
|
+
return ownKeys(o);
|
|
46
|
+
};
|
|
47
|
+
return function (mod) {
|
|
48
|
+
if (mod && mod.__esModule) return mod;
|
|
49
|
+
var result = {};
|
|
50
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
51
|
+
__setModuleDefault(result, mod);
|
|
52
|
+
return result;
|
|
53
|
+
};
|
|
54
|
+
})();
|
|
55
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
56
|
+
exports.clearToolVersionCache = clearToolVersionCache;
|
|
57
|
+
exports.gatherCurrentScan = gatherCurrentScan;
|
|
58
|
+
exports.createBaseline = createBaseline;
|
|
59
|
+
const child_process_1 = require("child_process");
|
|
60
|
+
const crypto_1 = require("crypto");
|
|
61
|
+
const fs = __importStar(require("fs"));
|
|
62
|
+
const path = __importStar(require("path"));
|
|
63
|
+
const health_1 = require("../analyzers/health");
|
|
64
|
+
const cache_1 = require("../analyzers/cache");
|
|
65
|
+
const gather_1 = require("../analyzers/quality/gather");
|
|
66
|
+
const tests_1 = require("../analyzers/tests");
|
|
67
|
+
const gitleaks_1 = require("../analyzers/tools/gitleaks");
|
|
68
|
+
const tool_registry_1 = require("../analyzers/tools/tool-registry");
|
|
69
|
+
const constants_1 = require("../constants");
|
|
70
|
+
const baseline_file_1 = require("./baseline-file");
|
|
71
|
+
const policy_1 = require("./policy");
|
|
72
|
+
const producers_1 = require("./producers");
|
|
73
|
+
const salt_1 = require("./salt");
|
|
74
|
+
/** Hash used for baseline-envelope metadata fields (policy, ignore,
|
|
75
|
+
* toolchain, config). Distinct concern from finding-identity
|
|
76
|
+
* fingerprints — these never enter the matcher's identity space. */
|
|
77
|
+
function hashContent(content) {
|
|
78
|
+
return (0, crypto_1.createHash)('sha1').update(content).digest('hex').slice(0, 16); // fingerprint-helper-ok: envelope-metadata hash, not finding identity
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Read a small file's text content with the canonical "absent → ''"
|
|
82
|
+
* convention. Treating absent files as the empty string keeps the
|
|
83
|
+
* downstream metadata hash stable across runs where the file is
|
|
84
|
+
* still missing.
|
|
85
|
+
*/
|
|
86
|
+
function readOptionalFile(filePath) {
|
|
87
|
+
try {
|
|
88
|
+
return fs.readFileSync(filePath, 'utf8');
|
|
89
|
+
}
|
|
90
|
+
catch {
|
|
91
|
+
return '';
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
/** Resolve the absolute commit SHA + branch name of the working tree.
|
|
95
|
+
* Empty strings when the directory isn't a git repo — the rest of
|
|
96
|
+
* the orchestrator works fine, only the git-aware matcher loses its
|
|
97
|
+
* diff anchor on a future check. */
|
|
98
|
+
function readRepoState(cwd) {
|
|
99
|
+
const run = (...args) => {
|
|
100
|
+
try {
|
|
101
|
+
return (0, child_process_1.execFileSync)('git', args, {
|
|
102
|
+
cwd,
|
|
103
|
+
encoding: 'utf8',
|
|
104
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
105
|
+
}).trim();
|
|
106
|
+
}
|
|
107
|
+
catch {
|
|
108
|
+
return '';
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
return {
|
|
112
|
+
commitSha: run('rev-parse', 'HEAD'),
|
|
113
|
+
branch: run('rev-parse', '--abbrev-ref', 'HEAD'),
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
/** Build the analysis-environment hash bundle from the live repo. */
|
|
117
|
+
function buildAnalysisMeta(cwd) {
|
|
118
|
+
const policyHash = hashContent(JSON.stringify(policy_1.DEFAULT_BROWNFIELD_POLICY));
|
|
119
|
+
const ignoreHash = hashContent(readOptionalFile(path.join(cwd, '.dxkit-ignore')));
|
|
120
|
+
const configHash = hashContent(readOptionalFile(path.join(cwd, '.vyuh-dxkit.json')));
|
|
121
|
+
// toolchainHash is filled in by `createBaseline` once the
|
|
122
|
+
// per-tool version map has been resolved (depends on the gather).
|
|
123
|
+
return { dxkitVersion: constants_1.VERSION, policyHash, ignoreHash, toolchainHash: '', configHash };
|
|
124
|
+
}
|
|
125
|
+
/** Build the per-tool name → version map from the security
|
|
126
|
+
* aggregate's provenance. Sparse; only the tools that actually
|
|
127
|
+
* ran appear. Versions come from each tool's registered
|
|
128
|
+
* `versionCheck` invocation via `findTool`, so the resulting
|
|
129
|
+
* `toolchainHash` actually differs when a tool is upgraded —
|
|
130
|
+
* closing the drift-detection gap that placeholder values left
|
|
131
|
+
* open. In-process scanners (no external binary) are tagged with
|
|
132
|
+
* the dxkit version so a dxkit upgrade invalidates the toolchain
|
|
133
|
+
* hash even when no external tool changed — see
|
|
134
|
+
* `IN_PROCESS_TOOLS`.
|
|
135
|
+
*
|
|
136
|
+
* Compound tool names like `'osv-scanner-nuget-direct'` (the
|
|
137
|
+
* per-pack synthetic names the dep-vuln providers emit) are
|
|
138
|
+
* resolved by progressively shortening on `-` boundaries until a
|
|
139
|
+
* matching TOOL_DEFS key is found — so
|
|
140
|
+
* `'osv-scanner-nuget-direct'` → `'osv-scanner-nuget'` →
|
|
141
|
+
* `'osv-scanner'` (the canonical key). */
|
|
142
|
+
function buildToolsMap(toolNames, cwd) {
|
|
143
|
+
const out = {};
|
|
144
|
+
for (const name of toolNames) {
|
|
145
|
+
if (!name)
|
|
146
|
+
continue;
|
|
147
|
+
out[name] = resolveToolVersion(name, cwd);
|
|
148
|
+
}
|
|
149
|
+
return out;
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Scanner names that don't correspond to an external binary — their
|
|
153
|
+
* "version" tracks the dxkit version. Adding a new in-process
|
|
154
|
+
* scanner (e.g. a future regex-based dependency checker) means
|
|
155
|
+
* appending its name here, never special-casing inside
|
|
156
|
+
* `resolveToolVersion`.
|
|
157
|
+
*
|
|
158
|
+
* Drives the `provenance.{secrets,codePatterns,...}.tool` values
|
|
159
|
+
* that surface when external tools are unavailable — gitleaks
|
|
160
|
+
* absent → `grep-secrets` runs the in-process fallback; the
|
|
161
|
+
* TLS-bypass registry is always in-process.
|
|
162
|
+
*/
|
|
163
|
+
const IN_PROCESS_TOOLS = new Set(['tls-bypass-registry', 'grep-secrets']);
|
|
164
|
+
/**
|
|
165
|
+
* Per-process cache of resolved tool versions, keyed by `${name}::${cwd}`.
|
|
166
|
+
*
|
|
167
|
+
* Why this exists: `findTool` spawns an `execFileSync` subprocess to
|
|
168
|
+
* run each tool's `versionCheck` command. Under heavy concurrent
|
|
169
|
+
* load (parallel vitest workers, large suites running side-by-side),
|
|
170
|
+
* that subprocess can occasionally complete with empty stdout —
|
|
171
|
+
* `resolveToolVersion`'s `if (status.version) return status.version`
|
|
172
|
+
* branch is skipped, the `return 'present'` fallback fires, and the
|
|
173
|
+
* resulting toolchainHash drifts between two back-to-back gathers
|
|
174
|
+
* within the same process. The matcher's `tooling_drift` gate then
|
|
175
|
+
* fires spuriously.
|
|
176
|
+
*
|
|
177
|
+
* Tool versions don't change mid-process — once we've resolved
|
|
178
|
+
* `gitleaks → 8.24.0` for `cwd`, every subsequent ask in the same
|
|
179
|
+
* process should return the same answer. The cache locks the first
|
|
180
|
+
* probe's outcome and skips later subprocess spawns entirely; same
|
|
181
|
+
* answer always, with the side benefit of faster repeated gathers.
|
|
182
|
+
*
|
|
183
|
+
* NOT applied to `findTool` itself: `tools-cli.ts` runs an install
|
|
184
|
+
* command then immediately re-probes (the install just created the
|
|
185
|
+
* binary, we need fresh state). That callsite must keep getting
|
|
186
|
+
* uncached results. The cache stays local to the toolchain-version
|
|
187
|
+
* resolver here.
|
|
188
|
+
*/
|
|
189
|
+
const VERSION_CACHE = new Map();
|
|
190
|
+
function resolveToolVersion(name, cwd) {
|
|
191
|
+
const cacheKey = `${name}::${cwd}`;
|
|
192
|
+
const cached = VERSION_CACHE.get(cacheKey);
|
|
193
|
+
if (cached !== undefined)
|
|
194
|
+
return cached;
|
|
195
|
+
const resolved = resolveToolVersionUncached(name, cwd);
|
|
196
|
+
VERSION_CACHE.set(cacheKey, resolved);
|
|
197
|
+
return resolved;
|
|
198
|
+
}
|
|
199
|
+
function resolveToolVersionUncached(name, cwd) {
|
|
200
|
+
if (IN_PROCESS_TOOLS.has(name))
|
|
201
|
+
return `dxkit-${constants_1.VERSION}`;
|
|
202
|
+
const parts = name.split('-');
|
|
203
|
+
for (let i = parts.length; i > 0; i--) {
|
|
204
|
+
const candidate = parts.slice(0, i).join('-');
|
|
205
|
+
const def = tool_registry_1.TOOL_DEFS[candidate];
|
|
206
|
+
if (!def)
|
|
207
|
+
continue;
|
|
208
|
+
// Probe the version a few times — under heavy CPU load (parallel
|
|
209
|
+
// test pools, concurrent scanner runs) the underlying `execSync`
|
|
210
|
+
// subprocess can occasionally return before its `--version`
|
|
211
|
+
// output streams back, leaving us with a bare `'present'` even
|
|
212
|
+
// though the tool itself is fully functional. The per-process
|
|
213
|
+
// VERSION_CACHE then locks that empty result for the lifetime of
|
|
214
|
+
// the run, which is what we want for byte-stable toolchainHashes
|
|
215
|
+
// but is wrong when the empty result was a transient artifact.
|
|
216
|
+
// Three attempts absorb the hiccup without slowing the common
|
|
217
|
+
// path (first probe succeeds → exit immediately).
|
|
218
|
+
for (let attempt = 0; attempt < 3; attempt++) {
|
|
219
|
+
const status = (0, tool_registry_1.findTool)(def, cwd);
|
|
220
|
+
if (status.version)
|
|
221
|
+
return status.version;
|
|
222
|
+
}
|
|
223
|
+
return 'present';
|
|
224
|
+
}
|
|
225
|
+
return 'unknown';
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Test seam: clear the version cache between test runs so per-test
|
|
229
|
+
* fixtures don't leak resolutions into one another. Production
|
|
230
|
+
* callers never use this — the cache lives for the entire CLI
|
|
231
|
+
* invocation and dies with the process.
|
|
232
|
+
*/
|
|
233
|
+
function clearToolVersionCache() {
|
|
234
|
+
VERSION_CACHE.clear();
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* Run every analyzer once, dispatch through the producer registry,
|
|
238
|
+
* and return the assembled `CurrentScan`. Used by `createBaseline`
|
|
239
|
+
* to capture today's state and by `runGuardrailCheck` to gather the
|
|
240
|
+
* current side of the cross-run diff.
|
|
241
|
+
*
|
|
242
|
+
* Pure-orchestrator: each step has a single responsibility (analyze
|
|
243
|
+
* → produce entries → resolve envelope metadata).
|
|
244
|
+
*/
|
|
245
|
+
async function gatherCurrentScan(options) {
|
|
246
|
+
const cwd = path.resolve(options.cwd);
|
|
247
|
+
const analysisResult = await (0, cache_1.readOrBuildAnalysisResult)({
|
|
248
|
+
cwd,
|
|
249
|
+
build: (innerCwd) => (0, health_1.gatherAnalysisResultBody)(innerCwd, { verbose: !!options.verbose }),
|
|
250
|
+
});
|
|
251
|
+
const aggregate = analysisResult.capabilities.securityAggregate;
|
|
252
|
+
if (!aggregate) {
|
|
253
|
+
throw new Error('baseline scan: cached AnalysisResult missing securityAggregate ' +
|
|
254
|
+
'(expected to be populated by gatherAnalysisResultBody).');
|
|
255
|
+
}
|
|
256
|
+
const repoState = {
|
|
257
|
+
...readRepoState(cwd),
|
|
258
|
+
root: cwd,
|
|
259
|
+
};
|
|
260
|
+
// Salt resolves once; threaded into every producer that needs to
|
|
261
|
+
// compute HMACs. The mode lands on the baseline file so the
|
|
262
|
+
// matcher can re-derive the same salt at check time (or warn when
|
|
263
|
+
// it can't).
|
|
264
|
+
const { mode: saltMode, salt } = (0, salt_1.resolveSalt)(cwd);
|
|
265
|
+
// Build the producer context once. Every analyzer's gather runs
|
|
266
|
+
// here (or earlier inside readOrBuildAnalysisResult) so producers
|
|
267
|
+
// can be pure or near-pure consumers — adding a new producer
|
|
268
|
+
// means extending this context with one more input, never
|
|
269
|
+
// adding another producer-specific block in this function.
|
|
270
|
+
const testGapsReport = await (0, tests_1.analyzeTestGaps)(cwd, { verbose: !!options.verbose });
|
|
271
|
+
const hygieneMarkers = (0, gather_1.gatherHygieneMarkers)(cwd);
|
|
272
|
+
const gitleaksOutcome = (0, gitleaks_1.gatherGitleaksResult)(cwd);
|
|
273
|
+
const rawSecrets = gitleaksOutcome.kind === 'success' ? gitleaksOutcome.rawSecrets : [];
|
|
274
|
+
const producerCtx = {
|
|
275
|
+
cwd,
|
|
276
|
+
commitSha: repoState.commitSha,
|
|
277
|
+
salt,
|
|
278
|
+
analysisResult,
|
|
279
|
+
testGapsReport,
|
|
280
|
+
hygiene: hygieneMarkers,
|
|
281
|
+
rawSecrets,
|
|
282
|
+
};
|
|
283
|
+
// Dispatch through the canonical producer registry (CLAUDE.md
|
|
284
|
+
// Rule 10). Adding a new identity kind means registering a
|
|
285
|
+
// producer in `src/baseline/producers/index.ts` — never an edit
|
|
286
|
+
// here.
|
|
287
|
+
const findings = (0, producers_1.runProducers)(producerCtx, producers_1.PRODUCERS);
|
|
288
|
+
const toolNames = new Set();
|
|
289
|
+
if (aggregate.provenance.secrets.tool)
|
|
290
|
+
toolNames.add(aggregate.provenance.secrets.tool);
|
|
291
|
+
if (aggregate.provenance.codePatterns.tool)
|
|
292
|
+
toolNames.add(aggregate.provenance.codePatterns.tool);
|
|
293
|
+
if (aggregate.provenance.depVulns.tool)
|
|
294
|
+
toolNames.add(aggregate.provenance.depVulns.tool);
|
|
295
|
+
if (aggregate.provenance.tlsBypass.ran)
|
|
296
|
+
toolNames.add('tls-bypass-registry');
|
|
297
|
+
const tools = buildToolsMap([...toolNames].sort(), cwd);
|
|
298
|
+
const analysisMeta = {
|
|
299
|
+
...buildAnalysisMeta(cwd),
|
|
300
|
+
toolchainHash: hashContent(JSON.stringify(tools)),
|
|
301
|
+
};
|
|
302
|
+
return {
|
|
303
|
+
findings,
|
|
304
|
+
aggregate,
|
|
305
|
+
repoState,
|
|
306
|
+
saltMode,
|
|
307
|
+
tools,
|
|
308
|
+
analysisMeta,
|
|
309
|
+
producerCtx,
|
|
310
|
+
};
|
|
311
|
+
}
|
|
312
|
+
/**
|
|
313
|
+
* Run the baseline-create pipeline. Pure-orchestrator: gather the
|
|
314
|
+
* current scan via the shared step, then write it to disk under the
|
|
315
|
+
* given name.
|
|
316
|
+
*/
|
|
317
|
+
async function createBaseline(options) {
|
|
318
|
+
const cwd = path.resolve(options.cwd);
|
|
319
|
+
const name = options.name ?? baseline_file_1.DEFAULT_BASELINE_NAME;
|
|
320
|
+
const filePath = (0, baseline_file_1.pathForBaseline)(cwd, name);
|
|
321
|
+
if (!options.force && fs.existsSync(filePath)) {
|
|
322
|
+
throw new Error(`baseline already exists at ${filePath}. Pass force: true to overwrite, ` +
|
|
323
|
+
`or use a different --name to keep both.`);
|
|
324
|
+
}
|
|
325
|
+
const scan = await gatherCurrentScan({ cwd, verbose: options.verbose });
|
|
326
|
+
const file = {
|
|
327
|
+
schemaVersion: baseline_file_1.BASELINE_SCHEMA_VERSION,
|
|
328
|
+
name,
|
|
329
|
+
createdAt: new Date().toISOString(),
|
|
330
|
+
repo: scan.repoState,
|
|
331
|
+
analysis: scan.analysisMeta,
|
|
332
|
+
tools: scan.tools,
|
|
333
|
+
saltMode: scan.saltMode,
|
|
334
|
+
findings: scan.findings,
|
|
335
|
+
};
|
|
336
|
+
(0, baseline_file_1.writeBaselineFile)(filePath, file);
|
|
337
|
+
return { path: filePath, file };
|
|
338
|
+
}
|
|
339
|
+
//# sourceMappingURL=create.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create.js","sourceRoot":"","sources":["../../src/baseline/create.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Convert a stored `BaselineEntry` into the `LocatedIdentity` shape
|
|
3
|
+
* the git-aware matcher consumes. Pure function — no I/O.
|
|
4
|
+
*
|
|
5
|
+
* The matcher's location-pair pass keys off `(file, rule, line)` and
|
|
6
|
+
* its content-hash pass keys off `(rule, contentHash)`. Both passes
|
|
7
|
+
* pair on the rule string verbatim, so the converter MUST normalize
|
|
8
|
+
* the rule across tool boundaries — otherwise a finding reported by
|
|
9
|
+
* tool A in run 1 and tool B in run 2 would silently fail to pair
|
|
10
|
+
* (the identity hashes would agree via the canonical-rule mapping,
|
|
11
|
+
* but the matcher's earlier passes would have already missed them).
|
|
12
|
+
*
|
|
13
|
+
* For hygiene findings the marker acts as the rule discriminator —
|
|
14
|
+
* the identity hash partitions occurrences by marker text, so the
|
|
15
|
+
* location-pair pass must too. The canonical-rule registry doesn't
|
|
16
|
+
* apply to hygiene markers; the marker IS the canonical name.
|
|
17
|
+
*
|
|
18
|
+
* Kinds without file/line locators (dep-vuln, duplication,
|
|
19
|
+
* coverage-gap, license, test-gap, test-file-degradation, god-file,
|
|
20
|
+
* stale-file, large-file, secret-hmac) fall through to the matcher's
|
|
21
|
+
* multiset pass — they're paired by exact identity-hash equality,
|
|
22
|
+
* which the matcher already handles without any locator metadata.
|
|
23
|
+
*/
|
|
24
|
+
import type { LocatedIdentity } from './git-aware-match';
|
|
25
|
+
import type { BaselineEntry } from './types';
|
|
26
|
+
/**
|
|
27
|
+
* Build a `LocatedIdentity` from one stored entry. The id is the
|
|
28
|
+
* already-computed identity hash; locator fields are populated for
|
|
29
|
+
* the kinds the matcher's location-pair / content-hash passes can
|
|
30
|
+
* use.
|
|
31
|
+
*/
|
|
32
|
+
export declare function entryToLocated(entry: BaselineEntry): LocatedIdentity;
|
|
33
|
+
/** Convenience: map an array of entries through `entryToLocated`. */
|
|
34
|
+
export declare function entriesToLocated(entries: ReadonlyArray<BaselineEntry>): ReadonlyArray<LocatedIdentity>;
|
|
35
|
+
//# sourceMappingURL=entry-to-located.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"entry-to-located.d.ts","sourceRoot":"","sources":["../../src/baseline/entry-to-located.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAGH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAE7C;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,aAAa,GAAG,eAAe,CAgCpE;AAED,qEAAqE;AACrE,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,aAAa,CAAC,aAAa,CAAC,GACpC,aAAa,CAAC,eAAe,CAAC,CAEhC"}
|