Architecture

Only the entry points know a build system or the command line: the hatchling and pdm-backend hooks, the setuptools plugin, the wrapper backend, and the embed and archive commands. Each gathers the options, the build scripts and the build facts (time, revision, toolchain) and hands them, with a ContentProvider, to the pipeline for its artifact. The pipeline opens the artifact once, reads it, gives the provider a ProviderContext that reads from the same open artifact, and maps what it read to components. It then adds what every artifact of the project shares: supplier, source links, revision, tools, dependencies and formulation.

The diagram follows one build, from the entry point to the document written into the artifact:

        flowchart LR
    entry["Entry point<br/>build hook, plugin, wrapper backend,<br/>embed or archive command"]
    collect["Collect<br/>options, revision,<br/>build tools, artifact"]
    provider["Content provider<br/>what the project adds"]
    model["Model<br/>the CycloneDX document"]
    write["Write<br/>into the wheel or archive"]
    entry --> collect --> model --> write
    provider --> model
    classDef io fill:#cfe4ff,stroke:#1f6feb,color:#0b1f3a;
    classDef core fill:#d8f3dc,stroke:#2d6a4f,color:#081c15;
    class entry,write io;
    class collect,provider,model core;
    

Every step raises SbomError, which the command line reports without a traceback. Each integration imports its own build backend and nothing else does, so the provider API and the command line work without any backend installed.

The one extension point is the ContentProvider, which every entry point loads from the content-provider option. A hatchling custom hook can override content_provider() to build the provider itself.