#!/usr/bin/env bash # # StemeDB Validation Script # # Validates that StemeDB works end-to-end: # 1. Builds the API server # 2. Starts the server in the background # 3. Waits for health check # 4. Creates an assertion via curl # 5. Queries it back # 6. Shuts down the server # # Usage: # ./scripts/validate.sh # Run validation # ./scripts/validate.sh --no-build # Skip cargo build (faster) # # Exit codes: # 0 - All checks passed # 1 - Validation failed # set -euo pipefail # Configuration readonly API_HOST="${STEMEDB_BIND_ADDR:-127.0.0.1:18180}" readonly API_URL="http://${API_HOST}" readonly SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" readonly PROJECT_DIR="$(dirname "$SCRIPT_DIR")" readonly DATA_DIR="${PROJECT_DIR}/tmp/validate-$$" readonly PID_FILE="${DATA_DIR}/server.pid" readonly LOG_FILE="${DATA_DIR}/server.log" # Colors (if terminal supports it) if [[ -t 1 ]]; then RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[0;33m' BLUE='\033[0;34m' NC='\033[0m' # No Color else RED='' GREEN='' YELLOW='' BLUE='' NC='' fi # Logging helpers info() { echo -e "${BLUE}[INFO]${NC} $*"; } success() { echo -e "${GREEN}[PASS]${NC} $*"; } warn() { echo -e "${YELLOW}[WARN]${NC} $*"; } fail() { echo -e "${RED}[FAIL]${NC} $*"; exit 1; } # Cleanup on exit cleanup() { if [[ -f "$PID_FILE" ]]; then local pid pid=$(cat "$PID_FILE") if kill -0 "$pid" 2>/dev/null; then info "Stopping server (PID $pid)..." kill "$pid" 2>/dev/null || true wait "$pid" 2>/dev/null || true fi fi if [[ -d "$DATA_DIR" ]]; then rm -rf "$DATA_DIR" fi } trap cleanup EXIT # Parse arguments SKIP_BUILD=false for arg in "$@"; do case $arg in --no-build) SKIP_BUILD=true ;; --help|-h) echo "Usage: $0 [--no-build]" echo "" echo "Validates StemeDB end-to-end (build, start, assert, query, shutdown)." echo "" echo "Options:" echo " --no-build Skip cargo build (use existing binary)" echo " --help Show this help message" exit 0 ;; esac done # Main validation main() { echo "" echo "==========================================" echo " StemeDB Validation" echo "==========================================" echo "" # Create temp data directory mkdir -p "$DATA_DIR" # Step 1: Build if [[ "$SKIP_BUILD" == "false" ]]; then info "Building stemedb-api..." cd "$PROJECT_DIR" if ! cargo build --package stemedb-api --quiet 2>&1; then fail "Build failed" fi success "Build complete" else info "Skipping build (--no-build)" fi # Step 2: Start server info "Starting API server..." cd "$PROJECT_DIR" # Use release binary if available (fast startup), fall back to cargo run local server_bin="$PROJECT_DIR/target/release/stemedb-api" if [[ -x "$server_bin" ]]; then STEMEDB_WAL_DIR="$DATA_DIR/wal" \ STEMEDB_DB_DIR="$DATA_DIR/db" \ STEMEDB_BIND_ADDR="$API_HOST" \ "$server_bin" > "$LOG_FILE" 2>&1 & else STEMEDB_WAL_DIR="$DATA_DIR/wal" \ STEMEDB_DB_DIR="$DATA_DIR/db" \ STEMEDB_BIND_ADDR="$API_HOST" \ cargo run --package stemedb-api --quiet > "$LOG_FILE" 2>&1 & fi echo $! > "$PID_FILE" # Step 3: Wait for health info "Waiting for server to be ready..." local attempts=0 local max_attempts=30 while [[ $attempts -lt $max_attempts ]]; do if curl -s "${API_URL}/v1/health" > /dev/null 2>&1; then break fi sleep 0.5 ((attempts++)) done if [[ $attempts -eq $max_attempts ]]; then echo "" echo "Server log:" cat "$LOG_FILE" || true fail "Server failed to start within 15 seconds" fi success "Server is healthy" # Step 4: Health check details info "Checking health endpoint..." local health_response health_response=$(curl -s "${API_URL}/v1/health") echo " Response: $health_response" if ! echo "$health_response" | grep -q '"status":"healthy"'; then fail "Health check failed" fi success "Health check passed" # Step 5: Create a properly signed assertion info "Creating assertion (with valid Ed25519 signature)..." # Generate a properly signed assertion using the helper binary # This creates a fresh keypair and signs "{subject}:{predicate}" local assertion_json assertion_json=$(cargo run --package stemedb-api --example gen_test_assertion --quiet 2>/dev/null) if [[ -z "$assertion_json" ]]; then fail "Failed to generate signed assertion" fi local assert_response assert_response=$(curl -s -X POST "${API_URL}/v1/assert" \ -H "Content-Type: application/json" \ -d "$assertion_json") echo " Response: $assert_response" if ! echo "$assert_response" | grep -q '"status":"created"'; then fail "Assertion creation failed" fi local assertion_hash assertion_hash=$(echo "$assert_response" | grep -o '"hash":"[^"]*"' | cut -d'"' -f4) success "Assertion created: ${assertion_hash:0:16}..." # Step 6: Query the assertion back (with retry for ingestion) info "Querying assertion..." # Retry loop - ingestion worker needs time to process WAL local query_attempts=0 local query_max_attempts=10 local query_response="" while [[ $query_attempts -lt $query_max_attempts ]]; do query_response=$(curl -s "${API_URL}/v1/query?subject=StemeDB_Validation&predicate=test_status") local count count=$(echo "$query_response" | grep -o '"total_count":[0-9]*' | cut -d':' -f2) if [[ "$count" -gt 0 ]] 2>/dev/null; then break fi sleep 0.5 ((query_attempts++)) done echo " Total count: $(echo "$query_response" | grep -o '"total_count":[0-9]*' | cut -d':' -f2)" echo " Ingestion took ~$((query_attempts * 500))ms" if ! echo "$query_response" | grep -q '"StemeDB_Validation"'; then echo " Full response: $query_response" fail "Query did not return expected subject (tried ${query_attempts} times)" fi if ! echo "$query_response" | grep -q '"working"'; then fail "Query did not return expected value" fi success "Query returned correct data" # Step 7: Test query with lens info "Testing lens-based query..." local lens_response lens_response=$(curl -s "${API_URL}/v1/query?subject=StemeDB_Validation&predicate=test_status&lens=Recency") if ! echo "$lens_response" | grep -q '"working"'; then fail "Lens query failed" fi success "Lens query (Recency) works" # Final summary echo "" echo "==========================================" echo -e " ${GREEN}All validation checks passed!${NC}" echo "==========================================" echo "" echo "StemeDB is working correctly. You can now:" echo " 1. Start the server: cargo run --package stemedb-api" echo " 2. View API docs: http://localhost:18180/swagger-ui" echo " 3. Use the Go SDK: cd sdk/go/examples/basic && go run main.go" echo "" } main "$@"