bitwarden/bump-rust-sdk
Bump the server's util/RustSdk `bitwarden-crypto` git-rev pin to a bitwarden/clients release — map the client's sdk-internal version to a commit, fix breaking changes, then verify.
npx skills add https://github.com/bitwarden/server --skill bump-rust-sdk
util/RustSdk/rust/Cargo.toml pins bitwarden-crypto from bitwarden/sdk-internal by git rev; bump
it periodically to track a bitwarden/clients release. RustSdk is Seeder test infrastructure
(util/, not src/ production): it gives the C# Seeder field-level encryption
(encrypt_string/decrypt_string/encrypt_fields) to produce cryptographically correct Protected
Data for integration tests. EncryptPropertyAttribute drives which fields get encrypted.
Clients consume sdk-internal as npm (@bitwarden/sdk-internal, e.g. 0.2.0-main.841); the server
pins a git rev. The .NNN suffix is an opaque counter from a private Azure publish task — not a
GitHub Actions run_number, and it does not track main commits 1:1. Do not infer the SHA from a run
number or timestamp; both pick the wrong commit (verified: 841→c5d5bba, 842→c9f9dba, 840→1e45444
— no time correlation). Read the commit the build bakes into the published WASM instead:
# <VERSION> is the npm version from the clients release tag (Step 1), e.g. 0.2.0-main.841
cd "$(mktemp -d)"
curl -sSL "https://registry.npmjs.org/@bitwarden/sdk-internal/-/sdk-internal-<VERSION>.tgz" -o pkg.tgz
tar xzf pkg.tgz
grep -ao "main ([0-9a-f]\{7\})" package/bitwarden_wasm_internal_bg.wasm | sort -u # -> main (c5d5bba)
cd /path/to/sdk-internal && git rev-parse c5d5bba # -> full rev to pin in Cargo.toml
That full SHA is the exact source the production client runs. @bitwarden/commercial-sdk-internal
ships the same commit, so the open-source tarball's embedded SHA is authoritative for both.
web-v* release tag from clients, then its npm version: gh release list --repo bitwarden/clients --limit 5 | grep web-v
git -C /path/to/clients show <tag>:package.json | grep sdk-internal # -> 0.2.0-main.841
references/api-surface.md; watch fortype renames, removed/deprecated functions, changed signatures, and trait changes:
cd /path/to/sdk-internal
git log --oneline <old-rev>..<new-rev> -- crates/bitwarden-crypto
git diff <old-rev>..<new-rev> -- crates/bitwarden-crypto/src/keys/mod.rs crates/bitwarden-crypto/src/lib.rs
bitwarden-crypto rev in Cargo.toml.rust-version against util/RustSdk/rust-toolchain.toml;if the MSRV rose above our channel, bump the channel to the MSRV (not sdk-internal's dev
toolchain), else the build fails "requires rustc X or newer".
cargo update -p bitwarden-crypto (targeted — re-resolves only what the new rev needs; a barecargo update churns the lockfile).
#[allow(deprecated)] + a why-comment for newly-deprecated APIs. cd util/RustSdk/rust
cargo build && cargo test # roundtrip test is the gate: encrypt_string_decrypt_string_roundtrip
cargo fmt --check
git diff ../NativeMethods.g.cs # must be unchanged
dotnet test test/SeederApi.IntegrationTest/
Review the Cargo.lock diff for unexpected transitive crypto crates (rsa, aes, sha2).
Protected Data is decryptable in the web client:
cd util/SeederUtility
dotnet run -- organization -n SdkBumpTest -d sdk-bump-test.example -u 3 -c 10 -g 5 -o Traditional -m
# or a preset: dotnet run -- seed --preset dunder-mifflin-enterprise-full --mangle
# SeederApi HTTP alternative — start `dotnet run` in util/SeederApi, then:
curl -X POST localhost:5000/seed -H 'X-Play-Id: sdk-bump-test' -H 'Content-Type: application/json' \
-d '{"template":"SingleUserScene","arguments":{"email":"[email protected]","password":"<8+ char pwd>"}}'
curl -X DELETE localhost:5000/seed/sdk-bump-test # cleanup
Pass = seeded users log in with the fake master password (see util/SeederUtility/README.md),
ciphers are decryptable in the web vault, no Seeder errors, and cleanup deletes all tracked entities.
util/ test infrastructure, not src/ production; the server never decrypts Vault Data,so the zero-knowledge invariant is unaffected.
cryptographic primitives real clients use.
references/api-surface.md must mirror the actual code. After a bump, regenerate it: read every .rs
in util/RustSdk/rust/src/, extract the bitwarden_crypto use statements, and rewrite the file.
A Stop hook (.claude/hooks/rust-sdk-surface-check.sh) blocks if Cargo.toml changed but
api-surface.md did not.
| File | Change |
| --- | --- |
| util/RustSdk/rust/Cargo.toml | bitwarden-crypto rev pin |
| util/RustSdk/rust-toolchain.toml | bump channel only if the MSRV rose |
| util/RustSdk/rust/src/*.rs | breaking-change fixes |
| util/RustSdk/rust/Cargo.lock | re-resolved (cargo update -p bitwarden-crypto) |
| util/RustSdk/NativeMethods.g.cs | should NOT change — verify |
references/api-surface.md — types, traits, and functions imported from bitwarden-crypto.references/examples/2026-06-bump.md — the June 2026 bump, worked end-to-end.Take bitwarden/bump-rust-sdk from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.