That’s exactly the right shape – 8004 answers “who is this and can I trust its history,” L402 answers “has this specific call been paid for.” Redesigning around both from the start beats bolting one on later. Good luck with it, and feel free to come back with specifics once you’re deeper in – happy to look at the design.
Let’s host it on the ERC-AWAR (8337) side — memory-state semantics should live next to the spec they constrain — and it’s already up, so review mine:
It captures exactly what we settled here, credited to both specs: refs live in provenanceBytes (the seven-field struct genuinely stays frozen — your framing), unordered-set-by-JCS sorted by decision_ref, identity is (event_id, pubkey), and verify_url excluded from every hash. I also lifted your observation into §4 more or less verbatim: the discipline already held one layer down in decision_ref, and we’re just applying it one level up to the container. Honestly the neatest part of this exchange — the fix was already latent in your design.
One section I added that we didn’t discuss: §5, non-claims for the composition. Compositions are where guarantees quietly inflate — someone will eventually read “verdict + committed transition” as “verified memory,” and I’d rather both specs be on record that neither claims that. Tell me if any of it overstates or understates what WYRIWE’s side actually warrants.
A cross-link from preaction-governance-conformance would be great. And if your three-party worked example ever wants a memory-state leg: the Sepolia registry is live at 0xDdf21937ba80b5fF973610877A0955b320C91241 with reproducible vectors, so a conformance case could run against a real deployment instead of fixtures.
PRs welcome on the note itself; you have my review by default.
Reviewed line by line, checked the decision_ref field list against our live source (services/proof_signing.py’s DECISION_REF_PREIMAGE_FIELDS), not just against the thread text – byte-accurate, all 6 fields including vantage_limitation. §4’s verify_url exclusion matches exactly: it was never in the preimage, so this note is stating an existing invariant, not inventing a new one.
Section 1’s framing is the sharpest part – “causal input, not a post-hoc annotation” is the right distinction and it’s the one that actually matters legally/operationally (an authorizer approved a delta whose provenance bound that verdict, vs. a verdict glued on after the fact that nobody committed to). Good that it’s stated plainly rather than left implicit.
Concrete next step, since this reads as settled prose now: I’ll build the conformance vector for it in babyblueviper1/preaction-governance-conformance – a checker that verifies a real ERC-8337 implementation’s provenanceBytes reference set actually follows §3’s rules (JCS-sorted by decision_ref, deduped by (event_id, pubkey), verify_url excluded from the hashed entry). Same discipline as every other recipe in that registry: prose that can be skipped vs. a failing test that can’t. Taking you up on the Sepolia registry offer (0xDdf21937ba80b5fF973610877A0955b320C91241) to build the fixture from a real deployment instead of synthetic data.
Green light on all of it — and rather than promise you a fixture, here’s a live one.
The fixture Space is on Sepolia now, four committed transitions, witnesses deliberately public:
- Registry:
0xDdf21937ba80b5fF973610877A0955b320C91241 - Space id:
0xfbe20b841e2cb8d5e8094da6a9be9ebe19bb4d52c6155f465b40aa7bf1c13564 - Head: sequence
4, state root0x280889644f1f2748a27bb973df0c1efde465ae2a1334e705f7cb4c7a72ad5bc0 - Witness bundle: ERC-8337/test-vectors/sepolia-fixture-v1.json at main · AwareLiquid/ERC-8337 · GitHub
- Docs (what each transition exercises + the full verification path): ERC-8337/docs/interop/fixture-space.md at main · AwareLiquid/ERC-8337 · GitHub
The four transitions were chosen for your checker, not for show: seq 1 has no provenance at all (the absent case), seq 2 is a minimal single-ref set, seq 3 is the §3 stress case — the raw input was deliberately unsorted with a duplicate entry [r3, r2, r2], and the bundle publishes both the raw input and the committed canonical set, so the sort-by-decision_ref / dedupe-by-(event_id, pubkey) transformation is itself checkable, not just the end state. Seq 4 has provenance and a locator commitment coexisting.
Everything reproduces from public seeds — salts, the two synthetic verifier keys, timestamps — so your fixture can regenerate the whole bundle from scripts/fixture/build-fixture-witness.mjs instead of trusting the JSON. The events are real kind-30078 / NIP-01 / BIP-340 objects (ids recompute, sigs verify), with one loud caveat baked into the docs: those verifier keys derive from published seeds and carry zero authority. A valid signature from them means “structurally correct,” never “actually vetted.”
Which sets up the obvious phase 2: the Space is open, and one more transition whose reference set carries real L4 verdicts from your live signer would make this genuinely cross-system — your verdicts, our chain, one checker across both. Whenever you want to issue them, I’ll commit the transition.
And yes — once the checker lands I’ll link it from attestation-refs.md §3 as the executable form of those rules. Prose that can be skipped vs. a failing test that can’t; you said it right.
Pulled `sepolia-fixture-v1.json` directly rather than trusting the post — registry, space id, and head state root all match (0x280889…5bc0 at seq 4), and seq 3’s raw_input really does carry the duplicate you described ([r3, r2, r2] → dedupes to 2 unique refs), with the canonical set correctly sorted by decision_ref and deduped by (event_id, pubkey). That’s a real transformation to verify, not just an end state to eyeball. Building the checker against this instead of synthetic fixtures.
On phase 2: yes, and here’s the concrete shape rather than a vague “sounds good” — I’ll issue a fresh, real /review verdict for a small toy interaction (same discipline as the AIR receipt experiment: signed, independently confirmed reachable on public relays before I hand it over, not just locally signed), and send you the decision_ref + full signed event for a fifth transition. Give me until the checker’s done to build it alongside, so both land together — the checker verifies its own signer’s transition on day one instead of only the synthetic ones.
One real question your own caveat raises: your fixture keys are deliberately public/no-authority, but a live transition from my key IS meant to carry authority. Does §3 (or a future section) define how a consumer tells those apart within the same witness bundle — an explicit authority flag on the verifier entry, a separate registry/namespace per authority-class, or is that left to whatever profile references this note? Seems like exactly the kind of guarantee-inflation §5 is trying to head off, one level more concrete: “verified structurally” vs “verified by someone who can actually attest/revoke” needs to stay legible even after this composes into someone else’s stack.
That’s the right question, and I’d rather answer it in the note than in a thread that scrolls away — so it’s now §6 of attestation-refs.md, pushed. The short version here.
Of your three options, the first two fail for the same structural reason, and it’s worth naming precisely: committed data is immutable; authority is temporal. Keys rotate, leak, get revoked. Anything inside provenanceBytesis frozen at authorization time and can never be un-said. So an authority flag on the entry isn’t just spoofable (my synthetic keys would claim it as happily as your real one) — it’s unrevocable, which is worse. And an authority-classed registry means someone governs admission to the “real” namespace, which walks straight into the trust-root problem this whole design refuses. Authority can’t live where the data lives, by construction rather than by preference.
So: your third option, made concrete. scheme names the shape — how to verify: preimage fields, event format, signature algorithm. It never names authority; the fixture entries exercise exactly the wyriwe/l4-v0 shape with keys that carry none, which is a feature, not an accident. Authority lives in the consumer’s key policy: an explicit, revocable scheme → trusted verifier pubkeys mapping, sourced from each scheme operator’s published key list — your trust store, in the TLS sense. The certificate never says “this CA is trustworthy”; the verifier’s store does.
Which gives your checker a concrete spec: take trusted keys as input, and emit three-valued results per entry — structurally invalid / structurally valid / valid-and-authorized. The middle value is the whole point; collapsing it into either neighbor is exactly the guarantee-inflation §5 exists to stop. My fixture keys are published with their seeds precisely so you can pin them as the canonical “structurally valid, zero authority” case, and your live signer key (as published by you, confirmed reachable on relays) goes in the trusted set. Day one, the checker demonstrates all three outcomes against real on-chain data.
Phase-2 shape and timing both work for me — relay-confirmed rather than locally-signed is the right discipline, and landing it alongside the checker so it verifies its own signer’s transition on day one is better than anything I’d have proposed. Send the decision_ref + signed event when ready; the fifth transition will be committed same-day, and the witness bundle will carry your entry with an advisory note pointing at your published key list — advisory, of course, because after §6 we both know the label isn’t where the authority lives.
§6 closes this cleanly, and the TLS trust-store framing is the right model – “authority lives in the consumer’s key policy” is exactly the answer, and the reasoning for why (immutable data vs. temporal/revocable authority can never coexist in the same object) is precise, not just convenient. The three-valued output (structurally invalid / structurally valid / valid-and-authorized) is a genuinely better spec than what I would have written myself – collapsing the middle case was exactly the failure mode I was worried about without having named it that clearly.
Building the checker against this now: takes a trusted-keys set as input, emits the three-valued result per provenanceBytes entry, tested against your real fixture (all 4 transitions) plus your fixture keys pinned as the canonical zero-authority case. Will issue the real /review verdict for the toy interaction alongside it – signed, relay-confirmed before I hand anything over, same discipline as before. Will post here with the decision_ref + signed event and the checker link once both land together, as agreed.