← back to AbramsEgo
scripts/smoke.sh
96 lines
#!/bin/bash
# scripts/smoke.sh — fast (<10s) no-deps regression net for the AbramsEgo dashboard.
#
# Curls /api/data on the RUNNING instance (:9773) and asserts the contract the
# SPEC panels depend on. Run this FIRST in any audit/replenish pass instead of
# re-deriving curl checks. Exits non-zero and names the failing assertion.
#
# Env overrides: ABRAMSEGO_BASE, ABRAMSEGO_USER, ABRAMSEGO_PASS.
set -u
BASE="${ABRAMSEGO_BASE:-http://127.0.0.1:9773}"
AUSER="${ABRAMSEGO_USER:-admin}"
APASS="${ABRAMSEGO_PASS:-DW2024!}"
TMP="$(mktemp)"
trap 'rm -f "$TMP"' EXIT
CODE=$(curl -s -m 8 -o "$TMP" -w '%{http_code}' -u "$AUSER:$APASS" "$BASE/api/data") || {
echo "FAIL http_reachable — curl could not reach $BASE/api/data"; exit 1; }
[ "$CODE" = "200" ] || { echo "FAIL http_200_with_auth — got HTTP $CODE"; exit 1; }
python3 - "$TMP" <<'PY'
import json, sys
def fail(name, detail=''):
print(f"FAIL {name}" + (f" — {detail}" if detail else ''))
sys.exit(1)
try:
d = json.load(open(sys.argv[1]))
except Exception as e:
fail('json_parse', str(e))
KEYS = ['activity', 'canaries', 'cost', 'crons', 'kamatera', 'localFleet',
'officers', 'pnl', 'revenue', 'sessions', 'system', 'usage',
'usageSummary', 'wins']
missing = [k for k in KEYS if k not in d]
if missing:
fail('all_14_top_level_keys', 'missing: ' + ', '.join(missing))
jobs = (d['crons'] or {}).get('jobs') or []
if len(jobs) <= 100:
fail('crons_length_gt_100', f'got {len(jobs)}')
# Provider COUNT is data-driven (30-day ledger window) — 4 vs 5 providers is
# normal drift, not a regression. The panel contract is: non-empty list whose
# entries carry provider+total.
prov = (d['cost'] or {}).get('byProvider') or []
if not prov:
fail('cost_byProvider_nonempty', 'empty byProvider list')
bad = [p for p in prov if not p.get('provider') or not isinstance(p.get('total'), (int, float))]
if bad:
fail('cost_byProvider_shape', f'{len(bad)} entries missing provider/total')
cans = (d['canaries'] or {}).get('canaries') or []
nulls = [c.get('name', '?') for c in cans if c.get('verdict') is None]
if nulls:
fail('canaries_verdicts_nonnull', 'null verdict: ' + ', '.join(nulls))
if (d['localFleet'] or {}).get('error') is not None:
fail('localFleet_error_null', str(d['localFleet'].get('error')))
print(f"PASS — 200 auth, 14 keys, crons {len(jobs)}, providers {len(prov)}, "
f"canaries {len(cans)} all-verdict, localFleet clean")
PY
SMOKE_RC=$?
[ "$SMOKE_RC" = "0" ] || exit "$SMOKE_RC"
# --- A2A security gate (TK-10381) — the activation gate MUST hold ------------
# The A2A client can consult EXTERNAL agents; these assertions prove the feature
# ships OFF and safe: empty allowlist = zero egress possible, and the payload
# linter keeps secrets from ever leaving. If any of these fail, the gate has
# regressed (someone opened the allowlist or dropped the linter) — investigate.
A2A_AGENTS=$(curl -s -m 8 -u "$AUSER:$APASS" "$BASE/api/a2a/agents")
# By default the gate must be CLOSED (empty allowlist). Once Steve intentionally
# activates a peer (see memos/a2a-activation-runbook.md), set A2A_EXPECT_PEERS=1
# so this stops false-alarming — the two gate-MECHANISM checks below still run.
if [ "${A2A_EXPECT_PEERS:-0}" = "1" ]; then
echo "NOTE a2a_allowlist — peers intended (A2A_EXPECT_PEERS=1): $A2A_AGENTS"
else
echo "$A2A_AGENTS" | grep -q '"agents":\[\]' || {
echo "FAIL a2a_allowlist_empty — allowlist non-empty but A2A_EXPECT_PEERS!=1 (gate opened unexpectedly?): $A2A_AGENTS"; exit 1; }
fi
A2A_REFUSE=$(curl -s -m 8 -u "$AUSER:$APASS" -X POST -H 'Content-Type: application/json' \
-d '{"agent":"__smoke_nobody__","q":"ping"}' "$BASE/api/a2a/consult")
echo "$A2A_REFUSE" | grep -q 'not in allowlist' || {
echo "FAIL a2a_gate_refuses_unlisted — expected 'not in allowlist', got: $A2A_REFUSE"; exit 1; }
A2A_LINT=$(curl -s -m 8 -u "$AUSER:$APASS" -X POST -H 'Content-Type: application/json' \
-d '{"agent":"__smoke_nobody__","q":"my ANTHROPIC_API_KEY=sk-ant-smoke"}' "$BASE/api/a2a/consult")
echo "$A2A_LINT" | grep -q 'payload blocked' || {
echo "FAIL a2a_payload_linter — expected 'payload blocked', got: $A2A_LINT"; exit 1; }
echo "PASS a2a — allowlist empty (gate holds, zero egress), unlisted agent refused, payload linter armed"