Enterprise Features: - Hosted mode with remote sync for team pattern aggregation - Community sharing with privacy-preserving anonymization - LLM-based semantic claim extraction with Gemini integration - Pattern learning with promotion to declarative extractors - High-entropy secrets extractor with configurable thresholds - Auth bypass and insecure cookies extractors Module Refactoring: - Split oversized files to comply with 500-line limit - Config split: types/core.rs, types/extractors.rs, types/hosted.rs, etc. - Handlers split: scan.rs, policy.rs, report.rs modules - Extractors split: declarative/, high_entropy_secrets/, insecure_cookies/ - Learning split: store modules with metrics and persistence SDK & Ontology: - stemedb-ontology SDK with fluent builders and StemeDB client - Pharma domain extractors for FDA Orange Book data - Consumer health UAT test infrastructure Code Quality: - Fixed clippy warnings (needless_borrows_for_generic_args) - Added KVStore trait imports where needed - Fixed utoipa path re-exports for OpenAPI docs Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
213 lines
7.2 KiB
Bash
Executable File
213 lines
7.2 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
#
|
|
# UAT Pre-Flight Check: Validate API Readiness
|
|
#
|
|
# This script checks that all required API endpoints exist and return expected
|
|
# responses before running UAT scenarios.
|
|
#
|
|
# Usage:
|
|
# ./validate_api_readiness.sh [API_URL]
|
|
#
|
|
# Example:
|
|
# ./validate_api_readiness.sh http://localhost:18180
|
|
|
|
set -euo pipefail
|
|
|
|
# Validate required dependencies
|
|
for cmd in curl grep; do
|
|
if ! command -v "$cmd" &> /dev/null; then
|
|
echo "ERROR: Required command '$cmd' is not installed."
|
|
exit 1
|
|
fi
|
|
done
|
|
|
|
API_URL="${1:-http://localhost:18180}"
|
|
TIMEOUT=5
|
|
|
|
echo "╔══════════════════════════════════════════════════════════════╗"
|
|
echo "║ UAT Pre-Flight Check: API Readiness Validation ║"
|
|
echo "╚══════════════════════════════════════════════════════════════╝"
|
|
echo
|
|
echo "Target API: $API_URL"
|
|
echo "Timeout: ${TIMEOUT}s per check"
|
|
echo
|
|
|
|
# Colors for output
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
NC='\033[0m' # No Color
|
|
|
|
PASSED=0
|
|
FAILED=0
|
|
WARNINGS=0
|
|
|
|
# Helper: Check if endpoint exists and returns expected status
|
|
check_endpoint() {
|
|
local method="$1"
|
|
local path="$2"
|
|
local expected_status="$3"
|
|
local description="$4"
|
|
local data="${5:-}"
|
|
|
|
echo -n " [$method $path] $description... "
|
|
|
|
if [ "$method" = "GET" ]; then
|
|
response=$(curl -s -w "\n%{http_code}" --max-time "$TIMEOUT" "$API_URL$path" 2>&1 || echo "000")
|
|
else
|
|
response=$(curl -s -w "\n%{http_code}" -X "$method" --max-time "$TIMEOUT" \
|
|
-H "Content-Type: application/json" \
|
|
-d "$data" \
|
|
"$API_URL$path" 2>&1 || echo "000")
|
|
fi
|
|
|
|
status=$(echo "$response" | tail -n1)
|
|
|
|
if [ "$status" = "$expected_status" ]; then
|
|
echo -e "${GREEN}✓${NC} ($status)"
|
|
((PASSED++))
|
|
return 0
|
|
elif [ "$status" = "000" ]; then
|
|
echo -e "${RED}✗ Connection failed${NC}"
|
|
((FAILED++))
|
|
return 1
|
|
else
|
|
echo -e "${YELLOW}⚠ Unexpected status: $status (expected $expected_status)${NC}"
|
|
((WARNINGS++))
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
# 1. Health Check
|
|
echo "1. Basic Connectivity"
|
|
check_endpoint "GET" "/v1/health" "200" "Health check endpoint"
|
|
echo
|
|
|
|
# 2. Core API Endpoints
|
|
echo "2. Core API Endpoints (UAT Dependencies)"
|
|
check_endpoint "GET" "/v1/skeptic?subject=test&predicate=test" "404" "Skeptic query endpoint (expects 404 for empty DB)"
|
|
check_endpoint "GET" "/v1/layered?subject=test&predicate=test" "404" "Layered query endpoint (expects 404 for empty DB)"
|
|
check_endpoint "GET" "/v1/query?subject=test&predicate=test" "404" "Generic query endpoint (expects 404 for empty DB)"
|
|
echo
|
|
|
|
# 3. Assertion Creation (with invalid data to check endpoint exists)
|
|
echo "3. Assertion Creation Endpoint"
|
|
invalid_assertion='{"subject":"test","predicate":"test","object":{"type":"Text","value":"test"},"confidence":0.5,"source_class":"Clinical","source_hash":"0000000000000000000000000000000000000000000000000000000000000000","signatures":[]}'
|
|
|
|
# This should fail validation (empty signatures), but endpoint should exist
|
|
echo -n " [POST /v1/assert] Assertion endpoint... "
|
|
response=$(curl -s -w "\n%{http_code}" --max-time "$TIMEOUT" \
|
|
-X POST "$API_URL/v1/assert" \
|
|
-H "Content-Type: application/json" \
|
|
-d "$invalid_assertion" 2>&1 || echo "000")
|
|
status=$(echo "$response" | tail -n1)
|
|
|
|
if [ "$status" = "400" ] || [ "$status" = "201" ]; then
|
|
echo -e "${GREEN}✓${NC} (endpoint exists, got $status)"
|
|
((PASSED++))
|
|
elif [ "$status" = "000" ]; then
|
|
echo -e "${RED}✗ Connection failed${NC}"
|
|
((FAILED++))
|
|
else
|
|
echo -e "${YELLOW}⚠ Unexpected status: $status${NC}"
|
|
((WARNINGS++))
|
|
fi
|
|
echo
|
|
|
|
# 4. OpenAPI Documentation
|
|
echo "4. OpenAPI Documentation"
|
|
check_endpoint "GET" "/api-docs/openapi.json" "200" "OpenAPI spec"
|
|
check_endpoint "GET" "/swagger-ui/index.html" "200" "Swagger UI"
|
|
echo
|
|
|
|
# 5. Required Data Structures (check OpenAPI schema)
|
|
echo "5. Data Structure Validation"
|
|
echo -n " Fetching OpenAPI spec... "
|
|
openapi=$(curl -s --max-time "$TIMEOUT" "$API_URL/api-docs/openapi.json" 2>/dev/null || echo "{}")
|
|
if [ "$openapi" != "{}" ]; then
|
|
echo -e "${GREEN}✓${NC}"
|
|
((PASSED++))
|
|
|
|
# Check for required schemas
|
|
echo -n " Checking CreateAssertionRequest schema... "
|
|
if echo "$openapi" | grep -q "CreateAssertionRequest"; then
|
|
echo -e "${GREEN}✓${NC}"
|
|
((PASSED++))
|
|
else
|
|
echo -e "${YELLOW}⚠ Missing${NC}"
|
|
((WARNINGS++))
|
|
fi
|
|
|
|
echo -n " Checking SkepticResponse schema... "
|
|
if echo "$openapi" | grep -q "SkepticResponse"; then
|
|
echo -e "${GREEN}✓${NC}"
|
|
((PASSED++))
|
|
else
|
|
echo -e "${YELLOW}⚠ Missing${NC}"
|
|
((WARNINGS++))
|
|
fi
|
|
|
|
echo -n " Checking LayeredQueryResponse schema... "
|
|
if echo "$openapi" | grep -q "LayeredQueryResponse"; then
|
|
echo -e "${GREEN}✓${NC}"
|
|
((PASSED++))
|
|
else
|
|
echo -e "${YELLOW}⚠ Missing${NC}"
|
|
((WARNINGS++))
|
|
fi
|
|
else
|
|
echo -e "${RED}✗ Failed to fetch${NC}"
|
|
((FAILED++))
|
|
fi
|
|
echo
|
|
|
|
# 6. Source Class Support
|
|
echo "6. Source Class Validation"
|
|
echo " Expected source classes: Regulatory, Clinical, Expert, Crowd, Anecdotal"
|
|
echo -n " Checking via OpenAPI... "
|
|
if echo "$openapi" | grep -q "Regulatory"; then
|
|
echo -e "${GREEN}✓${NC}"
|
|
((PASSED++))
|
|
else
|
|
echo -e "${YELLOW}⚠ Source classes not documented${NC}"
|
|
((WARNINGS++))
|
|
fi
|
|
echo
|
|
|
|
# Summary
|
|
echo "╔══════════════════════════════════════════════════════════════╗"
|
|
echo "║ Summary ║"
|
|
echo "╚══════════════════════════════════════════════════════════════╝"
|
|
echo
|
|
echo -e " ${GREEN}Passed:${NC} $PASSED"
|
|
echo -e " ${YELLOW}Warnings:${NC} $WARNINGS"
|
|
echo -e " ${RED}Failed:${NC} $FAILED"
|
|
echo
|
|
|
|
if [ "$FAILED" -gt 0 ]; then
|
|
echo -e "${RED}❌ API is NOT ready for UAT execution${NC}"
|
|
echo
|
|
echo "Common issues:"
|
|
echo " - API server not running (check: cargo run -p stemedb-api)"
|
|
echo " - Wrong API URL (current: $API_URL)"
|
|
echo " - Firewall blocking connections"
|
|
echo " - API still starting up (wait a few seconds and retry)"
|
|
exit 1
|
|
elif [ "$WARNINGS" -gt 0 ]; then
|
|
echo -e "${YELLOW}⚠️ API is mostly ready, but some checks failed${NC}"
|
|
echo
|
|
echo "You can proceed with UAT, but some scenarios may fail."
|
|
echo "Review the warnings above."
|
|
exit 0
|
|
else
|
|
echo -e "${GREEN}✅ API is READY for UAT execution${NC}"
|
|
echo
|
|
echo "Next steps:"
|
|
echo " 1. Run all UAT scenarios:"
|
|
echo " STEMEDB_API_URL=$API_URL cargo test --test consumer_health_uat run_all_uat_scenarios -- --ignored --nocapture"
|
|
echo
|
|
echo " 2. Run individual scenarios:"
|
|
echo " STEMEDB_API_URL=$API_URL cargo test --test consumer_health_uat uat_glp1_muscle_loss_contradiction -- --ignored --nocapture"
|
|
exit 0
|
|
fi
|