Releases: Fluent-Health/terraform-stack-plan
Release list
v0.44.0
Breaking
run stepis removed (#240). It was renamed torun wrapin #229 and kept
as a warning-only alias only until the downstream infra terramate scripts
switched over; that switch is live and no other caller remains.run stepnow
exits 2 as an unknown subcommand.run wrapis unaffected — it is the
canonical verb.
This is why the bump is a minor rather than a patch: the CLI surface shrank.
Security
Dependency fixes for the binary and the build:
google.golang.org/grpc→ 1.83.1 (#242) — clears GHSA-hrxh-6v49-42gf
(gRPC-Go: xDS RBAC and HTTP/2 vulnerabilities) and CVE-2026-84304 (gRPC-Go:
heap memory exhaustion via HTTP/2 DATA frame fragmentation). grpc is linked
into the binary, reachable viainternal/gauth→
google.golang.org/api/option→google.golang.org/grpc, so this is the fix
that matters for a released artifact:v0.43.1shipped grpc 1.81.1.github.com/getkin/kin-openapi→ 0.144.0 (#242) — clears
GHSA-r277-6w6q-xmqw (critical) plus CVE-2026-76905, CVE-2026-77354 and
CVE-2026-73502. Note this package is an indirect requirement ofoapi-codegen
andgo mod whyreports the main module does not need it, so it was not
compiled into the binary — build-time only.web/uilockfile (#243, #246):tar→ 7.5.22,undici→ 8.10.1,postcss→
8.5.26,browserslist→ 4.28.8,nanoid→ 3.3.18, andjs-yaml→ 4.3.2 via
aresolutionsoverride (@redocly/openapi-corepins it at an exact 4.2.0, so
there was no in-range target). All of these are Node-side build tooling and
none appears in the shipped SPA bundle — the built bundle's sourcemap
enumerates 41 modules and contains none of them. CI does rebuilddist/
before the Go build, so the embedded SPA content changes even though the
vulnerable packages never enter it.
Docs
v0.43.1
Patch release: fixes tfstackplan uniqueness to support repos with mixed BundleInstance layouts.
Fix
uniqueness: skip manifests with noenvironmentsblock instead of failing loud (#239, closes #238).LoadUnitsnow skips a matched instance manifest that lacks anenvironments:block entirely — a single-env / non-comparable instance (e.g. a per-env-file BundleInstance with only top-levelinputs) — rather than erroring. A present-but-malformedenvironmentsblock stays a hard error. This unblocks wiring the lint into repos (e.g.Fluent-Health/infra) that mix per-env-file and environments-block instances.
No other changes since v0.43.0.
v0.43.0
Batches issue #227 (the abstraction-tightening cleanup — workstreams B/C/D/A) plus the new uniqueness lint and two fixes, since v0.42.0.
Features
tfstackplan uniqueness— cross-env config uniqueness lint (#231).
Refactor — issue #227 (abstraction tightening)
- A — exec-event migration (#232 #233 #234 #235): execution/stack/edge/
superseded_bystate is now fully event-sourced through the new per-execution aggregateinternal/execution(streamrun:<execID>);executions/stacks/edges/execution_phasesare true projections rebuilt from the fold; the direct-write path (UpsertInit/UpdateStack/UpsertPhase/SetExecutionStatus/SupersedeExecution/ReviveExecution) is gone; the dead exec-event layer was removed frominternal/reconcile. - B — dead static-UI removal (#228): removed the orphaned
/imgSVG path and the user-facinggroup {}serve-config block (−961 lines). - C — naming/micro-packages (#229):
internal/statemoves→internal/moveset;run step→run wrap(with a warning alias); foldedinternal/causality→internal/runnerandinternal/presets→internal/classify. - D — docs restructure (#230): present-tense
docs/DESIGN.mdrewrite + reference-drift fixes.
Fixes
- serve: reset status and clear
superseded_bywhen an execution ID is reused (#226, closes #198). - claims/status: auto-discover server and default audience (PM-197, #225).
⚠️ Deploy note (breaking for live serve config)
Workstream B removed the group {} serve-config block. gohcl rejects unknown blocks, so any live serve .tfstackplan.hcl still carrying a group {} block must have it removed before deploying this version, or serve fails to start.
Deferred follow-ups
v0.42.0
Native merge queue fix (#221) + PR-view lifecycle fixes (#219, first shipped in v0.41.0).
Merge queue (#221) — with an armed serve-as-driver tier and GitHub's native merge queue, every queued PR stalled: serve posted no check on the merge-group head, so the required terraform/<env> context never appeared and the queue hung.
- Primary: resolve the merge group's PR from
merge_group.head_ref(gh-readonly-queue/<base>/pr-<n>-<sha>) — GitHub'scommits/{sha}/pullsreturns[]for the synthetic merge-queue commit, so the SHA lookup alone resolved no PR. - Secondary: always post the merge-gate check for the tier's own gated env, green when the PR changed no stacks (docs/CI/module-only), symmetric with the PR-head no-change check.
PR-view lifecycle (#219) — SHA-scoped lifecycle fold (no stale apply-side bar after a new push), verify renders done on a completed apply, honest stage badge.
Full changelog: v0.41.0...v0.42.0
v0.41.0
PR-view lifecycle-bar fixes (#219):
- SHA-scope the lifecycle fold — after a new push, the previous cycle's apply-side executions no longer render alongside the fresh plan (they were painting a stale, mostly-done "APPLYING" bar before apply had started).
- Verify segment renders done (green) on a terminally-succeeded apply when no verify step ran for those components, instead of sitting perpetually grey.
- Honest stage badge — no longer reads "applying" for a merely-pending (queued, not running) apply.
Full changelog: v0.40.0...v0.41.0
v0.40.0
PR view + approve flow (#216, #217)
Lifecycle stepper (#216)
- Context-aware segments: an apply run's housekeeping phases fold into the apply segment (sub-phase detail) — no more plan-side re-activation mid-apply; "now" is per-execution.
- Relevance-gated bar: plan-only PRs render a plan-only bar;
movesonly with detected state moves;initonly when observed. - The active plan/apply segment partially fills with k-of-N stack progress; plain-language phase descriptions in tooltip + caption; prominent per-tier stage badge (PLANNING/APPLYING/…).
- Honest no-change claims during apply (counts-known gating, plan-rollup fallback tagline).
Approve flow (#217)
- PAM requires a reason — the decision modal now prefills an honest editable default, marks the field required, and blocks empty submits; the UI backend defaults a missing reason as defense.
- Approve/deny decisions push to watching pages: new tier endpoint
POST /api/gate/reconcile(fire-and-forget nudge from the UI backend after every successful PAM decision) + the tier panel refetches approvals on SSE nudges — the gates strip and stepper update within seconds, no reload.
Wire: LifecyclePhase gains optional detail/progress_pct; new reconcileGates operation (all additive). Serve/UI-side only — no runner behavior change.
v0.39.0
PR view: lifecycle stepper refinements (#216)
- Context-aware segments: an apply run's housekeeping phases (warming/initializing/classify/report) fold into the apply segment as a sub-phase detail — a running apply no longer re-activates the done plan side; "now" is per-execution.
- Relevance-gated bar: plan-only PRs render a plan-only bar (no apply/verify noise);
movesshows only when the plan detected state moves;initonly when observed. - Real progress: the active plan/apply segment partially fills with k-of-N stack progress and shows the % in the caption.
- Plain-language phases: every segment carries a human description in the tooltip and the under-bar caption.
- Stage badge: PLANNING / AWAITING APPROVAL / APPLYING / APPLIED / … next to the tier name.
- Honest no-change claims: counts-known gating during apply; the tagline falls back to the plan rollup pre-classify.
Wire: LifecyclePhase gains optional detail + progress_pct (additive). Serve/UI-side only — no runner behavior change.
v0.38.0
PR view fixes (#215)
- Lifecycle stepper:
/api/lifecyclenow folds only the newest non-superseded execution per status context and coalesces re-observed canonical phase keys — no more repeatedprepare/linting/plan/...per push, one segment per phase. - Terminal plan status: a non-failed finalize persists
successfor plan/verify executions — the bar no longer sticks atreport · nowand the PRs list no longer pins to "planning". - Dependency graph: run-graph edges are normalized onto the stack namespace at record time (
runner.NormalizeEdgesin allrun *drivers) and defensively in the SPA — the PR-view graph renders instead of a blank box. - Flicker-free tier panel:
.latestresource reads, first-load skeleton, per-drill-in Suspense with shimmer, and an open animation — SSE refetches and stack clicks no longer collapse the panel. - Scanability: prominent change-summary tagline, group-header count rollups, bold counts on changed stacks, dimmed "— no changes" rows.
- Demo mode: emits the real phase sequence and a matching tier environment, reproducing these scenarios end-to-end.
Rollout note: serve + ui pick these up on deploy; edge normalization at record time requires the runner image on this version (older stored executions are normalized client-side).
v0.37.0
Release v0.37.0: Central UI reshape-completion — the three surfaces now match the reshape design.
- Ops board (#212): the applier-slot panel is wired to
/api/inspect/pool— per-tier capacity, occupied/free slot cards, and a waiting-for-slot list (replaces the placeholder). - PRs list (#213): per-tier lifecycle stage (terminal-wins, no more stuck-on-"running"), title/author/last-updated/change-summary, a merge/automerge badge, and a live GitHub merge-queue hero (new
/api/merge-queue). - PR view (#214): a unified per-phase lifecycle stepper (replaces per-stack progress blocks;
/api/lifecycle+ append-onlyexecution_phaseshistory), path-derived component grouping (no "untagged" catch-all), a decoupled gates strip that always surfaces pending approvals, a collapsible per-tier dependency graph, and removal of the● plancontext chips.