#!/usr/bin/env bash # scripts/verify_phase16.sh - v1.2 capstone e2e verification. # NOTE: terraform apply is blocked by IAM (P0 from Phase 15). This verify # runs the full platform flow UP TO the apply + the NFR + docs checks. set -euo pipefail ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" cd "$ROOT" fail() { echo "FAIL: $*" >&2; exit 1; } echo "=== Phase 16 — v1.2 capstone e2e verification ===" echo "(terraform apply blocked by IAM P0 — verifying everything up to the apply)" echo "" # 1. Consumer microservice content (from Phase 15) [ -f consumer-repos/acdl-consumer-microservice/app.py ] || fail "consumer app.py missing" [ -f consumer-repos/acdl-consumer-microservice/Dockerfile ] || fail "consumer Dockerfile missing" echo "Consumer microservice: OK" # 2. Full v1.2 platform flow: contract → IR → adapter → 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/p16_verify rm -rf "$WORK"; 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" "$WORK/ms_tf" 2>/dev/null || fail "adapter failed" MS_COUNT=$(python3 -c "import json; print(len(json.load(open('$WORK/ms_ir.json'))['resources']))") [ "$MS_COUNT" -ge 11 ] || fail "IR: $MS_COUNT resources (< 11)" echo "v1.2 contract -> IR -> adapter: OK ($MS_COUNT resources)" # 3. terraform validate + plan (the apply is the IAM-blocked step) cd "$WORK/ms_tf" terraform init -reconfigure -lock=false -input=false > /dev/null 2>&1 terraform validate 2>&1 | grep -q "Success" || fail "terraform validate failed" terraform plan -lock=false -input=false > /tmp/p16_plan.txt 2>&1 grep -q "Plan:" /tmp/p16_plan.txt || fail "terraform plan failed" PLAN=$(grep "Plan:" /tmp/p16_plan.txt | sed 's/\x1b\[[0-9;]*m//g') echo "terraform validate + plan: OK ($PLAN)" cd "$ROOT" # 4. NFR improvements (Phase 12) [ -f scripts/run_platform.sh ] || fail "run_platform.sh missing" [ ! -f scripts/run_spike_e2e.sh ] || fail "run_spike_e2e.sh should be deleted" [ ! -f scripts/run_spike_plan.sh ] || fail "run_spike_plan.sh should be deleted" grep -q "ecs:" terraform/bootstrap/spike_runner_policy.json || fail "IAM policy: no ECS" echo "NFR improvements (Phase 12): OK (run_platform.sh + IAM expanded)" # 5. P1-1 redaction (no live AWS key IDs in .ciagent/) if grep -rn "AKIAYOZHMKZ7RK26N66W\|AKIAYOZHMKZ772SINHFX" .ciagent/ 2>/dev/null; then fail "P1-1 redaction incomplete" fi echo "P1-1 redaction: OK (no live AWS key IDs)" # 6. README accuracy grep -q "v1.2 (active)" README.md || fail "README: no v1.2 active" grep -q "How the platform works" README.md || fail "README: no 'How the platform works' section" grep -q "run_platform.sh" README.md || fail "README: no run_platform.sh" echo "README accuracy: OK" # 7. v1.1 S3 regression (the whole 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" python3 adapters/terraform/adapter.py "$WORK/spike_ir.json" "$WORK/spike_tf" 2>/dev/null || fail "v1.1 regression: adapter" grep -q 'resource "aws_s3_bucket" "s3"' "$WORK/spike_tf/main.tf" || fail "v1.1 regression: no aws_s3_bucket" echo "v1.1 S3 regression: OK" # 8. L1 catalog (Phase 13) L1_COUNT=$(ls -d modules-ir/l1/*/ 2>/dev/null | wc -l) [ "$L1_COUNT" -eq 7 ] || fail "L1 catalog: $L1_COUNT (expected 7)" echo "L1 catalog: OK ($L1_COUNT L1s)" # 9. l2-microservice composition (Phase 14) [ -f modules-ir/l2/l2-microservice/composition.json ] || fail "l2-microservice composition missing" echo "l2-microservice: OK" # 10. .ciagent/ consistency grep -q '"milestone": "v1.2"' .ciagent/config.json || fail "config.json: milestone not v1.2" echo ".ciagent/ consistency: OK" # 11. Evidence events in the outbox (Phase 15 TERRAFORM_APPLY_BLOCKED + Phase 16 capstone) 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) >= 3, f'expected >=3 events, got {len(items)}' assert any('TERRAFORM_APPLY_BLOCKED' in str(i) for i in items), 'no TERRAFORM_APPLY_BLOCKED event' print(f'outbox: OK ({len(items)} event(s))') " || fail "outbox: evidence events missing" echo "Evidence events: OK" echo "" echo "=== Phase 16: VERIFIED (capstone, up to IAM-blocked apply) ===" echo "The v1.2 platform is verified end-to-end UP TO the terraform apply." echo "BLOCKER (P0-IAM): the operator must push spike_runner_policy.json to live AWS." echo "After unblock: terraform apply (13 to add) → live ECS service → HTTP 200." exit 0