@vyuhlabs/dxkit 2.4.5 → 2.4.7

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 (356) hide show
  1. package/CHANGELOG.md +1022 -0
  2. package/README.md +160 -45
  3. package/dist/analysis-result.d.ts +112 -0
  4. package/dist/analysis-result.d.ts.map +1 -0
  5. package/dist/analysis-result.js +52 -0
  6. package/dist/analysis-result.js.map +1 -0
  7. package/dist/analyzers/bom/detailed.d.ts.map +1 -1
  8. package/dist/analyzers/bom/detailed.js +19 -0
  9. package/dist/analyzers/bom/detailed.js.map +1 -1
  10. package/dist/analyzers/bom/gather.d.ts +27 -26
  11. package/dist/analyzers/bom/gather.d.ts.map +1 -1
  12. package/dist/analyzers/bom/gather.js +26 -87
  13. package/dist/analyzers/bom/gather.js.map +1 -1
  14. package/dist/analyzers/bom/index.d.ts +0 -7
  15. package/dist/analyzers/bom/index.d.ts.map +1 -1
  16. package/dist/analyzers/bom/index.js +98 -48
  17. package/dist/analyzers/bom/index.js.map +1 -1
  18. package/dist/analyzers/bom/types.d.ts +11 -13
  19. package/dist/analyzers/bom/types.d.ts.map +1 -1
  20. package/dist/analyzers/cache.d.ts +95 -0
  21. package/dist/analyzers/cache.d.ts.map +1 -0
  22. package/dist/analyzers/cache.js +309 -0
  23. package/dist/analyzers/cache.js.map +1 -0
  24. package/dist/analyzers/coverage-runner.d.ts +56 -0
  25. package/dist/analyzers/coverage-runner.d.ts.map +1 -0
  26. package/dist/analyzers/coverage-runner.js +72 -0
  27. package/dist/analyzers/coverage-runner.js.map +1 -0
  28. package/dist/analyzers/dashboard/index.d.ts +24 -0
  29. package/dist/analyzers/dashboard/index.d.ts.map +1 -0
  30. package/dist/analyzers/dashboard/index.js +666 -0
  31. package/dist/analyzers/dashboard/index.js.map +1 -0
  32. package/dist/analyzers/developer/gather.d.ts.map +1 -1
  33. package/dist/analyzers/developer/gather.js +205 -37
  34. package/dist/analyzers/developer/gather.js.map +1 -1
  35. package/dist/analyzers/developer/index.d.ts +1 -1
  36. package/dist/analyzers/developer/index.d.ts.map +1 -1
  37. package/dist/analyzers/developer/index.js +19 -8
  38. package/dist/analyzers/developer/index.js.map +1 -1
  39. package/dist/analyzers/dispatcher.d.ts +37 -0
  40. package/dist/analyzers/dispatcher.d.ts.map +1 -1
  41. package/dist/analyzers/dispatcher.js +56 -9
  42. package/dist/analyzers/dispatcher.js.map +1 -1
  43. package/dist/analyzers/docs/shallow.d.ts +17 -5
  44. package/dist/analyzers/docs/shallow.d.ts.map +1 -1
  45. package/dist/analyzers/docs/shallow.js +65 -2
  46. package/dist/analyzers/docs/shallow.js.map +1 -1
  47. package/dist/analyzers/dx/shallow.d.ts +17 -5
  48. package/dist/analyzers/dx/shallow.d.ts.map +1 -1
  49. package/dist/analyzers/dx/shallow.js +66 -2
  50. package/dist/analyzers/dx/shallow.js.map +1 -1
  51. package/dist/analyzers/health/actions.d.ts +1 -1
  52. package/dist/analyzers/health/actions.d.ts.map +1 -1
  53. package/dist/analyzers/health/actions.js +27 -9
  54. package/dist/analyzers/health/actions.js.map +1 -1
  55. package/dist/analyzers/health/detailed.d.ts +2 -1
  56. package/dist/analyzers/health/detailed.d.ts.map +1 -1
  57. package/dist/analyzers/health/detailed.js +11 -7
  58. package/dist/analyzers/health/detailed.js.map +1 -1
  59. package/dist/analyzers/health.d.ts +27 -0
  60. package/dist/analyzers/health.d.ts.map +1 -1
  61. package/dist/analyzers/health.js +271 -33
  62. package/dist/analyzers/health.js.map +1 -1
  63. package/dist/analyzers/licenses/gather.d.ts +35 -8
  64. package/dist/analyzers/licenses/gather.d.ts.map +1 -1
  65. package/dist/analyzers/licenses/gather.js +70 -13
  66. package/dist/analyzers/licenses/gather.js.map +1 -1
  67. package/dist/analyzers/licenses/index.d.ts +1 -1
  68. package/dist/analyzers/licenses/index.d.ts.map +1 -1
  69. package/dist/analyzers/licenses/index.js +52 -11
  70. package/dist/analyzers/licenses/index.js.map +1 -1
  71. package/dist/analyzers/licenses/types.d.ts +15 -0
  72. package/dist/analyzers/licenses/types.d.ts.map +1 -1
  73. package/dist/analyzers/maintainability/shallow.d.ts +17 -5
  74. package/dist/analyzers/maintainability/shallow.d.ts.map +1 -1
  75. package/dist/analyzers/maintainability/shallow.js +80 -2
  76. package/dist/analyzers/maintainability/shallow.js.map +1 -1
  77. package/dist/analyzers/quality/detailed.d.ts.map +1 -1
  78. package/dist/analyzers/quality/detailed.js +4 -6
  79. package/dist/analyzers/quality/detailed.js.map +1 -1
  80. package/dist/analyzers/quality/gather.d.ts +1 -14
  81. package/dist/analyzers/quality/gather.d.ts.map +1 -1
  82. package/dist/analyzers/quality/gather.js +48 -137
  83. package/dist/analyzers/quality/gather.js.map +1 -1
  84. package/dist/analyzers/quality/index.d.ts +9 -2
  85. package/dist/analyzers/quality/index.d.ts.map +1 -1
  86. package/dist/analyzers/quality/index.js +189 -117
  87. package/dist/analyzers/quality/index.js.map +1 -1
  88. package/dist/analyzers/quality/shallow.d.ts +50 -5
  89. package/dist/analyzers/quality/shallow.d.ts.map +1 -1
  90. package/dist/analyzers/quality/shallow.js +155 -2
  91. package/dist/analyzers/quality/shallow.js.map +1 -1
  92. package/dist/analyzers/quality/types.d.ts +14 -0
  93. package/dist/analyzers/quality/types.d.ts.map +1 -1
  94. package/dist/analyzers/security/actions.d.ts +11 -4
  95. package/dist/analyzers/security/actions.d.ts.map +1 -1
  96. package/dist/analyzers/security/actions.js +87 -37
  97. package/dist/analyzers/security/actions.js.map +1 -1
  98. package/dist/analyzers/security/aggregator.d.ts +236 -0
  99. package/dist/analyzers/security/aggregator.d.ts.map +1 -0
  100. package/dist/analyzers/security/aggregator.js +347 -0
  101. package/dist/analyzers/security/aggregator.js.map +1 -0
  102. package/dist/analyzers/security/detailed.d.ts +2 -2
  103. package/dist/analyzers/security/detailed.d.ts.map +1 -1
  104. package/dist/analyzers/security/detailed.js +10 -9
  105. package/dist/analyzers/security/detailed.js.map +1 -1
  106. package/dist/analyzers/security/gather.d.ts +103 -1
  107. package/dist/analyzers/security/gather.d.ts.map +1 -1
  108. package/dist/analyzers/security/gather.js +281 -9
  109. package/dist/analyzers/security/gather.js.map +1 -1
  110. package/dist/analyzers/security/index.d.ts +15 -0
  111. package/dist/analyzers/security/index.d.ts.map +1 -1
  112. package/dist/analyzers/security/index.js +463 -50
  113. package/dist/analyzers/security/index.js.map +1 -1
  114. package/dist/analyzers/security/shallow.d.ts +50 -6
  115. package/dist/analyzers/security/shallow.d.ts.map +1 -1
  116. package/dist/analyzers/security/shallow.js +154 -2
  117. package/dist/analyzers/security/shallow.js.map +1 -1
  118. package/dist/analyzers/security/types.d.ts +51 -0
  119. package/dist/analyzers/security/types.d.ts.map +1 -1
  120. package/dist/analyzers/tests/detailed.d.ts.map +1 -1
  121. package/dist/analyzers/tests/detailed.js +2 -3
  122. package/dist/analyzers/tests/detailed.js.map +1 -1
  123. package/dist/analyzers/tests/gather.d.ts +2 -1
  124. package/dist/analyzers/tests/gather.d.ts.map +1 -1
  125. package/dist/analyzers/tests/gather.js +98 -69
  126. package/dist/analyzers/tests/gather.js.map +1 -1
  127. package/dist/analyzers/tests/index.d.ts +11 -2
  128. package/dist/analyzers/tests/index.d.ts.map +1 -1
  129. package/dist/analyzers/tests/index.js +85 -18
  130. package/dist/analyzers/tests/index.js.map +1 -1
  131. package/dist/analyzers/tests/shallow.d.ts +19 -5
  132. package/dist/analyzers/tests/shallow.d.ts.map +1 -1
  133. package/dist/analyzers/tests/shallow.js +89 -2
  134. package/dist/analyzers/tests/shallow.js.map +1 -1
  135. package/dist/analyzers/tests/types.d.ts +41 -1
  136. package/dist/analyzers/tests/types.d.ts.map +1 -1
  137. package/dist/analyzers/tools/autogen-header.d.ts +8 -0
  138. package/dist/analyzers/tools/autogen-header.d.ts.map +1 -0
  139. package/dist/analyzers/tools/autogen-header.js +107 -0
  140. package/dist/analyzers/tools/autogen-header.js.map +1 -0
  141. package/dist/analyzers/tools/cloc.d.ts.map +1 -1
  142. package/dist/analyzers/tools/cloc.js +36 -5
  143. package/dist/analyzers/tools/cloc.js.map +1 -1
  144. package/dist/analyzers/tools/coverage.d.ts +1 -1
  145. package/dist/analyzers/tools/coverage.d.ts.map +1 -1
  146. package/dist/analyzers/tools/coverage.js.map +1 -1
  147. package/dist/analyzers/tools/debug-statements.d.ts +17 -0
  148. package/dist/analyzers/tools/debug-statements.d.ts.map +1 -0
  149. package/dist/analyzers/tools/debug-statements.js +58 -0
  150. package/dist/analyzers/tools/debug-statements.js.map +1 -0
  151. package/dist/analyzers/tools/default-exclusions.gitignore +28 -0
  152. package/dist/analyzers/tools/exclusions.d.ts +33 -6
  153. package/dist/analyzers/tools/exclusions.d.ts.map +1 -1
  154. package/dist/analyzers/tools/exclusions.js +95 -26
  155. package/dist/analyzers/tools/exclusions.js.map +1 -1
  156. package/dist/analyzers/tools/generic.d.ts +17 -2
  157. package/dist/analyzers/tools/generic.d.ts.map +1 -1
  158. package/dist/analyzers/tools/generic.js +206 -109
  159. package/dist/analyzers/tools/generic.js.map +1 -1
  160. package/dist/analyzers/tools/gitleaks.d.ts.map +1 -1
  161. package/dist/analyzers/tools/gitleaks.js +48 -1
  162. package/dist/analyzers/tools/gitleaks.js.map +1 -1
  163. package/dist/analyzers/tools/graphify.d.ts +30 -2
  164. package/dist/analyzers/tools/graphify.d.ts.map +1 -1
  165. package/dist/analyzers/tools/graphify.js +131 -15
  166. package/dist/analyzers/tools/graphify.js.map +1 -1
  167. package/dist/analyzers/tools/jscpd.d.ts +12 -2
  168. package/dist/analyzers/tools/jscpd.d.ts.map +1 -1
  169. package/dist/analyzers/tools/jscpd.js +129 -6
  170. package/dist/analyzers/tools/jscpd.js.map +1 -1
  171. package/dist/analyzers/tools/minified-detection.d.ts +9 -0
  172. package/dist/analyzers/tools/minified-detection.d.ts.map +1 -0
  173. package/dist/analyzers/tools/minified-detection.js +147 -0
  174. package/dist/analyzers/tools/minified-detection.js.map +1 -0
  175. package/dist/analyzers/tools/nuget-package-reference.d.ts +131 -0
  176. package/dist/analyzers/tools/nuget-package-reference.d.ts.map +1 -0
  177. package/dist/analyzers/tools/nuget-package-reference.js +175 -0
  178. package/dist/analyzers/tools/nuget-package-reference.js.map +1 -0
  179. package/dist/analyzers/tools/osv-scanner-deps.d.ts +48 -0
  180. package/dist/analyzers/tools/osv-scanner-deps.d.ts.map +1 -0
  181. package/dist/analyzers/tools/{osv-scanner-maven.js → osv-scanner-deps.js} +78 -46
  182. package/dist/analyzers/tools/osv-scanner-deps.js.map +1 -0
  183. package/dist/analyzers/tools/osv.d.ts +36 -0
  184. package/dist/analyzers/tools/osv.d.ts.map +1 -1
  185. package/dist/analyzers/tools/osv.js +26 -0
  186. package/dist/analyzers/tools/osv.js.map +1 -1
  187. package/dist/analyzers/tools/parallel.d.ts +1 -1
  188. package/dist/analyzers/tools/parallel.d.ts.map +1 -1
  189. package/dist/analyzers/tools/parallel.js +2 -2
  190. package/dist/analyzers/tools/parallel.js.map +1 -1
  191. package/dist/analyzers/tools/risk-score.d.ts +7 -0
  192. package/dist/analyzers/tools/risk-score.d.ts.map +1 -1
  193. package/dist/analyzers/tools/risk-score.js +9 -2
  194. package/dist/analyzers/tools/risk-score.js.map +1 -1
  195. package/dist/analyzers/tools/run-tests-helper.d.ts +43 -0
  196. package/dist/analyzers/tools/run-tests-helper.d.ts.map +1 -0
  197. package/dist/analyzers/tools/run-tests-helper.js +156 -0
  198. package/dist/analyzers/tools/run-tests-helper.js.map +1 -0
  199. package/dist/analyzers/tools/runner.d.ts.map +1 -1
  200. package/dist/analyzers/tools/runner.js +75 -12
  201. package/dist/analyzers/tools/runner.js.map +1 -1
  202. package/dist/analyzers/tools/semgrep.d.ts +39 -2
  203. package/dist/analyzers/tools/semgrep.d.ts.map +1 -1
  204. package/dist/analyzers/tools/semgrep.js +131 -9
  205. package/dist/analyzers/tools/semgrep.js.map +1 -1
  206. package/dist/analyzers/tools/timing.d.ts +17 -3
  207. package/dist/analyzers/tools/timing.d.ts.map +1 -1
  208. package/dist/analyzers/tools/timing.js +36 -14
  209. package/dist/analyzers/tools/timing.js.map +1 -1
  210. package/dist/analyzers/tools/tool-registry.d.ts +10 -0
  211. package/dist/analyzers/tools/tool-registry.d.ts.map +1 -1
  212. package/dist/analyzers/tools/tool-registry.js +120 -1
  213. package/dist/analyzers/tools/tool-registry.js.map +1 -1
  214. package/dist/analyzers/tools/tools-unavailable-prose.d.ts +18 -0
  215. package/dist/analyzers/tools/tools-unavailable-prose.d.ts.map +1 -0
  216. package/dist/analyzers/tools/tools-unavailable-prose.js +69 -0
  217. package/dist/analyzers/tools/tools-unavailable-prose.js.map +1 -0
  218. package/dist/analyzers/tools/upgrade-plan-resolver.d.ts.map +1 -1
  219. package/dist/analyzers/tools/upgrade-plan-resolver.js +7 -0
  220. package/dist/analyzers/tools/upgrade-plan-resolver.js.map +1 -1
  221. package/dist/analyzers/tools/vendored-advisor.d.ts +43 -0
  222. package/dist/analyzers/tools/vendored-advisor.d.ts.map +1 -0
  223. package/dist/analyzers/tools/vendored-advisor.js +107 -0
  224. package/dist/analyzers/tools/vendored-advisor.js.map +1 -0
  225. package/dist/analyzers/tools/walk-paths.d.ts +78 -0
  226. package/dist/analyzers/tools/walk-paths.d.ts.map +1 -0
  227. package/dist/analyzers/tools/walk-paths.js +150 -0
  228. package/dist/analyzers/tools/walk-paths.js.map +1 -0
  229. package/dist/analyzers/tools/walk-source-files.d.ts +70 -0
  230. package/dist/analyzers/tools/walk-source-files.d.ts.map +1 -0
  231. package/dist/analyzers/tools/walk-source-files.js +369 -0
  232. package/dist/analyzers/tools/walk-source-files.js.map +1 -0
  233. package/dist/analyzers/types.d.ts +204 -4
  234. package/dist/analyzers/types.d.ts.map +1 -1
  235. package/dist/analyzers/xlsx/bom.d.ts.map +1 -1
  236. package/dist/analyzers/xlsx/bom.js +8 -1
  237. package/dist/analyzers/xlsx/bom.js.map +1 -1
  238. package/dist/cli.d.ts.map +1 -1
  239. package/dist/cli.js +557 -189
  240. package/dist/cli.js.map +1 -1
  241. package/dist/constants.d.ts +1 -0
  242. package/dist/constants.d.ts.map +1 -1
  243. package/dist/detect.d.ts.map +1 -1
  244. package/dist/detect.js +24 -7
  245. package/dist/detect.js.map +1 -1
  246. package/dist/doctor.d.ts.map +1 -1
  247. package/dist/doctor.js +103 -53
  248. package/dist/doctor.js.map +1 -1
  249. package/dist/languages/capabilities/provider.d.ts +130 -1
  250. package/dist/languages/capabilities/provider.d.ts.map +1 -1
  251. package/dist/languages/capabilities/types.d.ts +68 -7
  252. package/dist/languages/capabilities/types.d.ts.map +1 -1
  253. package/dist/languages/csharp.d.ts +15 -1
  254. package/dist/languages/csharp.d.ts.map +1 -1
  255. package/dist/languages/csharp.js +624 -146
  256. package/dist/languages/csharp.js.map +1 -1
  257. package/dist/languages/go.d.ts.map +1 -1
  258. package/dist/languages/go.js +89 -11
  259. package/dist/languages/go.js.map +1 -1
  260. package/dist/languages/index.d.ts +131 -2
  261. package/dist/languages/index.d.ts.map +1 -1
  262. package/dist/languages/index.js +208 -0
  263. package/dist/languages/index.js.map +1 -1
  264. package/dist/languages/java.d.ts.map +1 -1
  265. package/dist/languages/java.js +121 -32
  266. package/dist/languages/java.js.map +1 -1
  267. package/dist/languages/kotlin.d.ts.map +1 -1
  268. package/dist/languages/kotlin.js +140 -32
  269. package/dist/languages/kotlin.js.map +1 -1
  270. package/dist/languages/python.d.ts.map +1 -1
  271. package/dist/languages/python.js +149 -44
  272. package/dist/languages/python.js.map +1 -1
  273. package/dist/languages/ruby.d.ts +115 -0
  274. package/dist/languages/ruby.d.ts.map +1 -0
  275. package/dist/languages/ruby.js +665 -0
  276. package/dist/languages/ruby.js.map +1 -0
  277. package/dist/languages/rust.d.ts.map +1 -1
  278. package/dist/languages/rust.js +103 -16
  279. package/dist/languages/rust.js.map +1 -1
  280. package/dist/languages/types.d.ts +228 -5
  281. package/dist/languages/types.d.ts.map +1 -1
  282. package/dist/languages/typescript.d.ts.map +1 -1
  283. package/dist/languages/typescript.js +201 -14
  284. package/dist/languages/typescript.js.map +1 -1
  285. package/dist/scoring/dimensions/documentation.d.ts +53 -0
  286. package/dist/scoring/dimensions/documentation.d.ts.map +1 -0
  287. package/dist/scoring/dimensions/documentation.js +106 -0
  288. package/dist/scoring/dimensions/documentation.js.map +1 -0
  289. package/dist/scoring/dimensions/dx.d.ts +53 -0
  290. package/dist/scoring/dimensions/dx.d.ts.map +1 -0
  291. package/dist/scoring/dimensions/dx.js +105 -0
  292. package/dist/scoring/dimensions/dx.js.map +1 -0
  293. package/dist/scoring/dimensions/maintainability.d.ts +53 -0
  294. package/dist/scoring/dimensions/maintainability.d.ts.map +1 -0
  295. package/dist/scoring/dimensions/maintainability.js +101 -0
  296. package/dist/scoring/dimensions/maintainability.js.map +1 -0
  297. package/dist/scoring/dimensions/quality.d.ts +108 -0
  298. package/dist/scoring/dimensions/quality.d.ts.map +1 -0
  299. package/dist/scoring/dimensions/quality.js +174 -0
  300. package/dist/scoring/dimensions/quality.js.map +1 -0
  301. package/dist/scoring/dimensions/security.d.ts +84 -0
  302. package/dist/scoring/dimensions/security.d.ts.map +1 -0
  303. package/dist/scoring/dimensions/security.js +135 -0
  304. package/dist/scoring/dimensions/security.js.map +1 -0
  305. package/dist/scoring/dimensions/testing.d.ts +56 -0
  306. package/dist/scoring/dimensions/testing.d.ts.map +1 -0
  307. package/dist/scoring/dimensions/testing.js +98 -0
  308. package/dist/scoring/dimensions/testing.js.map +1 -0
  309. package/dist/scoring/evaluator.d.ts +27 -0
  310. package/dist/scoring/evaluator.d.ts.map +1 -0
  311. package/dist/scoring/evaluator.js +124 -0
  312. package/dist/scoring/evaluator.js.map +1 -0
  313. package/dist/scoring/format.d.ts +34 -0
  314. package/dist/scoring/format.d.ts.map +1 -0
  315. package/dist/scoring/format.js +63 -0
  316. package/dist/scoring/format.js.map +1 -0
  317. package/dist/scoring/index.d.ts +37 -0
  318. package/dist/scoring/index.d.ts.map +1 -0
  319. package/dist/scoring/index.js +57 -0
  320. package/dist/scoring/index.js.map +1 -0
  321. package/dist/scoring/overall.d.ts +54 -0
  322. package/dist/scoring/overall.d.ts.map +1 -0
  323. package/dist/scoring/overall.js +76 -0
  324. package/dist/scoring/overall.js.map +1 -0
  325. package/dist/scoring/result.d.ts +111 -0
  326. package/dist/scoring/result.d.ts.map +1 -0
  327. package/dist/scoring/result.js +14 -0
  328. package/dist/scoring/result.js.map +1 -0
  329. package/dist/scoring/spec.d.ts +76 -0
  330. package/dist/scoring/spec.d.ts.map +1 -0
  331. package/dist/scoring/spec.js +22 -0
  332. package/dist/scoring/spec.js.map +1 -0
  333. package/dist/scoring/thresholds.d.ts +56 -0
  334. package/dist/scoring/thresholds.d.ts.map +1 -0
  335. package/dist/scoring/thresholds.js +75 -0
  336. package/dist/scoring/thresholds.js.map +1 -0
  337. package/dist/tools-cli.d.ts.map +1 -1
  338. package/dist/tools-cli.js +21 -2
  339. package/dist/tools-cli.js.map +1 -1
  340. package/dist/types.d.ts +17 -1
  341. package/dist/types.d.ts.map +1 -1
  342. package/package.json +1 -1
  343. package/templates/.claude/commands/dashboard.md +17 -9
  344. package/templates/.claude/rules/ruby.md +11 -0
  345. package/templates/configs/ruby/README.md +6 -0
  346. package/dist/analyzers/scoring.d.ts +0 -49
  347. package/dist/analyzers/scoring.d.ts.map +0 -1
  348. package/dist/analyzers/scoring.js +0 -422
  349. package/dist/analyzers/scoring.js.map +0 -1
  350. package/dist/analyzers/security/scoring.d.ts +0 -29
  351. package/dist/analyzers/security/scoring.d.ts.map +0 -1
  352. package/dist/analyzers/security/scoring.js +0 -40
  353. package/dist/analyzers/security/scoring.js.map +0 -1
  354. package/dist/analyzers/tools/osv-scanner-maven.d.ts +0 -42
  355. package/dist/analyzers/tools/osv-scanner-maven.d.ts.map +0 -1
  356. package/dist/analyzers/tools/osv-scanner-maven.js.map +0 -1
