[agent] Filed by the scheduled architecture audit routine (CLI and core). Register: discussion #560 register.
Kind: refactor (mechanical, no behavior change). Source: review 4.4 and 7.3; register C17.
Problem (main @ 045d7ec)
utils::digest holds the shape validators. Its sha256_hex(&str) -> Option<String> and sha1_hex(&str) check and lowercase a hex string. The computations carrying the same names live elsewhere, as private copies:
-
sha256_hex(bytes) -> String exists three times:
vendor::verify::file_sha256_hex (L777) and ServiceFetch::sha256_hex are two more.
-
sha1_hex(bytes) exists twice: vendor/jvm/mod.rs and vendor/maven_repo.rs.``
-
The sha512 SRI is formatted three times. There is a public redirect::vlt_preflight::sha512_sri,`` yet vendor/npm_pack.rs and `vendor/bun_lock.rs` inline their own. `vendor` would also have to import from `patch::redirect` to reuse it, which goes against the layering.
-
About 20 production sites inline hex::encode(Sha256::digest(..)), for example in update/download.rs, policy/mod.rs, vendor/{verify,redownload,bun_workspace,bun_binary,state,nuget_feed,maven_repo,pypi}.rs and redirect/upstream/client.rs. Three more inline hex::encode(Sha1::digest(..)).
-
The 64-hex validator also exists three times: apply::is_valid_blob_hash, api::client::is_valid_sha256_hex and utils::digest::is_hex(s, 64).
No copy has drifted in its output yet; all of them produce lowercase hex. The hazard is the name clash: sha256_hex means validate in utils::digest and compute in three other modules, so an import can silently pick the wrong one.
Impact
This is maintenance cost and a misuse hazard, not a live bug. It is the prerequisite for one hash-comparison rule; the case-policy bug is filed separately.
Proposed change
- Add the compute helpers to
utils::digest: sha256_hex_of(&[u8]), sha1_hex_of(&[u8]) and sha512_sri_of(&[u8]), plus an async file_sha256_hex moved from vendor::verify. Rename the validators to parse_sha256_hex/parse_sha1_hex so no name means both things.
- Fold
apply::is_valid_blob_hash and client::is_valid_sha256_hex into digest::is_hex(s, 64), keeping is_valid_blob_hash as a thin re-export if the CLI uses it.
- Delete: the five private compute copies,
vlt_preflight::sha512_sri (callers move to digest), the inline SRI blocks in npm_pack and bun_lock, and the ~23 inline hex::encode(ShaN::digest) expressions in production code.
Size and scope
About 25 files, around 120 lines removed and 40 added, all mechanical. Out of scope:
- changing any comparison's case sensitivity (see the hash-case bug);
- the git-sha256 blob hash in
hash/git_sha256.rs, a different algorithm;
- test and bench fixture copies. A follow-up can switch tests over once the helpers exist.
Acceptance criteria
Dependencies
None. This unblocks the hash-comparison bug fix (one digest::hex_eq).
[agent] Filed by the scheduled architecture audit routine (CLI and core). Register: discussion #560 register.
Kind: refactor (mechanical, no behavior change). Source: review 4.4 and 7.3; register C17.
Problem (main @
045d7ec)utils::digestholds the shape validators. Itssha256_hex(&str) -> Option<String>andsha1_hex(&str)check and lowercase a hex string. The computations carrying the same names live elsewhere, as private copies:sha256_hex(bytes) -> Stringexists three times:vendor/jvm/mod.rs;vendor/ledger_snapshots.rs;``utils/group_commit.rs.``vendor::verify::file_sha256_hex(L777) andServiceFetch::sha256_hexare two more.sha1_hex(bytes)exists twice:vendor/jvm/mod.rsandvendor/maven_repo.rs.``The sha512 SRI is formatted three times. There is a public
redirect::vlt_preflight::sha512_sri,`` yetvendor/npm_pack.rsand `vendor/bun_lock.rs` inline their own. `vendor` would also have to import from `patch::redirect` to reuse it, which goes against the layering.About 20 production sites inline
hex::encode(Sha256::digest(..)), for example inupdate/download.rs,policy/mod.rs,vendor/{verify,redownload,bun_workspace,bun_binary,state,nuget_feed,maven_repo,pypi}.rsandredirect/upstream/client.rs. Three more inlinehex::encode(Sha1::digest(..)).The 64-hex validator also exists three times:
apply::is_valid_blob_hash,api::client::is_valid_sha256_hexandutils::digest::is_hex(s, 64).No copy has drifted in its output yet; all of them produce lowercase hex. The hazard is the name clash:
sha256_hexmeans validate inutils::digestand compute in three other modules, so an import can silently pick the wrong one.Impact
This is maintenance cost and a misuse hazard, not a live bug. It is the prerequisite for one hash-comparison rule; the case-policy bug is filed separately.
Proposed change
utils::digest:sha256_hex_of(&[u8]),sha1_hex_of(&[u8])andsha512_sri_of(&[u8]), plus an asyncfile_sha256_hexmoved fromvendor::verify. Rename the validators toparse_sha256_hex/parse_sha1_hexso no name means both things.apply::is_valid_blob_hashandclient::is_valid_sha256_hexintodigest::is_hex(s, 64), keepingis_valid_blob_hashas a thin re-export if the CLI uses it.vlt_preflight::sha512_sri(callers move todigest), the inline SRI blocks innpm_packandbun_lock, and the ~23 inlinehex::encode(ShaN::digest)expressions in production code.Size and scope
About 25 files, around 120 lines removed and 40 added, all mechanical. Out of scope:
hash/git_sha256.rs, a different algorithm;Acceptance criteria
rg 'hex::encode\((sha2::|sha1::)?Sha(1|256)::digest' crates/socket-patch-core/src crates/socket-patch-cli/srcmatches onlyutils/digest.rsand test modules.rg 'fn sha(1|256)_hex|fn sha512_sri'matches onlyutils/digest.rsin production code.utils/digest.rspins known vectors ("","abc") for all three compute helpers.cargo test -p socket-patch-coreand-p socket-patch-clistay green.Dependencies
None. This unblocks the hash-comparison bug fix (one
digest::hex_eq).