livrare lot 2

This commit is contained in:
EVOTECH IT SRL 2026-07-10 03:39:53 -07:00
commit 8ecc78e729
763 changed files with 164593 additions and 0 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

Binary file not shown.

View file

@ -0,0 +1,275 @@
#!/usr/bin/env bash
# =============================================================================
# DiDi — Teste de integrare Lot 1 (Platforma AI) <-> Lot 2 (Backend)
# =============================================================================
# Demonstreaza ca cele doua loturi colaboreaza pe mediul live, non-distructiv.
#
# Trei niveluri:
# A. Conectivitate & contract — agent-v3 ajunge la fiecare serviciu Lot 1
# B. End-to-end pe tip de continut — pipeline complet -> verdict persistat
# C. Proprietati transversale — fail-open, rutare model local, gateway
#
# Fiecare test capteaza 3 artefacte: (1) request-ul, (2) access-log-ul
# serviciului Lot 1 care dovedeste primirea, (3) verdictul persistat in PG.
#
# Utilizare: bash run-integration-tests.sh
# Rezultate: results/results_<timestamp>.json + results/evidence_<timestamp>/
# =============================================================================
set -uo pipefail
# --- Config -----------------------------------------------------------------
AGENT="${AGENT_URL:-http://localhost:24803}"
KONG="${KONG_URL:-http://127.0.0.1:18000}"
KC="${KEYCLOAK_URL:-http://localhost:28080}"
USER_ID="${TEST_USER:-14142351-ad1e-466b-ac5d-4a7a0ff562bf}"
PG_C="${PG_CONTAINER:-didi-postgres}"
POLL_MAX="${POLL_MAX:-60}" # nr. maxim de poll-uri
POLL_INT="${POLL_INT:-3}" # secunde intre poll-uri
HERE="$(cd "$(dirname "$0")" && pwd)"
FIX="$HERE/fixtures"
TS="$(date +%Y%m%d_%H%M%S)"
OUT="$HERE/results"
EVID="$OUT/evidence_$TS"
RESULTS="$OUT/results_$TS.json"
mkdir -p "$EVID"
PASS=0; FAIL=0; DEGR=0
echo "[]" > "$RESULTS"
# --- Helpers ----------------------------------------------------------------
pg() { docker exec "$PG_C" psql -U bos_interface -d DIDI -tA -c "$1" 2>/dev/null; }
# extrage un camp dintr-un JSON de pe stdin: jget '<path python>' ex: "data.status"
jget() { python3 -c "import sys,json;
try: d=json.load(sys.stdin)
except: print(''); sys.exit()
for k in '$1'.split('.'):
d = d.get(k, '') if isinstance(d, dict) else ''
print(d if d is not None else '')"; }
# inregistreaza un rezultat de test in JSON-ul agregat
rec() { # id level name requirement target status detail evidence_file
python3 - "$RESULTS" "$@" <<'PY'
import json,sys
f=sys.argv[1]; ida,lvl,name,req,tgt,st,detail,ev=sys.argv[2:10]
data=json.load(open(f))
data.append({"id":ida,"level":lvl,"name":name,"requirement":req,
"target":tgt,"status":st,"detail":detail,"evidence":ev})
json.dump(data,open(f,'w'),ensure_ascii=False,indent=2)
PY
case "$6" in PASS) PASS=$((PASS+1));; DEGRADED) DEGR=$((DEGR+1));; *) FAIL=$((FAIL+1));; esac
printf ' [%-8s] %-4s %s\n' "$6" "$1" "$3"
}
# probe de conectivitate din INTERIORUL agent-v3 (consumatorul real), via node fetch
probe_from_agent() { # url -> printeaza "STATUS <code>" sau "ERR <msg>"
docker exec didi-agent-v3 node -e "
fetch('$1',{signal:AbortSignal.timeout(6000)})
.then(r=>{console.log('STATUS '+r.status)})
.catch(e=>{console.log('ERR '+e.message)})" 2>/dev/null
}
# lanseaza o analiza async si asteapta verdictul; printeaza JSON-ul result
analyze() { # media_type json_body
local body="$2"
local resp sid st
resp="$(curl -sk --max-time 30 -X POST "$AGENT/api/v3/pipeline/analyze-async" \
-H 'Content-Type: application/json' -d "$body" 2>/dev/null)"
sid="$(echo "$resp" | jget 'data.session_id')"
if [ -z "$sid" ]; then echo "{\"error\":\"dispatch_failed\",\"raw\":$(echo "$resp"|python3 -c 'import sys,json;print(json.dumps(sys.stdin.read()))')}"; return; fi
local i=0
while [ $i -lt "$POLL_MAX" ]; do
st="$(curl -sk --max-time 10 "$AGENT/api/v3/pipeline/$sid/queue-status" | jget 'data.status')"
[ -z "$st" ] && st="$(curl -sk --max-time 10 "$AGENT/api/v3/pipeline/$sid/queue-status" | jget 'status')"
if [ "$st" = "completed" ] || [ "$st" = "failed" ]; then break; fi
sleep "$POLL_INT"; i=$((i+1))
done
curl -sk --max-time 10 "$AGENT/api/v3/pipeline/$sid/result"
echo "$sid" > /tmp/.last_sid
}
# upload un fisier media -> printeaza public_url
upload_media() { # filepath
curl -sk --max-time 60 -X POST "$AGENT/api/v3/media/upload" \
-F "file=@$1" -F "user_id=$USER_ID" 2>/dev/null | jget 'data.public_url'
}
echo "============================================================"
echo " DiDi — Teste integrare Lot1<->Lot2 $TS"
echo " Agent: $AGENT User: ${USER_ID:0:8}... Evidence: $EVID"
echo "============================================================"
# =============================================================================
# NIVEL A — Conectivitate & contract (agent-v3 -> servicii Lot 1)
# =============================================================================
echo; echo "### NIVEL A — Conectivitate din agent-v3 catre serviciile Lot 1"
declare -A A_SVC=(
[A1]="llm-api:14011|/health|LLM text (Qwen3.5)|extractoare/flux LLM"
[A3]="audio-api:54300|/health|Whisper transcriere|extractor Whisper"
[A4]="video-api:54600|/health|BusterX deepfake|extractor deepfake"
[A5]="extractors:54400|/health|EXIF/NER/YOLO/OCR|extractoare NER/YOLO/OCR"
[A6]="forensic:8080|/health|forensic media|analiza forensica media"
[A7]="web-api:51100|/health|cautare web claims|modul web-crawl/evidence"
[A8]="brain-api:8090|/health|RAG/fact-check cache|flux ML fact-check"
)
for id in A1 A3 A4 A5 A6 A7 A8; do
IFS='|' read -r hp path label req <<< "${A_SVC[$id]}"
out="$(probe_from_agent "http://$hp$path")"
echo "$id $hp$path -> $out" >> "$EVID/A_connectivity.log"
if echo "$out" | grep -q "STATUS 200"; then
rec "$id" "A" "$label ($hp)" "$req" "$hp" "PASS" "$out" "A_connectivity.log"
else
rec "$id" "A" "$label ($hp)" "$req" "$hp" "FAIL" "$out" "A_connectivity.log"
fi
done
# A2 — LLM vision-capable: modelul qwen3.5 incarcat pe llm-api (rol vision)
models="$(docker exec didi-agent-v3 node -e "fetch('http://llm-api:14011/v1/models',{signal:AbortSignal.timeout(6000)}).then(r=>r.json()).then(d=>console.log(JSON.stringify(d))).catch(e=>console.log('ERR'))" 2>/dev/null)"
echo "A2 models: $models" >> "$EVID/A_connectivity.log"
if echo "$models" | grep -q 'qwen3.5'; then
rec "A2" "A" "LLM vision/OCR (llm-api)" "extractor OCR" "llm-api:14011" "PASS" "model qwen3.5 loaded" "A_connectivity.log"
else
rec "A2" "A" "LLM vision/OCR (llm-api)" "extractor OCR" "llm-api:14011" "FAIL" "$models" "A_connectivity.log"
fi
# A9 — domain-check T4: apel real POST /api/v1/check/check
dc="$(docker exec didi-agent-v3 node -e "
fetch('http://domain-check-api:11000/api/v1/check/check',{method:'POST',
headers:{'Content-Type':'application/json'},
body:JSON.stringify({domain:'google.com',check_options:{whois:true,dns:true,ssl:true}}),
signal:AbortSignal.timeout(30000)})
.then(r=>r.json()).then(d=>console.log(JSON.stringify({ok:d.success,risk:(d.data||{}).risk_score}))).catch(e=>console.log('ERR '+e.message))" 2>/dev/null)"
echo "A9 domain-check: $dc" >> "$EVID/A_connectivity.log"
if echo "$dc" | grep -q '"ok":true'; then
rec "A9" "A" "Domain-check T4 (WHOIS/DNS/SSL)" "scor credibilitate sursa" "domain-check-api:11000" "PASS" "$dc" "A_connectivity.log"
else
rec "A9" "A" "Domain-check T4 (WHOIS/DNS/SSL)" "scor credibilitate sursa" "domain-check-api:11000" "FAIL" "$dc" "A_connectivity.log"
fi
# =============================================================================
# NIVEL B — End-to-end pe tip de continut
# =============================================================================
echo; echo "### NIVEL B — Analize end-to-end (pipeline complet -> verdict)"
run_e2e() { # id name media_type body req logcontainer logpattern
local id="$1" name="$2" mt="$3" body="$4" req="$5" lc="$6" lp="$7"
local since res verdict cat score status sid
since="$(date -u +%Y-%m-%dT%H:%M:%S)"
res="$(analyze "$mt" "$body")"
sid="$(cat /tmp/.last_sid 2>/dev/null)"
echo "$res" > "$EVID/B_${id}_result.json"
status="$(echo "$res" | jget 'data.status')"; [ -z "$status" ] && status="$(echo "$res" | jget 'status')"
score="$(echo "$res" | jget 'data.risk_score')"; [ -z "$score" ] && score="$(echo "$res" | jget 'risk_score')"
cat="$(echo "$res" | jget 'data.risk_category')"; [ -z "$cat" ] && cat="$(echo "$res" | jget 'risk_category')"
# dovada access-log Lot 1
if [ -n "$lc" ]; then
docker logs --since "$since" "$lc" 2>&1 | grep -iE "$lp" | tail -5 > "$EVID/B_${id}_lot1_${lc}.log" 2>/dev/null
fi
# dovada verdict din PG
pg "SELECT input_type||'|'||status||'|'||COALESCE(risk_category,'')||'|'||COALESCE(risk_score::text,'') FROM bos_analysis.analysis_session WHERE session_id='$sid';" > "$EVID/B_${id}_pg.txt" 2>/dev/null
local pgrow; pgrow="$(cat "$EVID/B_${id}_pg.txt")"
if [ "$status" = "completed" ]; then
rec "$id" "B" "$name" "$req" "$mt" "PASS" "verdict=$cat score=$score | PG:$pgrow" "B_${id}_result.json"
else
rec "$id" "B" "$name" "$req" "$mt" "FAIL" "status=$status | PG:$pgrow" "B_${id}_result.json"
fi
}
# B1 — text dezinformare
run_e2e "B1" "Text dezinformare -> verdict LLM" "text" \
"{\"media_type\":\"text\",\"text\":\"OMS a confirmat oficial ca vaccinurile anti-COVID contin microcipuri 5G folosite pentru controlul mintal al intregii populatii prin unde radio.\",\"user_id\":\"$USER_ID\"}" \
"orchestrare + flux LLM" "didiAI-llm-api" "chat/completions"
# B2 — URL real (domeniu + web)
run_e2e "B2" "URL -> componenta domain + web" "url" \
"{\"media_type\":\"url\",\"url\":\"https://www.bbc.com/news\",\"user_id\":\"$USER_ID\"}" \
"web-crawl/evidence + credibilitate sursa" "didiAI-domain-check" "check/check"
# B3 — imagine (OCR/vision)
IMG_URL="$(upload_media "$FIX/fake_headline.jpg")"
echo "B3 image url: $IMG_URL" > "$EVID/B_B3_upload.txt"
run_e2e "B3" "Imagine -> OCR/vision + extractoare" "image" \
"{\"media_type\":\"image\",\"media_url\":\"$IMG_URL\",\"user_id\":\"$USER_ID\"}" \
"extractor OCR/vision" "didiAI-llm-api" "chat/completions"
# B4 — audio (Whisper)
AUD_URL="$(upload_media "$FIX/jfk_speech.wav")"
echo "B4 audio url: $AUD_URL" > "$EVID/B_B4_upload.txt"
run_e2e "B4" "Audio -> transcriere Whisper -> verdict" "audio" \
"{\"media_type\":\"audio\",\"media_url\":\"$AUD_URL\",\"user_id\":\"$USER_ID\"}" \
"extractor Whisper" "didiAI-audio" "transcriptions|POST"
# B5 — video (BusterX)
VID_URL="$(upload_media "$FIX/test_clip.mp4")"
echo "B5 video url: $VID_URL" > "$EVID/B_B5_upload.txt"
run_e2e "B5" "Video -> BusterX deepfake -> verdict" "video" \
"{\"media_type\":\"video\",\"media_url\":\"$VID_URL\",\"user_id\":\"$USER_ID\"}" \
"extractor deepfake" "didiAI-video-api" "POST|analyze|predict"
# =============================================================================
# NIVEL C — Proprietati transversale
# =============================================================================
echo; echo "### NIVEL C — Fail-open, rutare model local, gateway"
# C1 — FAIL-OPEN: opresc web-api, rulez o analiza, verific ca se TERMINA (degradat)
echo " [C1] opresc temporar didiAI-web-api pentru testul de fail-open..."
docker stop didiAI-web-api >/dev/null 2>&1
sleep 2
since="$(date -u +%Y-%m-%dT%H:%M:%S)"
res="$(analyze "text" "{\"media_type\":\"text\",\"text\":\"Presedintele a anuntat ieri o crestere economica de 15% intr-o singura luna, cel mai mare salt din istoria tarii.\",\"user_id\":\"$USER_ID\"}")"
echo "$res" > "$EVID/C1_failopen_result.json"
c1status="$(echo "$res" | jget 'data.status')"; [ -z "$c1status" ] && c1status="$(echo "$res" | jget 'status')"
docker start didiAI-web-api >/dev/null 2>&1
echo " [C1] didiAI-web-api repornit."
if [ "$c1status" = "completed" ]; then
rec "C1" "C" "Fail-open (web-api oprit -> analiza se termina)" "reziliza/fail-open servicii AI" "didiAI-web-api" "DEGRADED" "analiza completa fara web-api: status=$c1status" "C1_failopen_result.json"
else
rec "C1" "C" "Fail-open (web-api oprit -> analiza se termina)" "reziliza/fail-open servicii AI" "didiAI-web-api" "FAIL" "status=$c1status (nu a degradat gratios)" "C1_failopen_result.json"
fi
# C2 — RUTARE MODEL LOCAL: analiza text, dovada apel local qwen3.5, zero OpenRouter
since="$(date -u +%Y-%m-%dT%H:%M:%S)"
res="$(analyze "text" "{\"media_type\":\"text\",\"text\":\"Guvernul a decis marirea salariului minim incepand cu luna urmatoare, conform anuntului oficial.\",\"user_id\":\"$USER_ID\"}")"
sid="$(cat /tmp/.last_sid)"
docker logs --since "$since" didiAI-llm-api 2>&1 | grep -iE "chat/completions" | tail -5 > "$EVID/C2_llm_access.log"
llmhits="$(wc -l < "$EVID/C2_llm_access.log" 2>/dev/null | tr -d ' ')"
usage="$(pg "SELECT COALESCE(llm_usage::text,'{}') FROM bos_analysis.analysis_session WHERE session_id='$sid';")"
echo "$usage" > "$EVID/C2_llm_usage.json"
# provider din DB pentru modelul primar
prov="$(pg "SELECT p.provider_code||'|'||p.base_url FROM bos_parammgmt.llm_provider p JOIN bos_parammgmt.llm_model m ON m.provider_id=p.provider_id WHERE m.model_code='qwen3.5' LIMIT 1;")"
echo "provider: $prov" >> "$EVID/C2_llm_usage.json"
if [ "${llmhits:-0}" -ge 1 ] && echo "$prov" | grep -q 'llm-api:14011'; then
rec "C2" "C" "Rutare model local (Qwen3.5, fara fallback platit)" "flux LLM local" "llm-api:14011" "PASS" "llm-api hits=$llmhits provider=$prov" "C2_llm_access.log"
else
rec "C2" "C" "Rutare model local (Qwen3.5, fara fallback platit)" "flux LLM local" "llm-api:14011" "FAIL" "llm-api hits=$llmhits provider=$prov" "C2_llm_access.log"
fi
# C3 — GATEWAY: Kong pazeste lantul AI (401 fara token pe calea pipeline)
code_notoken="$(curl -sk --max-time 10 -H 'Host: localhost' -o /dev/null -w '%{http_code}' \
-X POST "$KONG/agent-v3/api/v3/pipeline/analyze-async" -H 'Content-Type: application/json' \
-d '{"media_type":"text","text":"aaaaaaaaaa","user_id":"x"}' 2>/dev/null)"
echo "Kong /agent-v3/.../analyze-async fara token -> $code_notoken" > "$EVID/C3_gateway.log"
if [ "$code_notoken" = "401" ]; then
rec "C3" "C" "Gateway Kong pazeste lantul AI (401 fara JWT)" "API Gateway + securitate" "kong:8000" "PASS" "analyze-async fara token -> $code_notoken" "C3_gateway.log"
else
rec "C3" "C" "Gateway Kong pazeste lantul AI (401 fara JWT)" "API Gateway + securitate" "kong:8000" "FAIL" "cod neasteptat: $code_notoken" "C3_gateway.log"
fi
# =============================================================================
# Sumar
# =============================================================================
echo; echo "============================================================"
echo " SUMAR: PASS=$PASS DEGRADED=$DEGR FAIL=$FAIL"
echo " JSON: $RESULTS"
echo " Dovezi: $EVID"
echo "============================================================"
python3 - "$RESULTS" "$PASS" "$DEGR" "$FAIL" "$TS" <<'PY'
import json,sys
f,p,d,fa,ts=sys.argv[1:6]
data=json.load(open(f))
out={"timestamp":ts,"summary":{"pass":int(p),"degraded":int(d),"fail":int(fa),"total":len(data)},"tests":data}
json.dump(out,open(f,'w'),ensure_ascii=False,indent=2)
print("Scris:",f)
PY