Registrul Interdicțiilor — Platform Design & Generic Registry Plan
Acest conținut nu este încă disponibil în limba selectată.
This document accompanies interdictii_full.md (domain inventory) and interdictii.jdl
(authoritative entity shape). It contains:
- Diagrams — system context, component architecture, DB schema, lifecycle, activity, and sequence views of the current Interdicții registry.
- Generic Registry Platform plan — a reusable architecture for building any government registry (interdicții, permise, contracte, ONG-uri, sancțiuni, amenzi, etc.) on the same foundation.
Diagram labels use English structural terms and Romanian domain terms, mirroring the codebase convention.
1. System context
Section titled “1. System context”Where the registry sits among its actors and external systems.
flowchart TB subgraph Actors["Actori"] Operator["Operator registru<br/>(INSPECTOR / OPERATOR)"] Sef["Șef direcție<br/>(SEF_DIRECTIE)"] Auditor["Auditor"] Admin["Administrator"] Public["Public / persoană vizată"] ExternalGov["Sistem extern govtech<br/>(API consumer)"] end
subgraph System["Registrul Interdicțiilor (SaaS)"] Portal["Portal web<br/>(Angular SPA)"] API["REST API<br/>(Spring Boot)"] PublicAPI["API public de consultare<br/>(read-only)"] end
subgraph External["Sisteme externe"] MConnect["MConnect / interop"] ANAF["Registre persoane juridice<br/>(ANAF / IDNO)"] CivilReg["Registru de stat al populației<br/>(IDNP)"] Mail["SMTP / notificări"] end
Operator -->|CRUD interdicții| Portal Sef -->|aprobare| Portal Auditor -->|consultare + audit log| Portal Admin -->|users, autorități| Portal Public -->|consultare după IDNP/IDNO| PublicAPI ExternalGov -->|verificare automată| PublicAPI
Portal --> API API <-->|verificare identitate| CivilReg API <-->|verificare companie| ANAF API --> Mail API <-->|federație identități / SSO| MConnect2. Component / architecture view
Section titled “2. Component / architecture view”The technical layering of the deployable monolith — Angular SPA in the browser, Spring Boot serving REST + static assets, with PostgreSQL / Elasticsearch / Cache as backing stores.
flowchart LR subgraph Browser["Browser"] SPA["Angular 19 SPA<br/>standalone components"] end
subgraph Backend["Spring Boot 3 monolith<br/>(md.gov.interdictii)"] direction TB Sec["SecurityFilterChain<br/>+ JWT filter"] Rest["web.rest.*Resource<br/>(controllers)"] Svc["service.*Service<br/>+ impl/"] QSvc["service.*QueryService<br/>(JPA Criteria)"] Map["service.mapper<br/>(MapStruct)"] Dto["service.dto"] Repo["repository.*Repository<br/>(Spring Data JPA)"] SRepo["repository.search<br/>(Spring Data Elasticsearch)"] Dom["domain.*<br/>(JPA entities)"] Audit["AbstractAuditingEntity<br/>+ SpringSecurityAuditorAware"] Liq["Liquibase changelogs"] end
subgraph Stores["Stores"] PG[("PostgreSQL<br/>(prod) / H2 (dev)")] ES[("Elasticsearch<br/>(Interdictie, Entitate)")] Cache[("Ehcache + Hibernate L2")] end
Mail["SMTP"]
SPA -- HTTPS + JWT --> Sec Sec --> Rest Rest --> Svc Svc --> QSvc Svc --> Map Map --> Dto Svc --> Repo Svc --> SRepo Repo --> Dom SRepo --> Dom Dom --> Audit Repo --> Cache Repo --> PG SRepo --> ES Liq -. migrations .-> PG Svc --> MailKey conventions:
- Controllers exchange DTOs with the outside world; entities never leave the service layer.
*QueryService+*Criteriaprovide URL-driven filtering on the four filterable entities (Interdictie,Entitate,Act,AutoritateEmitenta).- Only
InterdictieandEntitateare mirrored to Elasticsearch. AbstractAuditingEntitypopulatescreatedBy / createdDate / lastModifiedBy / lastModifiedDateautomatically via the JPA auditor.
3. Database schema
Section titled “3. Database schema”3.1 Current schema (mirrors interdictii.jdl)
Section titled “3.1 Current schema (mirrors interdictii.jdl)”erDiagram INTERDICTIE { bigint id PK varchar statut "StatutInterdictie" varchar stare "StareInterdictie" date start_date date end_date clob description varchar categorie_jurisdictie "CategorieJurisdictie" varchar categorie_domeniu "CategorieDomeniu" bigint entitate_id FK bigint act_id FK bigint autoritate_id FK varchar created_by timestamp created_date varchar last_modified_by timestamp last_modified_date }
ENTITATE { bigint id PK varchar nume varchar functie date start_date_functie varchar idnp_idno "IDNP(13) / IDNO(13)" varchar tip "FIZICA | JURIDICA" }
APP_USER { bigint id PK varchar username UK varchar password varchar statut "StatutUser" varchar rol "RolUser" }
AUTORITATE_EMITENTA { bigint id PK varchar name }
RIDICARE_INTERDICTIE { bigint id PK clob description bigint interdictie_id FK "OneToOne" bigint act_id FK bigint autoritate_id FK }
ACT { bigint id PK date start_date date end_date varchar name clob description }
JHI_USER { bigint id PK varchar login UK varchar password_hash varchar email boolean activated }
JHI_AUTHORITY { varchar name PK "ROLE_*" }
INTERDICTIE ||--o{ ENTITATE : "vizează" INTERDICTIE }o--|| AUTORITATE_EMITENTA : "emisă de" INTERDICTIE }o--o| ACT : "în baza" RIDICARE_INTERDICTIE ||--|| INTERDICTIE : "ridică (1:1)" RIDICARE_INTERDICTIE }o--o| ACT : "în baza" RIDICARE_INTERDICTIE }o--o| AUTORITATE_EMITENTA : "emisă de" JHI_USER ||--o{ JHI_AUTHORITY : "are"Notă:
JHI_USER/JHI_AUTHORITYsunt entitățile JHipster built-in pentru autentificare/roluri (Spring Security).APP_USEReste entitatea de domeniu distinctă (operator registru), păstrată separat deliberat — veziCLAUDE.md.
3.2 Extended schema (target — derivat din interdictii_full.md)
Section titled “3.2 Extended schema (target — derivat din interdictii_full.md)”The full domain doc lists 9 entity categories (PF, PJ, administratori, funcționari, străini, mărfuri, arme, vehicule, active financiare/tranzacții), 10 lifecycle statuses, 4 authority families, and 4 classification axes (jurisdicție, domeniu, durată, intensitate). The current v0 shape collapses these; the extended target below covers totul, inclusiv interdicții pe bunuri și pe tranzacții (cu scope: limite valorice, contraparte, geo).
Trei concepte noi față de v0:
ENTITATEpolimorfic acoperă toate cele 9 categorii (vezi §3.3 pentru mapping detaliat).ACTIUNE_INTERZISA— acțiunea/operațiunea blocată (IMPORT, TRANZACTIONARE, CIRCULATIE, PORT_ARMA, …). O interdicție poate bloca mai multe acțiuni pe același entitate, fiecare cu scope propriu (de ex. „tranzacții > 50.000 MDL către contraparte din jurisdicție Y”).DOMENIU_APLICARE(jsonb peACTIUNE_INTERZISA) — predicate de scope: limite valorice, geografie, contraparte, ferestre temporale, canale.
erDiagram ENTITATE { bigint id PK varchar categorie "PF|PJ|ADMIN|FUNCTIONAR_PUBLIC|STRAIN|MARFA|ARMA|VEHICUL|ACTIV_FINANCIAR" varchar identificator "IDNP|IDNO|VIN|IBAN|serie_arma|cod_tarifar|..." varchar nume_afisat jsonb atribute "schema per categorie - vezi 3.3" } INTERDICTIE { bigint id PK bigint entitate_id FK bigint autoritate_id FK varchar statut "vezi sectiunea 4 - 10 stari" varchar stare varchar jurisdictie "NATIONALA|LOCALA|REGIONALA|INTERNATIONALA|TRANSFRONTALIERA" varchar domeniu "ADMIN|PENAL|FISCAL|VAMAL|MEDIU|SECURITATE|MIGRATIONAL|ECONOMIC" varchar durata "TEMPORARA|PERMANENTA|CONDITIONATA|PANA_LA_EXECUTARE" varchar intensitate "TOTALA|PARTIALA|CONDITIONATA|PROGRESIVA" date start_date date end_date bigint temei_legal_id FK bigint conditie_id FK "doar daca durata=CONDITIONATA" text description } ACTIUNE_INTERZISA { bigint id PK bigint interdictie_id FK varchar actiune "IMPORT|EXPORT|CIRCULATIE|TRANZACTIONARE|PORT_ARMA|EXERCITARE_FUNCTIE|IESIRE_TARA|..." jsonb scope "limite valori, geografie, contraparte, fereastra temporala, canale" varchar intensitate "TOTALA|PARTIALA - per actiune, poate diferi de cea a interdictiei" } CONDITIE { bigint id PK varchar tip "EVENIMENT|INDEPLINIRE_OBLIGATIE|DECIZIE_AUTORITATE|PRAG_TEMPORAL" text descriere boolean indeplinita timestamp data_indeplinire bigint act_indeplinire_id FK } TEMEI_LEGAL { bigint id PK varchar act_normativ "Cod Penal|Cod Contraventional|Legea privind sanctiunile|..." varchar articol varchar alineat } INTERDICTIE_ACT { bigint interdictie_id FK bigint act_id FK varchar rol "EMITERE|MODIFICARE|RIDICARE|REVOCARE|CONTESTARE|PRELUNGIRE|EXECUTARE" date data_atasare } ACT { bigint id PK varchar tip "HOTARARE|DECIZIE|PROCES_VERBAL|ORDIN|SENTINTA|..." varchar numar date data varchar storage_uri "S3/MinIO" varchar hash_sha256 varchar signature "MSign" } AUTORITATE_EMITENTA { bigint id PK varchar nume varchar familie "JUDICIARA|ADMINISTRATIVA|CONTROL|SPECIALA" varchar nivel "CENTRALA|TERITORIALA" varchar cod_idno } EVENIMENT_INTERDICTIE { bigint id PK bigint interdictie_id FK varchar tip "CREATA|APROBATA|SUSPENDATA|REACTIVATA|CONTESTATA|REVOCATA|RIDICATA|EXPIRATA|EXECUTATA|PRELUNGITA|CONDITIE_INDEPLINITA" varchar actor "user login" timestamp data jsonb payload } NOTIFICARE { bigint id PK bigint interdictie_id FK varchar canal "EMAIL|MCONNECT|SMS|WEBHOOK" varchar destinatar varchar status timestamp sent_at }
ENTITATE ||--o{ INTERDICTIE : "vizat de" AUTORITATE_EMITENTA ||--o{ INTERDICTIE : "emite" TEMEI_LEGAL ||--o{ INTERDICTIE : "fundamenteaza" INTERDICTIE ||--o{ ACTIUNE_INTERZISA : "blocheaza" INTERDICTIE }o--o| CONDITIE : "asteapta" INTERDICTIE ||--o{ INTERDICTIE_ACT : "" ACT ||--o{ INTERDICTIE_ACT : "" INTERDICTIE ||--o{ EVENIMENT_INTERDICTIE : "event log" INTERDICTIE ||--o{ NOTIFICARE : ""3.3 Acoperire completă a entităților (mapping cu interdictii_full.md §1)
Section titled “3.3 Acoperire completă a entităților (mapping cu interdictii_full.md §1)”Toate cele 9 categorii din documentul de domeniu sunt acoperite. Tabelul de mai
jos arată cum se concretizează ENTITATE.atribute și ce acțiuni (actiune în
ACTIUNE_INTERZISA) sunt tipice per categorie.
| Categorie entitate (§1.x) | categorie | identificator | atribute (jsonb) | Acțiuni tipice în ACTIUNE_INTERZISA |
|---|---|---|---|---|
| 1.1 Persoană fizică (civil) | PF | IDNP (13) | nume, prenume, data_nasterii | IESIRE_TARA, EXERCITARE_PROFESIE, DETINERE_ARMA, ACCES_PERIMETRU, PARTICIPARE_PUBLICA |
| 1.2 Persoană juridică | PJ | IDNO (13) | denumire, forma_org (SRL/SA/ONG/IS), caen | DESFASURARE_ACTIVITATE, ACHIZITII_PUBLICE, IMPORT, EXPORT, ADMINISTRARE, SUSPENDARE_LICENTA |
| 1.3 Administrator / fondator | ADMIN | IDNP | functie, pj_administrata_idno | OCUPARE_FUNCTIE_CONDUCERE, ADMINISTRARE_PJ |
| 1.4 Funcționar public / demnitar | FUNCTIONAR_PUBLIC | IDNP | functie, institutie, nivel | EXERCITARE_FUNCTIE, ACCES_FUNCTIE_PUBLICA, INCOMPATIBILITATE |
| 1.5 Străin / apatrid | STRAIN | nr. pașaport / id document | cetatenie, alias[], data_nasterii | INTRARE_RM, SEDERE_RM, REINTOARCERE (după expulzare) |
| 1.6 Mărfuri / bunuri | MARFA | cod tarifar / nr. lot | denumire, categorie (arme/medicamente/sub_periculoase/bunuri_culturale/contrafacute), cantitate, um | IMPORT, EXPORT, CIRCULATIE, COMERCIALIZARE, CONFISCARE |
| 1.7 Arme / muniții | ARMA | serie armă | tip, calibru, producator | PROCURARE, PORT_ARMA, FOLOSIRE, COMERCIALIZARE, RETRAGERE_PERMIS |
| 1.8 Vehicul / mijloc transport | VEHICUL | VIN + nr. înmatriculare | marca, model, an, categorie | CIRCULATIE, INMATRICULARE, EXPLOATARE, SECHESTRU |
| 1.9 Activ financiar / cont | ACTIV_FINANCIAR | IBAN / nr. cont / cod activ | banca, titular_idnp_idno, moneda | TRANZACTIONARE, RETRAGERE, TRANSFER, DEPUNERE, BLOCARE_CONT, INDISPONIBILIZARE, SECHESTRU |
Exemple concrete de ACTIUNE_INTERZISA.scope
Section titled “Exemple concrete de ACTIUNE_INTERZISA.scope”Scope-ul permite condiționarea acțiunii blocate — esențial pentru interdicții pe tranzacții și bunuri unde rar se blochează „totul”:
// 1.9 - blocare tranzacții peste prag, către o anumită jurisdicție{ "actiune": "TRANZACTIONARE", "scope": { "suma_min_mdl": 50000, "directie": "OUTGOING", "contraparte_jurisdictie": ["RU","BY"], "canale": ["SWIFT","SEPA"] } }
// 1.6 - import interzis dintr-o țară, pentru o categorie de marfă{ "actiune": "IMPORT", "scope": { "tara_origine": ["RU"], "cod_tarifar_prefix": ["2710"], "valabil_intre": ["2026-01-01","2026-12-31"] } }
// 1.8 - circulație restrânsă geografic și temporal{ "actiune": "CIRCULATIE", "scope": { "zona": "mun. Chisinau, sector Centru", "interval_orar": "07:00-22:00", "exceptie": "regim de urgenta medicala" } }
// 1.1 - interdicție parțială de exercitare a profesiei{ "actiune": "EXERCITARE_PROFESIE", "scope": { "profesie": "avocat", "domeniu": "drept penal", "instanta_exceptie": [] } }Taxonomia entităților
Section titled “Taxonomia entităților”flowchart TB ENTITATE[("ENTITATE<br/>polimorfic")]
ENTITATE --> Persoane["Persoane"] ENTITATE --> Bunuri["Bunuri / obiecte"] ENTITATE --> Active["Active financiare"]
Persoane --> PF["PF — civil<br/>IDNP"] Persoane --> PJ["PJ — SRL/SA/ONG/IS<br/>IDNO"] Persoane --> ADMIN["ADMIN — fondator/conducător<br/>IDNP + ref PJ"] Persoane --> FUNCT["FUNCTIONAR_PUBLIC<br/>IDNP + funcție"] Persoane --> STRAIN["STRAIN / apatrid<br/>pașaport"]
Bunuri --> MARFA["MARFA — bunuri / mărfuri<br/>cod tarifar / lot"] Bunuri --> ARMA["ARMA — armă / muniție<br/>serie armă"] Bunuri --> VEHICUL["VEHICUL<br/>VIN + nr. înmatriculare"]
Active --> CONT["ACTIV_FINANCIAR<br/>IBAN / nr. cont"]
PF -.acțiuni.-> AP1["IESIRE_TARA, EXERCITARE_PROFESIE,<br/>DETINERE_ARMA, ACCES_PERIMETRU"] PJ -.acțiuni.-> AP2["DESFASURARE_ACTIVITATE,<br/>ACHIZITII_PUBLICE, IMPORT, EXPORT"] MARFA -.acțiuni.-> AP3["IMPORT, EXPORT, CIRCULATIE,<br/>COMERCIALIZARE, CONFISCARE"] ARMA -.acțiuni.-> AP4["PROCURARE, PORT_ARMA,<br/>FOLOSIRE, COMERCIALIZARE"] VEHICUL -.acțiuni.-> AP5["CIRCULATIE, INMATRICULARE,<br/>EXPLOATARE, SECHESTRU"] CONT -.acțiuni.-> AP6["TRANZACTIONARE, TRANSFER,<br/>BLOCARE_CONT, SECHESTRU"]Note de implementare
Section titled “Note de implementare”- Identificatori unici per categorie: index parțial pe
(categorie, identificator)în PostgreSQL —IDNPse poate repeta întrePFșiADMIN(aceeași persoană în roluri diferite), dar nu în interiorul unei categorii. - Validare structurală a
atribute:JSON Schemaper categorie, stocat în cod (resource files) sau într-o tabelăENTITATE_SCHEMA(Pattern C — multi-tenant). - Acțiuni vs. intensitate vs. domeniu: domeniul (§4.2) este clasificarea juridică; acțiunea interzisă este operațiunea concretă blocată. O singură interdicție domeniu=FISCAL pe un cont poate avea două acțiuni: BLOCARE_CONT (totală) și TRANZACTIONARE cu scope=„retrageri > 10k MDL”.
- Entitate compusă (cazuri rare — de ex. „administratorul X interzis să
conducă PJ Y”): modelat ca două entități + două
ACTIUNE_INTERZISAlegate prin scope ce referențiază entitatea parteneră.
4. Lifecycle — state diagram
Section titled “4. Lifecycle — state diagram”Toate cele 10 statuturi din interdictii_full.md §2 (Draft, Activă,
Suspendată, Contestată, Anulată, Revocată, Expirată, Executată, Prelungită,
Condiționată) sunt modelate explicit. statut în JDL rămâne pentru clasificarea
administrativă; diagrama de mai jos modelează stare (ciclul de viață
operațional).
Semantica distincțiilor subtile:
- ANULATĂ vs REVOCATĂ — ambele termină interdicția, dar: Anulată = desființată definitiv de o autoritate superioară (ex. instanță superioară admite contestația). Revocată = retrasă voluntar de emitent.
- RIDICATĂ vs EXECUTATĂ — Ridicată = încetare prin act dedicat
(
RidicareInterdictie). Executată = efectele „do X” au fost realizate (ex. confiscare finalizată, expulzare efectuată). - CONDIȚIONATĂ = pre-activă, așteptând îndeplinirea unei condiții
(
Conditie.indeplinita = true); când condiția se îndeplinește → ACTIV. - PRELUNGITĂ este o stare tranzitorie în care se procesează actul de
prelungire; după înregistrare se întoarce la ACTIV cu
end_dateextins.
stateDiagram-v2 [*] --> DRAFT: creată (OPERATOR)
DRAFT --> CONDITIONATA: aprobată + durata=CONDITIONATA DRAFT --> ACTIV: aprobată (SEF_DIRECTIE) DRAFT --> ANULAT: respinsă în draft
CONDITIONATA --> ACTIV: condiție îndeplinită CONDITIONATA --> ANULAT: condiție imposibilă / decăzută
ACTIV --> SUSPENDAT: suspendare temporară SUSPENDAT --> ACTIV: reactivare SUSPENDAT --> REVOCATA: retragere în timpul suspendării
ACTIV --> CONTESTATA: contestație depusă CONTESTATA --> ACTIV: contestație respinsă CONTESTATA --> ANULAT: contestație admisă<br/>(autoritate superioară)
ACTIV --> RIDICATA: act de ridicare emis<br/>(RidicareInterdictie) ACTIV --> REVOCATA: retrasă de emitent ACTIV --> EXPIRAT: end_date atins<br/>(scheduled job) ACTIV --> EXECUTATA: efecte realizate<br/>(ex. confiscare finalizată) ACTIV --> PRELUNGITA: cerere de prelungire PRELUNGITA --> ACTIV: prelungire înregistrată<br/>(end_date extins) PRELUNGITA --> EXPIRAT: prelungire respinsă + end_date trecut
RIDICATA --> [*] REVOCATA --> [*] EXPIRAT --> [*] EXECUTATA --> [*] ANULAT --> [*]
note right of EXPIRAT Tranziție automată prin scheduled job (Spring @Scheduled) end note
note right of ACTIV Singura stare în care interdicția produce efecte juridice publice (alături de SUSPENDAT pentru istoric). end note
note left of CONDITIONATA Vezi entitatea CONDITIE din §3.2 — eveniment, obligație, decizie. end noteTabel matrice tranziții → eveniment emis (alimentează EVENIMENT_INTERDICTIE):
| De la → la | Eveniment | Trigger | Actor |
|---|---|---|---|
| ∅ → DRAFT | CREATA | manual | OPERATOR |
| DRAFT → ACTIV | APROBATA | manual | SEF_DIRECTIE |
| DRAFT → CONDITIONATA | APROBATA | manual | SEF_DIRECTIE |
| CONDITIONATA → ACTIV | CONDITIE_INDEPLINITA | manual sau job | sistem/OPERATOR |
| ACTIV → SUSPENDAT | SUSPENDATA | manual | autoritate |
| SUSPENDAT → ACTIV | REACTIVATA | manual | autoritate |
| ACTIV → CONTESTATA | CONTESTATA | manual | OPERATOR / entitate |
| ACTIV → REVOCATA | REVOCATA | manual | emitent |
| ACTIV → RIDICATA | RIDICATA | manual | OPERATOR (+ RidicareInterdictie) |
| ACTIV → EXECUTATA | EXECUTATA | manual | OPERATOR |
| ACTIV → PRELUNGITA | PRELUNGIRE_CERUTA | manual | OPERATOR |
| PRELUNGITA → ACTIV | PRELUNGITA | manual | SEF_DIRECTIE |
| ACTIV → EXPIRAT | EXPIRATA | automat | sistem (@Scheduled) |
| oricare → ANULAT | ANULATA | manual | autoritate superioară |
5. Activity diagrams
Section titled “5. Activity diagrams”5.1 Creare interdicție (cu aprobare)
Section titled “5.1 Creare interdicție (cu aprobare)”flowchart TD Start([Operator inițiază]) --> SearchSubj{Entitate<br/>existent?} SearchSubj -- Nu --> CreateSubj[Creează Entitate / Entitate<br/>+ verifică IDNP/IDNO] SearchSubj -- Da --> SelectSubj[Selectează din listă] CreateSubj --> FillForm SelectSubj --> FillForm[Completează formular interdicție<br/>statut, stare=DRAFT, jurisdicție, domeniu,<br/>start/end date, temei legal] FillForm --> AttachAct[Atașează Act/acte<br/>upload PDF / referință] AttachAct --> SelectAuth[Selectează AutoritateEmitenta] SelectAuth --> Save[Save → POST /api/interdictii] Save --> Validate{Validare<br/>backend?} Validate -- Eșec --> ShowErr[Afișează erori validare] --> FillForm Validate -- OK --> Persist[Persistă în DB<br/>stare=DRAFT] Persist --> Index[Indexează în Elasticsearch] Index --> NotifySef[Notifică SEF_DIRECTIE pentru aprobare] NotifySef --> Review{Aprobare?} Review -- Aprobă --> Activate[stare=ACTIV<br/>EVENIMENT: APROBATA] Review -- Respinge --> Reject[stare=ANULAT<br/>EVENIMENT: ANULATA] Activate --> NotifySubj[Notifică entitatea<br/>+ publish în registru public] NotifySubj --> End([Final]) Reject --> End5.2 Ridicare interdicție
Section titled “5.2 Ridicare interdicție”flowchart TD Start([Cerere de ridicare]) --> LookupInt[Caută interdicție<br/>după ID / IDNP-IDNO] LookupInt --> Check{stare = ACTIV?} Check -- Nu --> Reject1[Refuz: doar interdicții active<br/>pot fi ridicate] Check -- Da --> AttachAct[Atașează act de ridicare<br/>hotărâre / decizie] AttachAct --> SelectAuth[Autoritate care ridică] SelectAuth --> SaveRid[POST /api/ridicari-interdictie<br/>OneToOne cu Interdictie] SaveRid --> UpdateState[UPDATE interdictie<br/>SET stare=RIDICATA] UpdateState --> Event[INSERT EVENIMENT_INTERDICTIE<br/>tip=RIDICATA] Event --> Reindex[Re-indexare Elasticsearch] Reindex --> Notify[Notifică entitate + audit trail] Notify --> End([Final]) Reject1 --> End5.3 Consultare publică
Section titled “5.3 Consultare publică”flowchart TD Start([Public/sistem extern]) --> Input[Introduce IDNP / IDNO / nume] Input --> RateLimit{Rate<br/>limit OK?} RateLimit -- Nu --> Block[HTTP 429] RateLimit -- Da --> Query[GET /api/public/interdictii/_search<br/>?entitate=...] Query --> Filter[Filtru server-side:<br/>doar stare ACTIV / SUSPENDAT] Filter --> Found{Rezultate?} Found -- Nu --> Empty[200 OK<br/>fără înregistrări] Found -- Da --> Mask[Maschează câmpuri sensibile<br/>conform GDPR] Mask --> Return[200 OK + listă] Return --> AuditPub[Log consultare<br/>audit] Empty --> AuditPub AuditPub --> End([Final]) Block --> End6. Sequence diagrams
Section titled “6. Sequence diagrams”6.1 Operator creează o interdicție
Section titled “6.1 Operator creează o interdicție”sequenceDiagram autonumber actor Op as Operator participant SPA as Angular SPA participant API as InterdictieResource participant Svc as InterdictieServiceImpl participant Map as InterdictieMapper participant Repo as InterdictieRepository participant SRepo as InterdictieSearchRepository participant DB as PostgreSQL participant ES as Elasticsearch
Op->>SPA: completează formular SPA->>API: POST /api/interdictii (DTO + JWT) API->>API: @PreAuthorize ROLE_USER API->>Svc: save(dto) Svc->>Map: toEntity(dto) Map-->>Svc: Interdictie Svc->>Repo: save(entity) Repo->>DB: INSERT + AbstractAuditingEntity populates<br/>created_by / created_date DB-->>Repo: row(id) Repo-->>Svc: persisted entity Svc->>SRepo: index(entity) SRepo->>ES: PUT /interdictie/_doc/{id} Svc->>Map: toDto(entity) Map-->>Svc: dto Svc-->>API: dto API-->>SPA: 201 Created + Location header SPA-->>Op: confirmare + redirect detalii6.2 Aprobare de către șeful de direcție
Section titled “6.2 Aprobare de către șeful de direcție”sequenceDiagram autonumber actor Sef as Sef direcție participant SPA participant API as InterdictieResource participant Svc as InterdictieServiceImpl participant Repo participant Ev as EvenimentService participant Mail as MailService
Sef->>SPA: deschide lista DRAFT SPA->>API: GET /api/interdictii?stare.equals=DRAFT API->>Svc: findByCriteria Svc-->>SPA: page<DTO> Sef->>SPA: click "Aprobă" SPA->>API: PATCH /api/interdictii/{id}/aproba API->>Svc: aproba(id) Svc->>Repo: findById(id) Repo-->>Svc: entity (stare=DRAFT) Svc->>Svc: validate state transition Svc->>Repo: save (stare=ACTIV) Svc->>Ev: emit(APROBATA, actor=sef) Ev->>Repo: INSERT EVENIMENT_INTERDICTIE Svc->>Mail: sendApprovalNotice(entitate) Svc-->>API: dto API-->>SPA: 200 OK6.3 Consultare publică (sistem extern)
Section titled “6.3 Consultare publică (sistem extern)”sequenceDiagram autonumber participant Ext as Sistem extern (e.g. bancă) participant Gw as API Gateway / rate limit participant API as PublicInterdictieResource participant Svc participant SRepo as InterdictieSearchRepository participant ES participant Audit as AuditLog
Ext->>Gw: GET /public/api/interdictii?idnp=2002004001234<br/>+ API key Gw->>Gw: rate limit + API key valid Gw->>API: forward API->>Svc: searchActive(idnp) Svc->>SRepo: search({stare: ACTIV, entitate.idnp: ...}) SRepo->>ES: GET /interdictie/_search ES-->>SRepo: hits SRepo-->>Svc: list Svc->>Svc: applyPublicMask (drop fields) Svc->>Audit: log(consultare, idnp, api_key_owner) Svc-->>API: dto[] API-->>Gw: 200 OK Gw-->>Ext: JSON response6.4 Ridicare interdicție
Section titled “6.4 Ridicare interdicție”sequenceDiagram autonumber actor Op as Operator participant SPA participant RidAPI as RidicareInterdictieResource participant IntAPI as InterdictieResource (internal) participant Svc as RidicareInterdictieServiceImpl participant IntSvc as InterdictieServiceImpl participant Repo participant SRepo participant Ev as EvenimentService
Op->>SPA: formular ridicare<br/>(interdictieId, act, autoritate) SPA->>RidAPI: POST /api/ridicari-interdictie RidAPI->>Svc: save(dto) Svc->>Repo: findInterdictie(id) Repo-->>Svc: interdictie (stare=ACTIV) Svc->>Svc: assert(stare == ACTIV) Svc->>Repo: INSERT RidicareInterdictie (OneToOne) Svc->>IntSvc: markRidicata(interdictieId) IntSvc->>Repo: UPDATE stare=RIDICATA IntSvc->>SRepo: re-index IntSvc->>Ev: emit(RIDICATA) Svc-->>RidAPI: dto RidAPI-->>SPA: 201 Created6.5 Login JWT
Section titled “6.5 Login JWT”sequenceDiagram autonumber actor U as Utilizator participant SPA participant Auth as AuthenticateController participant SM as SecurityManager participant UDS as DomainUserDetailsService participant DB
U->>SPA: login (username, password) SPA->>Auth: POST /api/authenticate Auth->>SM: authenticate(token) SM->>UDS: loadUserByUsername UDS->>DB: SELECT FROM jhi_user DB-->>UDS: user + authorities UDS-->>SM: UserDetails SM->>SM: bcrypt verify SM-->>Auth: Authentication ok Auth->>Auth: generate JWT (HS512) Auth-->>SPA: 200 { id_token } SPA->>SPA: store JWT Note over SPA,Auth: subsequent requests carry<br/>Authorization: Bearer <jwt>7. Generic Registry Platform — Plan
Section titled “7. Generic Registry Platform — Plan”Goal: turn the Interdicții implementation into a reusable foundation (Registry-as-a-Service) on which other registries — permise, sancțiuni, contracte, ONG-uri, mediatori, experți judiciari, amenzi etc. — can be launched without rewriting the stack each time.
7.1 Core abstraction
Section titled “7.1 Core abstraction”Every registry of this shape collapses to the same primitives:
| Primitive | Rol | Exemplu în Interdicții | Exemplu în Permise auto |
|---|---|---|---|
| Entity (polimorfic) | Entitatea vizată — persoană, bun, activ | PF/PJ/marfă/armă/vehicul/cont (§3.3) | Conducător auto + Vehicul |
| Record | Înregistrarea de registru cu ciclu de viață | Interdictie | Permis |
| Restricted Action | Acțiunea/operațiunea blocată + scope | IMPORT, TRANZACTIONARE, IESIRE_TARA + scope (sume, geo, contraparte) | — (permise nu sunt restrictive) |
| Issuing Authority | Cine emite | AutoritateEmitenta (judiciară/administrativă/control/specială) | IGP / ASP |
| Legal Basis | Temeiul juridic | Cod Penal / Contravențional / sancțiuni internaționale | Cod Rutier art. Y |
| Supporting Act | Document justificativ | Hotărâre / Decizie / Proces-verbal | Examen + dosar medical |
| Condition | Eveniment/obligație de care depinde efectul | Conditie (pentru durata=CONDITIONATA) | Recuperare puncte |
| Lifecycle Event | Tranziție de stare (append-only) | EVENIMENT_INTERDICTIE (vezi matricea §4) | EVENIMENT_PERMIS |
| Lifting / Closure | Act care încheie | RidicareInterdictie / REVOCARE / EXECUTARE | Retragere permis |
| Consultation API | Acces public/sistem extern (cu mascare GDPR) | /public/api/interdictii?idnp=... | /public/api/permise |
| Audit Trail | Cine, ce, când, de ce | EVENIMENT_INTERDICTIE + AbstractAuditingEntity | idem |
| Notifications | Canal multi-protocol către entitate/sisteme | EMAIL / MCONNECT / SMS / WEBHOOK | idem |
Orice registru nou = configurarea acestor primitive + schema specifică entității (taxonomia categoriilor) + dicționarul de acțiuni interzise.
7.2 Capability map
Section titled “7.2 Capability map”flowchart LR subgraph Core["Registry Platform Core"] IAM["Identity & Access<br/>(JWT + SSO + RBAC)"] Tenancy["Multi-tenant<br/>(registru = tenant)"] Schema["Schema Engine<br/>(definire record + entitate via DSL)"] WF["Workflow Engine<br/>(state machine + aprobări)"] Doc["Document Storage<br/>(S3/MinIO + hash + semnătură)"] Audit["Audit & Event Store<br/>(append-only)"] Search["Search<br/>(Elasticsearch + index per tenant)"] Notif["Notifications<br/>(email / SMS / MConnect)"] Pub["Public Consultation API<br/>(rate limit + masking)"] Reports["Reporting & Analytics"] Interop["Govtech Interop<br/>(MConnect, ANAF, RSP)"] end
subgraph Registries["Registries (tenants)"] R1[Registrul Interdicțiilor] R2[Registrul Permiselor] R3[Registrul Sancțiunilor] R4[Registrul ONG-urilor] R5[...] end
R1 --> IAM & Tenancy & Schema & WF & Doc & Audit & Search & Notif & Pub & Reports & Interop R2 --> Schema & WF & Audit & Search & Notif R3 --> Schema & WF & Audit & Search & Notif R4 --> Schema & WF & Audit & Search & Notif7.3 Generalization strategy
Section titled “7.3 Generalization strategy”Three pragmatic patterns to make the codebase reusable, ordered from simplest to most flexible:
Pattern A — Template repo (cel mai rapid)
- Codebază JHipster template + checklist.
- Pentru fiecare registru nou: fork, înlocuiește JDL, regenerează, rebrand i18n.
- Pro: zero infra în plus, ușor de înțeles. Contra: divergență între forkuri.
Pattern B — Library + JDL conventions (recomandat pentru 3–10 registre)
- Extrage într-o librărie Maven (
gov-registry-commons) capabilities comune: audit trail, event store, public consultation skeleton, workflow base classes, document storage adapter, public API masking, rate limiter. - Fiecare registru rămâne aplicație JHipster separată dar depinde de librărie.
- JDL convention: orice registru declară un entity
Record, un entityEntitate, enumeriStatut/Stare, relații standard cuAuthorityșiAct.
Pattern C — Multi-tenant SaaS platform (long-term, 10+ registre)
- Single deployment, mai mulți tenanți.
- Schema engine bazată pe JSONB + descriptors: fiecare record are
(tenant_id, type, payload jsonb); descriptorul defines câmpuri, validări, workflow. - Workflow as data: state machine + tranziții stocate în DB, nu hardcoded.
- Pro: un cod, multi-livrabil. Contra: complexitate substanțială, performanță Elasticsearch per tenant trebuie gândită, custom UI per registru e mai greu.
Recomandare: începe cu A, evoluează la B după al doilea registru. Treci la C doar dacă apare claritate că vor fi >10 registre cu cerințe foarte similare.
7.4 Multi-tenant model (Pattern C, doar dacă se ajunge acolo)
Section titled “7.4 Multi-tenant model (Pattern C, doar dacă se ajunge acolo)”erDiagram TENANT { uuid id PK varchar slug "interdictii | permise | sanctiuni" varchar nume jsonb config } RECORD_TYPE { uuid id PK uuid tenant_id FK varchar code jsonb schema "JSON Schema for payload" jsonb workflow "state machine descriptor" } RECORD { uuid id PK uuid tenant_id FK uuid record_type_id FK uuid entity_id FK varchar state jsonb payload timestamp valid_from timestamp valid_to } ENTITY { uuid id PK uuid tenant_id FK varchar identifier "IDNP/IDNO/VIN/..." varchar type jsonb attributes } EVENT { uuid id PK uuid record_id FK varchar type varchar actor timestamp at jsonb data } AUTHORITY { uuid id PK uuid tenant_id FK varchar name varchar family } DOCUMENT { uuid id PK uuid tenant_id FK varchar uri varchar sha256 varchar signature } RECORD_DOCUMENT { uuid record_id FK uuid document_id FK varchar role }
TENANT ||--o{ RECORD_TYPE : "" TENANT ||--o{ ENTITY : "" TENANT ||--o{ AUTHORITY : "" RECORD_TYPE ||--o{ RECORD : "" ENTITY ||--o{ RECORD : "" AUTHORITY ||--o{ RECORD : "emite" RECORD ||--o{ EVENT : "" RECORD ||--o{ RECORD_DOCUMENT : "" DOCUMENT ||--o{ RECORD_DOCUMENT : ""7.5 Cross-cutting requirements (orice registru govtech)
Section titled “7.5 Cross-cutting requirements (orice registru govtech)”- Audit complet, append-only — toate modificările → event store. Folosit la contestații, investigații, conformitate cu Legea privind protecția datelor.
- GDPR / Legea 133 — câmpuri sensibile maskate în API public, retenție configurabilă, drept la ștergere doar prin proces formal.
- Semnătură electronică — integrare cu MSign / serviciul guvernamental de semnătură pentru acte oficiale.
- MConnect / interop — SSO și schimb structurat de date cu alte registre guvernamentale; identitate federată pentru funcționari.
- Verificare automată identitate — IDNP la RSP, IDNO la ASP/ANAF, înainte de salvare.
- Multi-language — minim RO + RU + EN (Interdicții are doar RO + EN; alte registre au cerință RU obligatorie).
- Rate limiting + API keys pentru consumatorii externi ai API-ului public.
- Backup + DR — RPO ≤ 1h, RTO ≤ 4h pentru registre cu efect juridic.
7.6 Roadmap (faze)
Section titled “7.6 Roadmap (faze)”gantt title Registry Platform — roadmap orientativ dateFormat YYYY-MM axisFormat %b %Y
section Faza 1 — Interdicții v1 JDL + entități generate :done, 2026-04, 1M Workflow DRAFT→ACTIV+aprobare :active, 2026-05, 1M Ridicare + event log :2026-06, 1M Public consultation API + masking :2026-07, 1M Integrare MSign + MConnect SSO :2026-08, 1M
section Faza 2 — Hardening & Reuse Extragere gov-registry-commons (Pattern B) :2026-09, 2M Document storage (MinIO + hash + signature) :2026-10, 1M Audit & reporting dashboard :2026-11, 1M
section Faza 3 — Al 2-lea registru (validare pattern) Registry #2 pe gov-registry-commons :2026-12, 3M Refactor după lecții învățate :2027-03, 1M
section Faza 4 — Multi-tenant (decizie după Faza 3) Schema engine + JSONB records :2027-04, 3M Workflow as data :2027-07, 2M Tenant onboarding self-service :2027-09, 2M7.7 Tehnologii recomandate per capability
Section titled “7.7 Tehnologii recomandate per capability”| Capability | Stack actual (Interdicții) | Notă pentru reuse |
|---|---|---|
| Backend framework | Spring Boot 3 + JHipster 8 | Bun pentru govtech RO/MD — comunitate, generators, audit gata. |
| Frontend | Angular 19 standalone | OK pentru forms-heavy. Pentru portal public consideră Next.js separat. |
| DB | PostgreSQL (prod), H2 (dev) | Trece la PG și în dev pentru Pattern C (JSONB). |
| Search | Elasticsearch | Per-tenant index în Pattern C. Pentru registre mici, considera PG full-text. |
| Cache | Ehcache + Hibernate L2 | OK monolith. Trece la Redis dacă scalezi orizontal. |
| Auth | JWT (HS512) | Pentru MConnect SSO — adaugă OIDC layer (Keycloak). |
| Document storage | (de adăugat) | MinIO on-prem (cerință de suveranitate). |
| Workflow | (hardcoded) | Pentru Pattern C: state-machine ca date + engine simplu, nu Camunda decât dacă justificat. |
| Migrations | Liquibase | Strict per-tenant changelog dacă mergi multi-tenant cu schema separată. |
| Notifications | SMTP (JHipster MailService) | Adaugă canal MConnect + SMS provider local. |
| Audit | AbstractAuditingEntity + event log nou | Append-only event store separat de tabele de business. |
7.8 Riscuri & decizii deschise
Section titled “7.8 Riscuri & decizii deschise”- Suveranitate date: hosting on-prem (govcloud MD) — exclude cloud public fără justificare legală.
- Schema rigidă vs. JSONB: rigid e mai sigur la audit; JSONB e mai flexibil la onboarding registre noi. Decizia trebuie luată înainte de Pattern C.
- Statut vs. stare: dacă în practică nu se folosesc independent, colapsează într-un singur enum în v1.1 (vezi nota din JDL).
Entitatepolimorfică: extinderea la marfă/vehicul/armă necesită refactorizare semnificativă; planifică pentru Faza 2.- Workflow engine: rezistă tentației de a adopta BPMN engine complex (Camunda etc.) până nu există ≥ 3 workflow-uri reale care îl justifică.
8. Referințe
Section titled “8. Referințe”interdictii_full.md— inventarul complet al domeniului (entități, statuturi, autorități, tipuri).interdictii.jdl— schema autoritativă a entităților v0.CLAUDE.md(root) — convenții de cod, layering, comenzi.- JHipster 8.11 docs: https://www.jhipster.tech/documentation-archive/v8.11.0