Skip to content
downpipes docs

Changelog and versioning

downpipes tracks more than one version, and they move independently. This page explains what each version line means, which version each artefact carries, and how the release artefacts relate to one another. It is for a developer or an auditor who needs to reason about compatibility. It also hosts the human-readable change record.

The headline distinction is the one to hold onto. The on-disk archive format carries its own version, downpipe/0.1.0, and it moves independently of any tool’s version. It is a semver version. While the major is 0, a change to any byte-level rule of the format bumps the minor, which is a new format identity rather than a revision of the old one, and a patch changes no byte-level rule. The reader, the recovery CLI and the engine each carry their own, separately moving version; changing one of them is not changing the format.

The version lines

There are four version lines, and they answer different questions.

Version lineWhat it isWhere it is setMoves when
Archive formatThe on-disk format string downpipe/0.1.0. It appears byte-identically in the cleartext root manifest and in the format’s key-derivation labels.The format constants, shared by the Go reference and the engine.Only a change to a format rule. While the major is 0, a byte-level change bumps the minor and is a new format identity; a patch changes no byte-level rule.
Tool (CLI) versionThe version of the offline downpipe reader and recovery CLI.Injected at release time by the build pipeline; an unstamped local build reports dev.Per CLI release.
Engine versionThe engine’s own release version, compared against the vendor-signed recommended version on the update check.A constant in the engine source, bumped per engine release.Per engine release.
Console versionThe console’s own build-stamped version, shown on the Provenance card and compared against the signed channel’s console component in the browser (the engine cannot know which console build a browser is running).Stamped by the console build into the bundle and its build-stamp file.Per console release.

The format version is the contract that matters for recovery. Because the reader and the format are versioned separately, an archive is readable by any reader accepting its format identity, whichever engine version produced it. A reader for the current format accepts exactly downpipe/0.1.x, so it opens every archive in the current format line and refuses one that names a different identity. That separation is what lets the recovery path stay independent of the engine.

The format version is distinct from the tool version

Do not conflate the two. The archive format string downpipe/0.1.0 lives in the format spec and moves only when a format rule changes. The tool version is a separate number that the CLI binary reports, and a plain local build of the CLI reports dev rather than a release number. A release of the CLI does not move the format version, and a change to the format does not pin the CLI to any one tool version.

The archive format version

The archive format is downpipe/0.1.0, specified normatively in the format spec and pinned by the conformance vectors. The version string is not cosmetic: it appears byte-for-byte in the root manifest and is mixed into the format’s HKDF and MAC labels, so it is bound into the cryptography rather than being a loose tag. Change the string and you change the derived keys, which is why a byte-level change produces a new format identity rather than an amendment to the existing one.

A change to any byte-level rule of the format is a new format version, not an erratum and not a changelog entry. While the major is 0, that change bumps the minor, and a reader built for the current format does not accept the result. A patch is reserved for a change that touches no byte-level rule, which is why a reader accepts the whole downpipe/0.1.x line rather than one exact string. That is a deliberately high bar. It means an archive’s interoperability is governed by the spec and its vectors, and a reader either accepts an archive’s format identity or it does not. The change record below tracks the engine, the console and the reader; it does not track format-rule changes, which are a spec concern.

The tool version and the engine version

The CLI’s version is injected at release time by the build pipeline through a linker flag. A plain go build, with no release stamping, leaves the version at dev, so an unstamped local build reports itself as dev. A build that the release pipeline did not cut reports dev, not a release number.

The engine carries its own version constant, separate from the CLI. The update check reads it and compares it against the recommended version in the vendor-signed channel: an update is available when the recommended version is newer than the engine’s own. The engine version also gates compatibility, since a release can declare a minimum engine version it must be applied onto, and the one-click apply refuses to apply a release onto too old an engine. A release may also carry a console component with its own version; the console compares that against its own baked build stamp in the browser, because the engine cannot know which console build a browser is running.

The release artefacts, and what each one is

The version numbers above are carried by several distinct artefacts. Each one is worth setting out before you reason about compatibility from a number.

The reader is built from source with Go 1.26 or newer, from a copy of the module you hold. downpipes-io/downpipe is a public, MIT-licensed repository, so go install github.com/downpipes-io/downpipe/cmd/downpipe@latest and a plain git clone both resolve. For an actual recovery, hold the source and a Go toolchain that already satisfies the toolchain go1.26.6 pin in go.mod in advance, and build with go build -mod=vendor, so the recovery itself makes no network call at the moment you need it. Install the tool sets out what that pin means for a build on a machine with no network.

