← Files Platform Engineering CopilotARCHIVED FILE

scripts/plan_risk.py

2.02 KB · Nov 3, 2026 · 00:12 UTC

↓ Download file

See the change to this file →

"""Summarize Terraform/Tofu plan JSON without printing any resource values or secrets.

Run against an authorized, locally saved `terraform show -json <plan>` document.
This report does NOT replace review of the full plan and dependent services.
"""
import json
from collections import Counter

def summarize(plan: dict) -> dict:
    if not isinstance(plan, dict):
        raise ValueError('plan must be a JSON object')
    changes=plan.get('resource_changes', [])
    if not isinstance(changes, list):
        raise ValueError('resource_changes must be a list')
    counts=Counter(); uncertainty=0
    for entry in changes:
        if not isinstance(entry,dict) or not isinstance(entry.get('change'),dict):
            raise ValueError('invalid resource change')
        change=entry['change'];actions=change.get('actions')
        if not isinstance(actions,list) or not actions or not all(isinstance(x,str) for x in actions):
            raise ValueError('invalid actions')
        if 'delete' in actions and 'create' in actions: category='replace'
        elif 'delete' in actions: category='delete'
        elif 'create' in actions: category='create'
        elif 'update' in actions: category='update'
        elif actions==['no-op']: category='no-op'
        elif actions==['read']: category='read'
        else: category='unknown'
        counts[category]+=1
        if change.get('after_unknown'): uncertainty+=1
    # High risk is a review flag, not a claim of real-world safety or harm.
    needs_review=counts['delete']>0 or counts['replace']>0 or counts['unknown']>0 or uncertainty>0
    return {'total_changes':len(changes),'actions':dict(sorted(counts.items())), 'entries_with_unknown_after':uncertainty,'requires_manual_risk_review':bool(needs_review), 'evidence_level':'local plan structure only'}

if __name__=='__main__':
    import sys
    if len(sys.argv)!=2: raise SystemExit('usage: python scripts/plan_risk.py <sanitized-plan.json>')
    with open(sys.argv[1],encoding='utf-8') as f:plan=json.load(f)
    print(json.dumps(summarize(plan),indent=2))

SHA-256: fc7db14f98285e7f8dd588f29f8235816d179ea63c3651659e5fa6bf456b2cd6