48aa955212
For the live FIFA gates. Records switch rules, sidecar status, log, trace and the Python contract result into a timestamped bundle, and reports CONFIGURED and OBSERVED state as two distinct sections. The separation is the whole point. 'blaze-switch.sh status = ON' is an assertion produced by the same tooling that performs the switch, and that tooling reported a successful rollback once when none had happened. The observed half comes from an unrelated source: the sidecar's own record of which peers connected to it. A non-loopback peer in that log proves the client's Blaze traffic landed on Rust without depending on reading an iptables rule correctly. Verified both ways: loopback-only traffic reports 'a FIFA session did NOT land here'; a non-loopback peer reports that it observably did. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
128 lines
4.8 KiB
Bash
Executable File
128 lines
4.8 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Capture evidence for one live-FIFA gate.
|
|
#
|
|
# gate-evidence.sh <gate-label> [outdir]
|
|
#
|
|
# Records what the system was configured to do AND what it observably did, and
|
|
# reports them separately.
|
|
#
|
|
# WHY BOTH
|
|
#
|
|
# `blaze-switch.sh status = ON` is an assertion produced by the same tooling
|
|
# that performs the switch. If that tooling is wrong — and it has been once
|
|
# already, reporting a rollback that had not happened — the assertion is
|
|
# worthless. The observed half comes from a different source entirely: the
|
|
# sidecar's own record of which peers connected to it. A remote peer appearing
|
|
# in the sidecar log is proof the client reached Rust that does not depend on
|
|
# reading an iptables rule correctly.
|
|
#
|
|
# Run it after each gate. It never modifies anything.
|
|
set -uo pipefail
|
|
|
|
HERE="$(cd "$(dirname "$(readlink -f "$0")")" && pwd)"
|
|
ROOT="$(cd "$HERE/.." && pwd)"
|
|
RUNDIR="${OPENFUT_SIDECAR_RUNDIR:-${TMPDIR:-/tmp}/openfut-sidecar}"
|
|
LOGFILE="${OPENFUT_SIDECAR_LOG:-$RUNDIR/sidecar.log}"
|
|
TRACE="${OPENFUT_BLAZE_TRACE:-}"
|
|
|
|
LABEL="${1:-}"
|
|
OUT="${2:-$ROOT/gate-evidence}"
|
|
[[ -n "$LABEL" ]] || { echo "usage: gate-evidence.sh <gate-label> [outdir]" >&2; exit 2; }
|
|
|
|
STAMP="$(date -u +%Y%m%dT%H%M%SZ)"
|
|
DEST="$OUT/${STAMP}-${LABEL}"
|
|
mkdir -p "$DEST"
|
|
|
|
say() { echo "$@"; }
|
|
both() { echo "$@" | tee -a "$DEST/summary.txt" >/dev/null; echo "$@"; }
|
|
|
|
both "=== gate evidence: $LABEL ($STAMP) ==="
|
|
both ""
|
|
|
|
# ---------------------------------------------------- configured (asserted)
|
|
both "--- CONFIGURED (asserted by tooling) ---"
|
|
{
|
|
"$HERE/blaze-switch.sh" status 2>&1
|
|
echo
|
|
"$HERE/sidecar.sh" status 2>&1
|
|
} > "$DEST/configured.txt"
|
|
sed 's/^/ /' "$DEST/configured.txt" | tee -a "$DEST/summary.txt"
|
|
|
|
# Raw rules, straight from the kernel, not via our parser.
|
|
{ sudo iptables -t nat -S 2>/dev/null || true; } > "$DEST/iptables-nat.txt"
|
|
both ""
|
|
|
|
# ------------------------------------------------------ observed (measured)
|
|
both "--- OBSERVED (measured from the sidecar's own record) ---"
|
|
|
|
if [[ ! -f "$LOGFILE" ]]; then
|
|
both " no sidecar log at $LOGFILE — nothing observed"
|
|
else
|
|
cp "$LOGFILE" "$DEST/sidecar.log" 2>/dev/null
|
|
|
|
banner="$(grep -m1 'openfut-blaze-host v' "$LOGFILE" 2>/dev/null || true)"
|
|
both " build: ${banner:-<none>}"
|
|
if grep -q 'tree=DIRTY' <<<"$banner"; then
|
|
both " !! DIRTY BUILD — this run is NOT parity evidence"
|
|
fi
|
|
|
|
conns="$(grep -c 'CONNECT from' "$LOGFILE" 2>/dev/null || echo 0)"
|
|
both " connections accepted: $conns"
|
|
|
|
# THE INDEPENDENT ASSERTION: which peers actually reached this process.
|
|
peers="$(grep -o 'CONNECT from [0-9.]*' "$LOGFILE" 2>/dev/null | awk '{print $3}' | sort -u || true)"
|
|
remote="$(grep -v '^127\.' <<<"$peers" | grep -v '^$' || true)"
|
|
both " peers: $(tr '\n' ' ' <<<"$peers")"
|
|
if [[ -n "$remote" ]]; then
|
|
both " REMOTE peer(s) reached the Rust sidecar: $(tr '\n' ' ' <<<"$remote")"
|
|
both " => the client's Blaze traffic observably landed on Rust"
|
|
else
|
|
both " no remote peer connected — only loopback (or nothing) reached Rust"
|
|
both " => a FIFA session did NOT land here"
|
|
fi
|
|
|
|
# Session shape, straight from the log.
|
|
logins="$(grep -c 'Authentication::login .*REPLY' "$LOGFILE" 2>/dev/null || echo 0)"
|
|
notifs="$(grep -c 'UserSessions::<' "$LOGFILE" 2>/dev/null || echo 0)"
|
|
both " login replies: $logins UserSessions notifications: $notifs"
|
|
both " close reasons:"
|
|
grep -o 'CLOSE after [0-9]* frame(s): .*' "$LOGFILE" 2>/dev/null \
|
|
| sort | uniq -c | sed 's/^/ /' | tee -a "$DEST/summary.txt" || true
|
|
|
|
# Anything that looks wrong.
|
|
probs="$(grep -E 'DECODE FAILED|REJECT|FAILED|absurd' "$LOGFILE" 2>/dev/null | head -20 || true)"
|
|
if [[ -n "$probs" ]]; then
|
|
both " ANOMALIES:"
|
|
sed 's/^/ /' <<<"$probs" | tee -a "$DEST/summary.txt"
|
|
else
|
|
both " no anomalies in the log"
|
|
fi
|
|
fi
|
|
|
|
# ------------------------------------------------------------------ trace
|
|
both ""
|
|
both "--- TRACE ---"
|
|
if [[ -n "$TRACE" && -f "$TRACE" ]]; then
|
|
cp "$TRACE" "$DEST/rust-blaze.trace"
|
|
frames="$(grep -c '^conn-' "$TRACE" 2>/dev/null || echo 0)"
|
|
both " $TRACE -> $DEST/rust-blaze.trace ($frames traced frames)"
|
|
both " routes seen:"
|
|
grep -o '^conn-[0-9]* \(RX\|TX\) [^ ]* [A-Za-z]*::[^ ]*' "$TRACE" 2>/dev/null \
|
|
| awk '{print $2, $4}' | sort | uniq -c | sort -rn | head -20 \
|
|
| sed 's/^/ /' | tee -a "$DEST/summary.txt" || true
|
|
else
|
|
both " no trace configured (set OPENFUT_BLAZE_TRACE before starting the sidecar)"
|
|
fi
|
|
|
|
# ----------------------------------------------------------- python health
|
|
both ""
|
|
both "--- PYTHON BACKEND (must stay healthy throughout) ---"
|
|
if contract="$(cd "$ROOT/fifa17-recon" && timeout 120 python3 tools/test_fut_contract.py 2>&1 | tail -1)"; then
|
|
both " contract suite: $contract"
|
|
else
|
|
both " contract suite: FAILED TO RUN"
|
|
fi
|
|
|
|
both ""
|
|
both "evidence bundle: $DEST"
|