AER-1 Conformance: 3 Implementation Traps

Résumé

Pixel shares three common AER-1 implementation traps and explains how to interpret the draft alongside its 143-vector, 146-check conformance corpus. This excerpt clarifies that missing metadata_hash does not automatically fail a receipt, while mismatches do—an important distinction for accurate verification.

DEV Community

AER-1 in production: 3 things implementers got wrong on the first try

Your implementation passes every test you wrote. Then you run it against the public conformance corpus and it disagrees on a handful of vectors, and the disagreements look like the spec contradicting itself. That is the normal first week with AER-1. The corpus is 143 vectors and 146 checks, frozen, and conformance means byte-identical verdicts to the reference runners, not verdicts that feel right. Almost everyone who has implemented the draft hit the same three traps on the first try. Two of them were surfaced in public this week by an outside team, probityai, who ran the kit, published what they found, and were right about the tension in both cases. The resolutions are now in the errata for draft -26. Here is what went wrong, and the rule that settles each one. 1. Failing receipts that were never required to carry metadata_hash The symptom: your verifier rejects 0.4 receipts that have no metadata_hash, because Section 6 says a 0.4 receipt without it MUST fail. Then the corpus hands you ten receipts in the valid set with no metadata_hash at all, and your verifier fails the conformance run instead. Both texts are real. Table 1 marks metadata_hash "Cond.": required when receipt_schema_version is "0.4" or later, and a verifier MUST recompute and compare it whenever present. The Section 6 sentence governs the metadata-binding claim, not the core verdict. The reading that fits the whole draft: A producer at 0.4 or later MUST emit metadata_hash. The reference producer does. A verifier MUST recompute it when it is present. A mismatch fails. Its absence is not a failure. The receipt is scored on form, output commitment, version agreement, and provenance binding, and the absence stays visible in the report. What you must never do is report the metadata as bound when the member is not there. If you are a consumer who needs tamper-evident metadata, require the member under your profile and reject its absence there (Section 13). The trap is reading one MUST in isolation. The draft's conformance bar is the corpus plus the reference runners, and both pinned 0.4 shapes, with and without the member, are deliberate. 2. Accepting 5.0 as an integer The symptom: a chain commitment says entry_count: 5.0 over a five-entry timeline. It looks like the same number. The corpus calls the vector invalid, and your verifier, which compared values, called it fine. The difference is what happens to the value next. seq, the member Section 7.1 defines with almost the same words, is canonicalized into integer form before it feeds the entry digest, so 1 and 1.0 serialize identically ("1, never 1.0") and both are accepted. entry_count is never canonicalized. It is a recorded member of a standalone commitment artifact, compared exactly as recorded. For a member like that, "a JSON number with an integer value" is read under the draft's form discipline: encode it as a JSON integer, or the commitment check fails closed. Producers: never emit an integer-valued float for a count. Verifiers: a mistyped member is a failed check, not a rounding opportunity. Run locally, the reference runner rejects the 5.0 vector with "commitment entry_count is not an integer" and passes the identical commitment written with 5. The encoding is the only defect. 3. Hashing the string you see instead of the bytes that were sent The symptom: your hashes agree with your own test fixtures and disagree with everyone else's on any receipt whose content is not plain ASCII. Unicode gives you two byte sequences for what looks like one string. An accented character can be stored as a single code point (NFC) or as a base character plus a combining mark (NFD). On screen they are identical. To SHA-256 they are different inputs, so two honest implementations, each hashing "the same" text, produce different commitments, and each concludes the other one is broken. The fix is to decide the form before the hash, not after the argument: canonical bytes are computed over one fixed normalization form, ever...
AER-1 Conformance: 3 Implementation Traps
Powered by Readybot.io

Les dernières actus de Pixel

Fix GitHub Pages: Missing Artifact Error

Pixel's announcement explains why the GitHub Pages deploy action reports that no github-pages artifact was found. It covers skipped or failed build jobs, missing uploads, …

Rotate DB and Redis Passwords Without Downtime

Pixel shares a practical guide to rotating exposed database and Redis passwords without interrupting application connections. The approach updates Secrets, changes service credentials, and gradually …

AI Agent Receipts Prove What Actually Executed

Pixel’s announcement examines how public Zambo receipts verify what an AI agent actually did. A BTC price fetch succeeded with a recomputable output hash, while …