Skip to content

fix(http): switch rustls crypto provider to ring#1493

Merged
chaliy merged 1 commit intomainfrom
claude/fix-aarch64-manylinux-aws-lc
Apr 30, 2026
Merged

fix(http): switch rustls crypto provider to ring#1493
chaliy merged 1 commit intomainfrom
claude/fix-aarch64-manylinux-aws-lc

Conversation

@chaliy
Copy link
Copy Markdown
Contributor

@chaliy chaliy commented Apr 30, 2026

Summary

The aarch64 manylinux wheel build for v0.2.0 failed with a C compile error in the aws-lc-sys crate:

aws-lc-sys-0.39.1/aws-lc/crypto/fipsmodule/cpucap/cpu_aarch64_linux.c:27:
  error: 'AT_HWCAP2' undeclared (first use in this function)

AT_HWCAP2 lives in glibc 2.18+ headers, but the manylinux2014 aarch64 cross sysroot baked into PyO3/maturin-action's auto container ships glibc 2.17. aws-lc-sys 0.39.x began referencing the constant unconditionally, breaking the entire publish-python.yml job after the v0.2.0 tag was created. The other six wheel targets (linux x86_64, macOS x86/arm64, windows, musl x86/aarch64) were unaffected because they don't cross-compile through that container.

Worse, aws-lc-sys is pulled in transitively by reqwest's rustls feature, so this regression could surface again any time the cross-sysroot vs. aws-lc-sys minimum-glibc gap shifts.

Fix

Drop the C-compiled crypto stack entirely:

  1. Switch reqwest from rustls (which transitively activates __rustls-aws-lc-rsaws-lc-rsaws-lc-sys) to rustls-no-provider.
  2. Add a direct workspace dep on rustls = "0.23" with the ring feature.
  3. Install ring as the process-wide default CryptoProvider before any reqwest client is built. ring is pure-Rust + asm and builds on every target we ship without a host toolchain dependency.

After this change:

$ cargo tree -i aws-lc-sys
error: package ID specification `aws-lc-sys` did not match any packages
$ cargo tree -i ring
ring v0.17.14
├── rustls v0.23.38
│   ├── bashkit, bashkit-bench, bashkit-cli, bashkit-eval, bashkit-js, bashkit-python
│   ├── hyper-rustls, tokio-rustls, …

Two install sites

The provider has to be installed before the first TLS handshake. Two places do this:

  • bashkit::network::client::build_client (under the http_client feature) — feeds bashkit-cli, bashkit-python, anything embedding bashkit with HTTP enabled.
  • bashkit-eval main — this binary uses reqwest directly without going through bashkit's http_client feature, so it can't piggyback on the helper above.

Both call paths go through an idempotent Once guard, so multiple invocations across crates and re-entrant code are safe. install_default returns Err after a provider is already present; we treat that as success because some provider is now active, which is all rustls needs.

Why this regressed silently

PR CI runs cargo build/cargo test on ubuntu-latest (x86_64) only. The aarch64 cross-compile path only fires inside publish-python.yml, which runs on release: published. So the bad combination rode all the way to the v0.2.0 GitHub Release.

Test coverage

Added in crates/bashkit/src/network/client.rs:

  • test_build_client_installs_ring_crypto_provider — calls build_client, then asserts a second install_default() returns Err. That's the proof the first install succeeded — exactly the invariant we need to keep TLS from panicking on first use.
  • test_install_default_crypto_provider_is_idempotent — multiple direct invocations don't panic; the Once guard works.

The 14 existing client tests under --features http_client continue to pass — none of them needed adjustment.

The actual end-to-end verification is the publish-python.yml aarch64 manylinux build itself, which can be re-dispatched against the v0.2.0 GitHub Release once this lands on main (no version bump needed).

Test plan

  • cargo fmt --check
  • cargo clippy --workspace --all-targets -- -D warnings
  • cargo test -p bashkit --lib --features http_client client (16 passed)
  • cargo tree -i aws-lc-sys returns "did not match any packages"
  • cargo tree -i ring shows ring as the sole crypto in all bashkit-* crates
  • CI green on PR
  • After merge: re-dispatch publish-python.yml for v0.2.0 and confirm aarch64 wheel builds + PyPI publishes

Coordination with #1492

This PR is independent of #1492 (Windows mount path fix). After both merge, we can re-run publish-python.yml and publish-js.yml against the existing v0.2.0 GitHub Release to push the missing wheels and npm package without cutting a new version.


Generated by Claude Code

Cross-compiled aarch64 manylinux wheel builds were failing inside
PyO3/maturin-action's auto manylinux container with:

  aws-lc-sys-0.39.1/aws-lc/crypto/fipsmodule/cpucap/cpu_aarch64_linux.c:27:
  error: 'AT_HWCAP2' undeclared

`AT_HWCAP2` lives in glibc 2.18+ headers, but the manylinux2014
aarch64 cross sysroot ships glibc 2.17. aws-lc-sys 0.39.x began
referencing it unconditionally, breaking the entire publish-python
job after v0.2.0 was tagged. The other six wheel targets (linux
x86_64, macOS x86/arm64, windows, musl x86/aarch64) were unaffected
because they don't cross-compile through that container.

Switch reqwest from `rustls` (which transitively pulls
`__rustls-aws-lc-rs`, `aws-lc-rs`, and `aws-lc-sys` -- all C-compiled)
to `rustls-no-provider`, then add a direct workspace dep on rustls
0.23 with `ring` enabled and install ring as the process-wide default
provider before any reqwest client is built.

After this change, `cargo tree -i aws-lc-sys` returns no match -- the
C-compiled crypto stack is gone. ring is pure-Rust + asm and builds
on every target we ship without a host toolchain dependency.

Two sites must install the provider:
- bashkit::network::client::build_client (under `http_client`,
  feeds bashkit-cli, bashkit-python via bashkit-cli, etc.)
- bashkit-eval main, which uses reqwest directly without going
  through bashkit's http_client feature

Both go through an idempotent `Once` guard so the install is
crash-safe across multiple call sites and re-entry.

Tests:
- new test_build_client_installs_ring_crypto_provider asserts that
  after `build_client`, a second `install_default()` returns Err --
  proving the first install succeeded
- new test_install_default_crypto_provider_is_idempotent confirms
  multiple calls don't panic
- existing 14 client tests still pass under --features http_client

Verified locally:
- cargo build --workspace
- cargo fmt --check
- cargo clippy --workspace --all-targets -- -D warnings
- cargo test -p bashkit --lib --features http_client client
  (16 passed, 0 failed)
- cargo tree -i aws-lc-sys -> "did not match any packages"
- cargo tree -i ring -> ring v0.17.14 used by all 5 bashkit-* crates
@cloudflare-workers-and-pages
Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Preview URL Updated (UTC)
✅ Deployment successful!
View logs
bashkit 7f61c8b Commit Preview URL

Branch Preview URL
Apr 30 2026, 04:38 PM

@chaliy chaliy merged commit 9a01b4d into main Apr 30, 2026
34 checks passed
@chaliy chaliy deleted the claude/fix-aarch64-manylinux-aws-lc branch April 30, 2026 17:04
@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 30, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@chaliy chaliy mentioned this pull request Apr 30, 2026
9 tasks
chaliy added a commit that referenced this pull request Apr 30, 2026
Patch release shipping #1492 (Windows mount path validation) and #1493 (rustls switched to ring) so the v0.2.0 publish-pipeline failures are unblocked.
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