github mattrobinsonsre/terrapod v2.0.0-beta.2

one hour ago

Terrapod is a free, open-source platform replacement for Terraform Enterprise — remote runs, state, a module and provider registry, label-based RBAC and OPA policy, wrapped around OpenTofu or Terraform as pluggable engines. This is the second 2.0 beta, and it is about governing an Ansible configure: the two controls that decide what a configure is allowed to touch.

Highlights

  • OPA policy sets now apply to a configure — a configure has no plan JSON, so policy sets never gated one before. They do now, evaluated in-Job before the playbook runs, against the run's resolved inventory document (input.hosts, input.groups, input.children). A configure is a single Job, so there is no between-Jobs moment for the API to hold it — the gate runs first inside the Job and fails closed. Guard a rule on data.terrapod_context.run.phase ("plan" or "configure"): a workspace with both halves enabled produces one composite run whose plan and configure phases evaluate the same policy sets, so a rule written for the playbook fires on the Terraform plan as well unless it says which it is for. Read Upgrading to 2.0 → Policy sets now evaluate on a configure before upgrading if you have mandatory policy sets and configure-enabled workspaces.

  • hard_limit: a --limit no run can widen past — default_limit is a default, and a run that supplies its own --limit replaces it outright, so it was never a control. hard_limit is intersected with whatever limit the run ends up with: a run may narrow within it and none may escape it. Empty means no ceiling, so nothing changes for an existing workspace. It bounds every path uniformly — a manual run, a push-triggered configure, a derived one, a composite — and it bounds what the API shows as well as what a run does, so the resolved read, the ?limit= preview and the stored run artifact all come back already intersected. !prod — "no run may touch production" — is the shape most people want. Settable on the workspace, in a bulk update, on an autodiscovery rule and on a service-catalog item.

Bug Fixes

  • A 1.x state of terrapod_role or terrapod_policy_set could not be read at all. allow_labels and deny_labels moved from map(string) to map(list(string)) without a state upgrader, so terraform failed to decode the prior state on refresh with no path forward but to remove the resource and re-import it. Both resources now carry a state upgrader; the audit for it found the second instance, which was unreported.
  • Status indicators read as unlit, and offline was not red. The dot fills moved onto the *-500 ramp and offline is now red. Every indicator also renders its status word beside it: no single colour stop clears WCAG 1.4.11's 3:1 against both the light and dark surfaces, so the text is what carries the meaning rather than the hue.
  • The light theme's table surfaces were flat neutral grey. They now carry a blue tint complementary to the brand text, which makes a surface edge legible by hue rather than by luminance.
  • Copy-to-clipboard gave no feedback at three of its four sites, and the shared control imposed a 36px height inside a 24px toolbar, which cost the run-log pane 12px.
  • Four code-scanning alerts cleared, two of them now gated by the linter that can catch them.

Security

  • No advisories. The accepted-risk register is down to two entries from five — three were retired because their stated exit condition was met (pip 26.3 vendors fixed urllib3 and msgpack). Both survivors were re-verified against current upstream rather than restamped: Debian trixie still carries no ncurses fix, and pip 26.3 still vendors setuptools 70.3.0 against an exit of >= 78.1.1.
  • Dependency bumps: python-multipart, lucide-react, three and their types.

Status

Beta — the API, the chart and the CLI surface are settled enough to try, and docs/upgrading-to-2.0.md is the path from 1.x. Not yet recommended for production.

Full Changelog: v2.0.0-beta.1...v2.0.0-beta.2

Don't miss a new terrapod release

NewReleases is sending notifications on new releases.