Files
molecule-core/tests/harness/_curl.sh
hongming a094460580
ci-arm64-advisory / fast-checks (push) Waiting to run
Lint shellcheck (arm64 pilot) / shellcheck-arm64 (pilot) (push) Successful in 9s
Block internal-flavored paths / Block forbidden paths (push) Successful in 34s
CI / Python Lint & Test (push) Successful in 14s
CI / Detect changes (push) Successful in 19s
publish-workspace-server-image / build-and-push (push) Successful in 2m58s
E2E Chat / detect-changes (push) Successful in 37s
E2E API Smoke Test / detect-changes (push) Successful in 37s
E2E Staging Canvas (Playwright) / detect-changes (push) Successful in 31s
E2E Staging SaaS (full lifecycle) / pr-validate (push) Successful in 1m8s
Handlers Postgres Integration / detect-changes (push) Successful in 13s
E2E Peer Visibility (literal MCP list_peers) / E2E Peer Visibility (local) (push) Successful in 2m2s
Harness Replays / detect-changes (push) Successful in 14s
publish-canvas-image / Build & push canvas image (push) Successful in 4m45s
Lint curl status-code capture / Scan workflows for curl status-capture pollution (push) Successful in 9s
Lint forbidden tenant-env keys / Scan workspace_secrets writers for forbidden env keys (push) Successful in 15s
E2E Peer Visibility (literal MCP list_peers) / E2E Peer Visibility (push) Has been skipped
Lint no tenant GITEA or GITHUB token write / Scan for repo-host token write into tenant workspace surface (push) Successful in 20s
lint-required-workflows-docker-host-pinned / Lint docker-host pin on docker-touching workflows (push) Successful in 8s
review-check-tests / review-check.sh regression tests (push) Successful in 16s
Secret scan / Scan diff for credential-shaped strings (push) Successful in 8s
lint-continue-on-error-tracking / lint-continue-on-error-tracking (push) Successful in 1m31s
Lint workflow YAML (Gitea-1.22.6-hostile shapes) / Lint workflow YAML for Gitea-1.22.6-hostile shapes (push) Successful in 1m29s
Ops Scripts Tests / Ops scripts (unittest) (push) Successful in 1m37s
CI / Shellcheck (E2E scripts) (push) Successful in 42s
E2E Staging SaaS (full lifecycle) / E2E Staging SaaS (push) Successful in 5m20s
E2E API Smoke Test / E2E API Smoke Test (push) Successful in 2m6s
Harness Replays / Harness Replays (push) Successful in 9s
Sweep stale e2e-* orgs (staging) / Sweep e2e orgs (push) Successful in 8s
Sweep stale AWS Secrets Manager secrets / Sweep AWS Secrets Manager (push) Successful in 10s
CI / Platform (Go) (push) Successful in 5m35s
E2E Chat / E2E Chat (push) Successful in 4m7s
Handlers Postgres Integration / Handlers Postgres Integration (push) Successful in 1m48s
CI / Canvas (Next.js) (push) Successful in 6m59s
CI / all-required (push) Successful in 14m21s
CI / Canvas Deploy Reminder (push) Successful in 2s
publish-workspace-server-image / Production auto-deploy (push) Successful in 13m0s
Staging SaaS smoke (every 30 min) / Staging SaaS smoke (push) Successful in 4m57s
E2E Staging Canvas (Playwright) / Canvas tabs E2E (push) Successful in 7m2s
Continuous synthetic E2E (staging) / Synthetic E2E against staging (push) Successful in 5m23s
test(e2e): add real staging image upload smoke (#1790)
test(e2e): add real staging image upload smoke (#1790)

Remove legacy test-token references, keep production test-token unavailable, add explicit tenant-header diagnostics, and verify real staging image upload/download through the live tenant workflow.
2026-05-24 10:20:49 +00:00

161 lines
6.1 KiB
Bash

# shellcheck shell=bash
# Sourceable helper for harness replays. Centralises the
# curl-against-cf-proxy pattern so scripts don't depend on /etc/hosts.
#
# Production CF tunnel routes by Host header, not by DNS — the request
# URL is to a public CF endpoint and the Host header carries the
# per-tenant identity. We replay the same shape locally:
#
# curl -H "Host: harness-tenant-alpha.localhost" http://localhost:8080/health
#
# This matches what cf-proxy/nginx.conf already routes (`server_name
# *.localhost` + `map $host $tenant_upstream`) and avoids the macOS
# /etc/hosts requirement that previously gated the harness behind a
# sudo step.
#
# Multi-tenant since Phase 2: alpha and beta tenants run in parallel.
# `curl_alpha_admin` and `curl_beta_admin` target each tenant's URL
# with that tenant's ADMIN_TOKEN + MOLECULE_ORG_ID. The legacy
# `curl_admin` is aliased to alpha for backwards compat with the
# pre-Phase-2 single-tenant replays.
#
# Usage:
# HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# source "$HERE/../_curl.sh" # from replays/<name>.sh
# curl_alpha_admin "$BASE/health"
# curl_beta_admin "$BASE/health"
# Bind to the cf-proxy's loopback port — the proxy front-doors every
# tenant and routes by Host header, exactly like production's CF tunnel.
: "${BASE:=http://localhost:8080}"
# Per-tenant identity. Each pair must match the corresponding tenant
# container's environment in compose.yml or auth/TenantGuard will fail
# in non-obvious ways (401 vs 403 vs silent route to wrong tenant).
: "${ALPHA_HOST:=harness-tenant-alpha.localhost}"
: "${ALPHA_ADMIN_TOKEN:=harness-admin-token-alpha}"
: "${ALPHA_ORG_ID:=harness-org-alpha}"
: "${BETA_HOST:=harness-tenant-beta.localhost}"
: "${BETA_ADMIN_TOKEN:=harness-admin-token-beta}"
: "${BETA_ORG_ID:=harness-org-beta}"
# Legacy single-tenant aliases — pre-Phase-2 replays use these without
# knowing the topology grew. They map to alpha. New replays should use
# the explicit alpha/beta variants for clarity.
: "${TENANT_HOST:=$ALPHA_HOST}"
: "${ADMIN_TOKEN:=$ALPHA_ADMIN_TOKEN}"
: "${ORG_ID:=$ALPHA_ORG_ID}"
# ─── Anonymous (no auth) ──────────────────────────────────────────────
# Anonymous request to alpha. Use for /health, /buildinfo, etc.
curl_alpha_anon() {
curl -sS -H "Host: ${ALPHA_HOST}" "$@"
}
# Anonymous request to beta.
curl_beta_anon() {
curl -sS -H "Host: ${BETA_HOST}" "$@"
}
# Legacy alias for single-tenant replays.
curl_anon() {
curl -sS -H "Host: ${TENANT_HOST}" "$@"
}
# ─── Admin-token requests ─────────────────────────────────────────────
# Admin-token request to alpha tenant. SaaS-shape auth: bearer token,
# tenant org header (TenantGuard activates), JSON content type.
curl_alpha_admin() {
curl -sS \
-H "Host: ${ALPHA_HOST}" \
-H "Authorization: Bearer ${ALPHA_ADMIN_TOKEN}" \
-H "X-Molecule-Org-Id: ${ALPHA_ORG_ID}" \
-H "Content-Type: application/json" \
"$@"
}
# Admin-token request to beta tenant.
curl_beta_admin() {
curl -sS \
-H "Host: ${BETA_HOST}" \
-H "Authorization: Bearer ${BETA_ADMIN_TOKEN}" \
-H "X-Molecule-Org-Id: ${BETA_ORG_ID}" \
-H "Content-Type: application/json" \
"$@"
}
# Legacy alias.
curl_admin() {
curl_alpha_admin "$@"
}
# ─── Cross-tenant negative-test helpers ───────────────────────────────
# These exist to MAKE WRONG calls — replays use them to assert
# TenantGuard rejects them. Names spell out what's mismatched.
# alpha bearer + alpha org, but talking to beta's URL. TenantGuard
# should reject because the org header doesn't match beta's MOLECULE_ORG_ID.
curl_alpha_creds_at_beta() {
curl -sS \
-H "Host: ${BETA_HOST}" \
-H "Authorization: Bearer ${ALPHA_ADMIN_TOKEN}" \
-H "X-Molecule-Org-Id: ${ALPHA_ORG_ID}" \
-H "Content-Type: application/json" \
"$@"
}
# beta bearer + beta org, but talking to alpha's URL.
curl_beta_creds_at_alpha() {
curl -sS \
-H "Host: ${ALPHA_HOST}" \
-H "Authorization: Bearer ${BETA_ADMIN_TOKEN}" \
-H "X-Molecule-Org-Id: ${BETA_ORG_ID}" \
-H "Content-Type: application/json" \
"$@"
}
# ─── Workspace-scoped (per-workspace bearer) ──────────────────────────
# Workspace-scoped request to alpha — uses a real per-workspace bearer minted
# through the admin token route, not the local-dev fixture-token route. Caller
# must export WORKSPACE_TOKEN.
curl_workspace() {
: "${WORKSPACE_TOKEN:?WORKSPACE_TOKEN must be set — mint via POST /admin/workspaces/:id/tokens}"
curl -sS \
-H "Host: ${TENANT_HOST}" \
-H "Authorization: Bearer ${WORKSPACE_TOKEN}" \
-H "X-Molecule-Org-Id: ${ORG_ID}" \
-H "Content-Type: application/json" \
"$@"
}
# ─── Postgres exec (per-tenant) ───────────────────────────────────────
# Direct postgres exec — for replays that need to seed activity_logs
# rows or read DB state that has no public HTTP route.
#
# SECRETS_ENCRYPTION_KEY placeholder lets compose validate without
# requiring up.sh's per-run key (exec doesn't actually use it but
# compose validates the file).
psql_exec_alpha() {
SECRETS_ENCRYPTION_KEY="${SECRETS_ENCRYPTION_KEY:-exec-placeholder}" \
docker compose -f "${HARNESS_COMPOSE:-$(dirname "${BASH_SOURCE[0]}")/compose.yml}" \
exec -T postgres-alpha \
psql -U harness -d molecule -At "$@"
}
psql_exec_beta() {
SECRETS_ENCRYPTION_KEY="${SECRETS_ENCRYPTION_KEY:-exec-placeholder}" \
docker compose -f "${HARNESS_COMPOSE:-$(dirname "${BASH_SOURCE[0]}")/compose.yml}" \
exec -T postgres-beta \
psql -U harness -d molecule -At "$@"
}
# Legacy alias — single-tenant replays default to alpha's DB.
psql_exec() {
psql_exec_alpha "$@"
}