#!/usr/bin/env bash # scripts/verify_phase15.sh - verify Phase 15 (consumer-repo-and-terraform-apply). # NOTE: terraform apply is BLOCKED by IAM (live spike_runner policy not updated; # root key deactivated per D-034). This verify confirms everything UP TO the apply. set -euo pipefail ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" cd "$ROOT" fail() { echo "FAIL: $*" >&2; exit 1; } echo "=== Phase 15 verification (partial — terraform apply blocked by IAM) ===" # 1. Consumer microservice content [ -f consumer-repos/acdl-consumer-microservice/app.py ] || fail "consumer app.py missing" [ -f consumer-repos/acdl-consumer-microservice/Dockerfile ] || fail "consumer Dockerfile missing" [ -f consumer-repos/acdl-consumer-microservice/README.md ] || fail "consumer README.md missing" grep -q "acdl-microservice" consumer-repos/acdl-consumer-microservice/app.py || fail "app.py: no service name" grep -q "EXPOSE 8080" consumer-repos/acdl-consumer-microservice/Dockerfile || fail "Dockerfile: no EXPOSE 8080" echo "Consumer microservice content: OK (app.py + Dockerfile + README.md)" # 2. Docker image built docker images acdl-microservice:latest --format '{{.Repository}}:{{.Tag}}' | grep -q "acdl-microservice:latest" || fail "Docker image acdl-microservice:latest not built" echo "Docker image: OK (acdl-microservice:latest built)" # 3. ECR push script [ -f scripts/push_consumer_image.py ] || fail "scripts/push_consumer_image.py missing" python3 -m py_compile scripts/push_consumer_image.py || fail "push_consumer_image.py: py_compile failed" echo "ECR push script: OK (present + compiles)" # 4. Contract + resolver + adapter pipeline (up to terraform plan) set -a; . .env.secrets; set +a export AWS_ACCESS_KEY_ID=$ACDL_AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY=$ACDL_AWS_SECRET_ACCESS_KEY AWS_DEFAULT_REGION=${AWS_DEFAULT_REGION:-us-east-1} WORK=/tmp/p15_verify rm -rf "$WORK" terraform/microservice; mkdir -p "$WORK" python3 acdl_platform/contract_resolver.py contracts/microservice.yaml "$WORK/ms_ir.json" 2>/dev/null || fail "resolver failed" python3 adapters/terraform/adapter.py "$WORK/ms_ir.json" terraform/microservice 2>/dev/null || fail "adapter failed" python3 -c "import json; ir=json.load(open('$WORK/ms_ir.json')); assert len(ir['resources'])>=11, f'expected >=11 resources, got {len(ir[\"resources\"])}'" || fail "IR: wrong resource count" echo "Contract -> IR -> adapter: OK (11 resources)" # 5. terraform init + validate + plan (the plan succeeds; apply is the IAM-blocked step) cd terraform/microservice terraform init -reconfigure -lock=false -input=false 2>&1 | tail -1 terraform validate 2>&1 | grep -q "Success" || fail "terraform validate failed" terraform plan -lock=false -input=false -out=tfplan > /tmp/p15_plan.txt 2>&1 grep -q "Plan:" /tmp/p15_plan.txt || { echo "--- plan output ---"; cat /tmp/p15_plan.txt | tail -20; fail "terraform plan failed"; } PLAN_SUMMARY=$(grep "Plan:" /tmp/p15_plan.txt | head -1 | sed 's/\x1b\[[0-9;]*m//g') echo "terraform validate + plan: OK ($PLAN_SUMMARY)" cd "$ROOT" # 6. Evidence event written to outbox (TERRAFORM_APPLY_BLOCKED) python3 -c " import boto3, os s = boto3.Session(aws_access_key_id=os.environ['AWS_ACCESS_KEY_ID'], aws_secret_access_key=os.environ['AWS_SECRET_ACCESS_KEY'], region_name=os.environ['AWS_DEFAULT_REGION']) d = s.client('dynamodb') r = d.query(TableName='acdl-outbox', KeyConditionExpression='contractId = :cid', ExpressionAttributeValues={':cid': {'S': '22222222-2222-2222-2222-222222222222'}}) items = r.get('Items', []) assert len(items) >= 1, 'no events in outbox for contract 22222222...' assert any('TERRAFORM_APPLY_BLOCKED' in str(item) for item in items), 'no TERRAFORM_APPLY_BLOCKED event in outbox' print(f'outbox: OK ({len(items)} event(s) for contract 22222222...)') " || fail "outbox: no TERRAFORM_APPLY_BLOCKED event" echo "Evidence event: OK (TERRAFORM_APPLY_BLOCKED in DynamoDB outbox)" # 7. Adapter fix regression: v1.1 spike still works python3 acdl_platform/contract_resolver.py contracts/spike.yaml "$WORK/spike_ir.json" 2>/dev/null || fail "v1.1 regression: resolver failed" python3 adapters/terraform/adapter.py "$WORK/spike_ir.json" "$WORK/spike_tf" 2>/dev/null || fail "v1.1 regression: adapter failed" grep -q 'resource "aws_s3_bucket" "s3"' "$WORK/spike_tf/main.tf" || fail "v1.1 regression: no aws_s3_bucket" echo "v1.1 regression: OK (spike.yaml -> l1-s3 -> aws_s3_bucket)" # 8. .ciagent/ consistency grep -q '"milestone": "v1.2"' .ciagent/config.json || fail "config.json: milestone not v1.2" echo ".ciagent/ consistency: OK" echo "" echo "=== Phase 15: PARTIALLY VERIFIED ===" echo "Consumer microservice + Docker image + adapter fixes: DONE." echo "terraform plan succeeds (13 to add)." echo "BLOCKER: terraform apply fails with AccessDenied — live IAM policy not updated." echo "UNBLOCK: operator runs create_iam_user.py with root/admin creds to push the expanded policy." echo "Then re-run terraform apply; Phase 16 will complete the e2e." exit 0