diff --git a/scripts/verify_phase09.sh b/scripts/verify_phase09.sh new file mode 100755 index 0000000..27b61bb --- /dev/null +++ b/scripts/verify_phase09.sh @@ -0,0 +1,77 @@ +#!/usr/bin/env bash +# scripts/verify_phase09.sh - Phase 09 v1-spike-ir-and-l1-and-adapter gate. +set -u +ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +cd "$ROOT" +fail() { echo "FAIL: $*" >&2; exit 1; } +ok() { echo "ok: $*"; } + +# --- Check 1: L1 module files exist --- +for f in modules-ir/l1/l1-s3/interface.json \ + modules-ir/l1/l1-s3/spike_instance.json \ + modules-ir/l1/l1-s3/README.md \ + modules-ir/registry.json \ + adapters/terraform/adapter.py \ + terraform/spike/main.tf \ + terraform/spike/terraform.tf \ + terraform/spike/providers.tf \ + scripts/run_spike_plan.sh; do + [ -f "$f" ] || fail "missing $f" +done +ok "all 9 deliverable files exist" + +# --- Check 2: spike_instance.json validates against ir.schema.json --- +( cd /tmp && python3 -c " +import json, jsonschema +inst = json.load(open('$ROOT/modules-ir/l1/l1-s3/spike_instance.json')) +schema = json.load(open('$ROOT/schemas/ir.schema.json')) +jsonschema.validate(inst, schema) +" ) || fail "spike_instance.json does not validate against ir.schema.json" +ok "spike_instance.json validates against ir.schema.json" + +# --- Check 3: registry has the l1-s3@1.0.0 entry --- +python3 -c " +import json +r = json.load(open('modules-ir/registry.json')) +assert 'l1-s3' in r and '1.0.0' in r['l1-s3'], 'l1-s3@1.0.0 missing' +print('l1-s3@1.0.0 present') +" || fail "registry missing l1-s3@1.0.0" +ok "registry has l1-s3@1.0.0" + +# --- Check 4: adapter py_compiles + generates terraform containing aws_s3_bucket --- +python3 -m py_compile adapters/terraform/adapter.py || fail "adapter.py py_compile failed" +TMP=$(mktemp -d) +python3 adapters/terraform/adapter.py modules-ir/l1/l1-s3/spike_instance.json "$TMP" 2>/dev/null +grep -q 'resource "aws_s3_bucket"' "$TMP/main.tf" || fail "adapter did not emit aws_s3_bucket resource" +grep -q 'output "bucket_arn"' "$TMP/main.tf" || fail "adapter did not emit bucket_arn output" +ok "adapter.py py_compiles + emits aws_s3_bucket + bucket_arn output" + +# --- Check 5: generated terraform/spike/*.tf match a fresh adapter run (D-P09-4 reproducibility) --- +diff "$TMP/main.tf" terraform/spike/main.tf || fail "terraform/spike/main.tf is stale (differs from a fresh adapter run)" +diff "$TMP/terraform.tf" terraform/spike/terraform.tf || fail "terraform/spike/terraform.tf is stale" +diff "$TMP/providers.tf" terraform/spike/providers.tf || fail "terraform/spike/providers.tf is stale" +ok "terraform/spike/*.tf match a fresh adapter run (reproducible)" +rm -rf "$TMP" + +# --- Check 6: no long-lived credential (AKIA) in committed files --- +# Skip .terraform/ (provider binaries contain AKIA bytes; gitignored anyway). +if grep -rn --exclude-dir=.terraform "AKIA" terraform/spike/ adapters/ modules-ir/ 2>/dev/null; then + fail "AKIA key id found in committed files (terraform/spike/ adapters/ modules-ir/)" +fi +ok "no AKIA in committed files (excluding .terraform/ provider binaries)" + +# --- Check 7: .env.secrets + terraform working artifacts are gitignored --- +git check-ignore -q .env.secrets || fail ".env.secrets not gitignored" +git check-ignore -q terraform/spike/.terraform/ || fail "terraform/spike/.terraform/ not gitignored" +git check-ignore -q terraform/spike/tfplan || fail "terraform/spike/tfplan not gitignored" +ok "secrets + TF working artifacts gitignored" + +# --- Check 8: real terraform plan against AWS succeeds (uses rotated spike key) --- +bash scripts/run_spike_plan.sh > /tmp/verify_phase09_plan.log 2>&1 || { + cat /tmp/verify_phase09_plan.log >&2 + fail "scripts/run_spike_plan.sh failed (see /tmp/verify_phase09_plan.log)" +} +grep -q "spike plan OK" /tmp/verify_phase09_plan.log || fail "run_spike_plan.sh did not print 'spike plan OK'" +ok "real terraform plan against AWS succeeded (rotated spike key, plan-only, -lock=false)" + +echo "VERIFIED — Phase 09: IR + l1-s3 + Terraform adapter; real terraform plan succeeds" \ No newline at end of file