Temă
Arhitectura
Pe scurt
Taraba e un monorepo cu trei aplicații web React și un API PHP (Laravel). Toate aplicațiile vorbesc cu API-ul prin GraphQL (date) și REST (fișiere, export, SEO), pe același domeniu prin nginx, deci autentificarea folosește cookie-uri HttpOnly fără CORS. Datele stau în MySQL; tot acolo stau sesiunile, limitările de încercări, codurile temporare și blocările proceselor periodice (fără Redis); fotografiile și documentele stau pe discul serverului (storage/app), servite de API. E-mailurile, SMS-urile și notificările push trec printr-un gateway care, în dezvoltare, le captează în Mailpit.
Componente
| Componentă | Tehnologie | Rol |
|---|---|---|
apps/site | React 19, Vite 8, React Router 8, TanStack Query 5 | site-ul public: căutare, anunțuri, vânzare, mesaje, checkout, comenzi, cont |
apps/backoffice | React 19, același cadru de spațiu de lucru | operațiuni: moderare, dispute, suport, utilizatori, comenzi, plăți, rapoarte, setări, echipă |
apps/crm | React 19, același cadru | marketing: contacte, segmente, campanii, automatizări, cupoane, analize |
apps/api | PHP 8.3+, Laravel 13, Lighthouse 6 (GraphQL schema-first), query builder (fără ORM) | toată logica de business, accesul la date, procese periodice |
packages/shared | TypeScript | rutele site-ului (sursă unică pentru linkuri), formatarea banilor |
packages/ui | React | traduceri (6 limbi), temă, client GraphQL, cadrul spațiului de lucru (conectare în doi pași, meniu, grafice) |
packages/vite-config | Vite | configurația comună a aplicațiilor (proxy către API în dezvoltare) |
apps/status | React 19, Vite 8 | starea întregii platforme: aplicațiile web (verificate de API din rețeaua internă), serviciile, mesaje de test (port 8084) |
apps/docs | VitePress 1.6 | site-ul intern al documentației, generat din docs/ (port 8083) |
tests/e2e | Node, fetch | 14 suite end-to-end ale API-ului (GraphQL și REST), contractul pe care se bazează aplicațiile |
tests/browser | Playwright, axe-core | parcursul complet prin cele trei aplicații, accesibilitate WCAG 2.1 AA |
Modulele API-ului
Fiecare modul (app/Modules/<Modul>) are serviciile, regulile și rutele REST ale lui; fiecare operație GraphQL are clasa ei (app/GraphQL/Queries, app/GraphQL/Mutations), care verifică accesul și apelează modulul. Datele se citesc și se scriu cu query builder-ul Laravel, în tranzacții acolo unde mai multe tabele se schimbă împreună.
| Modul | Responsabilitate |
|---|---|
auth | sesiuni clienți și echipă (în baza de date, tokenul stocat ca hash SHA-256), parole Argon2id, TOTP (RFC 6238), dispozitive de încredere, limitarea încercărilor, linkuri unice |
accounts | profil, setări, acorduri de marketing, IBAN, export și ștergere GDPR |
verification | cod SMS pentru telefon, verificarea identității (document privat), fotografia de profil |
catalog | categorii, căutare (MySQL FULLTEXT), anunțuri, fotografii (Intervention Image: WebP, fără metadate EXIF), favorite, căutări salvate, SEO (sitemap, robots) |
messaging | conversații, mesaje, oferte cu expirare |
commerce | checkout, plăți (simulate), comenzi, livrare, confirmare automată, evaluări, promovări |
notifications | notificări în aplicație, distribuire push după preferințe |
trust | raportări (anunțuri, utilizatori), dispute, suspendări |
support | tichete și răspunsuri pe e-mail |
backoffice | panou, moderare, administrarea utilizatorilor și comenzilor |
administration | anunțuri, categorii, cuvinte interzise, setări validate, plăți către vânzători, rapoarte, echipă, audit |
crm | contacte, segmente (SQL parametrizat), campanii, automatizări, cupoane, șabloane, analize, dezabonare |
platform | setări (cu cache), jurnal de audit |
health, diagnostics | stare servicii; mesaje de test (doar cu DIAGNOSTICS_ENABLED) |
Comunicare
GraphQL — POST /api/graphql, 185 de operații (referința). Erorile au extensions.code stabil, pe care interfața îl traduce în mesaje clare.
REST — doar unde GraphQL nu se potrivește:
| Endpoint | Acces | Scop |
|---|---|---|
POST /api/uploads/listing-photos | client | fotografie de anunț (multipart, max. 12 MB) |
POST /api/uploads/avatar | client | fotografie de profil |
POST /api/uploads/identity-document | client | actul de identitate (stocare privată) |
GET /api/media/* | public | imagini publice (listings/, avatars/, ilustrațiile demo) |
GET /api/staff/identity-documents/:id | echipă (verify_identity) | documentul, fără cache, cu audit |
GET /api/account/export | client | exportul GDPR (JSON) |
GET/POST /api/crm/unsubscribe | public (link semnat) | dezabonare (inclusiv one-click din clientul de e-mail) |
GET /robots.txt, /sitemap.xml, /sitemap-N.xml | public | SEO, servite de API prin nginx |
GET /api/health/live, /api/health | public | stare |
Procese periodice
Le pornește planificatorul Laravel: php artisan schedule:work în Docker, un cron la fiecare minut pe cPanel. Fiecare rulare ia blocarea procesului (în baza de date), deci un proces nu rulează niciodată de două ori în același timp, nici când e pornit și manual (operarea).
| Proces | Frecvență | Ce face |
|---|---|---|
| Confirmarea automată a comenzilor | la 10 minute | finalizează comenzile livrate fără reacție de 48 de ore și programează plata |
| Plăți către vânzători | orar | trimite plățile scadente (sau le marchează eșuate fără IBAN) |
| Alerte pentru căutările salvate | orar | anunță persoanele când apar anunțuri noi pentru căutările lor (și le înscrie în automatizarea CRM) |
| Alerte de stare | 5 min (configurabil, ALERT_CHECK_SECONDS) | e-mail către echipă când ceva cade și când își revine (doar cu ALERT_EMAILS) |
| Campanii programate | la 1 minut | trimite campaniile a căror oră a venit (inclusiv cele amânate de orele de liniște) |
| Automatizări CRM | la 5 minute | înscrie persoanele noi și execută pașii scadenți |
| Amintiri juridice | zilnic | anunță persoanele care nu au acceptat încă o versiune nouă a termenilor |
| Curățarea sesiunilor | orar | șterge sesiunile și linkurile unice expirate |
Decizii de arhitectură
| Decizie | De ce |
|---|---|
| Un singur API pentru trei aplicații | o singură sursă pentru reguli (prețuri, permisiuni, acorduri); aplicațiile rămân subțiri |
| GraphQL schema-first | schema (apps/api/graphql/schema.graphql) e contractul cu aplicațiile; testele e2e verifică fiecare operație pe care o folosesc |
| PHP pe găzduire obișnuită | rulează pe orice cPanel, fără Node.js, Redis sau stocare externă pe server |
| Același domeniu prin nginx, cookie HttpOnly | fără token-uri în JavaScript, fără CORS în producție |
| Bani în bani (numere întregi) | fără erori de rotunjire; formatarea doar la afișare |
| Moderare umană înainte de publicare | încrederea e propunerea de valoare; semnalele automate doar ajută omul |
| Gateway-uri pentru SMS, push și e-mail de marketing | furnizorul real se schimbă fără să atingă logica; în dezvoltare nimic nu pleacă la oameni |
| Documentele de identitate în prefix privat, șterse la decizie | minimizarea datelor (GDPR); imposibil de servit public din greșeală |
| Setări în baza de date, validate și auditate | comisioanele și regulile se schimbă fără release |
| Audit pentru acțiunile echipei | trasabilitate pentru dispute, suspendări, bani și date sensibile |
Structura codului
apps/
api/ app/Modules/<Modul>/ app/GraphQL/{Queries,Mutations} graphql/schema.graphql
database/{migrations,seeders} routes/{api,console}.php tests/{Unit,Feature}
site/ src/{features,api,layout,lib,ui,i18n}
backoffice/ src/{pages,api,lib}
crm/ src/{pages,api}
packages/ shared, ui (+ ui/src/workspace), vite-config
tests/e2e/ cele 14 suite end-to-end ale API-ului
tests/browser/ parcursul complet, accesibilitate
docs/ această documentație; docs/tools generează diagramele
docker/ imaginile (api, aplicații web, documentație, backup, dezvoltare) și configurația nginx
docker-compose.yml rularea ca în producție
docker-compose.dev.yml dezvoltare cu codul montat live