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.