diff --git a/tests/e2e/test_peer_visibility_mcp_local.sh b/tests/e2e/test_peer_visibility_mcp_local.sh index 4fd378d45..a69bc40a9 100755 --- a/tests/e2e/test_peer_visibility_mcp_local.sh +++ b/tests/e2e/test_peer_visibility_mcp_local.sh @@ -24,14 +24,12 @@ # # Only PROVISIONING differs from staging: # - staging: POST /cp/admin/orgs (cold EC2 tenant) + per-tenant admin -# token + each workspace's MCP bearer from create response or an admin -# token-mint fallback. +# token + each workspace's MCP bearer from the POST /workspaces +# create response. # - local: POST /workspaces directly against the local stack -# (BASE, default http://localhost:8080), MCP bearer minted via -# GET /admin/workspaces/:id/test-token (e2e_mint_test_token — -# deterministic, gated by MOLECULE_ENV != production). Same model -# every other local E2E (test_priority_runtimes_e2e.sh, -# test_api.sh) already uses; no new credential/provision flow. +# (BASE, default http://localhost:8080), MCP bearer consumed inline +# from the create response (auth_token field). Same model every +# other local E2E uses; no new credential/provision flow. # # By default the local backend creates external-mode workspace rows and # drives the literal MCP path directly. That keeps the local peer-visibility @@ -81,6 +79,17 @@ NAME_PREFIX="PV-Local-$$-$(date +%H%M%S)" log() { echo "[$(date +%H:%M:%S)] $*"; } ok() { echo "[$(date +%H:%M:%S)] ✅ $*"; } +extract_auth_token() { + python3 -c " +import sys, json +try: + d = json.load(sys.stdin) +except Exception: + print(''); sys.exit(0) +print(d.get('auth_token') or d.get('connection', {}).get('auth_token') or '') +" 2>/dev/null +} + CREATED_WSIDS=() ADMIN_BEARER="${MOLECULE_ADMIN_TOKEN:-${ADMIN_TOKEN:-}}" ADMIN_AUTH=() @@ -131,17 +140,6 @@ if ! curl -fsS "$BASE/health" -m 5 >/dev/null 2>&1; then echo "::error::Local stack not healthy at $BASE/health — bring it up (make up) before this gate. Infra, not a workspace bug (feedback_fix_root_not_symptom)." >&2 exit 1 fi -# admin/test-token is the local MCP-bearer mint path; it 404s in -# production. If it is off, this gate cannot drive the literal call. -if ! curl -fsS "$BASE/admin/workspaces/preflight-probe/test-token" ${ADMIN_AUTH[@]+"${ADMIN_AUTH[@]}"} -m 5 >/dev/null 2>&1; then - # A 404 here is EITHER "no such ws" (fine — endpoint is enabled) OR the - # endpoint is disabled (MOLECULE_ENV=production). Distinguish by body. - PROBE=$(curl -s "$BASE/admin/workspaces/preflight-probe/test-token" ${ADMIN_AUTH[@]+"${ADMIN_AUTH[@]}"} -m 5 2>/dev/null) - if echo "$PROBE" | grep -qi 'production\|disabled\|not found.*endpoint'; then - echo "::error::GET /admin/workspaces/:id/test-token disabled (MOLECULE_ENV=production?). Cannot mint a local MCP bearer." >&2 - exit 1 - fi -fi ok " local stack healthy" # ─── Resolve per-runtime provisioning secrets ────────────────────────── @@ -244,6 +242,12 @@ log "1/5 provisioning parent ($PARENT_RUNTIME, mode=$PV_LOCAL_PROVISION_MODE) + P_RESP=$(curl -s -X POST "$BASE/workspaces" ${ADMIN_AUTH[@]+"${ADMIN_AUTH[@]}"} -H "Content-Type: application/json" \ -d "{\"name\":\"${NAME_PREFIX}-parent\",\"runtime\":\"$PARENT_RUNTIME\",\"tier\":3$PARENT_EXTRA,\"secrets\":$PARENT_SECRETS}") PARENT_ID=$(echo "$P_RESP" | python3 -c 'import json,sys;print(json.load(sys.stdin).get("id",""))' 2>/dev/null) +# PARENT_TOKEN captured for symmetry with the per-sibling auth-token +# capture in the runtime loop below + reserved for follow-up steps +# that need parent-side auth. Current downstream steps reach the parent +# via admin token, so the variable isn't dereferenced — SC2034. +# shellcheck disable=SC2034 # captured for downstream parent-auth use; see #1644 follow-up +PARENT_TOKEN=$(echo "$P_RESP" | extract_auth_token) if [ -z "$PARENT_ID" ]; then echo "::error::parent create failed: $(echo "$P_RESP" | head -c 300)" >&2 exit 1 @@ -259,6 +263,8 @@ log " PARENT_ID=$PARENT_ID runtime=$PARENT_RUNTIME" WS_IDS_MAP="" # shellcheck disable=SC2034 # map values are updated through portable eval-based helpers. VERDICT_MAP="" +# shellcheck disable=SC2034 # map values are updated through portable eval-based helpers. +WS_TOKENS_MAP="" _map_set() { # _map_set local __m="$1" __k="$2" __v="$3" __cur eval "__cur=\$$__m" @@ -294,11 +300,17 @@ for rt in $PV_RUNTIMES; do R=$(curl -s -X POST "$BASE/workspaces" ${ADMIN_AUTH[@]+"${ADMIN_AUTH[@]}"} -H "Content-Type: application/json" \ -d "{\"name\":\"${NAME_PREFIX}-$rt\",\"runtime\":\"$CREATE_RUNTIME\",\"tier\":2,\"parent_id\":\"$PARENT_ID\"$CREATE_EXTRA,\"secrets\":$SEC}") WID=$(echo "$R" | python3 -c 'import json,sys;print(json.load(sys.stdin).get("id",""))' 2>/dev/null) + WTOK=$(echo "$R" | extract_auth_token) if [ -z "$WID" ]; then echo "::error::$rt workspace create failed: $(echo "$R" | head -c 300)" >&2 exit 1 fi + if [ -z "$WTOK" ]; then + echo "::error::$rt workspace create did not return an auth_token — cannot drive the literal MCP call" >&2 + exit 1 + fi _map_set WS_IDS_MAP "$rt" "$WID" + _map_set WS_TOKENS_MAP "$rt" "$WTOK" CREATED_WSIDS+=("$WID") ALL_WS_IDS="$ALL_WS_IDS $WID" ACTIVE_RUNTIMES="$ACTIVE_RUNTIMES $rt" @@ -356,10 +368,10 @@ log "4/5 driving the LITERAL list_peers MCP call per online runtime..." echo "" for rt in $ONLINE_RUNTIMES; do wid="$(_map_get WS_IDS_MAP "$rt")" - WTOK=$(e2e_mint_test_token "$wid" 2>/dev/null || true) + WTOK="$(_map_get WS_TOKENS_MAP "$rt")" if [ -z "$WTOK" ]; then echo "--- $rt (ws=$wid) ---" - echo " ✗ $rt: could not mint a local MCP bearer (admin/test-token) — cannot drive the literal call" + echo " ✗ $rt: workspace create did not return an auth_token — cannot drive the literal call" _map_set VERDICT_MAP "$rt" "FAIL(no-bearer)" REGRESSED=1 echo "" diff --git a/tests/e2e/test_peer_visibility_mcp_staging.sh b/tests/e2e/test_peer_visibility_mcp_staging.sh index 43daf0646..e7c5af3eb 100755 --- a/tests/e2e/test_peer_visibility_mcp_staging.sh +++ b/tests/e2e/test_peer_visibility_mcp_staging.sh @@ -40,10 +40,10 @@ # drives: POST /cp/admin/orgs (provision), GET # /cp/admin/orgs/:slug/admin-token (per-tenant token), DELETE # /cp/admin/tenants/:slug (teardown). The per-tenant admin token drives -# tenant workspace creation; each workspace's OWN auth_token drives its -# MCP call. External-like runtimes may return the token in POST -# /workspaces; managed container runtimes usually require the admin token -# mint fallback below. +# tenant workspace creation; each workspace's OWN auth_token is consumed +# inline from the POST /workspaces 201 response to drive its MCP call. +# No dev-only admin token-mint routes are used in this E2E +# (feedback_no_dev_only_routes_in_e2e). # # Required env: # MOLECULE_ADMIN_TOKEN CP admin bearer — Railway staging CP_ADMIN_API_TOKEN @@ -265,44 +265,19 @@ 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}") WID=$(echo "$R" | python3 -c "import sys,json; print(json.load(sys.stdin).get('id',''))" 2>/dev/null) - # 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 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="" - if [ -z "$WTOK" ]; then - TTOK_FILE=$(mktemp) - TTOK_CODE=$(tenant_call_capture POST "/admin/workspaces/$WID/tokens" "$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="POST /admin/workspaces/$WID/tokens -> HTTP $TTOK_CODE body: $(echo "$TTOK_RESP" | redact_token_body)" - rm -f "$TTOK_FILE" - fi + [ -n "$WID" ] || fail "$rt workspace create failed: $(echo \"$R\" | head -c 300)" + [ -n "$WTOK" ] || fail "$rt workspace create did not return an auth_token — cannot drive its MCP call (workspace_id=$WID; create_resp: $(echo \"$R\" | redact_token_body))" 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