Neatbo.

Terraform plan declaration review

Review ordered Terraform plan actions, deposed copies, drift and output changes with recursive supplied sensitive and unknown masks.

Browser-local processingInputTerraform plan JSON1.xOutputMasked change report JSON / CSVUp to 5 MiB per file · File limit: 1
  1. 1Add input
  2. 2Adjust settings
  3. 3Get your result

Tool input and files are processed in this browser without being uploaded.

Your input

Inputs are kept temporarily in this tab when switching tools. Refreshing or closing clears them; large results may need to be regenerated.

⌘ / Ctrl + Enter to run

or drag and drop it here

Files stay on this device. Your originals stay unchanged.

.json

Up to 5 MiB per file · File limit: 1

    0 characters · 0 bytes
    Options

    Complete the required options first. You can keep the defaults for the rest.

    Preparing the tool…

    Before you start

    Read a long exported plan before sharing its change list. Keep replacement order and snapshot flags explicit while withholding marked values and unrelated raw plan sections.

    How to use this tool

    1. Paste terraform show -json output or select its exported JSON file.
    2. Review action order,deposed identity,drift/output sections and supplied mask pointers.
    3. Download complete masked JSON/CSV; retain the original privately when further review needs omitted sections.

    Supported inputs and limits

    One UTF-8 file/paste5MiB;10,000 resource changes,10,000 drift changes,10,000 output changes,100,000 JSON values,depth64. Complete downloads20MiB; budgets apply together and failures return no partial report.

    format_version1.x with resource_changes is required; state-only JSON,HCL and binary plans unsupported. Support only no-op/read/create/update/delete/delete→create/create→delete. Nonempty deferred_changes and other actions reject. Address+deposed identifies copies; the same address with different deposed keys remains.

    before/after preserve absent/null/present separately. Sensitive true subtrees become explicit redacted-sensitive markers; after_unknown true becomes unknown, including declared fields absent from partial after. Mask arrays must match shape. RFC6901 true-mask pointers are complete; missing optional masks mean no declaration, not automatic detection.

    Retained declared numeric tokens,replace_paths,previous_address,index,action_reason and importing declarations remain exact. Raw variables/planned_values/prior_state/configuration and other unreviewed top-field values are not exported; unknown resource/change field names are listed without their values.

    Unmarked values, addresses and import IDs can remain private. Flags/actions describe only the snapshot, not apply success,safety or real impact. Preview200 rows/cell2000; above20,000 report characters, copy is a labelled preview; full JSON/CSV remain complete. No Terraform/provider/HCL command or request runs.

    Worked example

    Example input

    {"format_version":"1.2","terraform_version":"1.13.3","resource_changes":[{"address":"module.x.sample.a[0]","mode":"managed","type":"sample","name":"a","change":{"actions":["delete","create"],"before":{"id":"old","pass":"s1","nested":[1,null]},"after":{"id":null,"pass":"s2","nested":[2,null]},"after_unknown":{"id":true},"before_sensitive":{"pass":true},"after_sensitive":{"pass":true},"replace_paths":[["nested",0]]}},{"address":"sample.b","mode":"managed","type":"sample","name":"b","change":{"actions":["create","delete"],"before":null,"after":{"z":9007199254740993},"after_unknown":{},"before_sensitive":false,"after_sensitive":false}},{"address":"module.x.sample.a[0]","mode":"managed","type":"sample","name":"a","change":{"actions":["delete"],"before":{"id":"old","pass":"s1","nested":[1,null]},"after":null,"after_unknown":false,"before_sensitive":{"pass":true},"after_sensitive":false,"replace_paths":[["nested",0]]},"deposed":"deadbeef"}],"applyable":true,"complete":false,"errored":false,"variables":{"password":{"value":"NEVER_EXPORT_RAW_VARIABLE_SECRET"}},"planned_values":{"secret":"NEVER_EXPORT_PLANNED_SECRET"},"prior_state":{"secret":"NEVER_EXPORT_STATE_SECRET"},"configuration":{"secret":"NEVER_EXPORT_CONFIG_SECRET"},"extra":{"secret":"NEVER_EXPORT_UNKNOWN_SECRET"},"resource_drift":[{"address":"sample.drift","change":{"actions":["delete"],"before":{"id":"drift"},"after":null,"before_sensitive":false,"after_sensitive":false,"after_unknown":false}}],"output_changes":{"public":{"actions":["update"],"before":1,"after":2,"before_sensitive":false,"after_sensitive":false,"after_unknown":false},"private":{"actions":["create"],"before":null,"after":"NEVER_EXPORT_OUTPUT_SECRET","after_sensitive":true,"after_unknown":false}}}
    Example options
    {"secondary":"","params":{"spreadsheetSafe":true}}

    Example output

    {"format":"Terraform-plan1-local-change-declarations","summary":{"formatVersion":"1.2","resourceChanges":3,"driftChanges":1,"outputChanges":2,"create":2,"update":0,"delete":3,"read":0,"noOp":0,"replacements":2,"sensitiveSubtrees":4,"unknownSubtrees":1,"jsonNodes":116,"unreviewedTopFields":5},"flags":{"applyable":true,"complete":false,"errored":false},"sections":[{"name":"resource_changes","values":[{"section":"resource_changes","address":"module.x.sample.a[0]","deposed":null,"actions":["delete","create"],"replacement":true,"replacementOrder":"delete→create","beforePresence":"present","afterPresence":"present","beforeSensitiveStatus":"declared","afterSensitiveStatus":"declared","afterUnknownStatus":"declared","beforeSensitive":["/pass"],"afterSensitive":["/pass"],"afterUnknown":["/id"],"before":{"id":"old","pass":{"$neatboState":"redacted-sensitive"},"nested":[1,null]},"after":{"id":{"$neatboState":"unknown"},"pass":{"$neatboState":"redacted-sensitive"},"nested":[2,null]},"replacePaths":[["nested",0]],"declarations":{"mode":"managed","type":"sample","name":"a"},"unreviewedFields":[],"unreviewedChangeFields":[]},{"section":"resource_changes","address":"sample.b","deposed":null,"actions":["create","delete"],"replacement":true,"replacementOrder":"create→delete","beforePresence":"null","afterPresence":"present","beforeSensitiveStatus":"declared","afterSensitiveStatus":"declared","afterUnknownStatus":"declared","beforeSensitive":[],"afterSensitive":[],"afterUnknown":[],"before":null,"after":{"z":9007199254740993},"replacePaths":[],"declarations":{"mode":"managed","type":"sample","name":"b"},"unreviewedFields":[],"unreviewedChangeFields":[]},{"section":"resource_changes","address":"module.x.sample.a[0]","deposed":"deadbeef","actions":["delete"],"replacement":false,"replacementOrder":null,"beforePresence":"present","afterPresence":"null","beforeSensitiveStatus":"declared","afterSensitiveStatus":"declared","afterUnknownStatus":"declared","beforeSensitive":["/pass"],"afterSensitive":[],"afterUnknown":[],"before":{"id":"old","pass":{"$neatboState":"redacted-sensitive"},"nested":[1,null]},"after":null,"replacePaths":[["nested",0]],"declarations":{"mode":"managed","type":"sample","name":"a","deposed":"deadbeef"},"unreviewedFields":[],"unreviewedChangeFields":[]}]},{"name":"resource_drift","values":[{"section":"resource_drift","address":"sample.drift","deposed":null,"actions":["delete"],"replacement":false,"replacementOrder":null,"beforePresence":"present","afterPresence":"null","beforeSensitiveStatus":"declared","afterSensitiveStatus":"declared","afterUnknownStatus":"declared","beforeSensitive":[],"afterSensitive":[],"afterUnknown":[],"before":{"id":"drift"},"after":null,"replacePaths":[],"declarations":{},"unreviewedFields":[],"unreviewedChangeFields":[]}]},{"name":"output_changes","values":[{"section":"output_changes","address":"public","deposed":null,"actions":["update"],"replacement":false,"replacementOrder":null,"beforePresence":"present","afterPresence":"present","beforeSensitiveStatus":"declared","afterSensitiveStatus":"declared","afterUnknownStatus":"declared","beforeSensitive":[],"afterSensitive":[],"afterUnknown":[],"before":1,"after":2,"replacePaths":[],"declarations":{},"unreviewedFields":[],"unreviewedChangeFields":[]},{"section":"output_changes","address":"private","deposed":null,"actions":["create"],"replacement":false,"replacementOrder":null,"beforePresence":"null","afterPresence":"present","beforeSensitiveStatus":"no-declaration","afterSensitiveStatus":"declared","afterUnknownStatus":"declared","beforeSensitive":[],"afterSensitive":[""],"afterUnknown":[],"before":null,"after":{"$neatboState":"redacted-sensitive"},"replacePaths":[],"declarations":{},"unreviewedFields":[],"unreviewedChangeFields":[]}]}],"omittedTopFields":["variables","planned_values","prior_state","configuration","extra"],"scope":"Actions and flags are snapshot declarations, not apply success/safety/impact. before/after use explicit $neatboState markers for sensitive/unknown/absent subtrees; presence fields distinguish actual null. Only supplied sensitive masks redact; unmarked values/addresses/import IDs may be private. Omitted top fields are not reviewed and their values are never exported. Unknown resource/change fields are named as unreviewed, not exported. Numeric tokens in retained declared values remain exact."}

    When something does not work

    Re-export a complete supported1.x plan; correct duplicate address+deposed identities, masks, actions or JSON. Unsupported deferred/new action semantics require another workflow. Rerun a valid source after failure/cancellation.

    Frequently asked questions

    Why does a replacement count a delete?

    Both ordered create/delete legs remain; replacement order distinguishes delete→create from create→delete. Counts cover resource_changes; drift/output sections are separate.

    Is the result fully sanitized?

    No. Only supplied sensitive true masks redact. Unmarked values,addresses and import IDs may be private; omitted top fields are unreviewed, not certified safe.

    Does unknown mean null?

    No. Actual null has null presence; absent has absent presence; true unknown masks use an explicit unknown marker. Missing masks are no-declaration.

    Documentation & further reading

    Related tools