Summary

  • RFC 9682 makes its Appendix A normative and replaces the collected ABNF in RFC 8610 Appendix B after addressing Errata 6278, 6526, 6527, 6543 and 6575. Its most operationally visible string change repairs the escape grammar and adds \u{hex} for Unicode scalar values.
  • The compatibility direction is asymmetric. The update is designed so conforming older CDDL remains usable under the revised rules, while CDDL that uses newly available syntax is not automatically processable by older implementations. RFC 9682 explicitly warns that mixed updated and unupdated CDDL tools can create confusion and potentially different interpretations of models.
  • A standards citation, a successful parse, a generated validator and a successful runtime exchange establish different facts. A defensible acceptance record therefore has to preserve the chain from standards text and exact model source through parser capability, parse result, any schema compilation, the generated validator, the deployed consumer, the actual runtime message and finally observed interoperability.

The real compatibility boundary is executable

The deceptively simple change in RFC 9682 is an escape sequence. The deeper change is what that sequence reveals about versioned protocol tooling.

RFC 8610 described CDDL as a notation for expressing CBOR and JSON data structures. Its formal syntax was collected in a normative ABNF appendix, using the Augmented Backus-Naur Form defined by RFC 5234. But the original document contained a mismatch around string literals. In the prose of RFC 8610, text strings were supposed to follow JSON string conventions. In its collected ABNF, however, SESC was both too permissive in one direction and incomplete in another: it allowed many characters to be placed after a backslash while failing to express the JSON-style \uXXXX and surrogate-pair forms that the prose intended to allow.

That distinction matters because “accepted by the old ABNF” and “compliant with RFC 8610” were never necessarily identical propositions. RFC 9682 is not merely adding ornamental syntax to an otherwise perfect grammar. It repairs discrepancies collected through the RFC errata process and then republishes the full corrected grammar. Its Introduction states that the normative collected ABNF in Appendix A replaces RFC 8610 Appendix B. The update covers Errata 6278, 6526, 6527 and 6543 in its string work, while the clarification associated with Erratum 6575 appears in its treatment of tag and simple-value arguments. RFC 9682 is therefore the authoritative collected grammar for CDDL as updated by that document, not merely commentary on the 2019 text.

The repaired string rules make the intended escape repertoire explicit. They cover the JSON-style forms such as \u2318 and surrogate-pair notation for characters above U+FFFF, and they introduce the more direct \u{hex} form, where the hexadecimal value denotes a Unicode scalar value. The RFC’s own examples deliberately express the same string content several ways: as literal Unicode, JSON-style escapes and brace-delimited hexadecimal escapes. It shows, for example, \u{1F073} alongside the corresponding surrogate-pair notation and the literal character. The resulting string contents are byte-wise identical even though the CDDL source spellings are different. RFC 9682

That example supplies the first essential separation in an acceptance argument: source equivalence is not semantic equivalence. Two model files can differ byte for byte while denoting the same string value. Conversely, two processors can be given the same source bytes and still not establish the same operational result if one understands the new syntax and the other does not.

RFC 9682 is unusually direct about that boundary. It describes the new hexadecimal escape as a backward-compatible addition, but immediately says that it is not automatically forward compatible: CDDL specifications that use the new syntax do not necessarily work with existing implementations until those implementations are updated. The same general compatibility pattern applies to the document’s enabling grammar changes: older conforming material continues to fit the updated language, while newly expressible material cannot simply be assumed to fit processors implementing the earlier language. RFC 9682

“Backward compatible” therefore cannot safely be translated into “every processor in the estate will accept every file written after RFC 9682.” It describes the relationship between the language revisions, not a magical upgrade of already-installed software. An older processor does not acquire a new production rule because the RFC Editor publishes one.

Nor should an organization infer a specific failure mode for such a processor without evidence. RFC 9682 does not say that every unupdated parser will reject \u{hex} in the same way, issue the same diagnostic, or fail at the same processing stage. Its security discussion takes the more careful position: environments containing a mixture of updated and unupdated CDDL tools have increased potential for confusion, and attackers may try to exploit differences in how parts of a system interpret a model. That is a warning about heterogeneous implementation state, not a catalogue of product-specific bugs. RFC 9682