@@ -0,0 +1,236 @@
1
+ /**
2
+ * Canonical security aggregator (G_v4_8 / 2.4.7 Phase C1).
3
+ *
4
+ * One source of truth for "code findings by severity", "dependency
5
+ * advisories by severity", "unique advisory count", and cross-tool
6
+ * dedup. Every consumer (standalone vuln-scan, health-side scorer,
7
+ * BoM, dashboard) reads from `SecurityAggregate` instead of
8
+ * re-counting raw envelope arrays.
9
+ *
10
+ * The disease this closes (D086 / D087 / D091):
11
+ *
12
+ * - **D086** Health Security section and standalone vuln-scan Code
13
+ * Findings table both reported "code findings by severity" but
14
+ * came up with different numbers (`0C 11H 18M 0L` vs
15
+ * `0C 17H 14M 0L`) on the same repo. Two consumers, two
16
+ * aggregation paths, slightly-different inclusion rules.
17
+ *
18
+ * - **D087** Vuln-scan exec summary said "Subtotal: 70" (sum of
19
+ * dep-vuln severity buckets) and the same page later said
20
+ * "81 advisories" (findings.length). 70 vs 81 on one page.
21
+ *
22
+ * - **D091** A single TLS-bypass root finding surfaced twice in the
23
+ * Code Findings table (registry-grep at `:74` HIGH, semgrep at
24
+ * `:72` MEDIUM) because code findings carried no fingerprint and
25
+ * no cross-tool dedup ran.
26
+ *
27
+ * Architectural posture:
28
+ *
29
+ * - The aggregator sits BETWEEN gather and reports. Gather still
30
+ * produces raw envelopes (`gatherSecrets`, `gatherFileFindings`,
31
+ * `gatherCodePatterns`, `gatherTlsBypassFindings`, `gatherDepVulns`);
32
+ * the aggregator merges + dedups + buckets them into the canonical
33
+ * shape; consumers read by field name.
34
+ *
35
+ * - Three separately-named severity buckets (`codeBySeverity`,
36
+ * `depBySeverity`, `secretsBySeverity`) — the shape forbids any
37
+ * consumer from accidentally summing cross-axis again.
38
+ *
39
+ * - Two named dep counts (`dependencyAdvisoryUniqueCount` for the
40
+ * canonical user-facing total; `dependencyFindingsRawCount` for
41
+ * diagnostic audit). Renderers cannot pick "the wrong number"
42
+ * without naming which they want.
43
+ *
44
+ * - Code findings get a canonical-rule + line-window fingerprint;
45
+ * cross-tool collisions collapse to ONE CodeFinding with
46
+ * `keptSeverity = max(severities)` and `producedBy` listing all
47
+ * contributing tools. The `dedupCollisions` audit trail records
48
+ * every collapse for `--detailed` visibility.
49
+ *
50
+ * - `provenance` distinguishes "tool ran, 0 findings" from "tool
51
+ * didn't run" — drives D080-style "(not run: typescript)" labels.
52
+ *
53
+ * G_v4_8 architectural gate (`scripts/check-architecture.sh`) blocks
54
+ * `countBySeverity` / severity-Record accumulator declarations
55
+ * outside this file, mirroring G_v4_7's walker allowlist.
56
+ */
57
+ import type { DepVulnFinding } from '../../languages/capabilities/types';
58
+ import type { Severity, SecurityFinding } from './types';
59
+ export type { Severity, FindingCategory, SecurityFinding } from './types';
60
+ /**
61
+ * Per-severity counts. Local copy (avoids cross-module import friction
62
+ * with `capabilities/types.SeverityCounts` — same shape, different
63
+ * module home).
64
+ */
65
+ export interface SeverityCounts {
66
+ critical: number;
67
+ high: number;
68
+ medium: number;
69
+ low: number;
70
+ }
71
+ /**
72
+ * Post-aggregation code/secret/config finding. Extends raw
73
+ * `SecurityFinding` with the identity + provenance fields the
74
+ * aggregator stamps:
75
+ *
76
+ * - `fingerprint` — stable 16-char hash of
77
+ * `(canonicalRule | file | lineWindow)`. Same key across runs;
78
+ * enables diff tooling and dedup-by-identity downstream.
79
+ * - `canonicalRule` — normalized rule id from the canonical-rule
80
+ * registry. Different raw tool/rule pairs that describe the same
81
+ * root finding collapse to the same `canonicalRule`. Unmapped
82
+ * pairs pass through as `raw:${tool}:${rule}` — conservative
83
+ * default; new collapse rules require explicit registry entries.
84
+ * - `producedBy` — every raw `tool` that contributed to this
85
+ * finding. Length > 1 means cross-tool dedup fired.
86
+ */
87
+ export interface CodeFinding extends SecurityFinding {
88
+ fingerprint: string;
89
+ canonicalRule: string;
90
+ producedBy: string[];
91
+ }
92
+ /**
93
+ * One collapsed-collision audit entry. Renders in `--detailed` so a
94
+ * security reviewer can verify "yes, these two tools agreed on this
95
+ * one finding" rather than wondering why a tool's findings count
96
+ * differs from the report's surface count.
97
+ */
98
+ export interface DedupCollision {
99
+ canonicalRule: string;
100
+ file: string;
101
+ line: number;
102
+ keptSeverity: Severity;
103
+ collapsedFrom: ReadonlyArray<{
104
+ tool: string;
105
+ rule: string;
106
+ line: number;
107
+ severity: Severity;
108
+ }>;
109
+ }
110
+ /**
111
+ * Per-tool run-state provenance. Distinguishes "tool ran with zero
112
+ * findings" from "tool didn't run." Drives the "(not run: …)" labels
113
+ * on report tool-attribution lines and the security scorer's "scan
114
+ * was partial" cap signal (D025e / D080 lineage).
115
+ */
116
+ export interface AggregateProvenance {
117
+ secrets: {
118
+ tool: string | null;
119
+ ran: boolean;
120
+ };
121
+ codePatterns: {
122
+ tool: string | null;
123
+ ran: boolean;
124
+ };
125
+ tlsBypass: {
126
+ ran: boolean;
127
+ patternCount: number;
128
+ };
129
+ fileFindings: {
130
+ ran: boolean;
131
+ };
132
+ depVulns: {
133
+ tool: string | null;
134
+ available: boolean;
135
+ unavailableReason: string;
136
+ };
137
+ }
138
+ /**
139
+ * The canonical security aggregate. Every consumer reads from this;
140
+ * consumers MUST NOT re-aggregate from raw envelope arrays. The
141
+ * G_v4_8 architectural gate enforces this at commit time.
142
+ */
143
+ export interface SecurityAggregate {
144
+ /** Code-pattern findings by severity (semgrep + tls-bypass-registry
145
+ * + any future per-pack code-pattern producers), post-dedup. */
146
+ codeBySeverity: SeverityCounts;
147
+ /** Dependency advisories by severity, derived from the
148
+ * fingerprint-unique advisory set (NOT the per-pack envelope
149
+ * count sum). Sums to `dependencyAdvisoryUniqueCount`. */
150
+ depBySeverity: SeverityCounts;
151
+ /** Secret + secret-adjacent findings (gitleaks + private-key files +
152
+ * .env-in-git) by severity. Each axis stays separate so consumers
153
+ * pick which they own. */
154
+ secretsBySeverity: SeverityCounts;
155
+ /** Findings partitioned by category, post-dedup. Renderers iterate
156
+ * these — never iterate raw envelope arrays. `dependency` is the
157
+ * fingerprint-unique advisory set. */
158
+ findingsByCategory: {
159
+ secret: ReadonlyArray<CodeFinding>;
160
+ code: ReadonlyArray<CodeFinding>;
161
+ config: ReadonlyArray<CodeFinding>;
162
+ dependency: ReadonlyArray<DepVulnFinding>;
163
+ };
164
+ /**
165
+ * The canonical user-facing advisory count: unique fingerprints
166
+ * across every pack's findings. Use for the vuln-scan "Subtotal:"
167
+ * line, BoM `totalAdvisories`, and the "Showing N of M" denominator.
168
+ * Aligns with BoM's existing fingerprint-unique semantics (D076 /
169
+ * D085) so vuln-scan and BoM never report different totals.
170
+ */
171
+ dependencyAdvisoryUniqueCount: number;
172
+ /**
173
+ * Diagnostic-only: per-pack envelope.findings.length sum BEFORE
174
+ * fingerprint dedup. Surfaces in `--detailed` audit logs so the
175
+ * delta vs `dependencyAdvisoryUniqueCount` is visible. Renderers
176
+ * should NOT use this for any user-facing count.
177
+ */
178
+ dependencyFindingsRawCount: number;
179
+ /** Audit trail of every cross-tool / cross-line-window collapse.
180
+ * Empty in the no-collision case. */
181
+ dedupCollisions: ReadonlyArray<DedupCollision>;
182
+ /** Per-source provenance — drives "(not run: typescript)" labels. */
183
+ provenance: AggregateProvenance;
184
+ }
185
+ /**
186
+ * Input envelopes for `buildSecurityAggregate`. Each field maps 1:1
187
+ * to a `gather*` function in `security/gather.ts`. The aggregator
188
+ * never invokes I/O; it's a pure function over already-gathered
189
+ * data, which keeps unit testing trivial.
190
+ */
191
+ export interface SecurityAggregateInput {
192
+ secrets: {
193
+ findings: SecurityFinding[];
194
+ toolUsed: string | null;
195
+ };
196
+ fileFindings: SecurityFinding[];
197
+ codePatterns: {
198
+ findings: SecurityFinding[];
199
+ toolUsed: string | null;
200
+ };
201
+ tlsBypass: SecurityFinding[];
202
+ /** Pattern count from `allTlsBypassPatterns()` — drives the
203
+ * `provenance.tlsBypass.ran` flag (ran=false when no patterns were
204
+ * registered, NOT when 0 findings matched against a non-empty
205
+ * pattern set). */
206
+ tlsBypassPatternCount: number;
207
+ depVulns: {
208
+ findings: DepVulnFinding[];
209
+ tool: string | null;
210
+ available: boolean;
211
+ unavailableReason: string;
212
+ };
213
+ }
214
+ /**
215
+ * Build the canonical aggregate from per-gatherer envelopes. Pure
216
+ * function — same input always produces the same output.
217
+ *
218
+ * Dedup pipeline (code-side):
219
+ * 1. Concat raw findings from secrets/fileFindings/codePatterns/tlsBypass.
220
+ * 2. Group by `(canonicalRule, file, lineWindow)` key.
221
+ * 3. For each group:
222
+ * - Emit ONE `CodeFinding` with `keptSeverity = max(severities)`,
223
+ * `producedBy` = unique sources.
224
+ * - If the group had >1 raw finding, record a `DedupCollision`
225
+ * audit entry.
226
+ *
227
+ * Dedup pipeline (dep-side):
228
+ * - Group `depVulns.findings` by `fingerprint`.
229
+ * - For each group: pick the highest-severity entry as the
230
+ * representative; severity counts are derived from the unique
231
+ * set so they match `dependencyAdvisoryUniqueCount`.
232
+ * - Findings without a fingerprint pass through unchanged (defensive;
233
+ * `stampFingerprints` in `gatherDepVulns` runs before this).
234
+ */
235
+ export declare function buildSecurityAggregate(input: SecurityAggregateInput): SecurityAggregate;
236
+ //# sourceMappingURL=aggregator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"aggregator.d.ts","sourceRoot":"","sources":["../../../src/analyzers/security/aggregator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,347 @@
1
+ "use strict";
2
+ /**
3
+ * Canonical security aggregator (G_v4_8 / 2.4.7 Phase C1).
4
+ *
5
+ * One source of truth for "code findings by severity", "dependency
6
+ * advisories by severity", "unique advisory count", and cross-tool
7
+ * dedup. Every consumer (standalone vuln-scan, health-side scorer,
8
+ * BoM, dashboard) reads from `SecurityAggregate` instead of
9
+ * re-counting raw envelope arrays.
10
+ *
11
+ * The disease this closes (D086 / D087 / D091):
12
+ *
13
+ * - **D086** Health Security section and standalone vuln-scan Code
14
+ * Findings table both reported "code findings by severity" but
15
+ * came up with different numbers (`0C 11H 18M 0L` vs
16
+ * `0C 17H 14M 0L`) on the same repo. Two consumers, two
17
+ * aggregation paths, slightly-different inclusion rules.
18
+ *
19
+ * - **D087** Vuln-scan exec summary said "Subtotal: 70" (sum of
20
+ * dep-vuln severity buckets) and the same page later said
21
+ * "81 advisories" (findings.length). 70 vs 81 on one page.
22
+ *
23
+ * - **D091** A single TLS-bypass root finding surfaced twice in the
24
+ * Code Findings table (registry-grep at `:74` HIGH, semgrep at
25
+ * `:72` MEDIUM) because code findings carried no fingerprint and
26
+ * no cross-tool dedup ran.
27
+ *
28
+ * Architectural posture:
29
+ *
30
+ * - The aggregator sits BETWEEN gather and reports. Gather still
31
+ * produces raw envelopes (`gatherSecrets`, `gatherFileFindings`,
32
+ * `gatherCodePatterns`, `gatherTlsBypassFindings`, `gatherDepVulns`);
33
+ * the aggregator merges + dedups + buckets them into the canonical
34
+ * shape; consumers read by field name.
35
+ *
36
+ * - Three separately-named severity buckets (`codeBySeverity`,
37
+ * `depBySeverity`, `secretsBySeverity`) — the shape forbids any
38
+ * consumer from accidentally summing cross-axis again.
39
+ *
40
+ * - Two named dep counts (`dependencyAdvisoryUniqueCount` for the
41
+ * canonical user-facing total; `dependencyFindingsRawCount` for
42
+ * diagnostic audit). Renderers cannot pick "the wrong number"
43
+ * without naming which they want.
44
+ *
45
+ * - Code findings get a canonical-rule + line-window fingerprint;
46
+ * cross-tool collisions collapse to ONE CodeFinding with
47
+ * `keptSeverity = max(severities)` and `producedBy` listing all
48
+ * contributing tools. The `dedupCollisions` audit trail records
49
+ * every collapse for `--detailed` visibility.
50
+ *
51
+ * - `provenance` distinguishes "tool ran, 0 findings" from "tool
52
+ * didn't run" — drives D080-style "(not run: typescript)" labels.
53
+ *
54
+ * G_v4_8 architectural gate (`scripts/check-architecture.sh`) blocks
55
+ * `countBySeverity` / severity-Record accumulator declarations
56
+ * outside this file, mirroring G_v4_7's walker allowlist.
57
+ */
58
+ Object.defineProperty(exports, "__esModule", { value: true });
59
+ exports.buildSecurityAggregate = buildSecurityAggregate;
60
+ const crypto_1 = require("crypto");
61
+ // ─── Canonical-rule registry ──────────────────────────────────────────────
62
+ /**
63
+ * Maps raw `(tool, rule)` pairs to a canonical rule id. Two raw
64
+ * findings with the same canonical rule (and same file + line window)
65
+ * collapse to one `CodeFinding` with `keptSeverity = max` and
66
+ * `producedBy = [tool₁, tool₂, …]`.
67
+ *
68
+ * Unmapped pairs fall through to `raw:${tool}:${rule}` — never
69
+ * accidentally collapses unrelated findings. Adding a new collapse
70
+ * is a one-line addition here; no aggregator code changes.
71
+ *
72
+ * Initial entries close D091's observed TLS-bypass cross-tool
73
+ * double-counting. Future entries land when a new language pack or
74
+ * semgrep ruleset surfaces overlap with an existing finding type.
75
+ */
76
+ const CANONICAL_RULE_MAP = new Map([
77
+ // TLS / certificate validation bypass — D091 closure
78
+ ['tls-bypass-registry:tls-validation-disabled', 'canonical:tls-bypass'],
79
+ ['semgrep:bypass-tls-verification', 'canonical:tls-bypass'],
80
+ ['semgrep:nodejsscan.node_tls_reject_unauthorized', 'canonical:tls-bypass'],
81
+ // Private-key file on disk — find + gitleaks may both surface
82
+ ['find:private-key-file', 'canonical:private-key-on-disk'],
83
+ ['gitleaks:private-key', 'canonical:private-key-on-disk'],
84
+ ]);
85
+ function canonicalRuleFor(tool, rule) {
86
+ return CANONICAL_RULE_MAP.get(`${tool}:${rule}`) ?? `raw:${tool}:${rule}`;
87
+ }
88
+ /**
89
+ * Line-window bucketing. Tools report the same code construct at
90
+ * slightly-different lines (semgrep on the declaration, registry-grep
91
+ * on the assignment — D091's `:72` vs `:74` shape). 3-line buckets
92
+ * absorb that drift without collapsing genuinely-different findings
93
+ * in the same file.
94
+ *
95
+ * Boundary edge case closed by C1.10: the natural fixed-boundary
96
+ * bucketing alone would miss adjacent findings straddling a
97
+ * multiple-of-3 (web-client surfaced DBConfigureForm.js:43 + :45 →
98
+ * buckets 42 + 45 → no collapse pre-C1.10). The grouping loop now
99
+ * does a neighbor-bucket lookup (naturalBucket ± 3) after the natural
100
+ * miss, restoring D091's intent across boundary-straddling pairs.
101
+ * Effective collapse window: ~3-5 lines depending on alignment.
102
+ */
103
+ function lineWindowFor(line) {
104
+ return Math.floor(line / 3) * 3;
105
+ }
106
+ /**
107
+ * Stable 16-char hex hash of `(canonicalRule | file | lineWindow)`.
108
+ * NUL-separated so distinct tuples can't collide via concatenation
109
+ * tricks. Mirrors `tools/fingerprint.computeFingerprint`'s format
110
+ * (SHA-1 first 8 bytes hex) so dep-vuln and code-finding fingerprints
111
+ * share a downstream type contract.
112
+ */
113
+ function computeCodeFingerprint(canonicalRule, file, line) {
114
+ const input = `${canonicalRule}\0${file}\0${lineWindowFor(line)}`;
115
+ return (0, crypto_1.createHash)('sha1').update(input).digest('hex').slice(0, 16);
116
+ }
117
+ // ─── Severity helpers ─────────────────────────────────────────────────────
118
+ const SEVERITY_RANK = {
119
+ critical: 3,
120
+ high: 2,
121
+ medium: 1,
122
+ low: 0,
123
+ };
124
+ function maxSeverity(a, b) {
125
+ return SEVERITY_RANK[a] >= SEVERITY_RANK[b] ? a : b;
126
+ }
127
+ function emptyCounts() {
128
+ return { critical: 0, high: 0, medium: 0, low: 0 };
129
+ }
130
+ function bumpCounts(counts, severity) {
131
+ counts[severity]++;
132
+ }
133
+ /**
134
+ * Build the canonical aggregate from per-gatherer envelopes. Pure
135
+ * function — same input always produces the same output.
136
+ *
137
+ * Dedup pipeline (code-side):
138
+ * 1. Concat raw findings from secrets/fileFindings/codePatterns/tlsBypass.
139
+ * 2. Group by `(canonicalRule, file, lineWindow)` key.
140
+ * 3. For each group:
141
+ * - Emit ONE `CodeFinding` with `keptSeverity = max(severities)`,
142
+ * `producedBy` = unique sources.
143
+ * - If the group had >1 raw finding, record a `DedupCollision`
144
+ * audit entry.
145
+ *
146
+ * Dedup pipeline (dep-side):
147
+ * - Group `depVulns.findings` by `fingerprint`.
148
+ * - For each group: pick the highest-severity entry as the
149
+ * representative; severity counts are derived from the unique
150
+ * set so they match `dependencyAdvisoryUniqueCount`.
151
+ * - Findings without a fingerprint pass through unchanged (defensive;
152
+ * `stampFingerprints` in `gatherDepVulns` runs before this).
153
+ */
154
+ function buildSecurityAggregate(input) {
155
+ // ─── Code-side dedup ────────────────────────────────────────────────
156
+ const rawCodeFindings = [
157
+ ...input.secrets.findings,
158
+ ...input.fileFindings,
159
+ ...input.codePatterns.findings,
160
+ ...input.tlsBypass,
161
+ ];
162
+ const groups = new Map();
163
+ for (const f of rawCodeFindings) {
164
+ const canonicalRule = canonicalRuleFor(f.tool, f.rule);
165
+ const naturalFingerprint = computeCodeFingerprint(canonicalRule, f.file, f.line);
166
+ // C1.10: neighbor-bucket lookup. The 3-line fixed bucket misses
167
+ // adjacent findings that straddle a multiple-of-3 line (web-client
168
+ // DBConfigureForm.js:43 + :45 → buckets 42 + 45 → different keys
169
+ // → no collapse pre-C1.10). Look up the natural bucket first, then
170
+ // the adjacent buckets (naturalBucket ± 3 via `line ± 3`). Same
171
+ // canonical-rule + file + neighbor-bucket counts as a match; merges
172
+ // into that group. Effective dedup window grows from "0-2 lines
173
+ // within one bucket" to "3-5 lines across one bucket boundary."
174
+ let fingerprint = naturalFingerprint;
175
+ let existing = groups.get(fingerprint);
176
+ if (!existing) {
177
+ for (const offset of [-3, 3]) {
178
+ const neighborFingerprint = computeCodeFingerprint(canonicalRule, f.file, f.line + offset);
179
+ const candidate = groups.get(neighborFingerprint);
180
+ if (candidate) {
181
+ existing = candidate;
182
+ fingerprint = neighborFingerprint;
183
+ break;
184
+ }
185
+ }
186
+ }
187
+ if (existing) {
188
+ existing.severity = maxSeverity(existing.severity, f.severity);
189
+ existing.producedBy.add(f.tool);
190
+ existing.raws.push({
191
+ tool: f.tool,
192
+ rule: f.rule,
193
+ line: f.line,
194
+ severity: f.severity,
195
+ });
196
+ // Prefer the lower line number as the canonical line — semgrep
197
+ // typically reports the declaration (earlier line) while
198
+ // registry-grep reports the assignment; the declaration is the
199
+ // more useful navigation target. Tie-break by category preserve.
200
+ if (f.line < existing.line) {
201
+ existing.line = f.line;
202
+ existing.title = f.title;
203
+ existing.rule = f.rule;
204
+ existing.tool = f.tool;
205
+ existing.cwe = f.cwe || existing.cwe;
206
+ }
207
+ }
208
+ else {
209
+ groups.set(fingerprint, {
210
+ fingerprint,
211
+ canonicalRule,
212
+ file: f.file,
213
+ line: f.line,
214
+ severity: f.severity,
215
+ category: f.category,
216
+ cwe: f.cwe,
217
+ rule: f.rule,
218
+ title: f.title,
219
+ tool: f.tool,
220
+ producedBy: new Set([f.tool]),
221
+ raws: [
222
+ {
223
+ tool: f.tool,
224
+ rule: f.rule,
225
+ line: f.line,
226
+ severity: f.severity,
227
+ },
228
+ ],
229
+ });
230
+ }
231
+ }
232
+ const codeFindingsByCategory = {
233
+ secret: [],
234
+ code: [],
235
+ config: [],
236
+ };
237
+ const codeBySeverity = emptyCounts();
238
+ const secretsBySeverity = emptyCounts();
239
+ const dedupCollisions = [];
240
+ for (const g of groups.values()) {
241
+ const finding = {
242
+ severity: g.severity,
243
+ category: g.category,
244
+ cwe: g.cwe,
245
+ rule: g.rule,
246
+ title: g.title,
247
+ file: g.file,
248
+ line: g.line,
249
+ tool: g.tool,
250
+ fingerprint: g.fingerprint,
251
+ canonicalRule: g.canonicalRule,
252
+ producedBy: [...g.producedBy].sort(),
253
+ };
254
+ if (g.category === 'secret') {
255
+ codeFindingsByCategory.secret.push(finding);
256
+ bumpCounts(secretsBySeverity, g.severity);
257
+ }
258
+ else if (g.category === 'config') {
259
+ codeFindingsByCategory.config.push(finding);
260
+ // Config findings (`.env in git`) are secret-adjacent — they
261
+ // share the secrets axis so the Security dimension treats them
262
+ // as the same risk class. Pre-aggregator code paths agreed on
263
+ // this; we preserve it.
264
+ bumpCounts(secretsBySeverity, g.severity);
265
+ }
266
+ else {
267
+ codeFindingsByCategory.code.push(finding);
268
+ bumpCounts(codeBySeverity, g.severity);
269
+ }
270
+ if (g.raws.length > 1) {
271
+ dedupCollisions.push({
272
+ canonicalRule: g.canonicalRule,
273
+ file: g.file,
274
+ line: g.line,
275
+ keptSeverity: g.severity,
276
+ collapsedFrom: g.raws,
277
+ });
278
+ }
279
+ }
280
+ // ─── Dep-side dedup ─────────────────────────────────────────────────
281
+ // Group by fingerprint. Findings without a fingerprint (defensive
282
+ // path — shouldn't happen post-`stampFingerprints`) get a synthetic
283
+ // unique key so they pass through individually.
284
+ const depGroups = new Map();
285
+ let syntheticFingerprintCounter = 0;
286
+ for (const f of input.depVulns.findings) {
287
+ const key = f.fingerprint ?? `__unstamped__${syntheticFingerprintCounter++}`;
288
+ const existing = depGroups.get(key);
289
+ if (!existing) {
290
+ depGroups.set(key, f);
291
+ }
292
+ else {
293
+ // Keep the higher-severity representative. Same advisory may
294
+ // appear multiple times if cross-pack joins didn't already
295
+ // collapse it (defensive).
296
+ if (SEVERITY_RANK[f.severity] > SEVERITY_RANK[existing.severity]) {
297
+ depGroups.set(key, f);
298
+ }
299
+ }
300
+ }
301
+ const uniqueDepFindings = [...depGroups.values()];
302
+ const depBySeverity = emptyCounts();
303
+ for (const f of uniqueDepFindings) {
304
+ bumpCounts(depBySeverity, f.severity);
305
+ }
306
+ // ─── Provenance ─────────────────────────────────────────────────────
307
+ const provenance = {
308
+ secrets: {
309
+ tool: input.secrets.toolUsed,
310
+ ran: input.secrets.toolUsed !== null,
311
+ },
312
+ codePatterns: {
313
+ tool: input.codePatterns.toolUsed,
314
+ ran: input.codePatterns.toolUsed !== null,
315
+ },
316
+ tlsBypass: {
317
+ // ran=true means the registry walk happened (patterns existed).
318
+ // ran=false means no pack registered TLS-bypass patterns — a
319
+ // legitimate "nothing to scan" state on a repo with no active
320
+ // packs declaring patterns.
321
+ ran: input.tlsBypassPatternCount > 0,
322
+ patternCount: input.tlsBypassPatternCount,
323
+ },
324
+ fileFindings: { ran: true },
325
+ depVulns: {
326
+ tool: input.depVulns.tool,
327
+ available: input.depVulns.available,
328
+ unavailableReason: input.depVulns.unavailableReason,
329
+ },
330
+ };
331
+ return {
332
+ codeBySeverity,
333
+ depBySeverity,
334
+ secretsBySeverity,
335
+ findingsByCategory: {
336
+ secret: codeFindingsByCategory.secret,
337
+ code: codeFindingsByCategory.code,
338
+ config: codeFindingsByCategory.config,
339
+ dependency: uniqueDepFindings,
340
+ },
341
+ dependencyAdvisoryUniqueCount: uniqueDepFindings.length,
342
+ dependencyFindingsRawCount: input.depVulns.findings.length,
343
+ dedupCollisions,
344
+ provenance,
345
+ };
346
+ }
347
+ //# sourceMappingURL=aggregator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"aggregator.js","sourceRoot":"","sources":["../../../src/analyzers/security/aggregator.ts"],"names":[],"mappings":"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"}
@@ -1,10 +1,10 @@
1
1
  import { SecurityReport } from './types';
