@vyuhlabs/dxkit 2.0.0 → 2.1.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.
Files changed (147) hide show
  1. package/CHANGELOG.md +153 -0
  2. package/README.md +21 -15
  3. package/dist/analyzers/bom/detailed.d.ts +26 -0
  4. package/dist/analyzers/bom/detailed.d.ts.map +1 -0
  5. package/dist/analyzers/bom/detailed.js +227 -0
  6. package/dist/analyzers/bom/detailed.js.map +1 -0
  7. package/dist/analyzers/bom/gather.d.ts +52 -0
  8. package/dist/analyzers/bom/gather.d.ts.map +1 -0
  9. package/dist/analyzers/bom/gather.js +183 -0
  10. package/dist/analyzers/bom/gather.js.map +1 -0
  11. package/dist/analyzers/bom/index.d.ts +23 -0
  12. package/dist/analyzers/bom/index.d.ts.map +1 -0
  13. package/dist/analyzers/bom/index.js +183 -0
  14. package/dist/analyzers/bom/index.js.map +1 -0
  15. package/dist/analyzers/bom/types.d.ts +71 -0
  16. package/dist/analyzers/bom/types.d.ts.map +1 -0
  17. package/dist/analyzers/bom/types.js +3 -0
  18. package/dist/analyzers/bom/types.js.map +1 -0
  19. package/dist/analyzers/health.js +20 -9
  20. package/dist/analyzers/health.js.map +1 -1
  21. package/dist/analyzers/licenses/detailed.d.ts +30 -0
  22. package/dist/analyzers/licenses/detailed.d.ts.map +1 -0
  23. package/dist/analyzers/licenses/detailed.js +194 -0
  24. package/dist/analyzers/licenses/detailed.js.map +1 -0
  25. package/dist/analyzers/licenses/gather.d.ts +15 -0
  26. package/dist/analyzers/licenses/gather.d.ts.map +1 -0
  27. package/dist/analyzers/licenses/gather.js +24 -0
  28. package/dist/analyzers/licenses/gather.js.map +1 -0
  29. package/dist/analyzers/licenses/index.d.ts +21 -0
  30. package/dist/analyzers/licenses/index.d.ts.map +1 -0
  31. package/dist/analyzers/licenses/index.js +146 -0
  32. package/dist/analyzers/licenses/index.js.map +1 -0
  33. package/dist/analyzers/licenses/types.d.ts +30 -0
  34. package/dist/analyzers/licenses/types.d.ts.map +1 -0
  35. package/dist/analyzers/licenses/types.js +13 -0
  36. package/dist/analyzers/licenses/types.js.map +1 -0
  37. package/dist/analyzers/security/detailed.d.ts +0 -3
  38. package/dist/analyzers/security/detailed.d.ts.map +1 -1
  39. package/dist/analyzers/security/detailed.js +37 -6
  40. package/dist/analyzers/security/detailed.js.map +1 -1
  41. package/dist/analyzers/security/gather.d.ts.map +1 -1
  42. package/dist/analyzers/security/gather.js +2 -0
  43. package/dist/analyzers/security/gather.js.map +1 -1
  44. package/dist/analyzers/security/index.d.ts.map +1 -1
  45. package/dist/analyzers/security/index.js +53 -14
  46. package/dist/analyzers/security/index.js.map +1 -1
  47. package/dist/analyzers/security/types.d.ts +5 -0
  48. package/dist/analyzers/security/types.d.ts.map +1 -1
  49. package/dist/analyzers/security/types.js +0 -3
  50. package/dist/analyzers/security/types.js.map +1 -1
  51. package/dist/analyzers/tools/osv.d.ts +49 -5
  52. package/dist/analyzers/tools/osv.d.ts.map +1 -1
  53. package/dist/analyzers/tools/osv.js +99 -17
  54. package/dist/analyzers/tools/osv.js.map +1 -1
  55. package/dist/analyzers/tools/runner.d.ts +11 -0
  56. package/dist/analyzers/tools/runner.d.ts.map +1 -1
  57. package/dist/analyzers/tools/runner.js +54 -0
  58. package/dist/analyzers/tools/runner.js.map +1 -1
  59. package/dist/analyzers/tools/tool-registry.d.ts.map +1 -1
  60. package/dist/analyzers/tools/tool-registry.js +77 -0
  61. package/dist/analyzers/tools/tool-registry.js.map +1 -1
  62. package/dist/analyzers/xlsx/bom.d.ts +27 -0
  63. package/dist/analyzers/xlsx/bom.d.ts.map +1 -0
  64. package/dist/analyzers/xlsx/bom.js +131 -0
  65. package/dist/analyzers/xlsx/bom.js.map +1 -0
  66. package/dist/analyzers/xlsx/index.d.ts +27 -0
  67. package/dist/analyzers/xlsx/index.d.ts.map +1 -0
  68. package/dist/analyzers/xlsx/index.js +92 -0
  69. package/dist/analyzers/xlsx/index.js.map +1 -0
  70. package/dist/analyzers/xlsx/licenses.d.ts +40 -0
  71. package/dist/analyzers/xlsx/licenses.d.ts.map +1 -0
  72. package/dist/analyzers/xlsx/licenses.js +140 -0
  73. package/dist/analyzers/xlsx/licenses.js.map +1 -0
  74. package/dist/cli.d.ts.map +1 -1
  75. package/dist/cli.js +178 -1
  76. package/dist/cli.js.map +1 -1
  77. package/dist/languages/capabilities/descriptors.d.ts +4 -1
  78. package/dist/languages/capabilities/descriptors.d.ts.map +1 -1
  79. package/dist/languages/capabilities/descriptors.js +20 -1
  80. package/dist/languages/capabilities/descriptors.js.map +1 -1
  81. package/dist/languages/capabilities/types.d.ts +59 -3
  82. package/dist/languages/capabilities/types.d.ts.map +1 -1
  83. package/dist/languages/csharp.d.ts +13 -0
  84. package/dist/languages/csharp.d.ts.map +1 -1
  85. package/dist/languages/csharp.js +228 -33
  86. package/dist/languages/csharp.js.map +1 -1
  87. package/dist/languages/go.d.ts.map +1 -1
  88. package/dist/languages/go.js +211 -26
  89. package/dist/languages/go.js.map +1 -1
  90. package/dist/languages/python.d.ts.map +1 -1
  91. package/dist/languages/python.js +187 -11
  92. package/dist/languages/python.js.map +1 -1
  93. package/dist/languages/rust.d.ts +13 -0
  94. package/dist/languages/rust.d.ts.map +1 -1
  95. package/dist/languages/rust.js +195 -29
  96. package/dist/languages/rust.js.map +1 -1
  97. package/dist/languages/types.d.ts +2 -1
  98. package/dist/languages/types.d.ts.map +1 -1
  99. package/dist/languages/typescript.d.ts.map +1 -1
  100. package/dist/languages/typescript.js +252 -1
  101. package/dist/languages/typescript.js.map +1 -1
  102. package/package.json +7 -2
  103. package/dist/agents/extract.d.ts +0 -25
  104. package/dist/agents/extract.d.ts.map +0 -1
  105. package/dist/agents/extract.js +0 -186
  106. package/dist/agents/extract.js.map +0 -1
  107. package/dist/agents/schemas.d.ts +0 -106
  108. package/dist/agents/schemas.d.ts.map +0 -1
  109. package/dist/agents/schemas.js +0 -86
  110. package/dist/agents/schemas.js.map +0 -1
  111. package/dist/agents/session.d.ts +0 -28
  112. package/dist/agents/session.d.ts.map +0 -1
  113. package/dist/agents/session.js +0 -223
  114. package/dist/agents/session.js.map +0 -1
  115. package/dist/analyzers/index.d.ts +0 -3
  116. package/dist/analyzers/index.d.ts.map +0 -1
  117. package/dist/analyzers/index.js +0 -6
  118. package/dist/analyzers/index.js.map +0 -1
  119. package/dist/analyzers/security/report.d.ts +0 -6
  120. package/dist/analyzers/security/report.d.ts.map +0 -1
  121. package/dist/analyzers/security/report.js +0 -118
  122. package/dist/analyzers/security/report.js.map +0 -1
  123. package/dist/analyzers/tools/dotnet.d.ts +0 -8
  124. package/dist/analyzers/tools/dotnet.d.ts.map +0 -1
  125. package/dist/analyzers/tools/dotnet.js +0 -81
  126. package/dist/analyzers/tools/dotnet.js.map +0 -1
  127. package/dist/analyzers/tools/gather-cache.d.ts +0 -16
  128. package/dist/analyzers/tools/gather-cache.d.ts.map +0 -1
  129. package/dist/analyzers/tools/gather-cache.js +0 -126
  130. package/dist/analyzers/tools/gather-cache.js.map +0 -1
  131. package/dist/analyzers/tools/go.d.ts +0 -8
  132. package/dist/analyzers/tools/go.d.ts.map +0 -1
  133. package/dist/analyzers/tools/go.js +0 -84
  134. package/dist/analyzers/tools/go.js.map +0 -1
  135. package/dist/analyzers/tools/node.d.ts +0 -8
  136. package/dist/analyzers/tools/node.d.ts.map +0 -1
  137. package/dist/analyzers/tools/node.js +0 -160
  138. package/dist/analyzers/tools/node.js.map +0 -1
  139. package/dist/analyzers/tools/python.d.ts +0 -8
  140. package/dist/analyzers/tools/python.d.ts.map +0 -1
  141. package/dist/analyzers/tools/python.js +0 -81
  142. package/dist/analyzers/tools/python.js.map +0 -1
  143. package/dist/analyzers/tools/rust.d.ts +0 -8
  144. package/dist/analyzers/tools/rust.d.ts.map +0 -1
  145. package/dist/analyzers/tools/rust.js +0 -86
  146. package/dist/analyzers/tools/rust.js.map +0 -1
  147. package/templates/.ai/templates/session-checkpoint-template.md +0 -97
