Section V · Changelog Encrypted Postgres backups Read the changelog
dbcrate

v0.5.3

2026-05-09

Beta

Schedules start firing. The agent is pinned to a database.

Agent

Added

  • AddedHeartbeat dispatch: pending jobs are parsed from the heartbeat response and run through the worker pool. No long-poll, no side channel.
  • Addedrun_probe command handler for live database-connectivity checks; the dispatcher maps it through the same lifecycle as backup and restore.
  • Added--log-level flag with debug-level wire tracing for heartbeat and /config.
  • AddedSOPS-managed key material for builds; the published binary registry is now sourced from a static-musl bash matrix.

Changed

  • Changed/config wire shape: expected_postgres_versionpostgres_major (nullable). The probe-result contract carries the detected major back.

Control plane

Added

  • AddedSchedule firing wired end-to-end. Schedule rows synchronise into the django-q2 scheduler on signal, a boot check refuses to start if the two have drifted, a scheduler heartbeat gates /readyz for the first three minutes, and a missed-fire detector flips stale QUEUED runs so the next cron tick can pick them up.
  • AddedCron → Job dispatch and pending-jobs in the heartbeat response.
  • AddedAgent ↔ database pinning. Each database is pinned to a single agent in its organisation. The dispatcher refuses to send work to any other agent, and /config narrows to the agent's pinned databases only.
  • AddedOn-demand “Run backup now” from the database detail page, async, with a flash, hidden until the pinned agent has been heard from.
  • AddedFirst-run welcome pages on databases, agents, backups, and storage when an organisation has no rows yet, with the next CTA inside the empty-state hero.
  • AddedRedesigned backups list and detail: window / outcome / database facets, cross-field search, fixed-layout responsive rows, and a presigned download link for the encrypted object.
  • AddedNewsreader / Inter / JetBrains Mono self-hosted across the console, theme-aware wordmark and favicon on every page, and the canonical overview dashboard built from real organisation data.

Fixed

  • FixedUser-defined schedules that never fired because of a stale next_run and a leftover second cluster. Q2 is collapsed to one cluster, and Schedule changes drive the row directly.
  • FixedEmpty-list pages no longer issue duplicate queries; an EXISTS-first short-circuit short-circuits the empty case.

v0.5.2

2026-04-22

Beta

The agent becomes a daemon. The dashboard learns to drive it.

Agent

Added

  • AddedProduction CLI shape: dbcrate enroll (one-shot, token → identity) and dbcrate run (daemon), plus dbcrate version. Re-enrolling is a deliberate operator gesture — the identity directory must be removed first.
  • AddedIdentity: Ed25519 keypair generated on the host, CSR built locally, certificate persisted alongside SQLite-backed durable state so in-flight job rows and identity survive a host restart.
  • AddedmTLS HTTP client that fetches identity per request and rotates on renewal.
  • AddedDaemon: heartbeat loop, state machine, halt-on-401, graceful shutdown that drains the worker pool.
  • AddedWorker pool: bounded-concurrency executor with a durable lifecycle; a recoverer reconciles stale in-flight rows on startup.
  • AddedCommand handlers for run_backup and run_restore, plus result-reporting endpoints (PostBackup, PostRestore) that carry structured failure reasons back to the control plane.
  • AddedCertificate renewal goroutine, with a ShouldRenewAt decider and a renewal RPC that obtains a fresh certificate well before expiry.

Control plane

Added

  • AddedDatabase creation wizard. Five steps — connection, agent pick-or-install, storage destinations (one primary, optional mirrors), schedule rules, review — with the agent step live-polling for fresh heartbeats so the operator can watch a freshly installed agent come up in the same tab.
  • AddedStorage destination probe: an end-to-end head_bucketput_objectget_object (with byte match) → delete_object sweep, run synchronously at submit and exposed as an HTMX endpoint for the “Test now” button. Results are cached on the destination.
  • AddedExpanded storage form to every S3-compatible provider with a tested config, plus a generic custom-endpoint option.
  • AddedAgent certificate renewal endpoint and a CRL endpoint.

v0.5.1

2026-03-25

Beta

Backups become unreadable to us. The agent encrypts on the host; the control plane keeps nothing it can decrypt.

Agent

Added

  • Addedage v1 encryption pipeline (X25519 + ChaCha20-Poly1305). Encrypt, decrypt, and recipient-fingerprint paths, exercised end-to-end against vanilla upstream age on the test path.

Control plane

Added

  • AddedEnd-to-end encryption to the organisation's public key. Per-organisation X25519 keypair, auto-issued at organisation creation, with a one-time recovery-key download gated behind recent-auth on the security tab. A backfill command exists for organisations created before the keypair work landed.
  • AddedPer-backup fingerprint pinned at upload time. A backup's file key is unwrapped on demand with a ranged GET against the age header, so only the few bytes needed reach the control plane.
  • AddedKeypair rotation as a one-button operation on the organisation security tab. The rotation re-wraps each backup's age header (the file body is untouched), records progress in a KeypairRotationJob, and handles backups that arrive mid-rotation.
  • AddedSettings shell with tabs (Organisation / People / Security) for admins, mirroring the operator profile (Identity / Security / Preferences / Activity). Timezone middleware and a user_dt filter route every timestamp through the operator's preferences.
  • AddedOrganisation invitations, with SHA-256-hashed tokens and an accept flow.

