Your browser sucks, JavaScript disabled! Gunnar's console needs JavaScript and WebAssembly. Git over SSH on port 2222 does not.

nordisk/dwarves

crates/dwarves-slsa/README.md

dwarves-slsa

dwarves' release-build mode (SLSA v1.0 Build L3; owner 2026-10-29: dwarves is the build server). A release build is a Runa pipeline (lane RELBUILD-RUNA): this crate plans it (runner::release_pipeline: sealed Sandbox containers and the forge's own Forge actions), and the dwarves forge runs it through the same Runa runner every CI pipeline runs through (dwarves::release_runa), with CI's caps and cancel. Its runs are pipeline release-build's runs in the forge's history (dwarves history, the UI's Pipeline tab, the server's History / GetRunReport / StepLog). This crate also writes the provenance from the run's record, the DSSE envelope the owner's YubiKey signs, its verification and the attested publish. The dwarves command reaches it as dwarves release-build … and as the Build Thing path dwarves buildthing <product> --suite S --variant V --release-build. There is no shell script and no container program here. First user: the crates.io releases of Holger and Gunnar. The library (statement, dsse, verify, subjects, lock) is what the monetize self-release and the media builds call later; a new kind of build gets its own build type URI.

Builder id https://git.gunnar.rs/nordisk/dwarves/slsa/builders/dwarves-server/v1 (statement::BUILDER_ID), THE dwarves builder id: a Build Thing build's provenance step names it too (dwarves' version and commit, releaseMode, runnerAccount and runnerSha256 in runDetails.builder.version)
Pipeline release-build (pipelines/release-build.runa.ron is its shape; Runa run id <release>-<first 12 hex of the request's sha256>)
Build type https://git.gunnar.rs/nordisk/dwarves/slsa/buildtypes/cargo-release/v1
Image ci4, localhost/nordisk-cargo-toolchain@sha256:875a7a32… (runner::DEFAULT_IMAGE)

A release, step by step

# a lane asks the dwarves server (the CLI and the UI's "Request release" form call the
# same API, Dwarf.Trigger of release/release-build; neither writes the inbox):
dwarves release-build request --name holger-2.0.1 --steps-from ~/d-pub2/publish-holger-2.0.1.sh \
   --pins holger-2.0.1.pins --org tunnr=mikronova --lock holger/Cargo.toml --lock holger/estate/Cargo.toml \
   [--server 127.0.0.1:7911]
#   -> queued release run holger-2.0.1-<12 hex>
dwarves history                                   # the run, its release state
dwarves release-build show holger-2.0.1-<12 hex>  # state, statement, artifacts and sha256, the signing command
# the owner, on loki (the YubiKey never comes near dwarf or the browser):
~/script-sign-release.sh release.statement.json   # -> release.intoto.jsonl
dwarves release-build attach holger-2.0.1-<12 hex> release.intoto.jsonl   # verified, then stored; the runner checks it again: signed
# then, on a copy of the signed run:
dwarves release-build wait <run>                  # or verify-run <run>
dwarves release-build publish <run>               # dry run: each crate packaged again = the attested bytes
dwarves release-build publish <run> --for-real
dwarves release-build check-published <run>       # what crates.io serves = the subjects
dwarves release-build attest <run> --repo ~/d-slsa3/holger   # attestations/holger-2.0.1.intoto.jsonl; commit it

# a lane's own build (not release mode; into ~/slsa-runs):
dwarves release-build build --name … (the spec flags)
# a Build Thing variant (binaries from the sources, the repo at its clean HEAD):
dwarves buildthing gunnar --suite ORIGINAL --variant gunnar-open --release-build [--pins siblings.pins]

--steps is the STEPS table of a publish-*.sh script (n crate version repo path verify), --pins its pins file (repo full-sha). Versions crates.io already has are staged from crates.io by their index checksum and not rebuilt (--rebuild-published rebuilds them: a reproducibility check, not for publishing).

A spec (--spec) can also run an EXAMPLE of a workspace from the sources and take the files it writes as subjects (Heimdall's verify-bundle guests: dist builds the three wasm components and their .wasm.blake3). The guest is its own workspace, so its lock is a second lock:

lock = ["heimdall/Cargo.toml", "heimdall/guests/verify-bundle/Cargo.toml"]
[[workspace_example]]
manifest = "heimdall/guests/verify-bundle/Cargo.toml"
example = "dist"
args = ["{out}/guests", "/target/guests"]      # {out} = the example's own output directory
outputs = ["guests/heimdall-verify-bundle.wasm", "guests/heimdall-verify-bundle.wasm.blake3", …]

It runs cargo run --release --locked --offline --example dist -- /example-out/guests /target/guests in a build container (network none, CARGO_NET_OFFLINE=true, so cargo the example starts is offline too); the forge then copies exactly the declared outputs to out/ (a missing, undeclared or linked file is red). The image needs what the example needs (Heimdall's: wasm32, clang and wasi-libc's headers, heim-ci by digest).

Release mode: the runner's own account (dwarf's host)

The lanes run as rickard. A runner that shares that account could have its binary or a run directory changed before the owner signs. In release mode it cannot:

# once, and again for each new runner binary: as root on dwarf's HOST, from /
sudo bash scripts/relbuild-user.sh <dwarves binary: a host path, or a path in the claude container>

The owner signs the statement of /srv/relbuild/runs/<run>/ and checks its sha256 against the one show prints (the sign script shows it). The lanes then copy the signed run and run wait, publish, check-published and attest on the copy. After the signature, any change to a copy is refused.

scripts/relbuild-user.sh never touches the YubiKey.

The isolation (checked on the sealed containers' data before the pipeline exists)

The release key is keys/release-signing-key.pub: the owner's YubiKey key (PIV slot 9c, P-256, PIN once, touch always), key id d24d3785e8281bcd37e8f2c40a3a85e8152d3ce2200a5c929a1a5ca636e8249e (release_key::RELEASE_KEY_ID). It is the same file as slsa/release-signing-key.pub in holger and gunnar, where its YubiKey attestation sits beside it. verify, wait, verify-run, publish, check-published and attest use it unless --key or $SLSA_KEY names another key; a bundle signed with any other key (SLSA_TEST_KEY included) is refused.

The one-time YubiKey setup is scripts/yubikey-setup.sh (the owner's). Verification for users: Holger's and Gunnar's docs/SLSA.md.