Packages · supply-chain

k2gl/slsa-provenance

Model SLSA provenance predicates in PHP.

Describe how an artifact was built — builder, invocation, materials — in the SLSA v1 shape.

k2gl/slsa-provenance version on Packagist k2gl/slsa-provenance total downloads k2gl/slsa-provenance license

Install

composer require k2gl/slsa-provenance
PHP
>=8.1
k2gl dependencies
k2gl/in-toto-attestation

Reach for it when

  • You’re producing a SLSA provenance predicate for a build.
  • You need the typed SLSA v1 structure rather than hand-built arrays.

Look elsewhere when

  • You need the Statement wrapper around the predicate — use in-toto-attestation.

k2gl/slsa-provenance

Typed SLSA Provenance predicates for PHP, both the current v1 and the legacy v0.2 that most real-world bundles still carry. Built on in-toto attestations.

SLSA Provenance describes how an artifact was built — the build definition (inputs) and the run details (who built it, when, and what came out). This package models that predicate as typed value objects and plugs it straight into an in-toto Statement, ready to sign with k2gl/dsse.

Install

composer require k2gl/slsa-provenance

Requires PHP 8.1+. Pulls in k2gl/in-toto-attestation and k2gl/dsse.

Usage

use K2gl\Slsa\Provenance;
use K2gl\Slsa\BuildDefinition;
use K2gl\Slsa\RunDetails;
use K2gl\Slsa\Builder;
use K2gl\Slsa\BuildMetadata;
use K2gl\InToto\ResourceDescriptor;

$provenance = new Provenance(
    new BuildDefinition(
        buildType: 'https://example.com/buildtypes/v1',
        externalParameters: ['repository' => 'https://github.com/k2gl/dsse', 'ref' => 'refs/tags/1.0.0'],
        resolvedDependencies: [
            new ResourceDescriptor(uri: 'git+https://github.com/k2gl/dsse', digest: ['gitCommit' => '…']),
        ],
    ),
    new RunDetails(
        builder: new Builder(id: 'https://github.com/actions/runner', version: ['runner' => '2.x']),
        metadata: new BuildMetadata(invocationId: 'run-42', startedOn: '2026-05-30T00:00:00Z'),
    ),
);

// Wrap as an in-toto Statement over the built artifacts, then sign with k2gl/dsse:
$statement = $provenance->toStatement([
    new ResourceDescriptor(name: 'app.phar', digest: ['sha256' => '…']),
]);
$envelope = $statement->sign($signer);   // K2gl\Dsse\Envelope

