ODCS Roadmap¶
Reference-implementation milestones for the Open Data Contract Standard. This roadmap tracks the Rust crate in src/.
The upstream ODCS specification is the source of truth for semantics. When this roadmap and the upstream specification disagree, the upstream specification wins.
Status overview¶
| Phase | Name | Focus | Status |
|---|---|---|---|
| 1 | Skeleton | Crate layout, CLI entry point, examples, tests | Complete (0.1.0) |
| 2 | Canonical Object Model | ODCS sections as Rust types | Complete (0.3.0) |
| 3 | Parsing | YAML and JSON parsing with diagnostics | Complete (0.3.0) |
| 4 | Diagnostics | Structured diagnostics aligned with DTCS style | Complete (0.4.0) |
| 5 | Validation | Phase-based validation pipeline | Complete (0.4.0) |
| 6 | CLI | validate, inspect, diagnostics, schema, version |
Complete (0.4.0) |
| 7 | JSON Schema parity | Conformance against official ODCS JSON Schema | Complete (0.4.0) |
| 8 | Python bindings | PyO3 bindings after Rust API stabilizes | Complete (0.4.0) |
| 9 | Parser hardening | Nested YAML duplicate-key detection | Complete (0.5.0) |
| 10 | Diagnostics metadata | validationPhase on validation diagnostics |
Complete (0.6.0) |
| 11 | Structural validation | Cross-field rules in structural.rs |
Complete (0.7.0) |
| 12 | Section semantics | Roles, SLA, pricing, support validators | Complete (0.8.0) |
| 13 | Cross-file references | Multi-document FQN resolution | Complete (0.8.0) |
| 14 | Compatibility analysis | Contract diff and breaking-change report | Complete (0.8.0) |
| 15 | Registry | Local contract index and lookup | Complete (0.9.0) |
| 16 | 1.0 release | API stabilization and upstream sync | Planned (1.0.0) |
Dependencies¶
Phase 1 Skeleton
│
├──► Phase 2 Canonical Object Model
│ │
│ └──► Phase 3 Parsing
│ │
│ └──► Phase 4 Diagnostics
│ │
│ └──► Phase 5 Validation
│ │
│ ├──► Phase 6 CLI
│ │
│ └──► Phase 7 JSON Schema parity
│ │
│ └──► Phase 8 Python bindings
│ │
│ ┌───────────────────────────────────────────┤
│ │ │
│ ▼ ▼
│ Phase 9 Parser hardening Phase 10 Diagnostics metadata
│ │ │
│ └───────────────────┬───────────────────────┘
│ ▼
│ Phase 11 Structural validation
│ │
│ ┌─────────────┴─────────────┐
│ ▼ ▼
│ Phase 12 Section semantics Phase 13 Cross-file references
│ │ │
│ └─────────────┬─────────────┘
│ ▼
│ Phase 14 Compatibility analysis
│ │
│ ▼
│ Phase 15 Registry
│ │
│ ▼
│ Phase 16 1.0 release
Phase 1 — Skeleton¶
Target: 0.1.0 — Complete
- [x] Repository layout aligned with DTCS conventions
- [x] Rust crate with full module skeleton per
crate-layout.md - [x] CLI entry point with
validate,inspect,diagnostics,schema, andversion - [x] Basic YAML and JSON parsing for minimal contracts
- [x] Examples and expanded test fixtures (valid, invalid, malformed, extensions)
- [x] Integration and CLI test coverage
- [x] CLI exit codes aligned with
cli-spec.md(0 valid, 1 validation, 2 parse/IO) - [x] CI pipeline (fmt, clippy, test)
Phase 2 — Canonical Object Model¶
Target: 0.3.0 — Complete
- [x] Shared types (
StableId,Tags,CustomProperty,AuthoritativeDefinitions,ContractDescription) - [x] Root
DataContractwith v3.1.0 required fields - [x]
SchemaObject/SchemaPropertywith nested quality - [x] Section modules: SLA, servers, team (object + legacy array), roles, pricing, support
- [x]
stakeholdersdocumented as N/A for v3.1.0
Phase 3 — Parsing¶
Target: 0.3.0 — Complete
- [x] YAML and JSON parsing via serde
- [x] Parse helpers (
success/failure_from_serde) - [x] Parse diagnostics with paths and unknown-field detection
- [x] Fixture migration and round-trip tests
- [x] Upstream JSON Schema reference fixture pinned under
schema/andtests/fixtures/
Phase 4 — Diagnostics¶
Target: 0.4.0 — Complete
- [x] Structured
Diagnosticrecords with id, severity, category, stage, message - [x]
object_refandremediationsupport - [x] Stable
odcs:diagnostic codes (includingodcs:json-schema-violationfor strict mode) - [x] CLI text and JSON output
Phase 5 — Validation¶
Target: 0.4.0 — Complete
- [x] Document validation (required root fields,
apiVersion/kindchecks) - [x] Schema validation (required schema/property names)
- [x] Quality validation (library metrics, rule-type constraints)
- [x] Reference validation (relationship endpoints)
- [x] Extension validation (custom property keys)
- [x]
--strictmode semantics (JSON Schema validation phase) - [x] Deeper reference resolution (schema-level
from, nested property shorthand)
Phase 6 — CLI¶
Target: 0.4.0 — Complete
odcs validate <path>
odcs inspect <path>
odcs diagnostics <path>
odcs schema
odcs version
- [x] Rust CLI with exit codes per
cli-spec.md - [x] Python
pyodcsCLI parity - [x] Full
--strictenforcement - [x] JSON Schema export from
odcs schema
Phase 7 — JSON Schema parity¶
Target: 0.4.0 — Complete
- [x] Pinned upstream schema fixture (
schema/odcs-v3.1.0.json) - [x] Conformance tests for valid section fixtures
- [x] Broader negative-case parity
- [x] Example corpus from upstream repository (
tests/fixtures/upstream/,scripts/sync-upstream-examples.sh) - [x] Strict-mode JSON Schema validation phase
Phase 8 — Python bindings¶
Target: 0.4.0 — Complete
- [x] PyO3 bindings via maturin (
pyodcs._native) - [x] Parse, validate, inspect helpers
- [x] Strict validation (
strict=True) andvalidate_result(strict=True) - [x]
pinned_schema()and schema CLI export - [x] Python CLI with full parity to Rust
odcs
Spec parity (0.4.0) — Complete¶
- [x] Default
validate()includes JSON Schema conformance - [x] Upstream
version/apiVersionsemantics aligned - [x] SLA model complete (
description,scheduler) - [x] Enum and server type validation in default mode
- [x] Expanded section fixture matrix and upstream corpus without normalization
- [x] Spec parity policy documented in
SPEC.md
Future milestones (0.5+)¶
Phases 1–9 deliver schema-complete ODCS v3.1.0 document parsing and validation, including nested duplicate-key detection. Phases 10–16 deepen observability, multi-document workflows, and ecosystem tooling on the path to 1.0.0.
| Release | Phases | Theme |
|---|---|---|
0.5.0 |
9 ✓ | Parser hardening (nested duplicate-key detection) |
0.6.0 |
10 ✓ | Diagnostics metadata (validationPhase) |
0.7.0 |
11 ✓ | Structural validation |
0.8.0 |
12, 13, 14 | Section semantics, cross-file references, compatibility analysis |
0.9.0 |
15 | Local registry and discovery |
1.0.0 |
16 | Stable public API, deprecation cleanup, upstream alignment |
Out of scope for this repository (see docs/implementation/non-goals.md): data quality execution, DTCS/DPCS transformation semantics, SQL generation, ETL, and runtime engines.
Phase 9 — Parser hardening¶
Target: 0.5.0 — Complete
Goal: Detect duplicate keys at any YAML nesting depth before serde deserialization, matching JSON behavior in src/parser/duplicate_keys.rs.
Context: Implemented via find_yaml_duplicate_key using an unsafe-libyaml event walk (pre-serde_yaml deserialize). JSON uses DupeDetectVisitor with a path stack. Both return DuplicateKeyFinding { key, object_ref } (e.g. schema[0].name). Flow-style mappings and YAML anchors/aliases remain out of scope.
Deliverables:
- [x] Extend
src/parser/duplicate_keys.rswith nested YAML duplicate-key detection (unsafe-libyamlevent walk; path-aware) - [x] Invoke nested check from
src/parser/yaml.rsbeforeserde_path_to_error::deserialize - [x] Emit
odcs:duplicate-keyviafailure_duplicate_keywith dottedobject_refpaths (e.g.schema[0].name) - [x] Fixtures:
tests/fixtures/invalid-nested-duplicate-key.yamland.json - [x] Tests in
tests/validation_negative.rs; CLI exit code2intests/cli.rs - [x] Python parse test in
python/tests/test_pyodcs.py; explicitunsafe-libyaml = "0.2.11"inCargo.toml
Out of scope: Duplicate keys inside YAML flow scalars or anchors/aliases (documented in module).
Done when: Nested YAML duplicate keys fail parse with odcs:duplicate-key and a non-root object_ref; CI green. ✓
Phase 10 — Diagnostics metadata¶
Target: 0.6.0 — Complete
Goal: Attach the validation pipeline phase to every validation diagnostic so CI and tooling can filter by origin without parsing messages.
Context: ValidationPhase exists but Diagnostic only records coarse stage (parse | validation | …). validation_error does not accept a phase.
Deliverables:
- [x] Add optional
validation_phase: Option<ValidationPhase>toDiagnostic(serde:validationPhase, camelCase) - [x] Extend
validation_error(or addphase_validation_error) to requireValidationPhasefor validation-stage diagnostics - [x] Wire phase through all validators:
document,structural,schema,quality,references,extensions,servers,sections,ids,json_schema - [x] Leave parse-stage diagnostics without
validationPhase(field omitted in JSON) - [x] CLI text/JSON output includes
validationPhasewhen set; updatedocs/user/diagnostics.md - [x] Export phase name constants in Python diagnostic docs (no separate
CODESentry — phases are metadata, not error ids) - [x] Snapshot or assertion tests that every validation diagnostic in fixture runs includes
validationPhase
Out of scope: Repurposing DiagnosticStage to encode validation phases; reserved stages (analysis, runtime, …) stay for future use.
Done when: odcs validate --json emits validationPhase on all validation errors; existing diagnostic id values unchanged.
Phase 11 — Structural validation¶
Target: 0.7.0 — Complete
Goal: Implement cross-field constraints in src/validation/structural.rs that require reading multiple sections of a contract and are not owned by a single-section validator.
Context: Root-field checks live in document.rs; section-specific checks are split across schema, extensions, sections, etc. Phase 11 fills the gap for inter-section rules.
Adopted rules (confirmed against upstream spec + pinned schema):
- [x] Unique non-empty
schema[].namevalues within a contract - [x]
slaDefaultElement, when set, references an existingschema[].name(element path notation; deprecated field) - [x]
slaProperties[].element, when set, references an existingschema[].name(comma-separated tokens supported) - [x] Unique non-empty
servers[].servervalues - [x] ~~
servers[].schema~~ — not adopted (database/catalog schema string in server details, not an ODCSschema[]reference)
Deliverables:
- [x] Spec audit note in
SPEC.mdlisting adopted structural rules and any intentional extensions - [x] Implement confirmed rules in
structural.rsusing existingvalidation_error+ phase metadata (Phase 10) - [x] Valid/invalid fixtures per rule under
tests/fixtures/ - [x] Tests in
tests/validation_negative.rs
Out of scope: Rules already enforced by JSON Schema or a single-section module (move only if logically cross-field); relationship endpoint resolution (Phase 5 / Phase 13).
Done when: structural.rs emits diagnostics for all adopted rules; no duplicate enforcement elsewhere.
Phase 12 — Section semantics¶
Target: 0.8.0 — Complete
Goal: Add Rust-side semantic validation for sections where JSON Schema coverage is thin and remaining business rules are not yet covered.
Context: extensions.rs already validates non-empty roles[].role, support channel, and SLA property; sections.rs validates team member usernames. Phase 12 adds remaining business semantics per section model.
Deliverables:
| Section | Module | Rules |
|---|---|---|
| Roles | sections.rs or roles.rs |
Unique roles[].id when present |
| Support | sections.rs |
Require url when channel is URL-bearing per spec enum |
| SLA | sections.rs or sla.rs |
Validate scheduler/schedule pairing if spec defines constraints |
| Pricing | sections.rs or pricing.rs |
When priceAmount is set, require priceCurrency; reject negative amounts if spec disallows |
- [x] Implement validators; prefer extending
sections.rsunless a section grows large enough to split - [x] Negative fixtures for each new rule
- [x] Update docs/implementation/testing-plan.md SLA row from “limited semantic validation” to covered items
- [x] All new diagnostics use
validationPhaseand stable existing codes where possible (missing-required-field,invalid-schema, etc.)
Out of scope: Re-validating fields already fully constrained by pinned JSON Schema; quality rule execution.
Done when: Each section in the table has at least one semantic rule beyond parse + JSON Schema; tests pass.
Phase 13 — Cross-file references¶
Target: 0.8.0 — Complete
Goal: Resolve fully-qualified relationship endpoints across a loaded set of contracts; fail unresolved refs with actionable diagnostics.
Context: references.rs validates shorthand table.column against an in-document index and accepts FQN strings via regex without resolving them. SPEC.md documents single-document resolution as the 0.4.0 policy.
Design decisions (resolve before coding):
- [x] ADR or
docs/implementation/cross-file-references.mdcovering: contract index key (idvs filename), FQN grammar (reuse existing regex), and load order - [x]
ContractSet(or equivalent) type: parse + index multiple documents from paths - [x] Extend reference validation to resolve FQN endpoints against the set
- [x] CLI:
odcs validate <path> --include <dir>or repeated--dep <path>(updatedocs/implementation/cli-spec.md) - [x] Library:
validate_set(&ContractSet)orparse_and_validate_paths(&[Path]) - [x] Python:
parse_and_validate_paths(...)binding - [x] Fixtures: two-contract valid/invalid pairs under
tests/fixtures/cross-file/
Out of scope for MVP: Remote URL fetching, registry-backed resolution (Phase 15), workspace manifests.
Done when: A relationship from/to referencing other-contract/table.column validates when other-contract is included and fails with odcs:unresolved-reference when omitted.
Phase 14 — Compatibility analysis¶
Target: 0.8.0 — Complete
Goal: Compare two parsed contracts and produce a structured breaking-change report for contract evolution workflows.
Context: Stub src/compatibility/mod.rs. DiagnosticCategory::Compatibility already exists but is used only for unsupported apiVersion.
Deliverables:
- [x]
CompatibilityReportwith classified changes:breaking,additive,deprecated,unchanged - [x] Compare dimensions:
- Root metadata (
id,status,version— informational, not breaking by default) - Schema objects: added/removed/renamed; property added/removed;
logicalTypechange;requiredtoggle - Quality rules: added/removed; metric or operator change
- Relationships: added/removed; endpoint change
- [x] Stable codes:
odcs:compatibility-breaking,odcs:compatibility-additive, … (document in diagnostics guide) - [x] CLI:
odcs diff <old> <new>with text +--json; exit0if no breaking changes,1if breaking - [x] Python:
pyodcs.diff(old, new)returning report dict - [x] Fixtures: pairs under
tests/fixtures/compatibility/
Out of scope: Automatic migration or contract rewriting; semver inference for version field.
Done when: odcs diff correctly classifies a fixture pair with known breaking schema removal; tests and CLI spec updated.
Phase 15 — Registry¶
Target: 0.9.0 — Complete
Context: Implemented in src/registry/. See registry ADR.
Deliverables:
- [x]
RegistryEntrymodel:id,version,path, optionaltags,apiVersion, content hash - [x] Local backend: index file (
.odcs/registry.json) + recursive contract directory scan - [x] API:
register,lookup(id),lookup(id, version),list - [x] CLI:
odcs registry index <dir>,odcs registry lookup <dir> <id>,odcs registry list <dir> - [x]
odcs validate --registry <dir>loads index for FQN resolution (builds on Phase 13) - [x] Python bindings for index/lookup/list
Out of scope for MVP: HTTP remote registry, auth, publish-subscribe, write-through to external systems.
Done when: Indexing a directory of contracts enables lookup by id and powers cross-file validation without explicit --include for indexed paths.
Phase 16 — 1.0 release¶
Target: 1.0.0 — Planned
Goal: Ship a stable, semver-major API with deprecated surfaces removed and documented upstream alignment policy.
Breaking cleanup (requires major bump):
- [x] Remove
--strictfrom Rust and Python CLIs - [x] Remove
ValidationOptions,validate_strict(),validate_with_options(), and Pythonstrict=parameters - [x] Migration note in
docs/user/migration.md(0.9.x → 1.0)
Upstream alignment (when upstream releases beyond 3.1.0):
- [ ] Follow SPEC.md synchronization workflow: pin schema, update model/validators, refresh fixtures via
scripts/sync-upstream-examples.sh - [ ] Document supported
apiVersionvalues per release - [ ] Add
stakeholdersmodel if upstream introduces the section (currently N/A — seestakeholders.rs)
Release gate:
- [x] Public API review:
docs/implementation/public-api.mdandapi-stability.md - [x] All phases 9–15 complete or explicitly deferred with changelog entries
- [x] Documentation sync (architecture, crate-layout, enterprise evaluation)
- [x] Registry path confinement for symlink escapes
- [ ] CHANGELOG and release notes for
1.0.0 - [ ] Crates.io + PyPI publish per docs/maintainer/releasing.md
Done when: 1.0.0 published; no deprecated strict API remains; README and SPEC reflect supported upstream version.