Standards and workflows for building secure, well-structured Terraform modules, including planning gates, validation steps, and implementation guidance.
82
84%
Does it follow best practices?
Impact
80%
1.77xAverage score across 5 eval scenarios
Passed
No known issues
Confirm that edits to Terraform code produce the infrastructure changes you expect — no more, no less. Treat the outcome as a gate.
Before running plan, verify the environment. If any check fails, STOP and report the failure to the user; do not proceed.
terraform version.aws sts get-caller-identity. Failures here
usually mean missing credentials, expired SSO, or the wrong AWS_PROFILE.
Ask the user to authenticate; do not guess the profile.examples/test_app relative to the repo
root. If this directory does not exist, ask the user which directory to
run the plan in. Do not silently fall back to another path.All commands run from the plan directory (default examples/test_app).
Initialize (idempotent):
terraform init -input=falseGenerate a machine-readable plan:
terraform plan -input=false -lock=false -out=tfplan
terraform show -json tfplan > tfplan.jsonUse tfplan.json as the source of truth. The stdout rendering is lossy
and hard to reason about programmatically.
State your expectation, then read the plan. Before opening
tfplan.json, write down the concise list of changes you expected your
edit to cause (e.g. "add one aws_iam_policy, update the role attached
to aws_lambda_function.api"). Then extract from tfplan.json, for each
entry under .resource_changes[]:
addresschange.actions (e.g. ["create"], ["update"], ["delete", "create"])change.before/change.after
differ, and any change.replace_pathsCross-check: every expected change must appear in the plan, and every planned change must be explained by an expected change. Mismatches mean the task is NOT complete.
Clean up:
rm -f tfplan tfplan.jsonA pass is only when every planned action matches what you intended to change. "No errors" is not enough; a plan can succeed and still do the wrong thing. A plan with zero changes is a FAIL if you expected changes — it usually means your edit didn't take effect (wrong module path, unmodified variable, etc.).
replace / forced-new on a resource you only meant to tweak —
check change.replace_paths to find the attribute causing it.delete on stateful resources (RDS, S3, EFS, DynamoDB) — almost
never intended; investigate before proceeding.count/for_each, variable default).When the plan passes, tell the user briefly which resources change and how (e.g. "1 create, 2 updates, 0 destroys; all match the intended edit"). When it fails, report the specific mismatch and stop — do not attempt further edits until the user has seen the discrepancy.