Criterii noi (din docs/mockups/prd-5.15-mockups.html), facute AC testabile:
- antet: referinta vizuala obligatorie la mockup-uri
- US-002: doar tokeni CSS, fara hex hardcodat (AA pe teme luminoase)
- US-003: layout exact strip D6 (glife/copy/last-auth) + stari goale + ierarhie all-time
- US-004: 'Eroare VIN' ilustrativ; pills din labels.py
- US-007: referinta picker op<->cod (2 stari) + reveal odometru
Include si revizia /plan-eng-review care era in working tree necomisa
(E1-E8, US-011 authz, US-012 analytics, Val 0, raport eng CLEARED).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Tema grafit, tokenuri identice cu landing.html. Acopera cele 3 piese pe
care mockup-urile existente nu le aratau si rezolva contradictiile
mockup<->PRD: VIN unic (fara Confirma VIN), contor Trimise all-time ca
cifra principala, culori prin tokeni (nu hex hardcodat), picker prestatii
pe operatie (op<->cod) in loc de chips plate.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
PRD 5.14 rescris cu pivotul arhitectural: LLM doar etichetator OFFLINE,
runtime = clasificator local fara API (fuzzy + embeddings), baza de
cunostinte GOLD partajata cross-account (validarea unui service ajuta
toate). Decizia 8 (corpus per-cont) SUPERSEDED.
Tooling nou OpenRouter (free, familia NVIDIA Nemotron): or_common.py
(client + corpus pe frecventa, cheie din .env) + or_modeltest.py
(comparatie modele, acord ensemble vs Groq). Masurat: super-120b +
nano-9b fiabile, 3/3 unanim pe 87% volum; ultra-550b aruncat.
Corpus real (4 CSV service, coloana NR=frecventa) + etichete Groq
bootstrap incluse ca date de masurare.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Dashboard compact (carduri-contor + lista slim), formular editare slim cu
VIN unic, Observatii (text liber = operatii service) si prestatii ca chips
multi-select. Propaga sistemul de design al landing-ului (teme/culori/carduri)
in controalele aplicatiei.
Decizii confirmate cu userul: D1 contoarele inlocuiesc bara de status; D2 teme
aditive (light/dark/petrol/Auto + grafit/cobalt/cupru/hartie); D3 chips reale
multi-cod; D4 contor Trimise all-time + luna + azi; D5 obs = denumirea
operatiilor de service (in payload, fara coloana noua; concatenat la import).
8 stories / 5 valuri, backend separat de UI. Draft, asteapta poarta de aprobare.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Dogfood pe import + Trimiteri (mobil/tableta <1024px), pur CSS + markup, backend
trimitere neatins:
- Card compact real pentru .tabel-trimiteri (preview + Trimiteri): vehicul=titlu,
stare=pill dreapta-sus, operatie+cod, meta data/km muted, nota mica. Inlocuieste
stiva generica eticheta+valoare (carduri de ~450px -> ~135px). Anuleaza regula
desktop tr.trimitere-row > td{padding:11px} in blocul compact.
- FIX editare preview: OOB swap pe <tr> esua tacit in htmx 1.9 (un <tr> brut se
pierde la parsarea unui fragment fara context de tabel) -> randul ramanea cu
starea veche dupa salvare. Inlocuit cu reload complet al preview-ului prin
HX-Trigger:reincarcaPreview + detalii randSalvat. /editeaza si /confirma-review
folosesc helper-ul _raspuns_rand_salvat.
- Feedback post-salvare: toast global "Randul N actualizat · <stare>" + scroll +
flash pe randul actualizat (base.html window.arataToast + listener randSalvat).
- Modal editare: Salveaza + Anuleaza pe acelasi rand (sistem .act): desktop text,
mobil doua iconite Lucide 44px alaturate (save/x). Macro icon('x') + .act-primary.
- Randuri deja-trimise/duplicate colapsate implicit in preview + toggle "Arata N".
- Select "Operatii de mapat" full-width pe mobil (nu mai iese din viewport).
- Bara de filtre Trimiteri adaptata mobil: pills pe banda cu scroll orizontal,
cautare vehicul proeminenta (nu 8 butoane full-width stivuite).
- Nota preview = culoarea camp-fix (accent) ca sa atraga atentia; hint-urile
camp-fix per-camp scoase (campul Note e self-explanatory).
- Confirmare trimitere: scos campul email (Declarant); text mai clar
("Confirma numarul din N gata de trimis"). Backend confirmed_by ramane optional.
Teste: contractul OOB (rupt in browser) inlocuit cu noul contract
(reincarcaPreview + randSalvat) in test_web_preview_edit / test_preview_edit_ui /
test_import_review. Suita: 992 passed (exclus live).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Referinta pentru generarea unui mockup de homepage public: plan gratuit
(sub 100 prezentari/luna), beneficii interfata, integrare API. Tokeni de
culoare/tipografie preluati din design.md.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
5.12 (livrat): editare in modal a randurilor de preview, cont obligatoriu inainte de
import, formular editare extras (_form_editare, _editare_preview_modal), plus suita de
teste aferenta (preview edit/compact, mapare op, form editare, signup, admin panel).
Design + planificare:
- docs/design.md: sistem de design (tokeni, breakpoints, scara control, componente, a11y).
- docs/prd/prd-5.12-* si prd-5.13-* (5.13 cu raport /autoplan: CEO+Design+Eng, audit trail).
Curatare: sterse PNG-urile de test/mockup temporare din radacina.
Nota: implementarea CSS 5.13 (responsive compact + sistem butoane) NU e inca facuta —
planul revizuit cere refactorul testelor fragile din test_web_responsive.py INAINTE de CSS.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Suita completa 843 passed/1 skipped. E2E real in browser confirma:
modal/focus-trap/poll-guard/responsive si fluxul live de corectie.
Fara leak de cod brut pe rand (R1/D2).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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>
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>
Cod_prestatie necunoscut in nomenclator nu se mai trimite raw la RAR (HTTP 500
ORA-12899 + record partial FINALIZATA pe care reconcilierea il marca fals sent):
e promovat la cod_op_service si tratat ca operatie de mapat.
Optiune top-level boolean on_unmapped_error pe POST /v1/prezentari + /valideaza:
- false (default) -> submission needs_mapping (intra in editor)
- true -> respinge fara enqueue (status error, submission_id=null, erori)
- None -> default per-cont accounts.on_unmapped_error_default (implicit 0)
Inlocuieste enum-ul anterior on_unmapped (needs_mapping/error) cu un boolean mai
simplu; coloana de cont migrata aditiv la INTEGER on_unmapped_error_default.
Izolare teste de .env-ul de dezvoltare: tests/conftest.py fixeaza default sigur
pe AUTOPASS_REQUIRE_API_KEY / AUTOPASS_WORKER_USE_TEST_CREDS (precedenta peste
.env in pydantic-settings) + fixturile env din test_creds_delivery/test_t1 pineaza
explicit aceste flag-uri, ca fallback-ul creds pe cont sa fie atins.
Teste: 752 passed (fara flag pe CLI).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
T6 — worker supravegheat:
- app/worker/healthcheck.py: probe pe heartbeat-ul din DB (beat invechit -> exit 1).
Prinde worker-ul agatat (proces viu, beat inghetat) pe care restart:always nu-l
vede. Cablat ca healthcheck pe serviciul worker in compose.
- sidecar autoheal: restarteaza efectiv containerul unhealthy (compose simplu doar
marcheaza, nu restarteaza la unhealthy).
T7 — deploy:
- tools/backup.py: backup ONLINE via Connection.backup (WAL nu se copiaza sigur cu
cp); --keep N roteste snapshot-urile.
- .env.example documenteaza env-urile; volum persistent numit deja in compose.
Fix critic (split api/worker in 2 containere): AUTOPASS_CREDS_KEY trebuie PARTAJATA
api<->worker, altfel worker nu decripteaza creds-urile criptate de API -> submission
blocate. Acum impusa in compose (${...:?} -> fail explicit daca lipseste).
.gitignore: exceptie !.env.example.
5 teste noi (tests/test_deploy.py). 100 pass total.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Plan sect.5: parola RAR vine per-cerere, stocata CRIPTATA in submission pana la
primul login reusit pe cont, apoi stearsa; JWT 30h acopera restul.
- app/crypto.py: Fernet, cheie din AUTOPASS_creds_key (nesetata -> efemera la
runtime, creds nu supravietuiesc restartului). encrypt/decrypt_creds.
- schema + migrare: submissions.rar_creds_enc (creds criptate).
- ingestie: cripteaza rar_credentials, le lipeste de fiecare submission nou.
Niciodata in clar in DB.
- worker: AccountSessions (login per-cont cu creds decriptate, cache JWT in
memorie, sterge creds-urile contului dupa primul login + refresh nomenclator).
401 creds gresite -> error fara retry; token expirat -> invalidare + requeue;
fara creds (restart) -> requeue "indisponibile" (ROAAUTO re-trimite).
claim_one intoarce account_id + creds_enc; recover_orphans filtrabil pe cont.
- requirements: cryptography==46.0.5.
Nota: refresh nomenclator e acum lazy la primul login per-cont (nu la pornire);
seed-ul fallback acopera editorul offline.
10 teste noi (tests/test_creds_delivery.py). 95 pass total.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Redactare:
- handler RequestValidationError dropeaza input/ctx din 422 (vectorul de
scurgere a rar_credentials.password pe /v1/prezentari); pastreaza type/loc/msg
- app/security.py: scrub/scrub_text + CredentialRedactingFilter pe root+uvicorn
- models.py: password cu repr=False
Auth API-key:
- app/auth.py: hash SHA-256 in api_keys (cheia in clar emisa o singura data),
header X-API-Key / Authorization: Bearer, dependency resolve_account_id
- enforcement pe flag AUTOPASS_require_api_key (prod on->401, dev off->cont
default id=1; cheie prezenta invalida->401 mereu)
- account_id real curge din cheie in ingestie + mapare
- tools/apikey.py: CLI create/rotate/revoke/list (fara endpoint HTTP admin)
16 teste noi (tests/test_security.py). 85 pass total.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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>