Files
rar-autopass/docs/prd/prd-5.1-hub-integrare.md
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

24 KiB
Raw Blame History

PRD 5.1 — Hub de integrare (pagina /integrare cu exemple de cod + retetar VFP + ping + export)

Stare: inchis (2026-06-22 — VERIFY PASS + E2E browser PASS + /code-review high incorporat; 568 teste pass; writeback ROADMAP facut; asteapta poarta umana de commit)

Proces complet: docs/ROADMAP.md §5. Contract RAR (sursa de adevar): docs/api-rar-contract.md. Starea trece: draft → aprobat → in-executie → verify-pass → inchis (actualizata de lead). Backend trimitere (worker, masina stari, idempotenta-logica, mapping-rezolvare) NU se atinge. Aceasta livrabila adauga DOAR suprafata de onboarding/integrare (citire) peste API-ul existent + stratul web. Schema neatinsa (zero coloane noi).

1. Obiectiv

Produsul e functional pe ambele canale (API + import web), dar un service nou care vine din Visual FoxPro sau soft propriu nu are de unde sa inceapa integrarea: cheia API se creeaza/roteste din web (/cont), insa nu exista nicio pagina cu cum chem API-ul, ce payload, ce header, in ce limbaj. Singurele referinte sunt README.md (curl) si Swagger /docs — invizibile din aplicatie si fara exemple in limbajul integratorului.

Livram o pagina /integrare (tab nou, autentificat, scoped pe contul din sesiune) care:

  • afiseaza exemple de cod pre-completate cu endpoint-ul real + account_id-ul utilizatorului pentru ambele canale (POST /v1/prezentari JSON si POST /v1/import upload fisier), in curl, Python, PHP, C#, Node;
  • include un retetar Visual FoxPro (POST via MSXML2.ServerXMLHTTP.6.0 SI WinHttp.WinHttpRequest.5.1, plus upload CSV);
  • ofera export OpenAPI (/openapi.json din FastAPI) + colectie Postman + link Swagger /docs;
  • are un buton "Testeaza conexiunea": utilizatorul lipeste cheia salvata, iar serverul confirma ca e valida si mapeaza pe contul lui (acelasi drum de auth ca API-ul real).

Constrangere de securitate (din app/auth.py): stocam DOAR SHA-256 al cheii API, deci nu putem reafisa cheia. Exemplele folosesc placeholder rfak_...; cheia reala se obtine o singura data la creare/rotire din /cont.

2. Non-Goals (anti scope-creep)

  • Nu reafisam cheia API — exemplele au placeholder, niciodata cheia in clar (SHA-256-only).
  • Fara markdown versionat in docs/ (decis cu utilizatorul: doar pagina in-app dinamica). Daca apare nevoia de referinta indexabila, e o livrabila viitoare separata.
  • Fara generare automata de SDK-uri — OpenAPI + Postman sunt punctul de plecare; integratorul genereaza singur.
  • Fara dry-run — validarea de payload fara enqueue e livrabila 5.2 (separata). GET /v1/ping verifica DOAR autentificarea (cheie valida + cont activ), nu valideaza continut.
  • Fara editarea exemplelor de catre user — continut read-only generat din schema.
  • Nu atinge backend-ul de trimitere (worker/masina stari/idempotenta-logica/mapping-rezolvare) si nici schema.
  • Fara i18n — pagina e in romana, ca restul UI-ului.

3. Stories atomice

