Verify what AGLedger ships

AGLedger ships four artifact surfaces: the Server container image, the Helm chart, the npm packages, and the PyPI package. Every one is built and signed by CI under a single keyless trust root: GitHub Actions OIDC to Sigstore (Fulcio) to the public Rekor transparency log. There is no long-lived signing token or static key for any published artifact, and verification runs entirely against the public Sigstore trust root, with no AGLedger-hosted key, endpoint, or source-repository access.

This page is the single index for the verify recipes. The image and chart recipes are also maintained in the install repository's SECURITY.md, which agrees with this page on the trust root. The npm and PyPI recipes below are the canonical copy.

Assurance level, per artifact

The SLSA Build level is stated per artifact rather than flattened to one number. The container and registry paths earn different guarantees, and over-claiming on either is exactly what a security reviewer flags.

ArtifactProvenance mechanismSLSA Build level
Server image agledger/agledgercosign keyless + slsa-github-generator isolated builder, plus SBOM, OpenVEX and malware-scan attestationsL3
Helm chart agledger/agledger-chartcosign keyless signature onlynone of its own
npm packages @agledger/{verify-core,verify,sdk,cli,mcp-server}npm provenance attestation (Sigstore) + signed CycloneDX SBOM attestationL2
PyPI package agledgerPEP 740 attestation via PyPI Trusted Publishingsigned publish attestation, no numbered level

The image reaches SLSA Build L3 because its provenance is produced by an isolated reusable workflow the build steps cannot tamper with. The chart carries a signature and no provenance or SBOM of its own: it is a templates tarball, and every attestation lives on the image digest it deploys. The npm packages publish hosted build provenance via Trusted Publishing, OIDC-bound and non-forgeable but without the isolated-builder guarantee, which is SLSA Build L2. PyPI's PEP 740 attestations bind each file to its publishing workflow and are not mapped to a numbered SLSA level.

Server image and Helm chart

Both are keyless-signed with cosign. A valid signature binds to the GitHub Actions workflow that built the release. Requires cosign 3.0 or later. Set the release you are verifying once:

VERSION=2.0.0
IDENTITY='^https://github\.com/agledger-ai/agledger-api/\.github/workflows/.+@refs/tags/v.+$'
ISSUER='https://token.actions.githubusercontent.com'

Verify the image signature, then the chart:

$ cosign verify --certificate-identity-regexp "$IDENTITY" --certificate-oidc-issuer "$ISSUER" \
    agledger/agledger:$VERSION
$ cosign verify --certificate-identity-regexp "$IDENTITY" --certificate-oidc-issuer "$ISSUER" \
    registry-1.docker.io/agledger/agledger-chart:$VERSION

Each prints Verification for ... and a JSON block whose certificate identity is the GitHub Actions workflow that built the artifact. Verify the CycloneDX SBOM and OpenVEX attestations the same way:

$ cosign verify-attestation --type cyclonedx --certificate-identity-regexp "$IDENTITY" \
    --certificate-oidc-issuer "$ISSUER" agledger/agledger:$VERSION
$ cosign verify-attestation --type openvex --certificate-identity-regexp "$IDENTITY" \
    --certificate-oidc-issuer "$ISSUER" agledger/agledger:$VERSION

The image also carries the result of a ClamAV known-malware scan of its shipping filesystem. cosign verify-attestation checks the signature and the predicate type, not the field values, so assert the result yourself:

$ cosign verify-attestation --type https://agledger.ai/attestations/malware-scan/v1 \
    --certificate-identity-regexp "$IDENTITY" --certificate-oidc-issuer "$ISSUER" \
    agledger/agledger:$VERSION \
  | jq -e '.payload | @base64d | fromjson | .predicate.result == "no-detections"'

For the SLSA Build L3 provenance, verify by digest with slsa-verifier:

$ slsa-verifier verify-image "agledger/agledger@$(crane digest agledger/agledger:$VERSION)" \
    --source-uri github.com/agledger-ai/agledger-api \
    --builder-id 'https://github.com/slsa-framework/slsa-github-generator/.github/workflows/generator_container_slsa3.yml@refs/tags/v2.1.0'

The --source-uri value is an identity check against the provenance in the public transparency log, not a fetch: it names the repository the build ran from, and verification succeeds without any access to it.

Docker Hub is the authoritative customer registry. Provenance binds to Docker Hub digests. Internal ECR or other registry mirrors are separate builds and will not digest-match. Verify against Docker Hub, then mirror the verified digest.

npm packages

npm audit signatures verifies both the registry signature and the Sigstore build-provenance attestation against the public transparency log. It audits the dependency tree of the project it runs in, so install the package into a project rather than globally:

$ npm init -y >/dev/null
$ npm install @agledger/verify-core     # or any @agledger/* package
$ npm audit signatures
audited 2 packages in 0s

2 packages have verified registry signatures

2 packages have verified attestations

The count covers every package in the tree, dependencies included.

Each package page on npmjs.com links the provenance to the exact GitHub Actions run and source commit that built it.

The CycloneDX SBOM is a signed attestation over the published tarball, held in the package's public GitHub repository (agledger-ai/verify, verify-core, sdk, cli or mcp-server). Verify it with the GitHub CLI, which exits 0 on a match:

$ npm pack @agledger/verify@2.0.0
$ gh attestation verify agledger-verify-2.0.0.tgz --repo agledger-ai/verify \
    --predicate-type https://cyclonedx.org/bom

PyPI package

agledger is published via PyPI Trusted Publishing with PEP 740 digital attestations, which bind each release to the agledger-ai/sdk-python publishing workflow (Sigstore identity, public Rekor). Inspect them with the pypi-attestations tool or the PyPI Integrity API:

$ pip install pypi-attestations
$ pypi-attestations verify pypi --repository https://github.com/agledger-ai/sdk-python \
    pypi:agledger-3.0.0-py3-none-any.whl

The pypi: argument names the released file, not a requirement spec; use the wheel filename of the PyPI release you are verifying. (The Python SDK versions independently of the Server, so its version differs from $VERSION above.)

What else ships with every release

This page verifies the artifacts you install. To verify the records a running Server produces (the hash-chained, signed audit chain) offline and with nothing but the published public keys, see Audit & Verification. The vault signing-key rotation procedure is in day-2 operations.

The image and chart recipes above mirror the install repository's SECURITY.md. Verifying on an air-gapped host, from the offline verification bundle with scripts/verify-release.sh, is in the install repository's air-gap/README.md.