Files
rar-autopass/docs/api-rar-contract.md
Claude Agent ff03041cd6 docs: contract RAR actualizat cu T1 verificat live (postPrezentare)
- WAF cere User-Agent pe toate apelurile (altfel 403); fara UA -> blocat
- format eroare validare: data=[{field,message}], 3 mesaje exacte capturate
- raspuns success live: data.id=68514, idPrezentare==id, idAgent server-side
- sistemReparat="null" acceptat, b64Image/odometruInitial omise OK
- odometruFinal string -> intors numar; camp extra listaPrestatii
- Open Q #5 (mesaje eroare) + WAF inchise

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

14 KiB

Contract RAR AUTOPASS — sursa de adevăr (verificat live)

Acesta este documentul autoritativ pentru contractul API RAR AUTOPASS. Înlocuiește presupunerile din docs/plans/* acolo unde diferă. Dacă un plan contrazice acest fișier, acest fișier are dreptate.

Surse:

  • docs/api-rar-documentatie-oficiala.md — răspuns oficial de la programatorii RAR.
  • Verificare live pe endpoint-ul de test (/public/login + getNomenclatorPrestatii), 2026-06-15.
  • Cod VFP testat (rar_autopass.prg) — confirmat ca URL-uri corecte.

Endpoint-uri

Mediu Bază
TEST (integrare — doar aici se testează) https://apps.rarom.ro/test-rar-autopass
PRODUCȚIE https://apps.rarom.ro/rar-autopass
Swagger test https://apps.rarom.ro/test-rar-autopass/swagger-ui/index.html

⚠️ …/v3/api-docs, …/v2/api-docs, …/swagger-resources întorc 403 (nu se pot descărca programatic). Swagger-ul nu permite autentificare directă — testarea reală se face din cod / Postman cu credențialele de test.

Rute confirmate

Operație Metodă + cale Stare
Login POST /public/login verificat live
Nomenclator prestații GET /nomenclator/getNomenclatorPrestatii verificat live (200)
Adăugare prezentare POST /prezentari/postPrezentare din VFP testat + doc oficial

Nota: doc-ul oficial citează operationId-ul Swagger getPrestatiiNomUsingGET, dar calea reală e /nomenclator/getNomenclatorPrestatii (cea din VFP). /nomenclator/getPrestatiiNom întoarce 403 — nu o folosi. operationId ≠ path.

⚠️ Header obligatoriu pe TOATE apelurile: User-Agent

WAF-ul RAR întoarce 403 Forbidden („Request forbidden by administrative rules") la orice request fără header User-Agent de browser — inclusiv /public/login și chiar swagger-ui. curl/clienți fără UA = blocați la WAF înainte de a ajunge la aplicație. MSXML2.XMLHTTP din VFP trimite un UA implicit, de aceea VFP-ul merge.

→ Gateway-ul (app/rar_client.py) trebuie să seteze User-Agent pe fiecare apel (ex. Mozilla/5.0). Confirmat live 2026-06-15: fără UA → 403; cu UA + creds greșite → 401; cu UA + creds corecte → 200.

Autentificare

POST /public/login body {"email": "...", "password": "..."} → 200, JSON cu câmpuri:

idUser, idAgent, cui, nume, prenume, email, token, activationToken,
activ, dataActivarii, dataSfarsit, blocat, expirat, tokenExists, authorities
  • Tokenul JWT se atașează la apelurile securizate: Authorization: Bearer {token}.
  • JWT claims (decodate live): { jti: "mobileJWT", sub: <email>, authorities: ["ADMIN"], iat, exp }.
  • ⚠️ JWT TTL = 108000 secunde = 30 de ORE (exp - iat). NU e un token scurt. Vezi „Corecții față de planuri" #1 — schimbă strategia de robustețe a worker-ului.
  • idUser vine din răspunsul de login (ex. live: 6766); idAgent poate fi null la login, dar serverul atribuie idAgent pe prezentare (vezi exemplul de răspuns oficial: idAgent: 1587).

postPrezentare — payload (request)

Câmpurile marcate OPTIONAL pot lipsi; restul sunt obligatorii. tipPrestatie NU se trimite (îl generează serverul).

{
  "vin": "XXXXXXXXXXXXXXXXX",
  "nrInmatriculare": "B999GEN",
  "dataPrestatie": "2024-07-25",
  "odometruFinal": "9999999",
  "odometruInitial": null,
  "prestatii": [
    { "codPrestatie": "OE-1", "idPrezentare": null },
    { "codPrestatie": "OE-2", "idPrezentare": null }
  ],
  "sistemReparat": "null",
  "status": "FINALIZATA",
  "obs": "TEST",
  "b64Image": "UklGR...."
}
Câmp Obligatoriu Note
vin DA 17 caractere, MAJUSCULE, fără spații/caractere speciale, fără literele O, I, Q
nrInmatriculare DA max 10 caractere, litere + cifre, MAJUSCULE, fără spații/caractere speciale
dataPrestatie DA format YYYY-MM-DD; nu mai devreme de 2024-12-01, nu mai târziu de azi
odometruFinal DA indicația km la final (exemplul oficial îl trimite ca string "9999999")
odometruInitial condiționat null normal; OBLIGATORIU dacă prestatii conține R-ODO sau I-ODO (indicația dinainte de reparație/schimbare)
prestatii DA listă {codPrestatie, idPrezentare:null}; codurile din nomenclator
status DA întotdeauna "FINALIZATA" prin API
sistemReparat DA (poate fi "null") exemplul oficial trimite string-ul "null"; valori reale nedocumentate (vezi Open Q)
obs NU (OPTIONAL) text liber
b64Image NU (OPTIONAL) poza odometrului; nu mai e obligatorie; dacă se atașează, trebuie format base64 valid

postPrezentare — răspuns (success) — VERIFICAT LIVE 2026-06-15

Răspuns real pe contul nostru de test (record creat data.id=68514):

{
  "statusCode": 200,
  "message": "Prezentare adaugata cu succes",
  "data": {
    "id": 68514,
    "dataPrestatie": "2026-06-15",
    "vin": "WVWZZZ1KZAW000123",
    "odometruFinal": 123456,
    "idAgent": 40,
    "tipPrestatie": "GENERIC",
    "odometruInitial": null,
    "idUser": 6766,
    "sistemReparat": "null",
    "obs": "TEST GATEWAY",
    "nrInmatriculare": "B999TST",
    "listaPrestatii": null,
    "status": "FINALIZATA",
    "prestatii": [
      { "idPrezentare": 68514, "codPrestatie": "OE-1" },
      { "idPrezentare": 68514, "codPrestatie": "OE-2" }
    ],
    "b64Image": null
  }
}
  • data.id = ID-ul prezentării la RAR (de reținut ca idPrezentare în submission).
  • prestatii[].idPrezentare == data.id (live: ambele 68514). Exemplul vechi sugera un număr separat mai mare (599950 vs 59950) — fals, e același id.
  • idAgent = atribuit de server (login a întors null, răspunsul are 40).
  • odometruFinal trimis ca string "123456"întors ca număr 123456 (server normalizează).
  • sistemReparat:"null" acceptat; b64Image omis → null; odometruInitial:null OK.
  • Câmp extra nedocumentat în răspuns: listaPrestatii: null (prezent lângă prestatii).
  • tipPrestatie = "GENERIC"generat de server, nu input client.

postPrezentare — răspuns (eroare validare) — VERIFICAT LIVE 2026-06-15

HTTP 400. data este un ARRAY de {field, message} (NU string), un element per eroare:

{
  "statusCode": 400,
  "message": "Validare eșuată pentru cererea de prezentare.",
  "data": [
    { "field": "vin", "message": "VIN trebuie să aibă exact 17 caractere, fara spatii sau caractere speciale, litere invalide :  O, I, Q." },
    { "field": "vin", "message": "VIN conține caractere invalide, spatii, sau  O, I, Q." }
  ]
}

Mesaje exacte capturate live (de mapat în UI/loguri gateway):

Constrângere încălcată field message (exact)
VIN cu O/I/Q vin VIN trebuie să aibă exact 17 caractere, fara spatii sau caractere speciale, litere invalide : O, I, Q. + VIN conține caractere invalide, spatii, sau O, I, Q.
dataPrestatie < 2024-12-01 dataPrestatie Data prestatiei nu poate fi anterioara datei de 01.12.2024.
dataPrestatie în viitor dataPrestatie Data prestatiei nu poate fi în viitor.

→ Gateway: parsează data ca listă de erori de câmp (nu citi data.message). Pe success data e obiect; pe 400 data e array — discriminează după statusCode/HTTP code.

Reguli de validare (server-side RAR, de aplicat și în gateway)

Aplicate deja pe ambele medii (test + producție):

  1. dataPrestatie: >= 2024-12-01 și <= azi.
  2. VIN: exact 17 caractere, majuscule, fără spații/caractere speciale, fără O, I, Q.
  3. nrInmatriculare: max 10 caractere, litere + cifre, majuscule, fără spații/caractere speciale.
  4. b64Image: dacă e prezent, trebuie base64 valid.
  5. odometruInitial: obligatoriu dacă prestatii conține R-ODO sau I-ODO.

→ Acestea devin reguli Pydantic exacte în app/api. Validează la gateway înainte de enqueue (stare needs_data) ca să nu primești 4xx de la RAR.

Nomenclator prestații (18 coduri, verificat live 2026-06-15)

cod nume
OE-1 REPARAȚIE
OE-2 INTRETINERE
OE-3 REVIZIE PERIODICA
OE-4 REGLARE FUNCTIONALA
OE-5 MODIFICARE CONSTRUCTIVA
OE-6 RECONSTRUCTIE
OE-7 ACTUALIZARE SOFTWARE
OE-8 INLOCUIRE SEZONIERA A ANVELOPELOR
OE-D AVARII GRAVE LA SISTEMUL DE DIRECTIE
OE-F AVARII GRAVE LA SISTEMUL DE FRANARE
OE-C AVARII GRAVE LA STRUCTURA DE REZISTENTA A CAROSERIEI
OE-S AVARII GRAVE LA STRUCTURA DE REZISTENTA A SASIULUI
OE-R AVARII GRAVE LA UN SISTEM DE RETINERE SI PROTECTIE IN CAZ DE ACCIDENT
OE-A AVARII GRAVE LA UN SISTEM AVANSAT DE ASISTENTA A CONDUCATORULUI AUTO (ADAS)
OE-I ISTORICUL INDICATIEI ODOMETRULUI (vehicule anterior inmatriculate in alte tari)
AITLV INREGISTRARE ATELIER INSPECTIE TAHOGRAFE / LIMITATOARE DE VITEZA
R-ODO REPARATIE ODOMETRU → declanșează odometruInitial obligatoriu
I-ODO INLOCUIRE ODOMETRU → declanșează odometruInitial obligatoriu

numePrestatie redat prescurtat pentru OE-D…OE-A (în API e textul lung complet). Nomenclatorul se ia live din API; nu hard-coda — folosește acest tabel doar ca referință.

Ciclu de viață prezentare (la RAR) — IMPORTANT

  • API-ul are un singur scop: INSERT prezentări cu status FINALIZATA. Toate celelalte operațiuni CRUD se fac din interfața web.
  • Prezentările FINALIZATA NU se pot anula prin API (nici din web). Doar cele SALVATA sunt anulabile/editabile, dar API nu produce SALVATA.
    • Încercarea de anulare a unei FINALIZATA întoarce: EROARE_STATUS_ANULARE("... Id not found.").
  • Corecția datelor eronate (după FINALIZATA) = solicitare la suport.autopass@rarom.ro (pe test nu e cazul). Nu există flux API de corecție/anulare pentru records-urile noastre.

Monitorizare (citire prezentări)

  • Pe mediul de test: la interogarea listei de prezentări finalizate NU primești și prestatii în răspuns.
  • Pe producție: prestațiile sunt disponibile; lista poate fi filtrată după keyword / interval de date și exportată în Excel.
  • Implicație dashboard: nu te baza pe prestatii din listă pe test; le ai în submissions local.

Corecții față de docs/plans/* (citește înainte de a refolosi planurile)

  1. JWT „scurt" → de fapt 30 de ORE. Planurile (plan-design-review §„Gestiunea credențialelor", plan-eng-review §worker) presupun JWT scurt și mută durabilitatea pe re-push din ROAAUTO („coada acoperă minutele, ROAAUTO acoperă orele"). Fals. Cu 30h, worker-ul singur poate relua peste orice pană RAR realistă în fereastra tokenului. Re-push-ul din ROAAUTO devine plasă de siguranță secundară, nu mecanismul principal. Re-evaluează: poate nu mai e nevoie de re-push în treapta 1, sau credențialele se pot reține în memorie pe durata penei.
  2. b64Image (poza odometrului) NU mai e obligatorie. Planurile o tratau ca posibil gap de conformitate / posibil obligatorie. Rezolvat: opțională. → Open Question „sursa pozei în ROAAUTO" se închide (nu mai e blocantă). Dacă e atașată, doar trebuie base64 valid.
  3. tipPrestatie NU e input client — îl generează serverul ("GENERIC"). Open Question #2 (valori acceptate tipPrestatie) se închide pentru request — nu-l trimite.
  4. sistemReparat: planul presupunea că e derivabil server-side din coduri și nu input liber. Parțial fals — apare în request (exemplul oficial trimite string-ul "null"). Rămâne open ce valori reale acceptă; sigur: poți trimite "null" când nu se aplică.
  5. Anulare / corecție prin API: NU există pentru records-urile noastre (sunt FINALIZATA). Scoate din scope endpoint-urile gateway PATCH /v1/prezentari/{id}/anulare și /corectie (proxy peste markPrezentareAnulataById / patchPrezentare) — nu se aplică FINALIZATA. Maparea stărilor + „Error & rescue map" din plan-eng-review trebuie ajustate.
  6. Regula needs_data e acum deterministă: odometruInitial lipsă doar când prestatii conține R-ODO sau I-ODO. (Planul vorbea generic de „repair odometru".)
  7. URL nomenclator confirmat = /nomenclator/getNomenclatorPrestatii (nu varianta din operationId Swagger). Constatarea #5 din plan-eng-review (URL-uri din VFP, nu din spec) — confirmată.

Open questions rămase (actualizat)

  1. Sursa pozei odometruluiînchis (poză opțională).
  2. sistemReparat — ce valori reale acceptă (în afară de "null"). De probat la postPrezentare test.
  3. Un singur user RAR per agent economic sau mai mulți (idUser/idAgent — afectează filtrarea monitorizării).
  4. JWT TTLînchis: 30h. Decizie nouă: simplifică worker-ul; reconsideră necesitatea re-push ROAAUTO.
  5. Comportamentul răspunsului de eroareînchis (format data:[{field,message}], mesaje capturate mai sus).
  6. WAF cere User-Agentînchis/confirmat (vezi secțiunea de sus).

Rămas de verificat live (postPrezentare real pe test) FĂCUT 2026-06-15

Login + nomenclator + JWT TTL + postPrezentare = toate verificate live. Record de test creat: data.id = 68514 (FINALIZATA, permanent pe test). Confirmat:

  • mesajele de eroare exacte (VIN O/I/Q, dată prea veche, dată viitoare) — vezi tabelul de erori;
  • forma răspunsului success pe contul nostru + data.id;
  • sistemReparat:"null" acceptat, b64Image/odometruInitial omise OK;
  • header User-Agent obligatoriu (altfel 403 WAF).

Rămas neprobat: ce alte valori sistemReparat (în afară de "null") acceptă (Open Q #2).