Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions docs/adr/0012-sbom-resolved-dependency-components.md
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,40 @@ already extracted. When neither a detected package nor a same-owner resolved
version exists for an identity, the component keeps its unversioned purl and
unset license.

## Amendment: license acknowledgement in CycloneDX

The CycloneDX renderer carries the declared-vs-concluded distinction — the same
one SPDX renders as `PackageLicenseDeclared` / `PackageLicenseConcluded`
(`src/output/spdx.rs`) — via `licenses[].acknowledgement`. Scope is the
CycloneDX renderer only; SPDX and the native ScanCode-compatible output are
unchanged (ADR 0008).

- **Spec version.** The renderer emits a single current CycloneDX schema
version — recent enough to define `licenses[].acknowledgement` — via
`specVersion`, the JSON `$schema`, and the XML `bom` namespace. The exact
version string, schema URL, and namespace are owned by `src/output/cyclonedx.rs`
and the validator config, not this record. Feature areas outside Provenant's
use (crypto/CBOM/formulation) are not emitted.
- **Acknowledgement is honest, not stamped.** It comes from the same package
fields SPDX uses: a parser-declared expression
(`declared_license_expression_spdx`, then raw `declared_license_expression`)
is `declared`; a license concluded from source/file detection
(`license_detections`) is `concluded`. The field tags provenance without
altering the expression a component reports. In JSON it sits beside
`expression`; in XML it is the `acknowledgement` attribute on `<expression>`.
- **License evidence is source-faithful.** Each component carries
`component.evidence` built from the file-content license detections of the
files it owns, using the same file→package ownership assembly computes
(`file.for_packages`): the distinct observed SPDX expressions as
`evidence.licenses`, and the file+line of each detection as
`evidence.occurrences`. Only detected packages own scanned files; a promoted
resolved dependency owns none, so it carries no evidence. This is
render-time reuse of data already in the document — nothing is re-detected.
- **Conformance is externally gated.** Goldens prove stability, not conformance;
all CycloneDX goldens and the four `examples/sbom` validate against the
official CycloneDX schema + XSD for the emitted version via
`scripts/validate_output_format_fixtures.py` (`cyclonedx-python-lib`).

## Consequences

### Benefits
Expand Down Expand Up @@ -222,6 +256,7 @@ unset license.

- Issue #1319
- Issue #1320 (versioned purls + vendored-license join amendment)
- Issue #1328 (CycloneDX 1.7 + license acknowledgement/evidence amendment)
- Promotion/dedup: `src/output/sbom.rs`
- CycloneDX renderer: `src/output/cyclonedx.rs`
- SPDX renderer: `src/output/spdx.rs`
Expand Down
2 changes: 1 addition & 1 deletion examples/sbom/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

