diff --git a/.gitignore b/.gitignore index 39f4f3c..6cf2119 100644 --- a/.gitignore +++ b/.gitignore @@ -540,3 +540,6 @@ scripts/ralph/screenshots/ scripts/ralph/archive/ scripts/ralph/usage.jsonl .claude/scheduled_tasks.lock + +# Service-auto reference material (local only, not in repo) +docs/service-auto/*.pdf diff --git a/docs/service-auto/claude-main-design-20260411-rethink.md b/docs/service-auto/claude-main-design-20260411-rethink.md new file mode 100644 index 0000000..0698060 --- /dev/null +++ b/docs/service-auto/claude-main-design-20260411-rethink.md @@ -0,0 +1,437 @@ +# Design: Service Auto Web — Learning + Talent-Risk Hedge (rethink v2) + +Generated by /plan-ceo-review on 2026-04-11 (pivot from the scrapped 2026-04-10 doc) +Revised by /plan-ceo-review on 2026-04-11 (v2 after HOLD SCOPE review + outside voice) +Branch: feat/service-auto +Repo: romfast/roa2web +Status: ACTIVE +Owner: Marius (ERP patron + sole dev) +Supersedes: `claude-main-design-20260410-205024.md` — premise invalidated (old doc was a product delivery plan; real intent is learning + capability hedge) + +## What this is (and what it is NOT) + +**This is:** a side-exploration prototype. Part learning project (Vue 3 + FastAPI async + +oracledb + PrimeVue), part strategic hedge against the "VFP is dead and I can't find +programmers" problem. Target = 1 end-to-end screen with 1 SP write, on the existing test +schema MARIUSM_AUTO at the office server `10.0.20.121/ROA`. Budget ≈ 2-4 hrs/week, ≈48-96 +hours total over 24 weeks (doubled from the original 12-week plan after sincere budget +recalibration — see Review Corrections). + +**This is NOT:** a product, an MVP, a migration plan, or a commitment to ship anything to +any client. The 4 existing clients stay on VFP + Oracle XE local. Zero migration. Zero +customer-facing delivery. Zero timeline pressure. + +**The deliverable is NOT a demo.** The deliverable is **a reusable template for future +Oracle-backed modules + a decision log**. See "Final deliverable" below. + +## Strategic driver (the one that matters) + +Visual FoxPro is a dead language. Marius cannot hire programmers willing to learn it. +Every year on VFP is another year of compounding talent risk on an ERP that powers 4 +long-term clients and generates stable revenue. The only realistic path to "someone else +can maintain this eventually" is moving incrementally to web stacks (Python/Vue) where the +labor pool exists. + +**Constraint that makes this hard:** Oracle coupling. The ERP has 25 years of PL/SQL, +cross-schema synonyms, tenant-per-schema architecture. Postgres migration is not 1:1 — +the PL/SQL and schema mechanics don't translate cleanly. Therefore the migration path is +**"stay on Oracle, switch UI + business logic layer to Python/Vue, keep PL/SQL as the +durable layer."** Service auto is the lowest-risk place to probe whether this path works. + +**Honest caveat on the hedge thesis:** PL/SQL + Oracle domain knowledge is itself a +scarce skill on the Romanian market. This prototype does NOT solve the hiring pipeline +problem for PL/SQL maintainers. What it solves is the Python+Vue+integration layer — the +UI/API half of the stack — where the labor pool is genuinely larger. The hedge is +"replace the half of the stack where hiring is easier"; it is NOT "fix the hiring problem +in one shot." This distinction matters for phase 2 scoping. + +**Success definition for this prototype:** after 24 weeks (or sooner), Marius has +direct evidence (working code, not hand-wavy) that the roa2web monolith can drive Oracle +business logic end-to-end via PL/SQL stored procedures, AND a reusable template +documenting exactly how. If that evidence is positive, the same pattern applies to the +next module. If it's negative, Marius knows this before sinking years into it. + +## The prototype — minimum viable experiment + +One screen, one SP, one test schema, one developer. Absolute scope wall. + +### Target feature + +**Screen:** `ComandaNoua.vue` — formular creare comandă nouă service auto. Minimal +fields: tip comandă (select 4 opțiuni), client (dropdown **hardcoded în Vue** — 2-3 +clienți test cu 1-2 mașini fiecare), operații solicitate (textarea). Submit → backend → +PL/SQL → insert row → return ID → display "Comanda X creată" via **PrimeVue Toast**. + +**SP:** `SP_CREEAZA_COMANDA(p_tip IN, p_client_id IN, p_masina_id IN, p_operatii IN, +p_comanda_id OUT, p_numar OUT)`. **Insert într-un tabel DEDICAT de comenzi** (nume real +în MARIUSM_AUTO — de verificat în VFP înainte de a scrie SP-ul, vezi pregătire săpt 3). +**NU inserează în ACT** (registrul jurnal) — ACT se hit-uiește doar la facturare, care e +NOT IN SCOPE pentru prototype. Validare minimă, return ID + număr. + +**Schema:** **MARIUSM_AUTO** — schemă dedicată de test, deja existentă pe serverul de la +biroul Marius (`10.0.20.121/ROA`), care nu e folosită de altcineva. Zero conexiune la +schemele de producție ale celor 4 clienți. Zero copy / impdp necesar — schema există deja. + +**User Oracle tehnic:** **`ROA_WEB`** — user nou dedicat app-ului FastAPI, cu grants +explicite per SP (`GRANT EXECUTE ON MARIUSM_AUTO.SP_CREEAZA_COMANDA TO ROA_WEB`), fără +acces direct la tabele. Pattern multi-tenant compatibil — același user va avea grants pe +alte scheme în phase 2 dacă probează. + +### Things this prototype will probe (the real learning) + +Fiecare din acestea e o ipoteză pe care prototype-ul trebuie să o confirme sau să o +infirme: + +| # | Ipoteză | Cum o probez | +|---|--------|-------------| +| 1 | `python-oracledb` async cleanly calls PL/SQL proc cu IN+OUT params | Săpt 1 POC: `poc/hello_async_out.py` cu `oracledb.connect_async()` + `cursor.var(oracledb.NUMBER)` + `await cursor.callproc('test_out', [out])`. **GATE**: dacă merge curat, prototype-ul continuă pe true-async. Dacă NU merge, fallback la pattern-ul sync-facade din `treasury_service.py` (deja proof-ed în prod). Fallback e pre-aprobat, NU blochează săpt 2+. | +| 2 | `session_callback` pentru CURRENT_SCHEMA switching nu leak-uiește între requests concurente | Săpt 4: 2 conexiuni paralele pe **aceeași schemă MARIUSM_AUTO**, ambele setează CURRENT_SCHEMA, rulează CALL-uri distincte, verific cu log-uri că nu se încurcă cursor tag reuse. **Limitare acceptată conștient:** testul pe 1 schemă nu dovedește 100% izolarea la multi-schemă — pentru asta ar trebui o a doua schemă test (ex: copie CLEVER), care e în afara budget-ului. Probă de primitive, nu de multi-schemă. | +| 3 | GRANTS de tip "EXECUTE ON SP, zero INSERT/UPDATE/DELETE pe tabele" țin în practică | Săpt 3: user `ROA_WEB` încearcă `INSERT INTO MARIUSM_AUTO.ACT` → `ORA-00942` sau `ORA-01031`; `SELECT * FROM MARIUSM_AUTO.ACT` → `ORA-00942`; `EXEC MARIUSM_AUTO.SP_CREEAZA_COMANDA(...)` → success. Un test automat pytest-marcat `integration` care rulează local. | +| 4 | `RAISE_APPLICATION_ERROR(-20001, 'mesaj cu diacritice ă î ș ț â')` ajunge în Vue ca eroare user-friendly, encoding corect | Săpt 11-12: SP aruncă eroare (client inexistent, tip invalid, operatii gol), serviciul traduce `oracledb.DatabaseError.code` la HTTP status (20001-20999 → 422 business, 12541/12170 → 503 infra, rest → 500), Vue afișează PrimeVue Toast cu mesajul. Obligatoriu test pe un mesaj cu diacritice pentru a proba `NLS_LANG` / encoding chain end-to-end. | +| 5 | FastAPI hot-reload + Vite dev-server + SSH tunnel Oracle e un DX acceptabil pentru side-work de 2-4h/săpt | Săpt 1: măsor timpul de la "save file" la "văd rezultatul" — dacă e > 10s, fix ecosistem înainte de content. **Documentat** în `docs/service-auto/week1-notes.md` cu numere concrete. | + +Dacă oricare din 1-4 eșuează cu un răspuns clar, **prototype-ul s-a încheiat cu succes** — +learning obținut, decision point clar, zero cod irosit care trebuie să supraviețuiască. + +## Scope wall — what is explicitly NOT in this prototype + +Toate aceste subiecte aparțin doc-ului scrapped sau sunt defer-uri la TODO-phase2. Niciunul nu intră aici: + +- ❌ Cei 4 clienți existenți, vreodată. Ei rămân pe VFP + XE local. Zero atingere. +- ❌ Migrare scheme, SSH tunnel VFP→Oracle central, decomisionare XE local +- ❌ eFactura / ANAF / SPV upload — irelevant fără producție +- ❌ Feature flags per-tenant, `FEATURE_FLAGS` table +- ❌ `SP_BON_CONSUM` (cross-schema synonyms), `SP_VALIDEAZA_COMANDA`, `SP_EMITE_FACTURA` — toate deferred +- ❌ **Insert în ACT la creare comandă** — ACT e registrul jurnal, se hit-uiește la facturare, care e NOT IN SCOPE +- ❌ `reconcile.py`, invariant checking, parallel testing cu VFP +- ❌ Runbook rollback, monthly restore drill, uptime monitoring, Telegram alerts +- ❌ 5 ecrane MVP (doar 1 — absolute wall) +- ❌ Mobile, responsive, iPad, tablet — desktop-only, viewport-whatever-is-convenient +- ❌ Playwright e2e, smoke parity pentru SPs +- ❌ Endpoint `/clienti` sau `/masini` pentru populare dropdown — hardcoded în Vue +- ❌ Onboarding client nou, referral pipeline, assignment cu telefoane +- ❌ Phase 2, Phase 3, Phase 4 — menționate doar în decision-log.md la finalul prototype-ului +- ❌ SLA, RPO, RTO, warm standby, backup discipline +- ❌ `X-Idempotency-Key`, double-submit protection, retry policy +- ❌ A doua schemă de test (ex: copie CLEVER) pentru probă multi-schemă — costă prea mult budget + +Dacă în timpul construcției una dintre aceste tentații începe să pară "doar 30 min în +plus", răspunsul e **scriu o notă, nu scriu cod**. Scope wall ține. Note de tipul +"probabil o să am nevoie de X pentru phase 2" merg în `docs/service-auto/TODO-phase2.md`, +nu în codul prototype-ului. + +## Review corrections (from /plan-ceo-review session, 2026-04-11) + +Această secțiune documentează ce s-a corectat față de prima versiune a planului, pentru a +fi transparent despre gândirea care a dus la planul final. + +### Correction 1 — Nu se creează `MarciusLabPool` nou + +**Prima versiune** spunea: "modifică `OracleMultiPool` sau adaugă wrapper" și "creează NEW +minimal helper `MarciusLabPool`". **Realitate:** `OracleMultiPool` la +`shared/database/oracle_pool.py` are deja suport multi-server prin `_pools: Dict[server_id, ConnectionPool]`. +MARIUSM_AUTO se adaugă ca **server nou** prin `register_server('mariusm_test', host='10.0.20.121', port=1521, user='ROA_WEB', password='...', service_name='ROA')` — zero pool nou, zero refactor. + +### Correction 2 — Pattern sync-in-async-facade e deja proof-ed în prod + +**Prima versiune** trata ipoteza #1 ("oracledb async + OUT params") ca unknown. **Realitate:** +`backend/modules/reports/services/treasury_service.py` deja apelează SPs cu OUT params de +tip `oracledb.CURSOR` și `oracledb.NUMBER` în producție, folosind pattern-ul +sync-in-async-facade (`async with oracle_pool.get_connection(...)`, cursor sync, fără +`await` pe execute/callproc). **Consecință:** ipoteza #1 e reîncadrată ca probă a +pattern-ului `oracledb.connect_async()` **true-async** — nou, neprobeat în codebase. +Săpt 1 e **gate** (vezi mai sus): dacă true-async merge → adoptă; dacă nu → fallback la +sync-facade care e deja dovedit. + +### Correction 3 — SP nu inserează în ACT + +**Prima versiune** spunea "Insert în ACT, validare minimă". **Realitate:** ACT e registrul +jurnal contabil (double-entry bookkeeping, clasa 6/7 — vezi +`.claude/rules/financial-indicators.md`). O comandă de service auto la CREARE aterizează +într-un **tabel dedicat** (ex: `COMENZI`, `COMD_SA`, nume real de verificat în VFP), NU +în ACT. ACT se hit-uiește la **facturare**, care e NOT IN SCOPE. SP-ul corect face INSERT +în tabela dedicată de comenzi. + +**Task în săpt 3 (preparare):** înainte de a scrie SP_CREEAZA_COMANDA, deschide VFP-ul +producție (cu grijă, doar read), caută fluxul real de "creează comandă nouă service auto", +identifică tabelele atinse, documentează în `docs/service-auto/tabele-service-auto.md`. + +### Correction 4 — `connection.commit()` e explicit în pattern + +**Prima versiune** nu menționa commit. **Realitate:** `oracledb` driver are autocommit OFF +default. Fără `connection.commit()` după `cursor.callproc`, SP-ul rulează dar datele NU se +salvează — **silent failure clasică**. Pattern-ul corect e: + +```python +async with oracle_pool.get_connection('mariusm_test') as conn: + with conn.cursor() as cursor: + out_id = cursor.var(oracledb.NUMBER) + out_numar = cursor.var(oracledb.STRING, size=50) + cursor.callproc('SP_CREEAZA_COMANDA', [..., out_id, out_numar]) + conn.commit() # <-- CRITICAL +``` + +**Test obligatoriu** în săpt 5-6: după `callproc + commit`, închide conexiunea, deschide +alta, `SELECT ... WHERE id = :id` — confirmă că row-ul persistă. Dacă nu, commit-ul e +problemă. + +### Correction 5 — Error code classification e explicită în plan + +**Prima versiune** zicea doar "ORA-20001 → toast". **Realitate:** există multe categorii +de erori Oracle, iar trducerea la HTTP trebuie să fie range-based: + +| Cod Oracle | HTTP | Ce vede user-ul | +|---|---|---| +| 20001 — 20999 (`RAISE_APPLICATION_ERROR`) | 422 | Mesajul din SP, curat de prefix | +| 12541, 12170, 12154 (connection / listener errors) | 503 | "Serviciul bazei de date e temporar indisponibil" | +| 01017 (invalid credentials) | 500 + critical log | "Eroare de configurare. Contactați administratorul." | +| 00942 (table or view not exist — grants leak) | 500 + critical log | "Eroare internă. Contactați administratorul." | +| Orice alt cod | 500 + full log | "Eroare internă neașteptată" | + +Săpt 11-12: scrie service-layer-ul cu `try/except oracledb.DatabaseError` + clasificare +pe range. Test cu diacritice în mesaj. + +### Correction 6 — Logging persistent per-modul + +**Prima versiune** nu menționa logging. **Realitate:** `backend/main.py:57` folosește +`logging.basicConfig` cu output doar în stdout. Dacă în săpt 5 vrei să recitești +log-urile din săpt 2, nu ai unde. Fix local pentru `service_auto`: + +```python +# backend/modules/service_auto/__init__.py +import logging, os +os.makedirs('backend/logs', exist_ok=True) +logger = logging.getLogger('service_auto') +fh = logging.FileHandler('backend/logs/service_auto.log') +fh.setFormatter(logging.Formatter('%(asctime)s %(levelname)s %(name)s: %(message)s')) +logger.addHandler(fh) +logger.setLevel(logging.INFO) +``` + +Log structurat la fiecare call: +```python +logger.info("service_auto.create_comanda START", extra={'user': user.username, 'tip': data.tip, 'client_id': data.client_id}) +logger.info("service_auto.create_comanda OK", extra={'comanda_id': comanda_id, 'duration_ms': elapsed}) +logger.warning("service_auto.create_comanda BUSINESS_ERROR", extra={'ora_code': code}) +logger.error("service_auto.create_comanda INFRA_ERROR", extra={'ora_code': code}, exc_info=True) +``` + +La sfârșit de fiecare săptămână, `grep` în log pentru count-uri și duration p99. + +### Correction 7 — Timeline dublat: 12 → 24 săptămâni + +**Prima versiune** aloca 12 săptămâni × 2-4 h/săpt = 24-48h. **Realitate (outside voice):** +10 tehnologii noi (Vue 3, Pinia, PrimeVue, Axios, FastAPI async, oracledb true-async, +`session_callback`, PL/SQL OUT params, JWT reuse cu auth store, error mapping) ÷ 24h = +~2.4h per tehnologie, **zero slack**. Plus 2-3 săpt pierdute realist pe VFP urgențe din +12. **Buget onest: 24 săptămâni × 2-4 h/săpt = 48-96h total.** Scope-ul rămâne același, +tempo-ul e mai onest. + +### Correction 8 — Week-12-style deliverable schimbă: template reutilizabil, nu demo + +**Prima versiune** zicea săpt 12 = "cleanup + phase 2 notes". **Realitate:** un demo pe un +branch throwaway nu e un hedge — e o demonstrație. Hedge-ul real e un **template +reutilizabil**. Noul deliverable pentru săpt 24: + +- `docs/service-auto/template-modul-oracle.md` — rețetă de 1 pagină pentru "cum adaugi un + modul nou peste Oracle în roa2web": register_server pattern, SP signature convention, + grants model, error map range, `session_callback` snippet, JWT reuse via + AuthenticationMiddleware, logging setup, file layout. +- `docs/service-auto/decision-log.md` — go / no-go pentru phase 2: ce a funcționat, ce + nu, sub ce condiții se justifică un al doilea modul, când să nu. +- `docs/service-auto/learnings.md` — notele săptămânale consolidate în lesson patterns. + +## What to reuse from the scrapped doc + +Nu tot efortul de pe doc-ul vechi e pierdut: + +- **Manual ROAAUTO PDF** (`docs/service-auto/manual_ROAAUTO.pdf`) — ground truth pentru + fluxul real de service auto. Folosit ca input pentru ce câmpuri trebuie să aibă + `ComandaNoua.vue` și ca referință pentru verificarea tabelelor atinse la creare comandă. +- **Legacy `/workspace/roaauto/frontend/src/views/orders/OrderCreateView.vue`** — + starting point pentru `ComandaNoua.vue` la ~125 linii, audit de 30 min în săptămâna 1. +- **Convenția de `@cached` + services** din `.claude/rules/backend-patterns.md` — dar NU + aplicat la endpoint-ul de INSERT (cache-ul e pentru reads). +- **Pattern-ul `treasury_service.py`** ca **golden example** de apel PL/SQL cu OUT params. + +## Risks + mitigations + +### Risk 1: 2-4 hrs/week + learning curve = prototype drifts into 12+ months +Corecția de buget (24 săpt) ajută. **Mitigare principală:** stop-point discipline +(milestone self-contained per săptămână) + **kill criterion explicit** (vezi mai jos). +Săpt 1 goal e **Hello World Oracle connection** — nu SP, nu schema, nu UI. + +### Risk 2: oracledb async + PL/SQL OUT params sunt poorly documented +Săpt 1 POC e exact asta, pe o procedură trivială. **Fallback pre-aprobat:** dacă +true-async nu merge, prototype-ul continuă cu sync-facade (pattern deja în prod). Zero +timp pierdut. + +### Risk 3: ~~CURRENT_SCHEMA switching conflictează cu OracleMultiPool~~ +**Corectat:** nu conflictează. `OracleMultiPool` izolează per `server_id`. +`session_callback` se aplică la `create_pool` call, nu la nivel de instance. Poți adăuga +un argument `session_callback=` la pool creation pentru `mariusm_test` fără să atingi +pool-urile altor servere. + +### Risk 4: Marius abandonează side project-ul după săpt 3 pentru că VFP-ul real cere atenție +Realitate acceptată (outside voice): 2-3 săpt pierdute în 12 e probabil. **Mitigare:** +timeline dublat la 24, fiecare săptămână e stoppable milestone, plus **kill criterion**. + +### Risk 5 (NEW): Integration issues concentrate la final +Outside voice observă: fiecare layer e mock-uit până la săpt 11, apoi totul se integrează. +Dacă Vue↔FastAPI↔oracledb are un CORS/proxy/JWT header issue, apare fără buffer. +**Mitigare:** două **integration checkpoints** intermediare: +- Săpt 6 checkpoint: un `curl` hit pe endpoint-ul fără UI, cu JWT real, care cheamă SP-ul și returnează JSON. Confirmă FastAPI↔oracledb chain. +- Săpt 9 checkpoint: `ComandaNoua.vue` hit endpoint-ul cu JWT real, confirmă doar un drum happy path fără error handling. Confirmă Vue↔FastAPI chain. + +### Risk 6 (NEW): Grants inventory pe MARIUSM_AUTO nedocumentat +Outside voice observă: testul negativ săpt 3 presupune clean slate. **Mitigare:** săpt 3, +înainte de testul negativ, rulează un `SELECT * FROM DBA_TAB_PRIVS WHERE grantee = 'ROA_WEB'` ++ `SELECT * FROM DBA_SYS_PRIVS WHERE grantee = 'ROA_WEB'` și documentează starting state +în `docs/service-auto/week3-grants-audit.md`. + +## Kill criterion (NEW — from outside voice) + +**Prototype-ul se oprește definitiv** (nu "pauză de o săptămână", ci "end of project, +scrie decision-log și gata") dacă ORICARE din: + +1. **Săpt 4 checkpoint:** `session_callback` nu funcționează după 2 săpt de încercări + (adică nu ai ajuns la o conexiune care schimbă CURRENT_SCHEMA curat, fără race). Decizia: + scrie `decision-log.md` cu "session_callback nefezabil în acest oracledb/Python combo, + multi-tenant necesită alt approach", apoi stop. +2. **Săpt 8 checkpoint:** nu ai un SP `SP_CREEAZA_COMANDA` funcțional testat din SQL + Developer + Python + grants OK. Decizia: `decision-log.md` cu "pattern SP-first prea + greu pentru side-project budget", apoi stop. +3. **Săpt 14 checkpoint:** nu ai un curl care apelează endpoint-ul + JWT real + SP + returnează JSON. +4. **Oricând:** 3 săpt consecutive în care nu ai atins nici măcar 1 oră de work pe + prototype. Side project-ul e mort, acceptă realitatea, `decision-log.md` cu + "abandoned — VFP demands exceeded budget". + +Stop NU înseamnă eșec. Stop înseamnă "am învățat ce trebuia, continuarea nu mai produce +valoare marginală". Fiecare stop produce un `decision-log.md` citibil în 6 luni. + +## Timeline (ajustat pentru 2-4 hrs/week × 24 săptămâni) + +**Fiecare săptămână e self-contained + oprire curată.** Ordering-ul original e păstrat, +doar spațiat pe 24 săpt în loc de 12, cu checkpoints de integration intermediare. + +| Săpt | Target | Cum știu că e gata | +|---|---|---| +| 1 | Oracle central rulează + `poc/hello_oracle.py` (sync) + `poc/hello_oracle_async.py` (`connect_async`) conectează cu `SELECT 1 FROM DUAL`. **Gate**: decide sync-facade vs true-async. DX check (save → result < 10s?). File handler logging setup. | Log arată rezultat, `docs/service-auto/week1-notes.md` scris | +| 2 | `poc/async_out_param_probe.py` — test SP trivial (`CREATE PROCEDURE test_out(p OUT NUMBER) AS BEGIN p := 42; END;`) + Python apel cu `cursor.var(int)` | Script scris, primește `42` | +| 3 | **Preparare:** audit grants curenți pe MARIUSM_AUTO (`DBA_TAB_PRIVS`, `DBA_SYS_PRIVS`). **Verifică tabelele** atinse de crearea comenzii în VFP, scrie `tabele-service-auto.md`. Creează user `ROA_WEB` + grants. | `week3-grants-audit.md` + `tabele-service-auto.md` scrise | +| 4 | Test negativ ipoteza #3 (INSERT direct → ORA-00942; SELECT direct → ORA-00942; CALL SP → success). Pytest integration marker. | Test automat rulează local, toate cele 3 asserts trec | +| 5 | `session_callback` pentru CURRENT_SCHEMA switching, test concurent pe 2 conexiuni paralele pe aceeași schemă | Log-uri clare, niciun cursor tag leak | +| 6 | **Checkpoint integration 1**: endpoint FastAPI minimal (fără logic, hardcoded return) + JWT reuse din middleware + curl hit cu JWT real. Doar ca să confirm că chain-ul FastAPI + auth merge. | `curl` cu JWT real returnează 200 | +| 7-8 | **Verify tabele** în VFP (din săpt 3), scrie `SP_CREEAZA_COMANDA` în SQL Developer, test manual cu `EXEC` | Row apare în tabela dedicată cu ID returnat prin OUT | +| 9-10 | Service-layer Python (`comenzi_service.create_comanda`) care apelează SP-ul prin pattern-ul ales în săpt 1 + `connection.commit()` + test persist după reconnect | Test automat: callproc + commit + new connection + SELECT → row există | +| 11 | Endpoint FastAPI `/api/service-auto/comenzi` care primește Pydantic, apelează service, returnează JSON | `curl` hit cu JWT real + body JSON → row inserted | +| 12 | **Checkpoint integration 2**: `ComandaNoua.vue` minimal (hardcoded dropdowns) + Pinia store + axios call → endpoint. Doar happy path, zero error handling. | Submit în browser → row inserted → console log "OK" | +| 13-16 | Error handling end-to-end: ORA-20001 (diacritice!) → HTTP 422 → PrimeVue Toast în română. ORA-12541 → HTTP 503 → Toast generic. Spinner pe buton cât SP rulează. Reset form la success. | Aruncă intenționat erori în SP, verifică fiecare drum | +| 17-20 | Buffer pentru VFP urgențe + lessons refactor (dacă săpt 1-16 au produs cod care trebuie curățat). Dacă nu e nevoie de buffer, rula ipoteza #2 mai adânc (2 conexiuni, concurență mai agresivă). | N/A — buffer | +| 21-22 | Scrie `template-modul-oracle.md` — reteta reutilizabilă | Doc scris, citibil de către un alt dev | +| 23 | Scrie `decision-log.md` — go/no-go phase 2, learnings consolidate | Doc scris, decizie clară | +| 24 | Cleanup: ștergerea `poc/` dacă e cazul, final commit pe branch, `learnings.md` consolidat | Branch clean, commit final | + +**Timeline-ul e intenționat conservativ.** La 2-4 hrs/week, 24 săpt = 48-96 ore totale. +Dacă merge mai repede, perfect — atingi mai devreme la sfârșit. Dacă merge mai încet, +fiecare săptămână e încă un milestone self-contained. + +## What would make this prototype fail (and it would still be useful) + +- Ipoteza #1 eșuează pentru **true-async**: fallback la sync-facade, prototype continue. + Zero învățare pierdută — sync-facade e deja în producție, știi că merge. +- Ipoteza #1 eșuează pentru **ambele** (sync + true-async): dacă nici sync-facade-ul din + `treasury_service.py` nu merge la MARIUSM_AUTO, e ceva radical prost cu oracledb + instalat la tine. **Stop și investighează**. +- Ipoteza #2 eșuează: `session_callback` fragil în practică → Marius știe că pool-per-tenant + e necesar, nu pool-single-with-tag. Design major changed, decision-log documentează. +- Ipoteza #3 eșuează: GRANTS model nu ține (SP cheamă alte SPs cu privilegii neașteptate) + → Marius știe că "Regula de aur via GRANTS" e naivă și trebuie altceva (VPD? + row-level security?). Design major changed. +- Ipoteza #4 eșuează: error propagation urâtă (encoding, truncation) → Marius știe că + trebuie protocol de eroare dedicat, nu `RAISE_APPLICATION_ERROR`. +- Ipoteza #5 eșuează: DX pentru 2-4 hrs/week e unusable → Marius știe că side project pe + acest stack nu e viabil și trebuie alt approach. + +Orice din aceste failures e **valoare mai mare** decât "prototype care merge happy path +fără să fi întâmpinat nicio problemă reală". Succesul real = învățare, nu cod. + +## Next actions (săpt 1, 2026-04-14 → 2026-04-18) + +Cel mai concret lucru, o singură zi, 2-4 ore: + +1. **Verifică SSH tunnel setup** de la containerul de dev (sau workstation-ul de acasă) + la `10.0.20.121/ROA`. Există `ssh-tunnel-manager.py` în `backend/shared/` — vezi dacă + se refolosește. +2. **`poc/hello_oracle.py`** (sync, la `MARIUSM_AUTO` user sau alt user Oracle existent) — + `oracledb.connect(...)` + `SELECT 1 FROM DUAL`. +3. **`poc/hello_oracle_async.py`** (true-async) — `oracledb.connect_async(...)` + același + `SELECT 1 FROM DUAL` cu `await cursor.execute(...)`. +4. **Setup logging file handler** pentru modulul `service_auto` (nu exista încă, dar + directory-ul `backend/modules/service_auto/` se poate crea în săpt 1 just to house + the logging setup). +5. **Raport săpt 1** — `docs/service-auto/week1-notes.md`, max 15 linii: ce a mers, ce a + fost greu, DX latency măsurat (save → result în secunde), gate decision (sync vs + true-async), buget rămas din săpt 1. + +Zero SP-uri, zero Vue, zero auth, zero scheme noi. Doar "Python vorbește cu Oracle local" +în ambele pattern-uri. + +## Non-negotiables + +1. **Cei 4 clienți nu sunt atinși niciodată în acest prototype.** MARIUSM_AUTO e + dedicat, zero copy, zero conexiune la producție. +2. **Scope wall la 1 ecran + 1 SP.** Tentațiile de scope creep merg la + `docs/service-auto/TODO-phase2.md`, nu în cod. +3. **Stop points weekly.** Fiecare săptămână e oprire curată. Nu se acceptă "oh, nu pot + să mă opresc aici pentru că e jumătate făcut". +4. **Succesul se măsoară în învățare + template reutilizabil**, nu în ecrane livrate. Un + prototype care descoperă o problemă e mai valoros decât unul care evită toate + problemele. +5. **Kill criterion trigger-ed → scrie decision-log → stop.** Nu "mai dau 2 săpt să văd". + +## Final deliverable (săpt 24) + +Nu e un ecran. Nu e un demo. E: + +1. `docs/service-auto/template-modul-oracle.md` — rețetă de 1 pagină citibilă de către un alt dev în 10 minute: + - Cum înregistrezi un server nou în `OracleMultiPool` + - Signature convention pentru SPs cu OUT params + - Grants model (user tehnic + `EXECUTE ON SP` + `ALTER SESSION SET CURRENT_SCHEMA`) + - Error code range classification (20xxx → 422, 12xxx → 503, else → 500) + - `session_callback` snippet pentru CURRENT_SCHEMA switching + - JWT reuse prin `AuthenticationMiddleware` + - Logging file handler per-modul + - File layout (`routers/`, `services/`, `models/`) +2. `docs/service-auto/decision-log.md` — go / no-go pentru phase 2: + - Ce ipoteze s-au confirmat, care nu + - Evidența concretă (log-uri, teste, numere DX) + - Condițiile sub care un al doilea modul e justificat + - Condițiile sub care NU e justificat (kill criterion retroactiv) +3. `docs/service-auto/learnings.md` — notele săptămânale consolidate, pattern-uri noi, + surprize, workarounds descoperite, Oracle edge cases. +4. Cod: tot sub branch `feat/service-auto`, NU merged în main. Branch = arhivă + referință. + +**Acest deliverable e valoros chiar dacă prototype-ul n-a ajuns la 100% din ipoteze.** + +--- + +**END OF RETHINK DESIGN v2. ~9 pages. Budget 2-4 hrs/week × 24 weeks = 48-96 hrs total.** + +--- + +## GSTACK REVIEW REPORT + +| Review | Trigger | Why | Runs | Status | Findings | +|--------|---------|-----|------|--------|----------| +| CEO Review | `/plan-ceo-review` | Scope & strategy | 1 | CLEAR (PLAN) | HOLD SCOPE mode, 0 critical gaps post-fix, 10 items deferred to TODO-phase2, plan file rewritten v2 with 8 review corrections | +| Codex Review | `/codex review` | Independent 2nd opinion | 0 | — | — | +| Eng Review | `/plan-eng-review` | Architecture & tests (required) | 0 | — | — | +| Design Review | `/plan-design-review` | UI/UX gaps | 0 | — | — | +| DX Review | `/plan-devex-review` | Developer experience gaps | 0 | — | — | + +**OUTSIDE VOICE:** Claude subagent (Codex unavailable). 15 findings total. 3 load-bearing surfaced as cross-model tension (SP→ACT modeling error, budget ~2x under-scoped, demo vs template deliverable). All 3 accepted by user and integrated into plan v2. + +**UNRESOLVED:** 0 + +**VERDICT:** CEO CLEARED — plan rewritten as v2 with 8 corrections, 0 critical gaps, 24-week timeline, template deliverable. Eng review recommended before writing any code (optional for learning prototype but helps catch architectural issues in service_auto module structure).