A dependency inventory generated in the pipeline

An inventory maintained by hand is out of date the day it is written; one generated by the build is correct by construction.

# per build, alongside the image
composer show --format=json > sbom/composer.json
npm ls --all --json    > sbom/npm.json

# the base image's packages, which the other two miss
docker run --rm --entrypoint sh app:"$TAG" -c 
  'apk info -v 2>/dev/null || dpkg -l' > sbom/os.txt

# tagged with the image digest, not the tag — tags move
echo "$(docker image inspect app:"$TAG" -f '{{index .RepoDigests 0}}')" 
  > sbom/digest.txt

Three sources are needed because no single tool sees all of them: the application dependencies, the JavaScript ones and the operating system packages in the base image, which is where a surprising share of advisories land. Keying the record on the image digest rather than the tag is what makes it answerable later — a tag is a moving pointer and the question is always about a specific deployed artefact.