Skip to main content

Python CI

cddl-verifier

Validate CBOR (RFC 8949) data against CDDL (RFC 8610) schemas, render it as annotated EDN (Extended Diagnostic Notation), and convert between CBOR and JSON. It is built for attestation formats such as CoRIM and CoSWID.

Scope. cddl-verifier supports a practical subset of CDDL and CBOR. It does not claim full RFC 8610 or RFC 8949 conformance yet; see Limitations and docs/CDDL_SUPPORT.md.

Surface Name
PyPI distribution cddl-verifier
Python import package cddl_verifier
Command-line tool cddl-verify

Installation

pip install cddl-verifier

Requires Python 3.9 or newer. There are no runtime dependencies: CBOR encoding and decoding are bundled. Extras for contributors: pip install "cddl-verifier[test]" (pytest) and [dev] (pytest, build, twine).

Quick start

Command line

cddl-verify schema.cddl data.cbor --type corim-map                     # validate, print annotated EDN
cddl-verify schema.cddl data.cbor --type corim-map --output data.edn   # write EDN to a file
cddl-verify schema.cddl data.cbor --show-types                         # list the parsed CDDL types

The exit status is 1 when the CBOR cannot be decoded or, with --type, when validation fails. Without --type the first rule is used and validation errors are only warnings (exit status 0). python -m cddl_verifier takes the same arguments. See docs/CLI.md.

Python

from pathlib import Path
from cddl_verifier import validate

result = validate(Path("schema.cddl"), Path("data.cbor").read_bytes(),
                  root_type="corim-map")
if result.valid:
    print("valid")
else:
    for diagnostic in result.diagnostics:
        print(diagnostic.code, diagnostic.message)
  • schema is CDDL text (str) or a path (pathlib.Path).
  • data is CBOR bytes or an already-decoded Python value.
  • root_type defaults to the first rule in the schema.
  • CBOR that cannot be decoded gives an invalid result with a "decode" diagnostic and its byte offset; it does not raise.

To check many items against one schema, or to render EDN, use Validator:

from cddl_verifier import Validator

validator = Validator(Path("schema.cddl"))
result = validator.validate(cbor_bytes, root_type="corim-map")
print(validator.to_edn(cbor_bytes, root_type="corim-map"))

CBOR and JSON helpers:

from cddl_verifier.cbor import encode, decode
from cddl_verifier.json_codec import cbor_to_json

raw = encode({0: "Alice", 1: b"\x01"}, canonical=True)
assert decode(raw) == {0: "Alice", 1: b"\x01"}
print(cbor_to_json(raw, typed=True, pretty=True))

Decoding is strict: the input must be exactly one complete CBOR item. Empty, truncated or trailing-byte input raises CBORDecodeError with the byte offset of the problem. See docs/API.md for the full API.