Removed

  • RemovedAn earlier in-database cache of unwrapped DEKs. Rotation operates on the age header directly; nothing decrypted lives at rest in the metadata DB.

v0.5.0

2026-02-26

Beta

The control plane comes online. The agent stops talking to YAML and starts talking to a server.

Agent

Changed

  • ChangedProject pivots to a server-driven architecture. The dev-mode YAML harness is kept for local development; the agent's source of truth in production is now the control plane it heartbeats to.

Control plane

Added

  • AddedFirst public cut. Django 6 application with operator accounts, organisations, role-based access control across four roles, an append-only audit log, envelope encryption for stored credentials, redacted structured logs, /healthz and /readyz endpoints, a CSP-enforcing middleware, and a django-q2 task cluster wired into boot.
  • AddedDatabases, storage destinations, schedules, and retention policies as first-class records. The default retention is GFS (7 daily, 4 weekly, 12 monthly), overridable per database, with an optional hard age bound.
  • AddedMutual TLS between the agent and the control plane. The agent generates its keypair on the host, sends a CSR, and receives a leaf certificate signed by the agent CA. The private key never leaves the host.
  • AddedHeartbeat and /config endpoints with hash short-circuiting — the server tells the agent it is up-to-date without re-sending the whole config when nothing has changed.
  • AddedSingle-use job credential exchange. Database passwords and storage secrets are fetched per job, never stored on the agent's disk, and the issuance is recorded in the audit log.
  • AddedOperator-facing backups history and a console dashboard. One-shot restore initiation from the console, with the agent reporting the result back.

v0.4.1

2026-01-22

Alpha

And to talk to SFTP.

Agent

Added

  • AddedSFTP storage backend, planned and built across forty-nine scenarios. OpenSSH + SFTP on the integration path, sat behind the same StorageBackend interface the S3 path uses.
  • AddedUpload / Download / Delete / List / ResumeUpload on SFTP, with the same crash-resume receipt the S3 path uses.

Changed

  • ChangedConfigProvider rejects S3 and SFTP destinations missing required fields up front, instead of failing partway through a job.

v0.4.0

2025-12-18

Alpha

The agent learns to talk to S3.

Agent

Added

  • AddedS3-compatible storage backend, built on AWS SDK v2 with a configurable endpoint. Works against AWS, Cloudflare R2, Backblaze B2, MinIO, Wasabi, Hetzner Object Storage, DigitalOcean Spaces, and anything else that speaks the protocol.
  • AddedResumable multipart uploads. The agent persists a small receipt after every part, so a crashed upload restarts where it left off instead of from byte zero.
  • AddedIntegration suite that drives the backend against a real MinIO — Upload, Download, Delete, List, and ResumeUpload, plus credential-leak negative tests.

Changed

  • ChangedBackups are keyed automatically from the database name and a UTC timestamp when no explicit key is supplied; the previous required flag is now optional.

v0.3.0

2025-11-25

Alpha

Postgres binaries get a registry, a signature, and a trust chain that survives rotation.

Agent

Added

  • AddedHTTPS binary registry with signed manifests. The agent fetches a pg_dump / pg_restore bundle for the server's major on demand and verifies the manifest signature before extraction.
  • AddedTwo-key trust hierarchy: a long-lived ROOT public key baked into the agent at build time signs a short-lived MSK certificate; the MSK signs every published manifest. Rotation does not require a new agent build.
  • Addeddbcrate binaries list, dbcrate backup, and dbcrate restore as one-shot dev CLI subcommands against the configured registry.
  • AddedReal-fixture error tests for the registry path: server failures, network failures, cache corruption. Each one returns a clean, well-typed error rather than a panic.

Changed

  • ChangedBuild pipeline: make build-dev and make build-prod bake the registry URL into the binary via -ldflags. The runtime YAML block becomes optional.

Fixed

  • FixedResponse size caps on registry fetches, a deterministic clock for manifest-validity checks, and a robust path for resolving the cert URL relative to the manifest.

v0.2.0

2025-10-20

Alpha

The agent learns to take a backup, put it back, and do both across every supported Postgres major.

Agent

Added

  • AddedEnd-to-end streaming backup pipeline: pg_dumpzstd → authenticated encryption → upload. Nothing of size is written to local disk.
  • AddedInverse restore pipeline: download → decrypt → decompress → pg_restore, closing the dev-mode loop.
  • AddedLocked-flag pg_dump and pg_restore adapters. The agent always emits Postgres custom format with a fixed set of flags.
  • AddedCross-version matrix: pg_dump pinned to the source's major, pg_restore chosen as max(source, target), with a small unencrypted descriptor sidecar so the restore knows which binary pair to ask for.
  • AddedEnd-to-end test matrix that runs backup and restore against real Postgres 13 through 18 in Docker.

v0.1.0

2025-09-15

First printing

The project is laid out. The agent is given a shape, and four interfaces to talk to the world.

Agent

Added

  • AddedProvider interfaces locked at the agent boundary: ConfigProvider, StorageBackend, BinaryRegistry, Notifier.
  • AddedDev-mode implementations — a YAML config loader, a local filesystem backend, a local-directory binary registry, and a stderr notifier — behind a dual-signal dev-mode gate.
  • AddedPre-flight Postgres major-version detection. The agent refuses to back up a server whose major it has no matching dump binary for, with a clear error rather than a half-finished archive.

The end of the record

Releases prior to v0.1 are kept in the engineering archive. They are not, in good conscience, fit for a public document.