Skip to content

refactor: carve verification core into wsc-verify-core (wasm-buildable)#129

Open
avrabe wants to merge 1 commit into
mainfrom
refactor/wsc-verify-core-carve
Open

refactor: carve verification core into wsc-verify-core (wasm-buildable)#129
avrabe wants to merge 1 commit into
mainfrom
refactor/wsc-verify-core-carve

Conversation

@avrabe
Copy link
Copy Markdown
Contributor

@avrabe avrabe commented May 23, 2026

Summary

Splits the network-free verification core out of wsc into a new workspace crate wsc-verify-core so it builds for wasm32-* with plain cargo. Closes the blocker recorded on #128.

wsc transitively required ring (via rustls/ureq/rcgen/rustls-webpki/x509-parser) — ring does not build for wasm32-* with the default LLVM toolchain. The classic verification path itself (PublicKey::verify, verify_multi, the WASM module parser, the signature-section parser) needs none of those; they belong to the keyless/Sigstore/provisioning machinery. The carve separates the two so MC/DC coverage tools (witness) and any future wasm consumer can instrument the verification core directly with cargo build --target wasm32-*.

What moved

Into src/verify-core/:

  • wasm_module/ — varint, component, mod
  • signature/{hash,info,keys,matrix,multi,sig_sections,simple}.rs
  • split.rs (inherent impl Module {…} methods)
  • secure_file.rs (key file IO — needed by KeyPair::from_file)
  • A minimal CoreError (avoids the From<X509Error> for WSError orphan-rule trap)

wsc:

  • depends on wsc-verify-core
  • re-exports its public API (wsc::PublicKey, wsc::Module, wsc::SIGNATURE_*, etc. — unchanged)
  • has From<CoreError> for WSError so the boundary is transparent under ?
  • keeps signature/keyless/, composition/, airgapped/, sct/, provisioning/, http/, runtime/ — the layers that need the heavy deps

Verification

Local checks (this branch, this commit):

Check Result
cargo build --workspace clean
cargo test --workspace --lib 772 passed, 0 failed (588 wsc + 166 verify-core + 18 attestation)
cargo build -p wsc-verify-core --target wasm32-wasip2 clean — no ring
cargo build -p wsc-verify-core --target wasm32-unknown-unknown clean — no ring
cargo tree -p wsc-verify-core -i ring "package not found"
same for rustls, ureq, rcgen, rustls-webpki, x509-parser "package not found"

A clean-room verification subagent independently re-validated all 8 of the above against the actual branch state with no access to my reasoning — every claim CONFIRMED.

Bazel

  • New src/verify-core/BUILD.bazel (rust_library with only the 7 lightweight deps)
  • src/lib/BUILD.bazel adds //src/verify-core:wsc-verify-core as a dep

Local Bazel was blocked by the sandbox (no Nix in PATH, network unreachable for the wizer fetch). CI will validate end-to-end.

Why this matters beyond #128

The verification core no longer carries the keyless / TLS / X.509 dependency closure. That's a real reduction in the audit and supply-chain surface of the actual verification code — useful in itself, separate from the witness MC/DC goal it unblocks.

Test plan

  • cargo build --workspace, cargo test --workspace --lib
  • cargo build -p wsc-verify-core --target wasm32-wasip2
  • cargo build -p wsc-verify-core --target wasm32-unknown-unknown
  • Clean-room verifier subagent confirmed 8/8 claims
  • CI green (full Bazel + workspace matrix)
  • Follow-up: witness MC/DC harness against the new crate (MC/DC coverage for verification functions via witness (WASM harness) #128)

🤖 Generated with Claude Code

The `wsc` crate transitively required `ring` (via rustls/ureq/rcgen/
rustls-webpki/x509-parser), which does not build for `wasm32-*` with
the default LLVM toolchain. The classic verification path itself
(`PublicKey::verify`, `verify_multi`, the WASM module parser, the
signature-section parser) needs none of that — those deps live in the
keyless / Sigstore / provisioning machinery.

This commit splits the network-free verification core into a new
workspace crate `wsc-verify-core`, which builds cleanly for both
`wasm32-wasip2` and `wasm32-unknown-unknown` with plain cargo (no
`ring`, no TLS, no X.509). `wsc` depends on the new crate and
re-exports its public API, so the `wsc::*` surface is unchanged.

Moved into `src/verify-core/`:
- `wasm_module/` (module parsing — varint, component, mod)
- `signature/{hash,info,keys,matrix,multi,sig_sections,simple}.rs`
- `split.rs` (inherent `impl Module` methods)
- `secure_file.rs` (key file IO, needed by `KeyPair::from_file`)

A minimal `CoreError` lives in the new crate so the orphan rule on
`From<X509Error> for WSError` doesn't drag x509-parser back into core.
`From<CoreError> for WSError` in the outer crate makes the boundary
transparent under `?`.

Verified:
- `cargo build --workspace`                          — clean
- `cargo test --workspace --lib`                      — 754 tests pass
  (588 wsc + 166 wsc-verify-core + 18 wsc-attestation)
- `cargo build -p wsc-verify-core --target wasm32-wasip2`            — clean
- `cargo build -p wsc-verify-core --target wasm32-unknown-unknown`   — clean

Local Bazel validation was blocked by missing Nix / network in this
environment; CI will validate the Bazel side end-to-end.

Unblocks #128 (witness MC/DC harness): the verification core can now
be instrumented directly via `witness instrument` + plain cargo, with
no Bazel pipeline detour. Also tightens the verification core's audit
surface — it no longer carries the keyless/TLS dependency closure.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant