GSSO — Înregistrări ale deciziilor de arhitectură
| Cod document | SPEC-GSSO-2026 / Raportul 01 |
| Versiune | 0.2 (sursa EN, text care prevalează) |
| Data | 2026-10-06 |
| Statut | Acceptat. GSSO-ADR-001..014 sunt Acceptat (decizia proprietarului, 2026-10-06); proprietarul poate încă solicita modificări, care necesită un ADR nou care îl înlocuiește |
| Rapoarte însoțitoare | 00 RFP · 02 Cerințe · 03 Consumatori și contract · 04 Documentație tehnică · 05 Foaie de parcurs |
Istoricul reviziilor
Section titled “Istoricul reviziilor”| Versiune | Data | Modificări |
|---|---|---|
| 0.1-draft | 2026-10-05 | GSSO-ADR-001..014, toate Propuse |
| 0.2 | 2026-10-06 | GSSO-ADR-001..014 acceptate de proprietar (Acceptat); revizuirea unor ADR-uri poate urma prin ADR-uri noi care le înlocuiesc |
| 0.3 | 2026-10-06 | Constatări din implementarea S1: GSSO-ADR-015 (modifică 008) și GSSO-ADR-016 (rafinează 004), ambele Propus |
Ce este un ADR
Section titled “Ce este un ADR”Un ADR consemnează o decizie semnificativă:
- contextul: situația care a impus luarea unei decizii;
- decizia: ce s-a ales;
- alternativele luate în considerare: ce a fost respins și de ce;
- consecințele: efectele pozitive și negative pe care echipa le acceptă.
Stilul casei urmează gregistry/docs/adr și paas_gflow/docs/reports/01-adr.en.md. Odată acceptat, un ADR este imuabil, iar o modificare necesită un ADR nou care îl înlocuiește.
Decizii din amonte care trebuie respectate:
saas_crm/docs/reports/DECISIONS.md: D9 (GSSO este platforma de identitate gStack), D27/D28 (GSSO este un PaaS existent, care trebuie reutilizat), D33 (stiva DEV-PLAYBOOK §2 pentru fiecare aplicație).gregistry/docs/adr/ADR-002-auth-oidc-gsso.md: fără parole locale, rolurile în GSSO, SPA-ul folosește PKCE, comunicarea M2M folosește client credentials.
| ID | Titlu | Statut |
|---|---|---|
| GSSO-ADR-001 | GSSO este un plan de control peste Keycloak, nu un nou furnizor de identitate | Acceptat |
| GSSO-ADR-002 | Model hibrid de realm-uri: gstack (personal), cetatean (cetățeni), tenant-* (izolate) | Acceptat |
| GSSO-ADR-003 | Un singur cluster Keycloak 26.6.x cu PostgreSQL propriu; se păstrează instanța existentă | Acceptat |
| GSSO-ADR-004 | Reconcilierea stării dorite prin Keycloak Admin REST API | Acceptat |
| GSSO-ADR-005 | Roluri cu spațiu de nume per platformă și un claim roles plat | Acceptat |
| GSSO-ADR-006 | Accesul se acordă prin AtribuireAcces, cu ciclu de viață și principiul „patru ochi” | Acceptat |
| GSSO-ADR-007 | Evenimentele Keycloak printr-un SPI event-listener către Kafka; stocare append-only; redirecționare către GLog | Acceptat |
| GSSO-ADR-008 | Utilizatorii rămân în Keycloak; GSSO păstrează o proiecție de citire | Acceptat |
| GSSO-ADR-009 | Un singur model de integrare pentru aplicații: gsso-spring-boot-starter și @gstack/gsso-angular | Acceptat |
| GSSO-ADR-010 | Stiva DEV-PLAYBOOK: microserviciul JHipster 9.1.0 gsso + gateway-ul gsso-gateway + gsso-web | Acceptat |
| GSSO-ADR-011 | Configurația ca cod: baseline-ul realm-urilor, extensiile și temele în depozit | Acceptat |
| GSSO-ADR-012 | Token exchange (RFC 8693, Keycloak standard token exchange V2) pentru apelurile în numele utilizatorului | Acceptat |
| GSSO-ADR-013 | Revocare în 60 s: token-uri scurte, închiderea sesiunilor, evenimente de revocare | Acceptat |
| GSSO-ADR-014 | Triajul EU AI Act: GSSO nu este un sistem de IA | Acceptat |
| GSSO-ADR-015 | Operațiunile asupra utilizatorilor sunt apeluri directe, auditate, la Admin API (modifică GSSO-ADR-008) | Propus |
| GSSO-ADR-016 | Implementarea reconcilierului: client Admin REST subțire, marcaje de proprietate, token lightweight (rafinează GSSO-ADR-004) | Propus |
GSSO-ADR-001 — GSSO este un plan de control peste Keycloak, nu un nou furnizor de identitate
Section titled “GSSO-ADR-001 — GSSO este un plan de control peste Keycloak, nu un nou furnizor de identitate”Statut: Acceptat (2026-10-06)
Context.
- Keycloak 26.6.3 deservește deja fiecare aplicație gStack la
sso.gstack.esempla.systems. Este un furnizor OIDC/SAML certificat, cu MFA, WebAuthn, brokering, federare LDAP, token exchange și o consolă de cont. - Ceea ce lipsește este guvernanța:
- un catalog de servicii;
- roluri delimitate per platformă;
- aprobarea accesului;
- controlul drift-ului;
- un audit durabil;
- un standard unic de integrare;
- o consolă în sistemul de design gStack.
- Designul
GSSO.dc.htmlprezintă GSSO drept „Single Sign-On (Keycloak)”.
Decizie.
- GSSO este un plan de control în jurul unui Keycloak încorporat.
- Keycloak deține autentificarea, credențialele, sesiunile, emiterea token-urilor, MFA, federarea, interfața de login (cu tema GDS) și autoservirea contului.
- GSSO deține:
- modelul guvernat (realm-uri, platforme, clienți, roluri de platformă, atribuiri, unități organizaționale, politici de autentificare);
- reconcilierea acestuia în Keycloak;
- depozitul de evenimente;
- rapoartele;
- API-ul
apppentru consumatori; - consola de administrare.
- GSSO nu manipulează niciodată parolele utilizatorilor și nu emite niciodată token-uri.
Alternative luate în considerare.
- Utilizarea exclusivă a consolei de administrare Keycloak standard. Respinsă: fără catalog, fără aprobare, fără detectarea drift-ului, fără GDS, fără audit dincolo de depozitul de evenimente propriu Keycloak, cu durată scurtă de păstrare.
- Scrierea unui furnizor de identitate propriu (Spring Authorization Server). Respinsă: ar reimplementa funcționalități certificate, critice pentru securitate (MFA, WebAuthn, broker SAML, LDAP), cu risc și cost ridicate.
- IAM comercial (Okta, Entra ID). Respinsă: constrângeri de suveranitate și de găzduire pentru datele guvernamentale, costul licențelor și investiția existentă în Keycloak.
Consecințe.
- (+) Codul critic pentru securitate rămâne într-un proiect matur, iar GSSO rămâne mic.
- (+) Aplicațiile existente continuă să funcționeze; URL-ul issuer-ului nu se schimbă pentru realm-urile preluate.
- (−) Două surse de configurație pot diverge, ceea ce este atenuat prin reconciliere (GSSO-ADR-004).
- (−) GSSO depinde de compatibilitatea Keycloak Admin API; actualizările sunt condiționate de teste (GSSO-NFR-OPS-004).
GSSO-ADR-002 — Model hibrid de realm-uri
Section titled “GSSO-ADR-002 — Model hibrid de realm-uri”Statut: Acceptat (2026-10-06)
Context.
- Sesiunile SSO Keycloak sunt per realm. Un utilizator autentificat în realm-ul A nu este autentificat în realm-ul B decât dacă B face brokering către A.
- În prezent, realm-ul
interdictiieste, de facto, realm-ul partajat al personalului, în timp ce alte denumiri de realm (gdocs,gnotify,gstorage,gstack,ultra) apar în cod fără niciun plan în spate. - Macheta enumeră câte un realm per sistem (
cancelaria,interdictii,portal-cetatean,glog-services). Aceasta oferă izolare, dar nu și SSO partajat.
Decizie.
| Realm | Cine | Clienți | Federare |
|---|---|---|---|
master | Doar inițializarea Keycloak și accesul de urgență (break-glass) | gsso-reconciler (cont de serviciu) | — |
gstack | Întregul personal gStack și operatorii tuturor instituțiilor | Fiecare client SaaS și PaaS destinat personalului, consola GSSO, conturile de serviciu ale tuturor serviciilor | AD/LDAP per instituție (opțional), fără MPass |
cetatean | Cetățeni și mediul de afaceri | Portaluri publice și SPA-uri destinate cetățenilor | MPass/eID (broker SAML), legături first-broker-login după IDNP |
tenant-<code> | Clienți izolați (site-uri whitelabel ultra-*, bts-*, esempla-* sau o instituție care solicită realm propriu) | Doar clienții acelui client | Per tenant |
- Instituțiile din
gstacksunt separate prin unități organizaționale (claim-ulorg_unit) și roluri de platformă, nu prin realm-uri. - Realm-urile de tenant sunt create dintr-un șablon de realm versionat.
- Selectorul de realm din consolă stabilește domeniul de realm al fiecărui ecran.
Alternative luate în considerare.
- Câte un realm per aplicație (ca în machetă). Respinsă pentru personal: fără SSO între aplicații, iar rolurile și utilizatorii sunt duplicați per realm. Se păstrează doar pentru
tenant-*. - Un singur realm pentru tot, inclusiv pentru cetățeni. Respinsă: cetățenii și personalul au politici diferite (MFA, durata sesiunii, federare, minimizarea datelor), iar interfețele de administrare pentru personal nu trebuie să fie accesibile cu un cont de cetățean.
- Keycloak Organizations (mai multe organizații într-un singur realm). Luată în considerare pentru instituții. Se păstrează ca opțiune ulterioară (Q-GSSO-1). Unitățile organizaționale prin atribute acoperă necesitățile actuale, cu o cuplare mai redusă la o funcționalitate recentă.
Consecințe.
- (+) Un singur login pentru toate aplicațiile personalului (obiectivul G-1).
- (+) Datele și politicile cetățenilor sunt izolate de cele ale personalului.
- (−) Realm-ul
gstackdevine critic. Disponibilitatea lui este disponibilitatea fiecărei aplicații a personalului (GSSO-NFR-AVL-*). - (−) Clienții existenți din
interdictiitrebuie migrați (raportul 05, faza S4) sauinterdictiieste preluat cagstack(Q-GSSO-1).
GSSO-ADR-003 — Un singur cluster Keycloak 26.6.x cu PostgreSQL propriu; se păstrează instanța existentă
Section titled “GSSO-ADR-003 — Un singur cluster Keycloak 26.6.x cu PostgreSQL propriu; se păstrează instanța existentă”Statut: Acceptat (2026-10-06)
Context.
- Keycloak-ul în funcțiune este 26.6.3 (containerul
keycloak, containerul de bază de datepostgres-keycloak) pe gazda demo partajată, în spatele nginx-ului de la margine (edge). - Fișierul de design gstyle menționează „Keycloak 24”, dar informația este depășită.
Decizie.
- GSSO fixează Keycloak 26.6.x (actualizările de patch sunt permise), cu o bază de date PostgreSQL dedicată, separată de baza de date GSSO.
- Depozitul GSSO furnizează definițiile compose și Helm care reproduc instanța în funcțiune:
KC_PROXY_HEADERS=xforwarded;- hostname-ul
sso.gstack.esempla.systems; - JAR-ul de extensii și temele montate;
- health și metrics activate.
- Instanța în funcțiune este preluată pe loc, nu înlocuită. Mai întâi se face backup bazei ei de date, apoi extensiile și tema GSSO sunt adăugate într-o fereastră de mentenanță aprobată de proprietar.
- Ținta HA pentru producție: 2 noduri Keycloak cu clusterul Infinispan încorporat (sesiuni replicate), în spatele ingress-ului.
Alternative luate în considerare.
- Keycloak nou și migrarea datelor: respinsă. Ar schimba secretele și ID-urile utilizatorilor (
sub) și ar strica fiecare aplicație. - PostgreSQL partajat cu GSSO: respinsă, deoarece cele două au profiluri diferite de backup, de actualizare și de rază de impact (blast radius).
Consecințe.
- (+) Nicio schimbare a URL-ului issuer-ului sau a
subpentru utilizatorii existenți. - (−) Preluarea necesită un runbook atent (raportul 04 §11) și un punct de rollback.
GSSO-ADR-004 — Reconcilierea stării dorite prin Keycloak Admin REST API
Section titled “GSSO-ADR-004 — Reconcilierea stării dorite prin Keycloak Admin REST API”Statut: Acceptat (2026-10-06)
Context.
- GSSO trebuie să aducă Keycloak în concordanță cu modelul său guvernat, să supraviețuiască eșecurilor parțiale și să evidențieze modificările manuale.
Decizie.
- Calea de scriere: fiecare modificare de catalog sau de atribuire înregistrează (commit), într-o singură tranzacție, modificarea entității GSSO plus un
JobSincronizare(outbox tranzacțional). Worker-ul reconcilier preia joburile în așteptare (SELECT … FOR UPDATE SKIP LOCKED) și le aplică prinkeycloak-admin-client26.x cu contul de serviciugsso-reconciler. - Idempotență: fiecare operație caută după cheia naturală (numele realm-ului, clientId, numele rolului, id-ul utilizatorului + rolul), apoi creează, actualizează sau nu face nimic (no-op). Id-ul intern Keycloak este stocat înapoi ca
kcId. - Reîncercare: backoff exponențial (1 s → 5 min, maximum 10 încercări), apoi
FAILED, ceea ce declanșează o alertă prin GNotify. - Reconciliere completă:
- periodic (implicit la fiecare 15 min) și la cerere;
- calculează o diferență (diff) per realm între starea dorită și Keycloak, doar pentru tipurile de obiecte gestionate;
- constatările devin rânduri
JobSincronizarecustare=DRIFTși un diff JSON.
- Politica de drift per realm:
REPORT(implicit): doar afișare;ENFORCE: corectare automată;IGNORE: pentru realm-urile preluate, pe durata migrării.
- Marcaj de proprietate: obiectele create de GSSO poartă atributul
gsso.managed=true. Obiectele negestionate sunt raportate ca „negestionate” și nu sunt niciodată șterse decât dacă sunt preluate. - Preluare (adoptare): un import doar-citire al clienților, rolurilor și maparilor de roluri ale unui realm în catalog, ca
Platforma+ClientAplicatie+RolPlatforma+AtribuireAcces(ACTIVA, sursa=ADOPTAT).
Alternative luate în considerare.
- Doar keycloak-config-cli / Terraform: potrivite pentru baseline-uri statice (folosite în GSSO-ADR-011), dar fără atribuiri la runtime, fără aprobare și fără interfață.
- Scrieri directe în baza de date Keycloak: respinsă ca nesuportată și nesigură.
- Apeluri sincrone din interfață, fără joburi: respinsă, deoarece eșecurile parțiale lasă o stare inconsecventă, fără reîncercare.
Consecințe.
- (+) Rezilient, observabil și reluabil.
- (−) Interfața trebuie să afișeze starea de sincronizare a fiecărui obiect (
stareSync). - (−) Consistență eventuală: de regulă sub 2 s, limitată de politica de reîncercare.
GSSO-ADR-005 — Roluri cu spațiu de nume per platformă și un claim roles plat
Section titled “GSSO-ADR-005 — Roluri cu spațiu de nume per platformă și un claim roles plat”Statut: Acceptat (2026-10-06)
Context.
- În prezent, rolurile de realm
ROLE_ADMINșiROLE_USERsunt partajate de toate aplicațiile. - Aplicațiile le citesc din
realm_access.rolessau dintr-un claim personalizatroles. - Grupurile candidate gFlow necesită denumiri de roluri prefixate cu aplicația (
CRM_*,GTENDERS_*).
Decizie.
- Fiecare rol expus de o platformă este un rol de realm denumit
<PLATFORMA_COD_UPPER>_<ROL>(de exempluINTERDICTII_EMITENT,CRM_ADMIN,GLOG_AUDITOR) și poartă atributulgsso.platforma=<cod>. - Rolurile compozite grupează rolurile inferioare din cadrul aceleiași platforme.
- Rolul implicit
ROLE_USERse păstrează pentru „utilizator autentificat din personal”. ROLE_ADMINeste depreciat. Pe durata migrării este mapat la<APP>_ADMINpentru fiecare aplicație care îl folosește, apoi este eliminat (raportul 05 S4).- Rolurile de client sunt permise pentru domeniile conturilor de serviciu (de exemplu
gstorage-service: object:read). Autorizarea oamenilor folosește doar roluri de realm, astfel încât un singur claimrolessă deservească fiecare aplicație. - Mapper-ul GSSO emite un tablou plat
roles(rolurile de realm ale utilizatorului, efective după aplicarea compozitelor). - Client scope-ul
gsso-roles-filteredpoate limita tabloul la rolurile platformei din audiența token-ului plusROLE_USER, pentru a păstra token-urile mici. - Starter-ul mapează
rolesla autorități Spring.<APP>_Xdevine autoritatea<APP>_X; pentru compatibilitate cu JHipster, aplicația poate mapa local<APP>_ADMINlaROLE_ADMIN.
Alternative luate în considerare.
- Roluri de client per aplicație pentru oameni: respinsă. Token-urile ar avea atunci nevoie de o structură de claim per client (
resource_access), iar grupurile candidate gFlow și interogările între aplicații ar deveni mai dificile. - Grupuri în loc de roluri: grupurile se folosesc în continuare, dar doar ca modalitate de a grupa roluri (de exemplu „Operator Cancelaria”). Autorizarea se face întotdeauna pe roluri.
Consecințe.
- (+) Rază de impact clară per platformă (obiectivul G-2).
- (+) Un singur claim pentru toate aplicațiile.
- (−) Aplicațiile existente trebuie să-și redenumească verificările de rol, ceea ce este atenuat prin harta de aliasuri a starter-ului pe durata migrării.
GSSO-ADR-006 — Accesul se acordă prin AtribuireAcces, cu ciclu de viață și principiul „patru ochi”
Section titled “GSSO-ADR-006 — Accesul se acordă prin AtribuireAcces, cu ciclu de viață și principiul „patru ochi””Statut: Acceptat (2026-10-06)
Context.
- Mapările de roluri făcute direct în Keycloak nu au motiv, aprobator sau termen de expirare.
- NFRQ56–66 impun principiul privilegiului minim și un audit de securitate.
- CAP-GSSO-04 necesită revocare rapidă.
Decizie.
- Rolul de platformă al unei persoane este atribuit exclusiv printr-o
AtribuireAcces:
SOLICITATA ──approve──▶ APROBATA ──reconciled──▶ ACTIVA ──revoke──▶ REVOCATA │ │ └──validPana passed──▶ EXPIRATA └──reject──▶ RESPINSA └──second approval required (sensitive)──▶ stays APROBATA(1/2)- Reguli, aplicate în stratul de servicii; fiecare tranziție scrie un
EvenimentGsso:- Solicitantul poate fi utilizatorul, managerul acestuia, proprietarul platformei sau o aplicație prin
api/v1/app. Motivul este obligatoriu. - Aprobatorul este proprietarul platformei sau un administrator de realm. Pentru rolurile sensibile este necesar și un al doilea aprobator, distinct, cu
GSSO_APPROVER. Nimeni nu își aprobă propria solicitare. ACTIVAse setează doar după ce reconcilierul confirmă maparea în Keycloak.validPanaeste opțional. Valoarea sa implicită provine din politica rolului (Q-GSSO-5). Un planificator orar face să expire atribuirile scadente. Utilizatorii primesc o avertizare de expirare cu 14 zile și cu 1 zi înainte, prin GNotify.- Revocarea și expirarea elimină maparea și declanșează GSSO-ADR-013.
- Administratorii pot acorda direct (solicitare și aprobare într-un singur pas) doar pentru rolurile nesensibile. Acest lucru este auditat ca
ACORDARE_DIRECTA.
- Solicitantul poate fi utilizatorul, managerul acestuia, proprietarul platformei sau o aplicație prin
- Conturile de serviciu primesc roluri prin configurația
ClientAplicatie, nu prin atribuiri.
Alternative luate în considerare.
- Doar maparea rolurilor în Keycloak: fără guvernanță.
- Un proces BPMN în gFlow: luat în considerare. GSSO este o dependență a gFlow (gFlow se autentifică prin GSSO), deci ar apărea o dependență circulară. Ciclul de viață este mic, iar o mașină de stări în stratul de servicii este suficientă.
Consecințe.
- (+) Răspunde la întrebarea „cine are ce, de ce, de când, până când, aprobat de cine”.
- (−) Adaugă un pas în munca administrativă zilnică, ceea ce este atenuat prin atribuiri în masă și șabloane de roluri (grupuri).
GSSO-ADR-007 — Evenimentele Keycloak printr-un SPI event-listener către Kafka; stocare append-only; redirecționare către GLog
Section titled “GSSO-ADR-007 — Evenimentele Keycloak printr-un SPI event-listener către Kafka; stocare append-only; redirecționare către GLog”Statut: Acceptat (2026-10-06)
Context.
- Keycloak păstrează evenimentele de utilizator și evenimentele de administrare în propria bază de date, cu expirare scurtă, și nu oferă mecanism de tip push.
- Dashboard-ul, evenimentele de securitate, ultima autentificare și proiecția au nevoie de ele.
- GLog este depozitul de audit WORM al gStack.
Decizie.
- Event listener. Extensia GSSO pentru Keycloak furnizează un
EventListenerProvider,gsso-kafka. Acesta publică fiecare eveniment de utilizator (LOGIN, LOGIN_ERROR, LOGOUT, CODE_TO_TOKEN, CLIENT_LOGIN, UPDATE_CREDENTIAL, REGISTER, IDENTITY_PROVIDER_*…) și fiecare eveniment de administrare (cu reprezentare) în topic-ul Kafkagsso.kc-events.v1:- CloudEvents în mod binar;
- cheie =
realmId:userId; - asincron, cu un buffer local limitat.
- Dacă Kafka este indisponibil, evenimentul se află în continuare în depozitul de evenimente Keycloak, iar golul este completat retroactiv (back-fill) din Admin API de către consumatorul GSSO.
- Consumator.
gssoconsumă topic-ul în mod idempotent (deduplicare dupăeventId), scrieEvenimentGssoși actualizeazăProiectieUtilizator(ultima autentificare, eșecuri) și agregatele dashboard-ului. - Evenimentele proprii GSSO. Modificările de catalog, tranzițiile atribuirilor și joburile de sincronizare sunt scrise în
EvenimentGssoîn aceeași tranzacție cu modificarea. - Stocare.
EvenimentGssoeste append-only:- repository-ul nu are metode de actualizare sau de ștergere;
- un trigger de bază de date respinge
UPDATEșiDELETE; - fiecare rând poartă
hashPrecedentșihash(lanț SHA-256 per realm).
- Redirecționare. Un releu redirecționează fiecare eveniment către GLog
POST /api/v1/app/audit-events(client credentials, scopeaudit:write), cu reîncercare, înregistrând id-ul de confirmare GLog. - Retenție. 90 de zile în GSSO (Q-GSSO-7); GLog păstrează traseul pe termen lung.
Alternative luate în considerare.
- Interogarea periodică (polling) a API-ului de evenimente Keycloak: respinsă ca mecanism principal din cauza latenței și a costului paginării. Se păstrează pentru back-fill.
- Listener-e Kafka terțe: respinsă. Sunt necesare învelișul CloudEvents și convenția de denumire a topic-urilor gStack.
Consecințe.
- (+) Dashboard aproape în timp real și traseu criminalistic (forensic).
- (−) Adaugă Kafka la dependențele de runtime ale Keycloak. O indisponibilitate Kafka nu blochează autentificările, deoarece listener-ul este asincron și neblocant.
GSSO-ADR-008 — Utilizatorii rămân în Keycloak; GSSO păstrează o proiecție de citire
Section titled “GSSO-ADR-008 — Utilizatorii rămân în Keycloak; GSSO păstrează o proiecție de citire”Statut: Acceptat (2026-10-06)
Context.
- Utilizatorii și credențialele trebuie să aibă o singură sursă master. Consola are nevoie de căutare rapidă între realm-uri, de ultima autentificare și starea MFA, precum și de vizualizări ale atribuirilor per utilizator.
Decizie.
- Keycloak este sursa master a utilizatorilor: identitate, atribute, credențiale, legături de federare.
- Editările de utilizatori din consolă apelează Keycloak Admin API prin reconcilier (
JobSincronizarede tipUTILIZATOR). Resetările de credențiale și acțiunile obligatorii (required actions) îl apelează sincron, deoarece nu reprezintă stare dorită. ProiectieUtilizatoreste reîmprospătată în trei moduri:- din evenimente;
- printr-o sincronizare completă nocturnă per realm (paginată, 500 pe pagină);
- la cerere, când un utilizator este deschis.
Stochează sub, username, numele, e-mailul,
idnp(criptat), starea activ/inactiv, tipurile MFA, ultima autentificare și realm-ul.
- Ștergerea unui utilizator în Keycloak elimină proiecția și anonimizează câmpurile de actor din tabelele de lucru ale GSSO. Rândurile de audit păstrează doar
sub.
Consecințe.
- (+) Fără dublă sursă master; utilizatorii federați (LDAP/MPass) sunt vizibili.
- (−) Proiecția poate întârzia cu câteva secunde; consola afișează momentul „reîmprospătat la”.
GSSO-ADR-009 — Un singur model de integrare pentru aplicații
Section titled “GSSO-ADR-009 — Un singur model de integrare pentru aplicații”Statut: Acceptat (2026-10-06)
Context.
- În prezent există patru modele (raportul 00 §2).
- Modelul A, cu JWT-uri HS512 emise de aplicație după autentificarea în Keycloak, păstrează o cheie locală de semnare și parole locale. Aceasta anulează logout-ul SSO, revocarea și auditul.
Decizie.
| Tip de aplicație | Model |
|---|---|
| Gateway JHipster + microservicii (playbook) | Gateway = client OAuth2 (BFF, authorization code + PKCE, confidențial). Microservicii = resource servers. Totul prin gsso-spring-boot-starter |
| Monolit Spring Boot cu SPA | Resource server prin starter; SPA = client public + PKCE prin @gstack/gsso-angular (sau modul BFF) |
| Serviciu-la-serviciu | Client credentials, câte un client confidențial per serviciu apelant; token exchange pentru apeluri în numele utilizatorului (GSSO-ADR-012) |
| Clienți Kafka | SASL OAUTHBEARER cu client credentials ale serviciului |
| Mobil (gsso_mob) | Client public + PKCE + redirect cu schemă personalizată |
| Servicii non-Java (Python RAG, Node) | Validare prin JWKS; fragment de cod documentat |
- Starter-ul (
systems.esempla.gsso:gsso-spring-boot-starter):- validarea issuer-ului și JWKS plus un validator de audiență;
roles→ autorități, cu o hartă de aliasuri opțională pentru migrare;GssoPrincipalcare expunesub,username,orgUnit,locale,idnp?;- un interceptor client-credentials pentru
RestClient/WebClientși un helper pentru token exchange; - un listener pentru evenimentele de revocare (GSSO-ADR-013);
- un
KeycloakHealthIndicatorîn grupul readiness; - un helper Testcontainers.
Reutilizează cod verificat din
gregistry(AudienceValidator) șicancelarie(KeycloakHealthIndicator).
- Biblioteca Angular (
@gstack/gsso-angular): login PKCE (sau modul sesiune BFF), un guard de rol și directiva*gssoHasRole, reîmprospătare silențioasă, logout unic și sincronizarea limbii din claim-ullocale. - Parolele locale și token-urile emise de aplicație sunt interzise pentru aplicațiile noi și eliminate din cele existente pe durata migrării (raportul 03 §2).
Consecințe.
- (+) O singură analiză de securitate acoperă toate aplicațiile; logout-ul și revocarea funcționează peste tot.
- (−) Aplicațiile cu modelul A (interdictii, gdocs, gnotify) necesită modificări de cod, planificate în raportul 05.
GSSO-ADR-010 — Stiva DEV-PLAYBOOK
Section titled “GSSO-ADR-010 — Stiva DEV-PLAYBOOK”Statut: Acceptat (2026-10-06)
Decizie.
gsso: JHipster 9.1.0,applicationType: microservice.- Pachetul
systems.esempla.gsso,authenticationType: oauth2(chiar GSSO, realm-ulgstack), Maven, PostgreSQL, Kafka. languages: ro,ru,encuronativ,skipClient: true.- Entitățile din
gsso.jdl.
- Pachetul
gsso-gateway: JHipster 9.1.0applicationType: gateway. Este BFF-ul pentrugsso-web(clientulgsso-console, confidențial) și punctul unic de intrare API; rutează doar/api/v1/**și/api/v1/app/**.gsso-web: un SPA Angular separat pe@gstack/gds-angular/@gstack/gds-core, cu temagdsThemedCss('#7c3aed')(--gds-accent-gsso), i18n ro/ru/en.keycloak/: extensiile (modul Maven, Java 21, Keycloak SPI 26.6.x), temele (FreeMarker + CSS GDS) și baseline-urile realm-urilor.- Versiunile Java, Spring Boot, Angular, PostgreSQL și Kafka sunt exact cele generate de JHipster 9.1.0, fixate la S0. Orice abatere necesită un ADR.
- Inițializare (bootstrapping): consola se autentifică chiar în Keycloak-ul pe care îl gestionează. Dacă GSSO este indisponibil, Keycloak și toate autentificările continuă să funcționeze; doar guvernanța este suspendată.
Consecințe.
- (+) Același set de instrumente și aceleași convenții ca celelalte aplicații gStack.
- (−) Consola depinde de realm-ul
gstack. Accesul de urgență (break-glass) este consola de administrare Keycloakmaster, păstrată doar pentru echipa platformei.
GSSO-ADR-011 — Configurația ca cod
Section titled “GSSO-ADR-011 — Configurația ca cod”Statut: Acceptat (2026-10-06)
Decizie.
- Depozitul conține următoarele, aplicate la momentul implementării de un job unic
gsso-bootstrapcare foloseștekeycloak-config-cli, cu substituție de variabile și fără secrete:keycloak/realms/gstack.json,cetatean.jsonșitenant-template.json: baseline-ul, adică setările realm-ului, fluxurile, client scope-urile, mapper-ele, politica de parole, temele, event listener-ul și cliențiigsso-consoleșigsso-reconciler;keycloak/extensions/(JAR);keycloak/themes/gstack/(login, cont, e-mail);docker-compose.ymlșihelm/.
- Obiectele de runtime (platformele, clienții și rolurile acestora, atribuirile, utilizatorii) sunt deținute de reconcilierul GSSO, nu de fișierele de baseline. Cele două seturi sunt disjuncte, astfel încât bootstrap-ul nu suprascrie niciodată obiectele de runtime.
- Secretele (secretele clienților, credențialele reconcilierului, SMTP, LDAP bind) provin din mediu sau din depozitul de secrete.
.env.exampleenumeră doar denumirile.
Consecințe.
- (+) Un Keycloak poate fi reconstruit din git plus un backup al bazei de date (obiectivul G-4), iar modificările pot fi analizate în merge request-uri.
GSSO-ADR-012 — Token exchange pentru apelurile în numele utilizatorului
Section titled “GSSO-ADR-012 — Token exchange pentru apelurile în numele utilizatorului”Statut: Acceptat (2026-10-06)
Context.
- CAP-GSSO-07: apelurile CRM ↔ gDocFlow ↔ gTenders trebuie să poarte identitatea utilizatorului, astfel încât aplicația apelată să aplice vizibilitatea acestuia.
Decizie.
- Se folosește standard token exchange (V2, internal-to-internal) din Keycloak, disponibil în 26.x.
- Fiecare platformă-țintă are un client scope de audiență.
- Un client-sursă poate face schimbul doar pentru audiențele enumerate în
ClientAplicatie.audienteSchimb. GSSO reconciliază aceste liste în permisiunile de token exchange sau în politicile de client. - Token-urile obținute prin schimb:
- păstrează
subal utilizatorului; - setează
audla țintă; - poartă
act.sub= clientul apelant; - sunt limitate la rolurile platformei-țintă.
- păstrează
- Impersonarea și schimbul external-to-internal sunt dezactivate.
Consecințe.
- (+) Delegare cu privilegiu minim, fără transmiterea parolelor utilizatorilor sau a token-urilor cu durată lungă de viață.
- (−) Perechile permise trebuie întreținute; ele sunt vizibile în consolă și în raportul 03.
GSSO-ADR-013 — Revocare în 60 s
Section titled “GSSO-ADR-013 — Revocare în 60 s”Statut: Acceptat (2026-10-06)
Context.
- CAP-GSSO-03/04 cer ca un utilizator sau un rol revocat să piardă accesul în 60 s (relaxat la 5 min în unele pachete).
- Resource server-ele validează JWT-urile offline, astfel încât un rol revocat rămâne într-un token de acces neexpirat.
Decizie.
- Durata de viață a token-ului de acces: 5 min în
gstack; 2 min pentru clienții marcațisensitive. - La revocare, expirare, dezactivarea utilizatorului sau „închiderea sesiunilor”, GSSO:
- elimină maparea sau dezactivează utilizatorul;
- șterge sesiunile utilizatorului în Keycloak (
logoutal utilizatorului, care declanșează și back-channel logout către clienții care îl suportă); - publică
gsso.access-revoked.v1pe Kafka cusub, rolurile de platformă afectate și un moment not-before.
- Starter-ul consumă
gsso.access-revoked.v1și păstrează în memorie o listă de interdicție (deny list) indexată dupăsub+ not-before, pe durata de viață a token-ului. O cerere cu un token emis înainte de momentul not-before primește 401. - Gateway-urile BFF își elimină, de asemenea, sesiunea de pe server la back-channel logout.
Alternative luate în considerare.
- Introspecția token-ului la fiecare cerere: respinsă din cauza latenței și a încărcării Keycloak pentru toate aplicațiile. Rămâne disponibilă pentru endpoint-urile foarte sensibile.
Consecințe.
- (+) Revocare în 60 s pentru aplicațiile care folosesc starter-ul. Celelalte se bazează pe expirarea token-ului (maximum 5 min).
GSSO-ADR-014 — Triajul EU AI Act
Section titled “GSSO-ADR-014 — Triajul EU AI Act”Statut: Acceptat (2026-10-06)
Decizie.
- GSSO nu este un sistem de IA în sensul Reg. (UE) 2024/1689 art. 3 alin. (1). Nu conține inferență, scoring sau clasificare (ranking) a persoanelor.
- Autentificarea bazată pe risc (MFA adaptiv pe baza semnalelor de IP sau de dispozitiv), dacă va fi adăugată ulterior, trebuie să fie bazată pe reguli și documentată. Orice scoring bazat pe ML necesită un nou triaj conform skill-ului
ai-actînainte de proiectare.
GSSO-ADR-015 — Operațiunile asupra utilizatorilor sunt apeluri directe, auditate, la Admin API
Section titled “GSSO-ADR-015 — Operațiunile asupra utilizatorilor sunt apeluri directe, auditate, la Admin API”Statut: Propus (2026-10-06). Modifică o frază din GSSO-ADR-008.
Context.
- GSSO-ADR-008 prevede că editările de utilizatori din consolă trec prin reconcilier ca
JobSincronizarede tipUTILIZATOR. - Utilizatorii nu sunt stare dorită: Keycloak este sursa lor master.
- Crearea unui utilizator trebuie să returneze imediat consolei id-ul său Keycloak, iar un administrator se așteaptă ca o dezactivare sau o închidere a sesiunilor să aibă efect imediat, nu după o coadă.
Decizie.
- Operațiunile asupra utilizatorilor apelează sincron Keycloak Admin API prin
KeycloakAdminClient: creare, editare, activare/dezactivare, acțiuni obligatorii (required actions), eliminarea credențialelor, închiderea sesiunilor, deblocare. - Fiecare operațiune reușită adaugă un
EvenimentGssoîn aceeași cerere și reîmprospăteazăProiectieUtilizator. - Erorile Keycloak sunt mapate la RFC 7807: 409 conflict, 400 validare, 502 pentru eșecurile Keycloak.
- Coada reconcilierului rămâne pentru starea dorită: realm-uri, clienți, roluri și, din S2, mapările de roluri ale atribuirilor.
Consecințe.
- (+) Feedback imediat și nicio coadă pentru operațiunile care nu reprezintă stare dorită.
- (−) O indisponibilitate Keycloak face ca operațiunile asupra utilizatorilor să eșueze imediat, în loc să fie amânate; consola afișează eroarea.
GSSO-ADR-016 — Detalii de implementare ale reconcilierului
Section titled “GSSO-ADR-016 — Detalii de implementare ale reconcilierului”Statut: Propus (2026-10-06). Rafinează GSSO-ADR-004; deciziile de acolo rămân valabile.
Context. Construirea și testarea S1 pe Keycloak 26.6.3 au evidențiat cinci aspecte pe care GSSO-ADR-004 le-a lăsat deschise sau le-a tratat greșit.
Decizie.
- Client Admin. Un client JSON subțire peste Spring
RestClient(KeycloakAdminClient) înlocuieștekeycloak-admin-client. Stiva RESTEasy a bibliotecii se potrivește prost cu Spring Boot 4, iar GSSO folosește o mică parte din API. Fiecare apel Keycloak trece în continuare prin această singură clasă. - Marcaj de proprietate.
gsso.managedia două valori:catalog: creat de reconcilier, care poate actualiza și șterge obiectul;baseline: deținut de fișierele baseline ale realm-ului sau de șablonul de tenant; reconcilierul nu îl modifică și nu îl șterge niciodată, iar detectarea drift-ului îl ignoră. Obiectele nemarcate sunt negestionate: raportate, niciodată șterse. O singură valoaretruear fi permis modului ENFORCE să șteargă clientul consolei și rolul implicitROLE_USERdin fiecare realm de tenant.
- Token de acces lightweight pentru
gsso-reconciler. Opțiuneaclient.use.lightweight.access.token.enabled. Un token complet poartă rolurile de administrare ale fiecărui realm creat de reconcilier și depășește limitele antetelor HTTP (HTTP 431) după câteva zeci de realm-uri. De asemenea, claim-urile sale devin învechite imediat după crearea unui realm (HTTP 403). Cu token-ul lightweight (≈780 de octeți, constant), Keycloak verifică permisiunile în timp real. Un 403 declanșează în continuare o reîmprospătare a token-ului și o reîncercare. - Ordonare. Worker-ul preia joburile scadente cu
FOR UPDATE SKIP LOCKEDși nu preia niciodată un realm care are deja un jobRUNNING, astfel încât joburile unui realm se aplică pe rând și în ordinea id-ului, inclusiv cu mai multe instanțe (GSSO-FR-079). - Clase de eșec.
- Tranzitorii: niciun răspuns, 401, 429, 5xx. Reîncercate cu backoff exponențial (1 s → 5 min),
FAILEDdupă 10 încercări. - Permanente: alte 4xx sau un obiect deținut de baseline.
FAILEDimediat.
- Tranzitorii: niciun răspuns, 401, 429, 5xx. Reîncercate cu backoff exponențial (1 s → 5 min),
Consecințe.
- (+) Fiecare aspect este acoperit de teste de integrare pe un Keycloak real (
ReconcilerIT). - (−) Clientul subțire trebuie extins manual când sunt necesare apeluri noi la Admin API.