Files
roa2web-service-auto/docs/service-auto/decision-log.md
2026-06-05 15:00:42 +00:00

13 KiB

Decision Log — Service Auto Prototype

Prototype: ROA2WEB feat/service-auto Owner: Marius (ERP patron + sole dev) Timeline: 24 săptămâni @ 2-4h/săpt Last updated: 2026-04-11

Acest fișier urmărește verdictele pe cele 6 ipoteze din docs/service-auto/claude-main-design-20260411-rethink.md §"Things this prototype will probe". Fiecare verdict e actualizat pe măsură ce testele rulează. Recomandarea finală (merge/no-go pentru phase 2) se completează după săpt 24.


Kill Criterion Status

Niciun kill criterion nu a fost declanșat până la data de mai sus.

Reminder: dacă orice ipoteză eșuează cu un răspuns clar → prototype încheiat cu succes (learning obținut, decision point clar, zero cod irosit). Kill ≠ eșec.


Ipoteza #1 — python-oracledb + OUT params

Ipoteză: python-oracledb apelează curat PL/SQL proc cu IN + OUT params (NUMBER + VARCHAR2).

Status: CONFIRMED

Dovezi:

  • Săpt 2 (poc/async_out_param_probe.py): cursor.var(oracledb.NUMBER) + cursor.callprocout_var.getvalue() returnează 42.0 corect. Assert PASSED. Latență callproc: ~1ms după connect. Note: .getvalue() returnează float, necesită int() cast.
  • Săpt 3 (test #1 + #2 SP_CREEAZA_COMANDA_PROTOTIP): SP cu 4 IN + 2 OUT (NUMBER + VARCHAR2) apelat via sync-facade în oracle_pool.get_connection('mariusm_test'). Test #1: 5.9ms, OUT p_id_ordl=412, p_nrord='P01-2'. Post-rollback: 0 rows
  • Pattern implementat în backend/modules/service_auto/services/comanda_service.py

Decizie adoptată: sync-facade (consistent cu oracle_pool.py), nu true-async (connect_async). Motivat în week1-notes.md §Gate Correction 9.

Implicație pentru template: pattern cursor.var(oracledb.NUMBER/STRING) + callproc

  • int(out.getvalue()) e reutilizabil direct pentru orice SP cu OUT params.

Ipoteza #2 — session_callback nu leak-uiește între requests

Ipoteză: session_callback pentru CURRENT_SCHEMA switching nu produce state leak între requests concurente pe același pool.

Status: CONFIRMED

Dovezi (2026-04-12, test_pool_concurrency.py — 3/3 passed):

  • test_two_concurrent_connections_return_correct_results: 2 asyncio tasks simultane pe același pool, bind values distincte (111, 222) → rezultate corecte fără cross-bleed.
  • test_session_callback_runs_per_connection: session_callback înregistrat pe server config → confirmat că se apelează la prima conexiune din pool; nu leaked state inter-connection.
  • test_ten_concurrent_queries_no_errors: 10 tasks concurente pe pool cu max=5POOL_GETMODE_WAIT queue-uiește corect excesul; toate 10 completate fără erori.

Nota bene: pool mariusm_test nu folosește session_callback (ROA_WEB apelează SP cu schemă explicită MARIUSM_AUTO.SP_...). Patch-ul session_callback în oracle_pool.py e disponibil pentru modulele viitoare care au nevoie de CURRENT_SCHEMA switching.


Ipoteza #3 — GRANTS model: EXECUTE ON SP, zero DML direct

Ipoteză: user ROA_WEB cu GRANT EXECUTE ON SP + zero INSERT/UPDATE/DELETE pe tabele → INSERT direct returnează ORA-00942, SP call returnează succes.

Status: CONFIRMED

Dovezi (2026-04-12):

  • ROA_WEB creat de DBA cu GRANT CREATE SESSION + GRANT EXECUTE ON SP + GRANT SELECT ON AUTO_VMASINICLIENTI + GRANT SELECT ON DEV_TIP_DEVIZ.
  • test_grants_integration.py — 3/3 passed (anterior 3 skipped — fișier lipsă parola):
    • test_insert_direct_failsORA-00942 (INSERT blocat)
    • test_select_direct_failsORA-00942 (SELECT pe tabel neautorizat blocat)
    • test_exec_sp_succeeds → SP apelat cu succes
  • Verificare live: AUTO_VMASINICLIENTI (266 rows) + DEV_TIP_DEVIZ (7 rows) accesibile; NOM_LUCRARI direct → ORA-00942 (Oracle ascunde complet obiectul, nu returnează 0 rows).
  • Pool mariusm_test switchat la ROA_WEB în .env / .env.prod / .env.test.

Arhitectura multi-tenant documentată (grants-audit.md §4):

  • Oracle 21c: schema-level grants (23ai) nu există. Proxy auth respins — anulează boundary SP-only.
  • Soluție: grants per-obiect incluse în deployment scripts. Firmă nouă = 1 script onboarding. Obiect nou în toate schemele = 1 script companion care loopează V_NOM_FIRME.

Ipoteza #4 — Diacritice encoding end-to-end

Ipoteză: RAISE_APPLICATION_ERROR(-20001, 'mesaj cu ă î ș ț â') ajunge în Vue ca eroare user-friendly, encoding corect prin tot stack-ul (Oracle → oracledb → FastAPI → Vue).

Status: CONFIRMED (Oracle→oracledb→FastAPI; Vue pending manual browser test)

Dovezi (2026-04-12, test_diacritice_encoding.py — 2/2 passed):

  • L1 — Oracle→oracledb: RAISE_APPLICATION_ERROR(-20001, 'Client invalid: ă î ș ț â Ă Î Ș Ț Â') trimis via bind variable → DatabaseError.args[0].message conține toate diacriticele intact. Set complet testat: ă î ș ț â Ă Î Ș Ț Â. NLS chain funcționează fără configurare explicită.
  • L2 — oracledb→FastAPI: _handle_oracle_error(e)HTTPException(422, detail) conține diacriticele, prefix ORA-20001: stripped corect.
  • Vue (manual pending): necesită browser + backend pornit; Toast PrimeVue afișează detail din 422 response. Probabilitate eșec mică (Vue nu modifică string-uri JSON).

Ipoteza #5 — DX acceptabil (save→result < 10s)

Ipoteză: FastAPI hot-reload + Vite dev-server + SSH tunnel Oracle e un DX acceptabil pentru side-work de 2-4h/săpt.

Status: CONFIRMED

Dovezi (week1-notes.md §Conectivitate):

Operație Timp
Sync connect 33ms
Async connect 22ms
Query 0.2-3.3ms
SP callproc (săpt 3) 5.9ms
  • Server Oracle e direct (10.0.20.121:1521) — fără SSH tunnel pe acest server.
  • uvicorn --reload detectează schimbările și reîncarcă în < 1s.
  • Total "save fișier → văd rezultatul" ≪ 10s. Gate trecut.

Implicație: ecosistemul nu necesită optimizare înainte de content. DX confirmat.


Ipoteza #6 — Auth multi-server fără modificări shared code

Ipoteză: flux-ul de auth existent (login → JWT cu server_idAuthenticationMiddleware) suportă un server nou fără modificări la shared/ code.

Status: CONFIRMED

Dovezi Oracle (week3-auth-audit.md, 2026-04-11):

  • pack_drepturi.verificautilizator('MARIUS M', '123')803
  • V_NOM_FIRME: 3 firme cu schema='MARIUSM_AUTO' (id 110/167/169)

Dovezi HTTP (2026-04-12):

POST /api/auth/login {"username":"VIZUALIZARE","password":"123","server_id":"mariusm_test"}
→ JWT companies: ["110","167","169"]  ✅
→ JWT server_id: "mariusm_test"       ✅
→ zero modificări în shared/auth/     ✅

GET /api/service-auto/ping (Bearer JWT)
→ {"result":1,"server":"mariusm_test","latency_ms":0.43}  ✅

Nota: MARIUS M are 2FA activat (email configurat) → testat cu VIZUALIZARE (no email, aceleași 3 firme MARIUSM_AUTO). Același cod auth, același JWT structure.


Decizii arhitecturale documentate

D1 — Sync-facade în loc de true-async (Săpt 1)

Decizie: oracle_pool.get_connection() + pool.acquire() (sync) în async def. Motivare: consistent cu pattern-ul deja proof-ed în treasury_service.py prod. True-async (connect_async) nu aduce beneficii la latențele măsurate (22-33ms connect).

D2 — SP_CREEAZA_COMANDA_PROTOTIP nou în loc de reuse pack_auto (Săpt 3)

Decizie: Opțiunea 3 din design doc — SP minimal cu 2 INSERT-uri (nom_lucrari → dev_ordl) și RETURNING id_lucrare, zero dependency pe pack_sesiune. Motivare: pack_auto.dev_adauga_lucrare v2 are 17 params + pack_sesiune coupling; SP nou cu RETURNING e idiomul Oracle modern și mai ușor de testat.

D3 — CONTAFIN_ORACLE în faza A, ROA_WEB în faza B (Săpt 3)

Decizie: Faza A (săpt 3+) folosește CONTAFIN_ORACLE (DBA role, zero grant work). ROA_WEB creat în faza B când ipoteza #3 e pusă la test. Motivare: faza A validează H1+H2+H5+H6 independent de H3.

D4 — Pool mariusm_test separat de central (Săpt 3)

Decizie: ID distinct mariusm_test în ORACLE_SERVERS deși e același host/user ca central. Motivare: pool sizing independent pentru module service_auto + swap atomic la ROA_WEB în faza B (schimbă doar .env, zero modificări cod).


Recomandare finală

Decizie: MERGE — prototype confirmă că arhitectura e viabilă pentru phase 2.

Data: 2026-04-12 Toate 6 ipoteze: CONFIRMED (H1, H2, H3, H4, H5, H6)

Verdict pe ipoteze

# Ipoteză Verdict Implicație phase 2
H1 oracledb + OUT params CONFIRMED Pattern cursor.var() reutilizabil direct
H2 session_callback concurență CONFIRMED Disponibil pentru module multi-schemă viitoare
H3 ROA_WEB grants SP-only CONFIRMED Arhitectura grants documentată + automatizată
H4 Diacritice encoding CONFIRMED NLS chain OK fără configurare explicită
H5 DX < 10s CONFIRMED Ecosistem nu necesită optimizare
H6 Auth multi-server zero shared code CONFIRMED Pattern reutilizabil pentru orice server Oracle nou

Ce a funcționat mai bine decât așteptat

  • Viteza SP: 5.9ms callproc (față de estimat 50ms) — server local, zero latency Oracle
  • Diacritice: zero configurare NLS necesară — oracledb + Oracle 21c funcționează out-of-box
  • Auth reuse: zero linii modificate în shared/.env + register_server() suficiente
  • ROA_WEB grants: soluția cu V_NOM_FIRME loop e mai curată decât anticipat

Precauții pentru phase 2

  • session_callback multi-schemă: testul de concurență a confirmat pool-ul, dar izolarea CURRENT_SCHEMA între două scheme diferite pe același pool nu e testată — tagged connections necesare dacă apare cazul (vezi TODO-phase2.md)
  • SP production-grade: SP_CREEAZA_COMANDA_PROTOTIP e minimal — nu setează id_sucursala, id_inspector, proc_tvav, observatii. Phase 2 decide: extinde SP-ul sau migrează la pack_auto.dev_adauga_lucrare (17 params, coupling cu pack_sesiune)
  • Vue manual browser test: ComandaNoua.vue nu a fost testată în browser (H4 Vue layer)

Deliverables prototype livrate

Fișier Ce conține
docs/service-auto/template-modul-oracle.md Rețetă reutilizabilă: 11 secțiuni, de la .env la tests
docs/service-auto/learnings.md 7 patterns consolidate din notele săptămânale
docs/service-auto/grants-audit.md Arhitectura grants multi-tenant + scripts onboarding
backend/modules/service_auto/ Modul complet: router, service, schemas, tests (22/22)
src/modules/service-auto/views/ComandaNoua.vue Formular cu date reale din Oracle
poc/hello_oracle.py, poc/async_out_param_probe.py POC-urile de referință

2026-04-13 — Skip 3 integration tests obsolete (post bc481da refactor)

Context

După commit bc481da (multi-tenant refactor) + 9cd7f35 (phase 3 PACK_AUTO)

  • migrația ff_2026_04_13_01_AUTO.sql (grants Tier 3), 3 integration tests vechi din hypothesis-probing phase 1 au rămas pe un contract depășit.

Teste marcate cu @pytest.mark.skip

Test Cauză Acțiune viitoare
test_grants_integration::test_select_direct_fails ff_2026_04_13_01_AUTO.sql acordă SELECT pe NOM_LUCRARI lui ROA_WEB (necesar pentru /operatii). Asserția ORA-00942 e inversă realității actuale. Șterge sau rescrie cu altă tabelă la care ROA_WEB n-are acces (dacă mai există un astfel de caz).
test_grants_integration::test_exec_sp_succeeds SP_CREEAZA_COMANDA_PROTOTIP nu mai e folosit în producție — comanda_service.crea_comanda invocă PACK_SERII_NUMERE.NUMAR_AUTO_INI + PACK_AUTO.DEV_ADAUGA_LUCRARE. Apelul cu 4 IN params cauzează PLS-00306. Rescrie ca smoke live pe PACK_AUTO.DEV_ADAUGA_LUCRARE (17 params) SAU șterge — acoperit de test_router_authorization + live smoke tests.
test_comanda_persist::test_comanda_persist_and_reconnect Același SP obsolete + durabilitate acum validată prin live smoke POST /api/service-auto/comenzi (vezi HANDOFF.md, 2026-04-13). Rescrie ca e2e peste endpoint-ul HTTP dacă e nevoie, altfel șterge.

Impact suite

Înainte După
62 passed, 3 failed (PLS-00306 + ORA-00942 inversat) 62 passed, 3 skipped (0 failed)

Ce NU s-a atins

  • Nu s-a modificat cod production (services/, routers/, schemas/) — nu există regresie reală, doar teste care testau contractul vechi.
  • test_insert_direct_fails rămâne activ și trece — ROA_WEB încă NU are INSERT pe NOM_LUCRARI, asertiunea e corectă.
  • test_pool_concurrency (3/3 passed) și test_diacritice_encoding (2/2 passed) au ieșit din lista de "failing" — trec pe setup-ul curent; HANDOFF.md era puțin în urmă.