Summary
SigningContext::staging() doesn't exist as a public constructor, and the lower-level SigningContext::new(...) requires a Keyring type that isn't re-exported. As a downstream consumer trying to write CI-side end-to-end tests against staging Sigstore, I'd like a way to construct a staging-pointed SigningContext without polluting production's transparency log.
Versions audited
sigstore-rs v0.13.0 (latest released as of this issue)
sigstore-rs main branch (sampled at the same time)
In both, the public surface of sigstore::bundle::sign::SigningContext exposes:
SigningContext::production() → wired to production Fulcio + Rekor + CTFE.
SigningContext::async_production() → async variant.
There's no staging() counterpart. The new(fulcio, rekor, ctfe_keyring) constructor is pub, but Keyring is pub(crate) and not re-exported in the public module surface.
Use case
I'm a maintainer on a downstream OCI artifact pipeline (https://github.com/sweengineeringlabs/justoci) that uses sigstore-rs as the production signer. We want CI-side end-to-end tests that exercise the full sign flow against real Fulcio + Rekor — but on staging (https://fulcio.sigstage.dev / https://rekor.sigstage.dev), so we don't write CI test runs to the public production Rekor log (immutable, public, forever).
Today the only escape is to vendor the Keyring construction code into our own crate, which adds maintenance burden and risks divergence from upstream's trust-root format.
Proposed fix
Mirror production() with staging() (and async_staging()). Concretely:
impl SigningContext {
pub fn staging() -> SigstoreResult<Self> {
let trust_root = SigstoreTrustRoot::staging()?; // assuming this exists; if not, expose it too
Self::from_trust_root(trust_root)
}
pub async fn async_staging() -> SigstoreResult<Self> { ... }
}
This mirrors what cosign-cli does (COSIGN_EXPERIMENTAL=1 cosign sign-blob --rekor-url https://rekor.sigstage.dev ... with the staging trust root). Downstream users want the same affordance from the SDK.
Alternative (if staging() is undesirable for some reason)
Re-export Keyring (and SigstoreTrustRoot if needed) so external callers can construct a custom SigningContext::new(...) themselves. This is more flexible but pushes trust-root assembly to the caller, which is fragile.
I'd prefer staging().
Open questions
- Is there a reason
staging() was deliberately omitted? (e.g. discouraging accidental staging-in-prod.)
- If so, would gating it behind a Cargo feature like
staging be acceptable?
Happy to send a PR if there's appetite for either approach.
Context for future readers
This issue is being tracked downstream at sweengineeringlabs/justoci#21 — once an upstream fix lands and we bump the dep, our attest/tests/sigstore_e2e_test.rs (currently SKIP-passing) starts exercising real signing end-to-end.
Summary
SigningContext::staging()doesn't exist as a public constructor, and the lower-levelSigningContext::new(...)requires aKeyringtype that isn't re-exported. As a downstream consumer trying to write CI-side end-to-end tests against staging Sigstore, I'd like a way to construct a staging-pointedSigningContextwithout polluting production's transparency log.Versions audited
sigstore-rsv0.13.0 (latest released as of this issue)sigstore-rsmainbranch (sampled at the same time)In both, the public surface of
sigstore::bundle::sign::SigningContextexposes:SigningContext::production()→ wired to production Fulcio + Rekor + CTFE.SigningContext::async_production()→ async variant.There's no
staging()counterpart. Thenew(fulcio, rekor, ctfe_keyring)constructor ispub, butKeyringispub(crate)and not re-exported in the public module surface.Use case
I'm a maintainer on a downstream OCI artifact pipeline (https://github.com/sweengineeringlabs/justoci) that uses
sigstore-rsas the production signer. We want CI-side end-to-end tests that exercise the full sign flow against real Fulcio + Rekor — but on staging (https://fulcio.sigstage.dev / https://rekor.sigstage.dev), so we don't write CI test runs to the public production Rekor log (immutable, public, forever).Today the only escape is to vendor the
Keyringconstruction code into our own crate, which adds maintenance burden and risks divergence from upstream's trust-root format.Proposed fix
Mirror
production()withstaging()(andasync_staging()). Concretely:This mirrors what
cosign-clidoes (COSIGN_EXPERIMENTAL=1 cosign sign-blob --rekor-url https://rekor.sigstage.dev ...with the staging trust root). Downstream users want the same affordance from the SDK.Alternative (if
staging()is undesirable for some reason)Re-export
Keyring(andSigstoreTrustRootif needed) so external callers can construct a customSigningContext::new(...)themselves. This is more flexible but pushes trust-root assembly to the caller, which is fragile.I'd prefer
staging().Open questions
staging()was deliberately omitted? (e.g. discouraging accidental staging-in-prod.)stagingbe acceptable?Happy to send a PR if there's appetite for either approach.
Context for future readers
This issue is being tracked downstream at sweengineeringlabs/justoci#21 — once an upstream fix lands and we bump the dep, our
attest/tests/sigstore_e2e_test.rs(currently SKIP-passing) starts exercising real signing end-to-end.