GDPR-by-Design: Architektonické vzory pro veřejné služby
Jak integrovat ochranu osobních údajů již od návrhu digitálních služeb PA: architektonické vzory, techniky pseudonymizace, minimalizace dat a správy souhlasu v souladu s článkem 25 GDPR.
Privacy by Design in PA: regulační povinnost a architektonická volba
Obecné nařízení o ochraně osobních údajů (GDPR), které vstoupilo v platnost 25. května 2018, se neomezuje pouze na ukládání povinností byrokratické pro orgány veřejné správy: Článek 25 stanoví, že ochrana údajů musí být integrována již od fáze návrhu informačních systémů a procesů, které zpracovávají osobní údaje. Tento princip, známý jako Privacy by Design, mění dodržování předpisů v jeden architektonická kvalita softwaru.
Pro vývojáře nebo architekta pracujícího na italských PA systémech - digitální registr, elektronický zdravotní záznam, servisní přístupové portály s SPID nebo CIE, systémy řízení administrativních procedur - pochopit a implementovat správně GDPR-by-Design není volitelné. Sankce stanovené Garantským orgánem pro ochranu osobních údajů mohou dosáhnout 4 % celosvětového ročního obratu soukromých subjektů; pro CHÚ důsledky zahrnují blokády ošetření, náhradu škody a značné poškození dobrého jména.
Co se dozvíte v tomto článku
- 7 základních principů Privacy by Design a jak je namapovat na konkrétní architektonická rozhodnutí
- Pseudonymizační a anonymizační vzory pro databáze a vládní API
- Implementace vzoru minimalizace dat v mikroslužbách PA
- Consent management: architektura a implementace systému v souladu s GDPR
- Automatické uchovávání dat a právo na vymazání v relačních databázích
- Vyhovující protokolování auditu: jak sledovat léčbu bez narušení soukromí
- DPIA (Data Protection Impact Assessment) pro vysoce rizikové systémy
7 základních principů a jejich dopad na architekturu
Ann Cavoukian, bývalá komisařka pro informace a soukromí z Ontaria, formalizovala 7 principů Privacy by Design, které GDPR bylo implementováno. Každý princip se promítá do konkrétních architektonických voleb:
| princip PbD | Článek GDPR | architektonický vzor | Konkrétní techniky |
|---|---|---|---|
| Proaktivní, nereaktivní | článek 25 | Soukromí modelování hrozeb | Posouzení rizika ochrany soukromí ve fázi návrhu |
| Soukromí jako výchozí | 25 odst. 2 | Přihlaste se ve výchozím nastavení | Výslovný souhlas, standardně minimalizace |
| Integrováno do designu | 25 odst. 1 | Privacy-Embedded Architecture | Pseudonymizace, šifrování v klidu |
| Plná funkčnost | článek 5 | Vyhýbání se nulovému součtu | Soukromí + zabezpečení nejsou v rozporu |
| End-to-end zabezpečení | článek 32 | Obrana do hloubky | TLS, šifrování, správa klíčů |
| Viditelnost a transparentnost | Článek 13/14 | Audit trail + zveřejnění | Anonymizované protokolování, upozornění na ochranu osobních údajů |
| Respektování soukromí uživatelů | Článek 7/8/17 | Ovládací prvky zaměřené na uživatele | Uživatelské rozhraní pro souhlas, právo být zapomenut, přenositelnost |
Vzor 1: Minimalizace dat v PA Microservices
Zásada minimalizace (čl. 5 odst. 1 písm. c) GDPR) vyžaduje, aby shromažďované údaje byly „přiměřené, relevantní a omezené na to, co nezbytné s ohledem na účely, pro které jsou zpracovávány“. V architektuře mikroslužeb se to promítá do vzoru Minimalizace dat na hranici: každá služba musí přijímat pouze data, která potřebuje k provedení jeho specifická funkce.
Zvažte službu ověření identity, abyste získali přístup ke zdravotní péči. Služba nepotřebuje název úplné informace občana k ověření, že má na dávku nárok: stačí mu anonymní identifikátor a oprávněný stav. Vzor je implementován přes Selektivní objekty DTO (Data Transfer Objects). e projekční dotazy.
# Pattern Data Minimization - Esempio Python/FastAPI
# Scenario: servizio prestazioni sanitarie PA
from pydantic import BaseModel
from typing import Optional
import hashlib
# SBAGLIATO: trasferisce dati non necessari
class CitizenFullDTO(BaseModel):
citizen_id: str
fiscal_code: str
first_name: str # Non necessario per verifica
last_name: str # Non necessario per verifica
birth_date: str # Non necessario per verifica
address: str # Non necessario per verifica
phone: str # Non necessario per verifica
# CORRETTO: minimizza i dati al minimo necessario
class CitizenEligibilityDTO(BaseModel):
# Solo un token opaco, non il codice fiscale reale
pseudonymous_id: str
is_eligible: bool
benefit_category: str
# Nessun dato personale identificativo
# Service layer con minimizzazione
class HealthBenefitService:
def __init__(self, citizen_repo, pseudonym_service):
self.citizen_repo = citizen_repo
self.pseudonym_service = pseudonym_service
def check_eligibility(self, pseudonymous_id: str, benefit_code: str) -> CitizenEligibilityDTO:
# Risolve il pseudonimo solo internamente, non lo espone
real_id = self.pseudonym_service.resolve(pseudonymous_id)
# Query mirata: solo il dato necessario
is_eligible = self.citizen_repo.check_benefit_eligibility(
citizen_id=real_id,
benefit_code=benefit_code
)
return CitizenEligibilityDTO(
pseudonymous_id=pseudonymous_id,
is_eligible=is_eligible,
benefit_category=benefit_code
)
# NON ritorna: nome, CF, indirizzo, telefono, email
# Repository con projection query (minimizzazione lato DB)
class CitizenRepository:
def check_benefit_eligibility(self, citizen_id: str, benefit_code: str) -> bool:
# SELECT solo la colonna necessaria, non SELECT *
query = """
SELECT EXISTS(
SELECT 1 FROM citizen_benefits
WHERE citizen_id = {citizen_id}
AND benefit_code = {benefit_code}
AND valid_until >= CURRENT_DATE
)
"""
return self.db.execute(query, {"citizen_id": citizen_id, "benefit_code": benefit_code}).scalar()
Vzor 2: Pseudonymizace a tokenizace
Pseudonymizace (definovaná v čl. 4 odst. 5 GDPR) je jedním z technických opatření výslovně zmíněných v čl. 25 lajků adekvátní k prokázání souladu s Privacy by Design. Liší se od anonymizace: Pseudonymizovaná data mohou být zpětně vysledován k zainteresované straně prostřednictvím dodatečných informací uchovávaných odděleně, zatímco anonymní údaje nikoli mohou být (a tedy nepodléhají GDPR).
U systémů PA je pseudonymizace často výhodnější než anonymizace, protože vám umožňuje udržovat vnitřní sledovatelnost (nezbytná pro audit a dodržování předpisů) při současné ochraně identity subjektů údajů v systémech front-end a v protokolech.
# Pattern Pseudonimizzazione con Vault separato
# Architettura: Pseudonym Vault isolato dal sistema principale
import secrets
import hmac
import hashlib
from datetime import datetime, timedelta
from dataclasses import dataclass
@dataclass
class PseudonymRecord:
pseudonym: str
real_id: str
created_at: datetime
expires_at: datetime
purpose: str # Finalità del trattamento (Art. 5(1)(b))
class PseudonymVault:
"""
Vault isolato che gestisce la mappatura pseudonimo <-> identità reale.
Accesso ristretto: solo servizi autorizzati con chiave vault.
Log di ogni accesso per audit GDPR.
"""
def __init__(self, vault_key: bytes, db_connection):
self._vault_key = vault_key
self._db = db_connection
def create_pseudonym(
self,
real_id: str,
purpose: str,
validity_days: int = 365
) -> str:
"""
Genera pseudonimo crittograficamente sicuro.
Usa HMAC-SHA256 con chiave vault per essere deterministico
(stesso real_id + purpose = stesso pseudonimo) ma non invertibile
senza la chiave vault.
"""
# HMAC deterministico: stesso input = stesso output
# Ma non reversibile senza vault_key
pseudonym_bytes = hmac.new(
key=self._vault_key,
msg=f"{real_id}:{purpose}".encode(),
digestmod=hashlib.sha256
).digest()
# Converti in stringa URL-safe
pseudonym = pseudonym_bytes.hex()[:32] # 128-bit, abbondante
# Registra nel vault (separato dal DB principale)
record = PseudonymRecord(
pseudonym=pseudonym,
real_id=real_id,
created_at=datetime.utcnow(),
expires_at=datetime.utcnow() + timedelta(days=validity_days),
purpose=purpose
)
self._db.insert_pseudonym(record)
return pseudonym
def resolve_pseudonym(self, pseudonym: str, requesting_service: str) -> str:
"""
Risolve pseudonimo -> identità reale.
Richiede autorizzazione esplicita del servizio richiedente.
Logga ogni accesso per audit.
"""
# Audit log obbligatorio
self._log_resolution_access(
pseudonym=pseudonym,
requesting_service=requesting_service,
timestamp=datetime.utcnow()
)
record = self._db.get_pseudonym(pseudonym)
if not record:
raise ValueError("Pseudonym not found")
if datetime.utcnow() > record.expires_at:
raise ValueError("Pseudonym expired")
return record.real_id
def _log_resolution_access(self, pseudonym: str, requesting_service: str, timestamp: datetime):
"""
Log GDPR-compliant: registra chi ha risolto quale pseudonimo e quando.
Il log stesso usa solo lo pseudonimo (non l'identità reale).
"""
self._db.insert_audit_log({
"action": "PSEUDONYM_RESOLVED",
"pseudonym_hash": hashlib.sha256(pseudonym.encode()).hexdigest(),
"requesting_service": requesting_service,
"timestamp": timestamp.isoformat(),
"legal_basis": "GDPR Art. 6(1)(e) - Task public interest"
})
Vzor 3: Správa souhlasu v souladu s GDPR
Souhlas (čl. 7 GDPR) musí být volné, konkrétní, informované a jednoznačné. Pro PA ve většině V některých případech není zpracování založeno na souhlasu, ale na různých právních základech (čl. 6 odst. 1 písm. e): úkol veřejného zájmu, o Čl. 6 odst. 1 písm. c): právní povinnost). Pokud je však zvoleným právním základem souhlas – například pro komunikaci marketing, newslettery nebo volitelné zpracování — systém správy souhlasu musí splňovat přesné požadavky.
Un Platforma pro správu souhlasu (CMP) pro PA si musí zapamatovat: co bylo přijato, kdy, s kým verze informací, z kterého kanálu, a musí umožňovat odvolání tak snadné, jak bylo poskytnutí.
-- Schema SQL: Consent Management GDPR-compliant
-- Database separato o schema isolato con accesso controllato
CREATE TABLE consent_purposes (
purpose_id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
code VARCHAR(64) UNIQUE NOT NULL,
name_it TEXT NOT NULL,
name_en TEXT,
description_it TEXT NOT NULL,
legal_basis VARCHAR(32) NOT NULL, -- 'consent', 'legal_obligation', 'public_task'
data_categories TEXT[] NOT NULL, -- Categorie di dati trattati
retention_days INTEGER NOT NULL,
third_parties TEXT[], -- Destinatari (trasparenza)
created_at TIMESTAMPTZ DEFAULT NOW(),
version INTEGER NOT NULL DEFAULT 1,
is_active BOOLEAN DEFAULT TRUE
);
CREATE TABLE citizen_consents (
consent_id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
-- Pseudonimo, non ID reale
citizen_pseudonym VARCHAR(64) NOT NULL,
purpose_id UUID REFERENCES consent_purposes(purpose_id),
status VARCHAR(16) NOT NULL CHECK (status IN ('granted', 'denied', 'withdrawn')),
granted_at TIMESTAMPTZ,
withdrawn_at TIMESTAMPTZ,
-- Prova del consenso (Art. 7(1): titolare deve dimostrare il consenso)
proof_channel VARCHAR(32) NOT NULL, -- 'web_portal', 'mobile_app', 'paper'
proof_ip_hash VARCHAR(64), -- Hash dell'IP, non IP raw
proof_session_id VARCHAR(128),
privacy_policy_version VARCHAR(16) NOT NULL,
-- Lingua in cui è stata mostrata l'informativa
consent_language VARCHAR(8) NOT NULL DEFAULT 'it',
user_agent_hash VARCHAR(64)
);
-- Indice per query rapide sulla revoca
CREATE INDEX idx_consents_pseudonym ON citizen_consents(citizen_pseudonym, status);
-- Vista per audit: mostra solo dati necessari al DPO
CREATE VIEW consent_audit_view AS
SELECT
c.consent_id,
c.citizen_pseudonym,
p.code AS purpose_code,
p.name_it AS purpose_name,
c.status,
c.granted_at,
c.withdrawn_at,
c.proof_channel,
c.privacy_policy_version
FROM citizen_consents c
JOIN consent_purposes p ON c.purpose_id = p.purpose_id;
-- Funzione per il diritto di revoca (Art. 7(3))
CREATE OR REPLACE FUNCTION withdraw_consent(
p_citizen_pseudonym VARCHAR(64),
p_purpose_code VARCHAR(64)
) RETURNS VOID AS $
BEGIN
UPDATE citizen_consents
SET
status = 'withdrawn',
withdrawn_at = NOW()
WHERE
citizen_pseudonym = p_citizen_pseudonym
AND purpose_id = (
SELECT purpose_id FROM consent_purposes WHERE code = p_purpose_code
)
AND status = 'granted';
-- Logga l'evento per audit
INSERT INTO consent_events (
event_type, citizen_pseudonym, purpose_code, occurred_at
) VALUES (
'CONSENT_WITHDRAWN', p_citizen_pseudonym, p_purpose_code, NOW()
);
END;
$ LANGUAGE plpgsql;
Vzor 4: Automatické uchovávání dat a právo na vymazání
Zásada „omezení ukládání“ (čl. 5 odst. 1 písm. e) GDPR) vyžaduje, aby byly osobní údaje uloženy "ve formě, která umožňuje identifikaci zainteresovaných stran po dobu nepřesahující dosažení účelů, pro které jsou zpracováványV praxi musí každý PA systém implementovat politiku uchovávání automatické, které bez ručního zásahu vymaže nebo anonymizuje data, jejichž platnost vypršela.
Právo na výmaz (článek 17 GDPR), známé jako „právo být zapomenut“, přidává další vrstvu složitosti: systém musí být schopen na požádání smazat údaje konkrétní fyzické osoby při respektování případných výjimek (například údaje nezbytné pro splnění zákonných povinností).
# Data Retention Manager - Python con scheduling automatico
from apscheduler.schedulers.asyncio import AsyncIOScheduler
from dataclasses import dataclass
from enum import Enum
from datetime import datetime, timedelta
from typing import List
class RetentionAction(Enum):
DELETE = "delete"
ANONYMIZE = "anonymize"
ARCHIVE = "archive"
@dataclass
class RetentionPolicy:
table_name: str
date_column: str
retention_days: int
action: RetentionAction
legal_basis: str # Documentazione dell'obbligo legale
# Registro delle politiche di retention (da configurazione, non hardcoded)
RETENTION_POLICIES: List[RetentionPolicy] = [
RetentionPolicy(
table_name="citizen_session_logs",
date_column="created_at",
retention_days=90, # 3 mesi per log sessione
action=RetentionAction.DELETE,
legal_basis="GDPR Art. 5(1)(e) - Storage limitation"
),
RetentionPolicy(
table_name="service_requests",
date_column="completed_at",
retention_days=2555, # 7 anni per atti amministrativi
action=RetentionAction.ANONYMIZE,
legal_basis="D.Lgs. 82/2005 Art. 40 - Conservazione atti"
),
RetentionPolicy(
table_name="consent_records",
date_column="withdrawn_at",
retention_days=365, # 1 anno dopo revoca per prova
action=RetentionAction.DELETE,
legal_basis="GDPR Art. 7(1) - Prova consenso"
),
]
class DataRetentionManager:
def __init__(self, db, audit_logger):
self.db = db
self.audit_logger = audit_logger
self.scheduler = AsyncIOScheduler()
async def run_retention_policy(self, policy: RetentionPolicy) -> dict:
"""Esegue una politica di retention e ritorna statistiche."""
cutoff_date = datetime.utcnow() - timedelta(days=policy.retention_days)
stats = {"policy": policy.table_name, "action": policy.action.value, "rows_affected": 0}
if policy.action == RetentionAction.DELETE:
result = await self.db.execute(
f"DELETE FROM {policy.table_name} WHERE {policy.date_column} < $1",
cutoff_date
)
stats["rows_affected"] = result.rowcount
elif policy.action == RetentionAction.ANONYMIZE:
# Anonymize: sostituisce dati identificativi con hash o NULL
result = await self.db.execute(
f"""UPDATE {policy.table_name}
SET
fiscal_code = 'ANONYMIZED_' || gen_random_uuid()::text,
first_name = NULL,
last_name = NULL,
email = NULL,
phone = NULL
WHERE {policy.date_column} < $1
AND fiscal_code NOT LIKE 'ANONYMIZED_%'""",
cutoff_date
)
stats["rows_affected"] = result.rowcount
# Audit log obbligatorio per ogni operazione di retention
await self.audit_logger.log({
"event": "RETENTION_EXECUTED",
"policy": policy.table_name,
"action": policy.action.value,
"cutoff_date": cutoff_date.isoformat(),
"rows_affected": stats["rows_affected"],
"legal_basis": policy.legal_basis,
"executed_at": datetime.utcnow().isoformat()
})
return stats
async def handle_erasure_request(self, citizen_pseudonym: str, request_id: str) -> dict:
"""
Gestisce il diritto alla cancellazione (Art. 17 GDPR).
Verifica le eccezioni prima di procedere.
"""
# Verifica eccezioni Art. 17(3) - obblighi legali, interesse pubblico, etc.
exceptions = await self._check_erasure_exceptions(citizen_pseudonym)
if exceptions:
# Non cancella, documenta il motivo del diniego
await self.audit_logger.log({
"event": "ERASURE_REQUEST_DENIED",
"citizen_pseudonym": citizen_pseudonym,
"request_id": request_id,
"reasons": exceptions
})
return {"status": "denied", "reasons": exceptions}
# Procede con la cancellazione
tables_affected = []
for table in ["citizen_session_logs", "consent_records", "service_requests_temp"]:
rows = await self.db.execute(
f"DELETE FROM {table} WHERE citizen_pseudonym = $1",
citizen_pseudonym
)
if rows.rowcount > 0:
tables_affected.append(table)
await self.audit_logger.log({
"event": "ERASURE_REQUEST_EXECUTED",
"citizen_pseudonym": citizen_pseudonym,
"request_id": request_id,
"tables_affected": tables_affected,
"executed_at": datetime.utcnow().isoformat()
})
return {"status": "completed", "tables_affected": tables_affected}
DPIA: kdy je povinný a jak jej strukturovat
La Posouzení dopadu na ochranu údajů (DPIA, Data Protection Impact Assessment) je povinné podle Čl. 35 GDPR při zpracování "může představovat vysoké riziko pro práva a svobody fyzické osobyPro italskou PA zveřejnil Garant ochrany osobních údajů seznam ošetření, která vyžadují DPIA je povinné.
Léčba PA vyžadující povinné DPIA
- Systematické profilování občanů (např. socioekonomické hodnocení)
- Ošetření ve velkém měřítku konkrétních kategorií údajů (zdravotní, soudní)
- Systematický dohled veřejných prostor (video dohled)
- Párovací/propojovací systémy datových sad z různých zdrojů
- Údaje zranitelných osob (nezletilí, pacienti, žadatelé o azyl)
- Inovativní využití technologií (AI/ML pro automatizovaná rozhodnutí, čl. 22)
- Mezinárodní převod osobních údajů
Strukturovaný DPIA zahrnuje: popis zpracování a jeho účelů, posouzení nezbytnosti a přiměřenosti, identifikaci a posouzení rizik pro práva subjektů údajů a předpokládaná opatření k řešení rizik (včetně záruk a bezpečnostních mechanismů). Zapojení DPO (Data Protection Officer) je povinné (čl. 35 odst. 2) a DPIA musí být aktualizovány, když se léčba změní.
Vzor 5: Protokolování auditu v souladu s GDPR
Podceňovaným požadavkem GDPR je odpovědnost (odpovědnost, čl. 5 odst. 2): vlastník léčby musí být schopen prokázat shodu. To vyžaduje systém protokolování auditu, který sleduje operace s osobními údaji, které se však – paradoxně – samy o sobě nestávají zdrojem nadměrného zpracování osobních údajů.
Auditní protokol v souladu s GDPR musí:
- Záznam SZO přistupoval k jakým datům a kdy, s použitím pseudonymů nebo systémových ID, kde je to možné
- Být neměnný (pouze příloha), aby byla zajištěna integrita důkazů
- Mít vlastní zásady uchovávání (protokoly nejsou uchovávány navždy)
- Být chráněn před neoprávněným přístupem (odděleně od hlavní DB)
- Podporujte efektivní dotazy, abyste mohli reagovat na požadavky DPO nebo ručitelského úřadu
# Audit Logger immutabile con PostgreSQL - append-only tramite trigger
# Usa una tabella separata con accesso write-only dall'applicazione
-- Schema audit log (database o schema separato)
CREATE TABLE gdpr_audit_log (
log_id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
-- Identificatori: pseudonimizzati dove possibile
subject_pseudonym VARCHAR(64), -- Chi ha eseguito l'azione
affected_entity_pseudonym VARCHAR(64), -- Su quale entità
-- Cosa è successo
action_type VARCHAR(64) NOT NULL, -- READ, UPDATE, DELETE, EXPORT, etc.
resource_type VARCHAR(64) NOT NULL, -- citizen_record, consent, health_data, etc.
-- Contesto
legal_basis VARCHAR(128), -- Base giuridica del trattamento
purpose VARCHAR(256), -- Finalità del trattamento
-- Metadati tecnici (senza dati personali)
service_name VARCHAR(128) NOT NULL,
request_id VARCHAR(128),
-- Timestamp immutabile
occurred_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
-- NON includere: IP raw, user agent completo, payload della request
);
-- Nega UPDATE e DELETE sulla tabella audit (append-only)
CREATE RULE no_update_audit AS ON UPDATE TO gdpr_audit_log DO INSTEAD NOTHING;
CREATE RULE no_delete_audit AS ON DELETE TO gdpr_audit_log DO INSTEAD NOTHING;
-- Funzione trigger per log automatico su tabelle sensibili
CREATE OR REPLACE FUNCTION audit_sensitive_access() RETURNS TRIGGER AS $
BEGIN
INSERT INTO gdpr_audit_log (
action_type,
resource_type,
subject_pseudonym,
affected_entity_pseudonym,
service_name,
legal_basis
) VALUES (
TG_OP, -- INSERT/UPDATE/DELETE
TG_TABLE_NAME,
current_setting('app.current_user_pseudonym', true),
NEW.citizen_pseudonym,
current_setting('app.service_name', true),
current_setting('app.legal_basis', true)
);
RETURN NEW;
END;
$ LANGUAGE plpgsql SECURITY DEFINER;
-- Applica il trigger alle tabelle sensibili
CREATE TRIGGER audit_health_records
AFTER INSERT OR UPDATE OR DELETE ON health_records
FOR EACH ROW EXECUTE FUNCTION audit_sensitive_access();
Celková architektura: GDPR-by-Design ve službě PA
Když dáme dohromady všechny popsané vzory, architektura služby PA v souladu s GDPR zahrnuje:
- Brána API: Vstupní bod, který ověřuje autentizaci (SPID/CIE), používá pseudonymizaci a propaguje právní základ v kontextu požadavku (prostřednictvím hlavičky nebo middlewaru)
- Pseudonymní trezor: izolovaná služba pro mapování pseudonymu a identity s omezeným přístupem a protokol auditu každého usnesení
- Mikroslužby s minimalizací dat: každá služba přijímá pouze nezbytná data, odhaluje minimální DTO, používat projekční dotazy do DB
- Služba správy souhlasu: spravuje souhlasy, ověřuje právní základy, podporuje odvolání a export dat (přenositelnost čl. 20)
- Plánovač retence: pravidelné úlohy, které uplatňují zásady uchovávání a spravují požadavky zrušení a vypracování zpráv pro DPO
- Služba protokolu auditu: pouze připojení, samostatné, s přístupem pouze pro zápis z aplikace a pouze pro čtení ze strany DPO/ručitele
Užitečné nástroje a rámce pro GDPR-by-Design v PA
- OpenDP: Knihovna Pythonu pro rozdílné soukromí, užitečná pro anonymizované analýzy
- Nástroj pro anonymizaci dat ARX: open source nástroj pro anonymizaci datové sady
- Klíčenka: Poskytovatel identity s otevřeným zdrojovým kódem s vestavěnou podporou správy souhlasu
- Datasketch: pro hašování a MinHash, užitečné při škálovatelné pseudonymizaci
- PgAudit: Rozšíření PostgreSQL pro protokolování auditu na úrovni databáze
- Návrháři Itálie: oficiální pokyny AgID k ochraně soukromí již od návrhu pro PA
- CNIL Privacy by Design Guide: praktická metodika francouzského úřadu platná v Itálii
Role DPO a spolupráce s vývojovým týmem
Podle Čl. 37 GDPR je jmenování pověřence pro ochranu osobních údajů (DPO) povinné pro všechny orgány veřejné moci a orgány veřejné moci (s výjimkou soudů při výkonu jurisdikčních funkcí). DPO není pouze údaj o souladu: pro vývojové týmy zastupuje interního konzultanta pro ochranu dat, který musí být zapojen od počátečních fází projektu.
V praxi by vývojový tým měl:
- Při zpracování osobních údajů zapojit DPO do přezkumu architektury
- Volby návrhu ochrany soukromí dokumentů v Architecture Decision Records (ADR)
- Zahrňte kontroly souladu s GDPR do definic uživatelského příběhu hotovo
- U každé nové funkce, která zavádí zpracování osobních údajů, proveďte Posouzení rizika ochrany soukromí
- Pokud je to možné, aktualizujte registr zpracování (článek 30) automatizovaným způsobem
Závěry a další kroky
GDPR-by-Design není byrokratický kontrolní seznam, který by se měl odškrtnout na konci vývoje: je to architektonický přístup který, pokud je integrován od raných fází projektu, vytváří bezpečnější, transparentnější a robustnější systémy. Vzorce popsané v tomto článku — minimalizace dat, pseudonymizace, správa souhlasu, uchovávání automatické protokolování auditu – vztahují se na jakoukoli digitální službu italské PA, od jednoduché stránka shromažďování souhlasu pro institucionální zpravodaj až po složité systémy, jako je zdravotní záznam elektronické nebo digitální platební platformy.
V dalším článku této série budeme analyzovat, jak implementovat přístupná uživatelská rozhraní pro druhý PA standard WCAG 2.1 AA: další regulační požadavek, který stejně jako GDPR odměňuje ty, kteří jej integrují již ve fázi návrhu.
Související články v této sérii
- GovTech #01: eIDAS 2.0 a EUDI Wallet – evropská digitální identita a ověřitelné přihlašovací údaje
- GovTech #02: OpenID Connect pro vládní identitu – SPID, CIE a osvědčené postupy zabezpečení
- GovTech #05: Přístupné uživatelské rozhraní pro implementaci PA - WCAG 2.1 AA
- GovTech #06: Integrace vládního API - SPID, CIE a pagoPA







