Initial Commit

This commit is contained in:
2026-05-27 23:29:53 +01:00
commit fbc70f96e6
10000 changed files with 1102152 additions and 0 deletions

View File

@@ -0,0 +1,87 @@
# OpenSpec Change: enterprise-slsa
- **Change ID**: enterprise-slsa
- **Package**: `@suaveplan/slsa`
- **Category**: universal / auth
- **Target path**: `universal/auth/slsa`
- **Status**: SHIPPED
- **Date**: 2026-04-19
## Why
The genesis `@suaveplan/slsa` package previously shipped a thin, flat
`src/lib/*.ts` layout that produced in-toto/SLSA provenance, verified it
against a policy, emitted CycloneDX 1.5 SBOMs, and assessed the build
environment. That surface is foundational but well short of the
CLAUDE.md target for the package, which calls out DSSE attestation
envelopes, a Sigstore Rekor transparency-log client (upload + inclusion
proof verification), a composite policy evaluator, structured errors via
`@suaveplan/error`, Zod schemas on every wire-format type, OTel audit
events, and the standard four-file feature-module layout.
## What Changes
### ADDED
- Four-file co-located feature-module layout under
`universal/auth/slsa/src/<category>/<feature>/`.
- Structured errors: `SlsaError` base + stable `SLSA.*` code registry
via `defineCodes`, plus per-domain subclasses
(`InvalidProvenanceError`, `InvalidSbomError`,
`VerificationFailedError`, `PolicyViolationError`, `RekorUploadError`,
`RekorInclusionError`, `AttestationInvalidError`,
`EnvironmentUnsupportedError`).
- Zod schemas for every wire-format type: `ProvenanceStatementSchema`,
`SlsaProvenancePredicateSchema`, `BuildDefinitionSchema`,
`RunDetailsSchema`, `BuilderSchema`, `BuildMetadataSchema`,
`ResourceDescriptorSchema`, `DigestSetSchema`,
`VerificationPolicySchema`, `VerificationResultSchema`, `SbomSchema`,
`SbomComponentSchema`, `SbomInputSchema`, `SlsaAssessmentSchema`,
`AssessmentEnvironmentSchema`, `RekorEntrySchema`,
`InclusionProofSchema`, `DsseEnvelopeSchema`, `AttestationSchema` with
`parseProvenance` / `parseSbom` helpers.
- DSSE PAE + envelope: `encodeDssePae`, `wrapInDsse`,
`verifyDsseEnvelope` (ed25519, keyid-scoped trust).
- Sigstore Rekor client: `RekorClient` with injectable `fetch`,
`uploadHashedrekord` / `uploadIntoto` (v0.0.2),
`getEntryByUuid` / `getEntryByLogIndex`, `verifyInclusionProof`
(RFC 6962 with `0x00`/`0x01` domain separators, odd-size carry-up).
- Composite policy evaluator `evaluatePolicy` layering
`verifyProvenance` + DSSE signatures + Rekor inclusion + min SLSA
level.
- OTel audit adapter: `createSlsaOtelAdapter` emitting
`slsa.provenance.generated`, `slsa.provenance.verified`,
`slsa.rekor.upload`, `slsa.rekor.inclusion_verified`,
`slsa.policy.violation`.
- Canonical JSON helper (`canonicalize`) for deterministic hashing /
signing.
- `computeDigest` routed through `@suaveplan/crypto-hash` — no direct
`node:crypto` imports.
- Rekor-inclusion signal on the L3 assessment gate.
- Per-feature subpath `exports` in `package.json`.
- Root `README.md` linking every co-located module `.md`.
### REMOVED
- `src/lib/*.ts` flat layout and its `node:crypto` digest path.
- Plain `new Error(...)` throws in favour of structured
`SlsaError` subclasses.
## Impact
- `@suaveplan/slsa` gains workspace deps `@suaveplan/error`,
`@suaveplan/types`, `@suaveplan/crypto`, `@suaveplan/crypto-hash`,
`@suaveplan/crypto-utils`, `@suaveplan/serialize`, plus
`@opentelemetry/api` and `zod` from catalogs.
- Downstream consumers (publish pipeline, release gates) can now call
`evaluatePolicy` for a single pass/fail decision and will receive
typed errors with `instanceof` narrowing.
- No other packages depend on `@suaveplan/slsa` today, so there is no
cross-package migration burden.
## Verification
- `bunx turbo lint typecheck test --filter=@suaveplan/slsa` — all green.
- Istanbul coverage: 99.2% statements, 100% functions, 99.44% lines,
95.15% branches. Meets the 95% floor on every axis.
- 13 test files, 170 test cases.

View File

@@ -0,0 +1,138 @@
# 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.

View File

