Found during an adversarial re-review of the schema-v2 stack (#287/#288). The core byte-determinism claim holds (no HashMap serialized, BTreeMap-backed extensions, aux sorted at create, golden test is a real cross-platform invariant). Two edge cases sit at the boundary of the "one bundle → one content address" guarantee.
1. serde_json feature unification. Nested serde_json::Value maps in extensions / attestations are BTreeMap-backed and key-sorted in this workspace (Cargo.lock has no indexmap). But if any crate in a downstream consumer's graph enables serde_json/preserve_order (or arbitrary_precision), feature unification flips Value map ordering to insertion order, changing the canonical bytes for manifests that carry extensions/attestations. The write_manifest_file doc already notes serializer settings matter; options are to (a) document this as an explicit build constraint, or (b) canonicalize Value trees (recursive key-sort) before writing so the address is independent of the feature.
2. Non-UTF-8 filenames embed lossily. path_to_manifest_string uses to_string_lossy, so a Unix filename with invalid UTF-8 canonicalizes fine, embeds with U+FFFD, passes the canonical-form check, then fails resolution at verify — violating the local "what create writes, verify must accept" contract. Fail-loud, deterministic, rare. A one-line OsStr-is-UTF-8 check at create (rejecting like the existing backslash case) would close it.
Severity: low / latent. Only affects manifests carrying extensions/attestations under an unusual downstream feature config (#1), or non-UTF-8 filenames (#2).
Found during an adversarial re-review of the schema-v2 stack (#287/#288). The core byte-determinism claim holds (no HashMap serialized, BTreeMap-backed extensions, aux sorted at create, golden test is a real cross-platform invariant). Two edge cases sit at the boundary of the "one bundle → one content address" guarantee.
1.
serde_jsonfeature unification. Nestedserde_json::Valuemaps inextensions/attestationsare BTreeMap-backed and key-sorted in this workspace (Cargo.lock has noindexmap). But if any crate in a downstream consumer's graph enablesserde_json/preserve_order(orarbitrary_precision), feature unification flipsValuemap ordering to insertion order, changing the canonical bytes for manifests that carry extensions/attestations. Thewrite_manifest_filedoc already notes serializer settings matter; options are to (a) document this as an explicit build constraint, or (b) canonicalizeValuetrees (recursive key-sort) before writing so the address is independent of the feature.2. Non-UTF-8 filenames embed lossily.
path_to_manifest_stringusesto_string_lossy, so a Unix filename with invalid UTF-8 canonicalizes fine, embeds with U+FFFD, passes the canonical-form check, then fails resolution at verify — violating the local "what create writes, verify must accept" contract. Fail-loud, deterministic, rare. A one-lineOsStr-is-UTF-8 check at create (rejecting like the existing backslash case) would close it.Severity: low / latent. Only affects manifests carrying extensions/attestations under an unusual downstream feature config (#1), or non-UTF-8 filenames (#2).