{"openapi":"3.1.0","info":{"title":"Gateway RAR AUTOPASS","version":"0.1.0"},"paths":{"/v1/prezentari":{"post":{"tags":["v1"],"summary":"Create Prezentari","description":"Enqueue una/mai multe prezentari. Idempotent: continut identic -> acelasi submission.\n\nValidarea de continut (app.validation) ruleaza inainte de enqueue: esecurile NU\nresping cererea, ci enqueue-aza cu status `needs_data` + motiv. JSON malformat ->\n422 din Pydantic (validare de shape).\naccount_id vine din cheia API (resolve_account_id): cont real cu cheie,\nimplicit id=1 in dev fara cheie, 401 fara cheie valida in prod.\nCand rar_credentials lipseste, submission-ul intra fara creds efemere: worker-ul\ncade pe creds-urile durabile ale contului (per-env: `accounts.rar_creds_{env}_enc`).","operationId":"create_prezentari_v1_prezentari_post","parameters":[{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PrezentareRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PrezentariResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["v1"],"summary":"List Prezentari","operationId":"list_prezentari_v1_prezentari_get","parameters":[{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Status"}},{"name":"data_de","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Data De"}},{"name":"data_pana","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Data Pana"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":100,"title":"Limit"}},{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","title":"Response List Prezentari V1 Prezentari Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/prezentari/valideaza":{"post":{"tags":["v1"],"summary":"Valideaza Prezentari","description":"Dry-run: valideaza payload exact ca POST /prezentari, fara enqueue si fara efecte secundare.\n\nIntoarce pentru fiecare prezentare: verdictul (status_estimat), erorile de\ncontinut si codurile nemapate — exact ce ar obtine trimiterea reala pe acelasi\npayload + aceeasi mapare de cont. rar_credentials ignorat complet.","operationId":"valideaza_prezentari_v1_prezentari_valideaza_post","parameters":[{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidarePrezentariRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidareResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/prezentari/{submission_id}":{"get":{"tags":["v1"],"summary":"Get Prezentare","operationId":"get_prezentare_v1_prezentari__submission_id__get","parameters":[{"name":"submission_id","in":"path","required":true,"schema":{"type":"integer","title":"Submission Id"}},{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","title":"Response Get Prezentare V1 Prezentari  Submission Id  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["v1"],"summary":"Delete Prezentare","description":"Sterge o trimitere blocata a contului cheii API.\n\nRaspuns 200 + body JSON (NU 204 — clienti VFP fac string-parse). Scope evaluat\nINAINTEA starii: cross-account / inexistent -> 404 (acelasi mesaj);\nown-account `sent`/`sending` -> 409 (conflict de stare).","operationId":"delete_prezentare_v1_prezentari__submission_id__delete","parameters":[{"name":"submission_id","in":"path","required":true,"schema":{"type":"integer","title":"Submission Id"}},{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","title":"Response Delete Prezentare V1 Prezentari  Submission Id  Delete"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/prezentari/{submission_id}/repune":{"post":{"tags":["v1"],"summary":"Repune Prezentare","description":"Re-pune in coada o trimitere blocata a contului cheii API.\n\n`error -> queued`, re-ruleaza classify. Acelasi oracol de scope/stare ca DELETE\n(404 cross-account/inexistent, 409 sent/sending).","operationId":"repune_prezentare_v1_prezentari__submission_id__repune_post","parameters":[{"name":"submission_id","in":"path","required":true,"schema":{"type":"integer","title":"Submission Id"}},{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","title":"Response Repune Prezentare V1 Prezentari  Submission Id  Repune Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/prezentari/{submission_id}/trimite-acum":{"post":{"tags":["v1"],"summary":"Trimite Acum Prezentare","description":"Elibereaza manual un rand tinut (paritate API cu /repune).\n\nScoped strict pe contul cheii API (account_id din sesiune/cheie, NICIODATA din body).\n404-before-leak pe id strain/inexistent. `held: 1 -> 0` DOAR daca randul e\n`queued AND held=1` (no-op sigur altfel: un rand deja `sending`/`sent` ramane neatins).\nWorker-ul preia randul la urmatorul poll (trimitere asincrona).","operationId":"trimite_acum_prezentare_v1_prezentari__submission_id__trimite_acum_post","parameters":[{"name":"submission_id","in":"path","required":true,"schema":{"type":"integer","title":"Submission Id"}},{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","title":"Response Trimite Acum Prezentare V1 Prezentari  Submission Id  Trimite Acum Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/nomenclator":{"get":{"tags":["v1"],"summary":"Get Nomenclator","operationId":"get_nomenclator_v1_nomenclator_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","title":"Response Get Nomenclator V1 Nomenclator Get"}}}}}}},"/v1/audit/export":{"get":{"tags":["v1"],"summary":"Audit Export","description":"CSV audit scoped pe contul cheii API. Filtre optionale `date_from`/`date_to` (YYYY-MM-DD)\n\npe data(updated_at). `status` implicit `sent` (ce a ajuns efectiv la RAR);\n`status=all` exporta toata coada contului. Leaga retinerea 90 zile prin coloana\n`purge_after`. b64_image nu se exporta.","operationId":"audit_export_v1_audit_export_get","parameters":[{"name":"date_from","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Date From"}},{"name":"date_to","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Date To"}},{"name":"status","in":"query","required":false,"schema":{"type":"string","default":"sent","title":"Status"}},{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/mapari":{"get":{"tags":["v1"],"summary":"Get Mapari","description":"Maparile operatie->cod ale contului curent.\n\nParametrul `account_id` din query e pastrat pentru compatibilitate, dar contul\nefectiv vine MEREU din cheia API. Daca e prezent si difera -> 400.","operationId":"get_mapari_v1_mapari_get","parameters":[{"name":"account_id","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Account Id"}},{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","title":"Response Get Mapari V1 Mapari Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["v1"],"summary":"Create Mapare","description":"Salveaza/actualizeaza o mapare op->cod si re-rezolva submission-urile blocate.\n\nContul vine din cheia API (NU din body) — un cont nu poate edita maparile\naltuia. Verifica intai ca `cod_prestatie` exista in nomenclator (nu lasam\nmapari catre coduri inexistente). Apoi upsert + re-rezolvare `needs_mapping`.","operationId":"create_mapare_v1_mapari_post","parameters":[{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MapareIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","title":"Response Create Mapare V1 Mapari Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/mapari/pending":{"get":{"tags":["v1"],"summary":"Get Mapari Pending","description":"Operatii ROAAUTO nemapate (din submission-uri needs_mapping) + sugestii fuzzy.\n\nFiltrate pe contul cheii API. Fiecare intrare: {account_id, cod_op_service,\ndenumire, blocked, suggestions:[{cod_prestatie, nume_prestatie, score}]}.","operationId":"get_mapari_pending_v1_mapari_pending_get","parameters":[{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","title":"Response Get Mapari Pending V1 Mapari Pending Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/conturi/rar-creds":{"post":{"tags":["v1"],"summary":"Set Rar Creds","description":"Seteaza creds RAR durabile per-cont, in slotul per-mediu (env-aware).\n\nSlotul tinta: `req.rar_target` ('test'/'prod') sau ancora globala (AUTOPASS_RAR_ENV).\nActiveaza mediul selectat (`rar_{env}_enabled=1`). Worker-ul le foloseste ca\nfallback cand submission-ul nu mai are creds efemere. Contul vine din cheia API.","operationId":"set_rar_creds_v1_conturi_rar_creds_post","parameters":[{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RarCredsIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","title":"Response Set Rar Creds V1 Conturi Rar Creds Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["v1"],"summary":"Delete Rar Creds","description":"Sterge creds RAR durabile per-cont (revenire la modelul efemer per submission).\n\n`env` (query param): 'test' | 'prod' -> sterge DOAR slotul acelui mediu + dezactiveaza-l.\nAbsent -> sterge AMBELE sloturi (revenire completa). Schimbare aditiva (back-compat).","operationId":"delete_rar_creds_v1_conturi_rar_creds_delete","parameters":[{"name":"env","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Env"}},{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","title":"Response Delete Rar Creds V1 Conturi Rar Creds Delete"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/import":{"post":{"tags":["import"],"summary":"Upload Import","description":"Upload fisier xlsx/csv -> staging in import_batches/import_rows.\n\nNu trimite nimic la RAR. Intoarce {import_id, columns, sample_rows, sheets?}.\nPII (raw_json) criptat Fernet la rest. Scrieri bulk in tranzactie explicita.","operationId":"upload_import_v1_import_post","parameters":[{"name":"sheet_name","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sheet Name"}},{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_upload_import_v1_import_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","title":"Response Upload Import V1 Import Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/import/{import_id}/column-mapping":{"get":{"tags":["import"],"summary":"Get Column Mapping","description":"Intoarce maparea de coloane existenta sau sugestii fuzzy.","operationId":"get_column_mapping_v1_import__import_id__column_mapping_get","parameters":[{"name":"import_id","in":"path","required":true,"schema":{"type":"integer","title":"Import Id"}},{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","title":"Response Get Column Mapping V1 Import  Import Id  Column Mapping Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["import"],"summary":"Save Column Mapping","description":"Salveaza/actualizeaza maparea de coloane pentru contul curent.\n\nSemnatura = hash al coloanelor fisierului. Drift: daca coloanele se schimba,\nmaparea veche nu se aplica (signature mismatch -> mapping_status='new').","operationId":"save_column_mapping_v1_import__import_id__column_mapping_post","parameters":[{"name":"import_id","in":"path","required":true,"schema":{"type":"integer","title":"Import Id"}},{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ColumnMappingIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","title":"Response Save Column Mapping V1 Import  Import Id  Column Mapping Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/import/{import_id}/preview":{"get":{"tags":["import"],"summary":"Preview Import","description":"Preview 6 stari per rand: ok/needs_mapping/needs_data/needs_review/already_sent/duplicate_in_file.\n\nNu enqueue-aza nimic. Already_sent = lookup batch. Duplicate_in_file = intra-batch\ncollision (EXCLUSIV aici, NU in reconcile.py/worker).","operationId":"preview_import_v1_import__import_id__preview_get","parameters":[{"name":"import_id","in":"path","required":true,"schema":{"type":"integer","title":"Import Id"}},{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","title":"Response Preview Import V1 Import  Import Id  Preview Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/import/{import_id}/commit":{"post":{"tags":["import"],"summary":"Commit Import","description":"Gate HARD confirmare + enqueue randuri ok + log atestare.\n\nTOCTOU: INSERT per-rand cu ON CONFLICT(idempotency_key) DO NOTHING.\nRanduri colidante = reclasificate already_sent in rezultatul commit-ului.\nrows_hash + n_confirmed acopera DOAR randurile efectiv puse in coada.","operationId":"commit_import_v1_import__import_id__commit_post","parameters":[{"name":"import_id","in":"path","required":true,"schema":{"type":"integer","title":"Import Id"}},{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CommitIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","title":"Response Commit Import V1 Import  Import Id  Commit Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/import/{import_id}/rand/{row_index}/editeaza":{"post":{"tags":["import"],"summary":"Editeaza Rand","description":"Persista editarea unui rand de preview (mutatie pura).\n\nNU recalculeaza statusul si NU atinge `submissions`; preview-ul rederiva statusul\nprin `_resolve_row_for_preview` cu override aplicat ultimul.","operationId":"editeaza_rand_v1_import__import_id__rand__row_index__editeaza_post","parameters":[{"name":"import_id","in":"path","required":true,"schema":{"type":"integer","title":"Import Id"}},{"name":"row_index","in":"path","required":true,"schema":{"type":"integer","title":"Row Index"}},{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RandEditIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","title":"Response Editeaza Rand V1 Import  Import Id  Rand  Row Index  Editeaza Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/import/{import_id}/export-failed":{"get":{"tags":["import"],"summary":"Export Failed Rows","description":"CSV cu randurile esuate (needs_data/needs_mapping/needs_review) pentru corectie + re-upload.","operationId":"export_failed_rows_v1_import__import_id__export_failed_get","parameters":[{"name":"import_id","in":"path","required":true,"schema":{"type":"integer","title":"Import Id"}},{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/ping":{"get":{"tags":["integrare"],"summary":"Ping","description":"Readiness check per cont.\n\nIntoarce:\n  account_id         — contul rezolvat din cheie (sau 1 in dev fara cheie)\n  mediu              — mediul RAR efectiv al contului (\"test\"/\"prod\"),\n                      nu ancora globala settings.rar_env\n  autentificat_cu_cheie — True daca cererea a venit cu o cheie API reala valida\n  are_creds_rar      — True daca contul are creds RAR stocate pe cel putin un mediu (test sau prod)\n  are_creds_test     — True daca contul are creds RAR pentru mediul Testare\n  are_creds_prod     — True daca contul are creds RAR pentru mediul Productie\n  ts                 — timestamp ISO UTC al cererii","operationId":"ping_v1_ping_get","parameters":[{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/integrare/postman.json":{"get":{"tags":["integrare"],"summary":"Postman Export","description":"Export colectie Postman v2.1.0 cu cele 3 rute de integrare.\n\nAllowlist hardcodat — NU deriva din app.routes pentru a nu expune\nrute interne (ex. /v1/conturi/rar-creds, rutele web etc.).","operationId":"postman_export_v1_integrare_postman_json_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/":{"get":{"tags":["web"],"summary":"Dashboard","description":"Dashboard principal cu tab-uri.\n\nParametrul ?tab= permite deep-link pe orice sectiune; panoul activ e randat\nserver-side la full load (fara palpaiere la refresh, degradare gratiosa fara JS).\nTab invalid -> fallback la 'acasa'. `?status=` pre-filtreaza lista Trimiteri de\npe Acasa (deep-link din banner-ul \"Necesita atentia ta\").\n\nVizitator neautentificat -> landing-ul comercial (in loc de redirect la /login),\ncu formularele de inregistrare/autentificare care posteaza la /signup si /login.","operationId":"dashboard__get","parameters":[{"name":"tab","in":"query","required":false,"schema":{"type":"string","default":"acasa","title":"Tab"}},{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Status"}},{"name":"subtab","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Subtab"}}],"responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/confidentialitate":{"get":{"tags":["web"],"summary":"Pagina Statica","operationId":"pagina_statica_confidentialitate_get","responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}}}}},"/termeni":{"get":{"tags":["web"],"summary":"Pagina Statica","operationId":"pagina_statica_termeni_get","responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}}}}},"/documentatie-api":{"get":{"tags":["web"],"summary":"Pagina Documentatie Api","description":"Documentatie API publica (varianta scurta a tab-ului Integrare, fara login).","operationId":"pagina_documentatie_api_documentatie_api_get","responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}}}}},"/_fragments/acasa":{"get":{"tags":["web"],"summary":"Fragment Acasa","description":"Fragment HTMX pentru tab-ul Acasa.","operationId":"fragment_acasa__fragments_acasa_get","responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}}}}},"/_fragments/import":{"get":{"tags":["web"],"summary":"Fragment Import","description":"Fragment HTMX pentru tab-ul Import — include zona de upload.","operationId":"fragment_import__fragments_import_get","responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}}}}},"/_fragments/coada":{"get":{"tags":["web"],"summary":"Fragment Coada","description":"\"coada\" nu mai are fragment propriu. Serveste continutul Acasa (Trimiterile sunt\nsectiune permanenta pe Acasa) — evita un fragment `_coada.html` orfan din\nbookmark-uri/HTMX vechi. Nu da 404.","operationId":"fragment_coada__fragments_coada_get","responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}}}}},"/_fragments/nomenclator":{"get":{"tags":["web"],"summary":"Fragment Nomenclator","description":"Browser nomenclator RAR (cache local upsert-at de worker la fiecare login).\n\nNecesita autentificare: este un fragment al dashboard-ului intern, nu un\nendpoint public. Fara sesiune -> redirect /login (via require_login).","operationId":"fragment_nomenclator__fragments_nomenclator_get","responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}}}}},"/_fragments/integrare":{"get":{"tags":["web"],"summary":"Fragment Integrare","description":"Fragment HTMX pentru tab-ul Integrare (hub documentatie + exemple cod).","operationId":"fragment_integrare__fragments_integrare_get","responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}}}}},"/_fragments/jurnal":{"get":{"tags":["web"],"summary":"Fragment Jurnal","description":"Tab Jurnal: evenimente app_events paginate + filtre, scoped pe cont.\n\nAdmin vede tot (filtru optional pe cont); non-admin doar evenimentele proprii.","operationId":"fragment_jurnal__fragments_jurnal_get","parameters":[{"name":"tip","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Tip"}},{"name":"nivel","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Nivel"}},{"name":"data_de","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Data De"}},{"name":"data_pana","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Data Pana"}},{"name":"cont","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cont"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer","default":0,"title":"Page"}}],"responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/_fragments/banner":{"get":{"tags":["web"],"summary":"Fragment Banner","operationId":"fragment_banner__fragments_banner_get","responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}}}}},"/_fragments/status":{"get":{"tags":["web"],"summary":"Fragment Status","description":"Bara de status persistenta cu etichete umane.\n\nScoped pe contul sesiunii. Expune starea worker, legatura RAR, ultima\nautentificare, contorii de coada si defalcarea blocatelor pe motiv.\nLogica in routes.py (nu in template) pentru testabilitate.","operationId":"fragment_status__fragments_status_get","responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}}}}},"/_fragments/trimiteri-versiune":{"get":{"tags":["web"],"summary":"Fragment Trimiteri Versiune","description":"Semnatura curenta a trimiterilor contului (JSON usor). Pollerul \"Date noi\" o\ncompara cu versiunea cu care s-a randat tabelul; daca difera, arata nudge-ul de\nreincarcare — tabelul nu se mai schimba singur.","operationId":"fragment_trimiteri_versiune__fragments_trimiteri_versiune_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/_fragments/submissions":{"get":{"tags":["web"],"summary":"Fragment Submissions","description":"Tabel Trimiteri, scoped pe cont, cu filtre optionale si paginare.\n\nTotalul se calculeaza DIFERIT dupa tipul de filtru:\n- FARA filtru Python (status-only / niciun filtru): SQL COUNT(*) + LIMIT/OFFSET\n- CU filtru vehicul/data activ: fetch-all -> filtreaza Python -> total=len -> slice\nSQL COUNT/LIMIT pe calea cu filtru Python ar da total gresit (taie inainte de filtru).","operationId":"fragment_submissions__fragments_submissions_get","parameters":[{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Status"}},{"name":"vehicul","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Vehicul"}},{"name":"data_de","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Data De"}},{"name":"data_pana","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Data Pana"}},{"name":"held","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Held"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer","default":1,"title":"Page"}}],"responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/_fragments/trimitere/{submission_id}":{"get":{"tags":["web"],"summary":"Fragment Trimitere Detaliu","description":"Detaliu complet al unei trimiteri, in panou dedicat (#trimitere-detaliu).\n\nScoped pe contul sesiunii: 404 daca randul nu exista SAU apartine altui cont\n(acelasi mesaj, nu confirmam existenta).","operationId":"fragment_trimitere_detaliu__fragments_trimitere__submission_id__get","parameters":[{"name":"submission_id","in":"path","required":true,"schema":{"type":"integer","title":"Submission Id"}}],"responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/trimitere/{submission_id}/mapeaza":{"post":{"tags":["web"],"summary":"Post Mapeaza Inline","description":"Mapare inline din panoul de detaliu: alege cod RAR pentru o operatie nemapata.\n\nReutilizeaza EXACT save_mapping + reresolve_account (ca tab-ul Mapari) — fara logica\nnoua de clasificare. Re-rezolva scoped pe batch-ul randului (canal API batch_id IS NULL\nSAU import batch), deblocand si randurile-frate cu aceeasi operatie. Scoped pe sesiune\n(404 cross-account/inexistent), CSRF obligatoriu, gard pe status needs_mapping.","operationId":"post_mapeaza_inline_trimitere__submission_id__mapeaza_post","parameters":[{"name":"submission_id","in":"path","required":true,"schema":{"type":"integer","title":"Submission Id"}}],"responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/trimitere/{submission_id}/corecteaza":{"post":{"tags":["web"],"summary":"Post Corectie Trimitere","description":"Corectie inline pentru randuri ne-trimise blocate (needs_data/needs_mapping).\n\nRe-valideaza (validation.py, fara reguli noi), reconstruieste payload_json,\nrecalculeaza idempotency_key (canonicalize -> build_key, ca la enqueue) si\nre-pune randul in 'queued' (re-enqueue). NU atinge worker-ul / masina de stari.\nRandurile sent/sending/queued/error raman read-only (gard explicit -> 403).\nColiziune de idempotency detectata INAINTE de UPDATE (fara 500/duplicat).","operationId":"post_corectie_trimitere_trimitere__submission_id__corecteaza_post","parameters":[{"name":"submission_id","in":"path","required":true,"schema":{"type":"integer","title":"Submission Id"}}],"responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/trimitere/{submission_id}/repune":{"post":{"tags":["web"],"summary":"Post Repune Trimitere","description":"Re-pune in coada un rand blocat (error/needs_data/needs_mapping) din dashboard.\n\nDaca randul e in starea `error` si formularul contine `cod_prestatie`, actualizeaza\ncodul in payload, recalculeaza cheia de idempotency si re-pune in coada direct (fara\n`requeue_submission`, care nu actualizeaza cheia). Scoped pe sesiune (404\ncross-account/inexistent, 409 sent/sending). Re-randeaza panoul de detaliu cu starea\nnoua + nudge `trimiteriChanged` pentru lista.","operationId":"post_repune_trimitere_trimitere__submission_id__repune_post","parameters":[{"name":"submission_id","in":"path","required":true,"schema":{"type":"integer","title":"Submission Id"}}],"responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/trimitere/{submission_id}/sterge":{"post":{"tags":["web"],"summary":"Post Sterge Trimitere","description":"Sterge un rand blocat din dashboard. Scoped pe sesiune; sent/sending interzis (409).","operationId":"post_sterge_trimitere_trimitere__submission_id__sterge_post","parameters":[{"name":"submission_id","in":"path","required":true,"schema":{"type":"integer","title":"Submission Id"}}],"responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/trimiteri/sterge-bulk":{"post":{"tags":["web"],"summary":"Post Sterge Bulk","description":"Sterge in bloc trimiterile selectate (doar blocate, scoped pe sesiune).\n\nSare peste randuri sent/sending (read-only) si cross-account (inexistente) fara a\nopri operatia — pe modelul panoului admin. Re-randeaza lista Trimiteri.","operationId":"post_sterge_bulk_trimiteri_sterge_bulk_post","responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}}}}},"/auto-send":{"post":{"tags":["web"],"summary":"Post Auto Send","description":"Comuta comutatorul \"Trimite automat la RAR\", persistat pe cont.\n\n`account_id` din SESIUNE (NICIODATA din formular). Non-optimist: raspunde cu toggle-ul\nre-randat din starea reala din DB (OOB outerHTML pe #auto-send-toggle-wrap).\n\nGarda de confirmare OFF->ON: daca exista N>0 randuri `queued AND held=1`, NU\ncomita ON pana la o confirmare tipata (modal) — intoarce toggle-ul pe starea veche +\nmodalul de confirmare (OOB in #modal-confirma-slot). Cu `confirma=1`: comita ON si\nelibereaza randurile tinute printr-un SINGUR UPDATE atomic, scoped strict pe cont.\nON->OFF nu retrage randuri deja eliberate.","operationId":"post_auto_send_auto_send_post","responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}}}}},"/trimitere/{submission_id}/trimite-acum":{"post":{"tags":["web"],"summary":"Post Trimite Acum","description":"Trimitere manuala per rand: elibereaza un rand tinut (held 1->0).\n\nScoped pe sesiune (404-before-leak pe id strain via `_fetch_submission_scoped`).\nUPDATE include `AND status='queued' AND held=1` -> no-op sigur daca randul a fost deja\nluat de worker (`sending`) sau eliberat intre afisaj si click (edge race). Worker-ul\npreia randul la urmatorul poll (trimitere asincrona).","operationId":"post_trimite_acum_trimitere__submission_id__trimite_acum_post","parameters":[{"name":"submission_id","in":"path","required":true,"schema":{"type":"integer","title":"Submission Id"}}],"responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/trimite-toate":{"post":{"tags":["web"],"summary":"Post Trimite Toate","description":"Trimitere manuala in bloc: elibereaza TOATE randurile tinute ale contului din\nsesiune (queued AND held=1 -> held=0) printr-un SINGUR UPDATE atomic scoped.\n\nNU poate elibera randurile altui cont (scope strict pe sesiune). Worker-ul preia\nrandurile la urmatorul poll.","operationId":"post_trimite_toate_trimite_toate_post","responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}}}}},"/trimiteri/bulk-fix":{"post":{"tags":["web"],"summary":"Post Bulk Fix","description":"Aplica un cod RAR la TOATE randurile blocate selectate.\n\nReuse form #bulk-trimiteri (checkbox-uri pe gestionabil). Fiecare rand e\nre-validat + idempotenta recalculata individual — un rand invalid nu pica lotul.\nSumar 'N reusite, M esuate'. Scoped pe cont (cross-account = silentios sarite).\nRandurile sent/sending/queued sarite silentios (gard gestionabil, ca sterge-bulk).","operationId":"post_bulk_fix_trimiteri_bulk_fix_post","responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}}}}},"/form-chips":{"post":{"tags":["web"],"summary":"Post Form Chips","description":"Re-randeaza sectiunea chips prestatii (HTMX server-driven).\n\nStare unica: hidden `chips_state` (JSON versionat, vezi _chips_state_from_form).\nDOUA actiuni: add (leaga codul de operatia tinta prin chips_target_index, sau\nadauga cod liber fara tinta; sentinelul __NEDECLARAT__ + tinta marcheaza\nexclus=1 pe item) si remove (chips_remove_index, index unic — acopera si fostul\nremove_flat). Fara scriere in DB (stateless mid-edit). Auth: sesiune activa;\nCSRF verificat.","operationId":"post_form_chips_form_chips_post","responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}}}}},"/trimitere/{submission_id}/salveaza-regula-chip":{"post":{"tags":["web"],"summary":"Post Salveaza Regula Din Chip","description":"Salveaza regula op->cod din chip.\n\nReuse EXACT save_mapping + reresolve_account (acelasi mecanism ca maparea inline).\nScoped pe sesiune (404 cross-account/inexistent), CSRF obligatoriu.\nRe-rezolva deblocand si submission-urile frate cu aceeasi operatie (pe batch_id).\nauto_send implicit False (conservator — userul poate activa din tab-ul Mapari).","operationId":"post_salveaza_regula_din_chip_trimitere__submission_id__salveaza_regula_chip_post","parameters":[{"name":"submission_id","in":"path","required":true,"schema":{"type":"integer","title":"Submission Id"}}],"responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/_fragments/mapari":{"get":{"tags":["web"],"summary":"Fragment Mapari","description":"Editor mapari: operatii ROAAUTO nemapate + sugestii fuzzy pe nomenclator RAR.\n\nScoped pe contul sesiunii: pending_unmapped primeste account_id explicit.","operationId":"fragment_mapari__fragments_mapari_get","responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}}}}},"/mapari":{"post":{"tags":["web"],"summary":"Post Mapare","description":"Salveaza maparea aleasa de user, re-rezolva submission-urile blocate, re-randeaza editorul.\n\nL14-S6: parametrul optional `denumire` permite inregistrarea in GOLD partajat\n(shared_mappings) cu cheia corecta (denumire normalizata, nu cod_op_service).\nFormularul din _mapari.html include un input hidden `denumire` per operatie.","operationId":"post_mapare_mapari_post","requestBody":{"content":{"application/x-www-form-urlencoded":{"schema":{"$ref":"#/components/schemas/Body_post_mapare_mapari_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/mapari/salvate":{"post":{"tags":["web"],"summary":"Post Editeaza Mapare Salvata","description":"Editeaza o mapare op->cod salvata (cod RAR / auto-send) + re-rezolva blocatele.\n\nScoped pe contul sesiunii (save_mapping foloseste account_or_default(sesiune) —\ncross-account imposibil). Respinge cod inexistent in nomenclator.\n\nL14-S6: `denumire` optional actualizeaza si GOLD partajat (shared_mappings).","operationId":"post_editeaza_mapare_salvata_mapari_salvate_post","requestBody":{"content":{"application/x-www-form-urlencoded":{"schema":{"$ref":"#/components/schemas/Body_post_editeaza_mapare_salvata_mapari_salvate_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/mapari/salvate/sterge":{"post":{"tags":["web"],"summary":"Post Sterge Mapare Salvata","description":"Sterge o mapare op->cod salvata. Scoped pe contul sesiunii.","operationId":"post_sterge_mapare_salvata_mapari_salvate_sterge_post","requestBody":{"content":{"application/x-www-form-urlencoded":{"schema":{"$ref":"#/components/schemas/Body_post_sterge_mapare_salvata_mapari_salvate_sterge_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/mapari/reguli-text":{"post":{"tags":["web"],"summary":"Post Salveaza Regula Text","description":"Salveaza o regula text (substring -> cod RAR) + re-rezolva submission-urile blocate.\n\nScoped pe contul sesiunii (save_text_rule foloseste account_or_default(sesiune)).\nValideaza cod_prestatie fata de nomenclator INAINTE de save (cod necunoscut ->\nrespins inline, fara salvare). La succes: mesaj „Regula salvata. Deblocate: N\"\n+ trigger trimiteriChanged (refresh lista), ca maparea inline.","operationId":"post_salveaza_regula_text_mapari_reguli_text_post","requestBody":{"content":{"application/x-www-form-urlencoded":{"schema":{"$ref":"#/components/schemas/Body_post_salveaza_regula_text_mapari_reguli_text_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/mapari/reguli-text/sterge":{"post":{"tags":["web"],"summary":"Post Sterge Regula Text","description":"Sterge o regula text. Scoped pe contul sesiunii.","operationId":"post_sterge_regula_text_mapari_reguli_text_sterge_post","requestBody":{"content":{"application/x-www-form-urlencoded":{"schema":{"$ref":"#/components/schemas/Body_post_sterge_regula_text_mapari_reguli_text_sterge_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/mapari/reguli-text/preview":{"post":{"tags":["web"],"summary":"Post Preview Regula Text","description":"Preview pre-salvare: cate operatii nemapate ar potrivi regula + cod propus.\n\nNU salveaza nimic (zero scriere DB). Normalizeaza pattern-ul cu\nnormalize_for_match, numara operatiile DISTINCTE nemapate ale contului\n(needs_mapping, reuse pending_unmapped) al caror text (denumire sau\ncod_op_service, normalizat) CONTINE pattern-ul + intoarce pana la 3 exemple.\nAdauga propunerea automata de cod (GOLD partajat > SILVER > embeddings, via\nenrich_suggestions) cu buton care preselecteaza codul in dropdown — fara salvare.\nPattern gol -> fragment gol (nu numara „tot\"). Scoped pe contul sesiunii.","operationId":"post_preview_regula_text_mapari_reguli_text_preview_post","requestBody":{"content":{"application/x-www-form-urlencoded":{"schema":{"allOf":[{"$ref":"#/components/schemas/Body_post_preview_regula_text_mapari_reguli_text_preview_post"}],"title":"Body"}}}},"responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/formate-coloane/editeaza":{"post":{"tags":["web"],"summary":"Post Editeaza Format Coloane","description":"Editeaza un format de coloane salvat (format data). Scoped pe cont prin id+account_id.\n\njson_mapare optional (string JSON valid) — daca e dat, inlocuieste maparea coloanelor.","operationId":"post_editeaza_format_coloane_formate_coloane_editeaza_post","requestBody":{"content":{"application/x-www-form-urlencoded":{"schema":{"$ref":"#/components/schemas/Body_post_editeaza_format_coloane_formate_coloane_editeaza_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/formate-coloane/sterge":{"post":{"tags":["web"],"summary":"Post Sterge Format Coloane","description":"Sterge un format de coloane salvat. Scoped pe cont prin id+account_id.","operationId":"post_sterge_format_coloane_formate_coloane_sterge_post","requestBody":{"content":{"application/x-www-form-urlencoded":{"schema":{"$ref":"#/components/schemas/Body_post_sterge_format_coloane_formate_coloane_sterge_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/_import/upload":{"post":{"tags":["web"],"summary":"Web Upload Import","description":"Upload fisier xlsx/csv → staging; intoarce fragment HTML.\n\nDaca maparea de coloane exista deja (signature match): computa preview imediat.\nDaca nu: intoarce formularul de mapare coloane.\nNu editeaza import_router.py — apeleaza parse_file si DB direct.","operationId":"web_upload_import__import_upload_post","requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_web_upload_import__import_upload_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/_import/{import_id}/mapare-coloane":{"post":{"tags":["web"],"summary":"Web Save Mapare Coloane","description":"Salveaza maparea de coloane si computa preview. Intoarce fragment HTML.","operationId":"web_save_mapare_coloane__import__import_id__mapare_coloane_post","parameters":[{"name":"import_id","in":"path","required":true,"schema":{"type":"integer","title":"Import Id"}}],"responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/_import/{import_id}/preview":{"get":{"tags":["web"],"summary":"Web Preview Import","description":"Preview 6 stari per rand. Tinta HTMX dupa mapare retinuta sau navigare directa.","operationId":"web_preview_import__import__import_id__preview_get","parameters":[{"name":"import_id","in":"path","required":true,"schema":{"type":"integer","title":"Import Id"}},{"name":"rar_env","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Rar Env"}}],"responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/_import/{import_id}/rand/{row_index}/editare-modal":{"get":{"tags":["web"],"summary":"Web Rand Editare Modal","description":"Fragment editare rand preview in modalul global (#detaliu-modal-body).\n\nInlocuieste editarea inline (tr.preview-edit) care cauza colapsare vizuala si\neroare JS la Anuleaza. Randeaza _editare_preview_modal.html. Campurile\nvehicul/data/odometru sunt preluate din starea curenta (resolved + override).","operationId":"web_rand_editare_modal__import__import_id__rand__row_index__editare_modal_get","parameters":[{"name":"import_id","in":"path","required":true,"schema":{"type":"integer","title":"Import Id"}},{"name":"row_index","in":"path","required":true,"schema":{"type":"integer","title":"Row Index"}}],"responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/_import/{import_id}/rand/{row_index}/editare":{"get":{"tags":["web"],"summary":"Web Rand Editare","description":"Fragment editare rand preview in modal — alias al /editare-modal.\n\nEditarea inline eliminata; ruta pastrata pentru compatibilitate cu apeluri\nexterne / teste existente. Delega la web_rand_editare_modal.","operationId":"web_rand_editare__import__import_id__rand__row_index__editare_get","parameters":[{"name":"import_id","in":"path","required":true,"schema":{"type":"integer","title":"Import Id"}},{"name":"row_index","in":"path","required":true,"schema":{"type":"integer","title":"Row Index"}}],"responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/_import/{import_id}/rand/{row_index}":{"get":{"tags":["web"],"summary":"Web Rand Display","description":"Iese din mod editare (Anuleaza) — re-randeaza randul read-only + OOB contoare.","operationId":"web_rand_display__import__import_id__rand__row_index__get","parameters":[{"name":"import_id","in":"path","required":true,"schema":{"type":"integer","title":"Import Id"}},{"name":"row_index","in":"path","required":true,"schema":{"type":"integer","title":"Row Index"}}],"responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/_import/{import_id}/rand/{row_index}/editeaza":{"post":{"tags":["web"],"summary":"Web Editeaza Rand","description":"Persista override (mutatie pura) + raspunde cu OOB rand+contoare sau erori in modal.\n\n- Succes: raspuns cu OOB pe rand (#preview-row-N) + OOB contoare (#preview-rezumat) +\n  header HX-Trigger-After-Settle:inchideModal (modalul se inchide, OOB se aplica).\n- Eroare camp: re-randeaza _editare_preview_modal.html cu valorile introduse + erorile\n  per-camp; modalul RAMANE DESCHIS; NU se emite inchideModal.\n\nINVARIANT CRITIC: submissions NEATINS — override-only pe import_rows.override_json,\nNU re-queue, NU insereaza in submissions.","operationId":"web_editeaza_rand__import__import_id__rand__row_index__editeaza_post","parameters":[{"name":"import_id","in":"path","required":true,"schema":{"type":"integer","title":"Import Id"}},{"name":"row_index","in":"path","required":true,"schema":{"type":"integer","title":"Row Index"}}],"responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/_import/{import_id}/rand/{row_index}/confirma-review":{"post":{"tags":["web"],"summary":"Web Confirma Review","description":"Confirma explicit valorile unui rand needs_review → seteaza reviewed=1 in DB.\n\nButonul 'Confirma valorile' din modal seteaza reviewed=1 pentru randul indicat.\nLa recalcul (_web_compute_preview), randul cu reviewed=1 si fara erori de\nvalidare reale devine ok (nu mai e blocat de flaguri ambigue).\n\nGuard: 404 cross-account (scoping JOIN), 409 batch committed.\nRaspunde OOB (rand + contoare) + HX-Trigger-After-Settle:inchideModal,\nidentic cu web_editeaza_rand la succes.","operationId":"web_confirma_review__import__import_id__rand__row_index__confirma_review_post","parameters":[{"name":"import_id","in":"path","required":true,"schema":{"type":"integer","title":"Import Id"}},{"name":"row_index","in":"path","required":true,"schema":{"type":"integer","title":"Row Index"}}],"responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/_import/{import_id}/confirma-toate-review":{"post":{"tags":["web"],"summary":"Web Confirma Toate Review","description":"Confirma in bloc TOATE randurile needs_review din batch → reviewed=1 (B1).\n\nUn singur click marcheaza reviewed=1 pe toate randurile cu resolved_status='needs_review'\ndin batch-ul curent (om in bucla: operatorul confirma explicit intreg lotul, fara\nauto-accept). Refoloseste EXACT logica din /confirma-review (reviewed=1 = marcaj separat,\nNU camp de continut), aplicata in masa. La recalcul (_web_compute_preview) randurile cu\nreviewed=1 si fara erori reale devin ok.\n\nCSRF + scoped sesiune (404 cross-account) + guard committed (409). O singura recompute\n+ re-randare #import-section la final (identic cu web_mapare_operatii).","operationId":"web_confirma_toate_review__import__import_id__confirma_toate_review_post","parameters":[{"name":"import_id","in":"path","required":true,"schema":{"type":"integer","title":"Import Id"}}],"responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/_import/{import_id}/mapare-operatie":{"post":{"tags":["web"],"summary":"Web Mapare Operatie","description":"Mapeaza o operatie nemapata din preview-ul de import la un cod RAR, in flux.\n\nSalveaza maparea (persistenta, operations_mapping) si re-randeaza preview-ul:\n_web_compute_preview recalculeaza cu noua mapare si re-scrie resolved_status in\nimport_rows, deci randurile afectate trec din needs_mapping in ok fara re-upload.","operationId":"web_mapare_operatie__import__import_id__mapare_operatie_post","parameters":[{"name":"import_id","in":"path","required":true,"schema":{"type":"integer","title":"Import Id"}}],"responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/_import/{import_id}/mapare-operatii":{"post":{"tags":["web"],"summary":"Web Mapare Operatii","description":"Un singur POST salveaza toate maparile de operatii.\n\nPrimeste perechi (cod_op_service, cod_prestatie) ca liste paralele din un singur\n<form> cu un select per operatie. Apeleaza save_mapping pentru fiecare pereche cu\ncod ales (reuse EXACT, fara logica noua). Perechile cu cod_prestatie gol sunt ignorate.\nPer-item — cod invalid -> skip + sumar, restul salvate. O singura recompute\n_web_compute_preview + re-randare #import-section la final.\nCSRF + scoped sesiune (404 cross-account via _web_compute_preview) + guard committed 409.","operationId":"web_mapare_operatii__import__import_id__mapare_operatii_post","parameters":[{"name":"import_id","in":"path","required":true,"schema":{"type":"integer","title":"Import Id"}}],"responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/_import/reset":{"get":{"tags":["web"],"summary":"Web Import Reset","description":"Reseteaza sectiunea de import la starea initiala (drop zone gol).","operationId":"web_import_reset__import_reset_get","responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}}}}},"/_import/{import_id}/confirma":{"post":{"tags":["web"],"summary":"Web Confirma Import","description":"Gate HARD confirmare + enqueue randuri ok + log atestare. Intoarce fragment HTML.\n\nReplica logica din import_router.commit_import dar cu input din form HTML\nsi raspuns HTML (nu JSON). INSERT per-rand ON CONFLICT DO NOTHING (TOCTOU).\naccount_id din sesiune propagat consecvent la build_key si toate lookup-urile.\nrequire_login — pe scrieri NICIODATA fallback cont 1 in prod.","operationId":"web_confirma_import__import__import_id__confirma_post","parameters":[{"name":"import_id","in":"path","required":true,"schema":{"type":"integer","title":"Import Id"}}],"responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/_fragments/cont":{"get":{"tags":["web"],"summary":"Fragment Cont","description":"Fragment HTMX card 'Contul meu': stare cheie + creds RAR + date firma.","operationId":"fragment_cont__fragments_cont_get","responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}}}}},"/cont/roteste-cheie":{"post":{"tags":["web"],"summary":"Cont Roteste Cheie","description":"Revoca toate cheile active si emite una noua. Afisata O SINGURA DATA.","operationId":"cont_roteste_cheie_cont_roteste_cheie_post","requestBody":{"content":{"application/x-www-form-urlencoded":{"schema":{"allOf":[{"$ref":"#/components/schemas/Body_cont_roteste_cheie_cont_roteste_cheie_post"}],"title":"Body"}}}},"responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/cont/date-firma":{"post":{"tags":["web"],"summary":"Cont Date Firma","description":"Actualizeaza datele firmei (companie, email, CUI) pentru contul din sesiune.\n\nValideaza campurile (reuse _norm_cui / _norm_email din accounts.py), verifica\nunicitatea CUI-ului, actualizeaza accounts.name/email/cui. CSRF enforce.\nScoped pe contul sesiunii (nu poate atinge alt cont).","operationId":"cont_date_firma_cont_date_firma_post","responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}}}}},"/integrare/test-cheie":{"post":{"tags":["web"],"summary":"Integrare Test Cheie","description":"Verifica cheia API lipita de utilizator — scoped pe contul sesiunii.\n\nPermite utilizatorului sa confirme ca o cheie copiata din generatorul de exemple\ncorespunde contului sau, fara efecte secundare (fara creare/rotire). Cheie goala,\ninvalida sau a altui cont -> mesaj de eroare neutru (fara eco al cheii in raspuns).","operationId":"integrare_test_cheie_integrare_test_cheie_post","requestBody":{"content":{"application/x-www-form-urlencoded":{"schema":{"allOf":[{"$ref":"#/components/schemas/Body_integrare_test_cheie_integrare_test_cheie_post"}],"title":"Body"}}}},"responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/cont/test-rar-creds":{"post":{"tags":["web"],"summary":"Cont Test Rar Creds","description":"Testeaza credentialele RAR prin login real pe mediul specificat.\n\nFara efecte secundare: nu salveaza nimic, nu creeaza submission. Pur validare.\nCamp parola NICIODATA re-pus in raspuns.\n\nDecizie env:\n- param `rar_env` explicit ('test'/'prod') -> folosit direct\n- altfel -> rar_env_efectiv_cont (default-ul contului) sau ancora globala settings.rar_env\n- signup nu colecteaza creds RAR, deci nu apeleaza aceasta functie","operationId":"cont_test_rar_creds_cont_test_rar_creds_post","requestBody":{"content":{"application/x-www-form-urlencoded":{"schema":{"allOf":[{"$ref":"#/components/schemas/Body_cont_test_rar_creds_cont_test_rar_creds_post"}],"title":"Body"}}}},"responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/cont/rar-medii":{"post":{"tags":["web"],"summary":"Cont Rar Medii","description":"Salveaza configuratia mediilor RAR per cont.\n\nDoua sectiuni independente (Testare / Productie): fiecare cu bifa de activare\nsi campuri email/parola. La salvare, pentru fiecare mediu activat cu creds noi:\n  - valideaza prin login pe acel env — RAR test si prod sunt sisteme separate;\n  - OK -> cripteaza cu Fernet si scrie in rar_creds_{env}_enc + enabled=1;\n  - esec login -> eroare per-env, mediul NU devine disponibil (creds nesalvate).\n\nActivarea Productie pentru prima oara necesita checkbox-ul de confirmare\n(constientizare L.142 — trimiterile sunt declaratii oficiale, finale si fara anulare).\n\nMediul implicit (rar_env_default) poate fi setat DOAR pe un mediu disponibil\n(validat server-side post-update; altfel eroare, valoarea veche ramane).\n\nParolele NICIODATA reflectate inapoi in pagina (camp gol cu placeholder).","operationId":"cont_rar_medii_cont_rar_medii_post","responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}}}}},"/cont/schimba-parola":{"post":{"tags":["web"],"summary":"Cont Schimba Parola","description":"Schimba parola de acces (login dashboard) a userului din sesiune (sub-tab Cont).\n\nVerifica parola actuala (scrypt), valideaza parola noua + confirmarea, rescrie\nhash-ul. Parola NICIODATA re-pusa in raspuns. CSRF enforce. Scoped pe user_id din\nsesiune (nu poate atinge alt user). Sesiunea ramane valida dupa schimbare.","operationId":"cont_schimba_parola_cont_schimba_parola_post","responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}}}}},"/_fragments/status/toggle-env":{"post":{"tags":["web"],"summary":"Fragment Status Toggle Env","description":"Comuta rar_env_default intre mediile disponibile ale contului.\n\nValideaza ca noul mediu e in lista mediilor disponibile inainte de UPDATE.\nIntoarce badge-ul din header actualizat (tinta hx-target) + status bar-ul\nca OOB swap, ca ambele sa ramana consecvente dupa comutare.\nIgnorat silentios daca contul are un singur mediu sau zero medii disponibile.","operationId":"fragment_status_toggle_env__fragments_status_toggle_env_post","responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}}}}},"/signup":{"get":{"summary":"Signup Get","operationId":"signup_get_signup_get","responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}}}},"post":{"summary":"Signup Post","operationId":"signup_post_signup_post","requestBody":{"content":{"application/x-www-form-urlencoded":{"schema":{"allOf":[{"$ref":"#/components/schemas/Body_signup_post_signup_post"}],"title":"Body"}}}},"responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/login":{"get":{"summary":"Login Get","operationId":"login_get_login_get","responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}}}},"post":{"summary":"Login Post","operationId":"login_post_login_post","requestBody":{"content":{"application/x-www-form-urlencoded":{"schema":{"allOf":[{"$ref":"#/components/schemas/Body_login_post_login_post"}],"title":"Body"}}}},"responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/logout":{"post":{"summary":"Logout Post","operationId":"logout_post_logout_post","requestBody":{"content":{"application/x-www-form-urlencoded":{"schema":{"allOf":[{"$ref":"#/components/schemas/Body_logout_post_logout_post"}],"title":"Body"}}}},"responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin":{"get":{"summary":"Admin Get","description":"Panou admin: conturi in asteptare + active.","operationId":"admin_get_admin_get","responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}}}}},"/admin/activate":{"post":{"summary":"Admin Activate","description":"Activeaza unul sau mai multe conturi (bulk). PRG 303.","operationId":"admin_activate_admin_activate_post","requestBody":{"content":{"application/x-www-form-urlencoded":{"schema":{"$ref":"#/components/schemas/Body_admin_activate_admin_activate_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/block":{"post":{"summary":"Admin Block","description":"Blocheaza (suspendare reversibila) unul sau mai multe conturi. PRG 303.","operationId":"admin_block_admin_block_post","requestBody":{"content":{"application/x-www-form-urlencoded":{"schema":{"$ref":"#/components/schemas/Body_admin_block_admin_block_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/archive":{"post":{"summary":"Admin Archive","description":"Arhiveaza (scos din listele active, date read-only) unul sau mai multe conturi. PRG 303.","operationId":"admin_archive_admin_archive_post","requestBody":{"content":{"application/x-www-form-urlencoded":{"schema":{"$ref":"#/components/schemas/Body_admin_archive_admin_archive_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/delete":{"post":{"summary":"Admin Delete","description":"Stergere SOFT (tombstone + purjare PII imediata) a unuia sau mai multor conturi. PRG 303.","operationId":"admin_delete_admin_delete_post","requestBody":{"content":{"application/x-www-form-urlencoded":{"schema":{"$ref":"#/components/schemas/Body_admin_delete_admin_delete_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/set-tier":{"post":{"summary":"Admin Set Tier","description":"Schimba planul (tier) unui cont din panou. require_admin + CSRF, PRG 303.\n\nReuseaza accounts.set_tier (valideaza tier-ul, protejeaza id=1, logheaza schimbarea).\nINCHEIE trial-ul (trial_until=NULL): alocarea manuala = plan real de-acum, cu efect\nimediat — altfel trial-ul Pro universal (30z la signup) ar masca alegerea pana la\nexpirare (decizie user 2026-06-29). Tier invalid / cont protejat -> re-randare cu eroare.","operationId":"admin_set_tier_admin_set_tier_post","requestBody":{"content":{"application/x-www-form-urlencoded":{"schema":{"$ref":"#/components/schemas/Body_admin_set_tier_admin_set_tier_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/set-trial":{"post":{"summary":"Admin Set Trial","description":"Acorda/prelungeste un trial Pro de N zile (de la acum), fara a schimba tier-ul de baza.\n\nrequire_admin + CSRF, PRG 303. Reuseaza accounts.set_trial (protejeaza id=1, logheaza).\ntrial_days <= 0 sau peste plafon -> re-randare panou cu eroare (422). Plafon defensiv 3650z.","operationId":"admin_set_trial_admin_set_trial_post","requestBody":{"content":{"application/x-www-form-urlencoded":{"schema":{"$ref":"#/components/schemas/Body_admin_set_trial_admin_set_trial_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/deactivate":{"post":{"summary":"Admin Deactivate","description":"Dezactiveaza un cont. Nu permite dezactivarea contului default id=1. PRG: redirect 303.","operationId":"admin_deactivate_admin_deactivate_post","requestBody":{"content":{"application/x-www-form-urlencoded":{"schema":{"$ref":"#/components/schemas/Body_admin_deactivate_admin_deactivate_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/healthz":{"get":{"summary":"Healthz","description":"Sanatate: worker viu + ultimul login RAR reusit + adancime coada.\n\nIntoarce 200 mereu cu detalii; orchestratorul decide restartul pe campul\n`worker_alive`.","operationId":"healthz_healthz_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","title":"Response Healthz Healthz Get"}}}}}}},"/metrics":{"get":{"summary":"Metrics","description":"Metrici text simplu (submissions pe status + backlog). Format Prometheus-lite.","operationId":"metrics_metrics_get","responses":{"200":{"description":"Successful Response","content":{"text/plain":{"schema":{"type":"string"}}}}}}}},"components":{"schemas":{"Body_admin_activate_admin_activate_post":{"properties":{"account_id":{"items":{"type":"integer"},"type":"array","title":"Account Id"},"csrf_token":{"type":"string","title":"Csrf Token","default":""}},"type":"object","required":["account_id"],"title":"Body_admin_activate_admin_activate_post"},"Body_admin_archive_admin_archive_post":{"properties":{"account_id":{"items":{"type":"integer"},"type":"array","title":"Account Id"},"csrf_token":{"type":"string","title":"Csrf Token","default":""}},"type":"object","required":["account_id"],"title":"Body_admin_archive_admin_archive_post"},"Body_admin_block_admin_block_post":{"properties":{"account_id":{"items":{"type":"integer"},"type":"array","title":"Account Id"},"csrf_token":{"type":"string","title":"Csrf Token","default":""}},"type":"object","required":["account_id"],"title":"Body_admin_block_admin_block_post"},"Body_admin_deactivate_admin_deactivate_post":{"properties":{"account_id":{"type":"integer","title":"Account Id"},"csrf_token":{"type":"string","title":"Csrf Token","default":""}},"type":"object","required":["account_id"],"title":"Body_admin_deactivate_admin_deactivate_post"},"Body_admin_delete_admin_delete_post":{"properties":{"account_id":{"items":{"type":"integer"},"type":"array","title":"Account Id"},"csrf_token":{"type":"string","title":"Csrf Token","default":""}},"type":"object","required":["account_id"],"title":"Body_admin_delete_admin_delete_post"},"Body_admin_set_tier_admin_set_tier_post":{"properties":{"account_id":{"type":"integer","title":"Account Id"},"tier":{"type":"string","title":"Tier"},"csrf_token":{"type":"string","title":"Csrf Token","default":""}},"type":"object","required":["account_id","tier"],"title":"Body_admin_set_tier_admin_set_tier_post"},"Body_admin_set_trial_admin_set_trial_post":{"properties":{"account_id":{"type":"integer","title":"Account Id"},"trial_days":{"type":"integer","title":"Trial Days"},"csrf_token":{"type":"string","title":"Csrf Token","default":""}},"type":"object","required":["account_id","trial_days"],"title":"Body_admin_set_trial_admin_set_trial_post"},"Body_cont_roteste_cheie_cont_roteste_cheie_post":{"properties":{"csrf_token":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Csrf Token"}},"type":"object","title":"Body_cont_roteste_cheie_cont_roteste_cheie_post"},"Body_cont_test_rar_creds_cont_test_rar_creds_post":{"properties":{"rar_email":{"type":"string","title":"Rar Email","default":""},"rar_parola":{"type":"string","title":"Rar Parola","default":""},"rar_env":{"type":"string","title":"Rar Env","default":""},"csrf_token":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Csrf Token"}},"type":"object","title":"Body_cont_test_rar_creds_cont_test_rar_creds_post"},"Body_integrare_test_cheie_integrare_test_cheie_post":{"properties":{"api_key":{"type":"string","title":"Api Key","default":""},"csrf_token":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Csrf Token"}},"type":"object","title":"Body_integrare_test_cheie_integrare_test_cheie_post"},"Body_login_post_login_post":{"properties":{"email":{"type":"string","title":"Email","default":""},"parola":{"type":"string","title":"Parola","default":""},"csrf_token":{"type":"string","title":"Csrf Token","default":""}},"type":"object","title":"Body_login_post_login_post"},"Body_logout_post_logout_post":{"properties":{"csrf_token":{"type":"string","title":"Csrf Token","default":""}},"type":"object","title":"Body_logout_post_logout_post"},"Body_post_editeaza_format_coloane_formate_coloane_editeaza_post":{"properties":{"format_id":{"type":"integer","title":"Format Id"},"format_data":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Format Data"},"csrf_token":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Csrf Token"}},"type":"object","required":["format_id"],"title":"Body_post_editeaza_format_coloane_formate_coloane_editeaza_post"},"Body_post_editeaza_mapare_salvata_mapari_salvate_post":{"properties":{"cod_op_service":{"type":"string","title":"Cod Op Service"},"cod_prestatie":{"type":"string","title":"Cod Prestatie"},"csrf_token":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Csrf Token"},"auto_send":{"type":"boolean","title":"Auto Send","default":false},"denumire":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Denumire"}},"type":"object","required":["cod_op_service","cod_prestatie"],"title":"Body_post_editeaza_mapare_salvata_mapari_salvate_post"},"Body_post_mapare_mapari_post":{"properties":{"cod_op_service":{"type":"string","title":"Cod Op Service"},"cod_prestatie":{"type":"string","title":"Cod Prestatie"},"csrf_token":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Csrf Token"},"auto_send":{"type":"boolean","title":"Auto Send","default":false},"denumire":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Denumire"}},"type":"object","required":["cod_op_service","cod_prestatie"],"title":"Body_post_mapare_mapari_post"},"Body_post_preview_regula_text_mapari_reguli_text_preview_post":{"properties":{"pattern":{"type":"string","title":"Pattern","default":""},"csrf_token":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Csrf Token"}},"type":"object","title":"Body_post_preview_regula_text_mapari_reguli_text_preview_post"},"Body_post_salveaza_regula_text_mapari_reguli_text_post":{"properties":{"pattern":{"type":"string","title":"Pattern"},"cod_prestatie":{"type":"string","title":"Cod Prestatie"},"csrf_token":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Csrf Token"},"auto_send":{"type":"boolean","title":"Auto Send","default":false}},"type":"object","required":["pattern","cod_prestatie"],"title":"Body_post_salveaza_regula_text_mapari_reguli_text_post"},"Body_post_sterge_format_coloane_formate_coloane_sterge_post":{"properties":{"format_id":{"type":"integer","title":"Format Id"},"csrf_token":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Csrf Token"}},"type":"object","required":["format_id"],"title":"Body_post_sterge_format_coloane_formate_coloane_sterge_post"},"Body_post_sterge_mapare_salvata_mapari_salvate_sterge_post":{"properties":{"cod_op_service":{"type":"string","title":"Cod Op Service"},"csrf_token":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Csrf Token"}},"type":"object","required":["cod_op_service"],"title":"Body_post_sterge_mapare_salvata_mapari_salvate_sterge_post"},"Body_post_sterge_regula_text_mapari_reguli_text_sterge_post":{"properties":{"pattern":{"type":"string","title":"Pattern"},"csrf_token":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Csrf Token"}},"type":"object","required":["pattern"],"title":"Body_post_sterge_regula_text_mapari_reguli_text_sterge_post"},"Body_signup_post_signup_post":{"properties":{"name":{"type":"string","title":"Name","default":""},"cui":{"type":"string","title":"Cui","default":""},"email":{"type":"string","title":"Email","default":""},"parola":{"type":"string","title":"Parola","default":""},"plan":{"type":"string","title":"Plan","default":""},"consent":{"type":"string","title":"Consent","default":""},"csrf_token":{"type":"string","title":"Csrf Token","default":""}},"type":"object","title":"Body_signup_post_signup_post"},"Body_upload_import_v1_import_post":{"properties":{"file":{"type":"string","format":"binary","title":"File"}},"type":"object","required":["file"],"title":"Body_upload_import_v1_import_post"},"Body_web_upload_import__import_upload_post":{"properties":{"file":{"type":"string","format":"binary","title":"File"},"sheet_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sheet Name"},"csrf_token":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Csrf Token"},"rar_env":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Rar Env"}},"type":"object","required":["file"],"title":"Body_web_upload_import__import_upload_post"},"ColumnMappingIn":{"properties":{"json_mapare":{"additionalProperties":{"type":"string"},"type":"object","title":"Json Mapare","description":"Mapare {col_fisier: camp_canonic}"},"format_data":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Format Data","description":"Format data, ex: DD.MM.YYYY"}},"type":"object","required":["json_mapare"],"title":"ColumnMappingIn"},"CommitIn":{"properties":{"n_confirmat":{"type":"integer","title":"N Confirmat","description":"Numarul de randuri ok confirmate (gate HARD)"},"reviewed_rows":{"items":{"type":"integer"},"type":"array","title":"Reviewed Rows","description":"Indecsi de rand needs_review bifate explicit de utilizator"},"confirmed_by":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Confirmed By","description":"Email/identifier utilizator (log atestare)"},"rar_env":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Rar Env","description":"Mediu RAR tinta ('test'|'prod'). None = default cont."}},"type":"object","required":["n_confirmat"],"title":"CommitIn"},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"MapareIn":{"properties":{"cod_op_service":{"type":"string","minLength":1,"title":"Cod Op Service"},"cod_prestatie":{"type":"string","minLength":1,"title":"Cod Prestatie"},"auto_send":{"type":"boolean","title":"Auto Send","default":true}},"type":"object","required":["cod_op_service","cod_prestatie"],"title":"MapareIn"},"PrestatieItem":{"properties":{"cod_prestatie":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cod Prestatie","description":"cod din nomenclator RAR, ex. OE-1"},"cod_op_service":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cod Op Service","description":"cod intern operatie ROAAUTO (mapat -> cod RAR)"},"denumire":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Denumire","description":"denumirea operatiei ROAAUTO (pentru fuzzy lookup la mapare)"}},"type":"object","title":"PrestatieItem","description":"O operatie de declarat. Contract hibrid:\n\nROAAUTO poate trimite FIE `cod_prestatie` (cod RAR direct, ex. OE-1), FIE\n`cod_op_service` (cod intern ROAAUTO) + `denumire` — pe care gateway-ul le\nmapeaza in cod RAR prin operations_mapping. Cel putin unul dintre\ncod_prestatie / cod_op_service e obligatoriu (shape -> 422 daca lipsesc ambele)."},"PrezentareIn":{"properties":{"vin":{"type":"string","title":"Vin"},"nr_inmatriculare":{"type":"string","title":"Nr Inmatriculare"},"data_prestatie":{"type":"string","title":"Data Prestatie"},"odometru_final":{"type":"string","title":"Odometru Final"},"odometru_initial":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Odometru Initial"},"prestatii":{"items":{"$ref":"#/components/schemas/PrestatieItem"},"type":"array","title":"Prestatii"},"sistem_reparat":{"type":"string","title":"Sistem Reparat","default":"null"},"obs":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Obs"},"b64_image":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"B64 Image"}},"type":"object","required":["vin","nr_inmatriculare","data_prestatie","odometru_final","prestatii"],"title":"PrezentareIn","description":"O prezentare de declarat la RAR.\n\nPydantic doar NORMALIZEAZA aici (strip/upper pe vin/nrInm). Validarea de\ncontinut (regex VIN, interval data, R-ODO/I-ODO, odometru) e in\napp.validation.validate_prezentare si NU resping cererea — marcheaza\n`needs_data`."},"PrezentareRequest":{"properties":{"rar_credentials":{"anyOf":[{"$ref":"#/components/schemas/RarCredentials"},{"type":"null"}]},"prezentari":{"items":{"$ref":"#/components/schemas/PrezentareIn"},"type":"array","minItems":1,"title":"Prezentari"},"on_unmapped_error":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"On Unmapped Error"},"rar_env":{"anyOf":[{"type":"string","enum":["test","prod"]},{"type":"null"}],"title":"Rar Env"},"raspuns":{"anyOf":[{"type":"string","enum":["minim","complet"]},{"type":"null"}],"title":"Raspuns"}},"type":"object","required":["prezentari"],"title":"PrezentareRequest","description":"Body pentru POST /v1/prezentari — una sau mai multe prezentari + creds RAR.\n\n`rar_credentials` e OPTIONAL: daca lipseste, worker-ul foloseste creds-urile RAR\ndurabile salvate pe cont (per-env: `accounts.rar_creds_{env}_enc`, via POST /v1/conturi/rar-creds).\nTrimite-le explicit doar cand vrei sa suprascrii creds-urile contului pe acea cerere."},"PrezentariResponse":{"properties":{"results":{"items":{"anyOf":[{"$ref":"#/components/schemas/SubmissionResult"},{"$ref":"#/components/schemas/SubmissionResultMinim"}]},"type":"array","title":"Results"}},"type":"object","required":["results"],"title":"PrezentariResponse"},"RandEditIn":{"properties":{"vin":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Vin"},"nr_inmatriculare":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Nr Inmatriculare"},"data_prestatie":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Data Prestatie"},"odometru_initial":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Odometru Initial"},"odometru_final":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Odometru Final"},"obs":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Obs"}},"type":"object","title":"RandEditIn","description":"Campuri de continut editabile in preview. None = ne-trimis (neschimbat);\n\"\" = sterge override-ul (revine la valoarea din fisier).\nobs = text liber fara validare de continut."},"RarCredentials":{"properties":{"email":{"type":"string","title":"Email"},"password":{"type":"string","title":"Password"}},"type":"object","required":["email","password"],"title":"RarCredentials","description":"Credentiale RAR per-cerere (vin de la ROAAUTO din Oracle). NU se stocheaza."},"RarCredsIn":{"properties":{"email":{"type":"string","minLength":1,"title":"Email"},"password":{"type":"string","minLength":1,"title":"Password"},"rar_target":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Rar Target"}},"type":"object","required":["email","password"],"title":"RarCredsIn","description":"Creds RAR durabile per-cont, stocate criptat (Fernet) in slotul per-mediu.\n\n`rar_target` selecteaza mediul: 'test' | 'prod'. Absent -> mediul ancorei globale\n(AUTOPASS_RAR_ENV), implicit 'test'. Schimbare aditiva — clientii vechi care nu trimit\n`rar_target` continua sa functioneze (comportament consistent cu ancora globala)."},"SubmissionResult":{"properties":{"submission_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Submission Id"},"index":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Index"},"vin":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Vin"},"nr_inmatriculare":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Nr Inmatriculare"},"status":{"type":"string","title":"Status"},"id_prezentare":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Id Prezentare"},"deduped":{"type":"boolean","title":"Deduped","default":false},"reactivated":{"type":"boolean","title":"Reactivated","default":false},"held":{"type":"boolean","title":"Held","default":false},"rar_env":{"type":"string","title":"Rar Env","default":"test"},"erori":{"items":{"type":"object"},"type":"array","title":"Erori","default":[]},"nemapate":{"items":{"type":"object"},"type":"array","title":"Nemapate","default":[]},"motiv":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Motiv"}},"type":"object","required":["status"],"title":"SubmissionResult"},"SubmissionResultMinim":{"properties":{"index":{"type":"integer","title":"Index"},"submission_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Submission Id"},"vehicul":{"type":"string","title":"Vehicul"},"status":{"type":"string","title":"Status"},"motiv":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Motiv"},"id_prezentare":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Id Prezentare"}},"type":"object","required":["index","vehicul","status"],"title":"SubmissionResultMinim","description":"Rezultat compact per prezentare — forma implicita a raspunsului.\n\nChei FIXE (mereu prezente), usor de parsat de clienti simpli (ex. VFP):\n`motiv` e null cand randul e curat in coada; `id_prezentare` e non-null\ndoar pe dedup al unui rand deja trimis la RAR."},"ValidarePrezentariRequest":{"properties":{"rar_credentials":{"anyOf":[{"$ref":"#/components/schemas/RarCredentials"},{"type":"null"}]},"prezentari":{"items":{"$ref":"#/components/schemas/PrezentareIn"},"type":"array","minItems":1,"title":"Prezentari"},"on_unmapped_error":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"On Unmapped Error"},"rar_env":{"anyOf":[{"type":"string","enum":["test","prod"]},{"type":"null"}],"title":"Rar Env"}},"type":"object","required":["prezentari"],"title":"ValidarePrezentariRequest","description":"Body pentru POST /v1/prezentari/valideaza — dry-run fara enqueue."},"ValidareResponse":{"properties":{"results":{"items":{"$ref":"#/components/schemas/ValidareResult"},"type":"array","title":"Results"}},"type":"object","required":["results"],"title":"ValidareResponse"},"ValidareResult":{"properties":{"index":{"type":"integer","title":"Index"},"valid":{"type":"boolean","title":"Valid"},"status_estimat":{"type":"string","title":"Status Estimat"},"rar_env":{"type":"string","title":"Rar Env","default":"test"},"erori":{"items":{"type":"object"},"type":"array","title":"Erori","default":[]},"nemapate":{"items":{"type":"object"},"type":"array","title":"Nemapate","default":[]},"prestatii_rezolvate":{"items":{"type":"object"},"type":"array","title":"Prestatii Rezolvate","default":[]}},"type":"object","required":["index","valid","status_estimat"],"title":"ValidareResult","description":"Verdictul dry-run per prezentare."},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"}}}}