2
2
  import { RankedAction } from '../remediation';
3
- import { SecurityCounts } from './scoring';
3
+ import { SecurityScoreInput } from '../../scoring';
4
4
  export interface SecurityDetailedReport extends SecurityReport {
5
5
  schemaVersion: string;
6
6
  securityScore: number;
7
- actions: Array<RankedAction<SecurityCounts>>;
7
+ actions: Array<RankedAction<SecurityScoreInput>>;
8
8
  }
9
9
  export declare function buildSecurityDetailed(report: SecurityReport): SecurityDetailedReport;
10
10
  export declare function formatSecurityDetailedMarkdown(detailed: SecurityDetailedReport, elapsed: string): string;
@@ -1 +1 @@
1
- {"version":3,"file":"detailed.d.ts","sourceRoot":"","sources":["../../../src/analyzers/security/detailed.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,cAAc,EAA6B,MAAM,SAAS,CAAC;AACpE,OAAO,EAAE,YAAY,EAAQ,MAAM,gBAAgB,CAAC;AAEpD,OAAO,EAAE,cAAc,EAAuB,MAAM,WAAW,CAAC;AAEhE,MAAM,WAAW,sBAAuB,SAAQ,cAAc;IAC5D,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,KAAK,CAAC,YAAY,CAAC,cAAc,CAAC,CAAC,CAAC;CAC9C;AAED,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,cAAc,GAAG,sBAAsB,CAUpF;AAID,wBAAgB,8BAA8B,CAC5C,QAAQ,EAAE,sBAAsB,EAChC,OAAO,EAAE,MAAM,GACd,MAAM,CAsKR"}
1
+ {"version":3,"file":"detailed.d.ts","sourceRoot":"","sources":["../../../src/analyzers/security/detailed.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,cAAc,EAA6B,MAAM,SAAS,CAAC;AACpE,OAAO,EAAE,YAAY,EAAQ,MAAM,gBAAgB,CAAC;AAEpD,OAAO,EAAyB,kBAAkB,EAAgB,MAAM,eAAe,CAAC;AAGxF,MAAM,WAAW,sBAAuB,SAAQ,cAAc;IAC5D,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,KAAK,CAAC,YAAY,CAAC,kBAAkB,CAAC,CAAC,CAAC;CAClD;AAED,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,cAAc,GAAG,sBAAsB,CAYpF;AAID,wBAAgB,8BAA8B,CAC5C,QAAQ,EAAE,sBAAsB,EAChC,OAAO,EAAE,MAAM,GACd,MAAM,CAoKR"}
@@ -4,15 +4,18 @@ exports.buildSecurityDetailed = buildSecurityDetailed;
4
4
  exports.formatSecurityDetailedMarkdown = formatSecurityDetailedMarkdown;
5
5
  const remediation_1 = require("../remediation");
6
6
  const actions_1 = require("./actions");
7
- const scoring_1 = require("./scoring");
7
+ const scoring_1 = require("../../scoring");
8
+ const tools_unavailable_prose_1 = require("../tools/tools-unavailable-prose");
8
9
  function buildSecurityDetailed(report) {
9
- const counts = (0, actions_1.countsFromReport)(report);
10
- const actions = (0, remediation_1.rank)((0, actions_1.buildSecurityActions)(report), counts, scoring_1.scoreSecurityCounts);
10
+ const input = (0, actions_1.countsFromReport)(report);
11
+ const scoreFromInput = (i) => (0, scoring_1.evaluateSpec)(scoring_1.SECURITY_SCORING_SPEC, i);
12
+ const actions = (0, remediation_1.rank)((0, actions_1.buildSecurityActions)(report), input, scoreFromInput);
11
13
  return {
12
14
  ...report,
13
- // v12 adds per-advisory dep-vuln detail under summary.dependencies.findings.
14
- schemaVersion: '12',
15
- securityScore: (0, scoring_1.scoreSecurityCounts)(counts).score,
15
+ // v13 carries the unified scorer output; same path the health
16
+ // audit's Security dimension uses, identical scores.
17
+ schemaVersion: '13',
18
+ securityScore: scoreFromInput(input).score,
16
19
  actions,
17
20
  };
18
21
  }
@@ -157,9 +160,7 @@ function formatSecurityDetailedMarkdown(detailed, elapsed) {
157
160
  L.push('');
158
161
  }
159
162
  L.push(`**Tools used:** ${detailed.toolsUsed.join(', ')}`);
160
- if (detailed.toolsUnavailable.length > 0) {
161
- L.push(`**Tools unavailable:** ${detailed.toolsUnavailable.join(', ')}`);
162
- }
163
+ L.push(...(0, tools_unavailable_prose_1.renderToolsUnavailableLines)(detailed.toolsUnavailable));
163
164
  L.push(`**Analysis time:** ${elapsed}s`);
164
165
  L.push('');
165
166
  L.push('*Generated by [VyuhLabs DXKit](https://www.npmjs.com/package/@vyuhlabs/dxkit) — detailed mode*');