Commit Graph

32 Commits

Author SHA1 Message Date
Claude Agent
35e97faae5 feat(5.9): US-008 - responsive Acasa (upload/status/filtre) + login/signup
- base.html: bloc @media (max-width:767px) US-008, scopat pe id-urile de pe Acasa
- upload (#import-section): drop-zone pe coloana, buton alegere full-width >=44px
- filtre (#filtre-trimiteri): o coloana, inputuri/buton full-width >=44px (!important pe latimile inline)
- status (#status-bar): randuri aliniate, fara scroll orizontal
- login.html/signup.html: clasa .auth-card centrata, max-width:100% pe mobil
- tabelul de trimiteri 5.8 neatins (doar verificat intact)
- teste noi: test_acasa_fara_scroll_orizontal_mobil, test_login_signup_full_width_mobil
- suita: 840 passed, 1 deselected

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 09:23:37 +00:00
Claude Agent
d3433015ad feat(5.9): US-007 - responsive pagini de continut (card Mapari, scroll contained Jurnal/Nomenclator/Admin, formulare stivate)
- base.html @media(max-width:767px): clasa .tabel-card (card per rand) scopata
  SEPARAT de .tabel-trimiteri 5.8; reguli formular full-width + butoane >=44px
  scopate pe #card-cont / #form-test-cheie / #filtre-jurnal (marker US-007)
- _mapari.html: tabel-card + data-eticheta pe toate 4 tabelele; override select
  in card local (evita batalia de specificitate cu stilul inline)
- _integrare.html: id=form-test-cheie (ancora de scope pe formularul de test)
- R12 per-tabel: Mapari=card; Jurnal/Nomenclator/Admin=.tablewrap scroll contained;
  Cont/Integrare=fara tabele (doar formulare)
- tests: +3 (tabele clasa responsive, formulare full-width, regresie carduri 5.8)
- suita: 838 passed, 1 deselected
- prd.json US-007 passes=true + notes; progress.txt

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 09:17:47 +00:00
Claude Agent
141949dc95 feat(5.9): US-004 - detaliu editabil in-place + butoane consolidate in modal
- _trimitere_detaliu.html rescris pe ordinea verticala R10: header+motiv,
  eroare blocanta, mapare inline, formular editabil/context read-only, actiuni,
  <details> Detalii tehnice colapsat
- zero dublare: campurile editabile apar O SINGURA DATA (nr rand propriu, VIN
  dedesubt, restul in grila); blocul read-only de grila contopit cu formularul
- R9: operatie+cod read-only deasupra campurilor cu prez.cod_rar (fallback
  nemapat), fara eticheta separata Cod RAR
- R2 (fix F7): buton primar conditionat de stare - error->Re-pune(/repune),
  needs_data/needs_mapping->Salveaza si retrimite(/corecteaza); duplicatul gol eliminat
- R11: un singur Sterge outline var(--err) pe rand separat, hx-confirm specific,
  full-width pe mobil (.detaliu-actiuni-jos in @media 767px, base.html)
- R5: hx-disabled-elt pe toate formele; inchidere pe succes prin inchideModal
- R4: script modal-appropriate pastrat (curatat de US-003)
- 6 teste noi in test_web_corectie.py; rutele + _detaliu_ctx NESCHIMBATE
- suita 835 passed (-m 'not live'); prd.json/progress.txt US-004 passes

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 09:07:18 +00:00
Claude Agent
45f6fbb726 feat(5.9): US-006 - fundatie responsive (viewport, nav, modal full-screen mobil)
- base.html: conventie breakpoint unic 767px documentata + bloc @media mobil extins
- modal full-screen pe mobil (100vw/100vh, fara backdrop lateral, x >=44px, scroll intern)
- header/nav colapsat sub 768px + tinte touch >=44px (.icon-btn/.tab-link/.cont-menu)
- tests/test_web_responsive.py NOU (3 teste) + prd.json/progress.txt US-006 passes

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 08:57:52 +00:00
Claude Agent
878e319ac5 feat(5.9): US-002 - tabel trimiteri: eticheta umana sub stare, cod RAR simplu, rand->modal
- Sub pill-ul de Stare apare eticheta umana scurta (`eticheta_problema` din US-001),
  text mic `s-error`, doar cand e ne-goala — stare transmisa prin text, nu doar culoare.
- Coloana Operatie linia 2: codul RAR ca chip discret FARA prefixul "cod RAR:";
  cand nemapat ramane "nemapat" muted (comportament 5.8 pastrat).
- R8: regula touch 44px (min-height + padding) pe `tr.trimitere-row` + afordanta hover/focus;
  chevron inexistent in cod (randul declanseaza deja modalul din US-003, fara aria-expanded).
- Teste: 7 teste noi US-002 + actualizate test_operatie_contine_cod_rar / test_tabel_nu_are_coloana_motiv;
  suita completa 826 passed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 08:52:33 +00:00
Claude Agent
fd4a05436d feat(5.9): US-003 - modal reutilizabil (overlay, focus-trap, a11y) + cleanup inline-expand 5.8
- base.html: #modal-detaliu (role=dialog, aria-modal) + #detaliu-modal-body swap target;
  focus-trap, inert+aria-hidden pe <main>, Esc/backdrop/x inchid, listener trimiteriChanged (R5/R7)
- _coada.html: ancora modal in afara #submissions-wrap; sters #trimitere-detaliu inert vechi
- _submissions.html: randul declanseaza modalul; sters tr.detaliu-rand sibling (R3)
- _trimitere_detaliu.html: script rescris pentru modal, fara marcheazaDetaliuDeschis/scrollIntoView (R4)
- teste: test_web_modal.py nou (3); test_web_detaliu_inline.py sters; test_acasa_trimiteri.py curatat (R3)
- gates: pytest PASS (suita completa 819). Browser E2E + design-review deferate la VERIFY.

Salvat manual: iteratiile Ralph 2-12 au ramas fara turns (30) inainte de commit.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-24 22:48:42 +00:00
Claude Agent
51dc504f1d feat(5.8): reguli mapare pe text (substring/cont) + UX tabel trimiteri (detaliu inline, fara scroll, cod RAR)
Reguli text per cont (operation_text_rules), resolve_prestatii cu param aditiv
text_rules + precedenta stricta, threadat pe toate cele 6 callsite-uri + valid_codes
+ seam classify_prezentare. UI Mapari: sectiune reguli + preview pre-salvare + overlap
+ telemetrie text_rule_hit. UX tabel: cod_rar sub operatie, pill eticheta scurta, fara
scroll orizontal (scopat .tabel-trimiteri + carduri <768px), detaliu inline expandabil
(a11y + pauza poll). code-review: reparat regula auto_send=0 care trimitea automat la RAR
in loc sa tina randul pentru review. 814 passed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-24 12:47:37 +00:00
Claude Agent
ac57b9250a feat(5.7): raspuns API onest la blocaje + mapare inline din detaliu
Raportat din client VFP: POST /v1/prezentari raspundea submission_id+status
fara motiv pe randuri blocate (erori se popula doar pe on_unmapped_error=True),
deci un needs_data/needs_mapping parea succes.

API (aditiv): SubmissionResult += nemapate + motiv. create_prezentari
populeaza erori (validare continut, 3 niveluri) / nemapate (coduri fara
mapare, COD_NEMAPAT) / motiv (rezumat uman) pe TOATE caile non-queued —
enqueue, respins (on_unmapped_error=True) si reactivare dedup peste error,
prin helperele _rezultat_enqueue / _rezultat_respins / _motiv_clasificare.
on_unmapped_error=True pastreaza erori=COD_NEMAPAT (compat clienti vechi).

Web: mapare inline in panoul de detaliu trimitere — ruta
POST /trimitere/{id}/mapeaza (reuse save_mapping + reresolve_account, scoped
sesiune + CSRF, re-rezolva pe batch_id-ul randului), helper
_nemapate_pentru_submission + context in _detaliu_ctx, sectiune in
_trimitere_detaliu.html (selector cod RAR cu sugestie fuzzy preselectata).
Apare doar pe operatii nemapate reale (nu pe auto_send=0).

/code-review high: reparat raspuns neonest la reactivare + dublu
load_nomenclator in _detaliu_ctx.

Teste: pytest -q 765 passed. Backend trimitere (worker/masina stari/
idempotenta) si schema NEATINSE. PRD: docs/prd/prd-5.7-*.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-23 20:51:16 +00:00
Claude Agent
c842e3352a feat(5.6): observabilitate + jurnal aplicatie + lifecycle trimiteri blocate
Implementeaza PRD 5.6 complet (14 stories, TDD). Doua axe:

Lifecycle trimiteri blocate (Val A):
- submissions_admin.py: sterge/repune scoped (404 cross-account inaintea lui 409 stare)
- reactivare dedup peste `error` cu CAS (WHERE id=? AND status='error'), creds noi in
  submissions + accounts.rar_creds_enc; worker invalideaza sesiunea RAR la creds proaspete
  (JWT 30h vechi nu mai trimite cu parola gresita); camp aditiv `reactivated:true`
- retentie randuri blocate 30z; purge_expired exclude queued/sending; purge_after curatat
  la reactivare/requeue
- API DELETE /v1/prezentari/{id} + /repune (200+JSON); UI butoane + bulk + banner actionabil

Observabilitate:
- app/observ.py log_event: dublu canal app_events (DB) + RotatingFileHandler per-proces,
  redactare creds/PII la scriere (redact_pii/vin_partial)
- request_id middleware + X-Request-ID pe toate raspunsurile
- handler global excepții -> 500 envelope 6-chei + request_id (traceback doar in jurnal)
- audit cerere API (api_prezentari/api_auth_esuat) + audit worker (rar_login/tranzitii)
- tab "Jurnal" filtrabil scoped (non-admin doar contul sau); retentie jurnal 90z
- rar_error expus in GET /v1/prezentari/{id} (recovery observabil)

pytest -q: 741 passed, 0 failed. Docs: PRD raport VERIFY, contract endpointuri noi, ROADMAP.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-23 18:45:39 +00:00
Claude Agent
5dc963a02c feat(api): rar_credentials optional pe POST /v1/prezentari
Cand `rar_credentials` lipseste din cerere, submission-ul intra fara creds
efemere, iar worker-ul cade pe creds-urile RAR durabile ale contului
(accounts.rar_creds_enc). Identificarea contului ramane pe cheia API.
Trimiterea explicita a creds-urilor suprascrie creds-urile contului pe acea
cerere (back-compat: fluxul vechi ROAAUTO merge identic).

- models.py: rar_credentials: RarCredentials | None = None
- router.py: cripteaza creds doar daca exista (altfel creds_enc=NULL)
- worker NEATINS: avea deja fallback _creds_for(...) or _creds_from_account(...)

Pagina /integrare aliniata: exemplele cod (7 limbaje) + export Postman nu mai
includ rar_credentials in payload; nota noua explica modelul (creds pe cont,
optional in payload). README rescris compact + reflecta optionalitatea.

Test nou: enqueue fara creds -> submission fara creds efemere -> fallback pe
contul cu creds salvate. Suita: 673 passed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-23 13:39:53 +00:00
Claude Agent
0517ae59fb feat(web): cautare + paginare client-side pe tabelele din Mapari
Maparile pot creste la sute de randuri. Enhancer reutilizabil (data-dt) in
base.html filtreaza si pagineaza DOM-ul deja randat, fara cereri server; re-init
la full load si dupa swap-urile HTMX. Aplicat pe cele 3 tabele (De rezolvat /
operatii salvate / formate coloane).

Randurile cu <select> expun haystack explicit prin data-dt-row (cod_op + cod_rar
+ denumire): altfel optiunile selectului ar pune tot nomenclatorul in textContent
si orice cautare ar potrivi orice rand.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-23 12:48:05 +00:00
Claude Agent
e3f295f912 fix(web): kebab anti-clipping partajat + panou admin redenumit + tabel mapari compact
- "Panou admin" -> "Conturi clienti" (titlu, antet, link meniu hamburger)
- Kebab actiuni mutat in component partajat (base.html) cu position:fixed
  pozitionat din JS: .tablewrap{overflow-x:auto} inducea overflow-y:auto care
  taia dropdown-ul pe ultimul rand (meniul admin nu se vedea). Sters CSS local.
- Mapari salvate: Salveaza/Sterge mutate in kebab (legate prin form=); coloana
  "In coada" doar checkbox (macro autosend_toggle compact, semantica de prezenta
  pastrata); select cod RAR limitat la 240px -> tabelul incape fara scroll.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-23 12:30:56 +00:00
Claude Agent
1fbd894329 feat(web): uniformizare/standardizare UI/UX + lifecycle conturi (PRD 5.5)
Aduce toate suprafetele dashboard-ului la grila tabelului Trimiteri, muta
navigarea intr-un meniu de cont (hamburger) si da panoului admin actiuni
reale de ciclu de viata. 9 stories, 3 valuri. UI pur (reskin + reasezare)
cu O SINGURA exceptie backend: modelul de stare a contului.

- US-001 sectiunea "Ajutor" eliminata din Acasa (wayfinding redundant).
- US-002 Nomenclator la grila standard (_submissions.html ca referinta).
- US-003 macro autosend compact (Manual<->Auto). Semantica de PREZENTA
  `auto_send` (bifat->true, absent->false) NEALTERATA — compatibil cu ambele
  parsere (Form(bool) la /mapari, bool(form.get()) la import). Zero backend.
- US-004 accounts.status (pending/active/blocked/archived/deleted), migrare
  defensiva idempotenta derivata din `active`, gate worker claim_one pe
  status='active' (echivalenta active=1 <=> status='active' pastrata).
- US-005 tabel Mapari compact + panou Ajutor (<details>, proza o singura data),
  coloana "In coada".
- US-006 meniu hamburger dropdown (Cont/Integrare/Nomenclator/Admin/logout) +
  context is_authenticated/is_admin/csrf_token defensiv in base.html.
- US-007 tab-bar redus la Acasa+Mapari; rutele /_fragments/{cont,integrare,
  nomenclator} + deep-link ?tab= raman valide.
- US-008 rute admin block/archive/delete + bulk pe lista account_id,
  require_admin + CSRF + PRG, dev id=1 sarit in bulk.
- US-009 admin UI: selectie bife + master + bara bulk + kebab per-rand,
  grupare pe stare (bloc nou blocate/arhivate), nota "cont dev implicit" scoasa.

Stergere = SOFT: tombstone (status='deleted'), dar PII purjata IMEDIAT
(rar_creds_enc + chei API revocate + CUI eliberat pentru re-inregistrare),
GDPR/L.142.

VERIFY: 671 teste pass (+40). E2E browser (Playwright) a prins 2 bug-uri
invizibile la TestClient: bara bulk cu display:flex inline invingea [hidden]
(mutat in CSS .bulk-bar[hidden]); conturi arhivate cadeau sub "in asteptare"
(grupare pe status). /code-review high a prins 2 bug-uri reale: soft delete
pastra creds RAR + CUI la nesfarsit fara purjare accounts (GDPR neonorat);
apostrof in numele firmei rupea confirm() inline din kebab — ambele reparate,
plus cleanup boilerplate rute (_lifecycle_route).

Backend trimitere (worker masina stari/idempotenta/mapping) neatins, cu
exceptia gate-ului de cont. Design: docs/design/5.5-uniformizare-ui.md.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-23 11:56:05 +00:00
Claude Agent
14e1c463f0 feat(errors): erori pe 3 niveluri (problema+cauza+fix) pe API si UI (PRD 5.4)
Catalog central pur app/errors.py ca sursa unica cod->{problema,fix},
consumat de API+UI+worker. Aditiv (field/message pastrate la octet) +
rar_error stocat superset. Scope: fluxul de declarare; login/signup/CSRF
neatinse. labels.parse_erori degradeaza gratios; UI progresiv AA light+dark.
631 teste.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-23 10:28:09 +00:00
Claude Agent
b48501d8e4 feat(web): light/dark mode cu comutator persistat + anti-FOUC (PRD 5.3)
Tema light ca bloc [data-theme="light"] peste variabilele :root (dark
nemodificat la octet). Comutator soare/luna in header pe toate paginile,
default OS-aware (prefers-color-scheme, fallback dark), persistenta in
localStorage doar la comutare explicita, script anti-FOUC in <head>
pre-paint. Suprafetele de stare hardcodate convertite la color-mix in
base.html + 7 fragmente _*.html (light lizibil, contrast WCAG AA).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-22 19:39:12 +00:00
Claude Agent
f0786051f5 feat(web): hub integrare /integrare — exemple cod + retetar VFP + ping + export (PRD 5.1)
Pagina /integrare (tab autentificat, scoped pe cont): exemple cod multi-limbaj
(curl/Python/PHP/C#/Node) + retetar Visual FoxPro (MSXML2 + WinHttp) pe ambele
canale (prezentari JSON + import fisier), export Postman/OpenAPI/Swagger si buton
"Testeaza conexiunea".

- 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: app/web/integrare_examples.py pur (7 limbaje x 2 canale, drift-test
  is_required(), JSON compact pentru C#/VFP)
- US-003: tab "Integrare" IA pe 2 niveluri (limbaj->canal, VFP cu dialecte),
  copy din <pre><code>, empty-state CTA, export .cardlink, script scoped
- US-004: POST /integrare/test-cheie (account_for_key direct, scoped sesiune,
  no-echo cheie)

Backend trimitere (worker/masina stari/idempotenta/mapping) si schema neatinse.
568 teste pass. VERIFY context curat + E2E browser (Playwright) + code-review high.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-22 12:16:41 +00:00
Claude Agent
6f6b163867 feat(web): editare celule in preview + Acasa unificata (PRD 3.6)
Implementeaza PRD 3.6 (US-001..007), pe canalul de import + stratul web;
worker / masina stari / idempotenta / mapare raman neatinse.

- US-003/004: tab-ul "Trimiteri" eliminat; Trimiterile devin sectiune
  permanenta sub upload pe Acasa ("Trimiterile tale"); upload comprimat la
  bara slim (hero pastrat la first-run); ?tab=coada si /_fragments/coada
  servesc Acasa (fara fragment orfan); poll gated pe visibilityState.
- US-001: coloana noua import_rows.override_json (nullable, Fernet, Approach B)
  + _migrate defensiv; ruta v1 + alias web .../rand/{i}/editeaza aplica patch
  canonic ULTIMUL in _resolve_row_for_preview si commit_import (mutatie pura,
  status rederivat, fara drift). Scoping JOIN -> 404, guard committed -> 409,
  semantica empty=clear, decrypt fail -> no-op.
- US-002: buton "Editeaza" pe rand; swap pe <tr> + OOB contoare (nu pe sectiune);
  form propriu (confirm dezactivat la editare); refoloseste grila responsiva +
  error-map din _trimitere_detaliu.html; mutual-exclusion intre randuri.
- US-005/006: "De rezolvat", "Operatii salvate" si "Formate de coloane" ca
  tabele (.tablewrap); H4: comutatorul reflecta auto_send STOCAT.
- US-007: bifa "auto-send" devine comutator etichetat pe COADA ("Pune automat
  in coada" / "Tine pentru verificare"), scoped pe operatie; name="auto_send"
  pastrat (semantica de prezenta -> bool corect cu ambele parsere, zero backend).

Fix-uri gasite la verificarea E2E in browser (htmx 1.9.12, JS — invizibile la
TestClient): useTemplateFragments=true (raspuns <tr>+OOB era parsat in context
de tabel -> swapError + contoare pierdute); re-activarea confirm-btn dupa salvare
deferita pe tick (evita editing=true tranzitoriu); n-hint actualizat de updateN.

Teste: 523 passed. E2E browser: Acasa unificata, upload slim, editare rand
(needs_data -> ok, swap pe rand, contoare OOB), Mapari tabelar + comutator.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 10:52:17 +00:00
Claude Agent
d7ba1195d4 feat(web): dashboard compact — import pe Acasa, status cu bife, Trimiteri lizibile, Mapari complete (3.5)
Acasa = ecran de import (tab Import scos, ?tab=import->Acasa). Bara status
compacta pe 2 randuri cu bife accesibile (glife + text) + data formatata.
'Coada'->'Trimiteri': coloane RO, stare umana, detaliu la click in panou
dedicat. Mapari pe 3 sectiuni (de rezolvat / op salvate / formate coloane),
Cont doar cheie+creds. Filtrare Trimiteri, corectie inline needs_data cu
re-enqueue + detectie coliziune idempotency, badge contoare pe tab-uri.
Helper pur partajat payload_view.py (web + GET /v1/prezentari).
Backend trimitere (worker/idempotenta/mapping/schema) neatins. 483 teste.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 08:56:45 +00:00
Claude Agent
4a1d28749a feat(web): dashboard ergonomic cu tab-uri, stepper import si microcopy uman (3.4)
Reorganizeaza interfata web pe trei principii, fara a atinge backend-ul de
trimitere (worker, mapping, idempotency, masina de stari neatinse):

- US-001 app/web/labels.py: modul pur stari tehnice -> text uman + clasa CSS
- US-002 bara status /_fragments/status: microcopy uman, defalcare blocate, scoped cont
- US-003 shell 6 tab-uri (Acasa/Import/Coada/Mapari/Cont/Nomenclator): deep-link
  ?tab=, panou activ randat server-side, fragmente inactive lazy, ARIA real
- US-004 stepper import 4 pasi (pur vizual; hx-target + csrf pastrate)
- US-005 Acasa onboarding checklist auto-bifat + colaps + empty states prietenoase

Reparat in cursul VERIFY/CLOSE: izolare teste (reset ratelimit._hits in fixturi),
regresie avertisment "cont in asteptare de activare" (re-introdus in bara status),
culori hardcodate -> variabile paleta. 434 teste pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 22:26:10 +00:00
Claude Agent
a40b20b3b4 feat(import): mapare operatie->cod RAR inline in preview + camp denumire_op
Inchide deadlock-ul din canalul de import web: operatiile nemapate dintr-un
batch in staging nu aveau unde sa fie mapate din UI. Editorul "Mapari de
rezolvat" citea doar din submissions comise, iar commit-ul arunca randurile
needs_mapping -> utilizatorul ramanea blocat fara a putea trimite.

- camp canonic nou `denumire_op`: coloana descriptiva (ex. "Reparatie Motor")
  alimenteaza denumirea operatiei, deci sugestia fuzzy devine utila (inainte
  denumire = codul opac). Aplicat in cele 3 locuri de resolve (preview, commit
  web, commit API).
- panou inline "Operatii de mapat la cod RAR" in preview: fiecare operatie
  nemapata cu sugestie preselectata + dropdown + auto-send + salveaza.
- ruta POST /_import/{id}/mapare-operatie: salveaza maparea (persistenta,
  operations_mapping) si re-randeaza preview-ul; randurile trec din
  needs_mapping in ok fara re-upload, maparea se retine pentru fisiere viitoare.
- fix bug pre-existent de semnatura coloane: semnatura se calcula din campurile
  mapate (json_mapare.keys), nu din antetul complet -> ignorarea unei coloane
  schimba semnatura si maparea retinuta nu mai era gasita la preview/re-upload.
  Acum mereu din antetul complet (web + API), consecvent cu preview/commit.

Teste noi: tests/test_import_mapare_operatie.py (6). Suita: 400 passed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 20:01:14 +00:00
Claude Agent
b92055eb01 feat(web): self-service cheie/creds + admin web + email signup (PRD 3.3b)
US-007: rute web proprii /cont/roteste-cheie + /cont/rar-creds scoped pe
sesiune (C13), sectiune "Contul meu" cu cheie afisata o data.
US-010: rol admin (users.is_admin) + require_admin->403 + CLI set-admin +
bootstrap primul cont=admin (count_admins in BEGIN IMMEDIATE, anti-race).
US-011: panou /admin (activare/dezactivare conturi, CSRF + PRG), link admin
+ logout pe dashboard.
US-012: app/email.py notify_signup best-effort degradat fara SMTP + config smtp_*.
Fix: migrare defensiva users.is_admin/email_verified in _migrate.

VERIFY x2 context curat (PASS) + /code-review high. 393 teste pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 17:19:06 +00:00
Claude Agent
504b490d3b feat(web): self-onboarding multi-tenant + auth sesiune (PRD 3.3a)
Canalul web trece de la 100% deschis (hardcodat cont 1) la autentificat si
multi-tenant. Un service nou se inregistreaza din browser, primeste o cheie API
(o singura data) si o sesiune; contul se creeaza "in asteptare" (active=0) si nu
trimite la RAR pana la activarea de catre admin (tools/account.py activate).

- users + app/users.py: parole scrypt (salt per-user, eticheta parametri onorata
  la verify pentru migrare cost), email unic case-insensitive
- sesiune: SessionMiddleware (same_site=strict, https_only config) + app/web/session.py
  (current_account/web_account/require_login->LoginRequired, set_session clear-inainte)
- CSRF (app/web/csrf.py) enforce in prod inclusiv pe login/signup + rate-limit
  in-proces (app/web/ratelimit.py) pe signup si login
- signup/login/logout (app/web/auth_routes.py): signup tranzactie atomica,
  cheie-o-data, log SIGNUP pentru descoperire admin
- dashboard + import scoped pe contul sesiunii (regula NULL->cont 1); toate rutele
  web care ating date sensibile sub require_login; nomenclator ramane global
- banner "cont in asteptare" pentru conturi active=0
- gate worker: claim_one LEFT JOIN accounts COALESCE(active,1)=1 (account_id NULL=activ)

VERIFY context curat (2 runde): leak cross-account /_fragments/mapari prins+reparat.
/code-review high: csrf_token lipsa pe re-randari de eroare, scrypt_params ignorat,
login fara rate-limit -- toate reparate. 361 teste pass (de la 313).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 16:43:21 +00:00
Claude Agent
854db66abc feat(ui): #15 U5 — web upload import (HTMX) drop→mapare→preview→confirma
Implementare completa U5 din plan-treapta2.md (sectiunea 13):

- _upload.html: drop zone + buton accesibil (a11y: drag nu e la tastatura),
  drag-and-drop JS, mesaj 'NU se trimite nimic pana confirmi',
  selector foi pt multi-sheet xlsx, stari eroare/mesaj
- _mapcoloane.html: formular mapare coloane cu .maprow/.mapcol.grow,
  sugestii fuzzy pre-selectate, etiichete <label> vizibile, sample values,
  format data configurabil
- _preview_import.html: tabel 6 stari, pills rezumat, filtre pe stare,
  .chk per-rand pe needs_review (D11), banner declarant .banner.warn
  direct deasupra input-ului N (D12), bara confirmare sticky,
  text 'dubla cu randul N' pe duplicate_in_file (D10 daltonism),
  link export CSV randuri esuate
- base.html: .s-needs_review (warn), .s-already_sent/.s-duplicate_in_file
  (muted), .drop-zone, .banner.warn, .sticky-bar, .htmx-indicator
- routes.py: rute /_import/upload/mapare-coloane/preview/reset/confirma;
  helper _web_compute_preview refoloseste _resolve_row_for_preview,
  _already_sent_lookup, _signature din import_router (fara a-l edita);
  commit ON CONFLICT DO NOTHING (TOCTOU); log atestare
- tests/test_import_ui.py: 15 teste (dashboard, upload, mapare, preview,
  confirmare N corect/gresit, reset, erori, multi-sheet, a11y D10/D11/D12)

279 teste total, 0 esecuri.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-16 21:04:56 +00:00
Claude Agent
b12be3d26c style(design): FINDING-004 — htmx vendorizat local, nu din CDN (offline-first)
Dashboard-ul incarca htmx din unpkg.com. Gateway-ul ruleaza offline (LXC/VPS
+ Cloudflare Tunnel); cand CDN-ul e blocat/inaccesibil, htmx nu se incarca si
dashboard-ul ramane static: zero polling (banner alerta blocate, coada,
mapari), butoanele de mapare nu trimit. Aceeasi decizie offline-first ca fontul
UI (FINDING-002, fara dependinta CDN).

Fix: vendorizez htmx.org@1.9.12 minificat in app/web/static/, montez StaticFiles
la /static in main.py, base.html refera /static/htmx.min.js. Verificat live:
window.htmx.version=1.9.12, fragment polls 200, zero regresie vizuala.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 20:58:24 +00:00
Claude Agent
bba5b31540 style(design): FINDING-003 — link-uri actiune card mai usor de atins (>=36px) + antet se rupe curat pe mobil 2026-06-15 20:50:14 +00:00
Claude Agent
facb1ca8b4 style(design): FINDING-002 — font stack UI intentionat (cross-platform, fara dependinta CDN; gateway ruleaza offline) 2026-06-15 20:49:39 +00:00
Claude Agent
39c0e16248 style(design): FINDING-001 — ierarhie titluri (H1 dominant 20px, sectiuni 15px) 2026-06-15 20:49:11 +00:00
Claude Agent
db64972c1d style(design): FINDING-002 — clarifica link-uri export CSV (tot -> toate)
Link-ul 'tot' era criptic. 'export CSV: trimise' / 'toate' spune ce descarca
fiecare (don't-make-me-think).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 20:39:21 +00:00
Claude Agent
8d3bc6bea5 style(design): FINDING-001 — tabele scroll in card pe mobil (fix overflow orizontal pagina)
Tabelul submissions (7 coloane, 591px) iesea din card pe 390px -> toata pagina
scrolla orizontal (docScrollW 636 > 390). Wrap in .tablewrap{overflow-x:auto} +
white-space:nowrap pe celule -> scroll IN card, pagina nu mai deborda. tabular-nums
pe coloanele numerice.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 20:39:04 +00:00
Claude Agent
6ab22ea0fb feat(T5/dashboard): import DBF idempotent + nomenclator browser + audit CSV + stare RAR
T5 (tools/import_dbf.py): citire prestatii_rar.DBF / mapare_prestatii.DBF cu
dbfread, raport dry-run (randuri valide/duplicate/goale, mapari orfane = cod
necunoscut in nomenclator), --commit cu upsert idempotent in tranzactie.

Dashboard: browser nomenclator, indicator stare RAR (indisponibil? derivat din
ultimul login < 30h, coada arata ultima stare locala), export audit CSV
(/v1/audit/export?status=sent|all&date_from&date_to, b64Image exclus,
coloana purge_after pentru retentia 90z).

Verify: 11 teste noi (test_import_dbf 6, test_dashboard 5), suita 111 pass,
dry-run real pe DBF-urile din repo + smoke live dashboard/CSV.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 20:32:26 +00:00
Claude Agent
a6df3b636f feat(T5): editor web mapare operatii (hibrid + fuzzy + on-demand needs_mapping)
T5 reinterpretat: nu import DBF, ci editor web al maparii operatie ROAAUTO ->
cod RAR, cu fuzzy lookup si validare de catre utilizator.

- Contract hibrid: item prestatie accepta cod_prestatie (RAR direct, back-compat)
  SAU cod_op_service+denumire (mapat de gateway prin operations_mapping).
- Ingestie: op intern necunoscut -> submission needs_mapping (nu pleaca la RAR);
  codul rezolvat se scrie inapoi in payload_json -> payload builder + worker neatinse.
- Editor HTMX (_mapari.html + GET /_fragments/mapari, POST /mapari): listeaza
  op-urile nemapate, fuzzy preselecteaza codul RAR, save -> re-rezolvare automata
  (queued / needs_data).
- Fuzzy: rapidfuzz.token_sort_ratio pe denumire normalizata (fara diacritice).
- Nomenclator: seed fallback 18 coduri la boot (offline) + refresh live din worker.
- Cont default id=1 cat timp auth API-key (CORE) nu exista (account_id NULL).
- Endpointuri API: GET /v1/mapari/pending, POST /v1/mapari (respinge cod inexistent).
- 15 teste noi (tests/test_mapping.py); 69 pass total.
- Contract actualizat (docs/api-rar-contract.md), rapidfuzz==3.14.5 in requirements.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 19:25:21 +00:00
Claude Agent
f1b5f1f80f feat: schelet gateway FastAPI (API v1 + worker + dashboard + SQLite WAL)
Structura repo conform plan.md sect. 4, booteaza cu /healthz verde:
- app/main.py: FastAPI (lifespan init_db), /healthz (worker viu + last login + queue), /metrics
- app/api/v1: POST /v1/prezentari (enqueue + dedup idempotency UNIQUE), GET prezentari/{id}, nomenclator, mapari
- app/rar_client.py: client RAR real (login/JWT, nomenclator, postPrezentare, getFinalizate) cu User-Agent obligatoriu (fix WAF 403)
- app/worker: proces separat, claim atomic BEGIN IMMEDIATE, heartbeat, login+send (send dezactivat by default)
- app/web: dashboard Jinja2+HTMX (coada, banner alerta blocate, worker viu/mort, stari empty)
- app/db.py + schema.sql: SQLite WAL, tabele accounts/api_keys/operations_mapping/nomenclator_rar/submissions/worker_heartbeat
- app/idempotency.py + payload.py: hash continut canonic + builder payload (status FINALIZATA, fara tipPrestatie)
- Dockerfile + docker-compose.yml (api+worker, volum SQLite persistent, restart:always)
- tools/import_dbf.py: stub T5

Verificat live: login prin rar_client OK (token 259), nomenclator 18 coduri, worker heartbeat -> /healthz worker_alive=True.
Ramas: T3 validare Pydantic, T4 snapshot payload, T2 reconciliere/retry worker, T5 import DBF, auth API-key, middleware redactare creds, criptare PII.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 12:04:11 +00:00