ArtefactWhat it is
The git tagThe tag a release is cut from. A tag names a reader build, never an archive format version, and the two number spaces move independently.
A from-source vendored buildBuilt with go build -mod=vendor against the dependencies checked into ./vendor, with no module download, and with no network call at all provided the machine’s own Go already satisfies the toolchain go1.26.6 pin. Run downpipe --help afterwards and confirm prune, recombine and unseal-export are listed before relying on it for a real recovery.
The release buildThe release pipeline builds against a tag and produces platform archives, CycloneDX SBOMs, a checksum file and a cosign Sigstore bundle over that checksum file.
The version a binary reportsThe release pipeline stamps the tag into the binary through a linker flag. A local build runs no such pipeline, so it reports dev.

Confirm the command set, not just the version string

Confirm the reader is complete with downpipe --help before a real recovery, and check that prune, recombine and unseal-export are listed. A from-source build stamps no release version, so the version string alone will not tell you whether the command set is complete.

Customers self-host their own engine and console, each running in their own Cloudflare account. The vendor serves the signed channel that self-hosted engines pull, and the base config pins its signer, so a base-config engine reports the channel as configured and verified. The deployed Cloudflare version id of a running engine is recorded for the update self-check, but it is not surfaced as a customer-facing version number; the version a customer reasons about is the engine version above.

The change record

The change record below follows the Keep a Changelog convention and Semantic Versioning. Each heading names the component it records, because the engine, console and tool lines move separately, as set out above. A tool version heading is not the archive format version, which is downpipe/0.1.0 and is tracked separately. Each entry states what the release contains. The line-by-line record, including dependency updates, is the CHANGELOG.md in each component’s repository.

Engine 0.3.5, 2026-09-21

The engine release that the signed stable update channel recommends. The public release workflow built and attested it. It writes the archive format downpipe/0.1.0.

Backup destinations are Cloudflare R2, Amazon S3, Google Cloud Storage and Azure Blob Storage. An Azure Blob destination supports immutable (WORM) retention and the Azure Government and Azure China cloud endpoints. It signs in as a Microsoft Entra service principal or with a SAS credential. The engine refuses a destination endpoint that resolves to a private, loopback or link-local address, and the destination client screens every request against the host it is about to reach. A DEST_ENDPOINT of http://localhost, http://127.0.0.1 or http://[::1] is refused. The syslog-over-TLS audit-export sink refuses a private, loopback or link-local host when you save the destination, and again before it opens a socket.

A self-serve licence binds to the Cloudflare accounts that activate it, up to the band’s estate count. The engine records its own Cloudflare account id after its first verified source attach or update, and at the end of a self-update. The engine status reports that account id, and the console sends it when it activates a licence.

A restore into a Cloudflare D1 database that is refused because the target already holds data writes nothing for that database. The SLA compliance report states the exact time window each row measures. After a recovery-code sign-in, a new passkey enrolment holds the new recovery codes pending until you confirm them in the console. The previous codes keep working until then. The offline reader 0.3.3 ships alongside this release, on its own tool version line.

Console 0.2.6, 2026-09-21

The console component that the signed stable update channel carries beside engine 0.3.5. The public release workflow built and attested it.

The Integrations screen shows every SIEM, observability, ITSM and notification destination as a logo tile, and shows which are connected, off or available to add. From the console you configure and monitor SIEM log push (Splunk HEC and other common formats), OTLP metrics push, and pull feeds for Prometheus, Microsoft Sentinel, Cribl and Exabeam.

You can add Azure Blob Storage as a destination, beside Cloudflare R2, Amazon S3 and Google Cloud Storage. Next to a second destination, the default Cloudflare storage from deploy time is labelled as the deploy-time binding and offers no Replace option, because it holds no separate credential. Multi-destination cost estimates add the storage, write and restore or drill costs of every destination in a 3-2-1 setup.

A D1 restore can restore a subset of tables. Media and object restores are queued and tracked per item, with self-identifying labels. For break-glass key recovery, the browser reassembles an M-of-N Shamir key quorum and offers the key for download, with no command line. A licence activates with a short claim code sent by email, which the console exchanges for the signed licence token.

