Code standards
Aceste standarde se aplică echipelor care dezvoltă soluții pentru ecosistemul eGov Moldova — atât echipelor proprii ale Agenției de Guvernare Electronică, cât și echipelor furnizorilor externi. Ele există pentru ca un cod scris de o echipă să poată fi întreținut, auditat și dezvoltat de o alta, ceea ce reprezintă ciclul de viață normal al unui sistem guvernamental.
Standardele sunt aplicate, acolo unde este posibil, prin automatizare — analizoare (analyzers), praguri de calitate în pipeline și revizuirea codului — nu prin memorie. Vedeți Revizuiri de cod pentru partea de proces.
Limbaje și framework-uri¶
Proiectele utilizează stiva tehnologică guvernamentală aprobată, descrisă în Instrumente și tehnologii: C# pe versiuni .NET suportate (LTS), ASP.NET Core pentru servicii, Blazor pentru interfețe web cu Fod.UIComponents — biblioteca proprie de componente UI a Agenției, care înlocuiește MudBlazor ca standard de componente — și Entity Framework Core pentru accesul la date.
- Nu introduceți framework-uri, limbaje sau dependențe semnificative noi fără o justificare arhitecturală explicită — consemnați decizia ca înregistrare a deciziei de arhitectură și obțineți aprobarea la nivel de arhitectură tehnică.
- Fixați versiunile dependențelor în manifestele proiectului; intervalele de versiuni flotante nu sunt permise în build-urile de producție.
- Preferați reutilizarea pachetelor NuGet partajate Egov (pentru MPass, MSign și configurare) în locul reimplementării integrărilor cu platformele.
Limbă¶
Tot codul, comentariile, mesajele de commit, identificatorii și contractele API sunt scrise în limba engleză. Limba română apare doar în textele orientate către utilizator (etichete, mesaje, notificări), care trebuie păstrate în resurse localizabile — niciodată scrise direct (hardcodate) în cod.
Atunci când vă integrați cu un sistem a cărui interfață folosește termeni în limba română, traduceți endpoint-urile și câmpurile în limba engleză la nivelul stratului de integrare, astfel încât restul sistemului să lucreze cu obiecte în limba engleză. Utilizați glosarul pentru traducerile consacrate ale termenilor din domeniul guvernamental și extindeți-l atunci când lipsește un termen.
Rău
var cerere = new CerereEliberareCertificat(); // Romanian identifier
Bine
var request = new CertificateIssueRequest();
Structura proiectului¶
Serviciile backend urmează Clean Architecture — dependențele sunt orientate spre interior, iar logica de business nu depinde niciodată de infrastructură:
| Strat | Conținut | Regulă de dependență |
|---|---|---|
| Domain | Entități, obiecte valoare, evenimente de domeniu, interfețe | Nu depinde de nimic |
| Application | Cazuri de utilizare, handler-e pentru comenzi/interogări, DTO-uri, validatori | Depinde doar de Domain |
| Infrastructure | DbContext-uri, repository-uri, clienți pentru servicii externe, mesagerie | Implementează interfețele din Domain |
| Presentation | Controllere, middleware, modele de cerere/răspuns | Depinde de Application; conectează Infrastructure |
Consecințe practice:
- Nu faceți niciodată referire la elemente de infrastructură (un
DbContext, un client HTTP, un producător de mesaje) din straturile Domain sau Application. - Nu returnați niciodată entități de bază de date direct din endpoint-urile API — mapați la DTO-uri la granița stratului Application.
- Organizați repository-urile cu folderele convenționale
src/șitests/; un singur serviciu per soluție (solution).
Convenții C¶
- Respectați convențiile standard Microsoft pentru C#:
PascalCasepentru tipuri și membri publici,camelCasepentru variabile locale și parametri, nume semnificative în locul abrevierilor. - Formatarea și stilul sunt impuse prin fișierul
.editorconfiginclus în repository, cu analizoare Roslyn activate; build-urile tratează avertismentele ca erori. - Activați nullable reference types în proiectele noi.
- Utilizați
async/awaitde la un capăt la altul pentru operațiuni I/O; nu blocați niciodată codul asincron (.Result,.Wait()). - Utilizați injectarea de dependențe (dependency injection) pentru toți colaboratorii; evitați accesul static la servicii și service locators.
- Utilizați jurnalizare structurată prin
ILogger<T>— vedeți Gestionarea jurnalelor;Console.WriteLinenu este jurnalizare.
Acces la date¶
- Toate modificările de schemă trec prin migrări versionate (EF Core Migrations); DDL manual asupra oricărui mediu partajat este interzis.
- Doar interogări parametrizate sau generate de ORM — concatenarea de șiruri în SQL este o încălcare critică de securitate, nu o problemă de stil.
- Noua logică de business trăiește în stratul Application, nu în proceduri stocate.
- Intrările din cache-ul Redis au întotdeauna un TTL.
Codare securizată¶
Cerințele de securitate fac parte din definiția codului funcțional, nu o activitate separată. Nivelul minim pentru aplicațiile din ecosistem este OWASP ASVS Level 2; în activitatea zilnică, modurile de eșec din OWASP Top 10 trebuie prevenite activ:
- Fără secrete în cod sau în fișierele de configurare din repository — fără șiruri de conexiune cu credențiale, chei API, token-uri sau certificate. Secretele trăiesc în mecanismele securizate de configurare/vault ale platformei. Această regulă nu are excepții și se aplică în orice mediu, inclusiv în dezvoltare.
- Validați datele de intrare pe server pentru fiecare punct de intrare; codificați (encode) corespunzător datele de ieșire, în funcție de destinație (HTML, SQL, jurnale).
- Autentificați utilizatorii doar prin MPass — stocarea personalizată a credențialelor este interzisă.
- Aplicați verificări de autorizare la nivel de resursă, la fiecare cerere, nu doar în interfață.
- Fără date reale de producție în mediile de dezvoltare sau testare (staging) — utilizați date sintetice sau mascate.
- Analiza statică (SAST) și scanarea dependențelor (SCA) rulează în pipeline și sunt blocante: un eșec la scanarea de securitate se remediază, nu se ocolește. Constatările critice sau de severitate ridicată neremediate opresc lansarea.
Testare¶
Testele fac parte din Definiția lui „Finalizat” — o funcționalitate fără teste nu este finalizată:
- Teste unitare pentru logica de business (straturile Domain și Application).
- Teste de integrare pentru servicii și API-uri, acoperind scenariile principale și căile de eroare.
- Teste end-to-end pentru fluxurile critice ale utilizatorilor, rulate pe staging înainte de lansare.
Acoperirea codului nou trebuie să fie de cel puțin 70%, logica de business fiind supusă unui prag mai ridicat (țintă 80%). Acoperirea este măsurată în pipeline și impusă ca prag de calitate, împreună cu analiza statică — o lansare cu praguri nereușite (failing gates) nu avansează. Vedeți pagina de revizuire a codului pentru modul în care aceasta se încadrează în fluxul de livrare.
Standarde de interfață cu utilizatorul¶
Interfețele web respectă Sistemul unitar de design (MUD) și sunt construite cu Fod.UIComponents, biblioteca de componente UI Blazor a Agenției. Interfețele noi folosesc Fod.UIComponents; aplicațiile MudBlazor existente migrează progresiv, pe măsură ce evoluează. Dincolo de sistemul de design, aceste reguli de implementare se aplică tuturor aplicațiilor AGE — ele fac diferența dintre o interfață care pare finalizată și una care își expune schema bazei de date:
Text și etichete
- Etichetele sunt în limba română corectă gramatical, cu majusculă doar la început de propoziție (sentence case): „Cod personal", nu „Cod Personal" — camelCase și Title Case nu sunt practici tipografice românești.
- Nu afișați niciodată nume tehnice brute în interfață:
UserTypedevine Tipul utilizatorului,CreatedAtdevine Data creării. Aceasta se aplică deopotrivă etichetelor, opțiunilor din liste derulante, coloanelor din grile și filtrelor. - Mesajele de eroare sunt în limba română, orientate către utilizator și acționabile: „Introduceți un IDNP valid (13 cifre)" — niciodată mesaje implicite ale framework-ului, precum "Length cannot be longer than…", și niciodată jargon tehnic.
Formate
- Date: 12 septembrie 2024 (sau 12 sep 2024 acolo unde spațiul este limitat); forma numerică este
12.09.2024— doar separator punct, ziua fără zero în față, luna cu zero în față. - Oră: format de 24 de ore —
14:30, niciodată2:30 PM.
Comportamentul formularelor
- Un formular are exact un buton vizual principal (submit/salvare); acțiunile secundare (Anulează) sunt vizual neutre; acțiunile tehnice sunt minime.
- Etichetele sunt întotdeauna prezente; placeholder-ele afișează conținut exemplificativ, nu înlocuiesc etichetele.
- Feedback-ul de validare apare atunci când un câmp pierde focusul (blur), nu la fiecare apăsare de tastă; câmpurile invalide primesc o stare vizuală clară, plus un mesaj.
- Câmpurile asociate sunt grupate pe același rând, cu spațiere de grilă consecventă; formularele sunt complet navigabile de la tastatură (Tab/Shift+Tab, Enter trimite formularul).
Structura și conținutul formularelor pentru ecranele reale provin din specificația de produs/design, nu din improvizația dezvoltatorului — regulile de mai sus reprezintă minimul, nu un substitut pentru livrabilele de design.