#!/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"