# Deploy — Onboarding schemă / server nou (Service Auto) **Scop**: Procedură completă pentru aducerea unei schem Oracle noi (firmă nouă) sub umbrela modulului `service-auto`, inclusiv cazul în care schema trăiește pe un server Oracle nou care nu e încă listat în `ORACLE_SERVERS`. **Audiență**: DBA + dev ops ROA2WEB. **Prerechizite**: `CONTAFIN_ORACLE` (sau DBA) pe instanța Oracle destinație; acces SSH la hostul backend pentru `.env` și restart. --- ## 0. Convenții - `` — numele schemei noi (ex: `ACME_AUTO`, `MARIUSM_AUTO`). - `` — cheia logică pentru server în `ORACLE_SERVERS` (ex: `acme_prod`). - `` — `id_firma` returnat de `V_NOM_FIRME` pentru schema nouă. - Toate exemplele folosesc placeholder-uri; **nu hardcoda** `MARIUSM_AUTO` în scripturi noi. --- ## 1. `impdp` schema nouă Schema nouă se creează dintr-o schemă template (sau dintr-un dump al unei firme existente) cu `impdp` + `REMAP_SCHEMA`. ```bash # Exemplu minimal — adaptează directory_name, dumpfile, logfile la instanța ta. impdp system/@ \ SCHEMAS=TEMPLATE_AUTO \ REMAP_SCHEMA=TEMPLATE_AUTO: \ DIRECTORY=DATA_PUMP_DIR \ DUMPFILE=template_auto.dmp \ LOGFILE=impdp_.log \ TRANSFORM=OID:N ``` **Opțiuni utile**: | Caz | Flag | |---|---| | Sequences există deja pe instanță (ex: secvențe globale) | `EXCLUDE=SEQUENCE` | | Doar DDL + date minimale (fără audit/log tables) | `EXCLUDE=TABLE:"IN('AUDIT_LOG','SESSION_LOG')"` | | Paralel pe server cu resurse | `PARALLEL=4` | | Reluare dacă a picat la jumătate | `TABLE_EXISTS_ACTION=SKIP` sau `REPLACE` | **Verificare post-impdp**: ```sql SELECT COUNT(*) FROM DBA_OBJECTS WHERE OWNER = ''; SELECT OBJECT_TYPE, COUNT(*) FROM DBA_OBJECTS WHERE OWNER = '' GROUP BY OBJECT_TYPE ORDER BY 2 DESC; ``` Obiectele critice pentru `service-auto` care **trebuie** să existe: - `PACK_AUTO`, `PACK_MIGRARE`, `PACK_SERII_NUMERE` (PACKAGE) - `AUTO_VMASINICLIENTI` (VIEW) - `DEV_TIP_DEVIZ`, `DEV_ORDL`, `NOM_LUCRARI`, `NOM_PARTENERI`, `CALENDAR` (TABLE) - `DEV_NOM_NORME`, `DEV_NOM_INSPECTORI`, `DEV_NOM_ASIGURATORI` (TABLE) --- ## 2. Rulează `onboarding_roa_web.sql` (GRANT-uri) **Fișier**: `docs/service-auto/onboarding_roa_web.sql` 1. Dacă e prima schemă pe instanță, rulează întâi §2 (CREATE USER ROA_WEB) — O SINGURĂ DATĂ pe instanță. Parola se ia din vault și se salvează în `backend/secrets/.oracle_pass` (gitignored). 2. Deschide o copie locală a fișierului și înlocuiește `` cu schema reală (un singur search-and-replace — vezi header-ul fișierului). 3. Rulează secțiunea §1 conectat ca `CONTAFIN_ORACLE` (sau DBA cu privilegii de GRANT). **Verificare post-grants**: ```sql -- Ar trebui să returneze ≥ 11 rânduri (6 granturi inițiale + 5 din migrații 04_13). SELECT TABLE_NAME, PRIVILEGE FROM DBA_TAB_PRIVS WHERE GRANTEE = 'ROA_WEB' AND OWNER = '' ORDER BY TABLE_NAME, PRIVILEGE; ``` --- ## 3. Update `.env` cu `ORACLE_SERVERS` (doar pentru server nou) Dacă schema nouă e pe un **server Oracle nou** (alt host decât cele existente), trebuie adăugat un entry în `backend/.env`. > **NU atinge `.env` direct pe serverele rulante în această procedură** — doar > documentează modificarea. Deployment-ul `.env` urmează procesul standard al > ops-ului (secret manager / Ansible / copy manual). Pattern per `backend/ENV-SETUP.md`: ```bash # backend/.env (extras) ORACLE_SERVERS=existing_key,acme_prod ORACLE_SERVER_ACME_PROD_DSN=oracle.acme.local:1521/ROA ORACLE_SERVER_ACME_PROD_USER=ROA_WEB ORACLE_SERVER_ACME_PROD_PASS_FILE=backend/secrets/acme_prod.oracle_pass ``` Dacă schema nouă trăiește pe un server **deja listat** în `ORACLE_SERVERS`, pasul 3 se sare — nu trebuie modificat nimic în `.env`. --- ## 4. Restart backend + verifică `V_NOM_FIRME` Per `CLAUDE.md`, serverele se pornesc/opresc **doar** cu scripturile dedicate: ```bash ./start-backend.sh restart # doar backend # sau ./start.sh prod # backend + frontend + tunnel (dacă e cazul) ./status.sh # verifică starea ``` **Verificare că schema nouă a fost descoperită**: ```bash # Autentifică-te în UI cu un user care are permisiuni pe schema nouă (sau via curl): curl -H "Authorization: Bearer " http://localhost:8000/api/auth/firme ``` Trebuie să apară `` cu noul `id_firma`. Notează `` — e folosit în pasul următor și în smoke tests. Dacă `V_NOM_FIRME` e cache-uit, forțează refresh conform `cache/decorators.py` (TTL schema lookups = 24h; restart backend = invalidare completă). --- ## 5. Rulează migrațiile service-auto în ordine cronologică Directorul `docs/service-auto/migrations/` conține migrațiile per-schemă care completează schema template cu modificările recente. Rulează-le **în ordine alfabetică a numelui fișierului** (convenția `ff_YYYY_MM_DD_NN_AUTO.sql` garantează ordine cronologică). Migrații curente (aprilie 2026): | Ordine | Fișier | Rol | |---|---|---| | 1 | `ff_2026_04_12_01_AUTO.sql` | Adaugă `DEV_ORDL.id_sucursala` + rescrie `SP_CREEAZA_COMANDA_PROTOTIP` | | 2 | `ff_2026_04_13_01_AUTO.sql` | GRANT-uri + index functional `IX_NOM_PARTENERI_DEN_UPPER` | | 3 | `ff_2026_04_13_02_AUTO.sql` | `GRANT INSERT ON NOM_PARTENERI` | **Rulare**: conectat **ca schema țintă** (``), NU ca `CONTAFIN_ORACLE`, pentru că DDL-ul interior (ALTER TABLE, CREATE INDEX, CREATE OR REPLACE PROCEDURE) rulează pe obiectele proprii ale schemei. ```bash # Înlocuiește schema name în fiecare fișier (sau folosește sqlplus ca ). sqlplus /@ @docs/service-auto/migrations/ff_2026_04_12_01_AUTO.sql sqlplus /@ @docs/service-auto/migrations/ff_2026_04_13_01_AUTO.sql sqlplus /@ @docs/service-auto/migrations/ff_2026_04_13_02_AUTO.sql ``` Toate migrațiile AUTO sunt **idempotente** (per `.claude/rules/oracle-migrations.md`): - `ALTER TABLE ADD` wrap în `PACK_MIGRARE.COLUMNEXIST` - `CREATE INDEX` wrap în `PACK_MIGRARE.OBJECTEXIST` - `CREATE OR REPLACE PROCEDURE` — natural idempotent - `GRANT` — no-op la re-rulare Re-rularea unei migrații = safe. Footer-ul `pack_migrare.UpdateVersiune(...)` e ce scrie în tabelul de versiuni. **Verificare migrații**: ```sql -- Ar trebui să returneze cele 3 versiuni ff_2026_04_12_01_AUTO ... ff_2026_04_13_02_AUTO SELECT VERSIUNE, DATA_APLICARE FROM .VERSIUNI_APLICATE WHERE VERSIUNE LIKE 'ff_2026_04%_AUTO' ORDER BY VERSIUNE; ``` (Numele tabelului de versiuni poate diferi — verifică în `PACK_MIGRARE` body.) --- ## 6. Smoke tests Folosește un JWT valid pentru un user cu permisiuni pe ``. ```bash TOKEN="" BASE="http://localhost:8000/api/service-auto" # 6.1. Ping — răspuns rapid, fără query Oracle. curl -H "Authorization: Bearer $TOKEN" $BASE/ping # 6.2. Tip deviz — citește din DEV_TIP_DEVIZ; verifică GRANT SELECT. curl -H "Authorization: Bearer $TOKEN" "$BASE/tip-deviz?id_firma=" # 6.3. Mașini — citește din AUTO_VMASINICLIENTI. curl -H "Authorization: Bearer $TOKEN" "$BASE/masini?id_firma=" # 6.4. Comenzi — JOIN DEV_ORDL + NOM_LUCRARI. curl -H "Authorization: Bearer $TOKEN" "$BASE/comenzi?id_firma=" ``` **Expectat**: 200 OK cu JSON (array-uri sau obiecte paginate). 401/403 = JWT sau permisiuni greșite. 500 cu `ORA-00942` = GRANT lipsă (re-rulează §2). 500 cu `ORA-04063` = migrațiile §5 nu au rulat complet (verifică `SP_CREEAZA_...` și `DEV_ORDL.id_sucursala`). --- ## 7. Rollback Dacă onboarding-ul a eșuat ireversibil sau schema nouă trebuie eliminată: ### 7.1. Oprește accesul din backend Elimină `` din `.env` `ORACLE_SERVERS` (dacă a fost adăugat la pasul 3) și `./start-backend.sh restart`. `V_NOM_FIRME` nu va mai fi interogat pe hostul respectiv. ### 7.2. Revocă granturi (optional — vor dispărea cu DROP USER) ```sql -- Conectat ca CONTAFIN_ORACLE / DBA REVOKE ALL ON .PACK_AUTO FROM ROA_WEB; REVOKE ALL ON .AUTO_VMASINICLIENTI FROM ROA_WEB; REVOKE ALL ON .DEV_TIP_DEVIZ FROM ROA_WEB; REVOKE ALL ON .CALENDAR FROM ROA_WEB; REVOKE ALL ON .DEV_ORDL FROM ROA_WEB; REVOKE ALL ON .NOM_LUCRARI FROM ROA_WEB; REVOKE ALL ON .DEV_NOM_NORME FROM ROA_WEB; REVOKE ALL ON .DEV_NOM_INSPECTORI FROM ROA_WEB; REVOKE ALL ON .DEV_NOM_ASIGURATORI FROM ROA_WEB; REVOKE ALL ON .NOM_PARTENERI FROM ROA_WEB; REVOKE ALL ON .PACK_SERII_NUMERE FROM ROA_WEB; ``` ### 7.3. DROP schema ```sql -- IRREVERSIBIL. Asigură-te că ai backup (expdp) înainte. DROP USER CASCADE; ``` După `DROP USER CASCADE`, toate granturile acordate de `` dispar automat — §7.2 devine redundant, dar îl păstrăm pentru cazul în care vrei să dezactivezi temporar accesul fără a pierde date. ### 7.4. Rollback migrație specifică (selectiv) Migrațiile AUTO nu au script de `DOWN`. Pentru rollback de SP, redeployează versiunea anterioară din `git log docs/service-auto/migrations/`. Pentru rollback de coloană (`DEV_ORDL.id_sucursala`): ```sql BEGIN IF PACK_MIGRARE.COLUMNEXIST('DEV_ORDL','ID_SUCURSALA')=1 THEN EXECUTE IMMEDIATE 'ALTER TABLE DEV_ORDL DROP COLUMN id_sucursala'; END IF; END; / ``` Atenție — drop coloană **pierde date**. Folosește doar dacă schema e nouă și nu are date reale. --- ## Anexă — Legături utile - [Grants audit](grants-audit.md) — raționament securitate ROA_WEB, attack surface, scalabilitate. - [`onboarding_roa_web.sql`](onboarding_roa_web.sql) — scriptul de granturi per-schemă. - [`migrations/`](migrations/) — migrații AUTO idempotente, rulate per-schemă. - [`backend/ENV-SETUP.md`](../../backend/ENV-SETUP.md) — structura `.env` și `ORACLE_SERVERS`. - [`CLAUDE.md`](../../CLAUDE.md) — reguli `start.sh` / `start-backend.sh` / `status.sh`.