no-terraform-guard-blocks
Ban Terraform validation, precondition, postcondition, and check blocks.
Why
The team keeps infrastructure declarations concise and reuses native provider controls and existing shared policy. Guard blocks can add a second policy layer to those declarations. This is an explicit design policy, not a claim that Terraform conditions are invalid or always redundant.
Fix
First identify the existing native or shared owner of the invariant. Do not replace a guard with a bespoke verifier, source-text test, repeated API audit, or deployment wrapper merely to satisfy this rule. Keep investigation and rollout readbacks one-off unless they close a demonstrated recurring enforcement gap. Preserve existing deployment safety invariants. Use reviewed immutable guard contracts when removing a guard would change deployment behavior. For other guards, move an invariant only after proving equivalent enforcement phase and behavior. Preserve Terraform types, provider validation, deletion protection and lifecycle settings. Review the behavior before removing a guard; no automatic deletion is provided.
Examples
check "ready" { assert { condition = var.ready error_message = "Require readiness." }}output "ready" { value = var.ready }data "example_image" "selected" { lifecycle { postcondition { condition = self.approved error_message = "Require an approved image." } }}data "example_image" "selected" { name = var.image }variable "replicas" { type = number validation { condition = var.replicas > 0 error_message = "Require a positive replica count." }}variable "replicas" { type = number }resource "example_service" "app" { count = var.enabled ? 1 : 0 replicas = var.replicas deletion_protection = true lifecycle { prevent_destroy = true }}resource "example_service" "app" { lifecycle { precondition { condition = var.ready error_message = "Require readiness." } }}resource "example_service" "app" { lifecycle { prevent_destroy = true }}