Commit Graph

115 Commits

Author SHA1 Message Date
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
36ec50d667 docs: 5.5 LIVRAT in ROADMAP (uniformizare UI/UX + lifecycle conturi)
Inchide randul 5.5 (DONE) + Ultima actualizare, dupa commit 1fbd894.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-23 11:56:55 +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
ae7960294f feat(api): endpoint dry-run POST /v1/prezentari/valideaza (PRD 5.2)
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. "Magical
moment" pentru integratori (ROAAUTO / soft propriu / punte VFP).

Cheia de design: helper pur partajat classify_prezentare (mapping.py) 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 (test_api.py verde).

Scope minim (decizie user): doar validare+mapare, fara idempotency/duplicat
(idempotency.py neatins); descoperibilitate in hub /integrare amanata.

VERIFY context curat PASS (577 teste; E2E API cu cele 3 verdicte + COUNT(*)=0
dupa dry-run). /code-review high: 0 findings.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-22 18:54:50 +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
be36c2c53b docs: Etapa 5 (ergonomie & integrare) + PRD 5.1 hub integrare aprobat
Directie noua: prioritate pe usurinta de integrare/ergonomie peste Etapa 4
(deprioritizata). ROADMAP: Etapa 5 cu 4 livrabile (5.1 hub integrare, 5.2
dry-run, 5.3 light/dark, 5.4 erori 3 niveluri).

PRD 5.1 (hub /integrare: exemple multi-limbaj + retetar VFP MSXML2/WinHttp +
GET /v1/ping readiness + export Postman/OpenAPI + test conexiune): 4 stories
atomice in 2 valuri, fundamentat cu lentila DX gstack pe codul real. 3 review-uri
de plan rulate (CEO/eng/design, toate APROB CU MODIFICARI) si incorporate.
Stare: aprobat.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-22 11:16:44 +00:00
Claude Agent
35f35d03cc fix(web): protejeaza decriptarea override_json in preview + inchide 3.6 (CLOSE)
decrypt_creds(override_json) era in afara try/except-ului care protejeaza
raw_json in preview_import (import_router) si _web_compute_preview (routes).
La rotatie cheie Fernet (risc acceptat R4) sau token corupt, raw_json degrada
gratios la {} dar override_json arunca 500 pe tot batch-ul. Acum ambalat
identic (fallback None -> {}).

Prins de /code-review high la CLOSE. Writeback: ROADMAP 3.6 -> DONE,
PRD -> inchis + Raport CLOSE. Duplicare _override_of/canonicalize notata
ca cleanup viitor (disciplina backend-neatins). 523 teste pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-22 09:09:03 +00:00
Claude Agent
178bc87006 docs: PRD 3.6 verify-pass + actualizare ROADMAP (E2E + LIVE RAR test)
VERIFY PASS pentru 3.6: suita 523 teste, E2E browser pe `/` (toate US-001..007),
si trimitere LIVE pe RAR test — import fara coloana data -> editarea completeaza
data (override_json) -> commit -> worker login RAR test -> postPrezentare -> sent
idPrezentare=68696 (confirmat independent in tools.rar_finalizate).

- ROADMAP: rand 3.6 = VERIFY-PASS + "Ultima actualizare".
- PRD 3.6: Stare -> verify-pass + sectiunea "## Raport VERIFY" completata
  (PASS per story, dovezi, cele 3 bug-uri JS prinse la E2E si reparate).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 11:00: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
ead63245da prd 3.6 2026-06-19 09:58:24 +00:00
Claude Agent
c8a19e2f06 chore: muta portul implicit 8000 -> 8010 (evita coliziunea cu roa2web)
start.sh, docker-compose.yml, README.md, CLAUDE.md aliniate la 8010
pentru a nu se suprapune cu backend-ul roa2web pe masina de test.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 09:11:37 +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
d10e9db998 gitignore 2026-06-18 22:27:46 +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
ccd26115f8 test(fixtures): muta CSV-urile de import exemplu in tests/fixtures/
Doua formate exemplu pentru import: test_data.csv (cod_prestatie RAR direct)
si test_data_mapping.csv (cod_op_service + denumire, necesita mapare operatie).
Folosite la testarea manuala a fluxului de import web.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 20:01:47 +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
4e2b6102a4 docs(prd): PRD 3.4 interfata web ergonomica (tab-uri + wizard + microcopy)
Reorganizare dashboard pe trei principii, doar stratul de prezentare
(Jinja2+HTMX, zero build), fara atingerea worker/mapare/idempotenta:
- tab-uri sus (Acasa/Import/Coada/Mapari/Cont/Nomenclator), un panou activ,
  fragmente lazy, deep-link ?tab= randat server-side, a11y tablist/aria
