Files
roa2web-service-auto/docs/service-auto/claude-main-design-20260411-rethink.md
Claude Agent f79a03062c docs(service-auto): add v2 design doc for learning prototype
CEO review output: rethink of scrapped 2026-04-10 product plan,
reframed as learning probe + talent-risk hedge. 24-week timeline,
1 screen + 1 SP + MARIUSM_AUTO test schema. Scope wall absolute:
zero touch on 4 existing VFP clients.

Document includes 8 review corrections vs first draft:
register_server over MarciusLabPool, SP targets dedicated orders
table not ACT ledger, explicit connection.commit(), Oracle error
code range classification, file handler logging, kill criterion,
integration checkpoints at weeks 6+12, template+decision-log as
week-24 deliverable.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-06-05 09:37:09 +00:00

438 lines
29 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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 confirm 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 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 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 "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
trebuie protocol de eroare dedicat, nu `RAISE_APPLICATION_ERROR`.
- Ipoteza #5 eșuează: DX pentru 2-4 hrs/week e unusable Marius știe 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ă 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
opresc aici pentru 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 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 (SPACT 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).