@@ -0,0 +1,129 @@
# Tasks — enterprise-slsa
> Closed 2026-04-19 — landed alongside this change; all tasks completed unless noted.
## Package scaffolding
- [x] Move from `src/lib/*.ts` flat layout to co-located four-file
feature modules.
- [x] Rewrite `package.json` with per-feature subpath `exports`.
- [x] Rewrite `vite.config.ts` for preserveModules + workspace externals.
- [x] Drop legacy `tsconfig.json`; keep `tsconfig.lib.json` only.
- [x] Rewrite `vitest.config.ts` with istanbul provider and
polyfills setup file.
- [x] Create `tests/setup/polyfills.ts` to polyfill WebCrypto under
Node.
## Dependencies
- [x] Add `@suaveplan/error` (workspace).
- [x] Add `@suaveplan/types` (workspace).
- [x] Add `@suaveplan/crypto` (workspace).
- [x] Add `@suaveplan/crypto-hash` (workspace).
- [x] Add `@suaveplan/crypto-utils` (workspace).
- [x] Add `@suaveplan/serialize` (workspace).
- [x] Add `@opentelemetry/api` (catalog:observability).
- [x] Add `zod` (catalog:forms).
## Errors
- [x] Create `SLSA_CODES` registry via `defineCodes`.
- [x] Create `SlsaError` base class.
- [x] Create `InvalidProvenanceError`.
- [x] Create `InvalidSbomError`.
- [x] Create `VerificationFailedError`.
- [x] Create `PolicyViolationError`.
- [x] Create `RekorUploadError`.
- [x] Create `RekorInclusionError`.
- [x] Create `AttestationInvalidError`.
- [x] Create `EnvironmentUnsupportedError`.
- [x] Co-located tests, md, and barrel.
## Schemas
- [x] Provenance schemas (`ProvenanceStatementSchema` and descendants).
- [x] SBOM schemas (`SbomSchema`, `SbomInputSchema`, components).
- [x] Verification schemas (`VerificationPolicySchema`,
`VerificationResultSchema`, assessment).
- [x] Attestation schemas (`DsseEnvelopeSchema`, `RekorEntrySchema`,
`InclusionProofSchema`).
- [x] `parseProvenance` / `parseSbom` with structured error output.
- [x] `parseProvenance` / `parseSbom` tests.
## OTel
- [x] `SlsaEventAttributes` typed attribute bag.
- [x] `SlsaOtelAdapter` interface + `createSlsaOtelAdapter` factory.
- [x] `noopSlsaOtelAdapter` default.
- [x] Co-located tests, md.
## Provenance
- [x] `canonicalize` (sorted-key JSON).
- [x] `computeDigest` via `@suaveplan/crypto-hash`.
- [x] `generateProvenance` with Zod-compatible inputs.
- [x] Validation via structured errors.
- [x] `serializeProvenance`, `hashProvenance`.
- [x] OTel `slsa.provenance.generated` event wiring.
- [x] Co-located tests, md.
## Verification
- [x] Split `checks.ts` rule file.
- [x] Add `checkBuildAge`, `checkSourceRepoPrefix`, `allowedBuilders`.
- [x] `verifyProvenance` with injectable clock and OTel adapter.
- [x] Co-located tests, md.
## SBOM
- [x] `generateSbom` with injectable clock + serial.
- [x] Structured `InvalidSbomError` on missing fields.
- [x] `serializeSbom`, `hashSbom`, `buildPurl`.
- [x] Co-located tests, md.
## Assessment
- [x] `assessSlsaLevel` with optional Rekor inclusion signal.
- [x] `detectEnvironment` reading `SLSA_*` env vars.
- [x] Co-located tests, md.
## Attestation (DSSE)
- [x] `encodeDssePae` per DSSE spec.
- [x] `wrapInDsse`.
- [x] `verifyDsseEnvelope` (ed25519, keyid scoping).
- [x] Co-located tests, md.
## Rekor
- [x] `verifyRfc6962InclusionProof` with odd-size carry-up.
- [x] `rfc6962LeafHash` utility.
- [x] `RekorClient` with injectable `fetch`.
- [x] `uploadHashedrekord` v0.0.1.
- [x] `uploadIntoto` v0.0.2 (computes payload sha256 automatically).
- [x] `getEntryByUuid`, `getEntryByLogIndex`.
- [x] `verifyInclusionProof` emits
`slsa.rekor.inclusion_verified` OTel event.
- [x] Response envelope flattening + Zod validation.
- [x] Co-located tests (no live Rekor), md.
## Policy
- [x] `evaluatePolicy` layering provenance verification + DSSE
signatures + Rekor inclusion + min SLSA level.
- [x] OTel `slsa.policy.violation` on failures.
- [x] Co-located tests, md.
## Docs
- [x] Co-located `.md` for every `.ts` implementation file.
- [x] Root `README.md` rewritten with Modules section.
## Verification
- [x] `bunx turbo typecheck --filter=@suaveplan/slsa` green.
- [x] `bunx turbo lint --filter=@suaveplan/slsa` green.
- [x] `bunx turbo test --filter=@suaveplan/slsa` green (170 tests).
- [x] `bunx turbo test:coverage --filter=@suaveplan/slsa` meets 95%
threshold on every axis.
- [x] `bunx turbo build --filter=@suaveplan/slsa` green.