8.3 KiB
Gateway RAR AUTOPASS
Gateway web (Python / FastAPI) care preia prezentarile de service-auto si le declara la RAR AUTOPASS (Legea 142/2023, OM 210/2024). Inlocuieste integrarea Visual FoxPro (ROAAUTO).
Doua procese peste acelasi SQLite, care comunica prin tabela submissions:
- API (
app.main:app) — dashboard web, API v1, signup/login, panou admin,/healthz,/metrics. - Worker (
app.worker) — login RAR, trimite prezentarile din coada, retry/backoff, heartbeat.
Trimiterea catre RAR e dezactivata implicit (AUTOPASS_WORKER_SEND_ENABLED=false) — sigur pentru probe.
Sursa de adevar pentru contractul RAR: docs/api-rar-contract.md.
Progres + proces: docs/ROADMAP.md.
Pornire rapida
pip3 install -r requirements.txt # Python 3.12+
uvicorn app.main:app --reload --port 8010 # API (dashboard /, Swagger /docs)
python3 -m app.worker # worker (doar daca vrei sa procesezi coada)
La prima pornire se creeaza schema SQLite si se face seed la nomenclatorul RAR — dashboard-ul si maparile merg imediat, offline. Pentru testarea UI-ului si a importului nu ai nevoie de worker.
Dev rapid fara login: porneste cu AUTOPASS_WEB_AUTH_REQUIRED=false (dashboard pe contul implicit id=1).
Cu start.sh (ambaleaza mediu + rol)
./start.sh test both --send # API + worker, trimite la RAR test (loguri in .run/)
./start.sh test finalizate # listeaza prezentarile inregistrate la RAR (verificare independenta)
./start.sh status # stare procese + /healthz
./start.sh stop # opreste procesele pornite cu "both"
./start-test.sh / ./start-prod.sh # fixeaza mediul (test/prod), forwardeaza rolul
Pagini web
| URL | Ce vezi |
|---|---|
/ |
Dashboard: coada, prezentari blocate, stare worker, import fisier, mapari, nomenclator |
/signup · /login |
Inregistrare cont (emite cheia API o data) · autentificare |
/admin |
Panou admin: conturi pe stari, activare/blocare/arhivare (doar admini) |
/integrare |
Exemple cod (Python/C#/Node/VFP), export Postman/OpenAPI, testeaza conexiunea |
/docs |
Swagger UI — API v1 interactiv |
/healthz · /metrics |
sanatate JSON · metrici text |
Import fisier (xlsx / csv)
Pe dashboard: incarca fisierul → mapeaza coloanele (sugerate automat fuzzy; maparea se retine
pe semnatura coloanelor, per cont) → preview (fiecare rand: ok / needs_mapping / needs_data /
already_sent / ...) → confirma (retastezi numarul de randuri ok). Randurile intra in coada.
Coloane recunoscute (cu sinonime): VIN, Nr inmatriculare, Data prestatie, Odometru final,
Odometru initial, Operatie, Observatii. Fiecare cont poate avea mai multe formate memorate.
API v1 (curl)
Dev: fara cheie → cont id=1. Productie (AUTOPASS_REQUIRE_API_KEY=true): header X-API-Key: rfak_....
curl -s http://localhost:8010/healthz | python3 -m json.tool # sanatate
curl -s http://localhost:8010/v1/nomenclator # coduri RAR (cache local)
curl -s http://localhost:8010/v1/prezentari # coada
# Trimite o prezentare. `rar_credentials` e OPTIONAL: daca lipseste, worker-ul
# foloseste creds-urile RAR salvate pe cont (POST /v1/conturi/rar-creds). Trimite-le
# explicit doar cand vrei sa le suprascrii pe acea cerere.
curl -s -X POST http://localhost:8010/v1/prezentari \
-H 'X-API-Key: rfak_...' -H 'Content-Type: application/json' \
-d '{
"prezentari": [{
"vin": "WAUZZZ8K0AA000001", "nr_inmatriculare": "B123ABC",
"data_prestatie": "2026-06-15", "odometru_final": "120000",
"prestatii": [{"cod_op_service": "REVIZIE PERIODICA", "denumire": "REVIZIE PERIODICA"}]
}]
}'
# Dry-run: valideaza payload + mapare, FARA enqueue, FARA creds
curl -s -X POST http://localhost:8010/v1/prezentari/valideaza \
-H 'X-API-Key: rfak_...' -H 'Content-Type: application/json' -d '{ "prezentari": [ ... ] }'
# Import fisier
curl -s -X POST http://localhost:8010/v1/import -H 'X-API-Key: rfak_...' -F 'file=@import.xlsx'
Toate endpointurile sunt in /docs. Exemple gata facute + Postman/OpenAPI: hub-ul /integrare.
Conturi si chei API
Fiecare service = un cont (accounts) cu lifecycle (pending → active → blocked / archived / deleted).
Worker-ul trimite doar pentru conturi active. Web-ul se autentifica prin sesiune (login email+parola),
API-ul prin cheie API (X-API-Key). Cheia identifica contul, e separata de credentialele RAR.
# Self-onboarding: service-ul deschide /signup → primeste cheia o data. Primul cont = admin.
# Sau din CLI (admin, pe masina gateway-ului):
python3 -m tools.account create --name "Service Auto SRL" --cui RO12345678 --with-key
python3 -m tools.account list [--pending] | activate --account N | set-admin --account N
python3 -m tools.apikey create|list|rotate|revoke --account N # cheie afisata O SINGURA DATA
Creds RAR per cont (ca worker-ul sa trimita fara parola in fiecare cerere) — criptate Fernet at-rest:
curl -s -X POST http://localhost:8010/v1/conturi/rar-creds \
-H 'X-API-Key: rfak_...' -H 'Content-Type: application/json' \
-d '{"email": "service@exemplu.ro", "password": "parola-rar"}'
GET-urile de listare (
/v1/prezentari,/v1/nomenclator,/v1/audit/export) sunt momentan globale si neprotejate — filtrarea pe cont ramane de adaugat.
Proba reala la RAR (mediu test)
- Pune creds de test in
settings.xml(copiaza dinsettings.xml.example, bloc<test>; nu se comite).settings.xmltine un singur cont RAR doar pentru dev/test — creds-urile conturilor reale stau criptate in DB. - Baga prezentari in coada (import sau API).
./start.sh test worker --send— worker-ul trimite si trece fiecare rand insent(cuid_prezentare),needs_datasauerror.- Verifica: dashboard,
curl /v1/prezentari, sau./start.sh test finalizate(listeaza direct de la RAR).
sent+id_prezentare= RAR a acceptat. La raspuns pierdut, worker-ul reconciliaza anti-duplicat (cauta in finalizate, marcheazasentfara re-trimitere).FINALIZATAe terminal la RAR.
Configurare (AUTOPASS_*)
| Variabila | Implicit | Rol |
|---|---|---|
DB_PATH |
./data/autopass.db |
calea SQLite |
RAR_ENV |
test |
test / prod |
REQUIRE_API_KEY |
false |
true = cere cheie pe /v1/* (prod) |
WEB_AUTH_REQUIRED |
true |
false = dashboard fara login, cont id=1 (dev) |
CREDS_KEY |
(efemera) | cheie Fernet creds RAR — trebuie PARTAJATA intre API si worker |
SESSION_SECRET |
(efemer) | secret cookie sesiune; persistent in prod |
WORKER_SEND_ENABLED |
false |
true = trimite efectiv la RAR |
SMTP_HOST (+ _PORT/_USER/_PASSWORD/_FROM) |
(none) | notificare admin la signup (best-effort) |
Genereaza chei: python3 -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"
(CREDS_KEY) si python3 -c "import secrets; print(secrets.token_hex(32))" (SESSION_SECRET).
Teste
python3 -m pytest -q # toata suita
python3 -m pytest tests/test_x.py -q # un fisier
Docker / deploy
cp .env.example .env # CRITIC: completeaza AUTOPASS_CREDS_KEY (partajata api+worker)
docker compose up --build # api (:8010) + worker + autoheal, acelasi image + volum SQLite
Structura
app/
main.py # FastAPI: API v1 + dashboard + auth + admin
api/v1/ # router.py (prezentari, valideaza, nomenclator, mapari, conturi),
# import_router.py, integrare_router.py (ping, postman/openapi)
web/ # routes.py (dashboard + import HTMX), auth_routes.py, admin_routes.py,
# session.py, csrf.py, labels.py, templates/, static/
worker/ # proces separat: login RAR, send, retry, heartbeat
rar_client.py # client HTTP RAR (login/JWT, postPrezentare, nomenclator)
auth.py users.py accounts.py # chei API, parole scrypt + admin, lifecycle conturi
validation.py mapping.py errors.py crypto.py # validare, mapare cod, erori 3-niveluri, Fernet
schema.sql # schema SQLite
tools/ # CLI admin: account, apikey, backup, rar_finalizate, import_dbf
docs/ # contract RAR + ROADMAP + prd/
tests/ legacy-vfp/ # suita pytest · arhiva ROAAUTO (referinta)