% 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 20–50k, 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) | ✅ | W12–W13, 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 §1–4) | --- # 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.