#!/usr/bin/env bash set -euo pipefail API_ORIGIN="${API_ORIGIN:-}" SMOKE_BEARER_TOKEN="${SMOKE_BEARER_TOKEN:-}" [[ "$API_ORIGIN" == https://* ]] || { printf 'SMOKE FAIL: API_ORIGIN must be an https origin\n' >&2 exit 1 } [[ "$API_ORIGIN" != *localhost* && "$API_ORIGIN" != *127.0.0.1* && "$API_ORIGIN" != *.invalid* ]] || { printf 'SMOKE FAIL: API_ORIGIN must use a production domain\n' >&2 exit 1 } [[ "$API_ORIGIN" != *.example* && "$API_ORIGIN" != *.test* ]] || { printf 'SMOKE FAIL: API_ORIGIN must not use a reserved example/test domain\n' >&2 exit 1 } API_ORIGIN="${API_ORIGIN%/}" json_assert_status_up() { python3 -c 'import json,sys; d=json.load(sys.stdin); assert d.get("status") == "UP", d; print("UP")' } printf '1/5 liveness: ' curl --fail --silent --show-error "$API_ORIGIN/actuator/health/liveness" | json_assert_status_up printf '2/5 readiness: ' curl --fail --silent --show-error "$API_ORIGIN/actuator/health/readiness" | json_assert_status_up STORES="$(curl --fail --silent --show-error "$API_ORIGIN/api/store/list")" STORE_ID="$(printf '%s' "$STORES" | python3 -c 'import json,sys; d=json.load(sys.stdin); assert d.get("code")==200,d; rows=d.get("data") or []; assert rows,"no pilot store"; print(rows[0]["id"])')" printf '3/5 public store list: PASS\n' SERVICES="$(curl --fail --silent --show-error "$API_ORIGIN/api/service-type/list?storeId=$STORE_ID")" SERVICE_NAME="$(printf '%s' "$SERVICES" | python3 -c 'import json,sys; d=json.load(sys.stdin); assert d.get("code")==200,d; rows=d.get("data") or []; assert rows,"no service type"; assert all(int(x.get("durationMinutes") or 0)>=30 for x in rows),rows; print(rows[0]["name"])')" printf '4/5 service duration contract: PASS\n' if date -v+1d +%F >/dev/null 2>&1; then TOMORROW="$(date -v+1d +%F)" else TOMORROW="$(date -d tomorrow +%F)" fi curl --fail --silent --show-error --get "$API_ORIGIN/api/appointment/available-slots" \ --data-urlencode "storeId=$STORE_ID" \ --data-urlencode "date=$TOMORROW" \ --data-urlencode "serviceType=$SERVICE_NAME" \ | python3 -c 'import json,sys; d=json.load(sys.stdin); assert d.get("code")==200,d; data=d["data"]; assert int(data["durationMinutes"])>=30; assert int(data["bookingCapacity"])>=1; assert isinstance(data.get("slots"),list); print("5/5 capacity slot contract: PASS")' if [[ -n "$SMOKE_BEARER_TOKEN" ]]; then AUTH_HEADER="Authorization: Bearer $SMOKE_BEARER_TOKEN" curl --fail --silent --show-error -H "$AUTH_HEADER" "$API_ORIGIN/api/admin/store" \ | python3 -c 'import json,sys; d=json.load(sys.stdin); assert d.get("code")==200,d; assert int(d["data"]["bookingCapacity"])>=1; print("protected admin store: PASS")' curl --fail --silent --show-error -H "$AUTH_HEADER" "$API_ORIGIN/api/appointment/list?page=1&pageSize=5" \ | python3 -c 'import json,sys; d=json.load(sys.stdin); assert d.get("code")==200,d; print("protected appointment list: PASS")' else printf 'Protected smoke SKIPPED: SMOKE_BEARER_TOKEN not provided\n' fi printf 'Production read-only smoke PASS\n'