# AutoPass — Roadmap & Proces de Dezvoltare
> **Sursa unica de progres + procesul de lucru.** O sesiune noua are nevoie doar de promptul:
> *"Citeste docs/ROADMAP.md si continua roadmap-ul [optional: livrabila X.Y]."*
> Sesiunea isi detecteaza singura faza (§5.7), planifica SAU executa, verifica si inchide —
> cu doua porti umane: aprobarea PRD-ului si confirmarea commit-ului.
>
> Contractul RAR (sursa de adevar de contract) = `docs/api-rar-contract.md`. Acolo unde un plan
> difera de contract, **contractul are dreptate**.
>
> Status fara emoji (preferinta proiect): **TODO** neinceput · **WIP** in lucru · **DONE** gata ·
> **BLOCAT** blocat de o dependenta · **AMANAT** deferat/taiat cu motiv.
---
## 1. Context
Gateway central care declara prestatiile de service-auto la **RAR AUTOPASS** (Legea 142/2023,
OM 210/2024), portat din clasa Visual FoxPro `RarAutoPass` (ROAAUTO). Stack: **Python/FastAPI +
SQLite (WAL) + httpx + Jinja2/HTMX**. Un container (API) + un proces separat (worker).
Doua canale de intrare, ambele **LIVE pe endpoint-ul de test RAR**:
- **Treapta 1** — canal API (`POST /v1/prezentari`) pentru ROAAUTO / soft propriu.
- **Treapta 2** — import xlsx/csv + mapare coloane + UI web (HTMX) pentru service-uri non-ROA.
---
## 2. Arhitectura (rezumat)
```
Canal API (ROAAUTO) ─┐
Upload web (xlsx/csv) ─┴─▶ Gateway FastAPI ─▶ validare → mapare op→cod → enqueue (PII criptat)
│
▼
WORKER (proces separat): claim atomic → login RAR → postPrezentare → retry
│
Dashboard (Jinja2+HTMX) ◀───────┴── monitorizare live RAR + coada + editor mapari + audit CSV
```
Reguli de contract (detalii in `docs/api-rar-contract.md`): `FINALIZATA` e terminal la RAR
(fara anulare/corectie prin API); idempotency = hash de continut server-side; JWT TTL = 30h.
---
## 3. Stadiu Implementare (dashboard)
> **Singurul loc din document care se modifica pe parcurs.** Detaliile NU intra aici — stau in
> PRD-uri (`docs/prd/prd-X.Y-*.md`), linkate in coloana Detalii. La fiecare livrabila terminata:
> schimba statusul + data + linkul PRD si actualizeaza "Ultima actualizare".
**Ultima actualizare**: 2026-06-23 — 5.5 APROBAT + IN EXECUTIE (uniformizare/standardizare UI/UX: tabele la grila Trimiteri, meniu hamburger + tab-bar redus Acasa/Mapari, panou admin cu selectie+bulk pe model nou `accounts.status`. 9 stories in 3 valuri, UI pur cu o singura exceptie backend = stare cont. Design+PRD aprobate, vezi randul 5.5). | ISTORIC: 5.4 LIVRAT (Erori pe 3 niveluri problema+cauza+fix pe API si UI: catalog central pur `app/errors.py` ca SINGURA sursa de adevar cod→{problema,fix}, consumat de API+UI+worker — face imposibila divergenta intre canale, acelasi invariant ca 5.2. 8 stories in 5 valuri. Tot ADITIV: `field`/`message`/`error` pastrate la octet, adaugam `cod/problema/cauza/fix`; `rar_error` stocat = SUPERSET (chei vechi intacte → `labels.py` nu se rupe intre valuri, zero migrare). Scope = fluxul de declarare; login/signup/CSRF neatinse. UI progresiv: lista compacta, 3 niveluri complete in detaliu/preview, AA light+dark. VERIFY context curat PASS 628 teste (byte-compat+superset verificate direct, E2E API+web; live RAR neprobat — lipsa creds key). `/code-review high`: 2 bug-uri reale reparate in `labels.py` (`motiv_uman` fara ramura 3-niveluri → 401 creds garbled in coloana Motiv; `parse_erori` element gol pe `{}`). 631 teste. Backend trimitere + schema NEATINSE. PRD: [prd-5.4](prd/prd-5.4-erori-3-niveluri.md)). | ISTORIC: 5.3 LIVRAT (Light/Dark mode: tema light ca bloc `[data-theme="light"]` peste variabilele `:root` — dark NESCHIMBAT la octet; comutator soare/luna in header pe toate paginile, default OS-aware cu fallback dark, persistenta `localStorage` doar la comutare explicita, script anti-FOUC in `
` pre-paint; suprafetele de stare hardcodate convertite la `color-mix` in `base.html` + 7 fragmente. Zero backend — pur frontend. VERIFY 2 runde: r1 FAIL a prins literalii dark ramasi in 7 fragmente HTMX (text invizibil in light, test vacuu pe doar base.html) → fix US-003 + test care scaneaza fragmentele; r2 PASS E2E browser (banner light ~13:1 contrast, toggle instant+persista+anti-FOUC, dark identic). `/code-review` high: 1 finding reparat (light `--ok` green sub AA ca text → green-700, ~5.0:1). 584 teste. PRD: [prd-5.3](prd/prd-5.3-light-dark-mode.md)). | ISTORIC: 5.2 LIVRAT (Endpoint dry-run `POST /v1/prezentari/valideaza`: valideaza payload + mapare si intoarce verdictul real — `status_estimat` queued/needs_data/needs_mapping + erori `[{field,message}]` + coduri nemapate + prestatii rezolvate — FARA enqueue, FARA creds, zero scriere DB). 1 story TDD. Cheia de design: helper pur partajat `classify_prezentare` folosit de AMBELE rute, ca dry-run-ul sa nu poata diverge de trimiterea reala (invariant de corectitudine); `create_prezentari` refactorizat pe el cu comportament identic. Scope minim per decizie user: doar validare+mapare (fara idempotency/duplicat, `idempotency.py` neatins), hub `/integrare` amanat ca follow-up (descoperibilitate). VERIFY context curat PASS (577 teste; E2E API cu cele 3 verdicte + COUNT(*)=0 dupa dry-run + fara leak creds in raspuns; regresia de aur verde; live RAR `FINALIZATA` neprobat — lipsa creds key, endpoint read-only nu atinge worker/coada/schema). `/code-review` high: 0 findings (refactor faithful, mutable-default Pydantic-safe, import local necesar anti-circular). PRD: [prd-5.2](prd/prd-5.2-dryrun-valideaza.md). | ISTORIC: 5.1 LIVRAT (Hub de integrare `/integrare`: exemple cod multi-limbaj + retetar VFP cu 2 dialecte + `GET /v1/ping` readiness + export Postman/OpenAPI + "Testeaza conexiunea"). 4 stories in 2 valuri (Val 1 = US-001/US-002/US-004 paralel pe fisiere disjuncte via Agent team; Val 2 = US-003 UI). Atentie operationala: US-003 a rulat intr-un worktree branched din ultimul commit (FARA modificarile necomise ale US-004 din working-tree) si la "copiere manuala" a SUPRASCRIS `routes.py`, stergand ruta `POST /integrare/test-cheie` (8 teste 404) — reparat prin re-aplicarea rutei de catre autorul US-004 pe `routes.py` curent. Lectie: stories care ating acelasi fisier in valuri diferite + worktree = clobber daca worktree-ul nu vede working-tree-ul; foloseste fisiere disjuncte SAU merge atent de catre lead. VERIFY context curat PASS (568 teste) + E2E browser Playwright (deep-link server-side, IA pe 2 niveluri, VFP cu 3 niveluri de tab comuta corect, copy, htmx test-cheie → fragment eroare, 0 erori consola) + enqueue live (`POST /v1/prezentari` → queued); live RAR `FINALIZATA` NEPROBAT in sesiune (lipsa `AUTOPASS_CREDS_KEY`/creds RAR test) — risc minim, backend trimitere NEATINS. `/code-review` high a prins 4 bug-uri reale (toate in suprafata noua, reparate + lock-uite cu teste): snippet C# JSON multi-linie nevalid (CS1010), snippet VFP `json.dumps(indent=0)` inca cu newline-uri → string literal rupt in ambele dialecte, snippet Node `node:buffer` nu exporta FormData → TypeError, script `_integrare.html` ne-scoped acumuland event-listeneri pe tab-bar-ul principal la fiecare swap htmx (scoped pe `#integrare-section`). Notat ca cleanup viitor (nereparat): `_render_integrare` dubleaza SQL `are_creds`/`are_cheie`, `ping` cu 2 conexiuni DB + `account_for_key` de 2 ori, `_campuri_obligatorii` necache-uit, panouri limbaj copy-paste (candidat macro Jinja2). Backend trimitere (worker/masina stari/idempotenta/mapping) si schema NEATINSE. PRD: [prd-5.1](prd/prd-5.1-hub-integrare.md). | ISTORIC: 3.6 INCHIS (editare celule in preview + Acasa unificata). CLOSE: `/code-review` high a prins 1 bug real (decriptare `override_json` neprotejata de try/except in ambele cai de preview — 500 pe tot batch-ul la rotatie cheie Fernet vs. `raw_json` care degrada gratios), reparat in `import_router.preview_import` + `routes._web_compute_preview`; duplicarea `_override_of`/canonicalize notata ca cleanup viitor. 523 teste pass. 7 stories in 3 valuri, executate de 2 echipe in paralel (TeamCreate) pe fisiere disjuncte (core: routes/import/templates; mapari: `_mapari.html`) + US-007 secvential. Livrate: tab "Trimiteri" eliminat→sectiune "Trimiterile tale" sub upload pe Acasa (US-003); upload bara slim accentuata cu hero la first-run (US-004); editare de celule in preview prin `import_rows.override_json` (Approach B, Fernet, patch canonic aplicat ULTIMUL in `_resolve_row_for_preview`+`commit_import` — completeaza inclusiv coloane ABSENTE din fisier), mutatie pura cu status rederivat (US-001); buton Editeaza pe rand cu swap pe ``+OOB contoare (nu pe sectiune), form propriu, mutual-exclusion, reuse grila `_trimitere_detaliu.html` (US-002); Mapari + formate de coloane ca tabele `.tablewrap`, H4 auto_send stocat (US-005/006); bifa "auto-send"→comutator etichetat pe COADA ("Pune automat in coada"/"Tine pentru verificare"), scoped pe operatie, `name=auto_send` pastrat (zero backend) (US-007). 523 teste pass. **VERIFY**: E2E browser pe `/` (Acasa unificata, upload slim, editare rand needs_data→ok cu swap pe rand + contoare OOB, Mapari tabelar + comutator) + LIVE pe RAR test — import fara coloana data → editarea completeaza data (override) → commit → worker login RAR test → `postPrezentare` → `sent` cu `idPrezentare=68696`, confirmat independent in lista finalizate RAR. 3 bug-uri JS (htmx 1.9.12) prinse DOAR la E2E in browser (invizibile la TestClient) si reparate: `useTemplateFragments=true` (raspunsul `
`+OOB era parsat in context de tabel → `swapError` + contoare pierdute), re-activare `confirm-btn` deferita pe tick (race `editing=true` tranzitoriu), `n-hint` ok-count actualizat de `updateN`. Backend trimitere (worker, masina stari, idempotenta-logica, mapping-rezolvare) NEATINS — singura atingere de schema: 1 coloana nullable `override_json` cu migrare defensiva. PRD: [prd-3.6](prd/prd-3.6-editare-preview-acasa-unificata.md). | ISTORIC: 3.5 LIVRAT (dashboard compact). 11 stories in 4 valuri, TDD. US-001 bara status compacta pe 2 randuri cu bife accesibile (glife ✓/✗ + text, nu doar culoare) + `format_data_rar` (dd.mm.yyyy hh24:mi:ss, helper pur). US-002 Acasa = ecranul de import (upload dominant inline, tab Import scos, `?tab=import`→Acasa fara 404). US-003 helper pur partajat `app/payload_view.py` (payload→campuri afisabile, defensiv, coercion Excel) refolosit si de `GET /v1/prezentari` (DRY). US-004 "Coada"→"Trimiteri": coloane RO + stare umana + detaliu complet la click in panou dedicat `#trimitere-detaliu` (nu inline — poll 10s), scoped 404 cross-account. US-005/006 CRUD mapari operatii + formate coloane salvate (scoped, re-rezolvare auto la edit cod). US-007 "Mapari" 3 sectiuni (de rezolvat / op salvate / formate coloane), "Cont" doar cheie+creds. US-008 motiv (mesaj validare) pe randuri needs_data in preview. US-009 filtre Trimiteri (stare SQL / vehicul+data Python) scoped + "sterge filtrele". US-010 corectie inline needs_data→queued cu payload+idempotency recalculate, sent read-only (403), coliziune idempotency prinsa pre-UPDATE. US-011 badge contoare pe tab-uri (Mapari/Trimiteri), scoped, aria-label. VERIFY context curat PASS (483 teste; E2E browser/RAR LIVE neprobat — recomandata probare manuala `--send`). `/code-review` high a prins 4 findings reale, toate reparate: corectie needs_mapping re-rezolva prestatiile (nu mai poate trimite cod nul la RAR), filtru fara LIMIT silentios, coliziune idempotency atomica (try/except IntegrityError), comparatie data doar ISO. Backend trimitere (worker, masina stari, idempotenta-logica, mapping-rezolvare, schema) NEATINS. PRD: [prd-3.5](prd/prd-3.5-dashboard-compact-trimiteri-mapari.md). Urmeaza Etapa 4 (4.1 mapare AI/MCP).
> 2026-06-18 — 3.4 LIVRAT (interfata web ergonomica: tab-uri + wizard + microcopy). US-001 modul pur `app/web/labels.py` (stari tehnice→text uman + clasa CSS; test parametrizat din CHECK-ul `schema.sql` iese rosu la stare nemapata). US-002 bara status `/_fragments/status` + `_status.html` (etichete umane, defalcare blocate pe motiv, poll 15s, scoped pe cont). US-003 shell 6 tab-uri (Acasa·Import·Coada·Mapari·Cont·Nomenclator) cu deep-link `?tab=`, panou activ randat server-side, fragmente inactive lazy pe click, ARIA real (tablist/tab/tabpanel + aria-selected + navigare cu sageti). US-004 stepper import 4 pasi (PUR vizual, `hx-target="#import-section"` + csrf pastrate). US-005 Acasa onboarding checklist auto-bifat (are_creds/are_trimiteri) + colaps cand totul gata + empty states prietenoase Coada/Mapari. VERIFY lead-driven (TestClient ACs + 434 pytest pass; E2E browser/RAR LIVE neprobat in sesiune — recomandata probare manuala `--send`). Fix izolare teste (reset `ratelimit._hits` in fixturi, 429 la rulare subset). `/code-review` high: regasit avertisment "cont in asteptare de activare" (regresie din scoaterea `/_fragments/banner`) re-introdus in bara status + culori hardcodate→variabile paleta. 434 teste pass. Backend trimitere neatins. PRD: [prd-3.4](prd/prd-3.4-ux-dashboard-web.md). Urmeaza Etapa 4 (4.1 mapare AI/MCP).
> 3.3b LIVRAT (self-service cheie/creds + admin web + email). US-007 rute web proprii pentru rotire cheie + setare creds RAR scoped pe sesiune (C13, nu endpointul API). US-010 rol admin (`users.is_admin`) + `require_admin`→`AdminRequired`→403 + CLI `tools/account.py set-admin` + bootstrap automat (primul cont care se inregistreaza = admin, citit in `BEGIN IMMEDIATE` anti-race). US-011 panou `/admin` (conturi in asteptare/active, activare/dezactivare cu CSRF + PRG, contul dev id=1 protejat) + link "Panou admin" pe dashboard doar pentru admini + buton logout. US-012 `app/email.py notify_signup` best-effort DEGRADAT fara SMTP (no-op + log, prinde orice exceptie, nu blocheaza signup) + config `smtp_*`. Fix migrare defensiva `users.is_admin`/`email_verified` in `_migrate` (gap prins de VERIFY r1, ca C1 pe `accounts.active`). 2 runde VERIFY context curat (r2 PASS, sweep securitate toate rutele noi sub require_login/require_admin + CSRF, scoped sesiune). `/code-review` high: TOCTOU bootstrap mutat in tranzactie + `_render_admin` extras (anti-duplicare + N+1). 393 teste pass. Urmeaza Etapa 4 (4.1 mapare AI/MCP). Deferat din 3.1 (P3): `rename`/`set-cui`, `--if-not-exists`. SMTP real = follow-up pe US-012.
> 3.3a LIVRAT (self-onboarding web core: `app/users.py` parole scrypt cu eticheta de parametri onorata la verify; `SessionMiddleware` same_site=strict + `app/web/session.py` guard `require_login`→`LoginRequired`; CSRF per-sesiune enforce in prod inclusiv pe login/signup + rate-limit signup & login in-proces; signup `active=0` tranzactie atomica + cheie-o-data + log `SIGNUP`; login/logout; dashboard & import multi-tenant scoped pe sesiune cu regula NULL→cont 1 — toate rutele web care ating date sensibile sub `require_login` + scope; gate worker `claim_one` `LEFT JOIN ... COALESCE(active,1)=1`. 2 runde VERIFY context curat — runda 1 a prins un leak cross-account pe `/_fragments/mapari`, reparat; runda 2 PASS. `/code-review` high a prins 3 findings, reparate. 361 teste pass). Urmeaza 3.3b (self-service cheie/creds + admin web + email). Deferat din 3.1 (P3): `rename`/`set-cui`, `--if-not-exists`.
### Etapa 1 — Canal API ROAAUTO (Treapta 1)
| # | Livrabila | Status | Data | Detalii |
|---|-----------|--------|------|---------|
| 1.1 | Gateway complet: validare + mapare + coada + worker + reconciliere + dashboard | DONE | 2026-06-15 | E2E LIVE prin gateway: `POST /v1/prezentari` → worker → `FINALIZATA` la RAR test (`idPrezentare=68516`). Cod `app/`, 279 teste. |
### Etapa 2 — Import xlsx/csv + UI web (Treapta 2)
| # | Livrabila | Status | Data | Detalii |
|---|-----------|--------|------|---------|
| 2.1 | Parser xlsx/csv 2-treceri + staging criptat (`POST /v1/import`) | DONE | 2026-06 | `app/import_parse.py`; encoding RO, delimiter sniff, coercion, robustete sheet/merged/footer |
| 2.2 | Creds RAR durabile per-cont + worker re-login fallback | DONE | 2026-06 | `accounts.rar_creds_enc`, gate purjare worker |
| 2.3 | `batch_id` scope `reresolve_account` (inchide R1 bulk-send) | DONE | 2026-06 | `app/mapping.py` |
| 2.4 | Mapare coloane + semnatura + detectie drift + fuzzy | DONE | 2026-06 | `app/api/v1/import_router.py` |
| 2.5 | Preview 6 stari + canonicalize partajat + gate HARD + atestare | DONE | 2026-06 | `duplicate_in_file`, `already_sent`, `needs_review`, `import_attestations`, TOCTOU `ON CONFLICT` |
| 2.6 | UI web upload HTMX (drop → mapare → preview → confirma) | DONE | 2026-06 | `app/web/templates/_upload.html`, `_mapcoloane.html`, `_preview_import.html` |
| 2.7 | Export randuri esuate CSV + job purjare `purge_after` + E2E | DONE | 2026-06 | `export_failed_rows`, `tests/test_import_e2e.py` |
### Etapa 3 — Multi-cont / self-onboarding (URMATORUL FOCUS)
| # | Livrabila | Status | Data | Detalii |
|---|-----------|--------|------|---------|
| 3.1 | Creare cont nou (CLI dedicat) | DONE | 2026-06-17 | CLI `tools/account.py` (create/list[--pending]/activate/deactivate, `--with-key` atomic) + `accounts.active` + index unic CUI + `app/accounts.py`. 20 teste noi. PRD: [prd-3.1](prd/prd-3.1-creare-cont.md) |
| 3.2 | Filtrare pe cont a GET-urilor de listare | DONE | 2026-06-17 | scope cheie pe `/v1/prezentari(/{id})`, `/v1/mapari(/pending)`, `/v1/audit/export` (NULL→cont 1); nomenclator global; 404 cross-account identic (B3) + allowlist campuri detaliu (B4) + helper `account_scope_clause` (B2) + index (B5). 14 teste noi, 313 pass. PRD: [prd-3.2](prd/prd-3.2-filtrare-cont-get.md) |
| 3.3a | Self-onboarding web (core) | DONE | 2026-06-17 | `users` (scrypt) + sesiune (`SessionMiddleware`, same_site=strict) + CSRF (enforce prod, inclusiv login/signup) + rate-limit signup/login + signup/login/logout + dashboard & import scoped pe sesiune (NULL→1, anti-leak C6) + gate worker `active=0` (`COALESCE`). 2 runde VERIFY (leak `/_fragments/mapari` prins+reparat) + code-review (csrf erori, scrypt_params, login rate-limit). 361 teste. PRD: [prd-3.3](prd/prd-3.3-self-onboarding-web.md) |
| 3.3b | Self-service cheie/creds + admin web + email | DONE | 2026-06-18 | US-007 (rute web proprii `/cont/roteste-cheie`+`/cont/rar-creds` scoped sesiune, C13), US-010 (rol admin `is_admin` + `require_admin`→403 + CLI `set-admin` + bootstrap primul cont=admin), US-011 (`/admin` activare/dezactivare cu CSRF+PRG, link doar pt admini + logout), US-012 (`app/email.py` notify best-effort degradat fara SMTP + log `SIGNUP`). Fix migrare defensiva `users.is_admin`/`email_verified`. 2 runde VERIFY context curat (r1 a prins migrarea lipsa, reparat; r2 PASS) + `/code-review` high (TOCTOU bootstrap admin mutat in tranzactie + extras `_render_admin` anti-duplicare/N+1). 393 teste. PRD: [prd-3.3](prd/prd-3.3-self-onboarding-web.md) |
| 3.4 | Interfata web ergonomica (tab-uri + wizard + microcopy uman) | DONE | 2026-06-18 | Dashboard reorganizat in 6 tab-uri (Acasa·Import·Coada·Mapari·Cont·Nomenclator) cu deep-link `?tab=` + panou activ server-side + lazy pe rest; bara status cu etichete umane (`app/web/labels.py`) + defalcare blocate; import ca stepper 4 pasi (PUR vizual); Acasa onboarding auto-bifat + empty states. Backend trimitere neatins. 434 teste. PRD: [prd-3.4](prd/prd-3.4-ux-dashboard-web.md) |
| 3.5 | Dashboard compact: import pe prima pagina, status cu bife, Trimiteri lizibile, Mapari complete | DONE | 2026-06-19 | 11 stories (4 valuri), 3 review-uri de plan facute. Acasa=ecran de import (scoate tab Import); bara status compacta font normal + bife accesibile (auto-send/RAR) + data `dd.mm.yyyy hh24:mi:ss`; "Coada"→"Trimiteri" cu coloane RO + detalii comanda din `payload_json` (helper partajat `payload_view.py`) + detaliu la click in panou dedicat; filtrare Trimiteri (US-009); corectie inline `needs_data` cu re-enqueue + detectie coliziune idempotency (US-010); badge contoare pe tab-uri (US-011); "Mapari" 3 sectiuni (de rezolvat / op salvate cu re-rezolvare auto / formate coloane), "Cont"=doar cheie+creds; feedback `needs_data` la import. Backend trimitere neatins. PRD: [prd-3.5](prd/prd-3.5-dashboard-compact-trimiteri-mapari.md) |
| 3.6 | Editare celule in preview + Acasa unificata (Trimiteri inline, upload slim, Mapari tabelar, comutator coada) | DONE | 2026-06-22 | 7 stories (3 valuri), 2 echipe in paralel (TeamCreate) pe fisiere disjuncte + US-007 secvential. US-003/004 tab "Trimiteri" eliminat→sectiune "Trimiterile tale" sub upload pe Acasa; upload bara slim (hero la first-run); `?tab=coada`+`/_fragments/coada`→Acasa; poll gated visibilityState. US-001 `import_rows.override_json` (Approach B, Fernet, `_migrate` defensiv) aplicat ULTIMUL in `_resolve_row_for_preview`+`commit_import` (mutatie pura; completeaza si coloane ABSENTE din fisier); ruta `.../rand/{i}/editeaza` scoped JOIN→404, guard committed→409, empty=clear. US-002 buton Editeaza pe rand, swap pe `
`+OOB contoare (nu pe sectiune), form propriu (confirm dezactivat la editare), mutual-exclusion, reuse grila `_trimitere_detaliu.html`. US-005/006 Mapari/formate tabelar (.tablewrap, H4 auto_send stocat). US-007 bifa auto-send→comutator pe COADA ("Pune automat in coada"/"Tine pentru verificare"), scoped operatie, `name=auto_send` pastrat (zero backend). 523 teste pass. VERIFY E2E browser + LIVE RAR test: import fara coloana data→editare completeaza data (override)→commit→worker login RAR test→`postPrezentare`→sent `idPrezentare=68696` (confirmat in finalizate RAR). 3 bug-uri JS prinse la E2E (invizibile la TestClient) reparate: htmx `useTemplateFragments` (raspuns `
`+OOB parsat in context tabel→swapError), re-activare confirm-btn deferita pe tick, `n-hint` actualizat. `/code-review` high (2026-06-22): 1 bug real reparat — decriptarea `override_json` era in afara `try/except`-ului care protejeaza `raw_json` in ambele cai de preview (`import_router.preview_import` + `routes._web_compute_preview`); la rotatie cheie Fernet / token corupt `raw_json` degrada gratios la `{}` dar `override_json` arunca 500 pe tot batch-ul — acum protejat identic. Notat ca cleanup viitor (nereparat, disciplina backend-neatins): `_override_of` + blocul canonicalize-dupa-override duplicate in 3-4 locuri (preview/commit API vs web). Backend trimitere (worker/masina stari/idempotenta/mapare) NEATINS. PRD: [prd-3.6](prd/prd-3.6-editare-preview-acasa-unificata.md) |
### Etapa 5 — Ergonomie & Integrare (FOCUS CURENT)
> Directie noua (2026-06-22, decizie utilizator): produsul e functional, dar greu de adoptat de
> service-urile care vin din Visual FoxPro / soft propriu. Prioritatea trece pe **usurinta de
> integrare + ergonomie**, peste Etapa 4 (vezi nota de mai jos). Propunere fundamentata cu lentila
> DX gstack (`/devex-review`) pe codul real: lipseste suprafata de onboarding API self-service,
> exemplele de cod, puntea VFP, dry-run-ul si tema light.
| # | Livrabila | Status | Data | Detalii |
|---|-----------|--------|------|---------|
| 5.1 | Hub de integrare (pagina `/integrare` autentificata): exemple cod multi-limbaj (curl/Python/PHP/C#/Node) + retetar **Visual FoxPro** (POST via `MSXML2.ServerXMLHTTP` + upload CSV) + export OpenAPI/Postman + buton "Testeaza conexiunea" | DONE | 2026-06-22 | 4 stories (2 valuri, 2 echipe paralel + restore dupa clobber de merge). US-001 `GET /v1/ping` readiness (`account_id/mediu/autentificat_cu_cheie/are_creds_rar/ts`) + `GET /v1/integrare/postman.json` (v2.1.0, allowlist 3 rute). US-002 `integrare_examples.py` pur (7 limbaje × 2 canale, drift-test `is_required()`). US-003 tab "Integrare" IA pe 2 niveluri (limbaj→canal, VFP cu dialecte MSXML2/WinHttp), copy din ``, empty-state CTA, export `.cardlink`, doar tokens. US-004 `POST /integrare/test-cheie` (`account_for_key` direct, scoped sesiune, no-echo). VERIFY: 568 teste + E2E browser (Playwright: VFP 3 niveluri comuta, htmx test-cheie → fragment eroare, 0 erori consola) + enqueue live; live RAR neprobat (lipsa creds key). `/code-review` high: 4 bug-uri reale reparate (C#/VFP snippet JSON multi-linie nevalid, Node `node:buffer` fara FormData, script ne-scoped acumuland listeneri). Backend trimitere NEATINS. PRD: [prd-5.1](prd/prd-5.1-hub-integrare.md) |
| 5.2 | Endpoint dry-run `POST /v1/prezentari/valideaza` — valideaza payload + mapare, intoarce erorile reale FARA enqueue | DONE | 2026-06-22 | 1 story (US-001), un worker TDD. Helper pur partajat `classify_prezentare` (mapping.py) folosit de AMBELE rute → garanteaza ca dry-run-ul da acelasi verdict ca trimiterea reala (invariant de corectitudine, nu doar DRY); `create_prezentari` refactorizat pe el (comportament identic, test_api.py verde). Ruta read-only: `{results:[{index,valid,status_estimat,erori,nemapate,prestatii_rezolvate}]}`, `rar_credentials` optional+ignorat, zero scriere DB, scope prin `resolve_account_id`. Doar validare+mapare (FARA idempotency/duplicat — decizie user; `idempotency.py` neatins) + hub `/integrare` amanat. VERIFY context curat PASS (577 teste; E2E API: queued/needs_data/needs_mapping + COUNT(*)=0 dupa dry-run, fara leak creds; regresia de aur `POST /v1/prezentari`→queued verde; live RAR neprobat — lipsa `AUTOPASS_CREDS_KEY`/creds test, endpoint read-only nu atinge worker/coada). `/code-review` high: 0 findings. PRD: [prd-5.2](prd/prd-5.2-dryrun-valideaza.md) |
| 5.3 | Light/Dark mode — toggle in header, persistat (localStorage); CSS deja pe variabile `:root` | DONE | 2026-06-22 | 3 stories (US-001 paleta light + US-003 fix suprafete fragmente; US-002 comutator+persistenta+anti-FOUC), un worker TDD secvential (toate ating templates). Tema light = bloc `[data-theme="light"]` care suprascrie variabilele `:root` (dark NESCHIMBAT la octet, default pastrat); fundalurile de stare hardcodate (`#241a1a`/`#201c0f`/`#16241c`) convertite la `color-mix(... 12%, var(--card))` in `base.html` + 7 fragmente `_*.html`. Comutator soare/luna in header (aria-label, >=36px), pe toate paginile (login/signup/dashboard/admin). Default OS-aware (`prefers-color-scheme`, fallback dark); persistenta `localStorage` DOAR la click (init doar sincronizeaza iconita → OS-aware ramane viu pana la comutare explicita); script anti-FOUC in `` inainte de `