Files
rootnode-academy/infra/scripts/staging-smoke-test.sh
T
ced4568 f3c356951c test(preprod): two-host routing simulation, drill suite, CI security scanning
- infra/scripts/simulate-two-host/: real two-Docker-network simulation
  (Gateway genuinely isolated from any Lab bridge network) proving the
  Lab Host Router fix - 13/13 real assertions (HTTP+WebSocket through the
  Router, Alice/Bob isolation, garbage/destroyed tokens, mTLS-only Router
  access).
- infra/scripts/drills/: Lab Host loss/rebuild (9/9), deployment rollback,
  CI-fails-closed (6 required failure modes), fake cohort dress rehearsal
  (14/14, one continuous narrative through the real app).
- infra/ci/gitea-workflows/build-and-test.yml: new security-scan job
  (npm audit, gitleaks, hadolint, shellcheck, trivy - all free/open-source),
  severity policy in docs/SECURITY_SCANNING.md (CRITICAL/HIGH blocks,
  MEDIUM/LOW reported only). Gates build-images alongside regression.

Found and fixed two real pre-existing bugs via the CI-fails-closed drill:
staging-smoke-test.sh and production-smoke-test.sh both had a classic
set -e gotcha (curl ... && echo "OK" as one statement - a failing command
that isn't last in an && chain doesn't trigger -e) that let an
unreachable/broken endpoint fall through silently instead of failing the
smoke test.

platform/test/e2e-phase3a.js updated for the new paginated
/api/admin/audit-events response shape (Phase 4.1 pagination work).
2026-08-24 20:16:00 -05:00

31 lines
1.7 KiB
Bash
Executable File

#!/usr/bin/env bash
# Staging acceptance test (Phase 4 §23/§18) — the four things a human needs before promoting a
# build: app deploys, migrations ran clean, the Gateway/Platform API/Provisioner are reachable,
# and (if OWNER_EMAIL/OWNER_PASSWORD are provided) a real assessment can be started end to end.
# Reuses platform/test/e2e-phase3b.js against the staging Gateway URL rather than re-inventing
# a parallel smoke-test harness — that suite already IS the full acceptance chain.
set -euo pipefail
STAGING_URL="${STAGING_GATEWAY_URL:?set STAGING_GATEWAY_URL, e.g. https://staging.academy.example.com}"
echo "==> Health checks"
# Phase 4.1 §23: this was `curl ... && echo ...` as one statement — under `set -e`, a failing
# command that ISN'T the last one in an && list does not trigger the shell to exit (a
# well-known bash gotcha), so a genuinely unreachable staging Gateway used to fall through
# silently instead of failing this script. Split into two statements so curl's own exit status
# is what `set -e` actually sees. Found by infra/scripts/drills/test-ci-fails-closed.sh.
curl -sf "$STAGING_URL/healthz" > /dev/null
echo "OK: Gateway /healthz"
if [ -n "${OWNER_EMAIL:-}" ] && [ -n "${OWNER_PASSWORD:-}" ]; then
echo "==> Full acceptance run (platform/test/e2e-phase3b.js against staging)"
cd "$(dirname "$0")/../../platform"
GATEWAY_URL="$STAGING_URL" OWNER_EMAIL="$OWNER_EMAIL" OWNER_PASSWORD="$OWNER_PASSWORD" \
SKIP_RESTART_TEST=1 node test/e2e-phase3b.js
else
echo "==> Skipping full e2e run — set OWNER_EMAIL/OWNER_PASSWORD for a real classroom-workflow"
echo " smoke test (bootstrap one first against staging: platform/api/bootstrap-owner.js)."
fi
echo "OK: staging smoke test passed"