% Raport de testare a integrării — DiDi Lot 1 (AI) ↔ Lot 2 (Backend) % PNRR DIGI150 · contract 11.1.i3.c9 % Data testării: 2026-07-09 --- # 1. Obiect și scop Prezentul raport documentează **testele de integrare** dintre **Lotul 2 — Backend** (motorul de analiză `agent-v3` + `didiFramework` + workeri) și **Lotul 1 — Platforma AI** (modelele LLM, deepfake, transcriere, extractoare, forensic, brain/RAG, domain-check). Raportul de testare a API-ului Lotului 2 (`03_Raport_Testare_API_Lot2`) acoperă **strict Lotul 2** și menționează explicit că serviciile AI (Lotul 1) „sunt testate separat, prin testele de integrare". Documentul de față **este acea probă**: demonstrează pe mediul live că cele două loturi **colaborează** — de la conectivitate punct-la-punct până la producerea unui verdict complet pe fiecare tip de conținut, plus proprietățile de reziliență și securitate ale integrării. Testarea confirmă cerințele din caietul de sarcini privind consumul de **extractoare specializate** (deepfake, NER, OCR, Whisper, YOLO), **modulul web-crawl/evidence**, **scorul de credibilitate a sursei** și **orchestrarea fluxurilor ML end-to-end** prin backend. --- # 2. Metodologie Testarea a fost efectuată pe platforma live (``, 2× H200), **non-distructiv**, printr-un harness reproductibil (`scripts/integration/run-integration-tests.sh`) structurat pe **trei niveluri**: - **Nivel A — Conectivitate & contract.** Din interiorul containerului `agent-v3` (consumatorul real), fiecare serviciu Lot 1 este sondat prin `didi-network`, pe nume de container (nu IP). Dovedește că boundary-ul de rețea și contractul HTTP funcționează. - **Nivel B — End-to-end pe tip de conținut.** Pentru fiecare din cele 5 tipuri (text, URL, imagine, audio, video) se lansează o analiză reală prin `POST /api/v3/pipeline/analyze-async` și se așteaptă verdictul persistat. Dovedește orchestrarea completă Lot2→Lot1→verdict. - **Nivel C — Proprietăți transversale.** Fail-open (degradare grațioasă la indisponibilitatea unui serviciu AI), rutarea către modelul LLM local (fără fallback plătit) și enforcement-ul gateway-ului peste lanțul AI. Fiecare test capturează **trei artefacte independente**: (1) request-ul emis de `agent-v3`, (2) **access-log-ul serviciului Lot 1** care dovedește primirea cererii, (3) **verdictul persistat în PostgreSQL** (`bos_analysis.analysis_session`). Toate artefactele brute sunt salvate în `scripts/integration/results/evidence_/`. Utilizatorul de test are credite alocate; strategia de dispatch este cea de producție (cozi RabbitMQ + workeri Docker + agregator de verdict). --- # 3. Rezultate | Metric | Valoare | |---|---| | Teste de integrare rulate | **17** | | — Nivel A (conectivitate) | 9 | | — Nivel B (end-to-end) | 5 | | — Nivel C (transversale) | 3 | | **PASS** | **16** | | **DEGRADED** (fail-open, comportament corect) | **1** | | **FAIL** | **0** | | Defecte identificate și remediate | 1 (Lot 1 — vezi §4) | ## 3.1 Nivel A — Conectivitate agent-v3 → servicii Lot 1 Toate cele 9 integrări din documentația de arhitectură (§9) răspund din chiar consumatorul `agent-v3`, pe `didi-network`: | # | Serviciu Lot 1 | Adresă (didi-network) | Cerință acoperită | Rezultat | |---|---|---|---|---| | A1 | LLM text (Qwen 3.5) | `llm-api:14011` | flux LLM / ML | **PASS** (HTTP 200, model `qwen3.5` încărcat) | | A2 | LLM vision / OCR | `llm-api:14011` | extractor OCR | **PASS** (`qwen3.5` vision-capable) | | A3 | Whisper transcriere | `audio-api:54300` | extractor Whisper | **PASS** (HTTP 200) | | A4 | BusterX deepfake | `video-api:54600` | extractor deepfake | **PASS** (HTTP 200) | | A5 | Extractoare | `extractors:54400` | NER/YOLO/OCR/EXIF | **PASS** (HTTP 200) | | A6 | Forensic media | `forensic:8080` | analiză forensică | **PASS** (HTTP 200) | | A7 | Web / evidence | `web-api:51100` | modul web-crawl | **PASS** (HTTP 200) | | A8 | Brain / RAG | `brain-api:8090` | flux ML fact-check | **PASS** (HTTP 200) | | A9 | Domain-check (T4) | `domain-check-api:11000` | scor credibilitate sursă | **PASS** (`POST /check/check` → `risk_score` real) | ## 3.2 Nivel B — Analize end-to-end (pipeline complet → verdict) Fiecare analiză a rulat prin cozile RabbitMQ și workerii de producție, verdictul fiind persistat în PostgreSQL. Coloana „Dovada Lot 1" citează access-log-ul serviciului apelat. | # | Input | Lanț Lot 1 | Verdict (scor/categorie) | Dovada Lot 1 | Rezultat | |---|---|---|---|---|---| | B1 | Text dezinformare (microcipuri 5G) | llm-api | **DISINFORMATION / 92** | `POST /v1/chat/completions 200` | **PASS** | | B2 | URL (bbc.com/news) | web + domain-check | **RELIABLE / 7** | `POST /api/v1/check/check 200` | **PASS** | | B3 | Imagine (titlu fals) | vision-OCR + extractoare | **DISINFORMATION / 95** | `POST /v1/chat/completions 200` (OCR a citit titlul) | **PASS** | | B4 | Audio (discurs) | Whisper → llm | **RELIABLE / 0** | `POST /v1/audio/transcriptions 200` | **PASS** | | B5 | Video | media-preprocess → BusterX | **RELIABLE / 5** | `POST /analyze/video 200` | **PASS** | > Nota B3: OCR-ul local (Qwen vision) a extras corect textul titlului fabricat din imagine, > iar pipeline-ul l-a clasificat DISINFORMATION — dovadă directă a lanțului vision→verdict. > Nota B5: verdict obținut după remedierea defectului D1 (vezi §4); BusterX a răspuns `200`. ## 3.3 Nivel C — Proprietăți transversale | # | Test | Cerință | Rezultat | |---|---|---|---| | C1 | **Fail-open**: `didiAI-web-api` oprit temporar, analiză lansată | reziliență / fail-open servicii AI | **DEGRADED** — analiza s-a **terminat** cu degradare grațioasă (`status=completed`), fără eșec; serviciul a fost repornit | | C2 | **Rutare model local**: analiză text | flux LLM local, fără fallback plătit | **PASS** — 5 apeluri către `llm-api:14011`, provider `qwen35` local; niciun apel OpenRouter plătit | | C3 | **Gateway**: `POST /pipeline/analyze-async` prin Kong fără token | API Gateway + securitate | **PASS** — Kong răspunde **401**, păzind lanțul AI | Rezultatul **DEGRADED** la C1 este comportamentul **corect și dorit**: afirmația de reziliență din documentația de arhitectură (§6, „fail-open pe servicii AI") este validată empiric — indisponibilitatea unui serviciu Lot 1 nu blochează analiza. --- # 4. Defecte identificate și remediate Testarea de integrare a identificat **1 defect real** (în Lotul 1), remediat și re-testat: | # | Severitate | Serviciu | Defect | Cauză rădăcină | Remediere | Verificare | |---|---|---|---|---|---|---| | **D1** | major | `didiAI-video-api` (BusterX), Lot 1 | `POST /analyze/video` → **500**; detecția deepfake nu rula (mascată de fail-open, care producea totuși verdict) | Bind-mount **stale** pe `/app/runs`: directorul host `local_gpu_stack/runs` fusese recreat după pornirea containerului → inode container (`6195429`) ≠ inode host (`6195434`) → `os.makedirs('/app/runs/')` eșua cu `FileNotFoundError` | `docker restart didiAI-video-api` (re-rezolvă bind-mount-ul la inode-ul curent) | Inode host == container (`6195434`); test de scriere OK; `POST /analyze/video` → **200**; verdict video RELIABLE/5 | Observație importantă: defectul era **mascat** de mecanismul fail-open — analiza video se finaliza cu verdict, dar BusterX nu se executa efectiv. Doar inspecția access-log-ului serviciului Lot 1 (parte din metodologia acestui raport) a expus problema. ## 4.1 Măsuri de robustețe adăugate (ca defectul să nu se repete și să nu mai fie tăcut) Pe lângă remedierea imediată, au fost adăugate două măsuri durabile: 1. **Healthcheck de scriere pe `video-api` (Lot 1).** Containerul `didiAI-video-api` a primit un healthcheck care **verifică efectiv scrierea în `/app/runs`** (nu doar `GET /health`). Un bind-mount stale îl face imediat `unhealthy` (vizibil în `docker ps` + dashboard), în loc să producă un `500` tăcut. `local_gpu_stack/docker-compose.yml`. 2. **Degradare vizibilă în verdict (Lot 2).** Când BusterX era activat dar nu a returnat rezultat, `media-preprocess-worker` scrie acum o santinelă `UNAVAILABLE`, iar `video-2-track.ts` o **semnalează explicit** în verdictul persistat: indicator `VID.2 „Verificare deepfake INDISPONIBILĂ — recomandată verificare manuală"` + `coupling_context.for_verdict.deepfake_check = "unavailable"` + `needs_manual_review = true`. Astfel un eșec al detecției deepfake **nu mai poate fi confundat** cu o verificare reușită. Verificat controlat (2 rulări video pe același clip): | Scenariu | `deepfake_check` | `needs_manual_review` | Indicator VID.2 | |---|---|---|---| | BusterX activ | *(absent)* | true | „BusterX deepfake detection: REAL" | | BusterX oprit | **`unavailable`** | true | „Verificare deepfake INDISPONIBILĂ — verificare manuală" | Fișiere: `agent-v3/src/queue/workers/media-preprocess-worker.ts`, `agent-v3/src/queue/workers/component-worker-helpers/video-2-track.ts`. --- # 5. Reflectarea integrării în specificația OpenAPI (Swagger) Integrarea cu Lotul 1 constă în dependențe **outbound** ale `agent-v3` (apeluri HTTP către servicii AI), nu în rute expuse de backend — prin urmare **nu** apare ca `paths` în specificația OpenAPI. A fost documentată, în schimb, prin două mecanisme: 1. **Endpoint de sondă de integrare** — `GET /api/v3/health/all` a fost extins să verifice **toate cele 9 servicii Lot 1** (pe lângă infrastructura internă), *fail-open*: o dependență AI indisponibilă produce `degraded` (HTTP 200), nu `unhealthy`. Endpoint-ul este documentat în `openapi.yaml` prin schema `DeepHealthResponse` și servește simultan ca **test de integrare live**, rulabil oricând. 2. **Bloc `x-integrations`** la nivel de specificație — listează cele 9 servicii Lot 1 consumate (cheie, variabilă de mediu, țintă pe `didi-network`, rol), contractul fail-open și sonda de health. Extensie OpenAPI validă, informativă. Ambele au fost validate cu `openapi-spec-validator` (rezultat: **VALID**, OpenAPI 3.0.3). Verificare live a sondei extinse: 14 dependențe (4 interne + 10 AI), toate `healthy`. --- # 6. Artefacte și reproducere | Artefact | Locație | |---|---| | Harness de testare (reproductibil) | `scripts/integration/run-integration-tests.sh` | | Fixturi (imagine, audio, video) | `scripts/integration/fixtures/` | | Rezultate structurate (JSON) | `scripts/integration/results/results_2026-07-09.json` | | Dovezi brute (access-log Lot 1, verdicte PG, health/all) | `scripts/integration/results/evidence_20260709_224124/` | | Sondă de integrare + schema OpenAPI | `agent-v3/openapi.yaml` (`x-integrations`, `DeepHealthResponse`) | | Tabel integrări Lot 1 | `docs/01_Arhitectura_Lot2.md` §9 | Rulare: `bash scripts/integration/run-integration-tests.sh` (variabile opționale: `AGENT_URL`, `TEST_USER`, `KONG_URL`). --- # 7. Concluzie Integrarea dintre **Lotul 2 (Backend)** și **Lotul 1 (Platforma AI)** este **funcțională și verificată end-to-end** pe mediul live: **16/17 teste PASS**, 1 DEGRADED (comportament fail-open corect), **0 FAIL**. Toate cele 9 servicii AI sunt raggiunse și consumate corect; cele 5 tipuri de conținut produc verdicte complete; reziliența (fail-open), rutarea către modelul local și enforcement-ul gateway-ului sunt confirmate. Singurul defect identificat (D1 — bind-mount stale pe BusterX) a fost remediat și re-testat cu succes. Integrarea Lot1↔Lot2 este **conformă și verificabilă**, iar starea ei live este observabilă permanent prin `GET /api/v3/health/all`.