Compatibility Policy
From 1.0, a model, a script or a pipeline written for one 1.x release runs on every later 1.x release. A 1.x release may add a key, a command, an option, a name or a record field. It does not remove one, and it does not change what one means. Each promise below has a test that fails when a change breaks it, so a release cannot break a promise by mistake. Upgrading to 1.0 lists what changed from 0.28.0 to 1.0.
What 1.x Keeps
| Promise | What a 1.x release may change | Test that guards it |
|---|---|---|
| The YAML blueprint format: every key, its type and what it means | add a key, a value or a form; widen a limit; make a required key optional. Every difference from the 1.0 schema must be one of these | tests/unit/test_yaml_format_frozen.py |
The desflow command: every command, argument and option, and how a 1.0 command line is read |
add a command, an option that is not required, or a choice; widen a limit. Every 1.0 command line parses to the same values | tests/unit/test_cli_surface.py |
| The public Python API: every name at the import paths listed below, with its signature, including the schema registry serializers and deserializers | add a name, or an argument with a default | tests/unit/test_public_api.py and tests/unit/public_api.txt |
| The record format of Records and Telemetry: each field with its name, type and position | add a field after the last one of its kind, or a record kind that reaches only the sinks that ask for it, as trace does |
tests/unit/test_record_contract.py |
The extra names of pip install "desflow[<extra>]": kafka, redis, postgres, confluent, glue, parquet, iceberg, fit, watch, fake and all |
add an extra | tests/unit/test_extras.py |
The registry path forms, such as <simulation>.resources.<name>.current_cap, that an ingress message, a scenario step and registry.update write to |
add a form | tests/unit/test_registry_paths.py |
The reserved payload keys: a key with two underscores on each side belongs to desflow, a sink drops the keys it does not route by, and __topic__, __table__, __path__ and __stream__ choose the destination, as Reserved Payload Keys says |
add a key | tests/unit/test_record_contract.py and the routing test of each sink |
The public Python API is every name exported at these import paths:
desflowdesflow.valuesdesflow.blueprintdesflow.analysisdesflow.explaindesflow.modelsdesflow.resources- the connector modules under
desflow.connectors, such asdesflow.connectors.egress.kafkaanddesflow.connectors.ingress.file
The API Reference shows each name at its path. A name imported from a module inside a package, such as desflow.core.context or desflow.blueprint.build, works in 1.0 and may stop working in a later 1.x release, so import it from the path the API Reference shows.
What Is Not Covered
- Seeded output. The records of a seeded run can change between 1.x releases, such as when a fix changes a draw or the order of events at one instant. Such a change is never made without a note, as the next section says.
desflow explain --json. Its shape can change in 1.x, and itsschema_versionchanges with it.- A form marked experimental. A key or a command added in 1.x while it is marked experimental can change until a release removes the mark.
- A Python version. A 1.x minor release may drop one, as Supported Versions and Platforms says.
- Simulation server. The server, its MCP tools and its
patternblueprint block ship after 1.0 behind theserverextra and start as experimental. Its REST API under/api/v1only adds once it is released.
No Silent Change to Results
A change to the result of a valid blueprint is a break, even where seeded output is not promised. The release lists it under Upgrading in the Changelog, with its reason. The regression job of the CI pipeline runs every example, conformance blueprint and regression scenario on the last release from PyPI and on each new commit, and fails on a difference that tests/regression/expected.yaml does not list with the release that made it. From 1.0 it also runs the files of v1.0.0 on desflow 1.0.0 and on the new commit, so an edit to an example cannot hide a change in what a 1.0 blueprint does.
Deprecation
A name, key or option that a 1.x release replaces keeps working with a FutureWarning for at least one minor release. The warning names its replacement. It is removed only in the next major version, 2.0, and the Upgrading section of that release says what to change.
Breaks After 1.0
A break is made only in a major version. It needs a stated reason and an Upgrading line with the old behaviour, the new behaviour and what to change. Where it is cheap, the release also adds a setting that keeps the old rule for one major version.
Supported Versions and Platforms
Fixes, including security fixes, ship in 1.x releases, and a release before 1.0 gets none. SECURITY.md says how to report a vulnerability. 1.0 supports Python 3.11 to 3.15, the versions the CI pipeline tests. A 1.x minor release may drop a Python version that has reached its end of life, or that a dependency no longer supports. That is not a break: the release raises requires-python, so pip installs the last release that supports the older Python.
| Platform | What is supported |
|---|---|
| Linux | every feature, including the examples that run services with odctl |
| Windows through WSL2 | the same as Linux, and the recommended way to run desflow on Windows |
| macOS | the core library and the command |
| Windows | the core library and the command; the service stacks of the examples are not supported |
Older Docs
The docs of each published release stay on the site under its version. A version other than the latest shows a banner that links to the latest. The docs of 0.20.0 to 0.28.0 show no banner, because each was built with the templates of its release, before the banner existed. Those releases came before this policy, so their pages promise no compatibility.