Security Centre, with passkeys, recovery codes and the owner-approval inbox, is available immediately after deploy, before the guided setup finishes. After a forced passkey re-enrolment, the console asks you to confirm that you saved the new recovery codes before it retires the previous codes. Access and security lists every live session for the account, with a Sign out on each. A pasted admin token is exchanged for a minted session and then discarded, so the browser does not keep the token. Every console file picker refuses a file above 64 KiB before it reads the file.

Reader 0.3.3, 2026-09-21

The offline reader, the recovery CLI and the library. The public release workflow built and attested it. It reads the archive format line downpipe/0.1.x. The release carries platform archives, CycloneDX SBOMs, checksums.txt and a Sigstore bundle over that file (checksums.txt.cosign-bundle).

The offline recovery path. The keygen, inspect, keys, verify, attest, restore, selftest, prune, recombine and unseal-export commands. The recovery path imports no telemetry and no vendor SDK. It calls no vendor service and no Cloudflare API, and it reads only the archive you point it at. A holder of the destination bucket bytes and the offline break-glass key can recover with no vendor in the loop.

Verification and attestation. End-to-end verification against an operator-pinned signer, the recipient set, the key commitment, every shard hash, the declared record count, the Merkle root and each record’s hash, with freshness enforced against the signed run log. A keyless attestation that verifies the root signature, the shard hashes and the run log without the break-glass identity and materialises no plaintext.

Restore targets. A dry run by default that plans the writes and reports conflicts, with --apply to write. The targets are a file per record, dotenv lines to stdout, and a discard sink that decrypts and verifies every record while writing nothing. A restore never overwrites existing target state.

The hybrid envelope. The post-quantum hybrid envelope: X25519 with ML-KEM-1024 for confidentiality with AES-256-GCM in a streamed cipher, and Ed25519 with ML-DSA-87 signatures where both halves are required and there is no downgrade, with HKDF-SHA-384 throughout. The hybrid combiner is pinned by a known-answer vector.

Reading from a bucket. Reading archives from a local directory, an S3-compatible bucket or an Azure Blob container, with every redirect refused. S3 credentials come from the standard AWS environment variables, and Azure credentials from AZURE_STORAGE_KEY or AZURE_STORAGE_SAS_TOKEN. The Azure backend has no delete, so prune --apply refuses against an Azure container.

The provisioner path. The setup, preflight, init and update commands used to stand up or upgrade the engine. The preflight command makes read-only GET-only calls to the Cloudflare API with an operator-supplied token. The setup command is a dry run by default that prints its plan and contacts nothing; under --apply it writes to Cloudflare, creating an Access application and policy and putting Secrets Store entries and Worker bindings. The init and update commands are plan printers that make no network call. None are on the recovery path.

Exit codes and version reporting. The six SPEC-normative exit codes, and codes 7 to 13 outside that set, as set out on the CLI exit codes. The version, --version and -v outputs report the build version, injected at release time and reported as dev for an unstamped local build.

Signed report verification. From reader 0.3.4, the verify-report command checks the signature on an assurance report that the engine generated. It reads the report JSON and your signer.pub, and it needs no archive and no identity. It makes no network call and is not on the recovery path. The command reference sets out its flags and exit codes.

Why the format version and the tool version are kept apart on purpose

The format constants live in a leaf package that imports none of the crypto, reader or command code, so the version-pinned byte rules sit in one place that the writer, the reader and the conformance vectors all share. The engine carries a parallel copy of those same constants, which must match the Go reference byte for byte: a label or a size that diverges between the two would be a silent interoperability break.

Keeping the format version in that leaf, separate from the tool and engine versions, is what lets the tool evolve without touching the format and lets the format move without pinning the tool. It is also why recovery holds across versions: an archive written by any engine version is openable by any reader that accepts the archive’s format identity, with no dependency on matching version numbers between the writer and the reader.

Where this fits

  • The command reference documents the downpipe CLI whose version this page describes, including the version command.
  • The open-core boundary explains which parts are MIT and which are source-available under the Elastic License 2.0, and how the from-source vendored build works as the no-network install path.
  • Applying an update from the channel covers how the engine version is compared against the vendor-signed recommended version.
  • Prove recoverability shows the offline reader recovering an archive independent of the engine version that wrote it.

Last updated .