What is supported

  • CDDL maps, arrays, type aliases, groups, type choices (/=), sockets (//=), optional fields, occurrence indicators, IANA-registered parameters (&(name: n)), CBOR tags (#6.n(...)), .cbor, .size, .regexp and value-range controls on integers. Details: docs/CDDL_SUPPORT.md.
  • Real CoRIM and CoSWID schemas: docs/CORIM_SUPPORT.md.
  • CBOR encoding and strict decoding with byte offsets in errors; duplicate map keys, invalid UTF-8 and excessive nesting are rejected.
  • Annotated EDN output with field names from the schema.
  • CBOR ↔ JSON conversion. typed=True keeps byte strings and tags, but non-string map keys (such as the integer keys in CoRIM maps) still become JSON strings, so maps with such keys do not round-trip exactly.

Limitations

  • CDDL: a practical subset, not the full RFC 8610 grammar. Malformed schemas are often accepted without an error. A standards-oriented parser is planned (#69, #70).
  • .size: counts characters instead of UTF-8 bytes on tstr, and is not enforced on uint (#67).
  • Canonical encoding: map keys are sorted and integers are shortest-form, but floats are always written as 8-byte doubles, so output is not fully RFC 8949 §4.2 deterministic (#66).
  • CBOR: indefinite-length items and undefined are not supported (CBORUnsupportedError). CBOR sequences are rejected; a sequence API is not available yet.
  • Value types: tags decode to (tag, value) tuples and arrays or maps used as map keys decode to tuples. These are provisional and expected to change (#78, #88).

Documentation

Document Contents
docs/CLI.md cddl-verify and JSON converter options, input rules, EDN output formats
docs/API.md Python API: validate, Validator, CBOR and JSON helpers
docs/CDDL_SUPPORT.md Supported CDDL syntax, types, and validation behaviour
docs/CORIM_SUPPORT.md CoRIM / CoSWID schema support
docs/CBOR_BUILDER_QUICK_REF.md, docs/ITERATIVE_CONSTRUCTION.md CBOR builder API in depth
docs/CBOR_DIAGNOSTIC_DUMP.md Diagnostic dump format
docs/CANONICAL_AND_JSON.md Canonical encoding and JSON round-trips
docs/ EDN formatting, tag notation, and annotation notes
TESTING.md Running and writing tests, CI setup
CHANGELOG.md Release history

Development

git clone https://github.com/sahebbiswas/cddl_verifier
cd cddl_verifier
pip install -e ".[test]"
pytest

The package source is in src/cddl_verifier/. Modules whose names start with an underscore are internal. See TESTING.md.

Versioning

The project follows Semantic Versioning 2.0.0. While the major version is 0, a minor bump (0.x.0) may contain breaking changes and a patch bump (0.x.y) is for backward-compatible fixes. The stable surface is the public API above (cddl_verifier, cddl_verifier.cbor, cddl_verifier.json_codec) and the cddl-verify CLI; underscore modules are not covered.

  • The version is defined once, as __version__ in src/cddl_verifier/_version.py. pyproject.toml reads it, cddl_verifier.__version__ exposes it, and cddl-verify --version prints it. Don't repeat the version number elsewhere.
  • A change that alters behaviour bumps the version and adds an entry to CHANGELOG.md (format: Keep a Changelog). Follow-up commits before a release go into the same, still-unreleased version.
  • Update this README and docs/ in the same change as the code they describe.

Releasing

Releases go to PyPI through publish_pypi.yml, which uses PyPI Trusted Publishing (no API tokens are stored).

  1. Set the version in _version.py, date its CHANGELOG section, and merge to main.
  2. Optional dry run: start the workflow manually (Actions → Publish to PyPI / TestPyPI → Run workflow); manual runs only upload to TestPyPI. A version can only be uploaded once per index, so use a pre-release such as 0.1.1rc1 for trial uploads. A release fails if its version is already on TestPyPI.
  3. Publish a GitHub release with tag vX.Y.Z matching the version. The workflow builds and checks the distributions, tests the wheel and sdist, uploads to TestPyPI, installs from there, and then uploads to PyPI.

One-time setup: on pypi.org and test.pypi.org, add a (pending) trusted publisher for repository sahebbiswas/cddl_verifier, workflow publish_pypi.yml, and environment pypi / testpypi respectively (or "any" environment). GitHub creates the environments on first use; add a required reviewer to pypi to gate production uploads.

Metadata

Release files for cddl-verifier 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for cddl-verifier 0.1.0
File Size Uploaded
cddl_verifier-0.1.0.tar.gz 125.8 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for cddl-verifier 0.1.0
File Interpreter ABI Platform
cddl_verifier-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 180.0 kB

Release files / cddl_verifier-0.1.0.tar.gz

Download URL cddl_verifier-0.1.0.tar.gz
Size 125.8 kB
Tags Source
SHA-256 checksum
How to use checksums
f07fdcdb97c085e35fe99dce9f15f643f10c9fcdb74ec70c36f2861e6684f201
BLAKE2b-256 checksum
How to use checksums
e713a40b24123c1cc48bbbcf4d9e6d9a81064c5bf7996900945b60ea2cf6c4cc
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 8, 2026.

Transparency log

Release files / cddl_verifier-0.1.0-py3-none-any.whl

Download URL cddl_verifier-0.1.0-py3-none-any.whl
Size 54.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
01c70c4adbcd767cd14c64a1f3209c99a2737633eb1243133bfab71b9028777d
BLAKE2b-256 checksum
How to use checksums
943e34d41ce172c2d0fb461a6fdeaf475411cad3c5a1789bb88c703542840af3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 8, 2026.

Transparency log

Release history Release notifications | RSS feed

1.0.2

2 release files

1.0.0

2 release files

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page