fix(deps): patch socket.io-parser advisory; add local CI preflight gate

Security Audit failed on a newly-published advisory, GHSA-2m8v-j782-fhvr
(socket.io-parser "Zero-attachment Memory Exhaustion", high). It affected both
projects transitively via socket.io / socket.io-client. Patched to 4.2.7 in both
lockfiles; no direct dependency versions changed.

Also adds the gate that should have caught the previous two CI failures before
they reached GitHub:

- scripts/ci-preflight.sh runs every gate from .github/workflows/ci.yml
  (frontend and backend lint/type-check/build, plus both prod-dependency audits
  with the same audit-ci flags and allowlist) and additionally the backend Jest
  suite, which CI does not currently run. It runs all gates rather than failing
  fast, so one invocation surfaces every problem. ~35s.
- scripts/claude-push-gate.sh wires that into a Claude Code PreToolUse hook so a
  `git push` is refused while any gate fails, with the failure detail returned
  inline. Non-push commands and --dry-run pass straight through.

Verified: with the fix reverted, the gate correctly denied the push and reported
"backend: lint FAIL"; with it restored, all 9 gates pass and both audit-ci
invocations exit 0.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2GT-Rich
2026-08-10 09:27:40 -07:00
co-authored by Claude Opus 4.8
parent 23a45703a5
commit d44a0ea8a7
4 changed files with 146 additions and 34 deletions
+64
View File
@@ -0,0 +1,64 @@
#!/usr/bin/env bash
# Run the same gates GitHub Actions runs, locally, before pushing.
#
# Mirrors .github/workflows/ci.yml exactly (frontend lint/type-check/build,
# backend lint/type-check/build, prod-dependency audits) and additionally runs
# the backend Jest suite, which CI does not currently cover.
#
# Usage: scripts/ci-preflight.sh [--skip-audit]
# Exit: 0 = everything CI checks would pass, 1 = at least one gate failed.
#
# Runs every gate rather than failing fast, so one invocation surfaces all
# problems instead of dribbling them out one push at a time.
set -uo pipefail
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
SKIP_AUDIT=0
[[ "${1:-}" == "--skip-audit" ]] && SKIP_AUDIT=1
FAILED=()
run() {
local label="$1" dir="$2"; shift 2
printf ' %-34s' "$label"
if (cd "$ROOT/$dir" && "$@") >/tmp/ci-preflight-out 2>&1; then
echo "ok"
else
echo "FAIL"
FAILED+=("$label")
# Keep a trimmed excerpt so the caller can see why without re-running.
{
echo "----- $label -----"
tail -25 /tmp/ci-preflight-out
echo
} >>/tmp/ci-preflight-failures
fi
}
: >/tmp/ci-preflight-failures
echo "Running CI gates locally (mirrors .github/workflows/ci.yml)"
run "backend: lint" backend npm run lint
run "backend: type-check" backend npx tsc --noEmit
run "backend: build" backend npm run build
run "backend: tests" backend npx jest --silent
run "frontend: lint" frontend npm run lint
run "frontend: type-check" frontend npx tsc --noEmit
run "frontend: build" frontend npm run build
if [[ $SKIP_AUDIT -eq 0 ]]; then
run "frontend: audit (prod)" frontend \
npx --yes audit-ci@^7 --high --skip-dev --allowlist GHSA-qwww-vcr4-c8h2
run "backend: audit (prod)" backend \
npx --yes audit-ci@^7 --high --skip-dev
fi
if [[ ${#FAILED[@]} -eq 0 ]]; then
echo "All CI gates passed."
exit 0
fi
echo
echo "FAILED: ${FAILED[*]}"
echo "Details in /tmp/ci-preflight-failures"
exit 1