Working draft for public review. Not a stable standard, IETF adoption, certification or production recommendation. Experimental profiles require explicit opt-in.

WD-02 Erratum E1

Contents

15 October 2026 · Applies to Working Draft 02 · Publication ID WD-02-E1

This erratum corrects two edge cases in the public implementer tools and clarifies the corresponding requirements. Read it with the consolidated WD-02 with E1. The original WD-02, WD-01 and both original ZIPs remain unchanged. E1 is not a new protocol wire version or a production-readiness claim.

1. Email validation after IDNA conversion

Affected text: Encoding rules section 3. A domain ending in U+3002, U+FF0E or U+FF61 could pass the original-input trailing-dot check, then map to a prohibited ASCII trailing dot. The old helper could return an address that it rejected on a second canonicalization.

After UTS #46/IDNA conversion, implementations MUST validate the resulting DNS A-labels, reject a trailing dot or empty label, and enforce length limits before returning or hashing the address. Accepted output MUST be idempotent under the same canonicalizer. The E1 helper applies those post-conversion checks. Pairwise-ID and message-digest helpers consequently reject the same invalid inputs. Valid internationalized domains and internal mapped separators remain supported.

2. Numeric JSON tokens before host conversion

Affected text: Core sections 5 and 6. Python rejected 1.0, 1e3 and -0.0, while a generic JavaScript parser converted them to safe integers before validation. Checking only the resulting Number did not implement the same input policy.

The accepted raw number-token grammar is -?(0|[1-9][0-9]*), bounded to -9007199254740991 through 9007199254740991. Fractions and exponents MUST be rejected before conversion, including integer-valued or rounded forms. Quoted strings containing the same characters are not number tokens. -0 is an integer token whose canonical representation is 0; signed input still has to be already canonical.

The corrected Python strict_loads and Node strictLoads implement this gate on JSON text. Call them before canonicalization and schema validation; do not use JSON.parse as a substitute for the numeric gate. A host object serializer cannot infer whether a Number originally came from the token 1 or 1.0. This is a restricted XCIM input profile using JCS, not a change to RFC 8785's general numeric algorithm. The corrected fixture runners use the shared parser at their JSON input boundaries.

3. Compatibility and regression evidence

No signed object is rewritten, and the 33 WD-02 schemas and their canonical IDs remain byte-identical. The schemas describe values; raw numeric spelling is enforced before schema validation. Receivers reviewing historical evidence MUST retain its explicitly accepted historical policy rather than silently modifying bytes to fit E1.

The added suite has 12 test methods covering mapped trailing dots, ignored code points, valid/idempotent IDNA results, rejection before recipient hashing, numeric roots/nested values, safe bounds, quoted strings, duplicate names, invalid UTF-8, surrogate errors, and a correctly signed receipt containing a forbidden numeric token. The two languages consume shared numeric-input vectors. All inherited WD-02 checks and example commands remain available.

4. Download and verify

Use the E1 source ZIP, SHA-256 sidecar and release manifest, not an overwritten WD-02 archive. From a clean extraction with Python and Node.js installed:

python -m pip install -r tools/requirements-ci.txt
python tools/xcim_check.py
python tools/check_email_normalization_vector.py
python tools/check_message_recipient_vector.py
python tools/shadow_mode_adapter.py examples/xcim-shadow-mode.eml
node tools/verify_proof_bundle_vector.mjs

Fixture success remains offline/synthetic, not protocol PASS, fresh permission, chain finality, accreditation or independent interoperability. EVP remains experimental and the original review gates remain open.