Metadata-Version: 2.4
Name: cddl-verifier
Version: 1.0.0
Summary: Validate CBOR data against CDDL schemas, generate annotated EDN, and convert CBOR/JSON
License-Expression: MIT
Project-URL: Homepage, https://github.com/sahebbiswas/cddl_verifier
Project-URL: Source, https://github.com/sahebbiswas/cddl_verifier
Project-URL: Issues, https://github.com/sahebbiswas/cddl_verifier/issues
Project-URL: Release notes, https://github.com/sahebbiswas/cddl_verifier/releases
Keywords: cbor,cddl,edn,rfc8610,rfc8949,corim,validation
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: Utilities
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Provides-Extra: test
Requires-Dist: pytest>=8; extra == "test"
Requires-Dist: pycddl<0.7,>=0.6.4; extra == "test"
Requires-Dist: hypothesis>=6.100; extra == "test"
Provides-Extra: dev
Requires-Dist: pytest>=8; extra == "dev"
Requires-Dist: pycddl<0.7,>=0.6.4; extra == "dev"
Requires-Dist: hypothesis>=6.100; extra == "dev"
Requires-Dist: build; extra == "dev"
Requires-Dist: twine; extra == "dev"
Dynamic: license-file

[![Python CI](https://github.com/sahebbiswas/cddl_verifier/actions/workflows/ci.yml/badge.svg)](https://github.com/sahebbiswas/cddl_verifier/actions/workflows/ci.yml)

# 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 parses the whole CDDL grammar (RFC 8610 as updated by
> RFC 9682) and enforces every construct and control operator in the
> [conformance matrix](https://github.com/sahebbiswas/cddl_verifier/blob/main/docs/CONFORMANCE.md),
> which lists each one with its tests. A [corpus](https://github.com/sahebbiswas/cddl_verifier/blob/main/docs/CORPUS.md)
> of real schemas and CBOR from RFCs and IETF drafts is checked against it, and
> the few places where it differs on purpose are listed there. See also
> [Limitations](#limitations) and [docs/CDDL_SUPPORT.md](https://github.com/sahebbiswas/cddl_verifier/blob/main/docs/CDDL_SUPPORT.md).
> The public API is stable from 1.0: see
> [docs/COMPATIBILITY.md](https://github.com/sahebbiswas/cddl_verifier/blob/main/docs/COMPATIBILITY.md).

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

## Installation

```bash
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, Hypothesis, pycddl) and `[dev]` (the same plus build, twine).

## Quick start

New here? [docs/GETTING_STARTED.md](https://github.com/sahebbiswas/cddl_verifier/blob/main/docs/GETTING_STARTED.md)
walks from installation to reading a failed validation, with a triage flow for each
kind of failure. For copy-pasteable workflows (validation, debugging, JSON conversion,
CI), see the [task-oriented recipes](https://github.com/sahebbiswas/cddl_verifier/blob/main/docs/RECIPES.md).

### Command line

```bash
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
cddl-verify schema.cddl data.cbor -M modules/ --module rfc9393=coswid.cddl  # load imported CDDL modules
```

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](https://github.com/sahebbiswas/cddl_verifier/blob/main/docs/CLI.md).

### Python

```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.path_text, 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.
- Each diagnostic also has the data `path`, the byte `offset` and bytes of the
  item, the `rule`, and what was `expected` and found. `result.to_json()` and
  `render_text(result.diagnostics, verbose=True)` render them. See
  [docs/API.md](https://github.com/sahebbiswas/cddl_verifier/blob/main/docs/API.md#diagnostic).

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

```python
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:

```python
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. `decode_sequence` reads a CBOR sequence (RFC 8742) as the list of
its items. See [docs/API.md](https://github.com/sahebbiswas/cddl_verifier/blob/main/docs/API.md) for the full API.

## What is supported

- CDDL maps, arrays, type aliases, groups, type choices (`a / b` and `/=`), sockets (`//=`),
  optional fields, occurrence indicators, IANA-registered parameters
  (`&(name: n)`), CBOR tags (`#6.n(...)`), numeric ranges (`0..255`,
  `0.0...1.0`), and the controls `.size`, `.cbor`, `.cborseq`, `.regexp`, `.bits`,
  `.ge`, `.gt`, `.le`, `.lt`, `.eq`, `.ne`, `.and`, `.within` and the RFC 9165 / RFC 9741
  controls (`.plus`, `.cat`, `.det`, `.abnf`, the text conversions, `.printf`, `.json`,
  `.join`). Details: [docs/CDDL_SUPPORT.md](https://github.com/sahebbiswas/cddl_verifier/blob/main/docs/CDDL_SUPPORT.md).
- Real CoRIM and CoSWID schemas: [docs/CORIM_SUPPORT.md](https://github.com/sahebbiswas/cddl_verifier/blob/main/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. A member is named by its
  key or its `&(name: 0)` label; with `comment_names=True` (`--comment-names`) a
  trailing comment (`0: tstr ; name`) names a member that has no `&(name: 0)` label
  (a label always wins).
- CBOR ↔ JSON conversion. `typed=True` keeps byte strings, tags and
  non-string map keys (such as the integer keys in CoRIM maps), so typed JSON
  converts back to the same CBOR data. Without it, map keys become JSON strings,
  and keys that would collide (`0` and `"0"`) raise an error.

## Limitations

- **CDDL**: the whole RFC 8610 grammar (as updated by RFC 9682) is parsed, and
  schemas that are not valid CDDL raise `SchemaError` with a line and column.
  So do schemas that parse but do not make sense, such as an undefined name, a
  misused generic or an unknown control operator
  ([#70](https://github.com/sahebbiswas/cddl_verifier/issues/70)).
  Validation covers a practical subset of what the grammar can express; the
  RFC 9165 and RFC 9741 controls are enforced (`.plus`, `.cat`, `.det`, `.abnf`,
  `.abnfb`, the base64, base32, base16 and base45 conversions, `.base10`,
  `.json`, `.printf` and `.join`), with the limits in
  [CDDL_SUPPORT.md](https://github.com/sahebbiswas/cddl_verifier/blob/main/docs/CDDL_SUPPORT.md#computed-literals-and-text-controls).
  The
  [conformance matrix](https://github.com/sahebbiswas/cddl_verifier/blob/main/docs/CONFORMANCE.md)
  has the full list.
- **Canonical encoding**: implements the RFC 8949 §4.2.1 core deterministic
  profile (see [CANONICAL_AND_JSON.md](https://github.com/sahebbiswas/cddl_verifier/blob/main/docs/CANONICAL_AND_JSON.md)).
  The optional §4.2.2 reduction of integral floats to integers is not applied,
  and floats are written in their shortest exact width in both modes (RFC 8949 §4.1);
  `float_width(value, 64)` fixes the width of one value.
- **CBOR**: indefinite-length items, `undefined` and the other simple values
  decode; the encoder writes definite-length items. `decode` rejects a CBOR
  sequence; `decode_sequence` reads one.
- **Value types**: tags decode to `CBORTag(tag, value)`; a `(tag, value)` tuple
  is not a tag (the encoder raises `TypeError` for one, since 0.24.0). Map keys
  that are booleans, floats, arrays, maps or tags decode to `CBORKey`, so
  `{1: a, true: b}` keeps both entries and re-encodes to the same bytes.

## Documentation

| Document | Contents |
|----------|----------|
| [docs/GETTING_STARTED.md](https://github.com/sahebbiswas/cddl_verifier/blob/main/docs/GETTING_STARTED.md) | Install, write a schema, validate, and triage each kind of failure, with example commands and output |
| [docs/RECIPES.md](https://github.com/sahebbiswas/cddl_verifier/blob/main/docs/RECIPES.md) | End-to-end CLI, Python, debugging, JSON/CBOR, CoRIM, and CI recipes |
| [docs/CLI.md](https://github.com/sahebbiswas/cddl_verifier/blob/main/docs/CLI.md) | `cddl-verify` and JSON converter options, input rules, EDN output formats |
| [docs/API.md](https://github.com/sahebbiswas/cddl_verifier/blob/main/docs/API.md) | Python API: `validate`, `Validator`, CBOR and JSON helpers |
| [docs/CDDL_SUPPORT.md](https://github.com/sahebbiswas/cddl_verifier/blob/main/docs/CDDL_SUPPORT.md) | Supported CDDL syntax, types, and validation behaviour |
| [docs/CONFORMANCE.md](https://github.com/sahebbiswas/cddl_verifier/blob/main/docs/CONFORMANCE.md) | Conformance matrix: every construct, control and CBOR item by layer, with status and tests |
| [docs/CORPUS.md](https://github.com/sahebbiswas/cddl_verifier/blob/main/docs/CORPUS.md) | Conformance corpus: real schemas and CBOR from RFC 8610, COSE, CoRIM, CoSWID, EDHOC and SUIT with the verdict each source gives, and what this library gets wrong |
| [docs/divergences.json](https://github.com/sahebbiswas/cddl_verifier/blob/main/docs/divergences.json) | Where this library and the independent `cddl` crate (`pycddl`) disagree on the conformance corpus, and who is right ([Differential testing](https://github.com/sahebbiswas/cddl_verifier/blob/main/TESTING.md#differential-testing)) |
| [docs/CORIM_SUPPORT.md](https://github.com/sahebbiswas/cddl_verifier/blob/main/docs/CORIM_SUPPORT.md) | CoRIM / CoSWID schema support |
| [docs/CBOR_BUILDER_QUICK_REF.md](https://github.com/sahebbiswas/cddl_verifier/blob/main/docs/CBOR_BUILDER_QUICK_REF.md), [docs/ITERATIVE_CONSTRUCTION.md](https://github.com/sahebbiswas/cddl_verifier/blob/main/docs/ITERATIVE_CONSTRUCTION.md) | `CBOR` builder API in depth |
| [docs/CBOR_DIAGNOSTIC_DUMP.md](https://github.com/sahebbiswas/cddl_verifier/blob/main/docs/CBOR_DIAGNOSTIC_DUMP.md) | Diagnostic dump format |
| [docs/CANONICAL_AND_JSON.md](https://github.com/sahebbiswas/cddl_verifier/blob/main/docs/CANONICAL_AND_JSON.md) | Canonical encoding and JSON round-trips |
| [docs/EDN_FORMATTING_IMPROVEMENTS.md](https://github.com/sahebbiswas/cddl_verifier/blob/main/docs/EDN_FORMATTING_IMPROVEMENTS.md), [docs/IANA_ANNOTATIONS_STATUS.md](https://github.com/sahebbiswas/cddl_verifier/blob/main/docs/IANA_ANNOTATIONS_STATUS.md) | What the annotated EDN looks like, and registered parameters |
| [docs/](https://github.com/sahebbiswas/cddl_verifier/tree/main/docs) | Tag notation and other notes |
| [docs/COMPATIBILITY.md](https://github.com/sahebbiswas/cddl_verifier/blob/main/docs/COMPATIBILITY.md) | What the 1.x compatibility promise covers, and what it does not; deprecation and Python version policy |
| [docs/BENCHMARKS.md](https://github.com/sahebbiswas/cddl_verifier/blob/main/docs/BENCHMARKS.md) | Benchmarks and profiling: how to run them and what they found |
| [docs/CDDL_AST_DESIGN.md](https://github.com/sahebbiswas/cddl_verifier/blob/main/docs/CDDL_AST_DESIGN.md) | Contributor design: CDDL AST, parser and how it was introduced |
| [TESTING.md](https://github.com/sahebbiswas/cddl_verifier/blob/main/TESTING.md) | Running and writing tests, CI setup |
| [CONTRIBUTING.md](https://github.com/sahebbiswas/cddl_verifier/blob/main/CONTRIBUTING.md) | Pull request checklist, versioning and releases |
| [Releases](https://github.com/sahebbiswas/cddl_verifier/releases) | Release notes |

## Development

```bash
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](https://github.com/sahebbiswas/cddl_verifier/blob/main/TESTING.md).

## Versioning and releases

Every pull request merged to `main` bumps the version in
[`src/cddl_verifier/_version.py`](https://github.com/sahebbiswas/cddl_verifier/blob/main/src/cddl_verifier/_version.py),
following [Semantic Versioning 2.0.0](https://semver.org/): a patch bump for
fixes and docs, a minor bump for new features, and a major bump only for an
incompatible change to the public API (`cddl_verifier`, `cddl_verifier.cbor`,
`cddl_verifier.json_codec` and the `cddl-verify` CLI). What is covered, and what
is not (message wording, EDN layout, internal modules), is in
[docs/COMPATIBILITY.md](https://github.com/sahebbiswas/cddl_verifier/blob/main/docs/COMPATIBILITY.md).
Releases are cut from `main` when it
is stable, so not every version is published. Each release's notes are on the
[GitHub releases page](https://github.com/sahebbiswas/cddl_verifier/releases);
there is no changelog file. See
[CONTRIBUTING.md](https://github.com/sahebbiswas/cddl_verifier/blob/main/CONTRIBUTING.md)
for the rules and the release steps.
