Skip to content

Environments and versioning

Status: GA Access: open, no token API contract: 0.3.0 · capability 2026-09-03.1 View as Markdown Open in Claude Open in ChatGPT
ContourBranchRuns wherePurpose
prodmainThe production host, on the nightly scheduleStable; every change arrives by deliberate promotion
devdevA local development stack (Docker: Postgres, Redis, API, web)Integration; all day-to-day work lands here first

The flow is one-directional: feature branches merge into dev via small pull requests; promotion to main is a separate, explicitly-approved step; deployment to the production host is a separate script run after that. A hotfix that must land on main directly is immediately forward-ported to dev in the same session — main is always a subset of dev.

Production is a single self-hosted Linux box behind a Caddy reverse proxy, reachable through a dynamic-DNS name on a non-standard port (entherium.duckdns.org:8443). That is the base URL in every example on this portal, and it is the real one — there is no managed API gateway and no vanity domain in front of it yet. The fleet of destination sites lives on separate hosts. For a platform at this stage the box is production: nightly runs, the API, the MCP server and the task board all answer from it, and its uptime is watched by an external dead-man’s switch.

This documentation is served from two places with the same build: from the API host under /developers/, and from a Cloudflare Pages mirror. The mirror is the canonical copy — every page’s canonical and og:url point there — and it stays up if the box does not. Both copies are rebuilt from the same commit by the same deploy scripts; when they differ, the mirror is the newer one.

Axis A: platform modules. Each module (platform, webui, contracts, services, this documentation site) is versioned independently by SemVer, derived automatically from Conventional Commits by release tooling — versions are never bumped by hand. An umbrella platform version tracks the whole.

Axis B: pipeline versions. Collect, Generate and Localize are versioned separately in the pipeline catalog, with immutable per-version code directories and per-contract pins. This axis moves at its own pace — a pipeline can advance several versions within one platform release, and vice versa. See Version lifecycle.

The two axes are deliberately decoupled: a platform deploy does not change which pipeline version the fleet runs, and promoting a pipeline version does not require a platform release.

  • Merged to dev — integrated, gate-checked (lint, types, tests run locally as the merge gate), not yet user-visible.
  • Promoted to main + deployed — running on the production host.
  • Enabled — the platform’s hard rule: a feature is only called deployed when it is switched on and its effect is observable (a metric, a page, a number). Code behind a disabled flag is explicitly not “deployed” in reports or documentation.