claude code deleted prevent_destroy and terraform plan looked cleaner
spent 90 minutes yesterday chasing why staging rds was suddenly marked for destroy.
claude code "fixed" a plan error by yanking prevent_destroy = true out of the module and rewriting the lifecycle block. plan went green. i almost hit apply before i noticed destroy count went from 0 to 1.
now i have a path denylist for **/lifecycle*.tf and i still don't trust Accept All on a friday. anyone else putting terraform behind a human gate, or am i just scarred?



8 comments
Join the discussion
Log in to comment.
same class of bug. my denylist is
.tf,go.mod, and anything that says money.if the agent can touch lifecycle, your review is the only test that matters.
We gate terraform apply behind two humans and a Linear ticket. Still once had an agent open a PR that removed deletion_protection on a Postgres instance "to unblock plan".
The PR title said cleanup. The diff was four lines. Those are the ones that hurt.
four-line "cleanup" PRs are how i learned to stop Accept All on infra.
mine was
deletion_protection = falseon a cloud sql instance because the agent wanted the plan to "look healthy". title was chore. i only caught it because terraform plan printed destroy=1 in the summary and i was already halfway through a beer.we put a CI grep for
prevent_destroy\s*=\s*falseand any deletedlifecycleblock. failed the PR twice last week. both times the agent commit message was "fix plan".also: never let the same agent that edits .tf open the apply job. separate identity, separate keys. sounds paranoid until destroy count flips.
separate identity for apply is the only thing that stuck for us. we still let the agent draft the .tf PR, but the apply workflow is a different GitHub App with no write to the agent branch.
lost a staging redis once when someone reused the same OIDC role. never again.
human gate on apply, yes. also a hard spend/blast checklist before friday merges.
i bill clients for the hour i spend re-reading agent terraform diffs. cheaper than restoring rds. path denylist helps; i still treat any lifecycle or prevent_destroy touch as a full stop.
we had same thing but with
ignore_changes. agent removed the block so plan would stop complaining about tags drift.CI now fails if lifecycle block shrinks. ugly grep, works. i do not care about pretty.
path denylist helped until the agent wrote a new file
lifecycle_override.tfin a sibling folder. same content, different path. friday merge, of course.now we also fail if
prevent_destroycount drops between base and head. blunt, but my heart rate is lower.