Parsing back (after verifying the envelope's signatures):

use K2gl\InToto\Statement;
use K2gl\Slsa\Provenance;

$statement  = Statement::fromEnvelope($envelope);
$provenance = Provenance::fromStatement($statement);   // checks predicateType

$provenance->buildDefinition->buildType;          // 'https://example.com/buildtypes/v1'
$provenance->runDetails->builder->id;             // 'https://github.com/actions/runner'
$provenance->runDetails->metadata?->invocationId; // 'run-42'

SLSA Provenance v0.2

Most provenance found in real Sigstore bundles is the older v0.2 predicate (https://slsa.dev/provenance/v0.2), which has a different shape from v1. It lives under K2gl\Slsa\V02 with its own typed value objects:

use K2gl\InToto\Statement;
use K2gl\Slsa\V02\Provenance;

$statement  = Statement::fromEnvelope($envelope);   // verify signatures first
$provenance = Provenance::fromStatement($statement);

$provenance->builder->id;                              // 'https://github.com/…'
$provenance->buildType;                                // 'https://…/generic@v1'
$provenance->invocation?->configSource?->uri;          // 'git+https://github.com/…'
$provenance->metadata?->completeness?->parameters;     // true
$provenance->materials[0]->digest;                     // ['sha1' => '…']

Building one wraps it in an in-toto Statement v0.1 by default — the version real-world v0.2 provenance is paired with. The two versions are orthogonal, so the Statement version can be overridden:

use K2gl\InToto\StatementVersion;
use K2gl\Slsa\V02\Builder;
use K2gl\Slsa\V02\Provenance;

$provenance = new Provenance(
    builder: new Builder(id: 'https://github.com/actions/runner'),
    buildType: 'https://github.com/slsa-framework/slsa-github-generator/generic@v1',
);

$statement = $provenance->toStatement([$subject]);                       // in-toto Statement v0.1
$statement = $provenance->toStatement([$subject], StatementVersion::V1); // …or v1

Predicate registry

Register the SLSA predicate types so in-toto's Statement::predicate() returns a typed Provenance instead of a raw array:

use K2gl\InToto\Statement;
use K2gl\Slsa\Predicates;
use K2gl\Slsa\Provenance;

Predicates::register();                  // registers v1 + v0.2 in the shared registry

$statement = Statement::fromEnvelope($envelope);
$predicate = $statement->predicate();    // a K2gl\Slsa\Provenance (or V02\Provenance), else the raw array

if ($predicate instanceof Provenance) {
    echo $predicate->buildDefinition->buildType;
}

License

MIT — see LICENSE. Independent, clean-room implementation of the SLSA Provenance specification.

API

Public classes and methods, generated from the source.

K2gl\Slsa\BuildDefinition class

  • __construct( public readonly string $buildType, public readonly array $externalParameters = [], public readonly ?array $internalParameters = null, public readonly array $resolvedDependencies = [], )
  • toArray(): array
  • fromArray(array $data): self

K2gl\Slsa\BuildMetadata class

  • __construct( public readonly ?string $invocationId = null, public readonly ?string $startedOn = null, public readonly ?string $finishedOn = null, )
  • toArray(): array
  • fromArray(array $data): self

K2gl\Slsa\Builder class

  • __construct( public readonly string $id, public readonly array $builderDependencies = [], public readonly ?array $version = null, )
  • toArray(): array
  • fromArray(array $data): self

K2gl\Slsa\Exception\InvalidProvenanceException class

K2gl\Slsa\Exception\SlsaException interface

K2gl\Slsa\Predicates class

  • register(?PredicateRegistry $registry = null): void

K2gl\Slsa\Provenance class

  • __construct( public readonly BuildDefinition $buildDefinition, public readonly RunDetails $runDetails, )
  • predicateType(): string
  • toArray(): array
  • toStatement(array $subject): Statement
  • fromStatement(Statement $statement): self
  • fromArray(array $data): self

K2gl\Slsa\RunDetails class

  • __construct( public readonly Builder $builder, public readonly ?BuildMetadata $metadata = null, public readonly array $byproducts = [], )
  • toArray(): array
  • fromArray(array $data): self

K2gl\Slsa\V02\Builder class

  • __construct( public readonly string $id, )
  • toArray(): array
  • fromArray(array $data): self

K2gl\Slsa\V02\Completeness class

  • __construct( public readonly ?bool $parameters = null, public readonly ?bool $environment = null, public readonly ?bool $materials = null, )
  • toArray(): array
  • fromArray(array $data): self

K2gl\Slsa\V02\ConfigSource class

  • __construct( public readonly ?string $uri = null, public readonly array $digest = [], public readonly ?string $entryPoint = null, )
  • toArray(): array
  • fromArray(array $data): self

K2gl\Slsa\V02\Invocation class

  • __construct( public readonly ?ConfigSource $configSource = null, public readonly ?array $parameters = null, public readonly ?array $environment = null, )
  • toArray(): array
  • fromArray(array $data): self

K2gl\Slsa\V02\Metadata class

  • __construct( public readonly ?string $buildInvocationId = null, public readonly ?string $buildStartedOn = null, public readonly ?string $buildFinishedOn = null, public readonly ?Completeness $completeness = null, public readonly ?bool $reproducible = null, )
  • toArray(): array
  • fromArray(array $data): self

K2gl\Slsa\V02\Provenance class

  • __construct( public readonly Builder $builder, public readonly string $buildType, public readonly ?Invocation $invocation = null, public readonly ?array $buildConfig = null, public readonly ?Metadata $metadata = null, public readonly array $materials = [], )
  • predicateType(): string
  • toArray(): array
  • toStatement(array $subject, StatementVersion $statementVersion = StatementVersion::V0_1): Statement
  • fromStatement(Statement $statement): self
  • fromArray(array $data): self