open-standards/wai/http-conformance/falsify/whole-applies-no-digest.patch
Transaction Science ebe0b3dca3 wai: the HTTP plan follows SPEC §7.1's offer rule
http-delivery §7 step 4: an envelope offers its refinements only when every
component conforms, which the verified head's manifest decides. Where one does
not, each refinement component of the picked entry is dropped
(components_nonconforming) and never requested, one stating no sha256 dropped
for that too (step 5); the base's path does not change. §10.3 and §13 say so,
and the status block no longer states a limitation.

http_binding: plan.rs gains WhyWhole::ComponentsNonconforming; session.rs gates
the range path and the whole-object path alike, so the dropped report stays
complete on both: digest-absent drops first, then the nonconforming ones.
http_verify.py does the same with staged_verify.component_roles, which now holds
the Python port of check_component_roles that claim_verify.py and http_verify.py
both read (registry-based; wai-http.yml's paths add the registry).

Corpus: object ONC (a base, a companion bound to nothing, a refinement with its
sha256) and fetch_ONC_whole / fetch_ONC_ranged; fetch_ORN_* now report the
refinement dropped for both reasons. Falsify: nonconforming-offered.patch and
http_verify.py --mutate nonconforming-offered; whole-applies-no-digest.patch
re-targeted at the moved digest-absent drop.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-08 01:38:05 -04:00

15 lines
937 B
Diff

# must fail: fetch_ORN_whole
# the whole path drops a refinement that states no digest without its own reason (session::FetchSession::advance_rest)
diff --git a/wai/wai-rs/src/http_binding/session.rs b/wai/wai-rs/src/http_binding/session.rs
index 32c85293..bc971a72 100644
--- a/wai/wai-rs/src/http_binding/session.rs
+++ b/wai/wai-rs/src/http_binding/session.rs
@@ -871,7 +871,7 @@ impl FetchSession {
// §7 step 4: not offered from an envelope that does not conform; one stating
// no digest is dropped for that too, as on the range path.
if nonconforming.contains(&i) {
- if w.manifest.renditions[i].sha256.is_none() {
+ if false && w.manifest.renditions[i].sha256.is_none() {
dropped.push((i, WhyWhole::DigestAbsent { index: i }));
}
continue;