first commit
This commit is contained in:
@@ -0,0 +1,89 @@
|
||||
# provenance
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
_(no submodules)_
|
||||
<!-- end:auto-docs -->
|
||||
## Purpose
|
||||
|
||||
Generates SLSA v1.0 provenance statements wrapped in in-toto v1 envelopes.
|
||||
Each statement records the artifact digest, builder identity, source
|
||||
repository, git ref, and build timing — the tamper-evident audit trail that
|
||||
lets downstream consumers verify an artifact was built by a trusted pipeline
|
||||
from an expected source.
|
||||
|
||||
## Features
|
||||
|
||||
- Canonical in-toto / SLSA v1.0 envelope shape.
|
||||
- Deterministic serialisation through `canonicalize` (sorted keys).
|
||||
- SHA-256 digest of the canonical encoding for signing / transparency logs.
|
||||
- Builder version auto-detection (Bun in CI; `unknown` elsewhere).
|
||||
- Structured `InvalidProvenanceError` for any malformed input.
|
||||
- OTel `slsa.provenance.generated` span event with builder + source attributes.
|
||||
|
||||
## Usage: Basic Example
|
||||
|
||||
```ts
|
||||
import { generateProvenance, hashProvenance } from "@suaveplan/slsa";
|
||||
|
||||
const statement = generateProvenance({
|
||||
packageName: "@suaveplan/utils",
|
||||
packageVersion: "1.2.3",
|
||||
artifactDigest: "abc123...",
|
||||
sourceCommit: "deadbeef...",
|
||||
sourceRepo: "https://gitlab.fq.io/suaveplan/project",
|
||||
sourceRef: "refs/heads/main",
|
||||
builderId: "https://gitlab.fq.io/suaveplan/project/-/runners/1",
|
||||
buildInvocationId: "ci-12345",
|
||||
buildStartedOn: new Date().toISOString(),
|
||||
});
|
||||
|
||||
const digest = hashProvenance(statement);
|
||||
```
|
||||
|
||||
## Usage: Advanced Example
|
||||
|
||||
```ts
|
||||
import {
|
||||
createSlsaOtelAdapter,
|
||||
generateProvenance,
|
||||
serializeProvenance,
|
||||
} from "@suaveplan/slsa";
|
||||
|
||||
const otel = createSlsaOtelAdapter();
|
||||
const statement = generateProvenance({
|
||||
/* ...fields... */,
|
||||
resolvedDependencies: [
|
||||
{
|
||||
uri: "pkg:npm/lodash@4.17.21",
|
||||
digest: { sha256: "lodashHashHex" },
|
||||
name: "lodash",
|
||||
},
|
||||
],
|
||||
otel,
|
||||
});
|
||||
|
||||
await fs.writeFile("provenance.json", serializeProvenance(statement));
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
- `generateProvenance(input: ProvenanceInput): ProvenanceStatement` —
|
||||
validates all required fields, returns the in-toto envelope. Throws
|
||||
`InvalidProvenanceError` when any field is empty, non-string, or when
|
||||
`buildStartedOn` / `buildFinishedOn` are not parseable ISO 8601.
|
||||
- `serializeProvenance(statement): string` — canonical (sorted-keys) JSON.
|
||||
- `hashProvenance(statement): string` — SHA-256 hex of the canonical
|
||||
serialisation, used as the subject of Rekor hashedrekord entries.
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
`buildType` is pinned to `https://suaveplan.app/slsa/build-type/bun-project/v1`
|
||||
— bumping this identifier is a semver break, since downstream verifiers may
|
||||
pattern-match on it. `resolvedDependencies` is emitted at both
|
||||
`buildDefinition.resolvedDependencies` and
|
||||
`buildDefinition.internalParameters.resolvedDependencies` to match the two
|
||||
common shapes found in GitHub's SLSA generator and the SLSA reference CLI.
|
||||
Builder version detection uses `globalThis.Bun` rather than a top-level
|
||||
import so the module is importable from non-Bun runtimes without a cold
|
||||
failure. Hashing uses the same canonicalisation function as DSSE payload
|
||||
encoding, so "the thing we signed" always matches "the thing we hashed".
|
||||
Reference in New Issue
Block a user