compliance.tf

Read the module diff before changing your source

   force_destroy       = var.force_destroy
   object_lock_enabled = var.object_lock_enabled
   tags                = var.tags
+
+  lifecycle {
+    prevent_destroy = true
+    ignore_changes = [tags, tags_all]
+  }
 }

This is the code change returned by the public preview for two rules on terraform-aws-modules/s3-bucket 5.15.4. You can read it without an account, without configuring AWS, and before changing a module source in your stack.

The capture reports 2 rules applied, 3 resources affected and 1 file changed. Those numbers tell you to look at the diff. They do not tell you whether every bucket gets destruction protection, or whether every submodule was inspected.

Ask for the exact module version and rules

curl -sS "https://registry.compliance.tf/api/v1/modules/terraform-aws-modules/s3-bucket/aws/5.15.4/rules/preview?rules=lifecycle_prevent_destroy_data,lifecycle_ignore_tags" \
  | jq '{summary, outcomes, files}'

lifecycle_prevent_destroy_data requests protection for supported data resources. lifecycle_ignore_tags requests lifecycle handling for tag changes. Keeping the version pinned makes the target of this request explicit.

The response contains summary, per-rule outcomes, and unified diffs in files. To explore the recorded response without a network call:

git clone https://github.com/antonbabenko/compliance.tf-demo
cd compliance.tf-demo/scenarios/02-free-preview
jq '{summary, outcomes, files}' expected/preview.json

That response was captured on 2026-10-07.

The directory bucket gets a different block

The ordinary aws_s3_bucket gets the block at the top of this page. The aws_s3_directory_bucket gets:

   tags = var.tags
+
+  lifecycle {
+    ignore_changes = [tags]
+  }
 }

There is no prevent_destroy in that added block. An applied-rule count would not reveal that distinction. Review the actual resource types and settings before translating "rules applied" into a statement about protection.

The settings also represent different choices. prevent_destroy rejects Terraform plans that destroy or replace a protected resource while its configuration is present. It does not survive removal of that configuration, and it does not prevent deletion through the AWS console.

ignore_changes assigns update ownership elsewhere. Terraform can configure the listed attributes at creation, but will not reconcile their later changes. That can be appropriate when another system manages tags. It also means that unwanted tag changes will not be repaired by Terraform. The Terraform lifecycle reference describes both behaviors; this demo captures the inserted code, not a deployed test of those behaviors.

Five omitted submodules matter more than a success flag

Inspect summary.scope_coverage and summary.submodules_omitted:

jq '.summary | {scope_coverage, submodules_omitted}' expected/preview.json

For this response, scope is module_root_only. The omitted paths are modules/account-public-access, modules/notification, modules/object, modules/table-bucket and modules/vectors. Success means the request succeeded within that stated scope, not that the entire package was rewritten.

Refused requests tell you where the public route stops

The same capture set includes five deliberate refusals:

RequestHTTPCode
&framework=soc2400PREVIEW_PARAM_NOT_ACCEPTED
&disable=s3_bucket_logging_enabled400PREVIEW_PARAM_NOT_ACCEPTED
Version latest instead of 5.15.4400PREVIEW_VERSION_NOT_PINNED
&ruleset=production403PREVIEW_TIER_REQUIRED
No rules= parameter400RULE_SYNTAX

Run make refusals from the scenario directory to read each recorded error and its remediation field. The public route accepts operational-rule requests for allowlisted, pinned modules. These errors are not evidence that the same parameters are unavailable on authenticated routes.

An error response and an empty successful diff are different results. For an example of the latter, see the not_configured rule in the lifecycle walkthrough.

Previewing and downloading are separate steps

make demo replays the recorded summary and diff. make live makes a fresh preview call. Neither target installs the rewritten module or runs a plan. Downloading from a framework host needs registry authentication.

Live preview calls are rate limited; the scripts space requests 11 seconds apart and retry HTTP 429 responses. Replays make no network calls. The Rules Playground offers another way to inspect the diff.

If you are evaluating a rule, read its diff, outcome and scope together. Then review an authenticated download and a plan for your own inputs before treating that code change as a tested infrastructure change.

On this page

Ask AI about this

Help improve this page