@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,69 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Tests → baseline-entry producer.
|
|
4
|
+
*
|
|
5
|
+
* Two kinds today:
|
|
6
|
+
*
|
|
7
|
+
* - `test-gap` — non-test source files lacking a matching test, as
|
|
8
|
+
* reported by `analyzeTestGaps`. Each gap carries a risk tier
|
|
9
|
+
* (`critical | high | medium | low`); the tier is part of identity
|
|
10
|
+
* so a file moving between tiers (CRITICAL → HIGH, or vice
|
|
11
|
+
* versa) registers as a fresh finding rather than a silent
|
|
12
|
+
* persisted one — the right signal for "this file's testing
|
|
13
|
+
* situation got worse."
|
|
14
|
+
*
|
|
15
|
+
* - `test-file-degradation` — test files present but not actively
|
|
16
|
+
* exercising the system under test (commented-out, empty body,
|
|
17
|
+
* schema-only stubs). The degradation status is part of identity
|
|
18
|
+
* for the same reason: a file moving from `'empty'` to
|
|
19
|
+
* `'schema-only'` is a different signal.
|
|
20
|
+
*
|
|
21
|
+
* Producer is pure over its input; the orchestrator calls
|
|
22
|
+
* `analyzeTestGaps(cwd)` (which itself shares the canonical
|
|
23
|
+
* `AnalysisResult` cache so it doesn't re-gather what the security
|
|
24
|
+
* producer already triggered).
|
|
25
|
+
*/
|
|
26
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
27
|
+
exports.testGapsToBaselineEntries = testGapsToBaselineEntries;
|
|
28
|
+
const finding_identity_1 = require("../finding-identity");
|
|
29
|
+
/**
|
|
30
|
+
* Build `test-gap` + `test-file-degradation` entries from a
|
|
31
|
+
* `TestGapsReport`. Active test files (status: 'active') are not
|
|
32
|
+
* emitted — they're the healthy case. Source files WITH a matching
|
|
33
|
+
* test are not emitted — they're not a gap. Output preserves the
|
|
34
|
+
* report's iteration order so re-runs against the same scan are
|
|
35
|
+
* byte-stable.
|
|
36
|
+
*/
|
|
37
|
+
function testGapsToBaselineEntries(report) {
|
|
38
|
+
const out = [];
|
|
39
|
+
for (const gap of report.gaps) {
|
|
40
|
+
// Defensive: `gaps` already excludes files with a matching test,
|
|
41
|
+
// but guard anyway so a future report-shape change can't silently
|
|
42
|
+
// double-up.
|
|
43
|
+
if (gap.hasMatchingTest)
|
|
44
|
+
continue;
|
|
45
|
+
const input = {
|
|
46
|
+
kind: 'test-gap',
|
|
47
|
+
file: gap.path,
|
|
48
|
+
risk: gap.risk,
|
|
49
|
+
};
|
|
50
|
+
out.push({ id: (0, finding_identity_1.identityFor)(input), kind: 'test-gap', file: gap.path, risk: gap.risk });
|
|
51
|
+
}
|
|
52
|
+
for (const tf of report.testFiles) {
|
|
53
|
+
if (tf.status === 'active')
|
|
54
|
+
continue;
|
|
55
|
+
const input = {
|
|
56
|
+
kind: 'test-file-degradation',
|
|
57
|
+
file: tf.path,
|
|
58
|
+
status: tf.status,
|
|
59
|
+
};
|
|
60
|
+
out.push({
|
|
61
|
+
id: (0, finding_identity_1.identityFor)(input),
|
|
62
|
+
kind: 'test-file-degradation',
|
|
63
|
+
file: tf.path,
|
|
64
|
+
status: tf.status,
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
return out;
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=tests.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tests.js","sourceRoot":"","sources":["../../../src/baseline/producers/tests.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;;AAkBH,8DAgCC;AAhDD,0DAAkD;AAQlD;;;;;;;GAOG;AACH,SAAgB,yBAAyB,CAAC,MAAsB;IAC9D,MAAM,GAAG,GAAoB,EAAE,CAAC;IAEhC,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC;QAC9B,iEAAiE;QACjE,kEAAkE;QAClE,aAAa;QACb,IAAI,GAAG,CAAC,eAAe;YAAE,SAAS;QAClC,MAAM,KAAK,GAAyB;YAClC,IAAI,EAAE,UAAU;YAChB,IAAI,EAAE,GAAG,CAAC,IAAI;YACd,IAAI,EAAE,GAAG,CAAC,IAAI;SACf,CAAC;QACF,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,IAAA,8BAAW,EAAC,KAAK,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC;IACzF,CAAC;IAED,KAAK,MAAM,EAAE,IAAI,MAAM,CAAC,SAAS,EAAE,CAAC;QAClC,IAAI,EAAE,CAAC,MAAM,KAAK,QAAQ;YAAE,SAAS;QACrC,MAAM,KAAK,GAAqC;YAC9C,IAAI,EAAE,uBAAuB;YAC7B,IAAI,EAAE,EAAE,CAAC,IAAI;YACb,MAAM,EAAE,EAAE,CAAC,MAAM;SAClB,CAAC;QACF,GAAG,CAAC,IAAI,CAAC;YACP,EAAE,EAAE,IAAA,8BAAW,EAAC,KAAK,CAAC;YACtB,IAAI,EAAE,uBAAuB;YAC7B,IAAI,EAAE,EAAE,CAAC,IAAI;YACb,MAAM,EAAE,EAAE,CAAC,MAAM;SAClB,CAAC,CAAC;IACL,CAAC;IAED,OAAO,GAAG,CAAC;AACb,CAAC"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-repo salt resolution for secret HMAC identity.
|
|
3
|
+
*
|
|
4
|
+
* The secret-HMAC scheme uses a salt that's:
|
|
5
|
+
* 1. Consistent across `baseline create` (writes HMACs) and every
|
|
6
|
+
* subsequent `guardrail check` (reads them).
|
|
7
|
+
* 2. Not stored in git — a baseline-file leak should not enable
|
|
8
|
+
* secret recovery via rainbow tables.
|
|
9
|
+
* 3. Reachable from every consumer — single dev, multiple devs on
|
|
10
|
+
* one repo, CI, shallow clones, detached HEADs.
|
|
11
|
+
*
|
|
12
|
+
* A three-step waterfall satisfies all three:
|
|
13
|
+
*
|
|
14
|
+
* 1. `DXKIT_BASELINE_SALT` env var — opt-in override for teams
|
|
15
|
+
* who want stronger isolation than the deterministic default.
|
|
16
|
+
* 2. `.dxkit/salt` file — reserved for environments where env-vars
|
|
17
|
+
* are awkward (cron jobs, embedded runners). Gitignored by
|
|
18
|
+
* default.
|
|
19
|
+
* 3. Deterministic default — `HMAC("dxkit-baseline-salt-v1",
|
|
20
|
+
* initialCommitSha)`. Zero-setup; same across clones of the
|
|
21
|
+
* same repo; different across different repos; reachable in
|
|
22
|
+
* shallow clones (git always includes the root commit).
|
|
23
|
+
*
|
|
24
|
+
* Every baseline file records which mode produced it so the
|
|
25
|
+
* matcher can either match the same mode (HMAC compare works) or
|
|
26
|
+
* gracefully degrade to location-only matching when the salt is
|
|
27
|
+
* unrecoverable on the current run.
|
|
28
|
+
*/
|
|
29
|
+
/** Resolution path that produced the salt. Stamped on every baseline
|
|
30
|
+
* file so the guardrail check knows what the matcher needs. */
|
|
31
|
+
export type SaltMode = 'env-var' | 'file' | 'deterministic';
|
|
32
|
+
export interface ResolvedSalt {
|
|
33
|
+
readonly mode: SaltMode;
|
|
34
|
+
readonly salt: string;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Resolve the salt for a repo. Pure dispatch over the three-step
|
|
38
|
+
* waterfall; no I/O happens past the resolution step that succeeds.
|
|
39
|
+
*
|
|
40
|
+
* Throws when none of the three paths can produce a salt — typically
|
|
41
|
+
* a non-git checkout with no env var set. Callers should surface the
|
|
42
|
+
* message verbatim so users learn which mode to configure.
|
|
43
|
+
*/
|
|
44
|
+
export declare function resolveSalt(cwd: string): ResolvedSalt;
|
|
45
|
+
//# sourceMappingURL=salt.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"salt.d.ts","sourceRoot":"","sources":["../../src/baseline/salt.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAOH;gEACgE;AAChE,MAAM,MAAM,QAAQ,GAAG,SAAS,GAAG,MAAM,GAAG,eAAe,CAAC;AAE5D,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAQD;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,YAAY,CAiCrD"}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Per-repo salt resolution for secret HMAC identity.
|
|
4
|
+
*
|
|
5
|
+
* The secret-HMAC scheme uses a salt that's:
|
|
6
|
+
* 1. Consistent across `baseline create` (writes HMACs) and every
|
|
7
|
+
* subsequent `guardrail check` (reads them).
|
|
8
|
+
* 2. Not stored in git — a baseline-file leak should not enable
|
|
9
|
+
* secret recovery via rainbow tables.
|
|
10
|
+
* 3. Reachable from every consumer — single dev, multiple devs on
|
|
11
|
+
* one repo, CI, shallow clones, detached HEADs.
|
|
12
|
+
*
|
|
13
|
+
* A three-step waterfall satisfies all three:
|
|
14
|
+
*
|
|
15
|
+
* 1. `DXKIT_BASELINE_SALT` env var — opt-in override for teams
|
|
16
|
+
* who want stronger isolation than the deterministic default.
|
|
17
|
+
* 2. `.dxkit/salt` file — reserved for environments where env-vars
|
|
18
|
+
* are awkward (cron jobs, embedded runners). Gitignored by
|
|
19
|
+
* default.
|
|
20
|
+
* 3. Deterministic default — `HMAC("dxkit-baseline-salt-v1",
|
|
21
|
+
* initialCommitSha)`. Zero-setup; same across clones of the
|
|
22
|
+
* same repo; different across different repos; reachable in
|
|
23
|
+
* shallow clones (git always includes the root commit).
|
|
24
|
+
*
|
|
25
|
+
* Every baseline file records which mode produced it so the
|
|
26
|
+
* matcher can either match the same mode (HMAC compare works) or
|
|
27
|
+
* gracefully degrade to location-only matching when the salt is
|
|
28
|
+
* unrecoverable on the current run.
|
|
29
|
+
*/
|
|
30
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
31
|
+
if (k2 === undefined) k2 = k;
|
|
32
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
33
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
34
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
35
|
+
}
|
|
36
|
+
Object.defineProperty(o, k2, desc);
|
|
37
|
+
}) : (function(o, m, k, k2) {
|
|
38
|
+
if (k2 === undefined) k2 = k;
|
|
39
|
+
o[k2] = m[k];
|
|
40
|
+
}));
|
|
41
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
42
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
43
|
+
}) : function(o, v) {
|
|
44
|
+
o["default"] = v;
|
|
45
|
+
});
|
|
46
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
47
|
+
var ownKeys = function(o) {
|
|
48
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
49
|
+
var ar = [];
|
|
50
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
51
|
+
return ar;
|
|
52
|
+
};
|
|
53
|
+
return ownKeys(o);
|
|
54
|
+
};
|
|
55
|
+
return function (mod) {
|
|
56
|
+
if (mod && mod.__esModule) return mod;
|
|
57
|
+
var result = {};
|
|
58
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
59
|
+
__setModuleDefault(result, mod);
|
|
60
|
+
return result;
|
|
61
|
+
};
|
|
62
|
+
})();
|
|
63
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
64
|
+
exports.resolveSalt = resolveSalt;
|
|
65
|
+
const child_process_1 = require("child_process");
|
|
66
|
+
const crypto_1 = require("crypto");
|
|
67
|
+
const fs = __importStar(require("fs"));
|
|
68
|
+
const path = __importStar(require("path"));
|
|
69
|
+
/** Domain separator for the deterministic default. Bumping the
|
|
70
|
+
* suffix would invalidate every existing deterministic-mode
|
|
71
|
+
* baseline (consumers would compute different salts for the same
|
|
72
|
+
* commit). Treat it as a permanent identifier. */
|
|
73
|
+
const DETERMINISTIC_DOMAIN = 'dxkit-baseline-salt-v1';
|
|
74
|
+
/**
|
|
75
|
+
* Resolve the salt for a repo. Pure dispatch over the three-step
|
|
76
|
+
* waterfall; no I/O happens past the resolution step that succeeds.
|
|
77
|
+
*
|
|
78
|
+
* Throws when none of the three paths can produce a salt — typically
|
|
79
|
+
* a non-git checkout with no env var set. Callers should surface the
|
|
80
|
+
* message verbatim so users learn which mode to configure.
|
|
81
|
+
*/
|
|
82
|
+
function resolveSalt(cwd) {
|
|
83
|
+
const envSalt = process.env.DXKIT_BASELINE_SALT;
|
|
84
|
+
if (envSalt && envSalt.length > 0) {
|
|
85
|
+
return { mode: 'env-var', salt: envSalt };
|
|
86
|
+
}
|
|
87
|
+
const filePath = path.join(cwd, '.dxkit', 'salt');
|
|
88
|
+
if (fs.existsSync(filePath)) {
|
|
89
|
+
const fileSalt = fs.readFileSync(filePath, 'utf8').trim();
|
|
90
|
+
if (fileSalt.length > 0) {
|
|
91
|
+
return { mode: 'file', salt: fileSalt };
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
try {
|
|
95
|
+
const sha = (0, child_process_1.execFileSync)('git', ['rev-list', '--max-parents=0', 'HEAD'], {
|
|
96
|
+
cwd,
|
|
97
|
+
encoding: 'utf8',
|
|
98
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
99
|
+
})
|
|
100
|
+
.trim()
|
|
101
|
+
.split('\n')[0];
|
|
102
|
+
if (!sha) {
|
|
103
|
+
throw new Error('git rev-list returned empty output');
|
|
104
|
+
}
|
|
105
|
+
const salt = (0, crypto_1.createHmac)('sha256', DETERMINISTIC_DOMAIN).update(sha).digest('hex');
|
|
106
|
+
return { mode: 'deterministic', salt };
|
|
107
|
+
}
|
|
108
|
+
catch {
|
|
109
|
+
throw new Error('Cannot derive a baseline salt: not a git repository (or no root commit reachable). ' +
|
|
110
|
+
'Set DXKIT_BASELINE_SALT or initialize a git repo before running baseline commands.');
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
//# sourceMappingURL=salt.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"salt.js","sourceRoot":"","sources":["../../src/baseline/salt.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8BH,kCAiCC;AA7DD,iDAA6C;AAC7C,mCAAoC;AACpC,uCAAyB;AACzB,2CAA6B;AAW7B;;;mDAGmD;AACnD,MAAM,oBAAoB,GAAG,wBAAwB,CAAC;AAEtD;;;;;;;GAOG;AACH,SAAgB,WAAW,CAAC,GAAW;IACrC,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC;IAChD,IAAI,OAAO,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAClC,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;IAC5C,CAAC;IAED,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;IAClD,IAAI,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC5B,MAAM,QAAQ,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC;QAC1D,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACxB,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;QAC1C,CAAC;IACH,CAAC;IAED,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAA,4BAAY,EAAC,KAAK,EAAE,CAAC,UAAU,EAAE,iBAAiB,EAAE,MAAM,CAAC,EAAE;YACvE,GAAG;YACH,QAAQ,EAAE,MAAM;YAChB,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC;SAClC,CAAC;aACC,IAAI,EAAE;aACN,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;QAClB,IAAI,CAAC,GAAG,EAAE,CAAC;YACT,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;QACxD,CAAC;QACD,MAAM,IAAI,GAAG,IAAA,mBAAU,EAAC,QAAQ,EAAE,oBAAoB,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAClF,OAAO,EAAE,IAAI,EAAE,eAAe,EAAE,IAAI,EAAE,CAAC;IACzC,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,KAAK,CACb,qFAAqF;YACnF,oFAAoF,CACvF,CAAC;IACJ,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `vyuh-dxkit baseline show` — pretty-print + filter the on-disk
|
|
3
|
+
* baseline file.
|
|
4
|
+
*
|
|
5
|
+
* Three render modes share one loaded `BaselineFile`:
|
|
6
|
+
*
|
|
7
|
+
* - **summary** (`baseline show` or `baseline show --summary`) —
|
|
8
|
+
* header (commit, branch, creation time, schema, dxkit version,
|
|
9
|
+
* salt mode) plus per-kind counts. The fast scan a developer
|
|
10
|
+
* reaches for to answer "what's the shape of this baseline?"
|
|
11
|
+
*
|
|
12
|
+
* - **kind-filtered** (`baseline show --kind <X>`) — every entry
|
|
13
|
+
* matching the named kind, with locator + identity prefix. The
|
|
14
|
+
* drill-down for "show me every dep-vuln in this baseline."
|
|
15
|
+
*
|
|
16
|
+
* - **JSON** (`baseline show --json [--kind <X>]`) — schema-banner-
|
|
17
|
+
* wrapped payload. Filter applies if specified. Designed for
|
|
18
|
+
* agents + CI consumers.
|
|
19
|
+
*
|
|
20
|
+
* Pure module — no I/O. The CLI layer loads the file via
|
|
21
|
+
* `readBaselineFile` and routes the result through these renderers.
|
|
22
|
+
*/
|
|
23
|
+
import type { BaselineFile } from './baseline-file';
|
|
24
|
+
import type { BaselineEntry } from './types';
|
|
25
|
+
/**
|
|
26
|
+
* JSON schema banner for the `baseline show --json` envelope.
|
|
27
|
+
* Distinct from the raw `schemaVersion: 'dxkit-baseline/v1'` field
|
|
28
|
+
* on the underlying file: this envelope is a *rendered view* and
|
|
29
|
+
* may carry a filter discriminator the raw file doesn't.
|
|
30
|
+
*/
|
|
31
|
+
export declare const BASELINE_SHOW_SCHEMA: "dxkit.baseline-show.v1";
|
|
32
|
+
/**
|
|
33
|
+
* The kinds a user can filter on. Mirror of the `BaselineEntry`
|
|
34
|
+
* discriminant union — keeps the CLI's flag-validation aligned with
|
|
35
|
+
* the storage shape.
|
|
36
|
+
*/
|
|
37
|
+
export declare const FILTER_KINDS: ReadonlyArray<BaselineEntry['kind']>;
|
|
38
|
+
/** Result of parsing the user's `--kind` value. Returns `null` for
|
|
39
|
+
* unknown values so the CLI surfaces a helpful error including the
|
|
40
|
+
* full list of accepted kinds. */
|
|
41
|
+
export declare function parseKindFilter(raw: string): BaselineEntry['kind'] | null;
|
|
42
|
+
/**
|
|
43
|
+
* Render the summary view: header lines + per-kind counts table.
|
|
44
|
+
* Always reports every kind that appears at least once; absent kinds
|
|
45
|
+
* are omitted to keep the table compact.
|
|
46
|
+
*/
|
|
47
|
+
export declare function renderSummary(file: BaselineFile): string;
|
|
48
|
+
/**
|
|
49
|
+
* Render every entry matching `kind`. Each line carries the
|
|
50
|
+
* identity prefix (first 12 chars — enough to distinguish entries
|
|
51
|
+
* by eye without bloating the line), the locator info, and any
|
|
52
|
+
* kind-specific discriminator.
|
|
53
|
+
*
|
|
54
|
+
* Returns the header + a notice when no entries match, rather than
|
|
55
|
+
* an empty string, so the user always sees confirmation that the
|
|
56
|
+
* filter ran.
|
|
57
|
+
*/
|
|
58
|
+
export declare function renderKind(file: BaselineFile, kind: BaselineEntry['kind']): string;
|
|
59
|
+
/**
|
|
60
|
+
* Render the JSON envelope. Wraps the underlying file (full or
|
|
61
|
+
* kind-filtered) in a top-level `schema` banner so consumers can
|
|
62
|
+
* version-gate before reading. Filter discriminator is included
|
|
63
|
+
* when present so consumers know whether they're seeing the full
|
|
64
|
+
* findings list.
|
|
65
|
+
*/
|
|
66
|
+
export declare function renderJson(file: BaselineFile, options?: {
|
|
67
|
+
readonly kind?: BaselineEntry['kind'];
|
|
68
|
+
}): {
|
|
69
|
+
readonly schema: typeof BASELINE_SHOW_SCHEMA;
|
|
70
|
+
readonly filter: {
|
|
71
|
+
readonly kind: BaselineEntry['kind'];
|
|
72
|
+
} | null;
|
|
73
|
+
readonly baseline: BaselineFile;
|
|
74
|
+
readonly summary: {
|
|
75
|
+
readonly total: number;
|
|
76
|
+
readonly byKind: Readonly<Partial<Record<BaselineEntry['kind'], number>>>;
|
|
77
|
+
};
|
|
78
|
+
};
|
|
79
|
+
//# sourceMappingURL=show.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"show.d.ts","sourceRoot":"","sources":["../../src/baseline/show.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAE7C;;;;;GAKG;AACH,eAAO,MAAM,oBAAoB,EAAG,wBAAiC,CAAC;AAEtE;;;;GAIG;AACH,eAAO,MAAM,YAAY,EAAE,aAAa,CAAC,aAAa,CAAC,MAAM,CAAC,CAe5D,CAAC;AAEH;;mCAEmC;AACnC,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,aAAa,CAAC,MAAM,CAAC,GAAG,IAAI,CAIzE;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,YAAY,GAAG,MAAM,CA6BxD;AAED;;;;;;;;;GASG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,aAAa,CAAC,MAAM,CAAC,GAAG,MAAM,CAkBlF;AAED;;;;;;GAMG;AACH,wBAAgB,UAAU,CACxB,IAAI,EAAE,YAAY,EAClB,OAAO,GAAE;IAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAA;CAAO,GACtD;IACD,QAAQ,CAAC,MAAM,EAAE,OAAO,oBAAoB,CAAC;IAC7C,QAAQ,CAAC,MAAM,EAAE;QAAE,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC,MAAM,CAAC,CAAA;KAAE,GAAG,IAAI,CAAC;IACjE,QAAQ,CAAC,QAAQ,EAAE,YAAY,CAAC;IAChC,QAAQ,CAAC,OAAO,EAAE;QAChB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;QACvB,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC;KAC3E,CAAC;CACH,CAcA"}
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* `vyuh-dxkit baseline show` — pretty-print + filter the on-disk
|
|
4
|
+
* baseline file.
|
|
5
|
+
*
|
|
6
|
+
* Three render modes share one loaded `BaselineFile`:
|
|
7
|
+
*
|
|
8
|
+
* - **summary** (`baseline show` or `baseline show --summary`) —
|
|
9
|
+
* header (commit, branch, creation time, schema, dxkit version,
|
|
10
|
+
* salt mode) plus per-kind counts. The fast scan a developer
|
|
11
|
+
* reaches for to answer "what's the shape of this baseline?"
|
|
12
|
+
*
|
|
13
|
+
* - **kind-filtered** (`baseline show --kind <X>`) — every entry
|
|
14
|
+
* matching the named kind, with locator + identity prefix. The
|
|
15
|
+
* drill-down for "show me every dep-vuln in this baseline."
|
|
16
|
+
*
|
|
17
|
+
* - **JSON** (`baseline show --json [--kind <X>]`) — schema-banner-
|
|
18
|
+
* wrapped payload. Filter applies if specified. Designed for
|
|
19
|
+
* agents + CI consumers.
|
|
20
|
+
*
|
|
21
|
+
* Pure module — no I/O. The CLI layer loads the file via
|
|
22
|
+
* `readBaselineFile` and routes the result through these renderers.
|
|
23
|
+
*/
|
|
24
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
25
|
+
if (k2 === undefined) k2 = k;
|
|
26
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
27
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
28
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
29
|
+
}
|
|
30
|
+
Object.defineProperty(o, k2, desc);
|
|
31
|
+
}) : (function(o, m, k, k2) {
|
|
32
|
+
if (k2 === undefined) k2 = k;
|
|
33
|
+
o[k2] = m[k];
|
|
34
|
+
}));
|
|
35
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
36
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
37
|
+
}) : function(o, v) {
|
|
38
|
+
o["default"] = v;
|
|
39
|
+
});
|
|
40
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
41
|
+
var ownKeys = function(o) {
|
|
42
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
43
|
+
var ar = [];
|
|
44
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
45
|
+
return ar;
|
|
46
|
+
};
|
|
47
|
+
return ownKeys(o);
|
|
48
|
+
};
|
|
49
|
+
return function (mod) {
|
|
50
|
+
if (mod && mod.__esModule) return mod;
|
|
51
|
+
var result = {};
|
|
52
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
53
|
+
__setModuleDefault(result, mod);
|
|
54
|
+
return result;
|
|
55
|
+
};
|
|
56
|
+
})();
|
|
57
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
58
|
+
exports.FILTER_KINDS = exports.BASELINE_SHOW_SCHEMA = void 0;
|
|
59
|
+
exports.parseKindFilter = parseKindFilter;
|
|
60
|
+
exports.renderSummary = renderSummary;
|
|
61
|
+
exports.renderKind = renderKind;
|
|
62
|
+
exports.renderJson = renderJson;
|
|
63
|
+
const logger = __importStar(require("../logger"));
|
|
64
|
+
/**
|
|
65
|
+
* JSON schema banner for the `baseline show --json` envelope.
|
|
66
|
+
* Distinct from the raw `schemaVersion: 'dxkit-baseline/v1'` field
|
|
67
|
+
* on the underlying file: this envelope is a *rendered view* and
|
|
68
|
+
* may carry a filter discriminator the raw file doesn't.
|
|
69
|
+
*/
|
|
70
|
+
exports.BASELINE_SHOW_SCHEMA = 'dxkit.baseline-show.v1';
|
|
71
|
+
/**
|
|
72
|
+
* The kinds a user can filter on. Mirror of the `BaselineEntry`
|
|
73
|
+
* discriminant union — keeps the CLI's flag-validation aligned with
|
|
74
|
+
* the storage shape.
|
|
75
|
+
*/
|
|
76
|
+
exports.FILTER_KINDS = Object.freeze([
|
|
77
|
+
'secret',
|
|
78
|
+
'code',
|
|
79
|
+
'config',
|
|
80
|
+
'dep-vuln',
|
|
81
|
+
'duplication',
|
|
82
|
+
'coverage-gap',
|
|
83
|
+
'test-gap',
|
|
84
|
+
'hygiene',
|
|
85
|
+
'license',
|
|
86
|
+
'test-file-degradation',
|
|
87
|
+
'god-file',
|
|
88
|
+
'stale-file',
|
|
89
|
+
'large-file',
|
|
90
|
+
'secret-hmac',
|
|
91
|
+
]);
|
|
92
|
+
/** Result of parsing the user's `--kind` value. Returns `null` for
|
|
93
|
+
* unknown values so the CLI surfaces a helpful error including the
|
|
94
|
+
* full list of accepted kinds. */
|
|
95
|
+
function parseKindFilter(raw) {
|
|
96
|
+
return exports.FILTER_KINDS.includes(raw)
|
|
97
|
+
? raw
|
|
98
|
+
: null;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Render the summary view: header lines + per-kind counts table.
|
|
102
|
+
* Always reports every kind that appears at least once; absent kinds
|
|
103
|
+
* are omitted to keep the table compact.
|
|
104
|
+
*/
|
|
105
|
+
function renderSummary(file) {
|
|
106
|
+
const lines = [];
|
|
107
|
+
lines.push(logger.bold(`Baseline '${file.name}'`));
|
|
108
|
+
lines.push('');
|
|
109
|
+
lines.push(` Commit: ${shortSha(file.repo.commitSha)} (${file.repo.branch || 'detached'})`);
|
|
110
|
+
lines.push(` Captured: ${file.createdAt}`);
|
|
111
|
+
lines.push(` Schema: ${file.schemaVersion}`);
|
|
112
|
+
lines.push(` dxkit: ${file.analysis.dxkitVersion}`);
|
|
113
|
+
lines.push(` Salt: ${file.saltMode}`);
|
|
114
|
+
const toolNames = Object.keys(file.tools).sort();
|
|
115
|
+
if (toolNames.length > 0) {
|
|
116
|
+
lines.push(` Tools: ${toolNames.map((t) => `${t}@${file.tools[t]}`).join(', ')}`);
|
|
117
|
+
}
|
|
118
|
+
lines.push('');
|
|
119
|
+
const counts = countByKind(file.findings);
|
|
120
|
+
const total = file.findings.length;
|
|
121
|
+
lines.push(logger.bold(`Findings: ${total} total`));
|
|
122
|
+
if (total > 0) {
|
|
123
|
+
const entries = Object.entries(counts);
|
|
124
|
+
entries.sort((a, b) => b[1] - a[1]);
|
|
125
|
+
const widestKind = Math.max(...entries.map(([k]) => k.length));
|
|
126
|
+
for (const [kind, count] of entries) {
|
|
127
|
+
lines.push(` ${kind.padEnd(widestKind)} ${count.toString().padStart(5)}`);
|
|
128
|
+
}
|
|
129
|
+
lines.push('');
|
|
130
|
+
lines.push(` Filter to one kind: vyuh-dxkit baseline show --kind <kind>`);
|
|
131
|
+
}
|
|
132
|
+
return lines.join('\n');
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Render every entry matching `kind`. Each line carries the
|
|
136
|
+
* identity prefix (first 12 chars — enough to distinguish entries
|
|
137
|
+
* by eye without bloating the line), the locator info, and any
|
|
138
|
+
* kind-specific discriminator.
|
|
139
|
+
*
|
|
140
|
+
* Returns the header + a notice when no entries match, rather than
|
|
141
|
+
* an empty string, so the user always sees confirmation that the
|
|
142
|
+
* filter ran.
|
|
143
|
+
*/
|
|
144
|
+
function renderKind(file, kind) {
|
|
145
|
+
const lines = [];
|
|
146
|
+
const matching = file.findings.filter((e) => e.kind === kind);
|
|
147
|
+
lines.push(logger.bold(`Baseline '${file.name}' — kind: ${kind}`));
|
|
148
|
+
lines.push(` Commit: ${shortSha(file.repo.commitSha)}`);
|
|
149
|
+
lines.push('');
|
|
150
|
+
if (matching.length === 0) {
|
|
151
|
+
lines.push(` (no entries of kind '${kind}')`);
|
|
152
|
+
return lines.join('\n');
|
|
153
|
+
}
|
|
154
|
+
lines.push(logger.bold(`${matching.length} ${kind} ${matching.length === 1 ? 'entry' : 'entries'}`));
|
|
155
|
+
lines.push('');
|
|
156
|
+
for (const entry of matching) {
|
|
157
|
+
lines.push(` ${entry.id.slice(0, 12)} ${describeEntry(entry)}`);
|
|
158
|
+
}
|
|
159
|
+
return lines.join('\n');
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Render the JSON envelope. Wraps the underlying file (full or
|
|
163
|
+
* kind-filtered) in a top-level `schema` banner so consumers can
|
|
164
|
+
* version-gate before reading. Filter discriminator is included
|
|
165
|
+
* when present so consumers know whether they're seeing the full
|
|
166
|
+
* findings list.
|
|
167
|
+
*/
|
|
168
|
+
function renderJson(file, options = {}) {
|
|
169
|
+
const findings = options.kind
|
|
170
|
+
? file.findings.filter((e) => e.kind === options.kind)
|
|
171
|
+
: file.findings;
|
|
172
|
+
const view = { ...file, findings };
|
|
173
|
+
return {
|
|
174
|
+
schema: exports.BASELINE_SHOW_SCHEMA,
|
|
175
|
+
filter: options.kind ? { kind: options.kind } : null,
|
|
176
|
+
baseline: view,
|
|
177
|
+
summary: {
|
|
178
|
+
total: findings.length,
|
|
179
|
+
byKind: countByKind(findings),
|
|
180
|
+
},
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
/** Per-kind occurrence count. Mirror of the matcher's multiset
|
|
184
|
+
* semantics — duplicate identities count separately. */
|
|
185
|
+
function countByKind(entries) {
|
|
186
|
+
const out = {};
|
|
187
|
+
for (const e of entries)
|
|
188
|
+
out[e.kind] = (out[e.kind] ?? 0) + 1;
|
|
189
|
+
return out;
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* One-line locator + discriminator string for a baseline entry.
|
|
193
|
+
* Kind-specific fields drive the format so a reader sees the
|
|
194
|
+
* meaningful axis (file:line for source-anchored kinds,
|
|
195
|
+
* package@version+advisory for dep-vulns, etc.).
|
|
196
|
+
*/
|
|
197
|
+
function describeEntry(entry) {
|
|
198
|
+
switch (entry.kind) {
|
|
199
|
+
case 'secret':
|
|
200
|
+
case 'code':
|
|
201
|
+
case 'config':
|
|
202
|
+
return `${entry.file}:${entry.line} [${entry.tool}/${entry.rule}]`;
|
|
203
|
+
case 'hygiene':
|
|
204
|
+
return `${entry.file}:${entry.line} [${entry.marker}]`;
|
|
205
|
+
case 'dep-vuln':
|
|
206
|
+
return `${entry.package}@${entry.installedVersion ?? '?'} [${entry.advisoryId}]`;
|
|
207
|
+
case 'duplication':
|
|
208
|
+
return `${entry.fileA}:${entry.startLineA} <-> ${entry.fileB}:${entry.startLineB} (${entry.lines} lines)`;
|
|
209
|
+
case 'coverage-gap':
|
|
210
|
+
return entry.symbol
|
|
211
|
+
? `${entry.file}:${entry.symbol}`
|
|
212
|
+
: `${entry.file}:${entry.lineRange?.[0] ?? '?'}-${entry.lineRange?.[1] ?? '?'}`;
|
|
213
|
+
case 'test-gap':
|
|
214
|
+
return `${entry.file} [risk: ${entry.risk}]`;
|
|
215
|
+
case 'license':
|
|
216
|
+
return `${entry.package}@${entry.version} [${entry.licenseType}]`;
|
|
217
|
+
case 'test-file-degradation':
|
|
218
|
+
return `${entry.file} [${entry.status}]`;
|
|
219
|
+
case 'god-file':
|
|
220
|
+
case 'large-file':
|
|
221
|
+
return entry.file;
|
|
222
|
+
case 'stale-file':
|
|
223
|
+
return `${entry.file} [.${entry.suffix}]`;
|
|
224
|
+
case 'secret-hmac':
|
|
225
|
+
return `[${entry.tool}/${entry.rule}] hmac:${entry.hmac.slice(0, 12)}`;
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
function shortSha(sha) {
|
|
229
|
+
if (!sha)
|
|
230
|
+
return '(no-commit)';
|
|
231
|
+
return sha.slice(0, 8);
|
|
232
|
+
}
|
|
233
|
+
//# sourceMappingURL=show.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"show.js","sourceRoot":"","sources":["../../src/baseline/show.ts"],"names":[],"mappings":"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"}
|