package/CHANGELOG.md CHANGED
@@ -7,6 +7,159 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [2.1.0] - 2026-04-23
11
+
12
+ Minor release adding two new analyzers and a shared XLSX converter.
13
+ Schema-compatible with 2.0.x for all pre-existing reports; introduces
14
+ two new report kinds (`licenses`, `bom`) and a schema v11 → v12 bump on
15
+ the detailed security report. Drop-in upgrade — no existing consumer
16
+ breaks.
17
+
18
+ ### Added — license inventory
19
+
20
+ - **`vyuh-dxkit licenses [path]`** — per-pack dependency license
21
+ inventory across TypeScript (license-checker-rseidelsohn), Python
22
+ (pip-licenses), Go (go-licenses), Rust (cargo-license), and C#
23
+ (nuget-license). Populates 11 fields per package (name, version,
24
+ description, license type, license text, source URL, supplier,
25
+ release date, etc.). Writes `.ai/reports/licenses-<date>.md`; with
26
+ `--detailed` also a risk-categorized JSON + markdown flagging
27
+ strong-copyleft, weak-copyleft, unknown-license, missing-attribution
28
+ packages. TypeScript provider normalizes source URLs through
29
+ `hosted-git-info` so `git+`/SCP/RFC-SSH variants collapse to canonical
30
+ HTTPS.
31
+ - **`vyuh-dxkit bom [path]`** — Bill of Materials joining `licenses`
32
+ with dependency vulnerabilities on `(package, version)`. One row per
33
+ installed package-version with license metadata (cols 1-9, 15 per
34
+ customer spec) AND per-package vulnerability rollup: max severity
35
+ (col 11), per-advisory list with CVSS scores (col 12), and derived
36
+ Tier-1 resolution proposal (col 13 — "Upgrade X to Y" when every
37
+ advisory has a fixedVersion, "Upgrade <parent> (transitive fix)" when
38
+ the fix is in a parent dep, "No fix available" otherwise). Detailed
39
+ mode (`--detailed`) emits a risk-review markdown with 6 triage
40
+ buckets (critical/high × no-fix/actionable, medium, low, license-
41
+ scanner-gap). `--xlsx` / `to-xlsx` produce the 15-column workbook
42
+ the customer's spreadsheet workflow expects, byte-identical headers.
43
+ - **`vyuh-dxkit to-xlsx <json>`** — shared converter. Reads any
44
+ licenses or bom detailed JSON and emits the canonical 15-col XLSX.
45
+ Lets downstream tooling stash JSON and render on demand without re-
46
+ running the analyzer.
47
+
48
+ ### Added — dependency-vulnerability per-advisory detail
49
+
50
+ - Every language pack's `depVulns` provider now populates
51
+ `DepVulnFinding[]` alongside the existing per-severity counts. Counts
52
+ remain per-package (for `vulnerabilities` command parity); findings
53
+ are per-advisory with id (GHSA/CVE/PYSEC/GO/RUSTSEC), installed +
54
+ fixed versions, CVSS score, aliases, summary, references, and tool
55
+ attribution. `gatherDepVulns` forwards findings into
56
+ `SecurityReport.summary.dependencies.findings` so the
57
+ `vulnerabilities --detailed` command renders per-advisory inventory
58
+ (previously: counts only).
59
+ - `DepVulnFinding` extended with nine optional fields for tier-layered
60
+ enrichment: `tool` (denormalized producer, renamed from unused
61
+ `source`), `cvssScore`, `upgradeAdvice`, `reachable`, `epssScore`,
62
+ `kev`, `riskScore`, `breakingUpgrade`, `aliases`, `summary`,
63
+ `references`. Per-pack Tier-1 providers populate what their native
64
+ tools emit; Tier-2/3/4 enrichment lands in later 10h sub-phases.
65
+ - Cross-pack OSV enhancement: `enrichOsv` (renamed from
66
+ `enrichSeverities`) now returns `{severity, cvssScore}` pairs, and
67
+ a new `resolveCvssScores` helper does batched alias-fallback
68
+ lookups. Fills the CVSS gap for GO-\* records (bulk of which carry
69
+ no severity but whose CVE aliases do) and PYSEC-\* records. TS pack
70
+ is a no-op via this path (npm-audit already ships CVSS at ~100%);
71
+ Python cvssScore coverage jumped from 0% → 100% on the fixture,
72
+ Go from 0% → 55% on vyuhlabs/Tickit.
73
+ - **Go pack parser fix** — `govulncheck -json` emits pretty-printed
74
+ multi-line JSON, not single-line ndjson. Previous `split('\n')`
75
+ parser silently failed on every invocation; new balanced-brace
76
+ `parseJsonStream` helper in `runner.ts` handles both shapes and
77
+ string-literal escapes. Reusable for any future tool that
78
+ pretty-prints.
79
+ - **Python pack manifest gating** — previously `pip-audit` ran with
80
+ no project context and silently scanned dxkit's own graphify-venv.
81
+ Now routes by manifest: `pip-audit <cwd>` for pyproject.toml/setup.py
82
+ projects, `pip-audit -r requirements.txt` for requirements projects,
83
+ null otherwise. Corrected platform audit: 97 → 94 dep vulns (3
84
+ phantom graphify-venv pip findings removed).
85
+
86
+ ### Added — tool registry
87
+
88
+ - TypeScript pack: `license-checker-rseidelsohn` (license inventory)
89
+ - Python pack: `pip-licenses` (license inventory)
90
+ - Go pack: `go-licenses` (license inventory, `go install golang.org/...`)
91
+ - Rust pack: `cargo-license` (license inventory, `cargo install`)
92
+ - C# pack: `nuget-license` (license inventory, `dotnet tool install`)
93
+
94
+ All bundled into per-pack provider commits so `findTool` + provider
95
+ invocation land together (CLAUDE.md rule 1).
96
+
97
+ ### Changed
98
+
99
+ - **Vulnerability report labelling** — Executive Summary now cleanly
100
+ separates "Code Findings" (your team patches source) from
101
+ "Dependency Vulnerabilities" (upgrade the dep) into two tables with
102
+ a combined total. Previously a single table labelled just "Severity
103
+ / Count" implied dep vulns were included, which they weren't. The
104
+ shallow report also now renders a worst-first per-advisory dep-vuln
105
+ table (50-row cap), so `vulnerabilities` without `--detailed` is
106
+ already actionable.
107
+ - **Security detailed schema** — bumps from `"11"` → `"12"` for the
108
+ new `summary.dependencies.findings: DepVulnFinding[]` field in the
109
+ JSON output. Additive — consumers reading just the old keys stay
110
+ compatible.
111
+ - **`DepVulnFinding.source` repurposed to `DepVulnFinding.tool`**.
112
+ The former `'osv.dev' | 'tool-default' | 'tool-reported'` enum was
113
+ dead code (declared, never written or read). Field now holds the
114
+ producer tool name (`npm-audit` / `pip-audit` / `govulncheck` /
115
+ `cargo-audit` / `dotnet-vulnerable`) so per-finding attribution
116
+ survives merges across multiple providers.
117
+
118
+ ### Fixed
119
+
120
+ - **npm-audit `fixAvailable` misinterpretation** — `fix.name` is the
121
+ top-level upgrade target, not the vulnerable package itself. Prior
122
+ code blindly assigned `fix.version` as `fixedVersion` on every
123
+ advisory, producing absurd output like "uuid@13.0.0 → Upgrade to
124
+ 3.2.1". Now branches on `fix.name === pkgName`: direct fix sets
125
+ `fixedVersion`; transitive fix sets `upgradeAdvice` with parent-
126
+ package guidance ("Upgrade @loopback/cli to 5.0.0 [major]
127
+ (transitive fix)"). Surfaced ~20 false positives on platform audit
128
+ covering uuid/octokit/tar/undici/underscore.
129
+ - **bom xlsx col 11/12/13 fill on non-vulnerable rows** — previously
130
+ blank, creating "scanned-clean vs not-scanned" ambiguity. Now fills
131
+ "None" / "No action required" so reviewers see at a glance which
132
+ rows dxkit actually processed.
133
+
134
+ ### Runtime dependencies added
135
+
136
+ - `exceljs ^4.4.0` — XLSX writer. Adds ~80 transitive deps (bumps
137
+ dxkit's own license-checker count 242 → ~325).
138
+ - `hosted-git-info ^9.0.2` + `@types/hosted-git-info ^3.0.5` — URL
139
+ canonicalisation (source URL column of licenses/bom).
140
+
141
+ ## [2.0.1] - 2026-04-22
142
+
143
+ Patch release following the 2.0.0 smoke-test. No API or schema changes —
144
+ drop-in upgrade from 2.0.0.
145
+
146
+ ### Fixed
147
+
148
+ - **`HealthReport.toolsUsed` now includes every external scanner that
149
+ actually ran.** Pre-2.0.1 the list was synthesized only from
150
+ `capabilities.lint` + `capabilities.depVulns`, so `semgrep` (code-
151
+ pattern scanner, `capabilities.codePatterns`) and `jscpd` (clone
152
+ detector, `capabilities.duplication`) didn't appear in the `health`
153
+ command's tool list even though they ran during
154
+ `gatherCapabilityReport`. `gitleaks` and `graphify` appeared only
155
+ because `tools/parallel.ts` pushed them separately. Now
156
+ `toolsFromCapabilities` mirrors all six external-scanner envelopes
157
+ (lint, depVulns, secrets, codePatterns, duplication, structural);
158
+ Layer 2's pushes dedupe via the existing `!includes(t)` guard.
159
+ Pseudo-tool envelopes (`imports.tool = 'ts-imports'`,
160
+ `testFramework.tool = 'typescript'`) stay out of the list — those
161
+ are language-pack identifiers, not external tools.
162
+
10
163
  ## [2.0.0] - 2026-04-22
11
164
 
12
165
  **BREAKING RELEASE.** The deterministic analyzer architecture introduced in
package/README.md CHANGED
@@ -32,25 +32,31 @@ The two modes are complementary. The analyzers run anywhere; the scaffolder writ
32
32
 
33
33
  ## Analyzer CLI (`vyuh-dxkit <command>`)
34
34
 
35
- Five deterministic analyzers. Each emits a markdown report to `.ai/reports/` and optional structured JSON.
35
+ Seven deterministic analyzers. Each emits a markdown report to `.ai/reports/` and optional structured JSON.
36
36
 
37
- | Command | What it does | Runtime | Output |
38
- | ----------------- | --------------------------------------------------------------- | ------- | ------------------------------------------ |
39
- | `health` | 6-dimension score (Testing, Quality, Docs, Security, Maint, DX) | 10–20s | `.ai/reports/health-audit-<date>.md` |
40
- | `vulnerabilities` | gitleaks + semgrep + `npm audit` / `pip-audit` | 5–30s | `.ai/reports/vulnerability-scan-<date>.md` |
41
- | `test-gaps` | Coverage artifact → import-graph → filename (strongest wins) | <1s | `.ai/reports/test-gaps-<date>.md` |
42
- | `quality` | Slop score + jscpd duplication + eslint/ruff + hygiene | 5–15s | `.ai/reports/quality-review-<date>.md` |
43
- | `dev-report` | Commits, contributors, hot files, velocity, conventional % | <1s | `.ai/reports/developer-report-<date>.md` |
37
+ | Command | What it does | Runtime | Output |
38
+ | ----------------- | --------------------------------------------------------------------------------- | ------- | ------------------------------------------ |
39
+ | `health` | 6-dimension score (Testing, Quality, Docs, Security, Maint, DX) | 10–20s | `.ai/reports/health-audit-<date>.md` |
40
+ | `vulnerabilities` | gitleaks + semgrep + per-pack dep-audit (per-advisory detail in `--detailed`) | 5–30s | `.ai/reports/vulnerability-scan-<date>.md` |
41
+ | `test-gaps` | Coverage artifact → import-graph → filename (strongest wins) | <1s | `.ai/reports/test-gaps-<date>.md` |
42
+ | `quality` | Slop score + jscpd duplication + eslint/ruff + hygiene | 5–15s | `.ai/reports/quality-review-<date>.md` |
43
+ | `dev-report` | Commits, contributors, hot files, velocity, conventional % | <1s | `.ai/reports/developer-report-<date>.md` |
44
+ | `licenses` | Dependency license inventory across every active pack (TS/Python/Go/Rust/C#) | 5–20s | `.ai/reports/licenses-<date>.md` |
45
+ | `bom` | **Bill of Materials** — joins licenses + vulnerabilities per package, 15-col XLSX | 10–40s | `.ai/reports/bom-<date>.{md,xlsx}` |
46
+
47
+ Plus a converter: `vyuh-dxkit to-xlsx <json-file>` renders any `licenses` or `bom` detailed JSON as the canonical 15-column XLSX.
44
48
 
45
49
  ### Flags (apply to all analyzer commands)
46
50
 
47
- | Flag | Effect |
48
- | ---------------- | ------------------------------------------------------------------------------------- |
49
- | `--detailed` | Also writes `<name>-detailed.md` + `.json` with evidence + ranked remediation actions |
50
- | `--json` | Emit pure JSON on stdout. Logs go to stderr so pipes stay clean |
51
- | `--verbose` | Print per-tool timing to stderr |
52
- | `--no-save` | Skip writing markdown; useful with `--json` |
53
- | `--since <date>` | (`dev-report` only) Analyze commits on or after `YYYY-MM-DD` |
51
+ | Flag | Effect |
52
+ | ---------------- | -------------------------------------------------------------------------------------- |
53
+ | `--detailed` | Also writes `<name>-detailed.md` + `.json` with evidence + ranked remediation actions |
54
+ | `--json` | Emit pure JSON on stdout. Logs go to stderr so pipes stay clean |
55
+ | `--verbose` | Print per-tool timing to stderr |
56
+ | `--no-save` | Skip writing markdown; useful with `--json` |
57
+ | `--xlsx` | (`licenses`, `bom` only) Also write 15-col `.xlsx` drop-in for spreadsheet workflows |
58
+ | `-o <file>` | (`licenses`, `bom`, `to-xlsx`) Override output path for xlsx / converted file |
59
+ | `--since <date>` | (`dev-report` only) Analyze commits on or after `YYYY-MM-DD` |
54
60
 
55
61
  ### Detailed mode — evidence + ranked fixes
56
62
 
@@ -0,0 +1,26 @@
1
+ /**
2
+ * BOM analyzer — detailed report.
3
+ *
4
+ * Extends the base BomReport with risk-categorized buckets so the
5
+ * reader can triage the inventory by what needs action first.
6
+ * Mirrors the licenses/detailed pattern (10h.2.2) but the categories
7
+ * are vuln-driven rather than license-driven, since BOM exists
8
+ * primarily to surface upgrade work.
9
+ */
10
+ import type { BomEntry, BomReport, BomSeverity } from './types';
11
+ export interface BomRiskCategory {
12
+ /** Severity tier for ordering. */
13
+ readonly priority: BomSeverity;
14
+ /** Stable category key — for programmatic filtering / dashboards. */
15
+ readonly id: 'critical-no-fix' | 'critical-actionable' | 'high-no-fix' | 'high-actionable' | 'medium-vulns' | 'low-vulns' | 'vuln-only-license-gap';
16
+ readonly title: string;
17
+ readonly rationale: string;
18
+ readonly recommendation: string;
19
+ readonly affected: ReadonlyArray<BomEntry>;
20
+ }
21
+ export interface BomDetailedReport extends BomReport {
22
+ riskCategories: ReadonlyArray<BomRiskCategory>;
23
+ }
24
+ export declare function buildBomDetailed(report: BomReport): BomDetailedReport;
25
+ export declare function formatBomDetailedMarkdown(detailed: BomDetailedReport, elapsed: string): string;
26
+ //# sourceMappingURL=detailed.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"detailed.d.ts","sourceRoot":"","sources":["../../../src/analyzers/bom/detailed.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAEhE,MAAM,WAAW,eAAe;IAC9B,kCAAkC;IAClC,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC;IAC/B,qEAAqE;IACrE,QAAQ,CAAC,EAAE,EACP,iBAAiB,GACjB,qBAAqB,GACrB,aAAa,GACb,iBAAiB,GACjB,cAAc,GACd,WAAW,GACX,uBAAuB,CAAC;IAC5B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,QAAQ,EAAE,aAAa,CAAC,QAAQ,CAAC,CAAC;CAC5C;AAED,MAAM,WAAW,iBAAkB,SAAQ,SAAS;IAClD,cAAc,EAAE,aAAa,CAAC,eAAe,CAAC,CAAC;CAChD;AAED,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,SAAS,GAAG,iBAAiB,CA8HrE;AASD,wBAAgB,yBAAyB,CAAC,QAAQ,EAAE,iBAAiB,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CA6G9F"}
@@ -0,0 +1,227 @@
1
+ "use strict";
2
+ /**
3
+ * BOM analyzer — detailed report.
4
+ *
5
+ * Extends the base BomReport with risk-categorized buckets so the
6
+ * reader can triage the inventory by what needs action first.
7
+ * Mirrors the licenses/detailed pattern (10h.2.2) but the categories
8
+ * are vuln-driven rather than license-driven, since BOM exists
9
+ * primarily to surface upgrade work.
10
+ */
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.buildBomDetailed = buildBomDetailed;
13
+ exports.formatBomDetailedMarkdown = formatBomDetailedMarkdown;
14
+ function buildBomDetailed(report) {
15
+ const categories = [];
16
+ // Buckets keyed by (severity, has-fix). The `actionable` axis matters
17
+ // because "critical with no fix" is qualitatively different from
18
+ // "critical with a one-line upgrade" — same severity, different
19
+ // remediation cost.
20
+ const buckets = new Map();
21
+ for (const e of report.entries) {
22
+ if (!e.maxSeverity)
23
+ continue;
24
+ const actionable = e.upgradeAdvice.startsWith('PROPOSAL:');
25
+ const key = `${e.maxSeverity}|${actionable ? 'fix' : 'nofix'}`;
26
+ const arr = buckets.get(key) ?? [];
27
+ arr.push(e);
28
+ buckets.set(key, arr);
29
+ }
30
+ const criticalNoFix = buckets.get('critical|nofix') ?? [];
31
+ if (criticalNoFix.length > 0) {
32
+ categories.push({
33
+ priority: 'critical',
34
+ id: 'critical-no-fix',
35
+ title: 'Critical vulns with no published fix',
36
+ rationale: 'These packages have one or more critical-severity advisories ' +
37
+ 'with no upstream fix version. Upgrading the dep does not resolve ' +
38
+ 'them — replacement or vendor pressure is the only remediation path.',
39
+ recommendation: 'Evaluate replacement packages, contact maintainers, or accept ' +
40
+ 'and document the risk. Do not ship to production untreated.',
41
+ affected: criticalNoFix,
42
+ });
43
+ }
44
+ const criticalActionable = buckets.get('critical|fix') ?? [];
45
+ if (criticalActionable.length > 0) {
46
+ categories.push({
47
+ priority: 'critical',
48
+ id: 'critical-actionable',
49
+ title: 'Critical vulns with an upgrade path',
50
+ rationale: 'These packages have critical advisories AND a published fixed ' +
51
+ 'version. The upgrade is the highest-leverage security action ' +
52
+ 'available for this codebase right now.',
53
+ recommendation: 'Schedule the upgrades immediately. Prefer the Tier-1 PROPOSAL ' +
54
+ 'target unless a major-version bump introduces compat risk.',
55
+ affected: criticalActionable,
56
+ });
57
+ }
58
+ const highNoFix = buckets.get('high|nofix') ?? [];
59
+ if (highNoFix.length > 0) {
60
+ categories.push({
61
+ priority: 'high',
62
+ id: 'high-no-fix',
63
+ title: 'High-severity vulns with no published fix',
64
+ rationale: 'High-severity advisories without an upstream fix. Less urgent ' +
65
+ 'than critical-no-fix but still warrants a documented decision.',
66
+ recommendation: 'Plan replacement evaluation alongside critical-no-fix items. ' +
67
+ 'Track the upstream advisory for fix availability.',
68
+ affected: highNoFix,
69
+ });
70
+ }
71
+ const highActionable = buckets.get('high|fix') ?? [];
72
+ if (highActionable.length > 0) {
73
+ categories.push({
74
+ priority: 'high',
75
+ id: 'high-actionable',
76
+ title: 'High-severity vulns with an upgrade path',
77
+ rationale: 'High-severity advisories with a published fixed version.',
78
+ recommendation: 'Schedule upgrades within the next sprint.',
79
+ affected: highActionable,
80
+ });
81
+ }
82
+ const mediumVulns = [
83
+ ...(buckets.get('medium|fix') ?? []),
84
+ ...(buckets.get('medium|nofix') ?? []),
85
+ ];
86
+ if (mediumVulns.length > 0) {
87
+ categories.push({
88
+ priority: 'medium',
89
+ id: 'medium-vulns',
90
+ title: 'Medium-severity vulnerabilities',
91
+ rationale: 'Medium-severity advisories. Plan into routine dep maintenance.',
92
+ recommendation: 'Batch into a recurring "dependency upgrade week" cadence. ' +
93
+ 'Watch for severity bumps — OSV/CVSS revisions can promote ' +
94
+ 'these into the high bucket.',
95
+ affected: mediumVulns,
96
+ });
97
+ }
98
+ const lowVulns = [...(buckets.get('low|fix') ?? []), ...(buckets.get('low|nofix') ?? [])];
99
+ if (lowVulns.length > 0) {
100
+ categories.push({
101
+ priority: 'low',
102
+ id: 'low-vulns',
103
+ title: 'Low-severity vulnerabilities',
104
+ rationale: 'Low-severity advisories. Track but not blocking.',
105
+ recommendation: 'Bundle into routine maintenance; no urgency.',
106
+ affected: lowVulns,
107
+ });
108
+ }
109
+ const vulnOnly = report.entries.filter((e) => !e.joinedFromBoth);
110
+ if (vulnOnly.length > 0) {
111
+ categories.push({
112
+ priority: 'medium',
113
+ id: 'vuln-only-license-gap',
114
+ title: 'License-scanner gap (vuln-only entries)',
115
+ rationale: 'These packages were reported by a vulnerability scanner but ' +
116
+ 'not by the license scanner. The license is shown as UNKNOWN; ' +
117
+ 'the most likely cause is a workspace / sub-package the license ' +
118
+ 'tool did not traverse.',
119
+ recommendation: 'Verify the licenses manually before shipping. If the package ' +
120
+ 'lives in a workspace, surface it in the root manifest or use ' +
121
+ 'the workspace-aware license tool flag.',
122
+ affected: vulnOnly,
123
+ });
124
+ }
125
+ return { ...report, riskCategories: categories };
126
+ }
127
+ const SEV_LABEL = {
128
+ critical: 'CRITICAL',
129
+ high: 'HIGH',
130
+ medium: 'MEDIUM',
131
+ low: 'LOW',
132
+ };
133
+ function formatBomDetailedMarkdown(detailed, elapsed) {
134
+ const L = [];
135
+ const s = detailed.summary;
136
+ L.push('# Bill of Materials (BOM) — Detailed');
137
+ L.push('');
138
+ L.push(`**Date:** ${detailed.analyzedAt.slice(0, 10)}`);
139
+ L.push(`**Repository:** ${detailed.repo}`);
140
+ L.push(`**Branch:** ${detailed.branch} (${detailed.commitSha})`);
141
+ L.push(`**Schema version:** ${detailed.schemaVersion}`);
142
+ L.push('');
143
+ L.push('---');
144
+ L.push('');
145
+ L.push('## Summary');
146
+ L.push('');
147
+ L.push(`- **Total packages:** ${s.totalPackages}`);
148
+ L.push(`- **Vulnerable packages:** ${s.vulnerablePackages}`);
149
+ L.push(`- **Total advisories:** ${s.totalAdvisories} (one package can have many)`);
150
+ L.push(`- **Actionable upgrades (Tier-1 proposals):** ${s.actionableVulns}`);
151
+ if (s.vulnOnlyPackages > 0) {
152
+ L.push(`- **Vuln-only entries (license gap):** ${s.vulnOnlyPackages}`);
153
+ }
154
+ L.push('');
155
+ L.push(`> Reconciles with \`vyuh-dxkit vulnerabilities\`: that command counts ` +
156
+ `per-advisory (${s.totalAdvisories}); bom collapses per-package ` +
157
+ `(${s.vulnerablePackages}) so each xlsx row is one upgrade decision.`);
158
+ L.push('');
159
+ L.push('---');
160
+ L.push('');
161
+ L.push('## Risk Review');
162
+ L.push('');
163
+ if (detailed.riskCategories.length === 0) {
164
+ L.push('No vulnerable packages — nothing to triage.');
165
+ }
166
+ else {
167
+ for (const cat of detailed.riskCategories) {
168
+ L.push(`### ${SEV_LABEL[cat.priority]}: ${cat.title} (${cat.affected.length})`);
169
+ L.push('');
170
+ L.push(`**Why this matters:** ${cat.rationale}`);
171
+ L.push('');
172
+ L.push(`**Recommendation:** ${cat.recommendation}`);
173
+ L.push('');
174
+ L.push('| Package@Version | License | # Vulns | Resolution |');
175
+ L.push('|-----------------|---------|--------:|------------|');
176
+ for (const e of cat.affected) {
177
+ const advice = e.upgradeAdvice.replace(/\|/g, '\\|');
178
+ L.push(`| \`${e.package}@${e.version}\` | ${e.licenseType} | ${e.vulns.length} | ${advice} |`);
179
+ }
180
+ L.push('');
181
+ }
182
+ }
183
+ L.push('---');
184
+ L.push('');
185
+ // Per-advisory inventory across every vuln in every entry. Lets the
186
+ // reader drill from "this package has 3 vulns" up to the actual CVE
187
+ // ids without leaving the markdown.
188
+ L.push('## Per-Advisory Inventory');
189
+ L.push('');
190
+ const SEV_RANK = { critical: 0, high: 1, medium: 2, low: 3 };
191
+ const flat = detailed.entries
192
+ .filter((e) => e.vulns.length > 0)
193
+ .flatMap((e) => e.vulns.map((v) => ({
194
+ severity: v.severity,
195
+ package: e.package,
196
+ version: e.version,
197
+ id: v.id,
198
+ fixedVersion: v.fixedVersion,
199
+ cvssScore: v.cvssScore,
200
+ tool: v.tool,
201
+ summary: v.summary,
202
+ })))
203
+ .sort((a, b) => SEV_RANK[a.severity] - SEV_RANK[b.severity] || a.package.localeCompare(b.package));
204
+ if (flat.length === 0) {
205
+ L.push('No vulnerabilities — empty inventory.');
206
+ }
207
+ else {
208
+ L.push(`${flat.length} advisories total.`);
209
+ L.push('');
210
+ L.push('| Severity | Package@Version | ID | Fix | CVSS | Tool | Summary |');
211
+ L.push('|----------|-----------------|----|-----|-----:|------|---------|');
212
+ for (const v of flat) {
213
+ const summary = (v.summary || '').replace(/\|/g, '\\|').replace(/\n/g, ' ').slice(0, 100);
214
+ const cvss = v.cvssScore !== undefined ? v.cvssScore.toFixed(1) : '—';
215
+ L.push(`| ${SEV_LABEL[v.severity]} | \`${v.package}@${v.version}\` | \`${v.id}\` | ${v.fixedVersion ?? '—'} | ${cvss} | ${v.tool} | ${summary} |`);
216
+ }
217
+ }
218
+ L.push('');
219
+ L.push('---');
220
+ L.push('');
221
+ L.push(`**Tools used:** ${detailed.toolsUsed.join(', ') || '(none)'}`);
222
+ L.push(`**Analysis time:** ${elapsed}s`);
223
+ L.push('');
224
+ L.push('*Generated by [VyuhLabs DXKit](https://www.npmjs.com/package/@vyuhlabs/dxkit) — detailed mode*');
225
+ return L.join('\n');
226
+ }
227
+ //# sourceMappingURL=detailed.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"detailed.js","sourceRoot":"","sources":["../../../src/analyzers/bom/detailed.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,52 @@
1
+ /**
2
+ * BOM analyzer data-gather. Joins LICENSES + DEP_VULNS via the
3
+ * existing capability gather functions — no new tool invocation logic
4
+ * (CLAUDE.md rule 2). The gather just calls each, then walks both
5
+ * result sets to build a per-package join keyed by `package@version`.
6
+ */
7
+ import type { DepVulnFinding } from '../../languages/capabilities/types';
8
+ import type { BomEntry } from './types';
9
+ /**
10
+ * Compare two version strings as semver triples. Strips a leading
11
+ * 'v' (Go-pack convention) and compares dot-separated numeric
12
+ * components. Falls back to lexicographic comparison when either
13
+ * input isn't a parseable triple — preserves a deterministic
14
+ * ordering for non-semver versions (e.g. cargo's "0.10.55+echo.1").
15
+ */
16
+ export declare function compareSemver(a: string, b: string): number;
17
+ /** Highest version in `versions` per compareSemver. Returns the input
18
+ * unchanged when only one version is supplied. */
19
+ export declare function maxSemver(versions: string[]): string;
20
+ /**
21
+ * Tier-1 resolution proposal derived purely from `fixedVersion`
22
+ * data shipped by each pack's depVulns provider. Per checkpoint §9:
23
+ * - no vulns → empty
24
+ * - every vuln has fixedVersion → "PROPOSAL: Upgrade to <maxFix> (resolves N)"
25
+ * - some vuln lacks fixedVersion → "No fix available — evaluate replacement"
26
+ *
27
+ * Higher tiers (10h.4 Snyk, 10h.6 osv-scanner fix) populate
28
+ * `upgradeAdvice` directly on each finding; the bom render layer
29
+ * picks the richest available value per package.
30
+ */
31
+ export declare function deriveTier1Resolution(vulns: DepVulnFinding[]): string;
32
+ /**
33
+ * Join LICENSES + DEP_VULNS by (package, version). Strategy:
34
+ * - Primary index: package@version. Both LicenseFinding and
35
+ * DepVulnFinding usually carry both — match exact.
36
+ * - Fallback: package only. DepVulnFindings without
37
+ * installedVersion fall back to package-name match against
38
+ * the licenses list (joins to the single matching version
39
+ * when unambiguous, all matching versions when not).
40
+ *
41
+ * License-only packages emit BomEntry with empty `vulns`. Vuln-only
42
+ * packages (rare — license scanner gap) emit a row with empty
43
+ * license fields and `joinedFromBoth: false` so the detailed report
44
+ * can flag the gap.
45
+ */
46
+ export interface BomGatherResult {
47
+ entries: BomEntry[];
48
+ toolsUsed: string[];
49
+ toolsUnavailable: string[];
50
+ }
51
+ export declare function gatherBomEntries(cwd: string): Promise<BomGatherResult>;
52
+ //# sourceMappingURL=gather.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gather.d.ts","sourceRoot":"","sources":["../../../src/analyzers/bom/gather.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EAAE,cAAc,EAAkB,MAAM,oCAAoC,CAAC;AACzF,OAAO,KAAK,EAAE,QAAQ,EAAe,MAAM,SAAS,CAAC;AAIrD;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAgB1D;AAED;mDACmD;AACnD,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,MAAM,CAGpD;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,cAAc,EAAE,GAAG,MAAM,CAQrE;AAYD;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,QAAQ,EAAE,CAAC;IACpB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,gBAAgB,EAAE,MAAM,EAAE,CAAC;CAC5B;AAED,wBAAsB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC,CAiF5E"}