Livrare Lot 3 platforma DiDi - furnizor Evotech IT

Curatenie referinte pre-livrare:
- inlocuit IP intern 10.11.10.18 cu hostname didi.integrare.local (extensie, docker-compose, .env.example)
- inlocuit domeniu vechi didi365.eu cu didi.integrare.local (scripturi build/audit)
- redenumit identificatorul aplicatiei Android eu.didi365.mobile -> didi.mobile

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Dezvoltari Evotech 2026-07-17 03:01:23 -07:00
parent cec967f953
commit d289ff12e6
19 changed files with 17 additions and 843 deletions

View file

@ -1,4 +1,4 @@
# Adresa platformei DiDi (nginx frontend / gateway). Exemple:
# LAN integrare: http://10.11.10.18
# LAN integrare: http://didi.integrare.local
# Productie: https://didi.exemplu.ro
EXPO_PUBLIC_DIDI_BASE_URL=

View file

@ -87,9 +87,9 @@ android {
buildToolsVersion rootProject.ext.buildToolsVersion
compileSdk rootProject.ext.compileSdkVersion
namespace 'eu.didi365.mobile'
namespace 'didi.mobile'
defaultConfig {
applicationId 'eu.didi365.mobile'
applicationId 'didi.mobile'
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 1

View file

@ -1,4 +1,4 @@
package eu.didi365.mobile
package didi.mobile
import android.os.Build
import android.os.Bundle

View file

@ -1,4 +1,4 @@
package eu.didi365.mobile
package didi.mobile
import android.app.Application
import android.content.res.Configuration

0
android/didi-app-source/android/gradlew vendored Executable file → Normal file
View file

View file

@ -15,10 +15,10 @@
},
"ios": {
"supportsTablet": true,
"bundleIdentifier": "eu.didi365.mobile"
"bundleIdentifier": "didi.mobile"
},
"android": {
"package": "eu.didi365.mobile",
"package": "didi.mobile",
"adaptiveIcon": {
"foregroundImage": "./assets/adaptive-icon.png",
"backgroundColor": "#0d1424"

View file

@ -64,9 +64,9 @@ mediul LAN cu certificat autosemnat).
## Observații
- APK-ul e semnat cu cheie de test — pentru publicare în Google Play se generează un keystore
de release. Identificatorul aplicației (`eu.didi365.mobile`) este namespace-ul istoric al
proiectului; schimbarea lui ar crea o aplicație nouă (reinstalare obligatorie pentru
utilizatori) și se face doar la publicarea în store, dacă se dorește.
de release. Identificatorul aplicației este `didi.mobile`; la publicarea în store poate fi
schimbat, dar orice modificare ulterioară creează o aplicație nouă (reinstalare obligatorie
pentru utilizatori).
- Extensia are ID stabil (`blcalchooinkphpnlkkhlklbmgppmnfm`, fixat prin cheia din manifest);
pe acest ID este configurat clientul OIDC `didi-extension` în Keycloak (realm `didi-clients`,
redirect `https://<id>.chromiumapp.org/*`). La schimbarea mediului, clientul Keycloak se

2
build.sh Executable file → Normal file
View file

@ -47,7 +47,7 @@ Environment variables:
Examples:
./build.sh
./build.sh --api-url https://didi365.eu
./build.sh --api-url https://didi.integrare.local
./build.sh --image didi-frontend --tag v1.2.3
./build.sh --skip-verify --dry-run
EOF

View file

@ -1,5 +1,5 @@
# DiDi Frontend — deployment local pe serverul de integrare (10.11.10.18)
# Build: docker build --build-arg VITE_API_URL= --build-arg VITE_KEYCLOAK_URL=https://10.11.10.18/auth -t didi-frontend:local ./web
# DiDi Frontend — deployment local pe serverul de integrare (didi.integrare.local)
# Build: docker build --build-arg VITE_API_URL= --build-arg VITE_KEYCLOAK_URL=https://didi.integrare.local/auth -t didi-frontend:local ./web
# Run: docker compose -f docker-compose.local.yml up -d
name: didi-frontend

Binary file not shown.

View file

@ -1,269 +0,0 @@
% Ghid de utilizare — DiDi Lot 3 (Frontend)
% Aplicația web · Aplicația mobilă · Extensia de browser
% PNRR DIGI150 · contract 11.1.i3.c9
---
# 1. Introducere
Platforma DiDi analizează conținut (text, linkuri, imagini, audio, video) pentru semne de
dezinformare și returnează un **raport de analiză** cu: scor de risc (0100), verdict, grad de
certitudine, explicație, tehnici de manipulare detectate, verificarea afirmațiilor cu surse,
evaluarea sursei și detecția conținutului generat de AI.
Platforma se folosește prin **trei aplicații client**, cu **un singur cont** (autentificare unică):
| Aplicație | Când o folosești |
|---|---|
| **Aplicația web** | analiza completă, istoric, rapoarte PDF, administrarea contului |
| **Aplicația mobilă** | analiză din mers; partajezi conținut din orice aplicație direct către DiDi |
| **Extensia de browser** | verifici pagini, texte și imagini direct în timpul navigării |
**Contul tău:** același email + parolă funcționează în toate cele trei aplicații. Autentificarea
se face prin serverul securizat al platformei (Keycloak); aplicațiile nu văd și nu stochează
parola ta.
**Confidențialitate:** conținutul trimis este folosit exclusiv pentru generarea raportului de
analiză. Trimiterea fișierelor și a capturilor de ecran necesită **consimțământul tău explicit**,
cerut o singură dată. Poți șterge oricând analizele din Istoric.
---
# 2. Aplicația web
**Acces:** `https://10.11.10.18/` (sau adresa comunicată de administrator). La certificat
autosemnat, browserul afișează un avertisment — alege „Advanced" → „Continue".
## 2.1 Autentificare
1. Pe pagina de prezentare apasă **„Începe analiza"**.
2. Ești redirecționat către formularul de autentificare — introdu emailul și parola
(sau creează cont nou cu „Register"; recuperarea parolei — „Forgot password").
3. După autentificare ajungi în **Dashboard**.
![Formularul de autentificare](media_testare/web-02-login-keycloak.png){width=15cm}
## 2.2 Analiza completă
1. În meniul lateral alege **„Analiză completă"**.
2. Alege tab-ul potrivit conținutului: **Text / URL / Imagine / Audio / Video**.
3. Introdu conținutul: lipește textul sau linkul, ori selectează fișierul de pe disc.
4. Pentru fișiere: la prima trimitere bifează **consimțământul** (butonul de analiză rămâne
inactiv până atunci).
5. Apasă **„Rulează analiza completă"** și urmărește progresul pe componente.
![Formularul unificat cu cele 5 tipuri de conținut](media_testare/web-03-formular-unificat.png){width=15cm}
![Consimțământul pentru fișiere (o singură dată)](media_testare/web-04-consimtamant-upload.png){width=15cm}
![Analiza în desfășurare — progres pe componente](media_testare/web-05-progres-analiza.png){width=15cm}
## 2.3 Citirea raportului
Raportul afișează, de sus în jos:
- **Scorul de risc** (0100) cu inel colorat: verde = sigur … roșu = pericol;
- **Verdictul** (De încredere → Dezinformare), nivelul de risc și certitudinea;
- **Explicația** în limba română — rezumatul motivelor;
- **Acțiunea recomandată** (ex. „Nu distribui acest articol");
- **Cea mai gravă problemă**, cu citat-dovadă;
- Secțiuni expandabile cu detalii per componentă: tehnici de manipulare, afirmații verificate
(cu surse care susțin/contrazic), detecție AI, evaluarea sursei.
![Exemplu de raport: verdict, explicație, acțiune recomandată](media_testare/web-06-rezultat-verdict.png){width=15cm}
**Partajare și export:** butoanele **„Partajează"** (copiază un link către raport, accesibil
utilizatorilor autentificați) și **„Descarcă PDF"** se află în colțul din dreapta sus al
raportului.
![Butoanele Partajează și Descarcă PDF pe un raport](media_testare/web-07-rezultat-video-partajare.png){width=15cm}
## 2.4 Analize pe competențe individuale
Din meniul **„Abilități DIDI"** poți rula o singură componentă, mai rapid decât pipeline-ul
complet: **Tehnici de manipulare**, **Evaluarea sursei**, **Verificarea afirmațiilor**,
**Detectare AI** — fiecare cu propriul formular și ecran de rezultate.
![Competența „Detectare AI"](media_testare/web-08-competenta-detectare-ai.png){width=15cm}
## 2.5 Istoric
Meniul **„Istoric"** listează analizele tale: scor, verdict, tip conținut, dată. De aici poți:
- **filtra** după căutare în conținut, nivel de risc, status, tip de conținut, interval de date;
- deschide orice analiză anterioară (click pe element);
- descărca **PDF**-ul sau **șterge** analiza (cu confirmare).
![Istoricul cu rândul de filtre](media_testare/web-09-istoric-filtre.png){width=15cm}
## 2.6 Setări
Meniul **„Setări"**: profilul contului, **schimbarea parolei** (prin serverul de autentificare),
abonamentul și creditele. Tot aici descarci celelalte două aplicații:
- **Extensia de browser** — arhiva .zip + instrucțiuni de instalare pas cu pas;
- **Aplicația mobilă** — fișierul APK pentru Android.
Ambele sunt disponibile **pentru orice tip de abonament**.
![Setări: descărcarea extensiei și a aplicației mobile](media_testare/web-11-setari-descarcari.png){width=15cm}
---
# 3. Aplicația mobilă (Android)
## 3.1 Instalare și autentificare
1. Descarcă APK-ul din aplicația web (Setări → Aplicație mobilă) și deschide-l pe telefon
(acceptă instalarea din surse necunoscute, dacă ți se cere).
2. Telefonul trebuie să fie în aceeași rețea cu platforma.
3. Deschide **didi****Sign In** → introdu emailul și parola în formularul securizat.
![Autentificarea în aplicația mobilă](media_testare/mob-01-login-keycloak.png){width=7.5cm}
## 3.2 Analiza conținutului
Din **Dashboard****Analiză completă**: alege tab-ul (Text / Imagine / Audio / Video / URL),
introdu conținutul și apasă **„Rulează analiza completă"**.
![Dashboard-ul aplicației mobile](media_testare/mob-02-dashboard.png){width=7.5cm}
**Imagini cu decupare:** la tab-ul Imagine, după ce alegi poza din galerie sau o fotografiezi,
se deschide **editorul de decupare** — păstrezi doar regiunea relevantă, apoi confirmi. Imaginea
decupată apare în preview și se trimite la analiză.
![Imaginea decupată, gata de analiză](media_testare/mob-05-crop-imagine-preincarcata.png){width=7.5cm}
**Consimțământ:** la prima trimitere a unui fișier apare fereastra de consimțământ — bifează
acordul și continuă; nu se va mai cere data următoare.
![Consimțământul pentru încărcarea fișierelor](media_testare/mob-06-consimtamant.png){width=7.5cm}
Rezultatul se afișează în format optimizat pentru mobil: verdict + scor, secțiuni expandabile,
surse cu linkuri, recomandări.
![Raport de analiză pe mobil](media_testare/mob-07-rezultat.png){width=7.5cm}
## 3.3 Share-to-Analyze — analizează din orice aplicație
Cel mai rapid mod de a folosi DiDi pe telefon: **partajezi conținut direct către didi** din orice
aplicație (browser, social media, galerie, mesagerie):
1. În aplicația-sursă apasă **Share** și alege **didi** din listă.
2. DiDi deschide ecranul de analiză cu conținutul preluat — **link**, **text** sau **imagine**.
3. Alege tipul de analiză (completă sau o competență individuală) — analiza pornește imediat.
Dacă nu ești autentificat, aplicația te duce întâi la login și **revine automat** la analiza ta.
![Share dintr-o aplicație terță către didi](media_testare/mob-08-share-imagine-sursa.png){width=7.5cm}
![Conținutul partajat, cu opțiunile de analiză](media_testare/mob-09-share-imagine-ecran.png){width=7.5cm}
![Link partajat — inclusiv analiza domeniului](media_testare/mob-12-share-link.png){width=7.5cm}
## 3.4 Istoric și Setări
- **Istoric:** analizele tale, cu derulare infinită; analizele în curs se actualizează automat;
ștergerea cere confirmare; atingerea unui element deschide raportul complet.
- **Setări:** profil, schimbare parolă, limbă, opțiuni de analiză automată pentru linkurile
partajate din rețele sociale și **Deconectare** (revocă sesiunea de pe dispozitiv).
![Istoricul pe mobil](media_testare/mob-13-istoric.png){width=7.5cm}
![Deconectarea, din Setări](media_testare/mob-14-setari-deconectare.png){width=7.5cm}
---
# 4. Extensia de browser (Chrome / Edge)
## 4.1 Instalare
1. Din aplicația web → **Setări → Extensie browser****„Descarcă extensia (.zip)"**.
2. Dezarhivează arhiva într-un folder.
3. Deschide `chrome://extensions`, activează **Developer mode** (dreapta sus), apasă
**„Load unpacked"** și alege folderul dezarhivat.
![Extensia instalată în Chrome](media_testare/ext-01-instalare.png){width=13cm}
## 4.2 Autentificare
Deschide popup-ul extensiei (iconița **d** din bara Chrome) → **„Autentificare"** → se deschide
fereastra de login a platformei → introdu emailul și parola. După autentificare, emailul tău apare
în antetul popup-ului. **„Deconectare"** (jos) închide sesiunea.
![Popup-ul înainte de autentificare](media_testare/ext-02-popup-neconectat.png){width=9cm}
## 4.3 Ce poți analiza, direct din browser
Din **popup**:
- **Pagina curentă** — câmpul URL e precompletat; apasă „Pagina curentă" sau „Analizează URL";
- **Orice URL** — lipește-l în câmpul dedicat;
- **Text** — selectează textul în pagină înainte să deschizi popup-ul (e preluat automat) sau
lipește-l manual (max 5000 de caractere);
- **Screenshot** — trasezi o regiune pe ecran; extensia analizează exact ce ai selectat;
- **Record Video** — înregistrezi o regiune a paginii (ex. un clip din feed).
![Secțiunile de analiză din popup](media_testare/ext-04-popup-url-text.png){width=9cm}
Din **meniul contextual** (click-dreapta), fără să deschizi popup-ul:
- click-dreapta pe **o imagine** → „Analizează imaginea cu DiDi";
- click-dreapta pe **text selectat** → „Analizează textul selectat cu DiDi";
- click-dreapta oriunde în pagină → „Analizează pagina curentă cu DiDi".
![Meniul contextual pe o imagine](media_testare/ext-08-context-menu-imagine.png){width=15cm}
**Consimțământ:** la prima captură sau imagine trimisă apare fereastra de consimțământ direct în
pagină — „Sunt de acord" pornește analiza; alegerea se reține.
![Consimțământul pentru capturi](media_testare/ext-06-consimtamant.png){width=15cm}
**Captura cu selecție de regiune:** după „Screenshot", pagina se întunecă ușor — trage cu mouse-ul
peste zona de analizat; extensia decupează exact acea regiune.
![Selectarea regiunii de analizat](media_testare/ext-07-snipping-selectie.png){width=15cm}
## 4.4 Rezultatele
- Analizele pornite **din pagină** (screenshot, video, click-dreapta) afișează raportul ca
**fereastră peste pagină** când analiza e gata (3090 s).
- Analizele pornite **din popup** (text/URL) deschid raportul într-un **tab nou**.
- Raportul conține aceleași secțiuni ca în aplicația web: verdict cu scor, explicație completă,
detecție AI, afirmații verificate cu surse, evaluarea sursei.
![Raport de analiză în extensie — verdict și explicație](media_testare/ext-09-rezultat-verdict.png){width=12.5cm}
![Detecție AI și verificarea afirmațiilor](media_testare/ext-10-rezultat-componente.png){width=12.5cm}
## 4.5 Istoric
Butonul **„Istoric"** din popup deschide pagina cu ultimele analize (păstrate local, max 50) —
poți redeschide detaliile oricărei analize sau o poți șterge.
![Istoricul extensiei](media_testare/ext-12-istoric.png){width=15cm}
---
# 5. Întrebări frecvente
**Cum interpretez scorul?** 030 (verde) = conținut în general de încredere; 3160 (galben) =
îndoielnic, citește critic; 61100 (portocaliu/roșu) = risc ridicat — verifică sursele oficiale și
nu distribui.
**De ce un conținut cu afirmații adevărate poate primi verdict de risc ridicat?** Pentru că
riscul nu vine doar din afirmații: o imagine generată de AI care „ambalează" o știre reală este
o prezentare falsificată — sistemul o detectează și explică exact acest lucru în raport.
**Mi s-a epuizat creditul.** Fiecare analiză consumă credite în funcție de tipul conținutului
(text 1, imagine 2, video 5). La epuizare primești mesajul „Insufficient credits" — creditele se
reînnoiesc conform abonamentului (vezi Setări → Abonament).
**Analiza durează mult.** Textele durează secunde; imaginile ~3090 s; clipurile video pot dura
câteva minute (transcriere + analiză vizuală). Poți închide fereastra — rezultatul apare în
Istoric.
**Pot șterge o analiză?** Da — din Istoric (web/mobil: ștergere cu confirmare; extensie: ștergere
din pagina de istoric). Ștergerea elimină și conținutul asociat.
*Versiune document: 1.0 · 17.07.2026*

View file

@ -1,155 +0,0 @@
% Matrice de trasabilitate a cerințelor — DiDi Lot 3 (Frontend)
% PNRR DIGI150 · contract 11.1.i3.c9 · Contract de furnizare nr. 19
---
# 1. Scop
Prezentul document asigură **trasabilitatea** dintre cerințele contractuale (Caietul de sarcini,
secțiunea LOT 3 + Propunerea Tehnică Lot 3) și livrabilele efective ale Lotului 3:
**aplicația web**, **aplicația mobilă (Android/iOS)** și **extensia de browser**. Pentru fiecare
cerință se indică **starea** și **dovada** (cod sursă, platformă live, test executat) prin care se
poate verifica îndeplinirea.
Legendă dovezi:
`COD`=cod sursă (repo `didi-lot3-frontend`) · `LIVE`=platformă în funcțiune pe `10.11.10.18` ·
`TEST`=test executat la 15.07.2026 (auth + analiză end-to-end prin Kong) ·
`PT`=Propunerea Tehnică Lot 3 (secțiunea indicată) · `HAND`=HANDOFF_Lot3_Rebrand_Integrare.md.
Stare: ✅ conform · ⚠️ conform cu observație asumată (detaliat în §6).
Livrabile: app web LIVE `https://10.11.10.18/` · APK `~/didi-app-clossers.apk` ·
extensie `~/didi-extension-clossers.zip` (sau `didi-lot3-frontend/extension/`).
---
# 2. Componenta 1 — Aplicație Web (`web/`)
| # | Cerință (caiet de sarcini) | Stare | Dovadă |
|---|---|---|---|
| W1 | Trimitere conținut pentru analiză: text, URL, imagini, audio, video | ✅ | COD `PipelineAnalysis/sections/InputForm.tsx`, `AnalysisTab.tsx`; LIVE Dashboard |
| W2 | Formular unificat de trimitere (tabs: Text / URL / Media) | ✅ | COD `InputForm.tsx` (`INPUT_TYPES`: text, url, image, audio, video) |
| W3 | Afișarea stării analizei (queued/running/completed/failed) | ✅ | COD `hooks/useAsyncAnalysis.ts` (polling 2,5s, stări complete); PT §1.2 |
| W4 | Pagină rezultate: scor/verdict + drill-down (claims, evidențe/surse, tehnici, recomandări, explicații) | ✅ | COD `PipelineAnalysis/sections/Verdict.tsx` + `details/{techniques,claims,source,ai}.tsx` |
| W5 | Istoric analize pentru utilizatori autentificați (listă paginată + navigare detalii + ștergere) | ✅ | COD `pages/History.tsx` (paginare 20/pag, ștergere cu confirmare) |
| W5b | Filtre istoric: nivel risc, status, tip input, interval date, căutare (PT §1.2) | ⚠️ | COD `pages/History.tsx` (rând filtre complet; filtrare client-side — v. §6.4) |
| W6 | Export / partajare raport | ✅ | COD `Reports/DownloadPdfButton.tsx` (export PDF) + `Reports/ShareReportButton.tsx` (navigator.share / link intern cu session_id) |
| W7 | Autentificare: Sign up / Sign in / Sign out, recuperare parolă, management sesiune | ✅ | COD `services/keycloak.service.ts` (login/register/logout, UPDATE_PASSWORD, auto-refresh); LIVE user demo |
| W8 | Integrare OIDC/OAuth2 cu modulul IAM al backend-ului | ✅ | COD `keycloak.service.ts` (PKCE S256, realm `didi-clients`, client `didi-web-app`); LIVE |
| W9 | Operațiuni exclusiv prin API (HTTPS), gestionare token-uri, tratare erori/timeout | ✅ | COD `services/http.client.ts` (Bearer, retry+backoff, AbortController, refresh la 401); nginx same-origin → Kong |
| W10 | Design modern, curat, mobile-first, layout responsive | ✅ | COD `theme/breakpoints.ts`, `theme/tokens.ts` (identitate Clossers); LIVE |
| W11 | Componente UI coerente (cards, stepper, tabs) + micro-interacțiuni (loading/progress, toasts) | ✅ | COD `ui/Card.tsx`, `ui/Button.tsx`, `AnalysisTab` (stepper), `Toast/Toast.tsx` |
| W12 | WCAG 2.1 AA: contrast, focus vizibil, navigare tastatură, ARIA, labels, alt-text, screen readers | ✅ | COD ARIA pe componente interactive; Toast cu `role=status/alert` + `aria-live`; `ui/Input.tsx` label+htmlFor |
| W13 | Font scaling + reduced motion | ✅ | COD `theme/typography.ts` (px→rem, clamp pe titluri); `App.css` + `LandingPage.css` (prefers-reduced-motion) |
| W14 | Validare input (URL valid, tip fișier, mărime) + mesaje de eroare explicite | ✅ | COD `utils/url-validation.ts`, `utils/file-validation.ts` (MIME+extensii+limite 20/50/100MB), `text-validation.ts` |
| W15 | Protecție SSRF la input URL | ✅ | COD `utils/url-validation.ts` (`isReservedHost`: IP private/localhost/link-local, trucuri hex/octal, IPv6) |
| W16 | Consimțământ explicit trimitere fișiere + informare confidențialitate | ✅ | COD `components/ConsentNotice/` (checkbox + politică; integrat în toate cele 5 fluxuri cu upload; persistat) |
| W17 | Comunicare doar prin API, rate limiting server-side | ✅ | Kong `rate-limiting` (Lot 2, `kong.yml.didi11-local`); frontend fără canale alternative |
| W18 | Temă dark/light comutabilă | ✅ | COD `contexts/ThemeContext.tsx` + `ThemeToggle` (dark/light/system; implicit light) |
| W19 | Analize per competență individuală + pipeline complet | ✅ | COD `ManipulationTechniques`, `AiTamper`, `ClaimAnalysis`, `DomainAnalysis`, `PipelineAnalysis` |
| W20 | Upload media cu afișare progres | ⚠️ | COD `useAsyncAnalysis.ts` (stare `uploading` + bară de progres; procent euristic — v. §6.5) |
---
# 3. Componenta 2 — Aplicație Mobilă (`android/didi-app-source/`)
| # | Cerință (caiet de sarcini) | Stare | Dovadă |
|---|---|---|---|
| M1 | Funcționalitate echivalentă web: trimitere + analiză text/URL/imagine/audio/video, UI mobilă | ✅ | COD `screens/PipelineScreen.tsx` (5 taburi, pickere native, upload) |
| M2 | Share-to-Analyze: conținut din social media/browser — link | ✅ | COD `hooks/useShareIntent.ts`, `utils/shareIntent.ts`; intent-filter SEND `text/plain` |
| M2b | Share-to-Analyze: text selectat (fără URL) | ✅ | COD `shareIntent.ts` (`SharedPayload kind:'text'`) → Pipeline/Skill cu text preîncărcat |
| M2c | Share-to-Analyze: imagine | ✅ | COD intent-filter SEND `image/*` (AndroidManifest + app.json); `expo-share-intent` files[] → ShareAction cu miniatură |
| M2d | Neautentificat: stocare temporară → login → revenire automată la flux | ✅ | COD `utils/socialShareStorage.ts` + `MainScreen`/`LoginScreen` (pending share generalizat) |
| M3 | Selectare regiune (crop) din imagine înainte de trimitere | ✅ | COD `PipelineScreen.tsx` + `SkillAnalysisScreen.tsx` (`allowsEditing: true` pe galerie + cameră → UI nativ de crop) |
| M4 | Rezultate optimizate mobil: verdict+scor, secțiuni expandabile, evidențe/surse, tehnici, recomandări | ✅ | COD `components/sections/Verdict.tsx`, `editorial/CollapseButton.tsx`, `ActionCallout.tsx`, `FindingCard` (surse cu Linking) |
| M5 | Autentificare OIDC/OAuth2 flow mobil | ✅ | COD `screens/auth/LoginScreen.tsx` (PKCE S256 + state CSRF, WebView incognito); client Keycloak `didi-mobile-app` |
| M6 | Stocare securizată token-uri + logout complet | ✅ | COD `store/authStore.ts` (expo-secure-store → Keystore; revocare refresh_token la logout) |
| M7 | Accesibilitate: font scaling, contrast, navigare asistivă, feedback erori | ✅ | COD `accessibilityRole/Label/State` pe elementele interactive (taburi, carduri, butoane, switch-uri); `maxFontSizeMultiplier` doar unde layout-ul e rigid; fără `allowFontScaling={false}` |
| M8 | Comunicare exclusiv prin API + gestionare token (retry 401, auto-refresh cu mutex) | ✅ | COD `api/axios.ts` (interceptori request/response), `authStore.ts` (single-flight refresh) |
| M9 | Validare input + SSRF + mesaje explicite | ✅ | COD `utils/validation.ts` (text 2050k, URL, MIME/extensii/limite, durată media, `isPrivateHost`) |
| M10 | Consimțământ explicit la trimitere fișiere + confidențialitate | ✅ | COD `utils/uploadConsent.ts` + `components/UploadConsentModal.tsx` (checkbox obligatoriu; persistat; menționare discretă ulterior) |
| M11 | Istoric analize (paginat/infinite scroll, polling progres, ștergere cu confirmare) | ✅ | COD `screens/HistoryScreen.tsx` + `api/history.ts` |
| M12 | Competențe individuale + pipeline complet | ✅ | COD `SkillsScreen.tsx` (4 competențe) + `SkillAnalysisScreen.tsx` |
| M13 | Setări: profil, schimbare parolă, deconectare | ✅ | COD `SettingsScreen.tsx` + `SignOutSection.tsx` (hook comun `useSignOut`; și în Dashboard) |
| M14 | Disponibilitate Android/iOS dintr-un singur codebase | ⚠️ | COD React Native/Expo (cross-platform); livrat build Android (APK) — v. §6.2 |
---
# 4. Componenta 3 — Extensie Browser (`extension/`)
| # | Cerință (caiet de sarcini) | Stare | Dovadă |
|---|---|---|---|
| E1 | Trimitere URL: analiza tab-ului curent | ✅ | COD `popup.js` (buton „Pagina curentă" + prefill URL tab activ) + context menu „Analizează pagina curentă" |
| E1b | Trimitere URL: input manual (câmp dedicat) | ✅ | COD `popup.html` (`#urlInput` + validare http/https) → `background.js analyzeUrl` |
| E2 | Trimitere text: analiza textului selectat din pagină | ✅ | COD `popup.js prefillFromActiveTab()` (getSelection → prefill) + context menu „Analizează textul selectat" |
| E2b | Trimitere text: input manual (câmp dedicat) | ✅ | COD `popup.html` (`#textInput`, max 5000) → `analyzeTextContent` |
| E3 | Trimitere imagine: selectare din pagină (context menu „Analyze image") | ✅ | COD `background.js` (`chrome.contextMenus`, id `didi-analyze-image`: fetch imagine → upload → analiză) |
| E3b | Trimitere imagine: captură cu crop/selector de regiune | ✅ | COD `content.js` (snipping overlay + drag select) + `background.js` (`captureVisibleTab` + `OffscreenCanvas` + devicePixelRatio) |
| E4 | Panel rezultat: verdict+scor, rezumat, fact-check (claims+status), tehnici, surse/evidențe | ✅ | COD `render.js` (headline+gauge, `explanation_ro/en`, `claimsCard` cu surse, `techniquesCard`, `sourceCard`); modal în pagină + tab standalone |
| E5 | Autentificare prin IAM: OIDC/OAuth2 cu PKCE | ✅ | COD `auth.js` (launchWebAuthFlow → Keycloak `didi-clients`, client `didi-extension`, PKCE S256 + state; refresh single-flight; logout cu revocare); TEST flux token→analiză |
| E6 | Stocare securizată token-uri conform politicilor browserului | ✅ | COD `chrome.storage.local` (izolat per-extensie, MV3); fără chei statice în cod |
| E7 | Minimizarea datelor (strict URL/text/fragment imagine selectat) | ✅ | COD `background.js` payload minimal (`{text|url|media_url}` + identitate token); capturile trimit doar regiunea decupată |
| E8 | Integrare exclusiv prin API + stări asincrone (queued/running/completed) + timeouts + mesaje clare | ✅ | COD `submitAndPoll` (analyze-async → queue-status 2s → result; timeout 5 min; erori propagate ca notificări); TEST end-to-end |
| E9 | Comunicare prin API Gateway cu autorizare | ✅ | TEST: `POST /agent-v3/api/v3/pipeline/analyze-async` cu Bearer prin Kong (JWT validat; 401 fără token); rate limiting Kong |
| E10 | Istoric analize | ✅ | COD `history.html/js` (pagină dedicată, max 50 intrări, ștergere per element) |
| E11 | Extractoare conținut rețele sociale (Facebook, Twitter/X) | ✅ | COD `content.js` (`FacebookExtractor`, `TwitterExtractor`) cablate: buton „Selectează postare" (popup) → `contentExtracted` → analiză automată |
| E12 | Consimțământ explicit pentru capturi + confidențialitate | ✅ | COD `content.js ensureUploadConsent()` (modal la prima captură; persistat) + notă de confidențialitate în popup |
| E13 | Permisiuni minimale | ✅ | COD `manifest.json` v3.2.0 (`clipboardWrite` eliminat; `identity`+`contextMenus` adăugate pentru cerințele E3/E5) |
| E14 | Accesibilitate popup: labels/ARIA, focus vizibil, keyboard | ✅ | COD `popup.html` (aria-label pe toate controalele, `aria-live` pe status) + `popup.css` (`:focus-visible`) |
---
# 5. Cerințe comune + criterii de evaluare
| Cerință / criteriu | Stare | Dovadă |
|---|---|---|
| Design responsive/mobile-first, onboarding minim | ✅ | W10, M1, popup extensie |
| WCAG 2.1 AA pe web + extensie (focus/contrast/tastatură/labels/ARIA — criteriul 5) | ✅ | W12W13, E14 |
| Validare input + mesaje explicite (toate componentele) | ✅ | W14, M9, E8 |
| Consimțământ explicit fișiere/capturi (toate componentele) | ✅ | W16, M10, E12 |
| Comunicare doar prin API, rate limiting și protecții server-side | ✅ | W17, M8, E9 (Kong: JWT + rate limiting + request-size-limiting) |
| E2 evaluare — IAM OIDC/OAuth2 funcțional pe web + mobil + extensie, TLS, validare token la gateway | ✅ | Toate cele 3 componente pe Keycloak realm `didi-clients` (clienți `didi-web-app`, `didi-mobile-app`, `didi-extension`); Kong validează JWT (TEST) |
| E4 evaluare — wireframes/mockups mapate pe endpoint-uri și stări | ✅ | PT Anexa C; implementare 1:1 în COD (endpoint-urile din PT §1.5 consumate identic) |
| Identitate vizuală Clossers (dezvoltată post-atribuire, conform PT §1.8) | ✅ | `clossers_brand_guide.html` aplicat pe toate 3 componentele (HAND §14) |
---
# 6. Observații asumate (nu afectează conformitatea funcțională)
1. **HTTPS cu certificat self-signed + HTTP în LAN.** Platforma rulează în rețea internă
(`10.11.10.18`); mobilul și extensia folosesc HTTP (nginx port 80 → Kong/Keycloak) deoarece
nu acceptă certificate self-signed. La expunere publică se instalează certificat valid și
se comută config-urile (o singură constantă per componentă). TLS este activ pe web (443).
2. **Build iOS.** Codebase-ul React Native/Expo este cross-platform (cerința de cod unic e
îndeplinită); build-ul iOS necesită mediu macOS/Apple Developer și se generează la cerere.
Livrat: APK Android semnat cu cheie de test (pentru Google Play se generează keystore de release).
3. **Autentificarea extensiei prin fereastra Keycloak HTTP** — de confirmat pe stația
beneficiarului că browserul permite flow-ul `launchWebAuthFlow` pe HTTP; alternativa este
certificatul valid de la pct. 1.
4. **Filtrele de istoric (web)** rulează client-side pe seturi de câte 100 de înregistrări
(maximul rutei user din backend); ruta backend cu filtre server-side există doar pe admin
(Lot 2). Comportamentul pentru utilizator este identic funcțional.
5. **Progresul la upload (web)** este afișat ca stare + bară euristică (fetch API nu expune
evenimente de progres byte-level); fișierele tipice (<100MB LAN) se încarcă în secunde.
---
# 7. Sinteză stare livrare
| Categorie | Rezultat |
|---|---|
| Cerințe caiet — App Web | **20/20** conforme (2 cu observație asumată) |
| Cerințe caiet — App Mobilă | **14/14** conforme (1 cu observație asumată) |
| Cerințe caiet — Extensie | **14/14** conforme |
| Cerințe comune + criterii evaluare | **8/8** |
| Autentificare unificată IAM (Keycloak OIDC/PKCE) | **3/3 componente** |
| Test end-to-end auth + analiză prin Kong (15.07.2026) | PASS (submit → poll → result + upload media, Bearer) |
| Verificare tip/build | `tsc` 0 erori (web + mobil) · `vite build` OK · APK build OK · extensie: syntax OK, manifest valid |
| Livrabile actualizate | imagine `didi-frontend:local` (LIVE) · `didi-app-clossers.apk` · `didi-extension-clossers.zip` |
Toate cerințele caietului de sarcini pentru LOT 3 și angajamentele din Propunerea Tehnică sunt
**implementate, livrate și verificabile**, cu dovezi trasabile în cod, pe platforma în funcțiune
și în testele executate. Neconformitățile identificate la analiza din 15.07.2026 (autentificare
extensie fără OIDC, analiza URL/text selectat/context-menu lipsă din UI extensie, crop mobil,
share imagini, consimțământ upload, filtre istoric, partajare raport, accesibilitate) au fost
**remediate integral** în aceeași zi, înainte de emiterea prezentei matrice.

View file

@ -1,402 +0,0 @@
% Raport de testare furnizor — DiDi Lot 3 (Frontend)
% PNRR DIGI150 · contract 11.1.i3.c9 · Contract de furnizare nr. 19
---
# 1. Scop
Prezentul raport documentează testarea funcțională de furnizor a livrabilelor Lotului 3 —
**aplicația web**, **aplicația mobilă (Android)** și **extensia de browser (Chrome/Edge MV3)**
executată pe platforma integrată (Lot 1 + Lot 2 + Lot 3) în perioada **1517.07.2026**.
Fiecare caz de test este trasabil către cerințele din
*06_Matrice_Trasabilitate_Cerinte_Lot3* (identificatorii **W** = aplicație web, **M** = aplicație
mobilă, **E** = extensie), cu **dovadă foto** capturată în timpul execuției — capturile
reprezentative pentru fiecare flux sunt incluse în prezentul raport. Setul complet de capturi
(89 de fișiere) este arhivat de furnizor și disponibil la cerere.
# 2. Mediul de testare
| Element | Valoare |
|---|---|
| Platformă backend (Lot 1 + Lot 2) | `10.11.10.18` — stack integral, 11/11 servicii healthy |
| Aplicație web | `https://10.11.10.18/` — imagine `didi-frontend:local` |
| Aplicație mobilă | APK release `didi-app-clossers.apk` (Expo SDK 54), emulator Android „Small Phone" — vezi detaliile de mai jos |
| Extensie browser | v3.2.x (finală 3.2.5), Chrome desktop, Load unpacked |
| Autentificare | Keycloak realm `didi-clients`; clienți `didi-web-app`, `didi-mobile-app`, `didi-extension` |
| API Gateway | Kong — validare JWT (RS256), rate limiting, limite de plan |
| Utilizator de test | `demo@didi.local` (plan Freemium/Explorer) |
**Configurația de test pentru aplicația mobilă — aleasă deliberat minimală.** Testarea s-a
executat pe un emulator Android configurat la limita de jos a dispozitivelor din piață, tocmai
pentru a demonstra că aplicația rulează fluent inclusiv pe hardware entry-level; funcționarea pe
această configurație garantează funcționarea pe orice dispozitiv Android modern, cu resurse egale
sau superioare:
| Parametru emulator | Valoare |
|---|---|
| Profil dispozitiv | „Small Phone" (Generic) |
| Memorie RAM | **1024 MB** (1 GB) |
| Heap VM per aplicație | **80 MB** |
| CPU | 4 nuclee x86_64 |
| Ecran | **720 × 1280 px**, 320 dpi (diagonală mică) |
| Stocare date | 6 GB |
| Imagine sistem | Android API 37.1, Google APIs + Play Store, pagini de memorie 16 KB |
| Rețea | latență „none", viteză „full" (LAN către `10.11.10.18`) |
Nota bene: imaginea de sistem cu **pagini de memorie de 16 KB** corespunde cerinței Google Play
pentru dispozitivele Android recente — compatibilitatea APK-ului cu acest mod este astfel
demonstrată explicit.
# 3. Sinteză rezultate
| Componentă | Cazuri de test | PASS | FAIL |
|---|---|---|---|
| Aplicație web | 11 | **11** | 0 |
| Aplicație mobilă | 12 | **12** | 0 |
| Extensie browser | 10 | **10** | 0 |
| Integrare backend (IAM/Gateway) | 4 | **4** | 0 |
| **Total** | **37** | **37** | **0** |
Defecte identificate pe parcursul testării și remediate înainte de închiderea raportului:
trunchierea explicației verdictului în extensie (remediat în v3.2.4), etichete
nelocalizate în raportul extensiei (remediat în v3.2.5), epuizarea creditelor planului de test
(comportament corect al platformei — limitele de plan se aplică server-side; creditele contului
demo au fost suplimentate administrativ).
---
# 4. Componenta 1 — Aplicația Web
## T-W01 · Pagina de prezentare și identitatea vizuală (W10)
**Flux:** Se accesează `https://10.11.10.18/` fără autentificare. Se verifică landing page-ul:
identitatea vizuală Clossers (teal/ink), secțiunile de prezentare, mock-up-ul „raport de analiză",
layout responsive. **Rezultat: PASS.**
![T-W01 — Landing page cu identitatea vizuală Clossers](media_testare/web-01-landing.png){width=15.5cm}
## T-W02 · Autentificare OIDC/OAuth2 prin Keycloak (W7, W8)
**Flux:** Din landing → „Începe analiza" → redirecționare către Keycloak (realm `didi-clients`) →
autentificare cu utilizatorul de test → revenire în aplicație cu sesiune activă (token Bearer,
auto-refresh). Sign out din meniul lateral revocă sesiunea. **Rezultat: PASS.**
![T-W02 — Formular de autentificare Keycloak](media_testare/web-02-login-keycloak.png){width=15.5cm}
## T-W03 · Formular unificat de trimitere conținut (W1, W2)
**Flux:** Dashboard → „Analiză completă". Se verifică prezența tab-urilor **Text / URL / Imagine /
Audio / Video** și a câmpurilor de input adaptate per tip, cu validare (buton inactiv fără
conținut valid). **Rezultat: PASS.**
![T-W03 — Formular unificat cu cele 5 tab-uri de conținut](media_testare/web-03-formular-unificat.png){width=15.5cm}
## T-W04 · Consimțământ explicit la trimiterea fișierelor (W16)
**Flux:** Tab Video → se selectează un fișier → butonul „Rulează analiza completă" rămâne
**inactiv** până la bifarea consimțământului („Sunt de acord ca fișierul trimis să fie procesat…"),
cu link către Politica de confidențialitate. După bifare, acordul persistă și la trimiterile
ulterioare rămâne o menționare discretă. **Rezultat: PASS.**
![T-W04 — Consimțământ obligatoriu înainte de upload (buton inactiv)](media_testare/web-04-consimtamant-upload.png){width=15.5cm}
## T-W05 · Afișarea stării analizei (W3)
**Flux:** Se trimite un fișier video → se urmărește bara de progres și starea per componentă
(Detectare AI, Evaluarea sursei, Tehnici de manipulare, Verificarea afirmațiilor — „în
așteptare" → rulare → finalizare), cu polling asincron. **Rezultat: PASS.**
![T-W05 — Stare analiză în desfășurare, cu componente și progres](media_testare/web-05-progres-analiza.png){width=15.5cm}
## T-W06 · Pagina de rezultate cu verdict și drill-down (W4)
**Flux:** La finalizarea analizei se afișează: scor de risc (0100) cu inel colorat funcțional,
categorie verdict, nivel risc, grad de certitudine, explicație în limba română, acțiune recomandată
(„Nu distribui acest articol"), cea mai gravă problemă cu citat-dovadă, secțiuni expandabile de
detalii per componentă. **Rezultat: PASS.**
![T-W06 — Verdict 92/100 DEZINFORMARE cu explicație și acțiune recomandată](media_testare/web-06-rezultat-verdict.png){width=15.5cm}
## T-W07 · Export PDF și partajare raport (W6)
**Flux:** Pe pagina de rezultate (analiză video) sunt disponibile butoanele **„Partajează"**
(navigator.share / copiere link către raport) și **„Descarcă PDF"**. Linkul partajat, deschis
într-un tab nou de un utilizator autentificat, deschide direct raportul respectiv din Istoric.
**Rezultat: PASS.**
![T-W07 — Rezultat analiză video cu butoanele Partajează și Descarcă PDF](media_testare/web-07-rezultat-video-partajare.png){width=15.5cm}
## T-W08 · Analize per competență individuală (W19)
**Flux:** Din meniul „Abilități DIDI" se rulează individual: Tehnici de manipulare, Evaluarea
sursei, Verificarea afirmațiilor, Detectare AI — fiecare cu input propriu și ecran de rezultate
dedicat. **Rezultat: PASS** (toate cele 4 competențe; capturi complete în setul livrat).
![T-W08 — Competența individuală „Detectare AI"](media_testare/web-08-competenta-detectare-ai.png){width=15.5cm}
## T-W09 · Istoric analize cu filtre (W5, W5b)
**Flux:** Dashboard → Istoric. Listă paginată cu analizele utilizatorului (scor, verdict, tip
conținut, durată, dată), export PDF și ștergere per element, navigare la detalii. Rândul de filtre:
căutare text, nivel risc, status, tip conținut, interval de date, resetare. **Rezultat: PASS.**
![T-W09 — Istoric analize cu rândul complet de filtre](media_testare/web-09-istoric-filtre.png){width=15.5cm}
**Verificare filtrare efectivă:** cu filtrul „Nivel risc: Critic" aplicat, lista se restrânge la
analizele cu nivel Critic; „Resetează" revine la lista completă. **Rezultat: PASS.**
![T-W09b — Filtrul „Critic" aplicat — lista restrânsă corespunzător](media_testare/web-10-istoric-filtru-aplicat.png){width=15.5cm}
## T-W10 · Setări cont + distribuirea aplicațiilor client (W7)
**Flux:** Dashboard → Setări: profil utilizator, schimbare parolă (flux Keycloak), abonament.
Secțiunile **„Extensie browser"** și **„Aplicație mobilă"** oferă descărcarea extensiei (.zip) și a
APK-ului **pentru orice tip de abonament**, cu instrucțiuni de instalare pas cu pas.
**Rezultat: PASS.**
![T-W10 — Setări: descărcare extensie browser și APK, cu instrucțiuni](media_testare/web-11-setari-descarcari.png){width=15.5cm}
## T-W11 · Validare input, SSRF și accesibilitate (W9, W12W15, W17)
**Flux (verificare tehnică, fără captură):** validarea URL-urilor respinge IP-uri private/localhost
(protecție SSRF, inclusiv forme hex/octal/IPv6); fișierele sunt validate pe MIME + extensie +
dimensiune (20/50/100 MB) cu mesaje explicite; toate apelurile trec exclusiv prin API Gateway cu
Bearer și tratare erori/timeout; WCAG: ARIA pe componentele interactive, `aria-live` pe toast-uri,
focus vizibil, font scaling (rem/clamp), `prefers-reduced-motion`. Verificat prin inspecția codului
(`utils/url-validation.ts`, `utils/file-validation.ts`, `services/http.client.ts`) și teste
negative manuale. **Rezultat: PASS.**
---
# 5. Componenta 2 — Aplicația Mobilă (Android)
Toate testele din această secțiune au fost executate pe emulatorul cu **resurse minimale** descris
în §2 (1 GB RAM, heap 80 MB, ecran 720×1280) — aplicația a rulat fluent, fără blocaje sau erori de
memorie, pe toată durata fluxurilor, inclusiv la încărcarea și decuparea imaginilor.
## T-M01 · Autentificare OIDC flow mobil (M5, M6)
**Flux:** Se instalează APK-ul → ecranul principal → Sign In → formularul Keycloak în WebView
(incognito) → autentificare cu utilizatorul de test → tokenii sunt stocați securizat (Keystore) și
sesiunea persistă la repornirea aplicației. **Rezultat: PASS.**
![T-M01 — Autentificare Keycloak în aplicația mobilă](media_testare/mob-01-login-keycloak.png){width=8cm}
## T-M02 · Dashboard și navigare (M1)
**Flux:** După autentificare, dashboard-ul afișează profilul și cardurile de navigare: Analiză
completă, Competențe individuale, Istoric, Setări. **Rezultat: PASS.**
![T-M02 — Dashboard mobil](media_testare/mob-02-dashboard.png){width=8cm}
## T-M03 · Analiză completă cu progres (M1)
**Flux:** Analiză completă → se trimite conținut → progres în timp real pe componente (polling
asincron), apoi rezultate. **Rezultat: PASS.**
![T-M03 — Analiză în desfășurare pe mobil](media_testare/mob-03-analiza-progres.png){width=8cm}
## T-M04 · Crop imagine înainte de trimitere (M3)
**Flux:** Tab Imagine → „Selectați din galerie" → se alege o imagine → se deschide **editorul
nativ de decupare** (selectarea regiunii) → imaginea decupată apare în preview și se trimite la
analiză. Același comportament la fotografiere cu camera. **Rezultat: PASS.**
![T-M04a — Selectarea imaginii din galerie](media_testare/mob-04-crop-selectare.png){width=8cm}
![T-M04b — Imaginea decupată, preîncărcată pentru analiză](media_testare/mob-05-crop-imagine-preincarcata.png){width=8cm}
## T-M05 · Consimțământ explicit la încărcarea fișierelor (M10)
**Flux:** La prima trimitere a unui fișier media apare modalul „Consimțământ pentru încărcarea
fișierelor" cu notă de confidențialitate; butonul de continuare este inactiv până la bifarea
acordului; „Anulează" oprește trimiterea. Acordul persistă; ulterior rămâne mențiunea discretă.
**Rezultat: PASS.**
![T-M05 — Modal de consimțământ cu checkbox obligatoriu](media_testare/mob-06-consimtamant.png){width=8cm}
## T-M06 · Rezultate în format optimizat mobil (M4)
**Flux:** Rezultatul afișează verdict + scor, secțiuni expandabile per componentă, evidențe/surse
cu linkuri, tehnici de manipulare și recomandări (ex. „NU DISTRIBUI"). **Rezultat: PASS.**
![T-M06 — Ecran de rezultate mobil](media_testare/mob-07-rezultat.png){width=8cm}
## T-M07 · Share-to-Analyze — imagine (M2c, M2d)
**Flux:** Din Google Photos → Share → **didi** → ecranul „Analizează imaginea" cu miniatura
conținutului partajat → se alege tipul de analiză → imaginea ajunge preîncărcată în fluxul de
analiză (cu mențiunea de consimțământ vizibilă). Testat și fluxul neautentificat: share → login →
revenire automată la analiză. **Rezultat: PASS.**
![T-M07a — Share din Google Photos către didi](media_testare/mob-08-share-imagine-sursa.png){width=8cm}
![T-M07b — Ecranul „Analizează imaginea" cu opțiunile de analiză](media_testare/mob-09-share-imagine-ecran.png){width=8cm}
![T-M07c — Imaginea partajată, preîncărcată în analiza completă](media_testare/mob-10-share-imagine-pipeline.png){width=8cm}
## T-M08 · Share-to-Analyze — text fără URL (M2b)
**Flux:** Dintr-o aplicație terță se partajează un **text simplu (fără link)** → didi deschide
ecranul „Analizează textul" cu textul preluat → analiza pornește cu textul preîncărcat pe tab-ul
Text. **Rezultat: PASS.**
![T-M08 — Text partajat fără URL, preluat pentru analiză](media_testare/mob-11-share-text.png){width=8cm}
## T-M09 · Share-to-Analyze — link (M2)
**Flux:** Din browser se partajează un URL → didi deschide ecranul „Analizează URL" cu linkul
preluat și opțiunile de analiză (inclusiv Analiză domeniu, disponibilă pentru URL-uri).
**Rezultat: PASS.**
![T-M09 — URL partajat, cu opțiunile de analiză](media_testare/mob-12-share-link.png){width=8cm}
## T-M10 · Competențe individuale (M12)
**Flux:** Ecranul Competențe → Tehnici de manipulare / Evaluarea sursei / Detecție AI / Analiză
afirmații, fiecare cu input adaptat și rezultate dedicate. **Rezultat: PASS** (capturi complete în
setul livrat).
## T-M11 · Istoric analize (M11)
**Flux:** Istoric cu listă paginată (infinite scroll), polling pentru analizele în curs, ștergere
cu confirmare, navigare la detalii. **Rezultat: PASS.**
![T-M11 — Istoric analize pe mobil](media_testare/mob-13-istoric.png){width=8cm}
## T-M12 · Setări și deconectare completă (M13)
**Flux:** Setări → profil, schimbare parolă, limbă, opțiuni social share și secțiunea
**„Deconectare"** (stil de avertizare) → dialog de confirmare → tokenul de refresh este revocat
server-side și aplicația revine la ecranul principal. **Rezultat: PASS.**
![T-M12 — Secțiunea Deconectare din Setări](media_testare/mob-14-setari-deconectare.png){width=8cm}
---
# 6. Componenta 3 — Extensia de Browser (Chrome/Edge MV3)
## T-E01 · Instalare din pachetul distribuit (E13)
**Flux:** Se descarcă arhiva din aplicația web (Setări → Extensie browser) → dezarhivare →
`chrome://extensions` → Developer mode → Load unpacked. Extensia se instalează cu ID-ul stabil
`blcalchooinkphpnlkkhlklbmgppmnfm` (fixat prin cheia din manifest, pe care este configurat
clientul Keycloak). **Rezultat: PASS.** *(Captura reflectă o versiune intermediară; versiunea
finală livrată este 3.2.5.)*
![T-E01 — Extensia instalată în Chrome, cu ID-ul stabil](media_testare/ext-01-instalare.png){width=14cm}
## T-E02 · Autentificare OIDC/OAuth2 cu PKCE (E5, E6)
**Flux:** Popup → „Autentificare" → se deschide fereastra Keycloak (realm `didi-clients`, client
`didi-extension`, PKCE S256 + state anti-CSRF) → login cu utilizatorul de test → popup-ul afișează
emailul contului; tokenii sunt stocați în `chrome.storage.local` (izolat per-extensie) cu refresh
automat; „Deconectare" revocă sesiunea Keycloak. **Rezultat: PASS.**
![T-E02a — Popup neconectat, cu butonul de autentificare](media_testare/ext-02-popup-neconectat.png){width=10cm}
![T-E02b — Autentificat: contul afișat în antetul popup-ului](media_testare/ext-03-login-keycloak.png){width=10cm}
## T-E03 · Analiză URL și text din popup (E1, E1b, E2b)
**Flux:** Popup-ul oferă: câmp URL cu validare + buton **„Pagina curentă"** (preia automat URL-ul
tab-ului activ) + „Analizează URL"; secțiune de text cu contor de caractere (max 5000) —
textul selectat în pagină este **preluat automat** la deschiderea popup-ului. Nota de
confidențialitate este afișată permanent. **Rezultat: PASS.**
![T-E03a — Secțiunea de analiză URL (tab curent + input manual)](media_testare/ext-04-popup-url-text.png){width=10cm}
![T-E03b — Secțiunea de text, istoricul și deconectarea](media_testare/ext-05-popup-istoric.png){width=10cm}
## T-E04 · Consimțământ explicit pentru capturi (E12)
**Flux:** La prima captură de ecran / trimitere de imagine apare modalul „Consimțământ pentru
analiză" (conținutul e folosit exclusiv pentru raport; se trimite doar fragmentul selectat);
„Anulează" oprește fluxul; acordul persistă. **Rezultat: PASS.**
![T-E04 — Modal de consimțământ în pagină, înaintea primei capturi](media_testare/ext-06-consimtamant.png){width=15.5cm}
## T-E05 · Captură de ecran cu selectarea regiunii (E3b)
**Flux:** Popup → „Screenshot" → overlay pe pagina curentă → utilizatorul trasează regiunea de
analizat (drag select) → extensia decupează exact regiunea selectată (OffscreenCanvas +
devicePixelRatio), o încarcă și pornește analiza. **Rezultat: PASS.**
![T-E05 — Snipping tool: selecția regiunii direct în pagină](media_testare/ext-07-snipping-selectie.png){width=15.5cm}
## T-E06 · Meniu contextual — analiza imaginii din pagină (E3)
**Flux:** Click-dreapta pe orice imagine dintr-un site → opțiunea **„Analizează imaginea cu
DiDi"** în meniul contextual → consimțământ (prima dată) → imaginea este preluată, încărcată și
analizată; rezultatul apare ca modal peste pagină. Meniul contextual include și „Analizează textul
selectat cu DiDi" (pe selecție) și „Analizează pagina curentă cu DiDi". **Rezultat: PASS.**
![T-E06 — Meniul contextual cu „Analizează imaginea cu DiDi" pe un site real](media_testare/ext-08-context-menu-imagine.png){width=15.5cm}
## T-E07 · Panel de rezultate complet (E4)
**Flux:** După analiză, rezultatul se afișează în panel (modal în pagină / tab dedicat): miniatura
conținutului analizat, scor de risc cu inel, verdict cu nivel și certitudine, explicație completă
în română, acțiune recomandată, Detecție AI, Verificarea afirmațiilor (status per afirmație +
surse cu poziție Susține/Contrazice), Evaluarea sursei (semnale de alarmă, avertismente).
**Rezultat: PASS.**
Caz demonstrativ relevant: imagine generată AI care relatează știri **adevărate** — sistemul
confirmă afirmațiile ca adevărate, dar detectează generarea AI (95%) și avertizează corect că
„prezentarea este falsificată" — nuanță redată integral în raport.
![T-E07a — Verdict cu miniatura imaginii analizate și explicația completă](media_testare/ext-09-rezultat-verdict.png){width=13cm}
![T-E07b — Detecție AI 95% + afirmații verificate ca adevărate (4/4)](media_testare/ext-10-rezultat-componente.png){width=13cm}
![T-E07c — Verificarea afirmațiilor cu surse și Evaluarea sursei](media_testare/ext-11-rezultat-sursa.png){width=13cm}
## T-E08 · Istoric analize în extensie (E10)
**Flux:** Popup → „Istoric" → pagină dedicată cu analizele efectuate (max 50, stocate local),
detalii per analiză și ștergere individuală. **Rezultat: PASS.**
![T-E08 — Pagina de istoric a extensiei](media_testare/ext-12-istoric.png){width=15.5cm}
## T-E09 · Minimizarea datelor (E7)
**Flux (verificare tehnică):** payload-urile trimise conțin strict conținutul de analizat
(`text` / `url` / URL-ul fragmentului de imagine încărcat) plus identitatea din token — nimic
suplimentar din pagină. Verificat prin inspecția codului (`background.js`) și a traficului.
**Rezultat: PASS.**
## T-E10 · Tratarea erorilor și limitele de plan (E8)
**Flux:** La epuizarea creditelor planului, backend-ul răspunde `402 — Insufficient credits`, iar
extensia afișează mesajul explicit utilizatorului; erorile de rețea/timeout sunt tratate cu mesaje
clare, fără blocarea interfeței. **Rezultat: PASS** (verificat în timpul testării, la epuizarea
efectivă a creditelor contului demo).
---
# 7. Teste de integrare backend (IAM + API Gateway)
Executate pe 15.07.2026, cu utilizatorul de test, direct pe traseul folosit de cele 3 componente.
| # | Test | Rezultat |
|---|---|---|
| T-I01 | Obținere token Keycloak (realm `didi-clients`) și validare JWT la Kong; apel fără token → **401** | **PASS** |
| T-I02 | `POST /agent-v3/api/v3/pipeline/analyze-async` cu Bearer → `202` + `session_id`; polling `queue-status``completed`; `GET …/result` → verdict complet (scor 72, QUESTIONABLE, explicație RO) | **PASS** |
| T-I03 | `POST /agent-v3/api/v3/media/upload` cu Bearer (multipart) → `public_url` funcțional, folosit apoi în analiză | **PASS** |
| T-I04 | CORS Keycloak pentru originea extensiei (`chrome-extension://blcal…`) pe endpoint-ul de token; discovery OIDC pe ambele scheme | **PASS** |
# 8. Concluzii
Toate cele **37 de cazuri de test au trecut**, acoperind integral cerințele funcționale ale
caietului de sarcini pentru LOT 3 și angajamentele din Propunerea Tehnică, pe toate cele trei
componente. Defectele identificate pe parcurs au fost remediate și retestate în aceeași fereastră
de testare (v3.2.43.2.5 extensie). Platforma este funcțională end-to-end pe mediul integrat
(Lot 1 + Lot 2 + Lot 3), cu autentificare unificată prin Keycloak și acces exclusiv prin API
Gateway.
Livrabilele finale supuse recepției: aplicația web în funcțiune pe `https://10.11.10.18/`,
`didi-app-clossers.apk`, `didi-extension-clossers.zip` (v3.2.5), împreună cu documentația
de livrare (matrice de trasabilitate, prezentul raport, ghid de utilizare).
*Întocmit: Furnizor Lot 3 · 17.07.2026*

Binary file not shown.

0
extension/build.sh Executable file → Normal file
View file

View file

@ -8,8 +8,8 @@
// service worker pe HTTP. Pe un mediu cu certificat valid, ambele valori se
// setează pe același https://…
(() => {
const DIDI_HOST_HTTP = 'http://10.11.10.18';
const DIDI_HOST_HTTPS = 'https://10.11.10.18';
const DIDI_HOST_HTTP = 'http://didi.integrare.local';
const DIDI_HOST_HTTPS = 'https://didi.integrare.local';
const REALM = 'didi-clients';

4
web/scripts/wcag-audit.sh Executable file → Normal file
View file

@ -2,7 +2,7 @@
# WCAG 2.1 AA audit script — runs Lighthouse + axe-core against key pages.
#
# Usage:
# ./scripts/wcag-audit.sh # Default: https://didi365.eu
# ./scripts/wcag-audit.sh # Default: https://didi.integrare.local
# BASE_URL=http://localhost:5173 ./scripts/wcag-audit.sh
#
# Required deps (auto-install if missing):
@ -17,7 +17,7 @@
# Audit produces a formal report for PNRR recepție (cerință E5 caiet sarcini).
set -euo pipefail
BASE_URL="${BASE_URL:-https://didi365.eu}"
BASE_URL="${BASE_URL:-https://didi.integrare.local}"
TIMESTAMP=$(date -u +"%Y%m%d-%H%M%S")
OUT_DIR="reports/wcag/${TIMESTAMP}"
mkdir -p "$OUT_DIR"