Files
Gestion-des-Marches-RLA/.agents/verify-rla-api.sh
T

85 lines
4.2 KiB
Bash

#!/bin/bash
# .agents/verify-rla-api.sh
# Hook Stop Antigravity pour rla-api.
# Bloque la fin de tour tant que l'appli n'est pas reellement verifiee (pas juste racontee).
# Ecrit toujours une preuve brute horodatee dans .agents/last-verify.log,
# lisible directement par Claude sans reconstruire toute la chaine de verification.
#
# Contrat Stop hook Antigravity : stdout DOIT etre un JSON avec "decision".
# "continue" = force l'agent a reprendre la main (echec, "reason" est injecte comme message systeme).
# Toute autre valeur = laisse terminer normalement.
set -uo pipefail
LOGDIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
LOGFILE="$LOGDIR/last-verify.log"
TS="$(date -u +"%Y-%m-%dT%H:%M:%SZ")"
FAIL=0
REASONS=()
run() { ssh nas "$1" 2>&1; }
{
echo "=== Verification rla-api - $TS ==="
echo "-- 1. Etat conteneur --"
STATUS="$(run "docker ps --filter name=rla-api --format '{{.Status}}'")"
echo "$STATUS"
if [[ "$STATUS" != *"healthy"* ]]; then
FAIL=1; REASONS+=("conteneur rla-api pas healthy (etat observe: ${STATUS:-aucun conteneur trouve})")
fi
echo "-- 2. .env interne au conteneur == .env compose (piege dotenv override deja rencontre) --"
ENV_COMPOSE="$(run "grep -E '^BASEROW_API_URL=' /volume1/docker/rla-api/.env")"
ENV_INTERNE="$(run "docker exec rla-api cat /app/.env 2>/dev/null | grep -E '^BASEROW_API_URL='")"
echo "compose: $ENV_COMPOSE"
echo "interne: $ENV_INTERNE"
if [[ -z "$ENV_INTERNE" || "$ENV_COMPOSE" != "$ENV_INTERNE" ]]; then
FAIL=1; REASONS+=(".env interne absent ou different du .env compose (cf runbook pdfkit/dotenv, meme classe de piege)")
fi
echo "-- 3. Auth + endpoint /api/synthese repond avec des donnees --"
JWT_SECRET="$(run "grep -E '^JWT_SECRET=' /volume1/docker/rla-api/.env | cut -d= -f2-")"
TOKEN=""
if [[ -n "$JWT_SECRET" ]]; then
b64url() { openssl base64 -A | tr '+/' '-_' | tr -d '='; }
HEADER=$(printf '{"alg":"HS256","typ":"JWT"}' | b64url)
EXP=$(( $(date +%s) + 600 ))
PAYLOAD=$(printf '{"id":1,"username":"nabil","role":"superadmin","region":"all","exp":%d}' "$EXP" | b64url)
SIG=$(printf '%s' "${HEADER}.${PAYLOAD}" | openssl dgst -sha256 -hmac "$JWT_SECRET" -binary | b64url)
TOKEN="${HEADER}.${PAYLOAD}.${SIG}"
API_OUT="$(run "curl -s --max-time 10 -H 'Authorization: Bearer $TOKEN' http://172.17.0.1:3005/api/synthese")"
echo "${API_OUT:0:400}"
API_COUNT="$(printf '%s' "$API_OUT" | grep -o '\"count\":[0-9]*' | head -1 | grep -o '[0-9]*')"
if [[ -z "$API_COUNT" || "$API_COUNT" -lt 1 ]]; then
FAIL=1; REASONS+=("endpoint /api/synthese ne renvoie pas de donnees exploitables")
fi
else
FAIL=1; REASONS+=("JWT_SECRET introuvable dans .env, impossible de tester l'API authentifiee")
fi
echo "-- 4. Export PDF synthese : coherence titre annonce vs lignes reellement extraites --"
if [[ -n "$TOKEN" ]] && run "command -v pdftotext" >/dev/null 2>&1; then
run "curl -s --max-time 15 -H 'Authorization: Bearer $TOKEN' 'http://172.17.0.1:3005/api/export/pdf?view=synthese' -o /tmp/verify-rla-api.pdf"
PDFTXT="$(run "pdftotext -layout /tmp/verify-rla-api.pdf - 2>/dev/null")"
ANNONCE="$(printf '%s' "$PDFTXT" | grep -oE 'Top [0-9]+ Alertes' | grep -oE '[0-9]+' | head -1)"
REELLES="$(printf '%s' "$PDFTXT" | grep -c 'CRITIQUE')"
echo "titre annonce: ${ANNONCE:-?} lignes | lignes reellement extraites: ${REELLES:-0}"
if [[ -n "$ANNONCE" && "${REELLES:-0}" -lt "$ANNONCE" ]]; then
FAIL=1; REASONS+=("PDF synthese : titre annonce $ANNONCE lignes mais $REELLES extraites (regression classe widthOfString/troncature)")
fi
else
echo "pdftotext absent sur cette machine (ou token manquant) - check ignore. Installer poppler-utils pour une couverture complete."
fi
echo "=== Resultat : $([[ $FAIL -eq 0 ]] && echo OK || echo ECHEC) ==="
} > "$LOGFILE" 2>&1
if [[ $FAIL -eq 1 ]]; then
REASON_TXT="Verification automatique echouee : $(IFS='; '; echo "${REASONS[*]}"). Preuve complete dans .agents/last-verify.log. Corrige avant de conclure, puis relance la verification."
ESCAPED=$(printf '%s' "$REASON_TXT" | python3 -c 'import json,sys;print(json.dumps(sys.stdin.read()))' 2>/dev/null || printf '"%s"' "$REASON_TXT")
printf '{"decision":"continue","reason":%s}\n' "$ESCAPED"
else
printf '{"decision":"stop"}\n'
fi