The repair also reaches beyond the new brace notation. Tightening SESC requires byte-string handling to account explicitly for an escaped apostrophe. The updated character productions make treatment of text strings, byte strings and comments more consistent, excluding DEL, the C1 control range and UTF-16 surrogate code points from the relevant unescaped character classes. RFC 9682 also explains that an earlier publication problem had lost backslashes in explanatory material associated with RFC 8610. These details reinforce the central point: the grammar revision concerns what source text means and what conforming processors should recognize. It does not, by itself, identify which executable in a deployment has implemented that meaning. RFC 9682

That gap is particularly important because CDDL sits one layer away from the protocol data it describes. RFC 8610 defines an instance as matching a CDDL specification when that data item is allowed by the specification. It was designed, among other goals, to enable automatic checking of CBOR data items for format compliance. But RFC 8610 also leaves the extent of enforcement to application designers and implementers. An application can use CDDL primarily as documentation, or it can enforce substantial portions of the description. The RFC explicitly says that it is not the intention for a CDDL tool to be “writing code” for an implementation.

That creates a hard evidentiary limit. A successful CDDL match proves something useful about a particular specification, instance and matcher. It does not by itself prove that an independently generated validator implements identical semantics, that an application invokes every relevant check, that the deployed binary contains the validator just examined, or that a peer running another processor will accept the same source model.

The CBOR boundary creates another distinction. CDDL is used to describe structures in the CBOR data model, while RFC 8949 specifies CBOR itself. RFC 8610 repeatedly distinguishes data-model constraints from particular serialization choices. For example, some CDDL expressions concern the set of values being described rather than mandating a particular floating-point representation, and an open-ended array description does not by itself dictate whether CBOR uses definite- or indefinite-length encoding. RFC 8610 That means “the model parsed” and even “the instance matched” should not be inflated into a universal claim about every wire-level property of a runtime message.

The useful control surface is therefore a chain of distinct acceptance claims:

Acceptance stage Evidence that belongs at this stage What it does not establish
Standards text The applicable language baseline, including RFC 8610 as updated by RFC 9682 Which deployed processors implement the update
Exact source model Immutable source bytes, version and content hash Whether any processor accepts those bytes
Parser Parser identity, version/build and declared or demonstrated support for the syntax used That another parser accepts or interprets the model identically
Parse result Acceptance or rejection of that exact model, with diagnostics and relevant interpreted literal values That downstream validation semantics are preserved
Schema compilation Where used, the exact compiler or transformation version, options and input identity That the resulting executable validator is semantically equivalent to the CDDL matcher
Generated validator Artifact identity plus evidence for the constraints and values it actually accepts and rejects That this is the artifact installed in production
Deployed consumer Exact deployed software/artifact identity and relevant configuration What a particular runtime message will do until exercised
Runtime message Exact encoded message, processing result and diagnostic or response actually observed General interoperability with other versions or peers
Observed interoperability Evidence that the required producer/consumer versions exchange the required messages successfully Compatibility with versions, syntax features or message classes that were not observed

This is not bureaucratic decomposition. Each row answers a different question.

Consider source syntax first. RFC 9682’s examples establish that a literal character, a JSON-style \u form and the new \u{hex} form can denote the same string content. So two source files may be semantically equivalent at the string-value level while having different parser compatibility. An updated parser may understand all three spellings. An older processor cannot be presumed to understand the newly added one merely because the resulting Unicode value would have been perfectly representable had it reached the semantic stage. RFC 9682

Now consider the inverse. The same source hash processed by two tools is strong evidence of source identity, but it is not evidence of parser identity. If the tools implement different CDDL grammar baselines, source equality has not eliminated the relevant variable. This is precisely why RFC 9682’s security considerations warn about combinations of updated and unupdated tools and about models being interpreted differently by different parts of a system. RFC 9682

The next boundary is between parse acceptance and semantic model. A parser saying “accepted” establishes that its syntax and associated processing accepted the document. For an escape-sensitive revision, stronger evidence records what value the parser attributed to the literal as well. When one source uses \u{1F073} and another uses a literal scalar value, the meaningful equivalence claim is not that their source files match; it is that the processor has derived the same intended string content and the surrounding CDDL semantics remain equivalent. RFC 9682 supplies examples of that equivalence, but each implementation path still needs evidence of its own acceptance. RFC 9682

