Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions .github/workflows/claim-check.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
name: Claim Check

# Gate the repo's load-bearing public claims (README badges, compliance docs)
# against re-derivable evidence. Drift between a claim and the actual source
# fails the build. See claims.yaml + the `claim-verification` skill.

on:
push:
branches: [main]
pull_request:
workflow_dispatch:

permissions:
contents: read

jobs:
claim-check:
name: Documentation claims hold
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Install PyYAML
run: pip install --quiet pyyaml
- name: Re-derive claims from source
run: python3 verification/claim-check/claim-check.py claims.yaml
9 changes: 8 additions & 1 deletion .github/workflows/publish-to-crates-io.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,14 @@ on:

jobs:
publish:
if: github.repository == 'pulseengine/sigil'
# Disarmed until crates.io publishing is actually configured. Set the repo
# variable CRATES_PUBLISH_ENABLED=true once EITHER a crates.io Trusted
# Publisher is registered for pulseengine/sigil (OIDC, tokenless — preferred)
# OR a CRATES_IO_TOKEN secret with publish scope exists. Until then this job
# SKIPS (neutral) rather than failing red on every tag — a perpetually-red
# publish job is a dead signal, not a gate (#220). Arming it re-publishes the
# registry, which has lagged at 0.9.0 since the auth broke at v0.9.1.
if: github.repository == 'pulseengine/sigil' && vars.CRATES_PUBLISH_ENABLED == 'true'
# Stays on ubuntu-latest: crates.io trusted publishing via OIDC; keep release publication on a vetted, well-known runner image until self-hosted publication path is independently audited.
runs-on: ubuntu-latest
permissions:
Expand Down
58 changes: 58 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,64 @@
All notable changes to sigil are documented here. The project follows
[Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [0.10.0] — 2026-08-07

Provenance identity and claim honesty. Records *which qualified toolchain-set*
produced an artifact, and corrects load-bearing SLSA claims to what the cited
spec actually defines — each backed by a gate so the fix can't silently rot.

### Added

- **`ToolInfo` carries the toolchain-layer identity (#217 / #221).** Two
optional fields — `toolchain` and `toolchain_manifest_digest` — populated from
`VARVE_LAYER` / `VARVE_LAYER_MANIFEST_DIGEST` at each transformation hop via
`ToolInfo::with_varve_env()`, so an attestation records not just *which tool*
ran but *which qualified set* it came from (satisfies varve REQ-PROV-001).
Backward-compatible on both sides: the fields `skip_serializing_if` when
absent, so a non-varve attestation serializes **byte-identically** to before;
and no `deny_unknown_fields`, so a v0.9.x verifier accepts a new attestation
and simply ignores the added fields. *Falsification:* an attestation produced
outside a varve dispatch is byte-for-byte unchanged; one produced under varve
carries the layer identity in its signed payload, and an old signed
attestation still verifies.

### Changed

- **Honest SLSA claims — no phantom Level 4 (#216).** Docs claimed *"SLSA Level
4 ✅ ACHIEVED"* while citing SLSA **v1.0**, whose Build track defines **L0–L3
only** (Level 4 lived in the superseded v0.1 draft). Reframed every public
surface — the README badge (`SLSA-L4_provenance` → `SLSA-Build_L3`),
`docs/slsa-compliance.md`, the automotive/wac/research docs, and code comments
— to state what we meet (**Build L3**) and to describe the reproducibility +
offline/hardware-attestation work as *"the properties SLSA v0.1 called Level
4"* (beyond-L3 hardening), never as a v1.0 level. A fictional `--slsa-level 4`
CLI example (no such flag exists) was corrected and marked illustrative. STPA
loss identifiers (`L4`/`L5`) were left untouched — a different concept.
*Falsification:* the new `claim-check` gate re-derives `count-max: 0` on
`SLSA[ -](Level ?4|L4)` across README/docs/examples/src on every commit — the
claim reappearing fails the build; deleting the honest disclaimer fails a
`count-min` presence check. Proven potent by negative control before wiring.

### Fixed

- **crates.io publish no longer fails red on every tag (#220, groundwork).** The
publish workflow had failed on every tag since v0.9.1 (v0.9.0 was the last
success — hence the registry froze at 0.9.0). It's now **disarmed** behind
`vars.CRATES_PUBLISH_ENABLED` — it *skips* cleanly rather than a perpetual red
that reads as a dead gate — and re-arms with one variable once a crates.io
Trusted Publisher (OIDC) or `CRATES_IO_TOKEN` is configured. Actually
re-publishing the registry (backfilling 0.9.1→0.10.0) is tracked as REQ-22 in
v0.11.0. Also fixed a latent stale `wsc-crypto → wsc 0.9.0` internal pin.

### Verification notes

Feature-loop steps 1–2 (spar AADL → WIT) are **N/A** for this release — no
architecture or interface change; both items are a struct-field addition, a
docs/claim correction, and CI wiring. Step 5 (witness MC/DC) is unaffected:
`ToolInfo`/`with_varve_env` live in the host-side `wsc-attestation` crate, not
the no_std `verify-core` wasm path the gate instruments (confirmed by grep), so
the baseline is untouched — no second bump.

## [0.9.4] — 2026-08-05

Release-integrity fixes. Unbreaks the release pipeline and lands the *real*
Expand Down
10 changes: 5 additions & 5 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ exclude = [
]

[workspace.package]
version = "0.9.4"
version = "0.10.0"
edition = "2024"
authors = ["Frank Denis <github@pureftpd.org>", "Ralf Anton Beier <ralf_beier@me.com>"]
license = "MIT"
Expand Down
2 changes: 1 addition & 1 deletion MODULE.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
module(
name = "wsc",
# Keep in sync with [workspace.package].version in Cargo.toml.
version = "0.9.4",
version = "0.10.0",
)

# Dependencies
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
[![codecov](https://codecov.io/gh/pulseengine/sigil/graph/badge.svg)](https://codecov.io/gh/pulseengine/sigil)
![Rust](https://img.shields.io/badge/Rust-CE422B?style=flat-square&logo=rust&logoColor=white&labelColor=1a1b27)
![Sigstore](https://img.shields.io/badge/Sigstore-keyless_signing-654FF0?style=flat-square&labelColor=1a1b27)
![SLSA](https://img.shields.io/badge/SLSA-L4_provenance-00C853?style=flat-square&labelColor=1a1b27)
![SLSA](https://img.shields.io/badge/SLSA-Build_L3-00C853?style=flat-square&labelColor=1a1b27)
![License: MIT](https://img.shields.io/badge/License-MIT-blue?style=flat-square&labelColor=1a1b27)

&nbsp;
Expand Down
42 changes: 42 additions & 0 deletions artifacts/dev/features.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -607,3 +607,45 @@ artifacts:
links:
- type: traces-to
target: DD-10

- id: REQ-20
type: requirement
title: wsc-attestation ToolInfo carries toolchain-layer identity
status: verified
description: "ToolInfo gains optional toolchain + toolchain_manifest_digest fields, populated from VARVE_LAYER / VARVE_LAYER_MANIFEST_DIGEST at each transformation hop, so an attestation records not just which tool ran but which qualified toolchain-set it came from. Satisfies varve REQ-PROV-001. Backward-compatible: fields serde-skip when absent; old attestations deserialize unchanged."
tags: [attestation, provenance, varve]
fields:
release: v0.10.0
provenance:
created-by: ai-assisted
model: claude-opus-4-8
timestamp: 2026-08-07T11:40:52Z
release: v0.10.0

- id: REQ-21
type: requirement
title: SLSA level claims match the cited spec (no phantom L4)
status: verified
description: "Docs claiming 'SLSA Level 4 ACHIEVED' while citing SLSA v1.0 assert conformance to a level v1.0's Build track does not define (L0-L3 only; L4 is planned). The claim must state the highest level the cited spec defines and we actually meet (L3), with the L4 aspiration marked as not-yet-specified. Load-bearing: downstream compliance docs cite these."
tags: [docs, claim-honesty, slsa]
fields:
release: v0.10.0
provenance:
created-by: ai-assisted
model: claude-opus-4-8
timestamp: 2026-08-07T11:40:52Z
release: v0.10.0

- id: REQ-22
type: requirement
title: crates.io publish rides the v* tag so the registry never lags a release
status: draft
description: "Per release-artifact-pipeline Track B: the release workflow publishes wsc (and member crates) to crates.io on the v* tag. Currently the registry serves 0.9.0 while v0.9.4 is released — four versions of library fixes invisible to cargo-add consumers (varve pinned 0.9.0). Publish must be gated (dry-run + verify) so a stale registry can no longer diverge from a tagged release."
tags: [release, crates-io, supply-chain]
fields:
release: v0.10.0
provenance:
created-by: ai-assisted
model: claude-opus-4-8
timestamp: 2026-08-07T11:40:52Z
release: v0.11.0
57 changes: 57 additions & 0 deletions claims.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# claims.yaml — load-bearing public claims, bound to re-derivable evidence.
# Gated by verification/claim-check/claim-check.py in CI (.github/workflows/claim-check.yml).
# See the `claim-verification` skill: mark -> bind -> gate. Truth-over-time is a
# property of THIS GATE, not of whoever last edited the docs.
#
# Add a claim here whenever a doc asserts what the system *is / does / proves*
# (verification status, capability, compliance level, a trusted-base count).
# Bind it to a predicate a machine re-derives from source — never a number typed
# in prose.

claims:
# --- SLSA compliance (issue #216 / REQ-20 sibling REQ-21) ----------------
# Ground truth: SLSA v1.0's Build track defines Build L0-L3 ONLY. "Level 4"
# existed in the superseded v0.1 draft and was dropped in v1.0. Claiming
# "SLSA Level 4 ACHIEVED" against v1.0 asserts a level the spec does not define.

- id: SLSA-NO-PHANTOM-L4
doc: README.md # anchor doc (must exist); the gate is the glob below
evidence:
# The phantom claim must stay absent across ALL public surfaces. `count-max: 0`
# greens at zero matches and goes RED the instant "SLSA Level 4"/"SLSA L4"/
# "SLSA-L4" reappears. The mandatory `SLSA` adjacency is deliberate: it does
# NOT match STPA loss identifiers ("L4"/"L5" with no SLSA prefix) in
# docs/security/stpa-*.md, which are a different concept entirely.
- kind: count-max
pattern: 'SLSA[ -](Level ?4|L4)'
glob: ['README.md', 'docs/**/*.md', 'examples/**/*.md', 'src/**/*.rs']
max: 0

- id: SLSA-BADGE-HONEST
doc: README.md
# The README SLSA badge must state the level v1.0 defines and we meet (Build L3),
# not the phantom L4. The badge IS the evidence — relabel it, don't fake it.
evidence:
- kind: verbatim
text: 'SLSA-Build_L3'

- id: SLSA-L3-DISCLAIMER-PRESENT
doc: docs/slsa-compliance.md
# The honest scoping sentence must not be quietly deleted. count-min is the
# presence dual of count-max (which would green a 0-match). Regex '.' spans the
# en-dash in "L0-L3" so the encoding can't drift the check.
evidence:
- kind: count-min
pattern: 'SLSA v1\.0 defines Build L0.L3 only'
glob: ['docs/slsa-compliance.md']
min: 1

- id: SLSA-L3-EVIDENCE
doc: docs/slsa-compliance.md
# The Build-L3 claim rests on real artifacts: build-platform provenance emitted
# by the release workflow, and material-pinning reproducibility tracking.
evidence:
- kind: file-exists
path: .github/workflows/release.yml
- kind: file-exists
path: src/attestation/src/reproducibility.rs
10 changes: 5 additions & 5 deletions docs/automotive-regulatory-compliance.md
Original file line number Diff line number Diff line change
Expand Up @@ -464,7 +464,7 @@ println!("R155 supply chain verification passed");
#### R156-H7: Reproducibility

- **Regulation**: R156 7.1.7 -- Reproducible update process
- **sigil Capability**: Build provenance enabling SLSA Level 4 reproducible builds
- **sigil Capability**: Build provenance enabling beyond-L3 (v0.1-L4-class) offline reproducible builds
- **Evidence Provided**: Deterministic, verifiable builds with pinned dependencies
- **Traced Artifacts**: [[ASSET-020]], [[CR-8]], [[SP-6]] (reproducible builds), [[REQ-7]] (reproducible build requirement)
- **Traceability**: R156 7.1.7 -> [[REQ-7]] -> [[CR-8]] -> [[ASSET-020]] -> Evidence: in-toto attestation with pinned materials enables independent reproduction
Expand Down Expand Up @@ -655,7 +655,7 @@ println!("R156 traceability complete");
#### ISO-H7: Reproducible Builds (Clause 5.4.6)

- **Regulation**: ISO 21434 Clause 5.4.6 -- Deterministic, verifiable build processes
- **sigil Capability**: Build provenance enabling SLSA Level 4 reproducibility
- **sigil Capability**: Build provenance enabling beyond-L3 (v0.1-L4-class) offline reproducibility
- **Evidence Provided**: Deterministic, independently verifiable builds
- **Traced Artifacts**: [[ASSET-020]], [[CR-8]], [[SP-6]], [[REQ-7]], [[DD-3]] (deterministic composition)
- **Traceability**: ISO 21434 5.4.6 -> [[REQ-7]] -> [[DD-3]] -> [[CR-8]] -> Evidence: in-toto attestation with pinned materials and deterministic build process
Expand Down Expand Up @@ -1017,7 +1017,7 @@ Each tool integrates with sigil through specific data flow interfaces ([[DF-1]]
- Provenance and traceability -- [[CR-8]], [[CG-3]], [[ASSET-020]]
- Cryptographic integrity -- [[CR-1]], [[CR-3]], [[CG-1]], [[CG-2]]
- Standards alignment (SLSA, in-toto) -- [[REQ-1]] through [[REQ-5]]
- **Unique**: Offline/embedded SLSA Level 4 -- [[DD-2]], [[CG-5]], [[CTRL-5]]
- **Unique**: Offline/embedded beyond-L3 (v0.1-L4-class) reproducibility -- [[DD-2]], [[CG-5]], [[CTRL-5]]

**Gaps** (10-40%):
- Runtime monitoring and detection -- [[RR-1]], [[FEAT-5]]
Expand All @@ -1034,7 +1034,7 @@ Each tool integrates with sigil through specific data flow interfaces ([[DF-1]]

**2. sigil Excels at Build-Time Security**
- Best-in-class provenance tracking for WASM components -- [[CR-8]], [[ASSET-020]]
- Industry-leading offline/embedded support (SLSA L4) -- [[DD-2]], [[CG-5]]
- Industry-leading offline/embedded support (beyond-L3, v0.1-L4-class) -- [[DD-2]], [[CG-5]]
- Strong alignment with supply chain security requirements -- [[CR-11]], [[CTRL-3]]

**3. sigil Requires Integration**
Expand All @@ -1047,7 +1047,7 @@ Each tool integrates with sigil through specific data flow interfaces ([[DF-1]]
For organizations pursuing automotive/EU compliance, **sigil provides**:

1. **60-90% of supply chain security requirements** (vs 10-30% with traditional signing) -- [[CR-11]], [[CTRL-3]], [[ASSET-017]], [[ASSET-018]], [[ASSET-019]]
2. **Unique offline SLSA Level 4** capability (no other WASM tool has this) -- [[DD-2]], [[CG-5]], [[CTRL-5]]
2. **Unique offline beyond-L3 (v0.1-L4-class) reproducibility** capability (no other WASM tool has this) -- [[DD-2]], [[CG-5]], [[CTRL-5]]
3. **Standards-based evidence** (CycloneDX, in-toto, SLSA) -- [[REQ-1]] through [[REQ-5]]
4. **Audit-ready provenance** (embedded in artifacts, extractable for reports) -- [[CR-8]], [[ASSET-020]]
5. **Hardware security integration** (ATECC608, TPM for R155/CRA) -- [[CTRL-5]], [[SP-7]], [[ASSET-004]]
Expand Down
7 changes: 4 additions & 3 deletions docs/provenance-supply-chain-research.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ WebAssembly (WASM) component provenance is an emerging area at the intersection

### 1.1 SLSA Framework (Supply-chain Levels for Software Artifacts)

**What It Is**: A comprehensive framework defining 4 levels of supply chain security maturity, from Level 0 (no controls) to Level 4 (maximum security).
**What It Is**: A supply-chain security framework. The current **v1.0 Build track defines Build L0–L3 only** (L0 no guarantees → L3 hardened build platform with non-falsifiable provenance). An earlier, superseded v0.1 draft defined an additional Level 4 (hermetic + reproducible + two-person review); that level was dropped in v1.0 pending redefinition.

**Source**: https://slsa.dev/ (OpenSSF, 2021+)

Expand All @@ -54,7 +54,8 @@ WebAssembly (WASM) component provenance is an emerging area at the intersection
| **1** | Scripted | Unsigned provenance | Human review |
| **2** | Automated CI/CD | Signed provenance (OIDC) | Automated |
| **3** | Hardened CI/CD | Cryptographically signed | Key & policy verification |
| **4** | Hermetic + air-gapped | Signed + reproducible | Hardware roots of trust |

_SLSA v1.0 defines Build L0–L3 only. The hermetic + air-gapped + reproducible / hardware-root-of-trust properties above L3 are what v0.1 called Level 4 (v0.1-L4-class); v1.0 dropped that level pending redefinition._

#### Applicability to wsc

Expand All @@ -63,7 +64,7 @@ WebAssembly (WASM) component provenance is an emerging area at the intersection
- ✅ Signed provenance (Sigstore/Rekor)
- ✅ OIDC authentication

**For Embedded/Provisioning Mode**: Can achieve **SLSA Level 4**:
**For Embedded/Provisioning Mode**: Can achieve the **v0.1-L4-class properties beyond Build L3**:
- ✅ Pre-signed certificates (no OIDC needed)
- ✅ Hardware root of trust (ATECC608)
- ✅ Offline verification (no internet dependency)
Expand Down
Loading
Loading