@cdxgen/cdxgen 13.5.0 → 13.7.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/README.md +17 -10
- package/bin/audit.js +7 -4
- package/bin/cdxgen.js +260 -37
- package/bin/convert.js +146 -22
- package/bin/evinse.js +28 -3
- package/bin/repl.js +47 -3
- package/bin/sign.js +211 -34
- package/bin/tracebom.js +18 -6
- package/bin/validate.js +24 -3
- package/bin/verify.js +113 -5
- package/data/behavior-taxonomy.schema.json +1491 -0
- package/data/cyclonedx-2.0-bundled.schema.json +18606 -5528
- package/data/cyclonedx-2.0-cryptography-defs.schema.json +857 -0
- package/data/license-aliases.json +24 -2
- package/data/pqc-migration.json +239 -0
- package/data/remediations.json +176 -0
- package/data/rules/ai-bom.yaml +1 -1
- package/data/rules/brotli-decoder.yaml +107 -0
- package/data/rules/cbom-security.yaml +4 -3
- package/data/rules/package-integrity.yaml +28 -0
- package/data/rules/vscode-extensions.yaml +75 -0
- package/data/spdx-license-list.json +121 -7
- package/data/spdx-licenses.json +69 -0
- package/data/spdx.schema.json +845 -2
- package/lib/audit/index.js +25 -3
- package/lib/cli/bomAssembly.js +172 -4
- package/lib/cli/cliOptions.js +121 -17
- package/lib/cli/index.js +720 -902
- package/lib/cli/jsBom.js +156 -64
- package/lib/cli/jvmBom.js +602 -86
- package/lib/cli/managedBom.js +161 -19
- package/lib/cli/nativeBom.js +52 -5
- package/lib/core/boundedFile.js +344 -0
- package/lib/core/brotliProbe.js +182 -0
- package/lib/core/env.js +34 -0
- package/lib/core/fs.js +138 -3
- package/lib/core/globPatterns.js +218 -0
- package/lib/core/httpClient.js +98 -1
- package/lib/core/lockPaths.js +38 -0
- package/lib/core/paths.js +24 -1
- package/lib/core/processTree.js +100 -8
- package/lib/core/projectConfig.js +332 -25
- package/lib/core/toolRegistry.js +184 -0
- package/lib/ecosystems/cppEvidence.js +263 -106
- package/lib/ecosystems/cppIncludeResolver.js +16 -5
- package/lib/ecosystems/denoutils.js +2 -2
- package/lib/ecosystems/ecosystems.js +25 -10
- package/lib/ecosystems/gemHostProbe.js +301 -0
- package/lib/ecosystems/golem.js +3 -8
- package/lib/ecosystems/gradleutils.js +1909 -229
- package/lib/ecosystems/jsEvidence.js +90 -38
- package/lib/ecosystems/kosi.js +3 -5
- package/lib/ecosystems/npmVersionResolution.js +376 -0
- package/lib/ecosystems/parsers-bazel.js +107 -6
- package/lib/ecosystems/parsers-js.js +505 -22
- package/lib/ecosystems/parsers-misc.js +209 -20
- package/lib/ecosystems/parsers-python.js +178 -30
- package/lib/ecosystems/parsers-rust.js +117 -15
- package/lib/ecosystems/pythonutils.js +128 -2
- package/lib/ecosystems/remote/huggingface.js +22 -0
- package/lib/ecosystems/rubyutils.js +538 -31
- package/lib/ecosystems/rusi.js +2 -4
- package/lib/ecosystems/scalacliutils.js +2 -0
- package/lib/ecosystems/scalasem.js +798 -152
- package/lib/ecosystems/vendoredCode.js +237 -3
- package/lib/ecosystems/venvProbe.js +360 -0
- package/lib/evinser/evinser.js +536 -71
- package/lib/evinser/scalasem.js +5 -1
- package/lib/helpers/agenticToolutils.js +525 -94
- package/lib/helpers/bomSigner.js +43 -9
- package/lib/helpers/jssSigner.js +1276 -0
- package/lib/helpers/vsixutils.js +1574 -315
- package/lib/inventory/agentBlueprint.js +193 -0
- package/lib/inventory/agentToolNames.js +145 -0
- package/lib/inventory/aiCollector.js +153 -7
- package/lib/inventory/aiInventory.js +44 -8
- package/lib/inventory/aiProviders.js +324 -0
- package/lib/inventory/atomUtils.js +77 -0
- package/lib/inventory/bomUtils.js +8 -1
- package/lib/inventory/brotliDecoder.js +142 -0
- package/lib/inventory/buildToolRateLimit.js +1 -1
- package/lib/inventory/cbomutils.js +56 -7
- package/lib/inventory/ciParsers/githubActionsLock.js +821 -0
- package/lib/inventory/citations.js +31 -2
- package/lib/inventory/communityAiConfigParser.js +978 -80
- package/lib/inventory/cyclonedx20.js +152 -0
- package/lib/inventory/cyclonedx20Common.js +286 -0
- package/lib/inventory/cyclonedx20Derived.js +159 -0
- package/lib/inventory/cyclonedx20Parties.js +552 -0
- package/lib/inventory/cyclonedx20Read.js +768 -0
- package/lib/inventory/cyclonedx20ReadCommon.js +374 -0
- package/lib/inventory/cyclonedx20ReadComponents.js +692 -0
- package/lib/inventory/cyclonedx20ReadContext.js +380 -0
- package/lib/inventory/cyclonedx20ReadEvidence.js +466 -0
- package/lib/inventory/cyclonedx20ReadSections.js +599 -0
- package/lib/inventory/cyclonedx20Render.js +766 -0
- package/lib/inventory/cyclonedx20RenderComponents.js +716 -0
- package/lib/inventory/cyclonedx20RenderDefinitions.js +405 -0
- package/lib/inventory/cyclonedx20RenderEvidence.js +726 -0
- package/lib/inventory/cyclonedx20RenderHardware.js +203 -0
- package/lib/inventory/cyclonedx20RenderPatents.js +174 -0
- package/lib/inventory/cyclonedx20RenderRefIds.js +314 -0
- package/lib/inventory/cyclonedx20RenderSections.js +499 -0
- package/lib/inventory/cyclonedx20Tables.js +594 -0
- package/lib/inventory/deps.js +141 -13
- package/lib/inventory/dosai.js +375 -6
- package/lib/inventory/dosaiParsers.js +3 -6
- package/lib/inventory/dotnetRuntime.js +367 -0
- package/lib/inventory/ecosystemFormulationParsers.js +979 -0
- package/lib/inventory/envcontext.js +436 -48
- package/lib/inventory/evidenceUtils.js +13 -1
- package/lib/inventory/fetchBatch.js +1 -1
- package/lib/inventory/formulationParsers.js +124 -14
- package/lib/inventory/gtfobins.js +13 -0
- package/lib/inventory/hbom.js +45 -6
- package/lib/inventory/hbomLoader.js +166 -0
- package/lib/inventory/hostRuntimeProbe.js +686 -0
- package/lib/inventory/jvmLocalRepos.js +9 -2
- package/lib/inventory/jvmToolEnv.js +29 -0
- package/lib/inventory/licenseEnhancer.js +12 -0
- package/lib/inventory/mavenCentralMirror.js +534 -0
- package/lib/inventory/mcpConfigParser.js +5 -0
- package/lib/inventory/nodeBuildInfo.js +218 -0
- package/lib/inventory/nodeHostProbe.js +202 -0
- package/lib/inventory/occurrenceKey.js +90 -0
- package/lib/inventory/osPackageResolver.js +182 -0
- package/lib/inventory/phpBuildInfo.js +10 -59
- package/lib/inventory/phpHostProbe.js +32 -488
- package/lib/inventory/pqcMigration.js +426 -0
- package/lib/inventory/rubyBuildInfo.js +972 -0
- package/lib/inventory/rubyHostProbe.js +218 -0
- package/lib/inventory/rustFormulationParser.js +21 -10
- package/lib/inventory/scalaCoords.js +4 -3
- package/lib/inventory/scalaDedupe.js +440 -0
- package/lib/inventory/source.js +114 -8
- package/lib/managers/binary.js +337 -3
- package/lib/managers/docker.js +79 -0
- package/lib/parsers/huggingfaceManifest.js +9 -1
- package/lib/parsers/huggingfaceUtils.js +18 -0
- package/lib/parsers/kiroPermissions.js +166 -0
- package/lib/parsers/largeJson.js +28 -11
- package/lib/parsers/vscodeExtensionId.js +183 -0
- package/lib/server/server.js +48 -35
- package/lib/stages/postgen/postgen.js +41 -1
- package/lib/stages/postgen/ruleEngine.js +13 -5
- package/lib/stages/postgen/specVersionCompat.js +76 -0
- package/lib/stages/pregen/envAudit.js +1 -0
- package/lib/stages/pregen/pregen.js +114 -57
- package/lib/validator/bomValidator.js +14 -2
- package/lib/validator/complianceEngine.js +30 -3
- package/lib/validator/complianceRules.js +1416 -4
- package/lib/validator/generated/validate-1.6.mjs +1 -1
- package/lib/validator/generated/validate-1.7.mjs +1 -1
- package/lib/validator/generated/validate-2.0.mjs +57554 -13851
- package/lib/validator/index.js +49 -8
- package/lib/validator/reporters/json.js +6 -0
- package/package.json +11 -10
- package/types/bin/repl.d.ts.map +1 -1
- package/types/lib/audit/index.d.ts +6 -2
- package/types/lib/audit/index.d.ts.map +1 -1
- package/types/lib/cli/bomAssembly.d.ts +29 -1
- package/types/lib/cli/bomAssembly.d.ts.map +1 -1
- package/types/lib/cli/cliOptions.d.ts +6 -0
- package/types/lib/cli/cliOptions.d.ts.map +1 -1
- package/types/lib/cli/index.d.ts.map +1 -1
- package/types/lib/cli/jsBom.d.ts +3 -18
- package/types/lib/cli/jsBom.d.ts.map +1 -1
- package/types/lib/cli/jvmBom.d.ts +15 -0
- package/types/lib/cli/jvmBom.d.ts.map +1 -1
- package/types/lib/cli/managedBom.d.ts.map +1 -1
- package/types/lib/cli/nativeBom.d.ts.map +1 -1
- package/types/lib/core/boundedFile.d.ts +100 -0
- package/types/lib/core/boundedFile.d.ts.map +1 -0
- package/types/lib/core/brotliProbe.d.ts +37 -0
- package/types/lib/core/brotliProbe.d.ts.map +1 -0
- package/types/lib/core/env.d.ts +14 -0
- package/types/lib/core/env.d.ts.map +1 -1
- package/types/lib/core/fs.d.ts +4 -0
- package/types/lib/core/fs.d.ts.map +1 -1
- package/types/lib/core/globPatterns.d.ts +70 -0
- package/types/lib/core/globPatterns.d.ts.map +1 -0
- package/types/lib/core/httpClient.d.ts +24 -0
- package/types/lib/core/httpClient.d.ts.map +1 -1
- package/types/lib/core/lockPaths.d.ts +19 -0
- package/types/lib/core/lockPaths.d.ts.map +1 -0
- package/types/lib/core/paths.d.ts +9 -0
- package/types/lib/core/paths.d.ts.map +1 -1
- package/types/lib/core/processTree.d.ts +17 -4
- package/types/lib/core/processTree.d.ts.map +1 -1
- package/types/lib/core/projectConfig.d.ts +47 -8
- package/types/lib/core/projectConfig.d.ts.map +1 -1
- package/types/lib/core/toolRegistry.d.ts +36 -0
- package/types/lib/core/toolRegistry.d.ts.map +1 -0
- package/types/lib/ecosystems/cppEvidence.d.ts +40 -13
- package/types/lib/ecosystems/cppEvidence.d.ts.map +1 -1
- package/types/lib/ecosystems/cppIncludeResolver.d.ts +2 -1
- package/types/lib/ecosystems/cppIncludeResolver.d.ts.map +1 -1
- package/types/lib/ecosystems/ecosystems.d.ts.map +1 -1
- package/types/lib/ecosystems/gemHostProbe.d.ts +28 -0
- package/types/lib/ecosystems/gemHostProbe.d.ts.map +1 -0
- package/types/lib/ecosystems/golem.d.ts.map +1 -1
- package/types/lib/ecosystems/gradleutils.d.ts +294 -20
- package/types/lib/ecosystems/gradleutils.d.ts.map +1 -1
- package/types/lib/ecosystems/jsEvidence.d.ts +14 -1
- package/types/lib/ecosystems/jsEvidence.d.ts.map +1 -1
- package/types/lib/ecosystems/kosi.d.ts.map +1 -1
- package/types/lib/ecosystems/npmVersionResolution.d.ts +119 -0
- package/types/lib/ecosystems/npmVersionResolution.d.ts.map +1 -0
- package/types/lib/ecosystems/parsers-bazel.d.ts.map +1 -1
- package/types/lib/ecosystems/parsers-js.d.ts +17 -20
- package/types/lib/ecosystems/parsers-js.d.ts.map +1 -1
- package/types/lib/ecosystems/parsers-misc.d.ts +19 -0
- package/types/lib/ecosystems/parsers-misc.d.ts.map +1 -1
- package/types/lib/ecosystems/parsers-python.d.ts +10 -0
- package/types/lib/ecosystems/parsers-python.d.ts.map +1 -1
- package/types/lib/ecosystems/parsers-rust.d.ts.map +1 -1
- package/types/lib/ecosystems/pythonutils.d.ts +19 -1
- package/types/lib/ecosystems/pythonutils.d.ts.map +1 -1
- package/types/lib/ecosystems/remote/huggingface.d.ts.map +1 -1
- package/types/lib/ecosystems/rubyutils.d.ts +144 -12
- package/types/lib/ecosystems/rubyutils.d.ts.map +1 -1
- package/types/lib/ecosystems/rusi.d.ts.map +1 -1
- package/types/lib/ecosystems/scalacliutils.d.ts.map +1 -1
- package/types/lib/ecosystems/scalasem.d.ts +58 -16
- package/types/lib/ecosystems/scalasem.d.ts.map +1 -1
- package/types/lib/ecosystems/vendoredCode.d.ts +26 -0
- package/types/lib/ecosystems/vendoredCode.d.ts.map +1 -1
- package/types/lib/ecosystems/venvProbe.d.ts +40 -0
- package/types/lib/ecosystems/venvProbe.d.ts.map +1 -0
- package/types/lib/evinser/evinser.d.ts +120 -13
- package/types/lib/evinser/evinser.d.ts.map +1 -1
- package/types/lib/evinser/scalasem.d.ts.map +1 -1
- package/types/lib/helpers/agenticToolutils.d.ts +53 -19
- package/types/lib/helpers/agenticToolutils.d.ts.map +1 -1
- package/types/lib/helpers/bomSigner.d.ts +20 -3
- package/types/lib/helpers/bomSigner.d.ts.map +1 -1
- package/types/lib/helpers/jssSigner.d.ts +288 -0
- package/types/lib/helpers/jssSigner.d.ts.map +1 -0
- package/types/lib/helpers/vsixutils.d.ts +303 -19
- package/types/lib/helpers/vsixutils.d.ts.map +1 -1
- package/types/lib/inventory/agentBlueprint.d.ts +70 -0
- package/types/lib/inventory/agentBlueprint.d.ts.map +1 -0
- package/types/lib/inventory/agentToolNames.d.ts +51 -0
- package/types/lib/inventory/agentToolNames.d.ts.map +1 -0
- package/types/lib/inventory/aiCollector.d.ts.map +1 -1
- package/types/lib/inventory/aiInventory.d.ts.map +1 -1
- package/types/lib/inventory/aiProviders.d.ts +85 -0
- package/types/lib/inventory/aiProviders.d.ts.map +1 -0
- package/types/lib/inventory/atomUtils.d.ts +19 -0
- package/types/lib/inventory/atomUtils.d.ts.map +1 -1
- package/types/lib/inventory/bomUtils.d.ts.map +1 -1
- package/types/lib/inventory/brotliDecoder.d.ts +58 -0
- package/types/lib/inventory/brotliDecoder.d.ts.map +1 -0
- package/types/lib/inventory/cbomutils.d.ts +17 -0
- package/types/lib/inventory/cbomutils.d.ts.map +1 -1
- package/types/lib/inventory/ciParsers/githubActionsLock.d.ts +101 -0
- package/types/lib/inventory/ciParsers/githubActionsLock.d.ts.map +1 -0
- package/types/lib/inventory/citations.d.ts +5 -0
- package/types/lib/inventory/citations.d.ts.map +1 -1
- package/types/lib/inventory/communityAiConfigParser.d.ts.map +1 -1
- package/types/lib/inventory/cyclonedx20.d.ts +99 -0
- package/types/lib/inventory/cyclonedx20.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20Common.d.ts +102 -0
- package/types/lib/inventory/cyclonedx20Common.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20Derived.d.ts +74 -0
- package/types/lib/inventory/cyclonedx20Derived.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20Parties.d.ts +91 -0
- package/types/lib/inventory/cyclonedx20Parties.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20Read.d.ts +51 -0
- package/types/lib/inventory/cyclonedx20Read.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20ReadCommon.d.ts +69 -0
- package/types/lib/inventory/cyclonedx20ReadCommon.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20ReadComponents.d.ts +77 -0
- package/types/lib/inventory/cyclonedx20ReadComponents.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20ReadContext.d.ts +118 -0
- package/types/lib/inventory/cyclonedx20ReadContext.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20ReadEvidence.d.ts +40 -0
- package/types/lib/inventory/cyclonedx20ReadEvidence.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20ReadSections.d.ts +45 -0
- package/types/lib/inventory/cyclonedx20ReadSections.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20Render.d.ts +53 -0
- package/types/lib/inventory/cyclonedx20Render.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20RenderComponents.d.ts +73 -0
- package/types/lib/inventory/cyclonedx20RenderComponents.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20RenderDefinitions.d.ts +29 -0
- package/types/lib/inventory/cyclonedx20RenderDefinitions.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20RenderEvidence.d.ts +110 -0
- package/types/lib/inventory/cyclonedx20RenderEvidence.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20RenderHardware.d.ts +42 -0
- package/types/lib/inventory/cyclonedx20RenderHardware.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20RenderPatents.d.ts +26 -0
- package/types/lib/inventory/cyclonedx20RenderPatents.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20RenderRefIds.d.ts +55 -0
- package/types/lib/inventory/cyclonedx20RenderRefIds.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20RenderSections.d.ts +45 -0
- package/types/lib/inventory/cyclonedx20RenderSections.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20Tables.d.ts +134 -0
- package/types/lib/inventory/cyclonedx20Tables.d.ts.map +1 -0
- package/types/lib/inventory/deps.d.ts +35 -2
- package/types/lib/inventory/deps.d.ts.map +1 -1
- package/types/lib/inventory/dosai.d.ts +36 -1
- package/types/lib/inventory/dosai.d.ts.map +1 -1
- package/types/lib/inventory/dosaiParsers.d.ts.map +1 -1
- package/types/lib/inventory/dotnetRuntime.d.ts +91 -0
- package/types/lib/inventory/dotnetRuntime.d.ts.map +1 -0
- package/types/lib/inventory/ecosystemFormulationParsers.d.ts +73 -0
- package/types/lib/inventory/ecosystemFormulationParsers.d.ts.map +1 -0
- package/types/lib/inventory/envcontext.d.ts +74 -12
- package/types/lib/inventory/envcontext.d.ts.map +1 -1
- package/types/lib/inventory/evidenceUtils.d.ts.map +1 -1
- package/types/lib/inventory/formulationParsers.d.ts.map +1 -1
- package/types/lib/inventory/gtfobins.d.ts.map +1 -1
- package/types/lib/inventory/hbom.d.ts +11 -0
- package/types/lib/inventory/hbom.d.ts.map +1 -1
- package/types/lib/inventory/hbomLoader.d.ts +54 -0
- package/types/lib/inventory/hbomLoader.d.ts.map +1 -1
- package/types/lib/inventory/hostRuntimeProbe.d.ts +44 -0
- package/types/lib/inventory/hostRuntimeProbe.d.ts.map +1 -0
- package/types/lib/inventory/jvmLocalRepos.d.ts +5 -1
- package/types/lib/inventory/jvmLocalRepos.d.ts.map +1 -1
- package/types/lib/inventory/jvmToolEnv.d.ts +12 -0
- package/types/lib/inventory/jvmToolEnv.d.ts.map +1 -1
- package/types/lib/inventory/licenseEnhancer.d.ts.map +1 -1
- package/types/lib/inventory/mavenCentralMirror.d.ts +170 -0
- package/types/lib/inventory/mavenCentralMirror.d.ts.map +1 -0
- package/types/lib/inventory/mcpConfigParser.d.ts.map +1 -1
- package/types/lib/inventory/nodeBuildInfo.d.ts +95 -0
- package/types/lib/inventory/nodeBuildInfo.d.ts.map +1 -0
- package/types/lib/inventory/nodeHostProbe.d.ts +15 -0
- package/types/lib/inventory/nodeHostProbe.d.ts.map +1 -0
- package/types/lib/inventory/occurrenceKey.d.ts +52 -0
- package/types/lib/inventory/occurrenceKey.d.ts.map +1 -0
- package/types/lib/inventory/osPackageResolver.d.ts +38 -0
- package/types/lib/inventory/osPackageResolver.d.ts.map +1 -1
- package/types/lib/inventory/phpBuildInfo.d.ts.map +1 -1
- package/types/lib/inventory/phpHostProbe.d.ts.map +1 -1
- package/types/lib/inventory/pqcMigration.d.ts +84 -0
- package/types/lib/inventory/pqcMigration.d.ts.map +1 -0
- package/types/lib/inventory/rubyBuildInfo.d.ts +271 -0
- package/types/lib/inventory/rubyBuildInfo.d.ts.map +1 -0
- package/types/lib/inventory/rubyHostProbe.d.ts +47 -0
- package/types/lib/inventory/rubyHostProbe.d.ts.map +1 -0
- package/types/lib/inventory/rustFormulationParser.d.ts +7 -2
- package/types/lib/inventory/rustFormulationParser.d.ts.map +1 -1
- package/types/lib/inventory/scalaCoords.d.ts.map +1 -1
- package/types/lib/inventory/scalaDedupe.d.ts +43 -0
- package/types/lib/inventory/scalaDedupe.d.ts.map +1 -0
- package/types/lib/inventory/source.d.ts +25 -0
- package/types/lib/inventory/source.d.ts.map +1 -1
- package/types/lib/managers/binary.d.ts.map +1 -1
- package/types/lib/managers/docker.d.ts +12 -0
- package/types/lib/managers/docker.d.ts.map +1 -1
- package/types/lib/parsers/huggingfaceManifest.d.ts +10 -1
- package/types/lib/parsers/huggingfaceManifest.d.ts.map +1 -1
- package/types/lib/parsers/huggingfaceUtils.d.ts +12 -0
- package/types/lib/parsers/huggingfaceUtils.d.ts.map +1 -1
- package/types/lib/parsers/kiroPermissions.d.ts +62 -0
- package/types/lib/parsers/kiroPermissions.d.ts.map +1 -0
- package/types/lib/parsers/largeJson.d.ts +4 -3
- package/types/lib/parsers/largeJson.d.ts.map +1 -1
- package/types/lib/parsers/vscodeExtensionId.d.ts +48 -0
- package/types/lib/parsers/vscodeExtensionId.d.ts.map +1 -0
- package/types/lib/server/server.d.ts.map +1 -1
- package/types/lib/stages/postgen/postgen.d.ts +7 -0
- package/types/lib/stages/postgen/postgen.d.ts.map +1 -1
- package/types/lib/stages/postgen/ruleEngine.d.ts.map +1 -1
- package/types/lib/stages/postgen/specVersionCompat.d.ts +25 -0
- package/types/lib/stages/postgen/specVersionCompat.d.ts.map +1 -1
- package/types/lib/stages/pregen/envAudit.d.ts.map +1 -1
- package/types/lib/stages/pregen/pregen.d.ts +12 -8
- package/types/lib/stages/pregen/pregen.d.ts.map +1 -1
- package/types/lib/validator/bomValidator.d.ts +5 -1
- package/types/lib/validator/bomValidator.d.ts.map +1 -1
- package/types/lib/validator/complianceEngine.d.ts +4 -4
- package/types/lib/validator/complianceEngine.d.ts.map +1 -1
- package/types/lib/validator/complianceRules.d.ts +14 -2
- package/types/lib/validator/complianceRules.d.ts.map +1 -1
- package/types/lib/validator/index.d.ts +10 -0
- package/types/lib/validator/index.d.ts.map +1 -1
- package/types/lib/validator/reporters/json.d.ts.map +1 -1
package/lib/inventory/dosai.js
CHANGED
|
@@ -2,12 +2,21 @@ import { Buffer } from "node:buffer";
|
|
|
2
2
|
import {
|
|
3
3
|
closeSync,
|
|
4
4
|
openSync,
|
|
5
|
+
readdirSync,
|
|
5
6
|
readFileSync,
|
|
6
7
|
readSync,
|
|
7
8
|
realpathSync,
|
|
8
9
|
statSync,
|
|
9
10
|
} from "node:fs";
|
|
10
|
-
import {
|
|
11
|
+
import {
|
|
12
|
+
basename,
|
|
13
|
+
delimiter,
|
|
14
|
+
extname,
|
|
15
|
+
isAbsolute,
|
|
16
|
+
join,
|
|
17
|
+
relative,
|
|
18
|
+
resolve,
|
|
19
|
+
} from "node:path";
|
|
11
20
|
import process from "node:process";
|
|
12
21
|
|
|
13
22
|
import { DEBUG_MODE, readEnvironmentVariable } from "../core/activity.js";
|
|
@@ -24,12 +33,22 @@ import {
|
|
|
24
33
|
} from "../core/fs.js";
|
|
25
34
|
import { formatDuration, reapProcessTree } from "../core/processTree.js";
|
|
26
35
|
import { encodeUriReference } from "../core/propertySanitizer.js";
|
|
36
|
+
import {
|
|
37
|
+
normalizeHuggingFaceReference,
|
|
38
|
+
toHuggingFaceSupplier,
|
|
39
|
+
} from "../parsers/huggingfaceUtils.js";
|
|
27
40
|
import {
|
|
28
41
|
indexJsonObject,
|
|
29
42
|
MAX_JSON_TEXT_BYTES,
|
|
30
43
|
readJsonMember,
|
|
31
44
|
readJsonRange,
|
|
32
45
|
} from "../parsers/largeJson.js";
|
|
46
|
+
import {
|
|
47
|
+
modelCreatorEntity,
|
|
48
|
+
modelCreatorFromOrganization,
|
|
49
|
+
resolveModelCreator,
|
|
50
|
+
} from "./aiProviders.js";
|
|
51
|
+
import { isPathExcludedByGlobPatterns } from "./atomUtils.js";
|
|
33
52
|
import {
|
|
34
53
|
addDosaiSetValue,
|
|
35
54
|
buildDosaiPurlAliasMap,
|
|
@@ -712,6 +731,198 @@ export function dosaiSectionsCdxgenReads(omittedSections) {
|
|
|
712
731
|
);
|
|
713
732
|
}
|
|
714
733
|
|
|
734
|
+
// The files dosai reads from a source tree whose changes make an existing
|
|
735
|
+
// methods slice stale: the C#, VB, and F# sources it analyses, the project
|
|
736
|
+
// and MSBuild files that shape the analysis, and the Razor and WebForms
|
|
737
|
+
// templates whose call sites it maps from build output. packages.config is
|
|
738
|
+
// read by cdxgen's own dotnet analysis and holds the same package list a
|
|
739
|
+
// csproj does, so a change to it can change the slice too. Solution files are
|
|
740
|
+
// left out: dosai opens them only to budget its restore runs, and a changed
|
|
741
|
+
// solution does not change the occurrences a slice holds.
|
|
742
|
+
const DOSAI_SLICE_SOURCE_EXTENSIONS = new Set([
|
|
743
|
+
".cs",
|
|
744
|
+
".cshtml",
|
|
745
|
+
".csproj",
|
|
746
|
+
".fs",
|
|
747
|
+
".fsi",
|
|
748
|
+
".fsproj",
|
|
749
|
+
".fsx",
|
|
750
|
+
".props",
|
|
751
|
+
".razor",
|
|
752
|
+
".targets",
|
|
753
|
+
".vb",
|
|
754
|
+
".vbproj",
|
|
755
|
+
]);
|
|
756
|
+
const DOSAI_SLICE_SOURCE_FILES = new Set(["packages.config"]);
|
|
757
|
+
|
|
758
|
+
// Directories that hold nothing dosai analyses. Its own tree walk skips the
|
|
759
|
+
// build-output directories (obj for every file, bin for sources) and the
|
|
760
|
+
// package and version-control directories, so a build cannot make a slice
|
|
761
|
+
// stale and a dependency tree cannot slow the check down.
|
|
762
|
+
const DOSAI_SLICE_SOURCE_SKIP_DIRS = new Set([
|
|
763
|
+
".git",
|
|
764
|
+
"bin",
|
|
765
|
+
"node_modules",
|
|
766
|
+
"obj",
|
|
767
|
+
]);
|
|
768
|
+
|
|
769
|
+
// The tree walk is bounded so a pathological tree (a symlink farm, or entries
|
|
770
|
+
// that appear faster than the walk reads them) cannot keep a scan from
|
|
771
|
+
// finishing. A walk that reaches a bound leaves freshness unknown, and the
|
|
772
|
+
// callers regenerate the slice, which is the run a fresh scan pays anyway.
|
|
773
|
+
const DOSAI_FRESHNESS_MAX_DIRS = 50_000;
|
|
774
|
+
const DOSAI_FRESHNESS_MAX_FILES = 200_000;
|
|
775
|
+
|
|
776
|
+
/**
|
|
777
|
+
* The newest mtime among the source files dosai analyses under a directory.
|
|
778
|
+
*
|
|
779
|
+
* The walk is deterministic and bounded: directory entries are read and then
|
|
780
|
+
* visited depth-first in sorted name order, symlinked directories are not
|
|
781
|
+
* followed, and counts of visited directories and analysed files cap the
|
|
782
|
+
* work. Excluded paths are pruned rather than filtered, so nothing beneath an
|
|
783
|
+
* excluded directory is read.
|
|
784
|
+
*
|
|
785
|
+
* @param {string} projectDir Absolute directory dosai analyses
|
|
786
|
+
* @param {string[]} excludePatterns Exclude globs relative to projectDir
|
|
787
|
+
* @returns {{mtimeMs: number|undefined, complete: boolean}} The newest mtime seen (undefined when no analysed file was found), and whether the walk finished, which is false for an unreadable directory or file, or a tree past the bounds
|
|
788
|
+
*/
|
|
789
|
+
function newestDosaiSourceMtimeSync(projectDir, excludePatterns) {
|
|
790
|
+
const newest = { mtimeMs: undefined, complete: true };
|
|
791
|
+
const stack = [[projectDir, ""]];
|
|
792
|
+
let dirsVisited = 0;
|
|
793
|
+
let filesVisited = 0;
|
|
794
|
+
while (newest.complete && stack.length) {
|
|
795
|
+
if (dirsVisited++ >= DOSAI_FRESHNESS_MAX_DIRS) {
|
|
796
|
+
newest.complete = false;
|
|
797
|
+
break;
|
|
798
|
+
}
|
|
799
|
+
const [dir, relDir] = stack.pop();
|
|
800
|
+
let entries;
|
|
801
|
+
try {
|
|
802
|
+
entries = readdirSync(dir, { withFileTypes: true });
|
|
803
|
+
} catch (_err) {
|
|
804
|
+
newest.complete = false;
|
|
805
|
+
break;
|
|
806
|
+
}
|
|
807
|
+
entries.sort((a, b) => (a.name < b.name ? -1 : a.name > b.name ? 1 : 0));
|
|
808
|
+
for (const entry of entries) {
|
|
809
|
+
const relPath = relDir ? `${relDir}/${entry.name}` : entry.name;
|
|
810
|
+
if (entry.isDirectory()) {
|
|
811
|
+
if (
|
|
812
|
+
!DOSAI_SLICE_SOURCE_SKIP_DIRS.has(entry.name.toLowerCase()) &&
|
|
813
|
+
!(
|
|
814
|
+
excludePatterns.length &&
|
|
815
|
+
isPathExcludedByGlobPatterns(relPath, excludePatterns)
|
|
816
|
+
)
|
|
817
|
+
) {
|
|
818
|
+
stack.push([join(dir, entry.name), relPath]);
|
|
819
|
+
}
|
|
820
|
+
continue;
|
|
821
|
+
}
|
|
822
|
+
if (
|
|
823
|
+
!DOSAI_SLICE_SOURCE_EXTENSIONS.has(extname(entry.name).toLowerCase()) &&
|
|
824
|
+
!DOSAI_SLICE_SOURCE_FILES.has(entry.name.toLowerCase())
|
|
825
|
+
) {
|
|
826
|
+
continue;
|
|
827
|
+
}
|
|
828
|
+
if (filesVisited++ >= DOSAI_FRESHNESS_MAX_FILES) {
|
|
829
|
+
newest.complete = false;
|
|
830
|
+
break;
|
|
831
|
+
}
|
|
832
|
+
try {
|
|
833
|
+
// statSync follows a symlink to the source it points at, which is
|
|
834
|
+
// the file dosai reads.
|
|
835
|
+
const mtimeMs = statSync(join(dir, entry.name)).mtimeMs;
|
|
836
|
+
if (newest.mtimeMs === undefined || mtimeMs > newest.mtimeMs) {
|
|
837
|
+
newest.mtimeMs = mtimeMs;
|
|
838
|
+
}
|
|
839
|
+
} catch (_err) {
|
|
840
|
+
newest.complete = false;
|
|
841
|
+
break;
|
|
842
|
+
}
|
|
843
|
+
}
|
|
844
|
+
}
|
|
845
|
+
return newest;
|
|
846
|
+
}
|
|
847
|
+
|
|
848
|
+
/**
|
|
849
|
+
* The cdxgen exclude patterns that apply under a directory, as globs relative
|
|
850
|
+
* to it.
|
|
851
|
+
*
|
|
852
|
+
* The patterns are matched the way the atom evidence filter matches
|
|
853
|
+
* `options.exclude`: a relative pattern matches at any depth, and an absolute
|
|
854
|
+
* pattern is anchored to the scanned directory, which for the walk means the
|
|
855
|
+
* patterns that sit beneath it are rebased to relative ones. Patterns that
|
|
856
|
+
* fall outside the directory are dropped.
|
|
857
|
+
*
|
|
858
|
+
* @param {string[]} excludes cdxgen exclude globs
|
|
859
|
+
* @param {string} projectDir Absolute directory dosai analyses
|
|
860
|
+
* @returns {string[]} Exclude globs relative to projectDir
|
|
861
|
+
*/
|
|
862
|
+
function dosaiSourceExcludePatterns(excludes, projectDir) {
|
|
863
|
+
const rebased = [];
|
|
864
|
+
if (!Array.isArray(excludes)) {
|
|
865
|
+
return rebased;
|
|
866
|
+
}
|
|
867
|
+
for (const pattern of excludes) {
|
|
868
|
+
if (typeof pattern !== "string" || !pattern.trim()) {
|
|
869
|
+
continue;
|
|
870
|
+
}
|
|
871
|
+
// resolve() leaves a relative pattern where it was and turns an absolute
|
|
872
|
+
// one into a path the relative() call drops the scanned directory from.
|
|
873
|
+
const underRoot = resolve(projectDir, pattern);
|
|
874
|
+
const rel = relative(projectDir, underRoot);
|
|
875
|
+
if (rel && !rel.startsWith("..") && !isAbsolute(rel)) {
|
|
876
|
+
rebased.push(rel.replaceAll("\\", "/"));
|
|
877
|
+
}
|
|
878
|
+
}
|
|
879
|
+
return rebased;
|
|
880
|
+
}
|
|
881
|
+
|
|
882
|
+
/**
|
|
883
|
+
* Whether an existing dosai methods slice is newer than the sources it
|
|
884
|
+
* describes.
|
|
885
|
+
*
|
|
886
|
+
* A slice written by an earlier scan holds the occurrences of the sources as
|
|
887
|
+
* they were then, so a slice that predates an edit must be regenerated rather
|
|
888
|
+
* than reused: reusing one keeps occurrences of call sites that no longer
|
|
889
|
+
* exist (issue 4675). The slice is fresh only when its mtime is not older
|
|
890
|
+
* than the newest mtime among the files dosai analyses under the directory.
|
|
891
|
+
* A missing slice, a slice whose mtime cannot be read, a source that cannot
|
|
892
|
+
* be stat-ed, and a tree that exceeds the walk bounds all count as stale: the
|
|
893
|
+
* callers regenerate the slice, which is the run a fresh scan pays anyway.
|
|
894
|
+
*
|
|
895
|
+
* @param {string} slicesFile Candidate dosai methods slice
|
|
896
|
+
* @param {string} projectDir Directory dosai analyses
|
|
897
|
+
* @param {Object} [options] Scan options; options.exclude prunes the walk
|
|
898
|
+
* @returns {boolean} True when the slice is newer than every source it describes
|
|
899
|
+
*/
|
|
900
|
+
export function dosaiSlicesFileIsFresh(slicesFile, projectDir, options = {}) {
|
|
901
|
+
if (!slicesFile || !projectDir || !safeExistsSync(slicesFile)) {
|
|
902
|
+
return false;
|
|
903
|
+
}
|
|
904
|
+
let sliceMtimeMs;
|
|
905
|
+
try {
|
|
906
|
+
sliceMtimeMs = statSync(slicesFile).mtimeMs;
|
|
907
|
+
} catch (_err) {
|
|
908
|
+
return false;
|
|
909
|
+
}
|
|
910
|
+
const excludePatterns = dosaiSourceExcludePatterns(
|
|
911
|
+
options.exclude,
|
|
912
|
+
resolve(projectDir),
|
|
913
|
+
);
|
|
914
|
+
const newest = newestDosaiSourceMtimeSync(
|
|
915
|
+
resolve(projectDir),
|
|
916
|
+
excludePatterns,
|
|
917
|
+
);
|
|
918
|
+
if (!newest.complete) {
|
|
919
|
+
return false;
|
|
920
|
+
}
|
|
921
|
+
// A directory with no file dosai analyses holds nothing that can go stale,
|
|
922
|
+
// so the slice counts as fresh.
|
|
923
|
+
return newest.mtimeMs === undefined || sliceMtimeMs >= newest.mtimeMs;
|
|
924
|
+
}
|
|
925
|
+
|
|
715
926
|
// The file each report returned by readDosaiReport came from, and whether it
|
|
716
927
|
// was trimmed to what cdxgen reads. persistDosaiSemanticsReport copies the
|
|
717
928
|
// file rather than re-serialising a trimmed or oversized report.
|
|
@@ -727,6 +938,105 @@ function referencedIds(entries, field) {
|
|
|
727
938
|
return ids;
|
|
728
939
|
}
|
|
729
940
|
|
|
941
|
+
// The fields of a MethodCalls row cdxgen reads: the component it names (Purl
|
|
942
|
+
// or Module), where the call site is (Path, FileName, LineNumber) and what it
|
|
943
|
+
// calls (ClassName, CalledMethod). Everything else a report row carries -
|
|
944
|
+
// arguments, evidence kinds, caller identities - no cdxgen consumer reads,
|
|
945
|
+
// and a report with millions of calls cannot afford to hold them.
|
|
946
|
+
const DOSAI_METHOD_CALL_FIELDS = [
|
|
947
|
+
"Purl",
|
|
948
|
+
"Module",
|
|
949
|
+
"Path",
|
|
950
|
+
"FileName",
|
|
951
|
+
"LineNumber",
|
|
952
|
+
"ClassName",
|
|
953
|
+
"CalledMethod",
|
|
954
|
+
];
|
|
955
|
+
|
|
956
|
+
/**
|
|
957
|
+
* The largest number of distinct method calls cdxgen keeps from one report.
|
|
958
|
+
*
|
|
959
|
+
* Reports in the millions of calls repeat the same call sites heavily, so the
|
|
960
|
+
* aggregated rows stay far below this; the cap exists so a report whose calls
|
|
961
|
+
* are all distinct degrades the occurrence evidence instead of the process.
|
|
962
|
+
*
|
|
963
|
+
* @returns {number} Cap on distinct kept rows
|
|
964
|
+
*/
|
|
965
|
+
export function maxDosaiMethodCalls() {
|
|
966
|
+
const configured = Number.parseInt(
|
|
967
|
+
readEnvironmentVariable("CDXGEN_DOSAI_MAX_METHOD_CALLS") || "",
|
|
968
|
+
10,
|
|
969
|
+
);
|
|
970
|
+
if (Number.isInteger(configured) && configured > 0) {
|
|
971
|
+
return configured;
|
|
972
|
+
}
|
|
973
|
+
return 1_000_000;
|
|
974
|
+
}
|
|
975
|
+
|
|
976
|
+
/**
|
|
977
|
+
* Build the `map` that turns report MethodCalls rows into what cdxgen keeps:
|
|
978
|
+
* rows the caller rejects are dropped, the rest are reduced to
|
|
979
|
+
* {@link DOSAI_METHOD_CALL_FIELDS} and aggregated by those fields, so a call
|
|
980
|
+
* site reached a million times is held once with a `CallCount`. Past
|
|
981
|
+
* {@link maxDosaiMethodCalls} distinct rows, further rows are dropped and one
|
|
982
|
+
* warning names the cap.
|
|
983
|
+
*
|
|
984
|
+
* @param {string} reportFile Report the rows come from, named in the warning
|
|
985
|
+
* @param {Object} [options] Options
|
|
986
|
+
* @param {Function} [options.keepMethodCall] Predicate choosing the rows to keep
|
|
987
|
+
* @param {number} [options.maxMethodCalls] Cap override, for tests
|
|
988
|
+
* @returns {{map: Function, finish: Function}} The row mapper, and the
|
|
989
|
+
* `finish` that reports a cap reached
|
|
990
|
+
*/
|
|
991
|
+
function dosaiMethodCallCollector(reportFile, options = {}) {
|
|
992
|
+
const keep = options.keepMethodCall;
|
|
993
|
+
const max = options.maxMethodCalls ?? maxDosaiMethodCalls();
|
|
994
|
+
const keptByKey = new Map();
|
|
995
|
+
let dropped = 0;
|
|
996
|
+
return {
|
|
997
|
+
map(methodCall) {
|
|
998
|
+
if (keep && !keep(methodCall)) {
|
|
999
|
+
return undefined;
|
|
1000
|
+
}
|
|
1001
|
+
const compact = {};
|
|
1002
|
+
for (const field of DOSAI_METHOD_CALL_FIELDS) {
|
|
1003
|
+
if (methodCall?.[field] !== undefined) {
|
|
1004
|
+
compact[field] = methodCall[field];
|
|
1005
|
+
}
|
|
1006
|
+
}
|
|
1007
|
+
const key = DOSAI_METHOD_CALL_FIELDS.map((field) => compact[field]).join(
|
|
1008
|
+
"\u0000",
|
|
1009
|
+
);
|
|
1010
|
+
const kept = keptByKey.get(key);
|
|
1011
|
+
if (kept) {
|
|
1012
|
+
kept.CallCount = (kept.CallCount ?? 1) + 1;
|
|
1013
|
+
return undefined;
|
|
1014
|
+
}
|
|
1015
|
+
if (keptByKey.size >= max) {
|
|
1016
|
+
dropped++;
|
|
1017
|
+
return undefined;
|
|
1018
|
+
}
|
|
1019
|
+
keptByKey.set(key, compact);
|
|
1020
|
+
return compact;
|
|
1021
|
+
},
|
|
1022
|
+
finish() {
|
|
1023
|
+
if (!dropped) {
|
|
1024
|
+
return;
|
|
1025
|
+
}
|
|
1026
|
+
console.warn(
|
|
1027
|
+
`The dosai report "${reportFile}" holds more distinct method calls than cdxgen keeps (${max}); ${dropped} call sites were dropped, so occurrence evidence may be incomplete. Raise the cap with CDXGEN_DOSAI_MAX_METHOD_CALLS.`,
|
|
1028
|
+
);
|
|
1029
|
+
recordDegradation("dosai.method-calls-capped", {
|
|
1030
|
+
ecosystem: "csharp",
|
|
1031
|
+
tool: "dosai",
|
|
1032
|
+
impact: "components",
|
|
1033
|
+
command: reportFile,
|
|
1034
|
+
detail: `The dosai report holds more distinct method calls than the cap of ${max}, so ${dropped} call sites were dropped from the occurrence evidence.`,
|
|
1035
|
+
});
|
|
1036
|
+
},
|
|
1037
|
+
};
|
|
1038
|
+
}
|
|
1039
|
+
|
|
730
1040
|
function readDosaiReport(reportFile, options, readTrimmed) {
|
|
731
1041
|
if (!reportFile || !safeExistsSync(reportFile)) {
|
|
732
1042
|
return undefined;
|
|
@@ -761,7 +1071,13 @@ function readDosaiReport(reportFile, options, readTrimmed) {
|
|
|
761
1071
|
}
|
|
762
1072
|
return report;
|
|
763
1073
|
} catch (err) {
|
|
764
|
-
if (
|
|
1074
|
+
if (err instanceof RangeError) {
|
|
1075
|
+
// A heap or string limit is a report-size problem the user can act on,
|
|
1076
|
+
// unlike a malformed report, so it is named even without debug output.
|
|
1077
|
+
console.warn(
|
|
1078
|
+
`The dosai report "${reportFile}" is too large to read: ${err.message}. Raise the Node.js heap, for example NODE_OPTIONS="--max-old-space-size=8192", or write the report with dosai's --sections so it holds less.`,
|
|
1079
|
+
);
|
|
1080
|
+
} else if (DEBUG_MODE) {
|
|
765
1081
|
console.log(
|
|
766
1082
|
`Unable to read the dosai report "${reportFile}": ${err.message}`,
|
|
767
1083
|
);
|
|
@@ -776,25 +1092,34 @@ function readDosaiReport(reportFile, options, readTrimmed) {
|
|
|
776
1092
|
* A report that fits in one JavaScript string is parsed whole. A larger one is
|
|
777
1093
|
* read in bounded runs, keeping the requested sections, the CallGraph nodes and
|
|
778
1094
|
* edges that PackageReachability references, and the MethodCalls accepted by
|
|
779
|
-
* `keepMethodCall` (none when it is omitted).
|
|
1095
|
+
* `keepMethodCall` (none when it is omitted). A kept MethodCalls row is
|
|
1096
|
+
* reduced to the fields cdxgen reads and aggregated by them, so a call site
|
|
1097
|
+
* reached many times is held once with a `CallCount`; distinct rows past
|
|
1098
|
+
* {@link maxDosaiMethodCalls} are dropped with one warning. Nothing cdxgen
|
|
1099
|
+
* reads is lost.
|
|
780
1100
|
*
|
|
781
1101
|
* @param {string} reportFile Path to the dosai methods JSON
|
|
782
1102
|
* @param {Object} [options] Options
|
|
783
1103
|
* @param {string[]} [options.sections] Sections to keep from a large report (default: every section cdxgen reads)
|
|
784
1104
|
* @param {Function} [options.keepMethodCall] Predicate choosing the MethodCalls to keep from a large report
|
|
1105
|
+
* @param {number} [options.maxMethodCalls] Cap on distinct kept MethodCalls, for tests
|
|
785
1106
|
* @param {number} [options.maxTextBytes] Largest report parsed whole, for tests
|
|
786
1107
|
* @returns {Object|undefined} Parsed report, or undefined when missing or invalid
|
|
787
1108
|
*/
|
|
788
1109
|
export function readDosaiMethodsReport(reportFile, options = {}) {
|
|
789
1110
|
const sections = options.sections || DOSAI_METHODS_SECTIONS;
|
|
790
|
-
|
|
1111
|
+
const collector =
|
|
1112
|
+
sections.includes("MethodCalls") && options.keepMethodCall
|
|
1113
|
+
? dosaiMethodCallCollector(reportFile, options)
|
|
1114
|
+
: undefined;
|
|
1115
|
+
const report = readDosaiReport(reportFile, options, (report, read) => {
|
|
791
1116
|
for (const section of sections) {
|
|
792
1117
|
if (section !== "CallGraph" && section !== "MethodCalls") {
|
|
793
1118
|
read(section);
|
|
794
1119
|
}
|
|
795
1120
|
}
|
|
796
|
-
if (
|
|
797
|
-
read("MethodCalls", {
|
|
1121
|
+
if (collector) {
|
|
1122
|
+
read("MethodCalls", { map: collector.map });
|
|
798
1123
|
}
|
|
799
1124
|
if (sections.includes("CallGraph")) {
|
|
800
1125
|
// CallGraph precedes PackageReachability in the file, which is why the
|
|
@@ -809,6 +1134,26 @@ export function readDosaiMethodsReport(reportFile, options = {}) {
|
|
|
809
1134
|
});
|
|
810
1135
|
}
|
|
811
1136
|
});
|
|
1137
|
+
// A report parsed whole kept every row, as it always has: reduce them to
|
|
1138
|
+
// the fields cdxgen reads and aggregate repeats, without the caller's
|
|
1139
|
+
// predicate, which the whole parse has never applied. A report that took
|
|
1140
|
+
// the trimmed path already went through the collector above.
|
|
1141
|
+
if (report && !dosaiReportSources.get(report)?.trimmed) {
|
|
1142
|
+
const wholeCollector = dosaiMethodCallCollector(reportFile, {
|
|
1143
|
+
maxMethodCalls: options.maxMethodCalls,
|
|
1144
|
+
});
|
|
1145
|
+
const reduced = [];
|
|
1146
|
+
for (const methodCall of report.MethodCalls || []) {
|
|
1147
|
+
const kept = wholeCollector.map(methodCall);
|
|
1148
|
+
if (kept !== undefined) {
|
|
1149
|
+
reduced.push(kept);
|
|
1150
|
+
}
|
|
1151
|
+
}
|
|
1152
|
+
report.MethodCalls = reduced;
|
|
1153
|
+
wholeCollector.finish();
|
|
1154
|
+
}
|
|
1155
|
+
collector?.finish();
|
|
1156
|
+
return report;
|
|
812
1157
|
}
|
|
813
1158
|
|
|
814
1159
|
/**
|
|
@@ -1844,6 +2189,23 @@ export function collectDosaiAiComponents(methodsSlice, components = []) {
|
|
|
1844
2189
|
format,
|
|
1845
2190
|
}));
|
|
1846
2191
|
}
|
|
2192
|
+
const hubReference = String(ai.Purl || "").startsWith("pkg:huggingface/")
|
|
2193
|
+
? normalizeHuggingFaceReference(ai.Purl)
|
|
2194
|
+
: undefined;
|
|
2195
|
+
const hubNamespace = hubReference?.repoId?.split("/")[0];
|
|
2196
|
+
// A Hub model is credited to the namespace only when it is the
|
|
2197
|
+
// creator's own organisation, as the source collectors do. Otherwise
|
|
2198
|
+
// dosai reports the provider the code calls, which names the client
|
|
2199
|
+
// rather than the model, so the creator is resolved from the model
|
|
2200
|
+
// name.
|
|
2201
|
+
const manufacturer = modelCreatorEntity(
|
|
2202
|
+
hubNamespace
|
|
2203
|
+
? modelCreatorFromOrganization(hubNamespace)
|
|
2204
|
+
: resolveModelCreator(ai.Name, {
|
|
2205
|
+
fileProviders: ai.Provider ? [ai.Provider] : [],
|
|
2206
|
+
provider: ai.Provider,
|
|
2207
|
+
}),
|
|
2208
|
+
);
|
|
1847
2209
|
const component = {
|
|
1848
2210
|
"bom-ref": ai.Id,
|
|
1849
2211
|
type: "machine-learning-model",
|
|
@@ -1851,6 +2213,13 @@ export function collectDosaiAiComponents(methodsSlice, components = []) {
|
|
|
1851
2213
|
version: ai.Version,
|
|
1852
2214
|
purl: ai.Purl,
|
|
1853
2215
|
modelCard,
|
|
2216
|
+
// The creator is the manufacturer; a Hugging Face namespace that
|
|
2217
|
+
// published the model is the supplier. The provider stays a
|
|
2218
|
+
// property either way.
|
|
2219
|
+
manufacturer,
|
|
2220
|
+
supplier: hubNamespace
|
|
2221
|
+
? toHuggingFaceSupplier(hubNamespace)
|
|
2222
|
+
: undefined,
|
|
1854
2223
|
properties: [
|
|
1855
2224
|
{ name: "cdx:ai:provider", value: ai.Provider || "unknown" },
|
|
1856
2225
|
{ name: "cdx:ai:deployment", value: ai.Deployment || "unknown" },
|
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
import { Purl } from "@cdxgen/cdx-purl";
|
|
13
13
|
|
|
14
14
|
import { safeExistsSync } from "../core/fs.js";
|
|
15
|
+
import { occurrenceLocationKey } from "./occurrenceKey.js";
|
|
15
16
|
|
|
16
17
|
/**
|
|
17
18
|
* Build a lowercase type/namespace/name lookup key for a purl.
|
|
@@ -68,10 +69,7 @@ export function dosaiLocation(item) {
|
|
|
68
69
|
return undefined;
|
|
69
70
|
}
|
|
70
71
|
const lineNumber = location?.LineNumber || item?.LineNumber;
|
|
71
|
-
|
|
72
|
-
return `${fileName}#${lineNumber}`;
|
|
73
|
-
}
|
|
74
|
-
return fileName;
|
|
72
|
+
return occurrenceLocationKey(fileName, lineNumber);
|
|
75
73
|
}
|
|
76
74
|
|
|
77
75
|
function dosaiSourceFileName(item) {
|
|
@@ -110,8 +108,7 @@ export function dosaiCallSiteLocation(methodCall, srcPath) {
|
|
|
110
108
|
if (!file || lowerFile.endsWith(".dll") || lowerFile.endsWith(".exe")) {
|
|
111
109
|
return undefined;
|
|
112
110
|
}
|
|
113
|
-
|
|
114
|
-
return lineNumber > 0 ? `${file}#${lineNumber}` : file;
|
|
111
|
+
return occurrenceLocationKey(file, methodCall?.LineNumber);
|
|
115
112
|
}
|
|
116
113
|
|
|
117
114
|
function dosaiCallSiteFile(methodCall, srcPath) {
|