Backend: - GET /api/service-auto/comenzi cu paginare server-side, filtre dată/status - ComandaRequest.id_sucursala (Optional) + FirmaItem.id_mama - get_firme() expune id_mama din V_NOM_FIRME - callproc SP_CREEAZA_COMANDA_PROTOTIP cu 7 argumente (+ p_id_sucursala) - Cache TTL in-process: tip_deviz 24h, masini 5min Frontend: - ComenziBrowseView.vue — DataTable lazy + filtre + status badges - ComandaNoua.vue — company store integration, idSucursala computed - service-auto/stores/sharedStores.js (createCompaniesStore factory) - HamburgerMenu: secțiune Service Auto (Comenzi + Comandă Nouă) - router: /service-auto/comenzi SQL: - migrations/ff_2026_04_12_01_AUTO.sql — idempotent (COLUMNEXIST guard + CREATE OR REPLACE SP) - onboarding_roa_web.sql — versioned, parametrizat cu :SCHEMA_NAME - .claude/rules/oracle-migrations.md — convenție ff_YYYY_MM_DD_NN_MODULE.sql Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
8.6 KiB
Grants Audit — ROA_WEB on MARIUSM_AUTO
Date: 2026-04-11
Auditor: oracle-agent (team service-auto-sapt3)
Oracle target: 10.0.20.121:1521/ROA
Queries run as: CONTAFIN_ORACLE
1. Findings
1.1. ROA_WEB user — DOES NOT EXIST
| Source query | Result |
|---|---|
SELECT * FROM DBA_USERS WHERE USERNAME='ROA_WEB' |
0 rows |
SELECT * FROM DBA_TAB_PRIVS WHERE GRANTEE='ROA_WEB' |
0 rows |
SELECT * FROM DBA_SYS_PRIVS WHERE GRANTEE='ROA_WEB' |
0 rows |
SELECT * FROM DBA_ROLE_PRIVS WHERE GRANTEE='ROA_WEB' |
0 rows |
No Oracle user ROA_WEB exists on the ROA instance. All four privilege dictionaries
are empty for this grantee. Clean slate — no cleanup needed before creation.
1.2. Why CONTAFIN_ORACLE "just works" on MARIUSM_AUTO
USER_ROLE_PRIVS for CONTAFIN_ORACLE:
RESOURCE, CONNECT, IMP_FULL_DATABASE, DBA, EXP_FULL_DATABASE
CONTAFIN_ORACLE holds the DBA role, so it has SELECT/INSERT/UPDATE/DELETE/EXECUTE ANY TABLE/PROCEDURE. No explicit per-table grants are needed — that's why the Săpt 1
POC (poc/hello_oracle.py) and this audit script both queried MARIUSM_AUTO without
any explicit grant work.
Implication for prototype (Săpt 3): we can connect as CONTAFIN_ORACLE directly,
skip ROA_WEB entirely, and still validate hypotheses #1 (oracledb + OUT params) and
#2 (SP creation + call). Only hypothesis #3 (grant-scoped access via SP, read-only
SELECT rejected) requires the scoped ROA_WEB user and is therefore the only
reason to ask DBA for the create.
1.3. Required target objects — exist
| Object | Type | Status |
|---|---|---|
MARIUSM_AUTO.AUTO_VMASINICLIENTI |
VIEW | present |
MARIUSM_AUTO.DEV_TIP_DEVIZ |
TABLE | present |
MARIUSM_AUTO.SP_CREEAZA_COMANDA_PROTOTIP |
— | not yet created (task #3) |
2. Decision — Two-phase approach
Phase A — Săpt 3 (this week): use CONTAFIN_ORACLE
- No DBA request needed.
- Prototype backend module
service_autoconnects via the existingCONTAFIN_ORACLEcredentials (already inbackend/.env). - Proves hypotheses #1 + #2 (sync-facade + PL/SQL OUT params) end-to-end.
backend/.enventry for MARIUSM_AUTO (task #5) points to existing CONTAFIN_ORACLE user; only schema owner changes (MARIUSM_AUTOinstead of whichever the login uses for current companies).
Phase B — Săpt 4+ (after prototype): create ROA_WEB and migrate
Needed only to prove hypothesis #3 (grant-scoped access through SP while direct DML/SELECT is rejected). This requires DBA action.
3. Motivare securitate — de ce ROA_WEB cu SP-only
Oracle version (confirmat 2026-04-12): Oracle Database 21c Express Edition.
Schema-level grants (23ai+) nu sunt disponibile. Proxy auth (12c+) există dar anulează
beneficiul de securitate — vezi §4.
3.1. Attack surface comparison
| User conectare | SQL injection poate face | Attack surface |
|---|---|---|
CONTAFIN_ORACLE (DBA) |
SELECT/INSERT/DELETE pe orice tabelă, orice schemă | maxim |
ROA_WEB proxied ca schemă |
SELECT/INSERT/DELETE pe orice tabelă din schemă | mediu |
ROA_WEB cu EXECUTE-only pe SP |
doar apel SP cu parametri validați de SP | minim |
CONTAFIN_ORACLE conectat din web = punct slab critic: SQL injection prin parametrii
unui request HTTP poate exfiltra sau modifica date din orice schemă de pe server.
ROA_WEB cu EXECUTE-only: atacatorul poate cel mult apela SP-urile cu parametri
injectați. SP-urile Oracle sunt compilate, nu interpretate — parametrii sunt bind
variables, nu SQL concatenat. Suprafața de atac e redusă la logica validată din SP.
3.2. De ce nu proxy authentication
Proxy auth (ALTER USER MARIUSM_AUTO GRANT CONNECT THROUGH ROA_WEB) dă ROA_WEB
identitatea completă a schemei proxied → SELECT/INSERT direct pe orice tabelă din
acea schemă. Pierde exact beneficiul de securitate pentru care creăm ROA_WEB.
4. Arhitectura multi-tenant scalabilă (Oracle 21c)
4.1. Workflow firmă nouă
Firmele noi se creează via impdp dintr-o schemă template menținută la zi:
impdp system/... SCHEMAS=TEMPLATE_AUTO REMAP_SCHEMA=TEMPLATE_AUTO:FIRMA_NOUA ...
Schema nouă conține deja toate obiectele (SP-uri, view-uri, tabele) din template. Onboarding-ul ROA_WEB = 1 script rulat după impdp:
-- onboarding_roa_web.sql — rulat ca CONTAFIN_ORACLE după impdp pentru fiecare firmă nouă
-- Înlocuiește FIRMA_NOUA cu schema reală
GRANT EXECUTE ON FIRMA_NOUA.SP_CREEAZA_COMANDA_PROTOTIP TO ROA_WEB;
GRANT SELECT ON FIRMA_NOUA.AUTO_VMASINICLIENTI TO ROA_WEB;
GRANT SELECT ON FIRMA_NOUA.DEV_TIP_DEVIZ TO ROA_WEB;
GRANT SELECT ON FIRMA_NOUA.CALENDAR TO ROA_WEB;
-- CALENDAR: period selector AppHeader (shared/routes/calendar.py)
GRANT SELECT ON FIRMA_NOUA.DEV_ORDL TO ROA_WEB;
-- DEV_ORDL: GET /api/service-auto/comenzi (list comenzi)
GRANT SELECT ON FIRMA_NOUA.NOM_LUCRARI TO ROA_WEB;
-- NOM_LUCRARI: JOIN cu DEV_ORDL pentru nrord (get_comenzi)
-- adaugă orice alte SP/view-uri noi apărute de la ultimul onboarding
4.2. Workflow SP/obiect nou
Când un SP nou se adaugă în toate schemele (ca parte dintr-o migrare), scriptul de migrare are două componente:
Componenta 1 — migration_YYYYMMDD_sp_noua.sql — rulat per schemă (existent deja):
CREATE OR REPLACE PROCEDURE MARIUSM_AUTO.SP_NOUA (...) AS ...;
-- (repetat pentru fiecare schemă/firmă)
Componenta 2 — migration_YYYYMMDD_sp_noua_grants.sql — rulat O SINGURĂ DATĂ,
loopează automat toate schemele din V_NOM_FIRME:
-- Rulat ca CONTAFIN_ORACLE după ce migration_1 a rulat pe toate schemele
BEGIN
FOR firm IN (
SELECT DISTINCT schema
FROM contafin_oracle.v_nom_firme
WHERE schema IS NOT NULL
) LOOP
BEGIN
EXECUTE IMMEDIATE
'GRANT EXECUTE ON ' || firm.schema || '.SP_NOUA TO ROA_WEB';
EXCEPTION WHEN OTHERS THEN
NULL; -- skip dacă schema nu a primit încă migrarea SP (deployment order)
END;
END LOOP;
END;
/
V_NOM_FIRME e sursa de adevăr pentru toate schemele active — același tabel folosit
de backend pentru login JWT. Orice firmă adăugată în V_NOM_FIRME e inclusă automat
la următoarea migrare grants.
4.3. ROA_WEB creation script (one-time, DBA action)
-- Rulat O SINGURĂ DATĂ ca SYS sau CONTAFIN_ORACLE
CREATE USER ROA_WEB IDENTIFIED BY "<REPLACE_WITH_STRONG_PASSWORD_FROM_VAULT>";
GRANT CREATE SESSION TO ROA_WEB;
-- Fără alte privilegii sistem. Accesul la date = exclusiv prin granturi per-obiect.
4.4. Negative test — confirmă hypothesis #3 (scoped access)
-- Conectat ca ROA_WEB (NU CONTAFIN_ORACLE):
SELECT * FROM MARIUSM_AUTO.DEV_ORDL WHERE ROWNUM < 2; -- ORA-00942 așteptat
INSERT INTO MARIUSM_AUTO.DEV_ORDL (id_ordl, id_lucrare) VALUES (1, 1); -- ORA-00942 așteptat
-- SP call via bind vars — succes așteptat (ROLLBACK după verificare):
BEGIN
MARIUSM_AUTO.SP_CREEAZA_COMANDA_PROTOTIP(
p_id_tip => 1,
p_id_masiniclient => <existing_id>,
p_id_firma => 110,
p_solicitari => 'Test H3',
p_id_ordl => :o_id_ordl,
p_nrord => :o_nrord
);
END;
/
ROLLBACK;
4.5. Sumar scalabilitate
| Eveniment | Acțiune ROA_WEB | Cost |
|---|---|---|
| ROA_WEB creat (o dată) | CREATE USER + GRANT CREATE SESSION |
O dată |
Firmă nouă (impdp) |
onboarding_roa_web.sql cu schema nouă |
1 script per firmă |
| SP nou în toate schemele | migration_YYYYMMDD_sp_noua_grants.sql (loop V_NOM_FIRME) |
1 script per migrare |
| View/tabelă nouă expusă | același pattern ca SP | 1 script per migrare |
Expunere CALENDAR pentru period selector |
GRANT SELECT {SCHEMA}.CALENDAR TO ROA_WEB per schemă |
1 linie per schemă (parte din onboarding §4.1) |
Expunere DEV_ORDL + NOM_LUCRARI pentru GET /comenzi |
GRANT SELECT {SCHEMA}.DEV_ORDL/NOM_LUCRARI TO ROA_WEB per schemă |
2 linii per schemă (parte din onboarding §4.1) |
5. Action items
- Task #1 — Grants audit completat (2026-04-11)
- Task #3 —
SP_CREEAZA_COMANDA_PROTOTIPcreat + testat cu rollback (2026-04-11) - Task #5 —
mariusm_testentry înbackend/.envcu CONTAFIN_ORACLE (2026-04-11) - Săpt 4 (deferred, DBA action):
CREATE USER ROA_WEB+GRANT CREATE SESSION(§4.3)- Rulează
onboarding_roa_web.sqlpentru MARIUSM_AUTO (§4.1) - Switch
backend/secrets/mariusm_test.oracle_pass+ user → ROA_WEB în.env - Rulează
test_grants_integration.py→ 3 skipped trebuie să devină 3 passed - Rulează negative test din §4.4 manual (SQL Developer sau sqlplus)