Technical architecture
Acest conținut nu este încă disponibil în limba selectată.
Every gStack service is built from the same technology stack and the same layering, so the estate is consistent end to end. This page is the concrete “what it’s built on”; for the conceptual picture see How gStack works.
The stack
Section titled “The stack”| Concern | Technology | Notes |
|---|---|---|
| Scaffolding | JHipster (8.11 monolith; 9.1 for microservices) | Generates the whole vertical slice from a JDL model |
| Backend | Spring Boot 3 (Java 17 / 21) | REST, service layer, Spring Security |
| Frontend | Angular (standalone components) on GDS | One design system across every SPA |
| Relational store | PostgreSQL (prod) / H2 (dev) | jsonb for polymorphic/flexible fields |
| Search | Elasticsearch | Full-text + filtered search on selected entities |
| Logs / observability | ELK (Elasticsearch · Logstash · Kibana) + GLog | Operational logs via ELK; business audit via GLog |
| Identity | Keycloak (OIDC) via gSSO | SSO, tokens, roles; no app mints its own tokens |
| Migrations | Liquibase | Append-only changelogs |
| Mapping | MapStruct | Entity ↔ DTO (entities never leave the service layer) |
| Async / messaging | RabbitMQ | Notifications, OCR/transcription, archive workers |
| Object storage | MinIO / S3 (via GStorage) | Bytes never in the DB |
| Packaging | Docker · compose on hosts · Kubernetes | Images in the GitLab container registry |
How a service is layered
Section titled “How a service is layered”Each application follows the same request path, so the same file means the same thing in every repo:
Angular SPA │ HTTPS + OIDC/JWT bearer ▼web.rest.*Resource ← controllers; exchange DTOs only ▼service.*Service (+ impl) ← business logic + lifecycle/state machineservice.*QueryService ← JPA Criteria filtering for list endpointsservice.mapper (MapStruct) ← entity ↔ DTO ▼repository.*Repository → PostgreSQLrepository.search.* → Elasticsearch- Entities never leave the service layer — controllers exchange DTOs.
- URL-driven filtering exists only on entities declared filterable in the JDL (via
*QueryService+*Criteria). - Auditing columns (
createdBy/createdDate/lastModified…) are auto-populated by a sharedAbstractAuditingEntity. - Lifecycle state machines are enforced in the service layer; each transition appends one row to a write-only event log.
Security
Section titled “Security”- OIDC/SSO through Keycloak (realm managed by gSSO); services are OAuth2 resource servers validating JWTs.
- Roles are platform-prefixed and carried in the token; endpoints authorize in the service/controller layer.
- Machine-to-machine access uses client-credentials tokens or, where required, mTLS (e.g. GNotify, GLog ingest).
- Append-only audit (Hibernate guard + DB trigger) backs every state change and is forwarded to GLog.
Build & run
Section titled “Build & run”- Model-first: the JDL is the source of truth; regenerate, then re-apply hand-written logic kept in separate classes.
- Build:
./mvnw(backend),./npmw(frontend); production images are built per app (backend + nginx-served frontend) and pushed toregistry.esempla.systems. - Run: docker-compose on the shared hosts behind a single edge nginx (TLS + per-app vhosts on the shared
gstack-webnetwork); SI RDP runs on a Kubernetes cluster. - Integrations: the government building blocks (MPass/MSign/MConnect/MNotify/MLog) are reusable Spring Boot starters, each with a mock mode for local development.
Every service ships trilingual (RO / RU / EN). Translations live in two places and are kept in sync:
webapp/i18n/{ro,ru,en}/*.json (frontend) and resources/i18n/messages_*.properties (backend). Romanian
domain terms (legal names) are never translated.