Skip to content

Define the portable sbom contract, without a generator - #10

Merged
mxwlf merged 1 commit into
mainfrom
docs/sbom-convention
Sep 24, 2026
Merged

mxwlf merged 1 commit into
mainfrom
docs/sbom-convention

Conversation

@mxwlf

@mxwlf mxwlf commented Sep 24, 2026

Copy link
Copy Markdown
Owner

Documentation only. Adds a sbom convention under Extending make ci for your
project
, and deliberately ships no generator.

The split

Portable — the contract Project-specific — the implementation
A sbom target, in the ci chain, after whatever builds The generator and its toolchain
Output under the same gitignored artifacts directory as the other reports The dependency-manifest path it reads
Published by the CI stubs beside test and coverage reports The SBOM's subject name and version

Why no generator here

An SBOM's substance is the resolved dependency graph, and that graph only exists
inside an ecosystem's resolver — NuGet's project.assets.json, a package-lock.json,
a populated virtualenv. Anything repo-level either shells out to those resolvers
anyway or parses manifests and guesses, and guessing gets transitive and
conditionally-referenced packages wrong.

There is also a concrete objection specific to this template: the obvious generator is
a .NET tool, and standardising on it would drag the .NET SDK into the Requirements list
for every non-.NET project created from here.

And this repository ships no artifact. Its only dependencies are pre-commit and the
rev-pinned hook repos — a developer toolchain nobody deploys — so an SBOM of it would
inventory something that is never shipped. Documenting the seam is the useful thing;
filling it is not.

Also recorded

  • Generate from the build output, not the source tree.
  • A per-pull-request SBOM and a release SBOM are different artifacts: the first is a
    drift detector, the second describes a released artifact and wants attaching and
    attesting.

dotnet-template implements this contract for .NET (SPDX 2.2 via Microsoft's
sbom-tool) and is linked as a worked example.

An SBOM is the clearest case of a check whose contract is portable while its
implementation cannot be, so this template defines the contract and ships no
generator: a `sbom` target in the `ci` chain, output under the gitignored artifacts
directory, published by the CI stubs beside the test and coverage reports.

Nothing portable can produce the document itself. An SBOM's substance is the
*resolved* dependency graph, which only exists inside an ecosystem's resolver —
NuGet's project.assets.json, a package-lock.json, a populated virtualenv. A
repo-level tool either shells out to those resolvers or parses manifests and
guesses, and guessing gets transitive and conditionally-referenced packages wrong.
Standardising one generator here would also force its toolchain onto every project
made from this template, which is what the Requirements list exists to avoid.

This repository gets no `sbom` target of its own on purpose: it ships no artifact.
Its only dependencies are pre-commit and the rev-pinned hook repos, so an SBOM of it
would inventory a developer toolchain nobody deploys.

Also records two decisions that are easy to get wrong: generate from the build
output rather than the source tree, and treat a per-pull-request SBOM (a drift
detector) as a different artifact from a release SBOM (which wants attaching and
attesting).
@mxwlf
mxwlf merged commit 9eca07f into main Sep 24, 2026
1 check passed
@mxwlf
mxwlf deleted the docs/sbom-convention branch September 24, 2026 23:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant