GRegistry — Registrul Sistemelor Informaționale (RSI) · Platform Design
Acest conținut nu este încă disponibil în limba selectată.
Acest document este sursa de adevăr arhitecturală pentru GRegistry, registrul sistemelor informaționale al platformei GStack (Republica Moldova). Acompaniază:
GRegistry.jdl— forma autoritativă a entităților (SOURCE OF TRUTH); orice schimbare de model se face acolo întâi, apoi se regenerează.docs/db_schema.md— DDL PostgreSQL derivat din JDL + note de indexare.docs/caiet_de_sarcini.md— cerințe funcționale și de conformitate.docs/Home.md— punct de intrare wiki + glosar.docs/adr/— Architecture Decision Records (deciziile deschise din §7 se materializează aici pe măsură ce se închid).
Ce este GRegistry. Catalogul unic — single source of truth — al tuturor
sistemelor informaționale din platforma GStack: sisteme CORE (GPass, GSign,
GPay, GConnect), BUSINESS (Cancelarie, Interdicții), PAAS (GLog, GStorage,
GNotify) și INFRASTRUCTURE (GSSO, GMonitor, GVault, GRegistry însuși). GRegistry
este scris de operatori de registru și citit de restul platformei:
GPortal (portal public — expune doar sistemele PUBLIC + PUBLISHED),
GLog, GStorage și GMonitor.
Etichetele din diagrame folosesc termeni structurali în engleză (nume de clase,
straturi) și termeni de domeniu în engleză proprii catalogului (InformationSystem,
PublicationRequest), cu proză explicativă în română — oglindind convenția din
codebase și documentul-soră saas_interdictii/docs/platform_design.md.
Diferă intenționat de Interdicții. GRegistry nu folosește Elasticsearch și nu folosește Kafka. Este un microservice API-first (
clientFramework=no), autentificat prin OAuth2/OIDC la GSSO (Keycloak), nu prin JWT propriu.
1. System context
Section titled “1. System context”Unde stă GRegistry între actorii care îl întrețin și sistemele GStack care îl consumă.
flowchart TB subgraph Actors["Actori (staff)"] Operator["Operator registru<br/>(ROLE_REGISTRY_OPERATOR)"] Approver["Aprobator publicare<br/>(ROLE_REGISTRY_ADMIN)"] Admin["Administrator platformă"] end
subgraph GReg["GRegistry — RSI (microservice, :8085)"] SPA["GRegistry SPA<br/>(Angular, separat — API-first)"] API["REST API<br/>(Spring Boot 3, api/v1)"] PubZone["Zona publică read-only<br/>(api/v1/public — vis=PUBLIC)"] end
subgraph Consumers["Consumatori GStack (read-only)"] GPortal["GPortal<br/>(portal public — doar PUBLIC + PUBLISHED)"] GLog["GLog<br/>(logare centralizată)"] GStorage["GStorage"] GMonitor["GMonitor<br/>(health / uptime)"] end
subgraph Platform["Servicii de platformă"] GSSO["GSSO / Keycloak<br/>(OAuth2 / OIDC)"] Registry["Service discovery<br/>(JHipster Registry / Consul)"] end
Operator -->|CRUD sisteme, medii, dependențe| SPA Approver -->|propune / aprobă / publică| SPA Admin -->|providers, consumatori, audit| SPA
SPA -->|HTTPS + OIDC bearer| API API --> PubZone
GPortal -->|GET filtrat vis=PUBLIC & publishedToPortal=true| PubZone GLog -->|citește catalog + preia RegistryAudit| API GStorage -->|rezolvă coduri de sistem| API GMonitor -->|citește Environment + endpoint-uri| API
SPA -. login OIDC .-> GSSO API <-.->|validează bearer token / JWKS| GSSO API -. self-register .-> RegistryRoluri cheie în context:
- GRegistry scrie o singură dată, citește de multe ori. Operatorii întrețin catalogul; toate celelalte sisteme îl consumă. Nu există flux invers de scriere dinspre consumatori.
- GPortal este consumatorul cel mai restricționat: vede exclusiv sistemele cu
visibility = PUBLICșipublishedToPortal = true. SistemeleINTERNALșiTESTnu părăsesc niciodată registrul. - Autentificarea este externă (GSSO/Keycloak). GRegistry este un OAuth2
resource server: validează bearer token-uri OIDC pe cheile publice (JWKS) ale
realm-ului
gregistryși mapează claim-urile de rol la authorities Spring Security (ROLE_REGISTRY_OPERATOR,ROLE_REGISTRY_ADMIN).
2. Component / architecture view
Section titled “2. Component / architecture view”Layering standard JHipster pentru un microservice Spring Boot 3, fără UI servit
din backend (clientFramework=no) și fără Elasticsearch / Kafka.
flowchart LR subgraph Browser["Browser / consumatori"] SPA["GRegistry SPA<br/>(Angular, styling din<br/>GRegistry.dc.html)"] Ext["GPortal / GLog / GStorage / GMonitor<br/>(HTTP clients)"] end
subgraph Backend["Microservice md.gov.gregistry (:8085)"] direction TB Sec["SecurityFilterChain<br/>OAuth2 resource server (JWT/OIDC)"] Rest["web.rest.*Resource<br/>(controllers — DTOs only)"] Svc["service.*Service<br/>(+ impl/)"] QSvc["service.*QueryService<br/>(JPA Criteria filtering)"] Map["service.mapper<br/>(MapStruct)"] Dto["service.dto"] Repo["repository.*Repository<br/>(Spring Data JPA)"] Dom["domain.*<br/>(JPA entities)"] Audit["AbstractAuditingEntity<br/>+ AuditorAware (OIDC subject)"] Liq["Liquibase changelogs"] end
subgraph Stores["Stores"] PG[("PostgreSQL")] Cache[("Ehcache + Hibernate L2")] end
subgraph Platform["Platformă"] GSSO["GSSO / Keycloak (JWKS)"] Registry["Service discovery"] end
SPA -- HTTPS + OIDC bearer --> Sec Ext -- HTTPS + OIDC bearer --> Sec Sec --> Rest Rest --> Svc Svc --> QSvc Svc --> Map Map --> Dto QSvc --> Repo Svc --> Repo Repo --> Dom Dom --> Audit Repo --> Cache Repo --> PG Liq -. migrations .-> PG Sec -. validează token .-> GSSO Backend -. self-register .-> RegistryConvenții cheie (obligatorii):
- Controllerele schimbă doar DTO-uri cu exteriorul; entitățile JPA nu părăsesc niciodată service layer-ul (regulă identică cu Interdicții).
- Filtrarea URL-driven există doar pe entitățile declarate
filterîn JDL —InformationSystem,Environment,PublicationRequest,SystemDependency— prin perechea*QueryService+*Criteria(JPA Criteria API). Celelalte entități (Provider,ApiEndpoint,RegistryConsumer,RegistryAudit) se accesează prin repository standard. - Paginare activă pe
InformationSystem,RegistryAudit,Environment,PublicationRequest(opțiuneapaginate ... with pagination). AbstractAuditingEntitypopulează automatcreatedBy / createdDate / lastModifiedBy / lastModifiedDate;AuditorAwareextrage identitatea din subiectul token-ului OIDC (sub/preferred_username).- Cache L2 (Ehcache) pe entitățile de referință citite intens de consumatori
(
Provider,InformationSystem), pentru a absorbi traficul read-heavy fără un motor de căutare dedicat. - Fără Elasticsearch, fără Kafka. Interogările de catalog se rezolvă în
PostgreSQL (indexuri + JPA Criteria); nu există
repository.search.*și niciun producer/consumer de evenimente.
3. Database schema
Section titled “3. Database schema”Rezumat — DDL-ul complet și notele de indexare stau în docs/db_schema.md. Diagrama
ER de mai jos reflectă direct GRegistry.jdl.
erDiagram PROVIDER { bigint id PK varchar code UK "2..60" varchar name varchar legal_name varchar contact_email varchar website boolean active }
INFORMATION_SYSTEM { bigint id PK varchar code UK "^[a-z][a-z0-9-]*$" varchar name varchar category varchar system_type "SystemType" varchar status "SystemStatus" varchar visibility "Visibility" varchar criticality "Criticality" varchar security_level "SecurityLevel" boolean handles_personal_data varchar current_version varchar description_ro varchar description_en varchar tech_lead varchar tech_lead_email boolean published_to_portal "denormalizat din PublicationRequest" timestamp created_at timestamp updated_at bigint provider_id FK "required" }
ENVIRONMENT { bigint id PK varchar environment_type "EnvironmentType" varchar state "EnvironmentState" varchar endpoint_url varchar deployed_version boolean monitored timestamp last_checked_at bigint system_id FK "required" }
SYSTEM_DEPENDENCY { bigint id PK varchar kind "DependencyKind" boolean required varchar note bigint system_id FK "consumatorul (required)" bigint depends_on_id FK "serviciul consumat (required)" }
PUBLICATION_REQUEST { bigint id PK varchar state "PublicationState" varchar requested_by timestamp requested_at varchar approved_by timestamp approved_at timestamp published_at varchar requested_visibility "Visibility" varchar comment bigint system_id FK "required" }
API_ENDPOINT { bigint id PK varchar path varchar protocol "ApiProtocol" varchar method varchar description boolean public_api bigint system_id FK "required" }
REGISTRY_CONSUMER { bigint id PK varchar name varchar description varchar filter_expression "ex. vis=public" boolean active }
REGISTRY_AUDIT { bigint id PK varchar change_type "ChangeType" varchar actor varchar summary_ro varchar summary_en varchar ip_address timestamp occurred_at bigint system_id FK "optional" }
PROVIDER ||--o{ INFORMATION_SYSTEM : "deține" INFORMATION_SYSTEM ||--o{ ENVIRONMENT : "are medii" INFORMATION_SYSTEM ||--o{ PUBLICATION_REQUEST : "cereri publicare" INFORMATION_SYSTEM ||--o{ API_ENDPOINT : "expune" INFORMATION_SYSTEM ||--o{ REGISTRY_AUDIT : "istoric modificări" INFORMATION_SYSTEM ||--o{ SYSTEM_DEPENDENCY : "consumă (system)" INFORMATION_SYSTEM ||--o{ SYSTEM_DEPENDENCY : "este consumat (dependsOn)"Note de schemă (detalii în docs/db_schema.md):
InformationSystem.codeeste cheia de join stabilă folosită de toți consumatorii (^[a-z][a-z0-9-]*$, unic). Numele afișabil (name) se poate schimba fără a rupe integrările.SystemDependencyeste graful de dependențe modelat prin douăManyToOnecătreInformationSystem:system(consumatorul) șidependsOn(serviciul consumat). Alimentează matricea de dependențe și vederile „consumed by”. Vezi §5.2 și întrebarea deschisă privind ciclurile (§7).publishedToPortaleste un flag denormalizat peInformationSystem, ținut în sincron cu stareaPublicationRequestla tranzițiile PUBLISH/UNPUBLISH (§4A). Sursa de adevăr a workflow-ului rămânePublicationRequest.RegistryAuditeste append-only din perspectiva aplicației: service layer-ul interzice UPDATE/DELETE (forensic / conformitate). Fiecare tranziție de stare și fiecare mutație de catalog scrie exact un rând.- Enumeri (
SystemType,SystemStatus,Visibility,Criticality,SecurityLevel,EnvironmentType,EnvironmentState,PublicationState,DependencyKind,ChangeType,ApiProtocol) se persistă cavarcharprin@Enumerated(STRING)— convenția JHipster.
4. Lifecycle — state diagrams
Section titled “4. Lifecycle — state diagrams”4.A PublicationRequest — fluxul de publicare (primar)
Section titled “4.A PublicationRequest — fluxul de publicare (primar)”Guvernează dacă un sistem apare pe GPortal, cu poartă de aprobare
DRAFT → PROPOSED → APPROVED → PUBLISHED. Doar sistemele cu visibility = PUBLIC
pot atinge PUBLISHED. La PUBLISH, InformationSystem.publishedToPortal = true;
la UNPUBLISH, false. Fiecare tranziție scrie un rând RegistryAudit (append-only).
stateDiagram-v2 [*] --> DRAFT: creată (OPERATOR)
DRAFT --> PROPOSED: propose<br/>(OPERATOR) PROPOSED --> APPROVED: approve<br/>(ADMIN) PROPOSED --> REJECTED: reject<br/>(ADMIN) APPROVED --> PUBLISHED: publish<br/>[guard: visibility=PUBLIC]<br/>publishedToPortal=true
PUBLISHED --> UNPUBLISHED: unpublish<br/>publishedToPortal=false
REJECTED --> DRAFT: revizuire UNPUBLISHED --> DRAFT: reia ciclul
PUBLISHED --> [*] REJECTED --> [*] UNPUBLISHED --> [*]
note right of APPROVED Poarta de vizibilitate: tranziția publish este respinsă (409) dacă InformationSystem.visibility != PUBLIC. end note
note left of PUBLISHED Singura stare în care sistemul este vizibil pe GPortal. publishedToPortal=true este citit de consumatori. end noteMatrice tranziție → RegistryAudit (ChangeType):
| De la → la | Acțiune | ChangeType scris | Actor | Efect secundar |
|---|---|---|---|---|
| ∅ → DRAFT | create | CREATE | OPERATOR | — |
| DRAFT → PROPOSED | propose | STATUS_CHANGE | OPERATOR | requestedBy/At |
| PROPOSED → APPROVED | approve | STATUS_CHANGE | ADMIN | approvedBy/At |
| PROPOSED → REJECTED | reject | STATUS_CHANGE | ADMIN | comment |
| APPROVED → PUBLISHED | publish | PUBLISH | ADMIN | publishedToPortal=true, publishedAt |
| PUBLISHED → UNPUBLISHED | unpublish | UNPUBLISH | ADMIN | publishedToPortal=false |
| REJECTED / UNPUBLISHED → DRAFT | revizuire | EDIT | OPERATOR | — |
Guard-ul de vizibilitate și scrierea RegistryAudit se enforce în service layer
(PublicationRequestServiceImpl), nu în controller.
4.B InformationSystem.status — ciclul de viață al sistemului (secundar)
Section titled “4.B InformationSystem.status — ciclul de viață al sistemului (secundar)”Independent de publicare: descrie maturitatea tehnică a sistemului.
stateDiagram-v2 [*] --> PLANNED: înregistrat PLANNED --> DEMO: build demo disponibil DEMO --> ACTIVE: intrat în producție ACTIVE --> DEPRECATED: marcat pentru retragere DEPRECATED --> RETIRED: scos din uz DEPRECATED --> ACTIVE: repus în uz (rollback) RETIRED --> [*]
note right of ACTIVE Tranzițiile scriu RegistryAudit cu ChangeType=STATUS_CHANGE. end note4.C Environment.state — sănătatea mediului (secundar)
Section titled “4.C Environment.state — sănătatea mediului (secundar)”Actualizat manual de operator sau împins de GMonitor; scrie RegistryAudit cu
ChangeType=ENV_CHANGE.
stateDiagram-v2 [*] --> PLANNED: mediu declarat, nedesfășurat PLANNED --> NONE: fără date de sănătate PLANNED --> UP: desfășurat + healthy NONE --> UP: primă verificare OK UP --> DEGRADED: latență / erori parțiale DEGRADED --> UP: recuperat UP --> DOWN: indisponibil DEGRADED --> DOWN: escaladare DOWN --> UP: restabilit DOWN --> DEGRADED: recuperare parțială5. Activity diagrams
Section titled “5. Activity diagrams”5.1 Înregistrare + publicare a unui sistem (cu poartă de aprobare)
Section titled “5.1 Înregistrare + publicare a unui sistem (cu poartă de aprobare)”flowchart TD Start([Operator inițiază]) --> SelProv{Provider<br/>existent?} SelProv -- Nu --> NewProv[Creează Provider<br/>code, name, active] SelProv -- Da --> PickProv[Selectează Provider] NewProv --> Fill PickProv --> Fill[Completează InformationSystem<br/>code, name, systemType, status,<br/>visibility, criticality, securityLevel] Fill --> SaveSys[POST /api/v1/information-systems] SaveSys --> ValSys{Validare<br/>backend?} ValSys -- Eșec --> ErrSys[RFC 7807 problem+json] --> Fill ValSys -- OK --> PersistSys[INSERT InformationSystem<br/>publishedToPortal=false] PersistSys --> AuditC[RegistryAudit: CREATE] AuditC --> AddEnv[Adaugă Environment-uri<br/>prod / staging / test] AddEnv --> CreatePR[Creează PublicationRequest<br/>state=DRAFT] CreatePR --> Propose[propose → state=PROPOSED] Propose --> Review{Admin<br/>aprobă?} Review -- Respinge --> Reject[state=REJECTED<br/>RegistryAudit: STATUS_CHANGE] Review -- Aprobă --> Approved[state=APPROVED] Approved --> VisGuard{visibility<br/>= PUBLIC?} VisGuard -- Nu --> Blocked[409 — nu poate fi publicat<br/>rămâne APPROVED] VisGuard -- Da --> Publish[state=PUBLISHED<br/>publishedToPortal=true<br/>RegistryAudit: PUBLISH] Publish --> Portal[GPortal îl preia la<br/>următoarea consultare] Portal --> End([Final]) Blocked --> End Reject --> End5.2 Adăugare / reîmprospătare a unei dependențe (actualizează matricea)
Section titled “5.2 Adăugare / reîmprospătare a unei dependențe (actualizează matricea)”flowchart TD Start([Operator: editează dependențe]) --> PickSys[Selectează InformationSystem<br/>consumatorul = system] PickSys --> PickDep[Selectează serviciul consumat<br/>dependsOn] PickDep --> Cycle{Auto-referință<br/>system == dependsOn?} Cycle -- Da --> RejectSelf[Refuz: dependență reflexivă] Cycle -- Nu --> SetKind[Setează kind<br/>API/EVENT/DATA/AUTH/STORAGE + required] SetKind --> SaveDep[POST /api/v1/system-dependencies] SaveDep --> Exists{Dependența<br/>există deja?} Exists -- Da --> Update[UPDATE kind/required/note<br/>RegistryAudit: DEPENDENCY_CHANGE] Exists -- Nu --> Insert[INSERT SystemDependency<br/>RegistryAudit: DEPENDENCY_CHANGE] Update --> Matrix Insert --> Matrix[Recalculează matricea de dependențe<br/>+ vederea consumed-by] Matrix --> End([Final]) RejectSelf --> EndCiclurile indirecte (A→B→A) nu sunt blocate în v1 — vezi întrebarea deschisă din §7.
5.3 Consultare publică de către un consumator (cu filtrare pe vizibilitate)
Section titled “5.3 Consultare publică de către un consumator (cu filtrare pe vizibilitate)”flowchart TD Start([Consumator: GPortal / sistem extern]) --> Auth{Token OIDC<br/>valid?} Auth -- Nu --> Unauth[401 / 403 — RFC 7807] Auth -- Da --> Query[GET /api/v1/public/information-systems<br/>?visibility.equals=PUBLIC] Query --> Filter[QueryService aplică filtrul server-side:<br/>visibility=PUBLIC AND publishedToPortal=true] Filter --> Project[Proiectează DTO public<br/>fără câmpuri interne/tech-lead sensibile] Project --> Found{Rezultate?} Found -- Nu --> Empty[200 OK — listă goală] Found -- Da --> Return[200 OK + pagină DTO] Return --> AuditRead[RegistryAudit: read extern<br/>actor=consumer, ipAddress] Empty --> AuditRead AuditRead --> End([Final]) Unauth --> End6. Sequence diagrams
Section titled “6. Sequence diagrams”6.1 Operatorul înregistrează un sistem nou
Section titled “6.1 Operatorul înregistrează un sistem nou”sequenceDiagram autonumber actor Op as Operator participant SPA as GRegistry SPA participant API as InformationSystemResource participant Svc as InformationSystemServiceImpl participant Map as InformationSystemMapper participant Repo as InformationSystemRepository participant AudSvc as RegistryAuditService participant DB as PostgreSQL
Op->>SPA: completează formular sistem SPA->>API: POST /api/v1/information-systems (DTO + Bearer) API->>API: @PreAuthorize ROLE_REGISTRY_OPERATOR API->>Svc: save(dto) Svc->>Map: toEntity(dto) Map-->>Svc: InformationSystem Svc->>Repo: save(entity) Repo->>DB: INSERT (+ AbstractAuditingEntity:<br/>created_by/created_date din OIDC subject) DB-->>Repo: row(id) Repo-->>Svc: persisted entity Svc->>AudSvc: record(CREATE, actor, systemId) AudSvc->>DB: INSERT RegistryAudit (append-only) Svc->>Map: toDto(entity) Map-->>Svc: dto Svc-->>API: dto API-->>SPA: 201 Created + Location SPA-->>Op: confirmare + redirect detalii6.2 Operatorul propune, adminul aprobă și publică o PublicationRequest
Section titled “6.2 Operatorul propune, adminul aprobă și publică o PublicationRequest”sequenceDiagram autonumber actor Op as Operator actor Adm as Admin participant SPA as GRegistry SPA participant API as PublicationRequestResource participant Svc as PublicationRequestServiceImpl participant SysSvc as InformationSystemService participant Repo as PublicationRequestRepository participant AudSvc as RegistryAuditService participant DB as PostgreSQL
Op->>SPA: creează cerere + propose SPA->>API: PATCH /api/v1/publication-requests/{id}/propose API->>Svc: propose(id) Svc->>Repo: save(state=PROPOSED) Svc->>AudSvc: record(STATUS_CHANGE) Svc-->>API: dto (PROPOSED) API-->>SPA: 200 OK
Adm->>SPA: deschide coada de aprobare SPA->>API: GET /api/v1/publication-requests?state.equals=PROPOSED API->>Svc: findByCriteria (QueryService) Svc-->>SPA: page<DTO> Adm->>SPA: click "Approve & Publish" SPA->>API: PATCH /api/v1/publication-requests/{id}/publish API->>API: @PreAuthorize ROLE_REGISTRY_ADMIN API->>Svc: approveAndPublish(id) Svc->>Repo: findById(id) Repo-->>Svc: entity (PROPOSED/APPROVED) Svc->>SysSvc: assert visibility == PUBLIC alt visibility != PUBLIC SysSvc-->>Svc: false Svc-->>API: throw (RFC 7807, 409 Conflict) API-->>SPA: 409 problem+json else visibility == PUBLIC Svc->>Repo: save(state=APPROVED → PUBLISHED) Svc->>SysSvc: setPublishedToPortal(systemId, true) SysSvc->>DB: UPDATE information_system SET published_to_portal=true Svc->>AudSvc: record(PUBLISH) AudSvc->>DB: INSERT RegistryAudit Svc-->>API: dto (PUBLISHED) API-->>SPA: 200 OK end6.3 GPortal consumă registrul public
Section titled “6.3 GPortal consumă registrul public”sequenceDiagram autonumber participant GP as GPortal participant GSSO as GSSO / Keycloak participant Sec as SecurityFilterChain (resource server) participant API as PublicInformationSystemResource participant QSvc as InformationSystemQueryService participant Repo as InformationSystemRepository participant AudSvc as RegistryAuditService participant DB as PostgreSQL
GP->>GSSO: client_credentials grant GSSO-->>GP: access_token (OIDC) GP->>Sec: GET /api/v1/public/information-systems<br/>?visibility.equals=PUBLIC (Bearer) Sec->>Sec: validează semnătura pe JWKS + scope alt token invalid Sec-->>GP: 401 (RFC 7807 problem+json) else token valid Sec->>API: forward API->>QSvc: findByCriteria(vis=PUBLIC) QSvc->>QSvc: forțează publishedToPortal=true QSvc->>Repo: JPA Criteria query Repo->>DB: SELECT ... WHERE visibility='PUBLIC'<br/>AND published_to_portal=true DB-->>Repo: rows Repo-->>QSvc: page<InformationSystem> QSvc-->>API: page<PublicDTO> API->>AudSvc: record(read extern, actor=gportal) AudSvc->>DB: INSERT RegistryAudit API-->>GP: 200 OK + pagină DTO end6.4 Actualizarea sănătății unui mediu — prod marcat DOWN
Section titled “6.4 Actualizarea sănătății unui mediu — prod marcat DOWN”sequenceDiagram autonumber participant GM as GMonitor participant SPA as GRegistry SPA (sau API direct) participant API as EnvironmentResource participant Svc as EnvironmentServiceImpl participant Repo as EnvironmentRepository participant AudSvc as RegistryAuditService participant DB as PostgreSQL
GM->>API: PATCH /api/v1/environments/{id}<br/>{ state: DOWN } (Bearer) API->>API: @PreAuthorize ROLE_REGISTRY_OPERATOR API->>Svc: partialUpdate(dto) Svc->>Repo: findById(id) Repo-->>Svc: env (state=UP, type=PRODUCTION) Svc->>Svc: validează tranziția UP → DOWN (§4.C) Svc->>Repo: save(state=DOWN, lastCheckedAt=now) Repo->>DB: UPDATE environment Svc->>AudSvc: record(ENV_CHANGE, "prod DOWN") AudSvc->>DB: INSERT RegistryAudit Svc-->>API: dto (DOWN) API-->>GM: 200 OK Note over GM,API: GMonitor și dashboard-urile<br/>reflectă noua stare la următoarea citire6.5 Login OIDC prin GSSO / Keycloak (bearer token flow)
Section titled “6.5 Login OIDC prin GSSO / Keycloak (bearer token flow)”sequenceDiagram autonumber actor U as Utilizator (staff) participant SPA as GRegistry SPA participant GSSO as GSSO / Keycloak (realm gregistry) participant Sec as SecurityFilterChain (resource server) participant API as *Resource
U->>SPA: accesează aplicația SPA->>GSSO: redirect Authorization Code + PKCE U->>GSSO: autentificare (user / parolă / MFA) GSSO-->>SPA: authorization code SPA->>GSSO: schimbă code → tokens (token endpoint) GSSO-->>SPA: access_token (JWT/OIDC) + id_token + refresh_token SPA->>SPA: stochează token; extrage rolurile din claims SPA->>Sec: GET /api/v1/... (Authorization: Bearer <access_token>) Sec->>GSSO: obține/cache-uiește JWKS (chei publice) Sec->>Sec: validează semnătura, exp, issuer, audience Sec->>Sec: mapează claims → authorities (ROLE_REGISTRY_*) Sec->>API: request autorizat API-->>SPA: 200 OK (DTO) Note over SPA,GSSO: la expirare, SPA reînnoiește<br/>silențios cu refresh_token7. GRegistry în platforma GStack — rol, standarde și decizii deschise
Section titled “7. GRegistry în platforma GStack — rol, standarde și decizii deschise”7.1 Rolul în ecosistem
Section titled “7.1 Rolul în ecosistem”GRegistry este coloana vertebrală de metadate a GStack: sursa unică din care celelalte sisteme află ce sisteme există, cine le deține, ce endpoint-uri expun, în ce mediu rulează și care depinde de care.
flowchart LR subgraph Src["Sursa de adevăr"] GReg["GRegistry (RSI)"] end subgraph Feeds["Alimentează (read-only)"] GPortal["GPortal<br/>catalog public (PUBLIC + PUBLISHED)"] GLog["GLog<br/>preia RegistryAudit + rezolvă coduri"] GStorage["GStorage<br/>rezolvă owner/system după code"] GMonitor["GMonitor<br/>ținte de monitorizare din Environment"] end GReg --> GPortal GReg --> GLog GReg --> GStorage GReg --> GMonitor GMonitor -. push health .-> GReg- GPortal citește exclusiv sistemele
PUBLIC+publishedToPortal=trueși le afișează cetățenilor. - GLog consumă
RegistryAudit(append-only) pentru logare centralizată și rezolvă codurile de sistem la nume lizibile. - GStorage folosește
InformationSystem.codeca cheie de proprietate a artefactelor. - GMonitor citește
Environment(endpoint-uri +monitored) ca listă de ținte și poate împinge înapoi starea de sănătate (ENV_CHANGE).
7.2 Aliniere la standardul GovStack API
Section titled “7.2 Aliniere la standardul GovStack API”GRegistry expune un contract HTTP conform convenției GStack (aceeași în tot ecosistemul):
| Element | Convenție |
|---|---|
| Versionare | prefix /api/v1 |
| Zone de acces | api/v1/public (consultare, vis=PUBLIC), api/v1 staff (operator), api/v1/admin (aprobare/config) |
| Health | /health/live (liveness), /health/ready (readiness) — expuse prin Spring Boot Actuator |
| Metrici | /metrics (Micrometer / Prometheus) |
| Contract | /api/v1/openapi.json (springdoc OpenAPI 3) |
| Erori | RFC 7807 application/problem+json pentru toate răspunsurile de eroare |
| Auth | OAuth2 / OIDC bearer (GSSO / Keycloak), authorities ROLE_REGISTRY_* |
Zonele de acces se mapează la authorities: public nu cere rol de scriere (doar token
valid + scope de citire), staff cere ROLE_REGISTRY_OPERATOR, iar tranzițiile de
aprobare/publicare cer ROLE_REGISTRY_ADMIN (vezi §4.A, §6.2).
7.3 Întrebări arhitecturale deschise
Section titled “7.3 Întrebări arhitecturale deschise”Se materializează ca ADR-uri în docs/adr/ pe măsură ce se închid:
- Retenția
RegistryAudit. Append-only, dar cât timp online? Politica de arhivare / offload către GLog și pragul de partiționare temporală nu sunt încă fixate. → candidat ADR. - Ciclurile de dependență.
SystemDependencyinterzice auto-referința directă (§5.2), dar ciclurile indirecte (A→B→A) sunt permise în v1. De decis dacă validăm aciclicitatea (DAG) la scriere sau doar semnalăm în matrice. → ADR. - Modelul de autentificare al consumatorilor. GPortal/GLog/GStorage/GMonitor
accesează prin
client_credentials(service accounts în Keycloak) sau printr-un API gateway cu chei? EntitateaRegistryConsumer(filterExpression,active) sugerează o listă de consumatori guvernată; relația cu conturile de serviciu Keycloak trebuie clarificată. → ADR. - Unicitate
SystemDependency. Trebuie un constraint unic pe(system, dependsOn, kind)pentru a evita duplicatele? Vezi șidocs/db_schema.md.
Aceste puncte sunt lăsate deliberat deschise pentru build-ul demo curent; se revizuiesc înainte de orice pas de production hardening (paralel cu checklistul din
saas_interdictii/docs/db_schema.md §8).
8. Referințe
Section titled “8. Referințe”GRegistry.jdl— schema autoritativă a entităților (SOURCE OF TRUTH).docs/db_schema.md— DDL PostgreSQL + note de indexare și unicitate.docs/caiet_de_sarcini.md— cerințe funcționale și de conformitate.docs/Home.md— punct de intrare wiki + glosar GStack.docs/adr/— Architecture Decision Records (deciziile din §7.3).GRegistry.dc.html— design context / sursă de styling pentru SPA.saas_interdictii/docs/platform_design.md— documentul-soră (Interdicții), din care se împrumută structura și convențiile de diagramare.- JHipster 8 microservices: https://www.jhipster.tech/microservices-architecture/
- RFC 7807 (Problem Details for HTTP APIs): https://www.rfc-editor.org/rfc/rfc7807