Conformance checklist
Level: the spec's keyword; spec = stated without a keyword; advice = these pages, not the spec.
Generating
| Rule | Level |
|---|---|
| Variant 0: 43-bit ms timestamp, then 57 random bits | spec |
| Timestamp past 2⁴³ − 1: keep the low 43 bits, don't error | SHOULD |
| Variant 1: all 100 payload bits random | spec |
| CSPRNG for both variants | advice |
Fixed bits: UUID version 0x8, UUID variant 0b10, TNID variant 0b00 or 0b01 | MUST |
| Name: 1–4 characters, null-padded at the low end | MUST |
TNID strings
| Rule | Level |
|---|---|
Format: name, ., 17 data characters | MUST |
| Reject: anything else, including whitespace and non-ASCII | MUST |
| Case-sensitive: never change case | spec |
| Not base64: don't use a base64 library | spec |
UUID form and 128-bit values
| Rule | Level |
|---|---|
| UUID form: read either case, write lowercase | RFC 9562 |
| Byte order: big-endian | spec |
Version and variant: exactly 0x8 and 0b10, not just the high bit | MUST |
| Name bits: reject all-null, or non-null after null | MUST |
| Reserved variants: accept TNID variants 2 and 3; opaque payload | SHOULD |
Extensions
Optional. An implementation that provides one MUST follow it exactly.
| Rule | Level |
|---|---|
| V0/V1 encryption: FF1, AES-128, radix 16, 25 digits, empty tweak, 10 rounds | MUST |
| Byte-identical output for the same input and key | MUST |
| Already in the target variant: return the input unchanged | SHOULD |
| Blocklist matching: case-insensitive substrings of the 17 data characters; patterns unmodified | MUST |
| Escaping a match: new random bits; advance the timestamp if the match is within characters 1–7 | SHOULD |
| Giving up: error, never block indefinitely | MUST |
| With encryption: check both the variant 0 and variant 1 data strings | SHOULD |
Testing
Pass every test vector, must-reject cases included; also in test-vectors.json.