Stavební blok GovStack: Implementujte moduly digitální správy
Jak implementovat digitální vládní služby pomocí modulárního přístupu GovStack: stavební blok pro identitu, platby, souhlas, digitální záznamy a zasílání zpráv. GovSpecs 2.0 (2025–2027), přijato více než 20 zeměmi jako paradigma pro škálovatelné a interoperabilní OOP.
GovStack: Modulární rámec pro digitální vládu
GovStack je mezinárodní iniciativa zahájená v roce 2020 Estonsko, Německo, ITU (Mezinárodní telekomunikační unie) e DIAL (Digital Impact Alliance) s cílem je sdílet nástroje, znalosti a osvědčené postupy potřebné k budování služeb digitální publikum ve velkém, aniž byste museli pokaždé začínat od nuly.
Základní myšlenka je jednoduchá, ale účinná: namísto vývoje monolitických systémů pro každou zemi vládní digitální služba je rozložena na BuildingBlock (funkční moduly), které nabízejí specifickou schopnost (totožnost, platby, zasílání zpráv, registry atd.) a to lze je libovolně kombinovat a budovat jakoukoli službu. Stavební bloky jsou interoperabilní, opakovaně použitelný a nezávislý na implementaci: GovStack definuje specifikace, nikoli software.
V roce 2025, se spuštěním GovSpecs 2.0 (strategie 2025–2027), GovStack vylepšil integrací nových stavebních bloků, aktualizací specifikací interoperability a definováním odstupňovaný model vyspělosti na podporu zemí s velkou digitální kapacitou jiný. Více než 20 zemí aktivně využívá přístup GovStack.
Co se naučíte
- 9 základních stavebních bloků GovStack a jejich technické specifikace
- Jak mapovat stávající italské PA služby (SPID, CIE, pagoPA) na GovStack Building Blocks
- Referenční architektura GovStack: vrstvený model a integrační sběrnice
- GovSpecs 2.0: co je nového ve strategii 2025–2027
- Praktická implementace Building Block Identity s OpenID Connect
- Building Block Payments: integrace s národními platebními systémy
- Consent Building Block: Správa souhlasu v souladu s GDPR
- Jak vyhodnotit, zda je GovStack vhodný pro váš kontext
9 základních stavebních kamenů
GovStack definuje 9 základních stavebních bloků (publikovaných v nové specifikaci 2025), které pokrývají křížové funkce nezbytné pro jakoukoli digitální vládní službu:
| BuildingBlock | Funkce | Protokoly / standardy | Italský příklad |
|---|---|---|---|
| Identita | Autentizace a správa identit | OIDC, SAML, W3C DID | Peněženka SPID, CIE, EUDI |
| Platby | Zpracování plateb a převodů | ISO 20022, REST API | payPA |
| Souhlas | Sběr a správa souhlasů | Rozsahy GDPR, DPIA, OAuth | CMP s GDPR-by-Design |
| Digitální registry | Vedení autoritativních registrů (matrika, katastr nemovitostí) | REST API, FHIR, CKAN | ANPR, katastr nemovitostí, profesní rejstřík |
| Zasílání zpráv | Bezpečná komunikace mezi vládou a občany | SMTP, Push, WebSocket, MQTT | IO App, PEC, upozornění pagoPA |
| Zprostředkování informací | Bezpečná výměna dat mezi systémy | X-Road, REST, GraphQL | PDND, AgID interoperabilita |
| Registrace | Registrace osob/subjektů pro služby | REST API, OAuth 2.0 | Portál INPS, SUAP, komunální portály |
| Plánovač | Správa schůzek a rezervací | iCalendar, REST API | Health CUP, digitální počítadlo |
| Pracovní postup | Orchestrování procesů a procedur | BPMN, vzor SAGA, REST | Systémy řízení praxe PA |
Referenční architektura GovStack
GovStack navrhuje vrstvenou architekturu, ve které jsou stavební bloky umístěny ve vrstvách s jasnými povinnostmi:
- Vrstva 0 – Infrastruktura: cloud, síť, zabezpečení. BB nejsou závislé na konkrétním cloudu; mohou běžet na AWS, Azure, GCP nebo on-premise infrastruktuře.
- Vrstva 1 - Základní stavební bloky: 9 základních BB. Jsou to autonomní služby, které odhalují Standardizovaná RESTful API. Každý BB má veřejnou specifikaci (schemata OpenAPI + JSON).
- Vrstva 2 – Sdílené služby: průřezové služby, jako je centralizované protokolování, síť služeb, API brána, zjišťování služeb. Tyto služby podporují všechny BB.
- Vrstva 3 – Aplikace: skutečné digitální služby (zápis do školy, žádost o certifikát, platba kolkovného), které řídí podkladové BB.
# Architettura di un servizio PA con Building Block GovStack
# Esempio: Servizio di iscrizione scolastica online
# Il servizio orchestra 5 Building Block:
# 1. Identity BB - autenticazione genitore con SPID/CIE
# 2. Registration BB - raccolta dati del bambino
# 3. Digital Registries BB - verifica iscrizione anagrafica
# 4. Consent BB - consenso al trattamento dati minori
# 5. Messaging BB - conferma iscrizione via IO App/email
# 6. Payments BB - pagamento tassa iscrizione via pagoPA
from dataclasses import dataclass
from typing import Optional
import httpx
@dataclass
class SchoolEnrollmentRequest:
parent_session_token: str # Token da Identity BB (SPID/CIE)
child_fiscal_code: str
school_code: str
year: int
class SchoolEnrollmentService:
"""
Servizio iscrizione scolastica che orchestra i Building Block GovStack.
Pattern: Saga orchestrator (gestione stati distribuiti con compensazioni).
"""
def __init__(
self,
identity_bb_url: str,
registry_bb_url: str,
consent_bb_url: str,
messaging_bb_url: str,
payments_bb_url: str
):
self.identity_url = identity_bb_url
self.registry_url = registry_bb_url
self.consent_url = consent_bb_url
self.messaging_url = messaging_bb_url
self.payments_url = payments_bb_url
async def process_enrollment(self, request: SchoolEnrollmentRequest) -> dict:
"""
Saga: processo iscrizione con compensazioni in caso di errore.
Ogni step è idempotente e reversibile.
"""
saga_log = []
try:
# Step 1: Verifica identità genitore tramite Identity BB
parent_identity = await self._verify_parent_identity(
request.parent_session_token
)
saga_log.append({"step": "identity_verified", "status": "ok"})
# Step 2: Verifica residenza bambino tramite Digital Registries BB
child_registry = await self._verify_child_in_registry(
request.child_fiscal_code,
parent_identity["fiscal_number"]
)
saga_log.append({"step": "registry_verified", "status": "ok"})
# Step 3: Raccolta consenso GDPR tramite Consent BB
consent_id = await self._collect_consent(
parent_identity["fiscal_number"],
purpose="school_enrollment_data_processing"
)
saga_log.append({"step": "consent_collected", "consent_id": consent_id})
# Step 4: Registrazione iscrizione tramite Registration BB
enrollment_id = await self._register_enrollment(
child_fc=request.child_fiscal_code,
school_code=request.school_code,
year=request.year,
parent_fc=parent_identity["fiscal_number"]
)
saga_log.append({"step": "enrollment_registered", "enrollment_id": enrollment_id})
# Step 5: Pagamento tassa (se prevista) tramite Payments BB
payment_url = await self._create_payment(
parent_fc=parent_identity["fiscal_number"],
enrollment_id=enrollment_id,
amount_cents=1500 # 15 euro
)
saga_log.append({"step": "payment_created", "payment_url": payment_url})
# Step 6: Notifica conferma tramite Messaging BB
await self._send_confirmation(
parent_fc=parent_identity["fiscal_number"],
enrollment_id=enrollment_id,
payment_url=payment_url
)
saga_log.append({"step": "notification_sent", "status": "ok"})
return {
"status": "success",
"enrollment_id": enrollment_id,
"payment_url": payment_url,
"saga_log": saga_log
}
except Exception as e:
# Compensazione: rollback degli step completati in ordine inverso
await self._compensate(saga_log, e)
raise
async def _verify_parent_identity(self, session_token: str) -> dict:
"""Chiama il Building Block Identity per validare il token SPID/CIE."""
async with httpx.AsyncClient() as client:
response = await client.post(
f"{self.identity_url}/v1/tokens/validate",
json={"token": session_token}
)
response.raise_for_status()
return response.json() # Returns: fiscal_number, name, surname, etc.
async def _verify_child_in_registry(self, child_fc: str, parent_fc: str) -> dict:
"""Chiama il Building Block Digital Registries per verificare l'anagrafe."""
async with httpx.AsyncClient() as client:
response = await client.get(
f"{self.registry_url}/v1/citizens/{child_fc}/family-relations",
params={"parent_fiscal_code": parent_fc}
)
response.raise_for_status()
return response.json()
async def _collect_consent(self, parent_fc: str, purpose: str) -> str:
"""Registra il consenso tramite il Building Block Consent."""
async with httpx.AsyncClient() as client:
response = await client.post(
f"{self.consent_url}/v1/consents",
json={
"citizen_pseudonym": self._pseudonymize(parent_fc),
"purpose": purpose,
"legal_basis": "GDPR Art. 6(1)(e)",
"version": "2025-01"
}
)
response.raise_for_status()
return response.json()["consent_id"]
async def _compensate(self, saga_log: list, error: Exception):
"""
Compensazione Saga: rollback in ordine inverso degli step completati.
Garantisce consistenza anche in caso di errori parziali.
"""
for step in reversed(saga_log):
try:
if step["step"] == "consent_collected":
await self._revoke_consent(step["consent_id"])
elif step["step"] == "enrollment_registered":
await self._cancel_enrollment(step["enrollment_id"])
except Exception as compensation_error:
# Logga l'errore di compensazione ma continua
print(f"Compensation error for {step['step']}: {compensation_error}")
def _pseudonymize(self, fiscal_code: str) -> str:
import hashlib, hmac
key = b"secret-vault-key" # In produzione: usa un HSM
return hmac.new(key, fiscal_code.encode(), hashlib.sha256).hexdigest()[:32]
GovSpecs 2.0: Co je nového ve strategii 2025–2027
GovSpecs 2.0, oznámený GovStack v roce 2025, zavádí důležité aktualizace k předchozí verzi specifikací:
- 4úrovňový model zralosti: z "Počáteční fáze" (pouze školení a architektura vysoká úroveň) na „pokročilou integraci“ (více BB integrovaných do vnitrostátních rámců interoperability). To umožňuje zemím přijmout GovStack podle svých vlastních priorit a schopností.
- Podpora pro ověřitelné přihlašovací údaje: Building Block Identity nyní obsahuje specifikace pro W3C Verifiable Credentials, v souladu s eIDAS 2.0 a evropským programem EUDI Wallet.
- DO BB: nový stavební blok pro integraci komponent umělé inteligence (jazykové modely, predikce, klasifikace) ve vládních službách s důrazem na transparentnost a vysvětlitelnost.
- Specifikace OpenAPI 3.1: Všechna BB API jsou nyní zdokumentována s OpenAPI 3.1, s Kompletní schémata JSON a testovatelné příklady prostřednictvím SwaggerUI.
- Testování shody: Automatizovaný rámec pro ověření implementace of BB vyhovuje specifikacím GovStack.
Implementace Building Block Identity s OIDC
Identita stavebního bloku je nejkritičtější a nejsložitější na implementaci. GovStack určuje, že musí vystavit následující rozhraní API:
# Building Block Identity - Implementazione minima conforme GovStack
# OpenAPI 3.1 compatible - FastAPI implementation
from fastapi import FastAPI, HTTPException, Header, Depends
from fastapi.security import HTTPBearer
from pydantic import BaseModel
from typing import Optional
import jwt
app = FastAPI(
title="Identity Building Block",
description="GovStack Identity BB - Conforme a GovSpecs 2.0",
version="2.0.0"
)
security = HTTPBearer()
# --- Modelli ---
class TokenValidationRequest(BaseModel):
token: str
expected_acr: Optional[str] = None # Livello autenticazione richiesto
class IdentityResponse(BaseModel):
sub: str # Identificativo presso l'IdP
fiscal_number: Optional[str] = None # Codice Fiscale (SPID/CIE)
given_name: str
family_name: str
birthdate: Optional[str] = None
acr: str # Livello autenticazione effettivo
auth_time: int # Timestamp autenticazione
session_valid_until: int # Scadenza sessione
class SessionCreationRequest(BaseModel):
idp_id: str # Identity Provider scelto dall'utente
redirect_uri: str
acr_values: str = "https://www.spid.gov.it/SpidL2"
scope: list = ["openid", "profile"]
ui_locales: str = "it"
# --- Endpoints del Building Block Identity ---
@app.post("/v1/sessions",
summary="Avvia sessione di autenticazione",
tags=["Sessions"],
response_model=dict)
async def create_authentication_session(request: SessionCreationRequest) -> dict:
"""
GovStack Identity BB - Avvia il flusso di autenticazione.
Restituisce l'URL di redirect verso l'IdP.
"""
# Genera state e nonce per sicurezza
import secrets
session_id = secrets.token_urlsafe(32)
state = secrets.token_urlsafe(32)
nonce = secrets.token_urlsafe(32)
# Recupera metadata dell'IdP dalla federazione OIDC
idp_metadata = await get_idp_metadata(request.idp_id)
# Costruisce URL autorizzazione (PKCE + Request Object)
auth_url = build_oidc_auth_url(
idp_auth_endpoint=idp_metadata["authorization_endpoint"],
client_id=CLIENT_ID,
redirect_uri=request.redirect_uri,
scope=request.scope,
state=state,
nonce=nonce,
acr_values=request.acr_values,
private_key=SIGNING_KEY
)
# Salva sessione (Redis o DB)
await session_store.save(session_id, {
"state": state, "nonce": nonce, "idp_id": request.idp_id
})
return {"session_id": session_id, "authorization_url": auth_url}
@app.post("/v1/tokens/validate",
summary="Valida un token di sessione",
tags=["Tokens"],
response_model=IdentityResponse)
async def validate_token(request: TokenValidationRequest) -> IdentityResponse:
"""
GovStack Identity BB - Valida un token e restituisce l'identità.
I servizi chiamanti usano questo endpoint per verificare l'autenticazione.
"""
try:
# Decodifica e valida il token (firma, scadenza, audience)
claims = jwt.decode(
request.token,
JWKS,
algorithms=["RS256"],
audience=CLIENT_ID
)
# Verifica livello autenticazione se richiesto
if request.expected_acr:
actual_acr = claims.get("acr", "")
if not _meets_acr_requirement(actual_acr, request.expected_acr):
raise HTTPException(
status_code=403,
detail=f"Insufficient authentication level. Required: {request.expected_acr}"
)
return IdentityResponse(
sub=claims["sub"],
fiscal_number=claims.get("fiscal_number"),
given_name=claims["given_name"],
family_name=claims["family_name"],
birthdate=claims.get("birthdate"),
acr=claims.get("acr", ""),
auth_time=claims.get("auth_time", 0),
session_valid_until=claims.get("exp", 0)
)
except jwt.ExpiredSignatureError:
raise HTTPException(status_code=401, detail="Token expired")
except jwt.InvalidTokenError as e:
raise HTTPException(status_code=401, detail=f"Invalid token: {str(e)}")
@app.delete("/v1/sessions/{session_id}",
summary="Termina sessione (logout)",
tags=["Sessions"])
async def end_session(session_id: str) -> dict:
"""
GovStack Identity BB - Logout con propagazione verso l'IdP.
Implementa OIDC Back-Channel Logout per notificare tutti i RP attivi.
"""
session = await session_store.get(session_id)
if not session:
raise HTTPException(status_code=404, detail="Session not found")
# Notifica logout all'IdP (OIDC Back-Channel Logout)
idp_metadata = await get_idp_metadata(session["idp_id"])
if "end_session_endpoint" in idp_metadata:
await propagate_logout(idp_metadata["end_session_endpoint"], session)
await session_store.delete(session_id)
return {"status": "session_terminated"}
def _meets_acr_requirement(actual: str, required: str) -> bool:
"""Verifica che il livello di autenticazione effettivo soddisfi il requisito."""
ACR_LEVELS = {
"https://www.spid.gov.it/SpidL1": 1,
"https://www.spid.gov.it/SpidL2": 2,
"https://www.spid.gov.it/SpidL3": 3,
"https://www.cie.gov.it/cie/aa": 2,
}
return ACR_LEVELS.get(actual, 0) >= ACR_LEVELS.get(required, 0)
Building Block Messaging: IO aplikace a vládní oznámení
Building Block Messaging řídí komunikaci mezi vládou a občany. V Itálii služba je více v souladu se specifikací GovStack Messaging I App (io.italia.it), národní aplikace pro komunikaci s PA spravovanou společností PagoPA S.p.A.
# Building Block Messaging - Integrazione con IO App
# API REST di IO App per invio messaggi ai cittadini
import httpx
from pydantic import BaseModel
from typing import Optional
class IOMessage(BaseModel):
fiscal_code: str # Codice Fiscale del destinatario
time_to_live: int = 3600 # Secondi di validità notifica push
content: dict # Contenuto del messaggio
default_addresses: Optional[dict] = None # Fallback email
class IOAppClient:
"""
Client per le API di IO App.
Le API IO App sono disponibili su https://developer.io.italia.it
"""
def __init__(self, api_key: str):
self.api_key = api_key
self.base_url = "https://api.io.italia.it/api/v1"
async def send_message(self, message: IOMessage) -> dict:
"""
Invia un messaggio a un cittadino tramite IO App.
Il cittadino deve aver attivato il proprio profilo IO.
"""
async with httpx.AsyncClient() as client:
response = await client.post(
f"{self.base_url}/messages",
headers={
"Ocp-Apim-Subscription-Key": self.api_key,
"Content-Type": "application/json"
},
json={
"fiscal_code": message.fiscal_code,
"time_to_live": message.time_to_live,
"content": message.content,
"default_addresses": message.default_addresses
}
)
response.raise_for_status()
return response.json()
async def check_profile(self, fiscal_code: str) -> bool:
"""
Verifica se un cittadino ha attivato il profilo IO e accetta messaggi dalla PA.
"""
async with httpx.AsyncClient() as client:
response = await client.get(
f"{self.base_url}/profiles/{fiscal_code}",
headers={"Ocp-Apim-Subscription-Key": self.api_key}
)
if response.status_code == 404:
return False
response.raise_for_status()
profile = response.json()
return profile.get("sender_allowed", False)
# Utilizzo: notifica iscrizione scolastica
async def notify_enrollment(fiscal_code: str, enrollment_id: str, payment_url: str):
io_client = IOAppClient(api_key="your-io-api-key")
# Verifica se il cittadino usa IO App
has_io = await io_client.check_profile(fiscal_code)
if has_io:
# Messaggio strutturato IO App con CTA pagamento
message = IOMessage(
fiscal_code=fiscal_code,
content={
"subject": f"Iscrizione Scolastica {enrollment_id} - Conferma",
"markdown": f"""
## La tua iscrizione è stata registrata
L'iscrizione con codice **{enrollment_id}** è stata registrata con successo.
Per completare la procedura, effettua il pagamento della tassa di iscrizione tramite il
link qui sotto.
**Importo**: 15,00 €
[Paga ora]({payment_url})
Per assistenza: [Ufficio Scolastico](https://istruzione.comune.esempio.it)
""",
"payment_data": {
"amount": 1500,
"notice_number": enrollment_id,
"payee": {
"fiscal_code": "COMUNE_FC",
"name": "Comune di Esempio"
}
}
},
default_addresses={"email": None} # No fallback email
)
await io_client.send_message(message)
else:
# Fallback: email tradizionale (da implementare)
await send_email_notification(fiscal_code, enrollment_id, payment_url)
Mapa GovStack na italském ekosystému
Itálie má již pokročilý ekosystém OOP, který se přirozeně mapuje na stavební bloky GovStack. Pro italského vývojáře přijetí GovStack neznamená začít od nuly: znamená to reorganizovat stávající integrace podle standardizovaného modulárního modelu.
| BB GovStack | Italská implementace | Úroveň zralosti | Mezera k vyplnění |
|---|---|---|---|
| Identita | SPID, CIE, eIDAS | Vysoká (úroveň 3–4) | Kompletní sjednocení OIDC, EUDI Wallet |
| Platby | payPA | Vysoká (úroveň 4) | Kompletní GPD REST API |
| Zasílání zpráv | IO aplikace, PEC | Vysoká (úroveň 3) | Penetrace IO App (v některých oblastech stále nízká) |
| Digitální registry | ANPR, katastr nemovitostí, PDND | Střední (úroveň 2–3) | Interoperabilita mezi registry je stále částečná |
| Zprostředkování informací | PDND | Střední (úroveň 2) | Adopce PDND stále roste |
| Souhlas | Různé (nestandardizované) | Nízká (úroveň 1) | Potřebujeme centralizovanou platformu pro konsensus |
| Plánovač | Krajský zdravotní POHÁR | Nízký-Střední (úroveň 1-2) | Regionální fragmentace; žádný národní standard |
| Pracovní postup | PA cvičné systémy (heterogenní) | Nízká (úroveň 1) | Velká heterogenita; je potřeba standardizace |
Kdy přijmout GovStack
GovStack je zvláště vhodný, když:
- Stavíte a nová digitální služba PA od nuly a chcete se vyhnout závislosti na dodavatelích
- Potřebujete integrovat stávající systémy a chtít sdílený referenční architektonický model
- Působíte v kontextu mnohonárodnostní (mezinárodní spolupráce, přeshraniční služby)
- Chcete přispívat do open source ekosystému GovStack a těžit z implementací v jiných zemích
GovStack je méně vhodný, když máte velmi specifické služby pro italský kontext, když systémy stávající (SPID, pagoPA) již splňují vaše požadavky bez režie dodatečné abstrakce, nebo když máte omezené prostředky ke správě složitosti distribuované federace.
Závěr: Série GovTech v perspektivě
Tento článek uzavírá sérii GovTech věnovanou digitalizaci veřejné správy. Prozkoumali jsme celý ekosystém: od veřejné digitální infrastruktury (DPI) po identitu Evropská unie (eIDAS 2.0, EUDI Wallet), od konkrétní implementace SPID a CIE k ochraně dat (GDPR-by-Design), od přístupnosti (WCAG 2.1 AA) po otevřená data (DCAT-AP_IT, CKAN) až mezinárodní modulární rámce (GovStack).
Společné vlákno je vždy stejné: veřejné digitální služby musí být včetně, bezpečné, interoperabilní a opakovaně použitelné. GovStack se svými standardizovanými stavebními bloky dodává společný slovník a sdílený architektonický model k dosažení těchto cílů v celosvětovém měřítku.
Celá řada GovTech
- #00: Digitální veřejná infrastruktura – architektura a stavební blok
- #01: eIDAS 2.0 a EUDI Wallet – příručka pro vývojáře
- #02: OpenID Connect for Government Identity
- #03: Open Data API Design – publikování a konzumace veřejných dat
- #04: GDPR-by-Design - Architektonické vzory pro veřejné služby
- #05: Přístupné uživatelské rozhraní pro implementaci PA - WCAG 2.1 AA
- #06: Integrace vládního API - SPID, CIE a IT digitální služby
- #07: GovStack Building Block - (tento článek)







