Files
2026-05-27 23:29:53 +01:00

5.6 KiB

SLSA capability spec — enterprise delta

ADDED Requirements

SLSA-01 Structured errors

The package SHALL expose a SlsaError base class extending SuaveplanError<SlsaCode>, a frozen SLSA_CODES registry built via defineCodes, and one subclass per code (InvalidProvenanceError, InvalidSbomError, VerificationFailedError, PolicyViolationError, RekorUploadError, RekorInclusionError, AttestationInvalidError, EnvironmentUnsupportedError). Every thrown error inside the package MUST be a subclass of SlsaError — no raw Error or string throws.

SLSA-02 Zod schemas

Every wire-format type SHALL have a sibling Zod schema co-located in src/schemas/*. Types SHALL be derived via z.infer rather than hand-authored. parseProvenance(input) and parseSbom(input) SHALL accept either a JSON string or an object and throw InvalidProvenanceError / InvalidSbomError (with context.issues) on failure.

SLSA-03 Canonical JSON

The package SHALL export a canonicalize(value): string helper that sorts object keys recursively and omits undefined. All hashing and DSSE payload encoding SHALL use this helper so digests are stable across producers.

SLSA-04 SHA-256 via @suaveplan/crypto-hash

The package SHALL NOT import from node:crypto. Hashing SHALL route through @suaveplan/crypto-hash's sha256 selector plus @suaveplan/crypto-utils's toHex / fromHex.

SLSA-05 Provenance generation

generateProvenance(input) SHALL produce an in-toto v1 statement with a SLSA v1.0 provenance predicate. Input SHALL be validated; missing or malformed fields SHALL raise InvalidProvenanceError with context.field. Invalid or reverse-ordered ISO 8601 timestamps SHALL also raise.

SLSA-06 Provenance verification

verifyProvenance(statement, policy, opts?) SHALL run the baseline rule set (statement type, predicate type, subject present, subject digest, builder trusted, build timestamps) and append optional rules based on the policy shape (expectedSourceRepo, expectedSourceRepoPrefix, requireFinishedOn, maxBuildDurationMs, maxAgeMs). The result SHALL be a structured VerificationResult — the function SHALL NOT throw on policy failure.

SLSA-07 SBOM generation

generateSbom(input, opts?) SHALL produce a CycloneDX 1.5 SBOM. workspace:* and catalog:key dependency references SHALL be rewritten to * and catalog-key respectively. clock and serial SHALL be injectable for deterministic tests. Canonical serialisation and SHA-256 hashing SHALL be exposed via serializeSbom and hashSbom.

SLSA-08 Assessment

assessSlsaLevel(env) SHALL return the highest achievable SLSA Build level (L0-L3) given the supplied signals. When hasRekorInclusion is false, L3 SHALL be blocked even if isolated-build and hardened-provenance are set. detectEnvironment() SHALL populate the signals from SLSA_* / CI / GITLAB_CI / GITHUB_ACTIONS env vars.

SLSA-09 DSSE attestation envelope

encodeDssePae(payloadType, payload) SHALL produce the exact DSSEv1 <len> <type> <len> <body> byte sequence defined by the DSSE spec. wrapInDsse(statement, signatures) SHALL canonicalise and base64-encode the statement. verifyDsseEnvelope(envelope, keys) SHALL verify every signature against the supplied ed25519 keys, honouring per-signature keyid scoping, and return a structured DsseVerificationResult with per-signature records.

SLSA-10 Sigstore Rekor client

RekorClient SHALL support uploadHashedrekord (v0.0.1), uploadIntoto (v0.0.2 with auto-computed payload sha256), getEntryByUuid, and getEntryByLogIndex. The client SHALL accept an injectable fetch implementation and an AbortSignal on every request. Non-2xx responses SHALL raise RekorUploadError with the status code and response body attached. Rekor's { [uuid]: entry } response shape SHALL be flattened and Zod-validated.

SLSA-11 Inclusion proof verification

verifyRfc6962InclusionProof SHALL apply the RFC 6962 leaf (0x00) and interior-node (0x01) domain separators, correctly carry unsibled nodes at odd tree levels, and compare the computed root case-insensitively against expectedRootHex. Out-of-range logIndex values SHALL raise RekorInclusionError.

SLSA-12 Policy evaluator

evaluatePolicy(statement, envelope, rekorEntry, policy, opts?) SHALL compose verifyProvenance with DSSE signature verification, Rekor inclusion-proof presence, and min-SLSA-level assertion. The function SHALL NOT throw on policy failure — callers branch on result.valid.

SLSA-13 OTel audit events

The package SHALL export createSlsaOtelAdapter(tracer?) emitting slsa.provenance.generated, slsa.provenance.verified, slsa.rekor.upload, slsa.rekor.inclusion_verified, and slsa.policy.violation span events with attributes under the slsa.* namespace. When no active span and no tracer are present, events SHALL be silently discarded.

SLSA-14 Feature-module layout

Every feature SHALL live in src/<category>/<feature>/<feature>.{ts,test.ts,md} with an optional <feature>.types.ts. A sibling .md ≥200 words is required for every non-test .ts except barrels and .types.ts.

SLSA-15 Subpath exports

package.json exports SHALL include one entry per feature module (./provenance/provenance, ./verification/verification, ./sbom/sbom, ./assessment/assessment, ./attestation/dsse, ./rekor/rekor-client, ./rekor/inclusion-proof, ./policy/policy, ./errors, ./otel, ./schemas) to preserve tree-shaking.

SLSA-16 Coverage floor

Istanbul coverage SHALL meet the 95% floor on statements, branches, functions, and lines. Current: 99.2 / 95.15 / 100 / 99.44.