- import ca stepper 4 pasi (Incarca/Potriveste/Verifica/Confirma)
- ghid de pornire auto-bifat + empty states (US-005)
- microcopy uman intr-un singur loc (labels.py): 'Trimitere automata: activa'
  in loc de 'worker viu'

Intrebari deschise rezolvate (6 tab-uri, ?tab=, pas 2 auto-bifat). Plan-reviews
CEO/Eng/Design aplicate in PRD (a11y, empty states, guard HTMX/CSRF la granita
US-003<->US-004, randare server-side). Stare: aprobat. Rand 3.4 TODO in ROADMAP.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 19:59:27 +00:00
Claude Agent
f149b24f96 chore: ignora .claude/ (config + memorie agenti, stare locala)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 18:27:59 +00:00
Claude Agent
958b182e8e feat(config): web_auth_required ON implicit (login obligatoriu pe rutele web)
Inverseaza default-ul C12: rutele web cer sesiune + CSRF implicit (sigur pentru
prod). Dev rapid pe contul 1 = opt-out explicit AUTOPASS_WEB_AUTH_REQUIRED=false.
Testele de comportament import/dashboard marcate explicit dev-mode; test nou
blocheaza default-ul. 394 teste pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 18:27:09 +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
748ab8b289 feat(api): scope pe cont la GET-urile de listare /v1/* (PRD 3.2)
Inchide scurgerea cross-account pe GET /v1/prezentari(/{id}),
/v1/mapari(/pending) si /v1/audit/export. Toate primesc
Depends(resolve_account_id) + account_scope_clause (regula NULL->cont 1,
OV-2). Nomenclatorul ramane global (referinta partajata, fara PII).

- B3: 404 cross-account byte-identic cu 404 inexistent (fara oracol enumerare)
- B4: get_prezentare cu allowlist de campuri (nu mai expune rar_creds_enc/
  payload_json/idempotency_key/rar_error)
- B1: pending_unmapped filtreaza in SQL; default None = global doar pentru web
- B2: helper account_scope_clause (DRY, doar pe submissions nullable)
- B5: index idx_submissions_account_status
- B8: regula de scope documentata in api-rar-contract.md
- TD-3.2: ?account_id != contul cheii -> 400

14 teste noi (cross-account, legacy NULL, B3, B4); suita 313 passed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 17:35:50 +00:00
Claude Agent
1c5b0cbc18 feat(account): CLI lifecycle conturi + accounts.active (PRD 3.1)
Inlocuieste crearea conturilor prin INSERT SQL manual cu un tool admin
dedicat, simetric cu tools/apikey.py. Fundatia Etapei 3 (3.2/3.3).

- app/accounts.py: create_account/set_active/list_accounts (helper pur,
  partajat CLI + viitor flux web 3.3). Normalizeaza CUI (trim+upper),
  prinde IntegrityError -> ValueError cu cauza+fix.
- accounts.active (lifecycle cont) + index unic partial ux_accounts_cui
  (unicitate la nivel de index, fara fereastra de coliziune). Migrare
  idempotenta in _migrate.
- tools/account.py: create (--name/--cui/--inactive/--with-key atomic),
  list [--pending], activate/deactivate --account N. Erori -> exit 2.
- 20 teste noi (12 helper + 8 CLI); suita 299 passed.

active e inert pana la gate-ul worker din 3.3 (documentat).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 12:38:13 +00:00
Claude Agent
6515de415b docs(prd): PRD-uri Etapa 3 (3.1/3.2/3.3) aprobate dupa autoplan
Faza PLAN pentru multi-cont / self-onboarding. Trei PRD-uri scrise, ancorate in
cod, trecute prin autoplan (voci Claude independente; Codex degradat pe usage-limit)
si aprobate la poarta umana.

- 3.1 creare cont: CLI tools/account.py + accounts.active; CUI unic prin index partial
- 3.2 filtrare GET pe cont: scope pe cheie, allowlist campuri, nomenclator global
- 3.3 self-onboarding web: sesiuni + cont 'in asteptare' + CSRF + interfata admin web
  + email; US-007 promovat in MVP (7->12 stories)

Dashboard ROADMAP actualizat (stare 'PRD aprobat', linkuri PRD).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 12:22:28 +00:00
Claude Agent
5dc3a477de claude 2026-06-17 07:23:58 +00:00
Claude Agent
fbf82622b6 docs: sistem ROADMAP unic (progres + proces) + template PRD
Inlocuieste planurile vechi (consolidate/realizate) cu un singur
docs/ROADMAP.md: dashboard de progres (Treapta 1+2 DONE LIVE, Etapa 3
TODO) + proces de dezvoltare embedded (PLAN separat de EXECUTE/VERIFY
pe sesiuni, PRD per livrabila cu stories atomice, agent team, bootstrap
reluabil din starea PRD).

- adauga docs/prd/TEMPLATE-prd.md (schelet PRD)
- sterge docs/plans/plan.md (Treapta 1 realizat), plan-treapta2.md
  (Treapta 2 realizat), docs/CONTEXT.md (snapshot neactual)
- actualizeaza referintele in README.md si api-rar-contract.md

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 07:21:20 +00:00
Claude Agent
c38807d88c docs(plan): adauga plan-treapta2.md (planul Treapta 2)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 06:51:39 +00:00
Claude Agent
9106983dd5 docs: README cu ghid de testare (browser, API, RAR, conturi/chei API)
Adauga README.md: arhitectura, configurare, rulare locala si cu start.sh,
testare in browser (dashboard, Swagger, import xlsx/csv), proba trimitere la
RAR test + verificare, formate de fisier per cont (signature_coloane), conturi
si chei API (CLI tools.apikey, exemple curl cu X-API-Key) si starea reala a
auth-ului (POST/import protejate; GET-uri de listare inca globale).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 06:51:34 +00:00
Claude Agent
0b3e2464e1 feat(ops): scripturi start.sh (test/prod, api/worker) + verificare RAR
start.sh ruleaza api/worker/both pe mediu test sau prod, cu --send pentru
trimiterea la RAR, plus status/stop. start-test.sh si start-prod.sh sunt
wrappere care fixeaza mediul. tools/rar_finalizate.py listeaza prezentarile
inregistrate la RAR (confirmare end-to-end ca au ajuns). .gitignore: .run/.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 06:51:27 +00:00
Claude Agent
5a8787bbc4 chore(legacy): muta proiectul Visual FoxPro in legacy-vfp/
Codul VFP original (ROAAUTO) era doar de testare/proba si nu se mai dezvolta.
Mutat in legacy-vfp/ (sursa .prg, proiect .pjx/.PJT, date .DBF/.CDX/.FPT,
test-comenzi.xml). Actualizat caile DBF default in tools/import_dbf.py si
referinta din tests/test_import_dbf.py. Adaugat legacy-vfp/README.md.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 06:51: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
55adfa214f test(e2e): T15 — E2E integrare import->commit->worker (MockRar) + masina de stari + failure registry
21 teste noi in tests/test_import_e2e.py:
  - Scenariul 1: upload xlsx/csv -> column-mapping -> preview -> commit -> worker -> FINALIZATA
  - Scenariul 2: re-upload acelasi continut -> already_sent (nu al doilea POST la RAR)
  - Scenariul 3: coada MIXTA API(creds efemere)+web(accounts.rar_creds_enc durabil) — T1/Voce#5
  - Masina de stari: queued->sending->sent/requeued/error + double-commit 409 + batch committed
  - Failure registry: RAR 400/403 + reconciliere raspuns pierdut (503) + max_retries->error
  - T16: purge_expired + purge_after setat la commit si la trimitere

Suita completa: 264 passed, 0 failed (fara regresii Treapta 1 sau Treapta 2).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-16 20:51:57 +00:00
Claude Agent
70f717d874 feat(import): #11-14 router import Treapta 2 — upload+staging+mapare+preview+commit+export
Implementeaza app/api/v1/import_router.py (router nou, montat in app):

POST /v1/import — upload xlsx/csv, staging in import_batches/import_rows,
  PII criptat Fernet (Issue 5a), BEGIN IMMEDIATE+executemany (Issue 6),
  purge_after 90z (T16), sugestii fuzzy coloane DRY (Issue 5b/Eng#4),
  detectie drift semnatura (T4/D3), multisheet support

GET/POST /v1/import/{id}/column-mapping — mapare coloane per cont cu
  semnatura + drift detection

GET /v1/import/{id}/preview — 6 stari per rand (ok/needs_mapping/needs_data/
  needs_review/already_sent/duplicate_in_file), already_sent batch lookup
  nu N+1 (Eng#5), intra-batch collision EXCLUSIV preview (OV-3/T11)

POST /v1/import/{id}/commit — gate HARD N confirmat (T5/D3), atestare pe
  valori (Voce#1), INSERT ON CONFLICT DO NOTHING TOCTOU (Issue 1/T12),
  import_attestations rows_hash+n_confirmed (Voce#9), batch_id/row_index (T7)

GET /v1/import/{id}/export-failed — CSV randuri esuate cu motiv (T8)

Teste: 36 cazuri noi in tests/test_import_api.py; 243 total, toate verzi.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-16 20:41:59 +00:00
Claude Agent
2c8367109c feat(parser): T14 — parser core 2-treceri xlsx/csv + T3 coercion + T10 data col-level + T13 robustete RO
Implementeaza app/import_parse.py (modul nou) cu toate cele 4 taskuri parser:

T14 (task #7): schelet parser + arhitectura 2-treceri (Issue 2 consens cross-model)
- Trecerea 1 read_only=True: dim-check FileTooLarge (>5000 randuri / >5MB) + detectie multi-sheet
- Trecerea 2 normal-mode: header + merged cells + body
- CSV delimiter sniff (csv.Sniffer + proba explicita {; , \t}) — export RO foloseste ;
- Encoding: UTF-8-sig -> UTF-8 -> cp1250 -> latin2 (fallback RO)
- Exceptii custom: FileTooLarge, HeaderError, MultipleSheets
- Coloane duplicate din merge: sufixate _2/_3 (nu HeaderError)

T3 (task #8): coercion guard + needs_review + mesaj formule-None
- VIN numeric (openpyxl citeste ca int/float) -> coercion_flags[row] needs_review
- Odometru float 123456.0 -> tunde .0 inainte de validare (§3.4bis, ordonare critica)
- Rata None > 60% pe coloana obligatorie -> formula_columns (Issue 3 mesaj specific)
- Datetime nativ -> convertit la YYYY-MM-DD (neambiguu)

T10 (task #9): dezambiguizare data la nivel de COLOANA (OV-8)
- Datetime nativ -> "native" (direct, fara ambiguitate)
- String: detectie format din intreaga coloana — daca oricare rand are token[1]>12 -> DD-first
- Daca toti zi<=12 -> "ambiguous" -> needs_review per rand
- parse_date_value() helper pentru preview resolve

T13 (task #10): robustete export RO
- Multi-sheet: >1 sheet non-gol -> MultipleSheets([...]) cu lista; sheet ales -> parse normal
- Merged header: _unmerge_header propaga valoarea topleft la toate coloanele din grup
- Footer trim: randuri trailing cu VIN + data ambele goale -> skip structural (nu needs_data)

Teste: 37 teste verzi in tests/test_import_parse.py (fixture-uri xlsx generate in-memory).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-16 20:31:27 +00:00
Claude Agent
ef52dc2823 feat(import): T16 job purjare + purge_after SET la sent (OV-5)
- mark(sent): seteaza purge_after = now + 90 zile (GDPR/L.142)
- purge_expired(conn): sterge submissions sent expirate + import_batches expirate
  (import_rows via ON DELETE CASCADE). NULL purge_after = nu expira.
- run(): tick de purjare odata pe ora (guard _last_purge_time + _PURGE_INTERVAL_S)
  NU mai agresiv, nu blocheaza trimiterea
- 8 teste: purge_after la sent, alte stari fara purge, expirati vs neexpirat,
  queued neatins, cascade import_rows, null purge_after pastrat

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-16 20:24:59 +00:00
Claude Agent
8cdfc976e4 feat(import): T7 batch_id scope reresolve_account — R1 INCHIS
- reresolve_account(conn, account_id, batch_id=None):
  - batch_id specificat -> scope la batch-ul exact (import commit explicit)
  - fara batch_id (POST /v1/mapari) -> EXCLUSIV canal API (batch_id IS NULL)
  - salvarea unei mapari NU mai re-queues randuri cross-batch (R1 inchis)
- 6 teste: izolare batch A/B, regresie API canal, batch explicit nu atinge API,
  schema batch_id/row_index, 3 batches izolate

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-16 20:23:11 +00:00
Claude Agent
61a7b4ea1c feat(import): T6 gate auto_send pe coduri nou-mapate (OV-1)
- load_mapping_meta: {cod_op_service -> {cod_prestatie, auto_send}}
- has_no_auto_send: verifica daca vreun item rezolvat via mapping are auto_send=0
- reresolve_account: auto_send=0 -> ramane needs_mapping (review_manual stat),
  NU trece pe queued; previne FINALIZATA eronat permanent
- reresolve_account primeste batch_id optional (pregatire T7, urmeaza)
- POST /v1/prezentari: auto_send=0 -> needs_mapping + motiv explicit
- 9 teste: load_mapping_meta, has_no_auto_send, reresolve (zero/unu), POST API

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-16 20:21:32 +00:00
Claude Agent
12f0ca3a81 feat(import): T1 accounts.rar_creds_enc durabil + worker fallback + gate purjare
- worker: _creds_from_account(conn, account_id) — fallback la accounts.rar_creds_enc
  cand submission n-are creds (canal web fara re-pusher, restart worker)
- run(): creds = _creds_for(claimed, settings) OR _creds_from_account(conn, account_id)
- gate purjare (Voce#5): comentariu explicit — sterge DOAR submissions.rar_creds_enc,
  NU accounts.rar_creds_enc (inofensiv pt canal web, neatins pt canal API)
- POST /v1/conturi/rar-creds: seteaza creds durabile criptate Fernet per cont
- DELETE /v1/conturi/rar-creds: revenire la modelul efemer Treapta 1
- 7 teste: fallback, restart, coada mixta, endpoint set/delete, gate purjare

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-16 20:18:41 +00:00
Claude Agent
4ea21a034e feat(import): T9 canonicalize_row + build_key partajat (idempotency)
- canonicalize_row: VIN upper, odometru strip ".0" (Excel float coercion),
  data strip — INAINTE de validare si cheie (§3.4bis)
- build_key: aplica account_or_default(None->1) inainte de hash (OV-2):
  canal API (None) si canal import (1) produc aceeasi cheie
- build_key_legacy: helper dual-lookup pentru randuri DB vechi (pre-T9)
- router.py: POST /v1/prezentari foloseste build_key(account_id, canonicalize_row(content))
- 14 teste: canonicalizare, cross-canal, dedup float/int odometru, legacy

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-16 20:15:59 +00:00
Claude Agent
80897ccbb1 feat(foundation): schema Treapta 2 + migrari aditive + openpyxl pinned (#1)
- accounts.rar_creds_enc TEXT (creds RAR durabile per-cont, D4)
- submissions.batch_id, row_index (T7 scoping R1)
- submissions.purge_after (T16 GDPR)
- Tabele noi: column_mappings, import_batches, import_rows, import_attestations
- _migrate idempotent pe DB veche (ALTER aditiv, pattern existent)
- openpyxl==3.1.5 adaugat in requirements.txt (Issue 4, PINNED)
- 15 teste noi: coloane, tabele, idempotenta, migrare DB veche, openpyxl

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-16 20:13:19 +00:00
Claude Agent
4295a0aa31 docs(plan): E2E live prin gateway confirmat (idPrezentare 68516 FINALIZATA)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 21:08:28 +00:00
Claude Agent
fa65e1da2e docs(plan): marcheaza /design-review done (FINDING-004 htmx local)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 20:59:25 +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
8748c21379 chore: ignore .gstack/ (artefacte locale gstack)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 20:40:12 +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