A further boundary appears whenever an engineering workflow turns a CDDL model into some other schema representation or an executable validator. That activity may be useful, but it is downstream of what RFC 8610 defines. RFC 8610 describes CDDL matching semantics and possible automated checking; it does not standardize every code generator, intermediate representation, optimization or validator architecture that implementers may build around the language. A clean parse before that transformation therefore cannot prove semantic preservation after it.

That distinction becomes acute around strings. A generated validator might never see the textual escape notation at runtime because the escape was resolved while processing the model. In such a design, parser capability determines whether the validator can be produced from the source at all, while the validator’s runtime job concerns the resulting value constraint. In another design, different stages may retain or reinterpret more source information. Neither behavior should be inferred from the RFC. The correct evidence comes from the actual implementation under examination.

Then comes deployment. An artifact that was generated correctly is not evidence that the deployed consumer contains that artifact. A version label alone may also be weaker than the exact artifact identity where multiple builds or configurations exist. The acceptance record therefore needs to reconnect the deployed consumer to the validator evidence rather than assuming that successful earlier work automatically propagated into operation.

Finally comes the message itself. Runtime evidence should identify what was actually exchanged: the message bytes or an equivalently immutable representation, the consumer version that processed them, and the observed result. When interoperability matters across organizational or software boundaries, evidence should also identify the counterparty or peer compatibility set being exercised. A protocol exchange that succeeds between two updated components says nothing about an older required consumer that was absent from the observation.

A hypothetical example makes the asymmetry concrete. Suppose a protocol team has a model whose string constraint is written with a literal Unicode character. The model is accepted by every processor the team currently requires. The team later rewrites that character as \u{1F073} for ASCII-only source convenience, using syntax specifically demonstrated by RFC 9682. The intended string value has not changed; under the revised grammar, the two spellings can denote identical content. Yet the evidence obligation has changed because the source has crossed a parser-version boundary. The fact that the new source parses in an updated authoring tool proves acceptance there. It does not prove acceptance in an older release tool, an external consumer’s model checker, or any downstream component that reparses the source independently. No behavior should be attributed to those components until their versions and results are observed. RFC 9682

Now extend the hypothetical. An updated parser accepts the model, a validator is generated, and tests against that validator pass. Those facts improve confidence, but they still establish only part of the chain. If the released consumer contains an earlier validator, or if another required consumer constructs its validator with an older parser, the clean result upstream has not resolved the compatibility question. Likewise, if the generated validator accepts the intended string value but runtime messages fail because of an unrelated CBOR representation requirement, the source grammar was never the complete explanation. CDDL matching and CBOR encoding occupy related but distinct layers under RFC 8610 and RFC 8949.

RFC 9682 itself supplies the security rationale for preserving this provenance. It says implementations using CDDL models operationally need to establish the provenance, authenticity, integrity and applicability of the models they employ, and advises developers to treat such models with the same care as other source code. RFC 9682 A source-code treatment implies more than storing a filename: it means knowing exactly which revision was processed, by which tool version, to produce which artifact that later executed.

Three essays by Lu Heng provide a useful analytical lens, but not an additional CDDL requirement. In “Running-Code Primacy”, the core distinction is between declaration and operational adoption. In “Minimum Initial Specification, Localized Future Decision, and Voluntary Adoption”, publication is separated from implementation, validation, deployment and adoption. And “On Reality Layers, Symbolic Power, and Why Clarity Feels So Hostile” distinguishes symbolic claims from things that are executable in practice. These are Lu Heng’s governance arguments, not normative statements from the IETF. Applied narrowly here, however, they sharpen a legitimate engineering question: which artifact actually exercises control at each point in the workflow?

For RFC 9682, the answer can change from stage to stage. The RFC controls the current standards definition. The checked-in model controls the source presented to a tool. The parser version controls whether that source reaches a semantic representation. A compiler or generator, where present, controls how that representation becomes another executable form. The released validator controls the checks encoded into an artifact. The deployed consumer and its configuration control which checks are actually invoked. The runtime message determines what those checks encounter.

Interoperability is demonstrated only when the required endpoints successfully meet under the relevant conditions.

None of those facts cancels the others. The mistake is letting one masquerade as the rest.