Skip to main content

Attestation Envelopes

RStack already writes business-readable contracts for every governed task — builder.json, validation.json, and readiness reports. Attestations (#73) wrap those contracts in a DSSE-style envelope so the evidence is tamper-evident: the envelope records what was attested (run, task, commit, file checksums), who produced it (agent, harness, model), and the contract snapshot itself. Anyone can later verify that the evidence a report points at is still the evidence that was produced.

Artifacts

The layout is per-task (a multi-task run cannot be addressed by a single flat builder.attestation.json).

Envelope shape

Predicate types: rstack.dev/builder-contract/v1alpha1, rstack.dev/validator-contract/v1alpha1, rstack.dev/release-readiness/v1alpha1.

CLI

verify-attestations exits non-zero only when an envelope is invalid (stale subject, mismatched run, malformed predicate, bad signature). Contracts that simply have no envelope yet are listed as missing — informational, because attestation is opt-in per run. A checkout with no .rstack run exits 0: nothing to verify is not a failure, which makes the command safe as a CI step (it runs in ci.yml after the test suite).

Unsigned local mode vs signed mode

  • unsigned (default): no key configured. The envelope still detects drift — subject checksums catch any post-hoc edit to contracts or claimed files — but proves nothing about the author.
  • local-dev-signature: set the RSTACK_ATTESTATION_KEY environment variable and attest produces an HMAC-SHA256 signature over the canonical (key-order-independent) envelope payload. Verification requires the same key — shared-secret integrity for a team that controls the key. The key is only ever read from the environment, never a CLI flag.
  • Sigstore / keyless signing is a deliberate extension point: signature.type is open, and the verifier reports unknown types honestly instead of pretending to verify them.

What verification checks

Business Hub

The Run Report page shows an attestation timeline — one row per envelope with its verification verdict, producer signature type, and creation time — sourced from the same verifier the CLI uses.