diff --git a/POWER.md b/POWER.md index 8a1c939..09a7b4f 100644 --- a/POWER.md +++ b/POWER.md @@ -25,6 +25,8 @@ Every Terraform/OpenTofu response must include: Never recommend direct production apply without a reviewed plan artifact and approval. +Never run `terraform destroy` (targeted or full) without first running `terraform plan -destroy` and showing the user every resource that will be deleted — including implicit dependents pulled in via locals or `for_each`. Get explicit confirmation before proceeding. Never use `-auto-approve` on destroy. + ## Workflow 1. **Capture execution context** — runtime+version, provider(s), backend, execution path, environment criticality. @@ -42,6 +44,7 @@ Never recommend direct production apply without a reviewed plan artifact and app | **Identity churn** | Resource addresses shift after refactor, `count` index churn, missing `moved` blocks | [Code Patterns: count vs for_each](skills/terraform-skill/references/code-patterns.md#count-vs-for_each-deep-dive), [Code Patterns: moved blocks](skills/terraform-skill/references/code-patterns.md#moved-blocks-terraform-11), [Code Patterns: LLM mistakes](skills/terraform-skill/references/code-patterns.md#llm-mistake-checklist--code-patterns) | | **Secret exposure** | Secrets in defaults, state, logs, CI artifacts | [Security & Compliance](skills/terraform-skill/references/security-compliance.md), [Code Patterns: write-only](skills/terraform-skill/references/code-patterns.md#write-only-arguments-terraform-111), [State Management](skills/terraform-skill/references/state-management.md) | | **Blast radius** | Oversized stacks, shared prod/non-prod state, unsafe applies | [State Management](skills/terraform-skill/references/state-management.md), [Module Patterns](skills/terraform-skill/references/module-patterns.md) | +| **Destroy cascade** | Targeted destroy deletes more than expected; locals referencing a targeted resource make all `for_each` consumers implicit dependents | Response Contract: plan-destroy first; [State Management: Safe Destroy](skills/terraform-skill/references/state-management.md#safe-destroy-protocol) | | **CI drift** | Local plan ≠ CI plan, apply without reviewed artifact, unpinned versions | [CI/CD Workflows](skills/terraform-skill/references/ci-cd-workflows.md), [Code Patterns: versions](skills/terraform-skill/references/code-patterns.md#version-management) | | **Compliance gaps** | Missing policy stage, no approval model, no evidence retention | [Security & Compliance](skills/terraform-skill/references/security-compliance.md), [CI/CD Workflows](skills/terraform-skill/references/ci-cd-workflows.md) | | **Testing blind spots** | Plan-only validation of computed values, set-type indexing, mock/real confusion | [Testing Frameworks](skills/terraform-skill/references/testing-frameworks.md) | diff --git a/skills/terraform-skill/SKILL.md b/skills/terraform-skill/SKILL.md index ede5994..f14fbe4 100644 --- a/skills/terraform-skill/SKILL.md +++ b/skills/terraform-skill/SKILL.md @@ -23,6 +23,8 @@ Every Terraform/OpenTofu response must include: Never recommend direct production apply without a reviewed plan artifact and approval. +Never run `terraform destroy` (targeted or full) without first running `terraform plan -destroy` and showing the user every resource that will be deleted — including implicit dependents pulled in via locals or `for_each`. Get explicit confirmation before proceeding. Never use `-auto-approve` on destroy. + ## Workflow 1. **Capture execution context** — runtime+version, provider(s), backend, execution path, environment criticality. @@ -40,6 +42,7 @@ Never recommend direct production apply without a reviewed plan artifact and app | **Identity churn** | Resource addresses shift after refactor, `count` index churn, missing `moved` blocks | [Code Patterns: count vs for_each](references/code-patterns.md#count-vs-for_each-deep-dive), [Code Patterns: moved blocks](references/code-patterns.md#moved-blocks-terraform-11), [Code Patterns: LLM mistakes](references/code-patterns.md#llm-mistake-checklist--code-patterns) | | **Secret exposure** | Secrets in defaults, state, logs, CI artifacts | [Security & Compliance](references/security-compliance.md), [Code Patterns: write-only](references/code-patterns.md#write-only-arguments-terraform-111), [State Management](references/state-management.md) | | **Blast radius** | Oversized stacks, shared prod/non-prod state, unsafe applies | [State Management](references/state-management.md), [Module Patterns](references/module-patterns.md) | +| **Destroy cascade** | Targeted destroy deletes more than expected; locals referencing a targeted resource make all `for_each` consumers implicit dependents | Response Contract: plan-destroy first; [State Management: Safe Destroy](references/state-management.md#safe-destroy-protocol) | | **CI drift** | Local plan ≠ CI plan, apply without reviewed artifact, unpinned versions | [CI/CD Workflows](references/ci-cd-workflows.md), [Code Patterns: versions](references/code-patterns.md#version-management) | | **Compliance gaps** | Missing policy stage, no approval model, no evidence retention | [Security & Compliance](references/security-compliance.md), [CI/CD Workflows](references/ci-cd-workflows.md) | | **Testing blind spots** | Plan-only validation of computed values, set-type indexing, mock/real confusion | [Testing Frameworks](references/testing-frameworks.md) | diff --git a/skills/terraform-skill/references/state-management.md b/skills/terraform-skill/references/state-management.md index ede40ef..5704884 100644 --- a/skills/terraform-skill/references/state-management.md +++ b/skills/terraform-skill/references/state-management.md @@ -16,6 +16,7 @@ This document provides detailed guidance on state management, from remote backen 5. [Multi-Team State Isolation](#multi-team-state-isolation) 6. [State Recovery & Troubleshooting](#state-recovery--troubleshooting) 7. [State Best Practices Summary](#state-best-practices-summary) + - [Safe Destroy Protocol](#safe-destroy-protocol) --- @@ -1792,6 +1793,16 @@ rm .terraform/terraform.tfstate.lock.info # ❌ Dangerous - High blast radius ✅ **Instead:** Split by component/team/environment +### Safe Destroy Protocol + +A targeted destroy can cascade far beyond its targets via implicit dependencies. Always follow this sequence: + +1. Run `terraform plan -destroy [-target=...]` — never skip straight to destroy +2. Read **every** resource under "will be destroyed", not just the targeted ones +3. ⚠️ Watch for `for_each` resources fed by a local that references a targeted resource — all instances become implicit dependents (e.g. targeting an `aws_eip` that is referenced in a `locals {}` block used by a `for_each` record resource will destroy **all** those records) +4. Get explicit user confirmation of the full list before proceeding +5. ❌ Never use `-auto-approve` on destroy in production + ### LLM Mistake Checklist — State Management Common model mistakes to correct before returning state-related recommendations: @@ -1804,6 +1815,7 @@ Common model mistakes to correct before returning state-related recommendations: - mixes prod and non-prod in the same backend key - recommends workspace-only isolation as a substitute for backend-level IAM separation - writes DynamoDB-lock configuration on Terraform 1.10+ instead of using `use_lockfile = true` on the S3 backend +- runs `terraform destroy -auto-approve` or skips `plan -destroy` before a targeted destroy — missing implicit dependents pulled in via shared locals - reads via `terraform_remote_state` within a single team's stack instead of using module outputs (see [module-patterns.md](module-patterns.md#3-use-terraform_remote_state-sparingly--only-at-true-ownership-boundaries)) - omits the rollback/recovery note for destructive state operations