Identifier
fiscal402.sorted-json/1. This is a Fiscal402 convention. It is not RFC 8785 JSON Canonicalization Scheme and is not an IANA standard.
Encoding
- Character encoding: UTF-8.
- Compact JSON:
JSON.stringifyafter key-sort. No spaces after:or,. No trailing newline. - Object keys sorted recursively with JavaScript string UTF-16 code unit order (
Object.keys(obj).sort()). - Keys whose value is
undefinedare omitted.nullis kept. - Array order is preserved. Elements are recursively canonicalized.
- Numbers follow JavaScript
JSON.stringify. Receipts do not emit NaN or Infinity. Monetary amounts are decimal strings.rate_percentis a JSON number. - Timestamps already on the record are not rewritten.
Signed payload
Hash every field except hashes and signature:
- spec, spec_version, receipt_id, mode, issued_at, protocol_version, tax_ruleset_version
- settlement, context, determination, fx, vies, artifacts, disclaimer
Algorithm
canonical
unsigned = receipt without hashes and signature
canonical = fiscal402.sorted-json/1(unsigned)
hashes.canonical_payload_sha256 = SHA-256(UTF-8 bytes of canonical)
signature.value = Ed25519(UTF-8 bytes of the hex digest string)The Ed25519 input is the hex digest string, not the raw 32-byte hash.
Legacy receipts
Receipts without hashes.canonicalization === "fiscal402.sorted-json/1" must be reported as legacy-stored-hash. Tools must not claim those payloads were reproduced with this identifier.