Comparație de calitate a repo-urilor: SalarEasy vs. restul (read-only, 19 sept 2026)
SalarEasy față de Facturare, Desire, Nucleu și Vertigo: calitate, teste, formă, bus factor.
Metodă: 13 repo-uri din bono-ro clonate local (shallow; SalarEasy pe staging cu istoric complet), numărători cu git, grep, wc și GitHub API. cloc nu e instalat: LOC = linii fizice per extensie, fără lock-files/dist. „Q3" = commit-uri de la 2026-07-01. Nimic modificat pe GitHub. Unde o metrică nu s-a putut calcula, scrie explicit.
Context care schimbă interpretarea: SalarEasy nu se dezvoltă pe main. main are 68 commit-uri (ultimul 13 aug); staging are 534 (API) / 538 (web), cu 378 / 340 în Q3 și ultimul push pe 18 sept. Toate cifrele de mai jos sunt de pe staging.
Rezumat
- SalarEasy e cel mai mare și cel mai testat codebase din organizație: 49.400 linii C# de producție + 64.000 de teste (2.860
[Fact]/[Theory]în 307 fișiere), plus 38.000 linii TS de producție cu 1.567 teste Vitest și 292 Playwright. Raport teste/producție 1,3 – egalat doar de document-vault (1,27), de 30x peste company-directory (0,04). - Arhitectura respectă șablonul casei: Api / ServiceInterface / ServiceAdapters / DomainModel / DomainServices / ScheduledTasks / Tests,
.hbm.xml, CQRS (59 Query + 45 Command + 8 Action), Quartz, ApiKey + politici.Documentation/project-standards/(9 fișiere) reproduce convențiile casei. - Unde e sub standard: fără
README.md,CLAUDE.md,CONTEXT.md,docs/adr/(zero ADR-uri la 534 commit-uri cu decizii legislative); rădăcină plată, 57 de binare (~91 MB) și două foldere export Drive commit-uite; prefixSRV.*(numele vechi);.NET 9când toate celelalte sunt pe.NET 10; Serilog în loc de NLog; Docker în loc de Windows Service + Azure Pipelines; propria variantă deBono.Infrastructure.NHibernate(6 fișiere / 183 linii) când celelalte 9 repo-uri C# poartă aceeași copie de 8–10 fișiere. - Fișiere mari: 11 fișiere de producție peste 500 de linii (
EnrollmentServiceAdapter.cs1.067,PayrollCalculator.cs971,RegesReceiptProcessor.cs945) față de zero în company-directory, vertigo-services, findocs, atom-core. Pe web, 6 pagini peste 1.000 (AddEmployeePage.tsx2.077). - Securitatea e la nivelul casei sau peste:
FallbackPolicyautentificat pe orice endpoint (ApiKey + cookie Google), roluriadmin/user, politici separate pentru autoangajare cu rate-limiter înainte de auth, audit filter. Restul au doar ApiKey global. Niciun secret înappsettingsnicăieri; 2 fișiere de test au credențiale de dev hardcodate. - CI-ul rulează testele doar teoretic:
ci.ymlcudotnet testdoar pe pull request, iar Alex face push direct pestaging(8 PR-uri în total, 5 rulări CI într-o lună, 3 roșii). Push pestaging= doardocker build; web =tsc -b, fărăvitest. Invoicing și vertigo-services rulează testele pe push lamain. - Facturare e cel mai apropiat profil de SalarEasy (19.000 LOC, 708 teste, CI verde, 7 autori), dar cu
CLAUDE.mdde 792 bytes, fără README/ADR. Efactura e cel mai slab din set: 4 aplicații, fără CI, fără README, 45 de teste la 16.000 LOC. - Repo-urile pornite de Prodi după august (company-directory, atom-core, findocs, vertigo-services, document-vault) au uniform README + CLAUDE.md specific + CONTEXT.md +
src//tests/+ pipelines, dar teste puține unde le-a scris el (company-directory 0[Fact]la 10.500 LOC, findocs 11, atom-core 0) și multe unde le-a scris Vlad (document-vault 247, vertigo-services 485). Șablonul garantează forma, nu testele; testele vin de la persoană. - Răspunsul onest la „depinde calitatea de Prodi?": forma (layout, docs, CI, deploy) depinde de șablon, iar șablonul de Prodi – și a apărut în septembrie, după ce SalarEasy, invoicing și waiting-list porniseră (toate trei sunt plate și fără README). Substanța (straturi, CQRS, teste, auth) nu a depins de prezența lui zilnică: Alex a livrat-o singur, cu AI (366/534 commit-uri co-semnate Claude, 39 mențiuni Codex ca reviewer) și cu direcțiile din aprilie (Slack cu Prodi, consemnat în
Rezumat_si_Probleme_Tehnice.md). - Riscul real la SalarEasy nu e calitatea codului, ci bus factor 1: 532/534 commit-uri sunt ale lui Alex, nu există README/CLAUDE.md,
maine mort, 41 de branch-uri neșterse. Un coleg nou sau un agent nu are de unde începe.
Tabel comparativ
LOC = producție / teste. „Layout casă" = straturile + src/ + tests/ + README + nuget.config, ca în company-directory. „CI teste" = pipeline care rulează testele pe fluxul obișnuit de push.
| Repo | Commit-uri total / Q3 | Autori | LOC prod / teste | Layout casă | Teste | CI teste | Auth | CLAUDE.md | ADR | Cel mai mare fișier prod | TODO |
|---|---|---|---|---|---|---|---|---|---|---|---|
| salareasy-api | 534 / 378 | alex-bono 532, chris 2 | 49.439 / 64.031 | Parțial (straturi DA; plat, SRV.*, fără README) | 2.860 în 307 fiș. | Doar pe PR | DA (Fallback + roluri) | NU | NU | EnrollmentServiceAdapter.cs 1.067 (11 >500) | 4 |
| salareasy-web | 538 / 340 | alex-bono 533, Claude 4, chris 1 | 38.051 / 34.625 | features/ + pages/ mixt | 1.567 unit + 292 e2e | NU (doar tsc) | – | NU (1 skill) | NU | AddEmployeePage.tsx 2.077 (6 >1000) | 0 |
| invoicing-services | 243 / 189 | Vlad 168, Adrian 32, Prodi 12, „Bono Name TODO" 24, Chris 7 | 19.010 / 11.295 | Parțial (plat, fără README) | 708 în 93 fiș. | DA | DA | 792 B | NU | QuestPdfInvoiceRenderer.cs 378 | 2 |
| efactura-services | 53 / 28 | Vlad 41, Claude 9, Chris 3 | 15.922 / 978 | Parțial (4 app-uri, fără CI/README) | 45 în 10 fiș. | NU (fără CI) | DA | 1,5 KB generic | NU | EInvoiceGenerator.cs 353 | 5 |
| vertigo-services | 86 / 86 | Vlad 86 | 11.680 / 10.474 | DA | 485 în 68 fiș. | DA | DA | 4,5 KB specific | 25 | ChangeRegisteredOffice.cs 205 | 0 |
| vertigo (BFF+React) | 31 / 31 | Adrian 31 | 6.768 TS + 923 C# / 0 | Șablon BFF | 0 | NU | DA (Google) | 12,5 KB | NU | DsComponentsSection.tsx 349 | 2 |
| waiting-list-services | 158 / 93 | Adrian 64, Prodi 44, Eduard 39, Chris 9 | 9.910 / 2.194 | Parțial (plat, fără README) | 119 în 12 fiș. | NU | DA | NU | NU | FindPeoplePagedQuery.cs 388 | 0 |
| waiting-list-web (Razor) | 228 / 131 | Adrian 110, Eduard 58, Prodi 47, Chris 8 | 4.401 C# + 1.617 cshtml / 0 | N/A (site public) | 0 | NU | N/A | NU | NU | PostHogLeadEventClient.cs 635 | 0 |
| waiting-list-admin (BFF+React) | 88 / 31 | Eduard 46, Prodi 21, Adrian 18, Chris 3 | 7.949 TS + 1.238 C# / 0 | Șablon BFF | 0 | NU | DA (Google) | 15 KB | NU | DesirePage.tsx 549 | 0 |
| atom-core | 12 / 12 | Vlad 12 | 3.944 / 0 | DA | 0 | NU | DA | 6,8 KB | 1 | 145 linii | 0 |
| findocs-services | 37 / 37 | Prodi 37 | 4.766 / 172 | DA | 11 în 1 fiș. | NU | DA | 5,6 KB | NU | AwsStorageServiceAdapter.cs 274 | 0 |
| document-vault-api | 40 / 40 | Vlad 40 | 6.114 / 7.790 | DA | 247 în 52 fiș. | DA | DA | 14,7 KB | 3 | <300 (top 5 sunt teste) | 0 |
| company-directory | 110 / 110 | Prodi 101, Claude 9 | 10.466 / 382 | DA (referința) | 0 [Fact] | NU | DA | 19 KB | NU | LuceneSearchReader.cs 248 | 0 |
Note: [Authorize] explicit e rar peste tot pentru că standardul e schema ApiKey aplicată global în Startup.cs; SalarEasy e singurul cu FallbackPolicy + politici pe rol. Nullable e enable în SalarEasy, efactura și BFF-uri, disable în majoritatea proiectelor lui Prodi. Zero controllere care ating ISession și zero repository-uri în toate cele 13 repo-uri.
SalarEasy în detaliu
Structură. SRV.Bono.Salarizare.{Api, Api.ServiceInterface, Api.ServiceAdapters, DomainModel, DomainServices, Common, Email, ScheduledTasks, Tests} + Bono.Infrastructure.NHibernate + MandrillLibrary (copie locală, nu pachetul Bono.Infrastructure.Mandrill folosit de invoicing și waiting-list). 42 entități .hbm.xml, 49 tabele, 76 migrații numerotate manual, 22 controllere cu 119 endpoint-uri, 14 job-uri Quartz. Logica stă în ServiceAdapters (19.051 linii) și DomainServices (16.989), controllerele sunt subțiri. QueryOver în 111 fișiere, SQL brut în 5.
Ce e bine.
- Testele nu sunt decorative:
Tests/Calculation/PayrollCalculatorTests.cs(1.924 linii),PayrollCombinationLeaveTests.cs,PayrollCombinationProfileTests.cs;test(d112): verify generated declarations with ANAF's DUKIntegrator– validare cu validatorul oficial;docker-compose.e2e.ymlcufake-reges; în webe2e/parity/(13 fișiere) verifică paritatea cu prototipul. - Securitate gândită:
Api/Security/AuthorizationPolicies.csexplică de ceEnrollmentIssuere doar ApiKey („un admin logat nu trebuie să poată emite linkuri pentru orice firmă"); rate limiter înainte de autentificare pe bootstrap-ul de autoangajare (Program.cs:43-48);Audit/AuditActionFilter.cs+ decoratori de audit. - Motorul de calcul e parametrizat:
KnownParamCode.PragScutireTaxe,SumaScutitaTaxedin tabela de parametri versionată;TaxExemptionNewRuleEffectiveDate = 2026-07-01; 15 clase mici înDomainServices/Calculation/(PersonalDeductionGridBuilder,ChildDeductionCalculator,MinimumWageValidator,RecurringBenefitSplitCalculator,GrossSalaryInForceResolver). - Plan înainte de cod:
docs/superpowers/plans/(D112 XML 236 KB, D112 PDF 61 KB), 18 faze înDocumentation/phase-plans/, 31 commit-uridocs:. Commit-uri granulare care spun de ce, cu review extern automat (address codex review of the submit saga).
Ce e riscant.
- Fișiere-monolit:
EnrollmentServiceAdapter.cs1.067,PayrollCalculator.cs971 (o metodă lungă cu pași A–K în comentarii),RegesReceiptProcessor.cs945,LeaveServiceAdapter.cs897,EmployeeServiceAdapter.cs867; web:AddEmployeePage.tsx2.077,EditEmployeePage.tsx1.288,AddMedicalLeavePage.tsx1.254,EmployeeSettingsPage.tsx1.227,AddCompanyPage.tsx1.099. - 160
catch (Exceptionîn producție și 31 de catch-uri care doar returnează/înghit (3 înLeaveServiceAdapter.cs, 2 înLibreOfficeDocxToPdfConverter.cs, câte 1 înRegesReceiptProcessor.cs,PayrollFinalizationGuard.cs,AnafController.cs) – de 5x peste orice alt repo (invoicing 6). TODO(tenant): no tenant filter herede două ori înReges/RegesServiceAdapter.cs:148,179– listări REGES fără filtru pe firmă. Aplicație internă, deci nu e breșă client, dar e un cuțit pe masă înainte de a deschide către clienți.Proxies/Topology/TopologyResolverRegistration.cs: „TEMPORARY MOCK boundary — REMOVE", fallback SIRUTA hardcodat din 19 aug, încă în cod.D112:BypassGate– gardă legală dezactivabilă prin config „pentru non-production hosts".- Igienă: 57 binare (~91 MB), foldere „Flux de angajare-20260415T…",
Salarizare_1.jpg,generate_excel_v1.py/.jsla rădăcină;mainmort din 13 aug; 41 branch-uri neșterse; migrații renumerotate de 4 ori (041→042→043,074→072) din cauza numerotării manuale. - Teste cu MariaDB local și credențiale în cod (
Tests/ScheduledTasks/PayrollRunJobTests.cs:38,RecurringBenefitMaterializationJobTests.cs:38), 10Skip =(„requires dev MySQL", „no DI seam"). - Zero ADR-uri pentru decizii cu consecințe legale (D112 v7, rotunjirea combinată CASS, „urmăm documentația clientului dacă ANAF nu respinge") – există doar în commit-uri și planuri de 200 KB.
Suprafața de domeniu (volum vs. calitate). REGES 7.809 linii producție (client, cozi, receipt processor, circuit pe respingeri de autentificare, rate limiter, nomenclator localități). D112 3.348 (model, XML declaratieUnica v7, PDF facsimil ANAF, secțiuni A/B/C, coduri casă, CAEN). Documente 5.839 (umplere .docx OpenXML cu {{#if}}, LibreOffice → PDF cu fallback QuestPDF, CIM, act adițional, acord de încetare, fișa postului, fluturaș, stat, notă contabilă, import CSV SAGA). Autoangajare 5.386 (sesiuni cu token-capabilitate, saga de submit, semnătură). Motor de calcul 2.330 în 15 clase (CAS/CASS/CAM/impozit, scutire, deducere personală pe grilă, deducere copii art. 77, tichete, beneficii art. 76 alin. 4^1 cu plafon anual + 33% lunar, concediu medical split firmă/Casa, pontaj, calendar). SalarEasy API singur e cât invoicing + vertigo-services + waiting-list-services + document-vault la un loc (49.400 vs. 46.700 LOC producție), pe un domeniu unde greșeala se plătește la ANAF.
Facturare (invoicing-services, efactura-services)
Invoicing are cea mai variată paternitate (7 identități git; „Bono Name TODO" cu 24 de commit-uri e un git neconfigurat) și e singurul din era pre-șablon cu CI care rulează testele pe main (708 [Fact], ultimele rulări verzi). Straturile casei, controllere subțiri, cel mai mare fișier 378 linii, 2 TODO. Lipsuri de formă: plat, fără README, CLAUDE.md cu o singură regulă, fără ADR; azure-pipelines.*, cloudbuild.yaml și Dockerfile coexistă – trei ținte de deploy, neclar care e activă.
Efactura e cel mai slab repo comparat: monorepo pe master cu 4 aplicații și 27 de csproj, 16.000 LOC și 45 de teste, fără niciun fișier CI, fără README, fără nuget.config, CLAUDE.md-uri de 1,1–1,5 KB care descriu stiva generic. Ultimul commit 5 aug. E codul lui Vlad din aceeași perioadă cu SalarEasy, fără șablon și fără presiunea testelor.
Vertigo (vertigo-services, vertigo)
vertigo-services e „șablon + persoană care testează": layout complet, 25 de ADR-uri (0020-employees-live-in-salareasy.md, 0025-documents-reach-the-vault-through-this-api.md), docs/salareasy-api-contract.md, 485 de teste, CI pe push la main/staging (verde), cel mai mare fișier 205 linii, zero TODO. E primul repo care consumă nucleul ca pachet (Bono.Core.DomainModel@0.4.0, Bono.DocumentVault.Api.ServiceInterface@0.1.0), nu ca copie.
vertigo (frontend) are 2 zile de viață (Adrian, 31 commit-uri) și e clona structurală a waiting-list-admin: BFF ASP.NET + React 19 / Vite 8 / TS 6 / Tailwind 4 / TanStack Query 5, strict + noUncheckedIndexedAccess, bono-ds.css (Edge), 1 any, CLAUDE.md 12,5 KB, BFF-ARCHITECTURE.md, STYLE.md. Zero teste, zero CI, dar cel mai mare fișier 349 linii.
Desire (waiting-list-services, -web, -admin)
Singurul produs cu echipă adevărată în git (Adrian, Eduard, Prodi, Chris), și arată cum arată codul de echipă înainte de șablon: -services are straturile casei și 119 teste, dar e plat, fără README/CLAUDE.md/ADR, cu deploy-staging.yml care publică fără să testeze. -web (Razor, public) are zero teste, PostHogLeadEventClient.cs 635 și EnrollmentApiController.cs 490 – controller gras, contrar regulii casei; are în schimb un .claude/skills/nhibernate-cqrs local. -admin e originalul șablonului BFF clonat în vertigo, zero teste.
Desire e mai uniform ca formă decât SalarEasy (Prodi e în 21–47 de commit-uri per repo), dar mult mai slab ca teste (119 + 0 + 0 față de 2.860 + 1.567 + 292). E dovada cea mai clară că prezența lui Prodi aduce convenții, nu acoperire de test.
Atom / Findocs / Vault (atom-core, findocs-services, document-vault-api, company-directory)
Repo-urile „post-retreat" (22 aug – 16 sept) sunt uniforme la milimetru: src/ + tests/, .slnx, README cu tabel de host-uri, CLAUDE.md specific (6–19 KB, cu „Facts", „Open questions", „House skills that own the next layers"), CONTEXT.md, docs/agents/, .scratch/, nuget.config cu feed bono.nuget, azure-pipelines.api.yml + .worker.yml, publish-packages.yml, .NET 10, NLog, Windows Service. company-directory (Prodi, 101 commit-uri în 12 zile) e referința declarată în README-ul lui atom-core și chiar e: cel mai mare fișier 248 linii, zero TODO, 14 documente în docs/. Diferența dintre ele e din nou testarea: document-vault (Vlad) 247 de teste în pipeline; company-directory (Prodi) un proiect IntegrationTests cu 8 fișiere și zero atribute xUnit; findocs 11; atom-core 0 („added step by step", spune README-ul).
Pentru SalarEasy contează două lucruri de aici: (a) șablonul nu exista când a pornit SalarEasy, deci nealinierea e cronologică, nu de atitudine; (b) atom-core publică Bono.Core.DomainModel ca pachet – exact mecanismul prin care SalarEasy poate intra în nucleu fără rescriere (ADR 0020 deja spune „employees live in salareasy").
Ce spune asta despre dependența de Prodi
Uniform indiferent de autor (vine din șablon/skills): straturile Api / ServiceInterface / ServiceAdapters / DomainModel / DomainServices / ScheduledTasks în toate cele 10 repo-uri C#, inclusiv la Alex; zero controllere pe ISession, zero repository-uri; CQRS Load*/Find*Query + Save*Command peste tot; Security/ApiKeyAuthenticationHandler.cs copiat identic în 9 repo-uri; niciun secret în appsettings; BFF-urile identice ca structură indiferent că le-au scris Eduard sau Adrian.
Diverge cu autorul (depinde de persoană):
- Testele: Alex 1,3 și Vlad 0,6–1,27 teste/producție; Prodi 0,04 și 0; Adrian/Eduard 0,22 și 0. Prodi scrie șablon și infrastructură, nu teste; Vlad și Alex scriu teste fără să le ceară nimeni.
- Mărimea fișierelor: Alex acceptă 900–2.000 de linii; Vlad și Prodi nu trec de 400. Stil personal plus presiune de livrare.
- Documentarea deciziilor: ADR-uri doar unde a fost Vlad după ce Prodi a pus convenția; Alex a scris 39.000 de linii de markdown în planuri, dar zero ADR și zero README; Prodi scrie README/CLAUDE.md excelente, dar puține teste.
- Igiena repo-ului: slabă la Alex (branch-uri, binare,
mainmort) și la echipa Desire/invoicing („Bono Name TODO" 29 de commit-uri), bună la Vlad și Prodi.
Ce depinde concret de Prodi: șablonul de repo a apărut în septembrie și e prezent numai în repo-urile pornite de el sau de Vlad după aceea. Cele pornite înainte (SalarEasy, invoicing, waiting-list, efactura) sunt toate plate și nedocumentate, indiferent de autor. Deci forma depinde de Prodi și de data de start a repo-ului; calitatea internă a codului nu. SalarEasy, construit fără feedback zilnic, e la nivelul lui Vlad ca disciplină de arhitectură și peste toți ca testare, dar sub nivelul casei ca formă și igienă – exact ce te aștepți de la un om bun care a lucrat singur, cu AI, fără cineva care să-i ceară README-ul și să-i șteargă branch-urile.
Recomandări concrete
- SalarEasy: forma casei fără să atingi codul (3–4 zile Alex + 1h review Prodi). README,
CLAUDE.mdspecific (pornind dinDocumentation/project-standards/),CONTEXT.md,src//tests/, scoaterea celor 57 de binare însalareasy-product/Drive,main=staging, ștergerea celor 41 de branch-uri. - SalarEasy: 8–10 ADR-uri retroactive (2 zile). D112 v7 și regula „documentația clientului dacă ANAF nu respinge", rotunjirea combinată CASS, salariul în vigoare pe lună, plafonul 33%, split concediu medical,
D112:BypassGate, sediul versionat, numerotarea contractelor. Sunt deja scrise în commit-uri; trebuie doar extrase îndocs/adr/ca în vertigo-services. - SalarEasy: CI care chiar rulează testele (1–2 zile).
ci.ymlpe push lastaging, cu serviciu MariaDB în Actions și connection string din env;vitest runînbuild-staging.yml. - SalarEasy: spargerea celor 5 fișiere de peste 900 de linii (5–8 zile, fezabil cu agent, testele existente sunt plasa). Întâi
PayrollCalculator.cs(pașii A–K sunt deja marcați), pentru că se schimbă la fiecare ordonanță;AddEmployeePage.tsxîn feature-vertical. - SalarEasy: cele trei cuțite de pe masă (1 zi).
TODO(tenant)dinRegesServiceAdapter.cs:148,179,TopologyResolverRegistration.cs„TEMPORARY MOCK",D112:BypassGaterefuzat la pornire în Production. - Efactura: păstrare sau arhivare (½ zi decizie, 3 zile aliniere dacă rămâne). Fără CI, fără README, 45 de teste, ultimul commit 5 aug. Ori tratamentul de la punctul 1 +
ci.yml, orizz-archived-. - Invoicing și waiting-list-services: README + CLAUDE.md +
src//tests/(1–2 zile fiecare),dotnet testîndeploy-staging.ymlla waiting-list. Plusgit config user.namepe mașina care semnează „Bono Name TODO". - Regulă de echipă: teste și ADR-uri în definiția de „gata" a șablonului. Repo-urile lui Prodi au 0–11 teste. Dacă
company-directorye referința, referința trebuie să aibă teste în pipeline (ca document-vault și vertigo-services), altfel echipa învață că testele sunt opționale exact de la modelul de urmat. 2 zile company-directory, 1 zi findocs, o linie înrepo-layout.md.
The Bono Way · v2 · Planul de lansare · 19 septembrie 2026 · pregătit de Claude pentru Bogdan; capitolele se rescriu de owner-ii lor. Sursa: repo „Bono Waiy", Markdown.