Real software bills of materials produced by [Provenant](https://github.com/getprovenant/provenant), one directory per target. Each target directory contains an SPDX tag-value document ([`sbom.spdx`](ripgrep/sbom.spdx)) and a CycloneDX JSON document ([`sbom.cdx.json`](ripgrep/sbom.cdx.json)), plus a short provenance README.

These examples are generated by Provenant 1.0.2 (the current build) scanning each project at a pinned commit with license, package, and copyright detection enabled. Every SBOM is a complete, closed inventory: each resolved dependency is promoted to a component with a package URL, and every dependency relationship resolves within the document.
These examples are generated by Provenant 1.0.3 (the current build) scanning each project at a pinned commit with license, package, and copyright detection enabled. Every SBOM is a complete, closed inventory: each resolved dependency is promoted to a component with a package URL, and every dependency relationship resolves within the document.

## Targets

Expand Down
2 changes: 1 addition & 1 deletion examples/sbom/express/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ SPDX tag-value ([`sbom.spdx`](sbom.spdx)) and CycloneDX JSON ([`sbom.cdx.json`](

- Source: `https://github.com/expressjs/express.git` at tag `v5.2.1`
- Pinned commit: `dbac741a49a5a64336b70c06e85c2e2706e36336`
- Generated by: Provenant 1.0.2
- Generated by: Provenant 1.0.3
- Command: `provenant scan <checkout> --license --package --copyright --strip-root --spdx-tv sbom.spdx --cyclonedx sbom.cdx.json`

## What's inside
Expand Down
125 changes: 117 additions & 8 deletions examples/sbom/express/sbom.cdx.json
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
{
"$schema": "http://cyclonedx.org/schema/bom-1.7.schema.json",
"bomFormat": "CycloneDX",
"specVersion": "1.3",
"serialNumber": "urn:uuid:88b5de63-2310-40c2-9151-0bc05ffaba28",
"specVersion": "1.7",
"serialNumber": "urn:uuid:9a30ff04-67e1-468e-aa86-b8e480c4b564",
"version": 1,
"metadata": {
"timestamp": "2026-07-24T13:05:02Z",
"timestamp": "2026-07-24T14:34:28Z",
"tools": [
{
"name": "Provenant",
"version": "1.0.2"
"version": "1.0.3"
}
],
"component": {
Expand All @@ -20,7 +21,8 @@
"purl": "pkg:npm/express@5.2.1",
"licenses": [
{
"expression": "MIT"
"expression": "MIT",
"acknowledgement": "declared"
}
],
"externalReferences": [
Expand All @@ -44,7 +46,60 @@
"type": "vcs",
"url": "https://github.com/expressjs/express"
}
]
],
"evidence": {
"occurrences": [
{
"location": "LICENSE",
"line": 1
},
{
"location": "LICENSE",
"line": 7
},
{
"location": "Readme.md",
"line": 261
},
{
"location": "index.js",
"line": 6
},
{
"location": "lib/application.js",
"line": 6
},
{
"location": "lib/express.js",
"line": 6
},
{
"location": "lib/request.js",
"line": 6
},
{
"location": "lib/response.js",
"line": 5
},
{
"location": "lib/utils.js",
"line": 5
},
{
"location": "lib/view.js",
"line": 6
},
{
"location": "package.json",
"line": 15
}
],
"licenses": [
{
"expression": "MIT"
}
]
}
}
},
"components": [
Expand All @@ -59,7 +114,8 @@
"purl": "pkg:npm/express@5.2.1",
"licenses": [
{
"expression": "MIT"
"expression": "MIT",
"acknowledgement": "declared"
}
],
"externalReferences": [
Expand All @@ -83,7 +139,60 @@
"type": "vcs",
"url": "https://github.com/expressjs/express"
}
]
],
"evidence": {
"occurrences": [
{
"location": "LICENSE",
"line": 1
},
{
"location": "LICENSE",
"line": 7
},
{
"location": "Readme.md",
"line": 261
},
{
"location": "index.js",
"line": 6
},
{
"location": "lib/application.js",
"line": 6
},
{
"location": "lib/express.js",
"line": 6
},
{
"location": "lib/request.js",
"line": 6
},
{
"location": "lib/response.js",
"line": 5
},
{
"location": "lib/utils.js",
"line": 5
},
{
"location": "lib/view.js",
"line": 6
},
{
"location": "package.json",
"line": 15
}
],
"licenses": [
{
"expression": "MIT"
}
]
}
},
{
"type": "library",
Expand Down
4 changes: 2 additions & 2 deletions examples/sbom/express/sbom.spdx
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ Provenant is a free software code scanning tool.
Visit https://github.com/getprovenant/provenant/ for support and download.
SPDX License List: 3.27</text>
## Creation Information
Creator: Tool: Provenant-1.0.2
Created: 2026-07-24T13:05:01Z
Creator: Tool: Provenant-1.0.3
Created: 2026-07-24T14:34:28Z
## Package Information
PackageName: express
SPDXID: SPDXRef-Package-1
Expand Down
2 changes: 1 addition & 1 deletion examples/sbom/flask/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ SPDX tag-value ([`sbom.spdx`](sbom.spdx)) and CycloneDX JSON ([`sbom.cdx.json`](

- Source: `https://github.com/pallets/flask.git` at tag `3.1.3`
- Pinned commit: `22d924701a6ae2e4cd01e9a15bbaf3946094af65`
- Generated by: Provenant 1.0.2
- Generated by: Provenant 1.0.3
- Command: `provenant scan <checkout> --license --package --copyright --strip-root --spdx-tv sbom.spdx --cyclonedx sbom.cdx.json`

## What's inside
Expand Down
Loading
Loading