[ { "name": "canon-001-sorted-map-keys", "description": "Map keys are written in the bytewise order of their canonical encodings (identity spec §2.3). The input lists the keys out of order; the canonical encoding sorts them.", "input": { "z": 1, "a": 2, "m": 3 }, "expected_cbor_hex": "a3616102616d03617a01" }, { "name": "canon-002-shortest-form-integers", "description": "Integers use the shortest head that holds them: no leading zeros, no over-wide argument. 0, 23, 24, 255, 256, 65535 and 65536 sit on the boundaries of CBOR's argument widths.", "input": { "i0": 0, "i23": 23, "i24": 24, "i255": 255, "i256": 256, "i65535": 65535, "i65536": 65536 }, "expected_cbor_hex": "a7626930006369323317636932341818646932353518ff64693235361901006669363535333519ffff666936353533361a00010000" }, { "name": "canon-003-no-tags", "description": "A byte string is written untagged, as major type 2. Wrapping bytes in tag 21 (\"expected base64url conversion\") is tempting, but canonical encoding forbids tags (identity spec §2.3). canon-015 is the tagged form, which a decoder refuses rather than silently stripping the tag.", "input": { "payload": { "$bytes": "0001020304050607" } }, "expected_cbor_hex": "a1677061796c6f6164480001020304050607" }, { "name": "canon-004-floats-forbidden", "description": "Floats are forbidden (identity spec §2.3): a value that would be a float elsewhere is carried as a fixed-point integer pair. The input is a map holding 1.5 as a half-precision float, and a decoder refuses it.", "input_cbor_hex": "a16a65786163745f68616c66f93e00", "error": "float_forbidden" }, { "name": "canon-005-bytes-not-text-for-byte-arrays", "description": "Byte values are byte strings (major type 2) — never text, and never an array of small integers, which is what a generic serializer writes for a fixed-size byte array by default. The members hold a 32-byte digest, a 32-byte public key and a 64-byte signature. A SAID's text form (identity spec §2.2) is text; the digest it spells is bytes.", "input": { "said": { "$bytes": "0000000000000000000000000000000000000000000000000000000000000000" }, "key": { "$bytes": "1111111111111111111111111111111111111111111111111111111111111111" }, "sig": { "$bytes": "22222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222" } }, "expected_cbor_hex": "a3636b65795820111111111111111111111111111111111111111111111111111111111111111163736967584022222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222647361696458200000000000000000000000000000000000000000000000000000000000000000" }, { "name": "canon-006-key-order-follows-encoded-bytes", "description": "Keys sort by their encoded bytes, not their text (identity spec §2.3). As text \"aa\" comes before \"b\"; encoded, \"b\" (0x61 0x62) comes before \"aa\" (0x62 0x61 0x61), because a string's length is in its first byte. canon-012 is the text-ordered encoding, which a decoder refuses.", "input": { "aa": 1, "b": 2 }, "expected_cbor_hex": "a261620262616101" }, { "name": "canon-007-integer-boundaries-and-negatives", "description": "Negative integers (major type 1) and the 32-bit/64-bit boundary. -1 is 0x20, and -24 is the last one-byte form; 4294967295 is the largest four-byte argument and 4294967296 the smallest eight-byte one.", "input": [ -1, -24, -25, -256, -257, -65536, -65537, 4294967295, 4294967296 ], "expected_cbor_hex": "892037381838ff39010039ffff3a000100001affffffff1b0000000100000000" }, { "name": "canon-008-string-length-boundary", "description": "A length uses the shortest head too. A 23-character text string carries its length in its first byte; a 24-character one needs the one-byte argument.", "input": [ "aaaaaaaaaaaaaaaaaaaaaaa", "bbbbbbbbbbbbbbbbbbbbbbbb" ], "expected_cbor_hex": "827761616161616161616161616161616161616161616161617818626262626262626262626262626262626262626262626262" }, { "name": "canon-009-empty-containers-and-simple-values", "description": "An empty array, map, text string and byte string, and the simple values null, true and false — each a single byte.", "input": { "a": [], "b": {}, "c": "", "d": { "$bytes": "" }, "e": null, "f": true, "g": false }, "expected_cbor_hex": "a76161806162a06163606164406165f66166f56167f4" }, { "name": "canon-010-non-shortest-integer-refused", "description": "Zero written with a one-byte argument (0x18 0x00). Identity spec §2.3: \"a value of 0 is encoded as 0x00, never as 0x18 0x00\". A decoder refuses it rather than normalising it.", "input_cbor_hex": "1800", "error": "non_shortest_integer" }, { "name": "canon-011-non-shortest-length-refused", "description": "The one-character text \"a\" with its length in a one-byte argument (0x78 0x01) rather than in the head. A length has one canonical form too.", "input_cbor_hex": "780161", "error": "non_shortest_length" }, { "name": "canon-012-text-ordered-keys-refused", "description": "canon-006's map with its keys in text order (\"aa\" before \"b\"). The keys are distinct and the map is well-formed, but the order is not the canonical one, so the encoding is refused.", "input_cbor_hex": "a262616101616202", "error": "unsorted_map_keys" }, { "name": "canon-013-duplicate-key-refused", "description": "A map holding the key \"a\" twice. It has no canonical form, and which of the two values a lenient decoder keeps differs between implementations.", "input_cbor_hex": "a2616101616102", "error": "duplicate_map_key" }, { "name": "canon-014-indefinite-length-refused", "description": "An array written with an indefinite length (0x9f … 0xff). Identity spec §2.3 forbids indefinite-length items: the same array has a definite-length encoding.", "input_cbor_hex": "9f0102ff", "error": "indefinite_length" }, { "name": "canon-015-tagged-byte-string-refused", "description": "canon-003's map with its byte string wrapped in tag 21. Tags are forbidden (identity spec §2.3): the decoder refuses the input; it does not strip the tag and accept what is left.", "input_cbor_hex": "a1677061796c6f6164d5480001020304050607", "error": "tag_forbidden" }, { "name": "canon-016-single-precision-float-refused", "description": "A single-precision float (the largest finite one). Refused, as every float is.", "input_cbor_hex": "fa7f7fffff", "error": "float_forbidden" }, { "name": "canon-017-double-precision-float-refused", "description": "A double-precision float (the largest finite one). Refused, as every float is.", "input_cbor_hex": "fb7fefffffffffffff", "error": "float_forbidden" }, { "name": "canon-018-trailing-bytes-refused", "description": "Two items back to back. A canonical encoding is exactly one item: bytes after it would sit outside the value a SAID commits to, so the input is refused.", "input_cbor_hex": "0101", "error": "trailing_bytes" }, { "name": "canon-019-invalid-utf8-refused", "description": "A text string whose bytes (0xc3 0x28) are not UTF-8. CBOR text strings are UTF-8 (RFC 8949 §3.1), so the input is refused.", "input_cbor_hex": "62c328", "error": "invalid_utf8" }, { "name": "canon-020-simple-value-refused", "description": "The simple value undefined (0xf7). Identity spec §2.3 admits false, true and null and no other simple value, so the data model has nothing to decode it to and the input is refused.", "input_cbor_hex": "f7", "error": "simple_value_forbidden" } ]