diff --git a/.gitea/workflows/e2e-peer-visibility.yml b/.gitea/workflows/e2e-peer-visibility.yml index 9492851ea..2eebbf734 100644 --- a/.gitea/workflows/e2e-peer-visibility.yml +++ b/.gitea/workflows/e2e-peer-visibility.yml @@ -86,6 +86,7 @@ on: - 'workspace-server/internal/handlers/registry.go' - 'workspace-server/internal/handlers/workspace.go' - 'tests/e2e/test_peer_visibility_mcp_staging.sh' + - 'tests/e2e/test_peer_visibility_token_mint_staging.sh' - 'tests/e2e/test_peer_visibility_mcp_local.sh' - 'tests/e2e/lib/peer_visibility_assert.sh' - '.gitea/workflows/e2e-peer-visibility.yml' @@ -98,6 +99,7 @@ on: - 'workspace-server/internal/handlers/registry.go' - 'workspace-server/internal/handlers/workspace.go' - 'tests/e2e/test_peer_visibility_mcp_staging.sh' + - 'tests/e2e/test_peer_visibility_token_mint_staging.sh' - 'tests/e2e/test_peer_visibility_mcp_local.sh' - 'tests/e2e/lib/peer_visibility_assert.sh' - '.gitea/workflows/e2e-peer-visibility.yml' @@ -137,8 +139,14 @@ jobs: echo "lib/peer_visibility_assert.sh — bash syntax OK" bash -n tests/e2e/test_peer_visibility_mcp_staging.sh echo "test_peer_visibility_mcp_staging.sh — bash syntax OK" + bash -n tests/e2e/test_peer_visibility_token_mint_staging.sh + echo "test_peer_visibility_token_mint_staging.sh — bash syntax OK" bash -n tests/e2e/test_peer_visibility_mcp_local.sh echo "test_peer_visibility_mcp_local.sh — bash syntax OK" + if rg -n '/admin/workspaces/.*/test-token|test-token' tests/e2e/test_*staging*.sh; then + echo "::error::staging E2E must not use dev-only /admin/workspaces/:id/test-token; use production-safe admin token minting instead" + exit 1 + fi echo "Staging fresh-provision MCP list_peers E2E runs on push to" echo "main / workflow_dispatch / daily cron (30+ min EC2 boot)." echo "The LOCAL backend runs in the peer-visibility-local job" diff --git a/tests/e2e/test_peer_visibility_mcp_staging.sh b/tests/e2e/test_peer_visibility_mcp_staging.sh index 68591a791..43daf0646 100755 --- a/tests/e2e/test_peer_visibility_mcp_staging.sh +++ b/tests/e2e/test_peer_visibility_mcp_staging.sh @@ -54,6 +54,9 @@ # E2E_PROVISION_TIMEOUT_SECS default 1800 (hermes/openclaw cold EC2 budget) # E2E_MINIMAX_API_KEY / E2E_ANTHROPIC_API_KEY / E2E_OPENAI_API_KEY # LLM provider key injected so the runtime can boot +# PV_TOKEN_DIAGNOSTIC_ONLY +# 1 -> stop after create/token acquisition. Useful +# to classify Hermes-only vs shared auth-route issues. # E2E_KEEP_ORG 1 → skip teardown (local debugging only) # # Exit codes: @@ -232,6 +235,12 @@ for i in $(seq 1 120); do curl -fsS "$TENANT_URL/health" -m 5 -k >/dev/null 2>&1 && { log " /health ok (attempt $i)"; break; } sleep 5 done +BUILDINFO=$(curl -fsS "$TENANT_URL/buildinfo" -m 10 2>/dev/null || true) +if [ -n "$BUILDINFO" ]; then + log " tenant buildinfo: $(echo "$BUILDINFO" | head -c 300)" +else + log " tenant buildinfo unavailable" +fi # ─── 4. Provision the parent + one sibling per runtime under test ────── # Inject the LLM provider key so each runtime can authenticate at boot. @@ -256,6 +265,8 @@ log " PARENT_ID=$PARENT_ID" # WS_IDS[runtime]=id ; WS_TOKENS[runtime]=auth_token (the MCP bearer) declare -A WS_IDS WS_TOKENS ALL_WS_IDS="$PARENT_ID" +TOKEN_ERRORS=0 +TOKEN_ERROR_SUMMARY="" for rt in $PV_RUNTIMES; do R=$(tenant_call POST /workspaces \ -d "{\"name\":\"pv-$rt\",\"runtime\":\"$rt\",\"tier\":2,\"parent_id\":\"$PARENT_ID\",\"secrets\":$SECRETS_JSON}") @@ -263,7 +274,7 @@ for rt in $PV_RUNTIMES; do # External-like runtimes may return connection.auth_token on create. # Managed container runtimes usually return only id/status here, then # receive their bearer through registry/bootstrap; for this literal MCP - # driver we mint an admin test token below. + # driver we mint through the production-safe admin token route below. WTOK=$(echo "$R" | extract_auth_token) [ -n "$WID" ] || fail "$rt workspace create failed: $(echo "$R" | head -c 300)" TOKEN_DIAG="" @@ -275,22 +286,28 @@ for rt in $PV_RUNTIMES; do TOKEN_DIAG="POST /admin/workspaces/$WID/tokens -> HTTP $TTOK_CODE body: $(echo "$TTOK_RESP" | redact_token_body)" rm -f "$TTOK_FILE" fi - if [ -z "$WTOK" ]; then - TTOK_FILE=$(mktemp) - TTOK_CODE=$(tenant_call_capture GET "/admin/workspaces/$WID/test-token" "$TTOK_FILE" 2>/dev/null || echo "curl_error") - TTOK_RESP=$(cat "$TTOK_FILE" 2>/dev/null || true) - WTOK=$(echo "$TTOK_RESP" | extract_auth_token) - TOKEN_DIAG="${TOKEN_DIAG} -GET /admin/workspaces/$WID/test-token -> HTTP $TTOK_CODE body: $(echo "$TTOK_RESP" | redact_token_body)" - rm -f "$TTOK_FILE" - fi - [ -n "$WTOK" ] || fail "$rt workspace did not return or mint an auth_token — cannot drive its MCP call (create_resp: $(echo "$R" | redact_token_body); token_fallbacks: $TOKEN_DIAG)" WS_IDS[$rt]="$WID" + if [ -z "$WTOK" ]; then + TOKEN_ERRORS=$((TOKEN_ERRORS + 1)) + TOKEN_ERROR_SUMMARY="${TOKEN_ERROR_SUMMARY} +[$rt] workspace did not return or mint an auth_token — cannot drive its MCP call (workspace_id=$WID; create_resp: $(echo "$R" | redact_token_body); token_fallbacks: $TOKEN_DIAG)" + log " $rt → $WID (token acquisition failed; continuing to classify other runtimes)" + continue + fi WS_TOKENS[$rt]="$WTOK" ALL_WS_IDS="$ALL_WS_IDS $WID" log " $rt → $WID" done +if [ "$TOKEN_ERRORS" -gt 0 ]; then + fail "token acquisition failed for $TOKEN_ERRORS runtime(s):$TOKEN_ERROR_SUMMARY" +fi + +if [ "${PV_TOKEN_DIAGNOSTIC_ONLY:-0}" = "1" ]; then + ok "token diagnostic passed for runtimes: $PV_RUNTIMES" + exit 0 +fi + # ─── 5. Wait for every sibling online ────────────────────────────────── log "5/6 waiting for all workspaces status=online (up to ${PROVISION_TIMEOUT_SECS}s — cold boot)..." WS_DEADLINE=$(( $(date +%s) + PROVISION_TIMEOUT_SECS )) diff --git a/tests/e2e/test_peer_visibility_token_mint_staging.sh b/tests/e2e/test_peer_visibility_token_mint_staging.sh new file mode 100755 index 000000000..62bfb3eff --- /dev/null +++ b/tests/e2e/test_peer_visibility_token_mint_staging.sh @@ -0,0 +1,22 @@ +#!/usr/bin/env bash +# Staging E2E diagnostic — classify peer-visibility token acquisition. +# +# This is intentionally narrower than test_peer_visibility_mcp_staging.sh: +# it provisions the same throwaway org, creates managed sibling workspaces, +# and stops immediately after auth_token acquisition. The default runtime set +# compares hermes with claude-code so a failure is easy to classify: +# - hermes fails, claude-code passes -> Hermes/runtime-specific +# - both fail -> shared admin/auth/proxy route +# +# Required env matches test_peer_visibility_mcp_staging.sh: +# MOLECULE_ADMIN_TOKEN +# Optional: +# MOLECULE_CP_URL, E2E_RUN_ID, PV_RUNTIMES, E2E_KEEP_ORG, +# E2E_MINIMAX_API_KEY / E2E_ANTHROPIC_API_KEY / E2E_OPENAI_API_KEY + +set -euo pipefail + +export PV_RUNTIMES="${PV_RUNTIMES:-hermes claude-code}" +export PV_TOKEN_DIAGNOSTIC_ONLY=1 + +exec "$(dirname "${BASH_SOURCE[0]}")/test_peer_visibility_mcp_staging.sh"