AkurAI Build
Menu

Public repository / 44c64d8135845564b85987762981dcab8d6ba997

AkurAI-PassVault / scripts/validate.sh

Latest change f0de6c29b6eff8151dc0f8eebcffcf409026c988 - feat: expose PassVault UI through AkurAI ID by Ólafur Búi Ólafsson

#!/usr/bin/env bash
# scripts/validate.sh — Post-deploy validation for AkurAI-PassVault
# PassVault serves its authenticated web UI and MCP API from the same process.
set -euo pipefail

: "${DOMAIN:=akurai-passvault.olibuijr.com}"
: "${PORT:=8102}"
: "${APP_NAME:=akurai-passvault}"
RED='\033[0;31m'; GRN='\033[0;32m'; NC='\033[0m'
pass=0; fail=0
pass_() { printf "  ${GRN}PASS${NC} %s\n" "$*"; ((pass++)); }
fail_() { printf "  ${RED}FAIL${NC} %s\n" "$*"; ((fail++)); }

echo "=== Post-deploy validation: ${APP_NAME} ==="

systemctl is-active --quiet "${APP_NAME}.service" 2>/dev/null && pass_ "systemd active" || fail_ "systemd not active"
health_check() {
  local url="$1" label="$2" response body status
  response=$(curl -sS --max-time 10 -w $'\n%{http_code}' "$url" 2>/dev/null || true)
  body="${response%$'\n'*}"
  status="${response##*$'\n'}"
  if [ "$status" = "200" ] && printf '%s' "$body" | python3 -c "import json,sys; d=json.load(sys.stdin); assert d.get('status') == 'ok'"; then
    pass_ "$label"
  else
    fail_ "$label (HTTP ${status:-unknown})"
  fi
}

health_check "http://127.0.0.1:${PORT}/api/health" "loopback health"
health_check "https://${DOMAIN}/api/health" "public health"

# OIDC entrypoint smoke test
auth_headers=$(curl -sS --max-time 10 -D - -o /dev/null "https://${DOMAIN}/login" 2>/dev/null || true)
auth_status=$(printf '%s' "$auth_headers" | awk 'NR == 1 { print $2 }')
auth_location=$(printf '%s' "$auth_headers" | awk 'tolower($1) == "location:" { print $2 }' | tr -d '\r')
if [ "$auth_status" = "303" ] && [[ "$auth_location" == https://auth.olibuijr.com/authorize\?* ]]; then
  pass_ "OIDC login redirect"
else
  fail_ "OIDC login redirect failed (HTTP ${auth_status:-unknown})"
fi

# MCP tools/list smoke test
TOKEN=$(sudo grep "^AKURAI_PASSVAULT_TOKEN=" /etc/akurai-passvault/env 2>/dev/null | cut -d= -f2- || echo "")
if [ -n "$TOKEN" ]; then
  response=$(curl -sS --max-time 10 -w $'\n%{http_code}' -X POST "https://${DOMAIN}/mcp" \
    -H "Authorization: Bearer ${TOKEN}" \
    -H "Content-Type: application/json" \
    -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}' 2>/dev/null || true)
  body="${response%$'\n'*}"
  status="${response##*$'\n'}"
  if [ "$status" = "200" ] && printf '%s' "$body" | python3 -c "import json,sys; d=json.load(sys.stdin); assert isinstance(d.get('result',{}).get('tools'), list)"; then
    pass_ "MCP tools/list OK"
  else
    fail_ "MCP tools/list failed (HTTP ${status:-unknown})"
  fi
else
  fail_ "MCP token not found — cannot verify MCP"
fi

echo "━━━━━━━━━━━━━━━━━━━━━━━━"
echo -e "${GRN}Pass: $pass${NC}  ${RED}Fail: $fail${NC}"
[ "$fail" -eq 0 ] || exit 1