#!/usr/bin/env bash # End-to-end smoke test for the license server. # # Builds the API image, brings up Postgres + API, runs the Alembic # migration, mints a license through /internal/mint, verifies the # resulting blob's Ed25519 signature against the dev pubkey, and # confirms the row landed in the DB. Tears everything down at exit. # # Run from the server/ directory: ./scripts/smoke.sh set -euo pipefail cd "$(dirname "$0")/.." PROJECT=dt-license-smoke COMPOSE=(docker compose -p "$PROJECT" -f compose.test.yml) cleanup() { echo "--- Tearing down ---" "${COMPOSE[@]}" down -v --remove-orphans >/dev/null 2>&1 || true } trap cleanup EXIT echo "--- Building image ---" "${COMPOSE[@]}" build echo "--- Starting stack ---" "${COMPOSE[@]}" up -d echo "--- Waiting for API health (max 60s) ---" for i in $(seq 1 60); do if curl -sf http://127.0.0.1:18090/health 2>/dev/null | grep -q '"status":"ok"'; then echo "API up after ${i}s" break fi sleep 1 done echo "--- Running migrations ---" "${COMPOSE[@]}" exec -T api alembic upgrade head echo "--- Re-checking health post-migration ---" curl -sf http://127.0.0.1:18090/health | tee /dev/stderr | grep -q '"db":"ok"' echo "--- POST /internal/mint ---" RESP=$(curl -s -w "\nHTTP=%{http_code}" -X POST http://127.0.0.1:18090/internal/mint \ -H "Authorization: Bearer test-admin-token" \ -H "Content-Type: application/json" \ -d '{"name":"Smoke Test","email":"smoke@example.com","tier":"core","source":"manual"}') echo "$RESP" HTTP_CODE=$(echo "$RESP" | tail -n1 | sed 's/HTTP=//') RESP=$(echo "$RESP" | sed '$d') if [ "$HTTP_CODE" != "201" ]; then echo "MINT FAILED (HTTP $HTTP_CODE)" "${COMPOSE[@]}" logs --tail 50 api exit 1 fi echo "$RESP" | python3 -m json.tool | head -8 BLOB=$(echo "$RESP" | python3 -c 'import json,sys; print(json.load(sys.stdin)["blob"])') echo "--- Verifying blob signature against host dev pubkey ---" python3 - <