Skip to content

ODCS integration and interop

The Open Data Contract Standard (ODCS, a Bitol / Linux Foundation project) is the settled industry format for describing data contracts. ODCS is deliberately a document standard — it describes the contract and delegates execution to engines. PyCharter plugs into that ecosystem as an execution engine: the same contract that round-trips through ODCS is what PyCharter enforces in-process — on API payloads, Kafka records, and ETL batches.

Export: to_odcs

from pycharter.contract_io import to_odcs

odcs_document = to_odcs(contract_dict)  # ODCS v3.1.0, JSON-serialisable
odcs_v32 = to_odcs(contract_dict, api_version="v3.2.0")  # opt-in native guidance

The exporter targets ODCS v3.1.0 and its output validates against the published v3.1.0 JSON schema (strict mode — the schema is vendored in the test suite and every export corpus document is checked). Highlights of the mapping:

The optional v3.2.0 export restores imported top-level and schema context, synonyms, semanticType, authoritative definitions, enum labels, and unchanged map/vector shapes to native ODCS fields. It retains the original foreign source under customProperties.pycharter for lossless re-import. The default remains v3.1.0 for existing consumers. Executable enum and map/vector changes in the canonical contract take precedence over stale source guidance. The v3.2 export is checked against the published v3.2 schema.

PyCharter ODCS v3.1.0
json_schema.properties schema[0].properties[] — date / date-time / time formats become first-class logical types; constraints live in logicalTypeOptions; nested objects and array items map natively
x-database.sql_type / x-database.primary_key physicalType / primaryKey per property
x-database-table.table_name schema[0].physicalName
metadata.governance_rules.pii_fields classification: pii per property
field_bindings primary concepts per-property authoritativeDefinitions (type: businessDefinition, URL = the SKOS concept IRI)
metadata.title / .version / .status / .description document name / version / status / description.purpose
validation_rules.rules (per-record gates) per-property quality[] entries, type: custom, engine: pycharter
data_quality.rules per-property or schema-level quality[]; library metrics normalised to metric (rowCount, nullValues, …)
data_quality.targets slaProperties[] with driver: quality
metadata.ownership team.members[] (full metadata also rides in customProperties for lossless re-import)
coercion_rules, field_bindings, versions customProperties[] pairs

The export is guaranteed lossless: every JSON Schema key without a native ODCS home is preserved verbatim in customProperties, and a CI gate round-trips every contract in the repository (from_odcs(to_odcs(c)) == c) on every build.

Import: native ingestion

An ODCS DataContract document is accepted anywhere a contract is accepted — auto-detected by its kind and apiVersion keys, no explicit conversion call needed:

from pycharter import Validator
from pycharter.contract_parser import parse_contract_file

validator = Validator.from_dict(odcs_document)  # enforce directly
metadata = parse_contract_file("orders.odcs.yaml")  # files too

from_odcs remains available for explicit conversion:

from pycharter.contract_io import from_odcs

contract = from_odcs(odcs_document)

Input is tolerant by design: v3.0.x, v3.1.x, and v3.2.x documents are accepted, with customProperties as the v3.1 pair list or a plain mapping — so contracts authored by other tools import regardless of dialect. ODCS sections PyCharter does not model (servers, support, price, roles, …) are preserved under metadata.odcs_passthrough, never silently dropped. Documents with multiple schema objects fail import with a ConfigValidationError; split them into one object per document before loading. This also applies when Validator.from_dict or parse_contract detects ODCS input automatically.

For a foreign v3.2 document, context, schema object guidance, synonyms, semanticType, and authoritative definitions remain in metadata.odcs_passthrough, with odcs_import_review: required. They are source material for a reviewer, not approved agent instructions or runtime rules. ODCS enum values become executable JSON Schema enum values; map and vector properties become JSON Schema object and fixed-length array shapes. The original ODCS schema remains available for details PyCharter cannot execute, including synonym metadata and vector distance metrics. Non-string map keys and key constraints fail import rather than pass with an unenforced rule. Imported guidance is reviewed as one bundle per exact contract version. The proposal service requires an explicit approval by a different, authenticated reviewer before guarded publication, even when native proposals permit commit without approval. The HTTP approval route uses the verified JWT workspace identity. Local CLI --as labels and anonymous development access do not satisfy this requirement.

Published metadata records odcs_import_review: guidance_reviewed, the reviewer, approval time, and odcs_guidance_review evidence reference. Its fingerprint binds the namespace, name, version, and source bundle. Candidate-supplied approval claims are discarded when staging. Direct store and API publication remain permitted; their unreviewed guidance stays withheld from agents.

Reviewer proposal detail shows source material as imported_unapproved until publication, then as imported_reviewed_advisory when the durable evidence matches. Full authenticated preparation also returns the reviewed bundle under import_guidance, explicitly labelled as source data rather than host/system instructions or executable rules. Metadata claims alone cannot enable it. A bundle containing a private field is withheld as a unit, and offline, compact, or budgeted views omit it. MCP schema fetch, HTTP Try it, the agent CLI, and provider adapters continue omitting imported descriptions from model-facing schemas after review. Earlier contract_reviewed versions need a new version and authenticated bundle approval; their trust is not upgraded. The v3.2 behavior follows the ODCS schema definition and context definition.

Round trip (from_odcs(to_odcs(c))) reproduces the canonical contract exactly — PyCharter-authored documents carry a pycharter customProperty that anchors format version and authored shape. The documented normalisations: ODCS library metric values come back as canonical PyCharter rule names with type: library, data_quality.rules regroup by column, and id/tags are regenerated deterministically on each export.

Numeric metric assertions use native ODCS entries when their authored shape fits the chosen schema. Shapes that ODCS 3.⅓.2 cannot represent exactly use the existing engine: pycharter custom encoding, including equal range endpoints, snake case operators, numeric bound strings, multiple operators, and an omitted assertion. Import restores the authored operators and rule type. See numeric assertions; this lossless encoding does not make a custom rule executable by another engine.

PyCharter and datacontract-cli

datacontract-cli is the ODCS reference implementation. The two tools own different halves of the contract lifecycle, and they compose:

Lifecycle stage Tool
Author, lint, and diff contracts; generate code/schemas (SQL, Avro, dbt, …) datacontract-cli
Verify contracts in CI and batch against warehouses, lakes, files datacontract-cli
Enforce contracts in-process at runtime — API payloads, Kafka records (per message), ETL stage boundaries PyCharter
Versioned contract registry + quality scoring + governed agent context PyCharter

A combined workflow: author and CI-gate the ODCS document with datacontract-cli, from_odcs it into PyCharter for runtime enforcement inside the producing service, and to_odcs any PyCharter-authored contracts back out so the rest of the ODCS toolchain (catalogs, datacontract-cli itself) can consume them. PyCharter is not a rival standard — it exports the standard.

Where Soda, Great Expectations, and dbt attach

Soda and Great Expectations execute quality checks warehouse-side (scheduled scans, post-load); dbt tests run inside dbt after materialisation. ODCS models all of them as pluggable quality engines, exactly as it models PyCharter (engine: pycharter on custom quality entries). The practical split: PyCharter rejects or coerces bad records before they land; warehouse-side engines measure what did land. Many stacks run both.

See also: PyCharter vs. the alternatives for the full capability matrix, and Agent integration (MCP) for serving contract-bound context to AI agents.