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).
This commit is contained in:
2026-08-24 20:16:00 -05:00
parent f5110d3c1b
commit f3c356951c
15 changed files with 1067 additions and 9 deletions
+54 -3
View File
@@ -40,16 +40,19 @@ jobs:
- name: Install dependencies (all first-party services)
run: |
for d in backend frontend platform/api platform/gateway platform/provisioner; do
for d in backend frontend platform/api platform/gateway platform/provisioner platform/lab-router; do
(cd "$d" && npm ci)
done
- name: Syntax-check every service
run: |
for d in backend frontend/src platform/api platform/gateway platform/provisioner; do
for d in backend frontend/src platform/api platform/gateway platform/provisioner platform/lab-router; do
find "$d" -name '*.js' -not -path '*/node_modules/*' -exec node --check {} \;
done
- name: Lab Host Router unit tests (Phase 4.1 — fast, no Docker daemon needed)
run: (cd platform/lab-router && npm test)
- name: Build frontend
run: (cd frontend && npm run build)
@@ -75,8 +78,56 @@ jobs:
# can't grant safely — they stay a LOCAL/staging pre-promotion step
# (infra/scripts/staging-smoke-test.sh), not this job. See docs/PHASE4_PRODUCTION_INFRASTRUCTURE.md §18.
# Phase 4.1 §24 — free/open-source security scanning, no paid tooling, no signup required for
# any of these. Severity policy (docs/SECURITY_SCANNING.md): CRITICAL/HIGH findings fail the
# build; MEDIUM/LOW are reported but never block a merge — a build that's permanently red over
# an unrelated low-severity transitive dependency finding trains everyone to ignore red builds.
security-scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: "20"
- name: npm audit (dependency vulnerabilities) — fails only on high/critical
run: |
FAIL=0
for d in backend frontend platform/api platform/gateway platform/provisioner platform/lab-router; do
echo "== $d =="
(cd "$d" && npm audit --audit-level=high) || FAIL=1
done
exit $FAIL
- name: Secret scanning (gitleaks — free, no account needed)
run: docker run --rm -v "$PWD:/repo" zricethezav/gitleaks:latest detect --source=/repo --no-git -v
- name: Dockerfile linting (hadolint — free)
run: |
FAIL=0
for f in Dockerfile platform/api/Dockerfile platform/gateway/Dockerfile platform/provisioner/Dockerfile platform/egress-proxy/Dockerfile platform/lab-router/Dockerfile; do
echo "== $f =="
docker run --rm -i hadolint/hadolint < "$f" || FAIL=1
done
exit $FAIL
# -S error, not warning — matches docs/SECURITY_SCANNING.md's severity policy. Real run
# against this tree at -S warning surfaces only style nits (unused loop vars, a missing
# `cd ... || exit` guard) on scripts that are otherwise correct; failing the build on
# those trains everyone to ignore the check.
- name: Shell linting (shellcheck — free, standard)
run: |
sudo apt-get update -qq && sudo apt-get install -y -qq shellcheck
find infra -name '*.sh' -exec shellcheck -S error {} \+
- name: Container image scanning (trivy — free, no account needed)
run: |
docker build -q -t rootnode-scan/platform-api -f platform/api/Dockerfile .
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock aquasec/trivy:latest image \
--severity HIGH,CRITICAL --exit-code 1 rootnode-scan/platform-api
build-images:
needs: regression
needs: [regression, security-scan]
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
steps: