Rule Engine
Deterministic optimization rules, evaluators, and finding fingerprints.
Typed evaluators run against canonical snapshots. Rules come from a versioned YAML manifest. No embedded scripts or expression language.
Rule manifest
Default: internal/application/rules/default_rules.yaml
Each rule specifies:
- ID, version, category, severity
- Applicability and thresholds
- Required signals (inventory, costs, metrics, pricing)
- Remediation text
- Evaluator name
Override path: rules_manifest_path in config, or COA_RULES_MANIFEST.
Built-in evaluators
| Evaluator | Finds |
|---|---|
stopped_instance_storage_cost |
Stopped instances still billing storage |
unattached_block_volume |
Detached EBS volumes |
stale_volume_snapshot |
Snapshots past retention threshold |
missing_cost_allocation_tags |
Spend without required tags |
ec2_downsize_candidate |
Oversized EC2 from utilization |
ec2_idle_instance |
Sustained low utilization |
ebs_volume_type_optimize |
gp2 → gp3 migration |
rds_downsize_candidate |
Oversized RDS |
nat_gateway_low_utilization |
NAT with minimal traffic |
Outcomes (per rule, per snapshot)
| Outcome | Meaning |
|---|---|
passed |
No finding |
failed |
Finding written |
suppressed |
Matched; filtered by suppressions.yaml |
not_evaluated |
Required signal missing |
error |
Unknown evaluator name |
Panics inside an evaluator mark the rule not_evaluated. They do not crash the process.
Finding fields
- Severity, category, resource IDs
- Evidence (stored on the analysis run)
- Assumptions, confidence
- Recommendation (from rule remediation)
- SHA-256 fingerprint:
rule_id+rule_version+ sorted resource IDs
Suppressions
config/suppressions.yaml:
suppressions:
- fingerprint: "<finding fingerprint>"
reason: "Accepted until decommission"
expires_at: "2026-12-31T23:59:59Z"
- rule_id: compute.stopped_instance_storage_cost
resource_id: res-i-stopped
reason: "Decommission scheduled Q3"
Expired entries are skipped.
CLI output
cloudopt analyze --json
Stdout JSON includes the full analysis object plus rule counts. Text mode prints passed / failed / suppressed / not_evaluated / error totals.