Backend + UI pentru acelasi comportament = stories separate. Toate rutele web noi sub require_login + scoped pe contul din sesiune. CSRF pe toate POST-urile web. Endpoint-urile /v1/* folosesc resolve_account_id.

US-001: Backend — endpoint-uri de integrare (GET /v1/ping + export Postman)

Ca integrator extern vreau un endpoint care confirma ca cheia mea functioneaza si o colectie Postman gata de importat pentru ca sa-mi validez conexiunea inainte sa trimit prezentari reale.

  • Depinde de: —
  • Fisiere: app/api/v1/integrare_router.py (NOU), montare in app/main.py (app.include_router), tests/test_integrare_api.py (~3 fisiere)
  • Montare (decizie eng-review P1): router nou cu prefix="/v1", inclus in app/main.py cu app.include_router(...) (consistent cu import_v1_router). NU sub-include in app/api/v1/router.py (acela are deja prefix="/v1" → ar dubla prefixul).
  • Test intai (RED): tests/test_integrare_api.pytest_ping_cu_cheie_valida_200 (raspuns: account_id, mediu test/prod, autentificat_cu_cheie=true, are_creds_rar, ts), test_ping_cu_bearer_valid_200 (Authorization: Bearer rfak_...), test_ping_fara_cheie_dev_cont_implicit (flag off → cont 1, autentificat_cu_cheie=false), test_ping_x_api_key_gol_in_dev_cont_implicit (whitespace tratat ca lipsa), test_ping_are_creds_rar_reflecta_contul (cont cu accounts.rar_creds_enctrue; fara → false), test_ping_cheie_invalida_401, test_ping_prod_fara_cheie_401 (flag on), test_ruta_ping_inregistrata_o_singura_data (assert pe app.routes — fara dubla inregistrare), test_postman_export_json_valid (Content-Type JSON, parseaza, schema Postman v2.1.0), test_postman_contine_exact_trei_requesturi (prezentari, import, ping; header X-API-Key: {{api_key}}; {{base_url}}), test_postman_nu_deriva_din_app_routes (allowlist hardcodat — NU expune /v1/conturi/rar-creds etc.).
  • Acceptance criteria:
    • GET /v1/ping (dependinta resolve_account_id) = readiness check, nu doar auth-echo: cheie valida → 200 {account_id, mediu, autentificat_cu_cheie, are_creds_rar, ts}; cheie invalida → 401; fara cheie cu require_api_key=true → 401; fara cheie in dev → cont 1 cu autentificat_cu_cheie=false. (are_creds_rar = contul are accounts.rar_creds_enc setate; citire-only, raspunde la "esti gata sa trimiti?", nu doar "cheia merge". CEO-review P1/P2.)
    • Suporta si Authorization: Bearer rfak_... (al doilea header documentat in pagina).
    • GET /v1/integrare/postman.json: colectie Postman v2.1.0 cu variabile base_url + api_key, exact 3 requesturi (allowlist hardcodat, NU derivat din app.routes): POST /v1/prezentari, POST /v1/import, GET /v1/ping, fiecare cu header X-API-Key: {{api_key}} si body exemplu (pt prezentari: payload din schema reala PrezentareRequest, inclusiv prestatii).
    • /openapi.json ramane accesibil (FastAPI implicit) — niciun regres.
    • NU atinge submissions, worker, schema. are_creds_rar = SELECT read-only pe accounts.
  • Verificare E2E: curl -H "X-API-Key: rfak_..." http://localhost:8010/v1/ping pe instanta locala → 200 cu contul corect + are_creds_rar; import postman.json in Postman/Swagger.

US-002: Helper pur — generator de exemple de cod multi-limbaj

Ca dezvoltator al gateway-ului vreau un modul pur care produce snippet-urile de integrare dintr-un (base_url, account_id) pentru ca pagina sa fie testabila si snippet-urile sa ramana langa schema reala.

  • Depinde de: —
  • Fisiere: app/web/integrare_examples.py (NOU), tests/test_integrare_examples.py (~2 fisiere)
  • Test intai (RED): tests/test_integrare_examples.pytest_snippet_curl_prezentari_contine_endpoint_si_header ({base_url}/v1/prezentari, X-API-Key: rfak_...), test_snippet_python_import_upload_multipart (foloseste files= / multipart pe /v1/import), test_toate_limbajele_prezente (curl, python, php, csharp, node, vfp_msxml, vfp_winhttp), test_ambele_canale_per_limbaj (fiecare limbaj are si prezentari JSON, si upload fisier), test_vfp_msxml_si_winhttp_distincte (MSXML2.ServerXMLHTTP.6.0 vs WinHttp.WinHttpRequest.5.1), test_payload_acopera_campurile_obligatorii_din_model (snippet-ul prezentari contine TOATE campurile obligatorii derivate prin field.is_required() din PrezentareIn — INCLUSIV prestatii cu ≥1 item — si RarCredentials{email,password}; drift-test corect: {c for c,f in PrezentareIn.model_fields.items() if f.is_required()} ⊆ campurile din snippet; campurile cu default — odometru_initial, obs, b64_image, sistem_reparat — NU dau drift fals), test_prestatii_in_snippet_are_cod (item-ul prestatii are cod_prestatie SAU cod_op_service — vezi PrestatieItem._require_one), test_placeholder_cheie_nu_e_valoare_reala (mereu rfak_..., niciodata o cheie injectata).
  • Acceptance criteria:
    • Functie pura exemple(base_url: str, account_id: int) -> dict care intoarce, per limbaj, snippet pt ambele canale.
    • Placeholder cheie = rfak_... (constant), endpoint-ul derivat din base_url.
    • Payload-ul JSON reflecta schema reala (PrezentareRequest): rar_credentials{email,password} + prezentari[] cu toate campurile obligatorii prin is_required(), inclusiv prestatii cu cel putin un item valid (eng-review P1: prestatii e fara default → obligatoriu; un payload fara el ar fi nevalid, exact ce pagina trebuie sa previna).
    • Drift-test foloseste field.is_required() (nu doar prezenta cheii), ca sa nu raporteze fals campurile cu default.
    • Fara I/O, fara DB, fara stare globala — pur (usor de testat).
  • Verificare E2E: acoperita de UI (US-003) + unit teste.

US-003: UI — tab "Integrare" cu exemple, retetar VFP si export

Ca utilizator vreau o pagina cu exemple gata de copiat in limbajul meu + linkuri de export pentru ca sa integrez gateway-ul fara sa caut prin README/Swagger.

  • Depinde de: US-001, US-002, US-004
  • Fisiere: app/web/routes.py (_render_integrare + /_fragments/integrare + integrare in _TABS_VALIDE + branch nou in _render_panel_for_tab — necesar pt deep-link server-side, altfel /?tab=integrare cade pe Acasa), app/web/templates/dashboard.html (tuplu nav nou + generalizarea scriptului ARIA tablist), app/web/templates/_integrare.html (NOU), tests/test_web_integrare.py (~4 fisiere)
  • Test intai (RED): tests/test_web_integrare.pytest_tab_integrare_in_nav, test_deeplink_tab_integrare_randeaza_panou_server_side (/?tab=integrare → panou randat, NU Acasa — prinde branch-ul lipsa din _render_panel_for_tab), test_fragment_integrare_necesita_login (require_login), test_pagina_contine_account_id_si_endpoint_real (din request.base_url), test_pagina_are_tab_limbaje_si_vfp_cu_dialecte (limbaj = tablist primar; VFP = un tab cu sub-tablist MSXML2/WinHttp), test_canal_secundar_prezentari_si_import, test_export_card_openapi_postman_swagger, test_buton_copiaza_citeste_din_pre_code (markup copy citeste din <pre><code>, nu din atribut), test_empty_state_cta_cont_cand_fara_cheie_sau_creds, test_fara_culori_hardcodate_doar_tokens (snippet-ul template-ului nu contine #-hex; doar var(--...)).
  • Acceptance criteria:
    • Tab nou "Integrare" in nav (dashboard.html), integrare in _TABS_VALIDE, branch nou in _render_panel_for_tab, deep-link /?tab=integrare randat server-side, fragment lazy pe click (pattern identic cu Mapari/Cont). NU atinge _render_panel_import/coada.
    • IA pe doua niveluri (design-review P1): tab primar = LIMBAJ (curl/Python/PHP/C#/Node/VFP) — VFP e UN tab, nu sectiune separata; in panelul VFP, al doilea tablist = dialect (MSXML2 / WinHttp). Tab secundar (in fiecare panel de limbaj) = CANAL (Prezentari JSON / Import fisier). Se vede UN singur snippet o data (fara produs cartezian 14-snippet pe ecran).
    • Refolosire ARIA (design-review P1): generalizeaza scriptul de keyboard-nav din dashboard.html (sageti/Home/End, roving tabindex, sync aria-selected+aria-controls) ca sa prinda ORICE [role=tablist], scoped pe containerul propriu (nu primul querySelector global) — altfel tab-urile imbricate (limbaj/canal/VFP-dialect) intra in conflict pe ArrowRight.
    • Copy-to-clipboard (design-review P2): buton per snippet care citeste textul din <pre><code> asociat (NU din data-*); feedback in aria-live="polite" + label "Copiat" cu revenire la "Copiaza" dupa ~2s; navigator.clipboard cu .catch() + fallback pt context ne-securizat (selecteaza textul + "Ctrl+C") — butonul nu ramane blocat fals pe "Copiat".
    • Empty-state onboarding (design-review P2 + CEO P1): cand sesiunea NU are cheie rotita sau NU are creds RAR, afiseaza deasupra snippet-urilor un empty-state cu CTA direct href="/?tab=cont" ("Genereaza cheia din Cont; o vezi o singura data"). Snippet-urile raman vizibile (placeholder-based). Flux de onboarding continuu, nu doar o nota text.
    • Card separat "Export & referinta" (componenta .cardlink): Swagger /docs, GET /openapi.json, GET /v1/integrare/postman.json (Postman = download; restul target="_blank" rel="noopener").
    • Integreaza formularul "Testeaza conexiunea" din US-004 (primul card al panoului; markup-ul tinteste ruta US-004).
    • Tokens de tema (design-review P3, pregatire 5.3): template-ul foloseste DOAR variabilele din :root (--bg/--card/--ink/--muted/--line/--accent), zero culori hex hardcodate; fara highlight de sintaxa colorat (ar introduce paleta noua). Cod copiabil pe --ink, nu --muted.
  • Verificare E2E: browser pe /integrare — comuta limbaj (inclusiv VFP cu dialect), comuta canal, copiaza un snippet (vezi "Copiat" + revenire), vede account_id-ul + endpoint-ul reale, deschide /openapi.json si importul Postman.

US-004: Backend web — "Testeaza conexiunea" (verifica cheia lipita, scoped pe sesiune)

Ca utilizator vreau sa lipesc cheia mea si sa primesc confirmare ca e valida pentru ca sa stiu ca integrarea va autentifica corect inainte sa scriu cod.

  • Depinde de: —
  • Fisiere: app/web/routes.py (POST /integrare/test-cheie, require_login + CSRF), app/web/templates/_integrare_test_rezultat.html (NOU — fragment de raspuns dedicat, NU inline in _integrare.html care apartine US-003; eng-review P2: evita fisier partajat intre valuri), tests/test_integrare_test_cheie.py (~3 fisiere)
  • Test intai (RED): tests/test_integrare_test_cheie.pytest_cheie_valida_a_contului_curent_ok (mesaj succes + account_id), test_cheie_a_altui_cont_respinsa (cheia mapeaza pe alt cont → mesaj "nu apartine contului tau", NU dezvaluie care), test_cheie_invalida_mesaj_clar, test_cheie_revocata_dupa_rotire_respinsa (eng-review P2: cel mai probabil caz de suport — lipesti cheia veche dupa rotire), test_cheie_goala_nu_da_fals_pozitiv_in_dev (eng-review P2: foloseste account_for_key direct, NU resolve_account_id cu fallback cont 1), test_fara_login_redirect_sau_401, test_csrf_lipsa_respinsa, test_cheia_nu_apare_in_raspuns_sau_log (no echo).
  • Acceptance criteria:
    • POST /integrare/test-cheie (require_login, CSRF): valideaza cheia lipita prin account_for_key direct (NU resolve_account_id — altfel in dev o cheie goala/gunoi ar cadea pe cont 1 si ar raporta fals "valida"); confirma DOAR daca mapeaza pe contul sesiunii; altfel mesaj neutru ("nu apartine contului tau", fara sa dezvaluie care cont).
    • Cheie revocata (dupa rotire) → tratata ca invalida (account_for_key filtreaza active=1).
    • Niciun echo al cheii in raspuns/log (regula 422-no-echo din main.py).
    • Raspuns HTML fragment dedicat (_integrare_test_rezultat.html), htmx swap intr-un container aria-live="polite": succes pe .flash (border --ok, "Cheie valida — cont X"), eroare pe .banner (border --err). Label uman, fara emoji.
    • Input type=password + autocomplete="off"; microcopy anti-confuzie langa camp: "Verificam doar daca cheia e valida. Nu o salvam si nu o memoram — cheia se gestioneaza in Cont." Buton "Testeaza conexiunea" (NU "Salveaza").
    • NU creeaza/roteste chei (doar verifica) — fara efecte secundare.
  • Verificare E2E: browser — lipeste cheia reala (din rotire /cont) → "valida, cont X"; lipeste gunoi → eroare clara; lipeste cheia veche dupa rotire → respinsa.

4. Graful de valuri

  • Val 1 (paralel, fisiere disjuncte): US-001 (integrare_router.py NOU) ‖ US-002 (integrare_examples.py NOU) ‖ US-004 (routes.py + test). US-001 si US-002 sunt fisiere noi; US-004 atinge routes.py (ruta noua, fara suprapunere cu US-003 care vine in Val 2). Atentie: US-003 si US-004 ating ambele routes.py → NU in acelasi val.
  • Val 2: US-003 (UI: routes.py + dashboard.html + _integrare.html) — depinde de US-001/US-002/US-004. Nota (eng-review P2): US-004 isi pune raspunsul in _integrare_test_rezultat.html (fisier propriu), NU in _integrare.html (al US-003) — asa cele doua valuri nu impart un template.

Prioritate de descope (CEO-review P2/P3) — daca timpul se scurteaza, taie in aceasta ordine inversa de valoare:

  1. (pastreaza ultimul) US-002 + US-003 exemple + retetar VFP in pagina = wedge-ul de adoptie, ne-negociabil.
  2. US-004 (test cheie) — potentator.
  3. US-001 ping — potentator.
  4. (primul taiat) export Postman/OpenAPI — audienta moderna (Python/Node), public secundar fata de VFP. Retetarul VFP ramane prim-clas indiferent de descope.

5. Considerații tehnice

  • Auth: header X-API-Key: rfak_... (sau Authorization: Bearer rfak_...), dependinta resolve_account_id (app/auth.py). In dev (require_api_key=false) lipsa cheii → cont 1; ping semnaleaza asta cu autentificat_cu_cheie.
  • Schema request (din app/models.py): PrezentareRequest{rar_credentials{email,password}, prezentari[PrezentareIn]}; PrezentareIn{vin, nr_inmatriculare, data_prestatie(YYYY-MM-DD), odometru_final(str), odometru_initial?, sistem_reparat="null", obs?, b64_image?, prestatii?[{cod_prestatie|cod_op_service, denumire}]}.
  • Import: POST /v1/import, multipart, camp file (app/api/v1/import_router.py).
  • base_url derivat din request.base_url; documenteaza override in spatele proxy (X-Forwarded). Risc minor de base_url gresit in spatele reverse-proxy — mitigat prin nota in pagina.
  • Pattern UI: tab nou = tuplu in dashboard.html + integrare in _TABS_VALIDE + _render_integrare + /_fragments/integrare (identic cu Mapari/Cont/Nomenclator).
  • OpenAPI/Postman: /openapi.json e gratuit din FastAPI; colectia Postman e construita o data din endpoint-urile cunoscute.

6. Riscuri

  • Drift de schema intre snippet-uri si PrezentareIn real → test care leaga snippet-ul de model_fields (US-002).
  • base_url gresit in spatele proxy → nota + derivare din request.
  • Confuzie dev "merge fara cheie" (cont 1) → ping raporteaza autentificat_cu_cheie=false.
  • Scurgere cheie in test-cheie → no-echo enforce + test dedicat (US-004).

7. Intrebari deschise

Rezolvate cu utilizatorul (2026-06-22): test conexiune = GET /v1/ping nou (independent de 5.2); exemple pe ambele canale (prezentari + import); continut doar in-app dinamic (fara markdown versionat); VFP = ambele dialecte (MSXML2 + WinHttp). Niciuna ramasa deschisa.

8. Verificare (rezumat E2E per canal)

  • API: curl GET /v1/ping cu cheie reala pe instanta locala (8010) → 200 cont corect; import postman.json.
  • Web: browser pe /integrare — comuta limbaj, copiaza snippet, vede account_id+endpoint reale, testeaza cheia.
  • Regresia de aur (neatinsa, dar de confirmat ca nu s-a stricat): POST /v1/prezentari (sau import → commit) → worker → FINALIZATA la RAR test.

Criteriu de succes al wedge-ului (CEO-review P3): un service nou (stil VFP) ajunge de la zero la o prezentare FINALIZATA la RAR test folosind DOAR pagina /integrare (copiaza snippet → testeaza cheia → vede are_creds_rar → trimite), fara suport uman si fara sa atinga README/Swagger separat.


Review-uri de plan (§5.3 — rulate 2026-06-22)

  • CEO (valoare/scope) — APROB CU MODIFICARI. Aplicat: ping/test ca readiness-check (are_creds_rar), CTA continuu spre /cont in empty-state, VFP prim-clas + prioritate de descope (§4), criteriu de succes masurabil (§8). (P2 "ping redundant" rezolvat prin diferentierea payload-ului: ping poarta are_creds_rar+mediu, deci e readiness, nu auth-echo.)
  • Eng (fezabilitate/teste) — APROB CU MODIFICARI. Aplicat: montare router prefix="/v1" in main.py fara dublare + test inregistrare unica; drift-test cu is_required() + prestatii obligatoriu (US-002); template dedicat _integrare_test_rezultat.html (US-004, anti fisier-partajat intre valuri); teste Bearer/cheie-goala/cheie-revocata; account_for_key nu resolve_account_id; Postman allowlist exact 3 (nu app.routes); _render_panel_for_tab in fisierele US-003.
  • Design (UI) — APROB CU MODIFICARI, claritate plan UI 6/10 → adresat. Aplicat: IA pe 2 niveluri (limbaj primar, canal secundar, VFP cu sub-dialect); refolosire + generalizare script ARIA tablist (scoped per container); copy din <pre><code> + aria-live + fallback non-HTTPS; empty-state cu CTA /?tab=cont; card "Export & referinta" cu .cardlink; doar tokens de tema (pregatire 5.3); microcopy anti-confuzie + type=password la test-cheie.

Toate cele trei: APROB CU MODIFICARI, modificarile incorporate mai sus. Asteapta poarta umana de aprobare (§5.8) → aprobat.


Raport VERIFY (2026-06-22 — subagent context curat + E2E browser lead)

Rezultat: PASS (dupa o runda de fix pe 4 discrepante minore).

  • Suita: python3 -m pytest -q564 passed, 0 failed (523 baseline + 41 noi: 11 API ping/postman, 8 examples, 10 web integrare initial + 4 lock-uri fix, 8 test-cheie).
  • US-001..US-004 (criterii de acceptare): toate PASS (verificator independent, dovezi in cod + teste + curl live pe :8010 — ping cont 1 autentificat_cu_cheie=false, cheie valida =true, Bearer ok, cheie invalida 401, postman.json 3 items allowlist fara /v1/conturi/rar-creds, openapi 200).
  • Fix dupa VERIFY r1 (4 discrepante PRD-vs-implementare, toate in _integrare.html, lock-uite cu teste noi): cardul Export foloseste .cardlink; linkul Postman are download (fara target=_blank); microcopy anti-confuzie la test-cheie ("Nu o salvam si nu o memoram…"); butonul Copiaza isi schimba label-ul in "Copiat" + revine la 2s.
  • E2E browser (Playwright, lead, dev web_auth_required=false→cont 1): PASS pe /?tab=integrare — randare server-side, IA pe 2 niveluri (limbaj→canal), VFP cu al 3-lea nivel (dialect MSXML2↔WinHttp comuta corect, snippet WinHttp.WinHttpRequest.5.1), endpoint+account_id reale, empty-state CTA /?tab=cont, card Export, microcopy prezent, htmx test-cheie: cheie invalida → fragment eroare in container aria-live ("Cheie invalida sau revocata"). 0 erori in consola (clasa de bug-uri htmx care a muscat 3.6 — absenta aici).
  • Regresia de aur (enqueue): POST /v1/prezentaristatus: queued (live :8010). Backend trimitere NEATINS (doar rute noi de citire + UI; zero modificari worker/masina-stari/idempotenta/schema) — confirmat la diff. Live RAR test (postPrezentare→FINALIZATA) NEPROBAT in sesiune: AUTOPASS_CREDS_KEY/creds RAR test indisponibile in mediu. Risc minim (cod de trimitere neatins).

Toate PASS → CLOSE.

/code-review high (2026-06-22 — CLOSE)

8 unghiuri (3 correctness + cleanup/altitude/conventii), verificare 1-vot. 4 bug-uri reale reparate (toate in suprafata noua, backend trimitere neatins), lock-uite cu teste:

  1. C# snippet — payload JSON multi-linie (json.dumps indent=2) intr-un string literal C# obisnuit → CS1010 (nu compileaza). Fix: _payload_json_compact (separators (",",":"), fara newline) pentru C#.
  2. VFP snippetjson.dumps(indent=0) PRODUCE TOTUSI newline-uri → cPayload = "..." rupt (VFP nu suporta string literal multi-linie) in ambele dialecte. Fix: acelasi helper compact.
  3. Node import snippetawait import("node:buffer") nu exporta FormDatanew FormData() arunca TypeError pe orice Node; plus import mort readFileSync/import("fs") duplicat. Fix: FormData/Blob globale (Node 18+) + readFileSync static folosit direct.
  4. Script _integrare.html ne-scopeddocument.querySelectorAll('[role=tablist]') ataseaza handlere si pe tab-bar-ul PRINCIPAL din dashboard.html, acumuland listeneri la fiecare swap htmx. Fix: scoping pe #integrare-section (root.querySelectorAll(...)), nu mai atinge tab-bar-ul principal.

Notat ca cleanup viitor (NEREPARAT, disciplina backend/altitudine — low value, fara risc): _render_integrare dubleaza SQL-ul are_creds/are_cheie din _get_acasa_context/_render_panel_cont (candidat de helper partajat); ping deschide 2 conexiuni DB + apeleaza account_for_key de 2 ori (derivabil din account_id != DEFAULT_ACCOUNT_ID); _campuri_obligatorii() necache-uit (apelat ~6×/render); cele 6 panouri de limbaj din _integrare.html copy-paste (candidat macro Jinja2); {{ mesaj }} fara | e explicit (salvat acum de autoescape, no-echo confirmat). Pre-existente (in afara 5.1): GET /v1/nomenclator + /_fragments/nomenclator neprotejate (deja notate in ROADMAP "de remediat").

568 teste pass.