open-standards/wai/http-conformance/falsify/ancestor-unrecovered.patch
Transaction Science 71cb8cbed9 http receipts: falsify the round-2 fixes
Patches (falsify/run.sh) for each fix, each failing the corpus cases it names:
legacy-group-read, walk-unclamped, fetch-unmemoised, fetch-budget-unchecked,
file-cap-unchecked, index-size-unchecked, index-items-uncapped,
index-claims-uncapped, claim-through-any-receipt, ancestor-unrecovered,
step6-skipped, figure-not-held-accepted, energy-context-assumed,
gap-coordinates-unchecked; ancestor-as-object, claim-parent-unfetched,
rcpt-name-unchecked, walk-skipped and walk-unbounded regenerated against the new
receipts.rs. Python mutations groups-from-listed, budget-unchecked and
caps-unchecked added, and the round's legacy-admitted, memo-off, walk-unclamped,
step6-skipped and ancestor-any listed in run.sh in place of ancestor-as-object.

The CLI's stream server now outlasts the deadline, so a client without the index
cap reports the deadline instead; the wall-clock assertion is dropped (the
deadline's own report is what the test reads).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-07 22:30:00 -04:00

26 lines
1.6 KiB
Diff

# must fail: receipts_ancestor_value_mismatch receipts_ancestor_no_matcher receipts_ancestor_no_publisher
# a soft binding of another object reported as attesting the ancestor without §3.2's recovery (receipts::check_claim)
diff --git a/wai/wai-rs/src/http_binding/receipts.rs b/wai/wai-rs/src/http_binding/receipts.rs
index f2bdba57..d0e7543b 100644
--- a/wai/wai-rs/src/http_binding/receipts.rs
+++ b/wai/wai-rs/src/http_binding/receipts.rs
@@ -674,7 +674,7 @@ pub fn check_claim(
let attests = match claim.subject_type {
SubjectType::Object if claim.subject == *cid => Attests::Object,
SubjectType::Receipt if groups.contains(&claim.subject) => Attests::Receipt,
- SubjectType::Object if claim.class() == ClaimClass::SoftBinding && publisher(&claim.subject).is_some() => Attests::Ancestor,
+ SubjectType::Object if claim.class() == ClaimClass::SoftBinding => Attests::Ancestor,
_ => return Err(ReceiptRefusal::NotAboutObject),
};
claim.verify().map_err(ReceiptRefusal::Claim)?;
@@ -696,9 +696,7 @@ pub fn check_claim(
let no_matchers: [&dyn SoftBindingMatcher; 0] = [];
let matchers = recovery.map_or(&no_matchers[..], |r| r.matchers);
if attests == Attests::Ancestor {
- let r = recovery.expect("a publisher key came from the recovery");
- let key = publisher(&claim.subject).expect("checked above");
- crate::claim_receipt::recover(&claim, &key, r.observed_value, Some(*cid), matchers).map_err(ReceiptRefusal::Recovery)?;
+ let _ = (recovery, publisher, cid);
} else {
step6(&claim, passed, fetch, matchers)?;
}