Tasarım Yoluyla GDPR: Kamu Hizmetlerine Yönelik Mimari Modeller
Kişisel verilerin korunmasının doğrudan PA dijital hizmetlerinin tasarımından nasıl entegre edileceği: mimari modeller, GDPR'nin 25. Maddesine uygun takma ad kullanma, veri minimizasyonu ve izin yönetimi teknikleri.
PA'da Tasarımdan Doğan Gizlilik: düzenleyici bir zorunluluk ve mimari bir seçim
25 Mayıs 2018'de yürürlüğe giren Genel Veri Koruma Yönetmeliği (GDPR), kendisini yükümlülükler getirmekle sınırlandırmıyor kamu idarelerine bürokratik: Madde 25, veri korumanın entegre edilmesi gerektiğini belirtmektedir tasarım aşamasından itibaren Kişisel verileri işleyen bilgi sistemleri ve süreçleri. Bu prensip, olarak bilinir Tasarıma Göre Gizlilik, mevzuat uyumluluğunu tek bir şeye dönüştürür mimari kalite yazılımın.
İtalyan PA sistemleri üzerinde çalışan bir geliştirici veya mimar için - dijital kayıt, elektronik sağlık kaydı, SPID veya CIE'li hizmet erişim portalları, idari prosedür yönetim sistemleri - anlayın ve uygulayın Doğru şekilde GDPR-by-Design isteğe bağlı değildir. Kişisel Verilerin Korunmasına İlişkin Garantör Kurum Tarafından Öngörülen Yaptırımlar özel kuruluşların küresel yıllık cirosunun %4'üne ulaşabiliyorlar; KA’lar için bunun sonuçları arasında ablukalar da yer alıyor. muamele, zararların tazmin edilmesi ve ciddi itibar kaybı.
Bu Makalede Neler Öğreneceksiniz?
- Tasarımdan Dolayı Gizliliğin 7 temel ilkesi ve bunların somut mimari kararlara nasıl yansıtılacağı
- Veritabanları ve devlet API'leri için takma ad kullanma ve anonimleştirme kalıpları
- PA mikro hizmetlerinde veri minimizasyon modelinin uygulanması
- Rıza yönetimi: GDPR uyumlu bir sistemin mimarisi ve uygulanması
- İlişkisel veritabanlarında otomatik veri saklama ve silme hakkı
- Uyumlu denetim günlüğü: gizliliği ihlal etmeden tedavilerin nasıl takip edileceği
- Yüksek riskli sistemler için DPIA (Veri Koruma Etki Değerlendirmesi)
7 Temel İlke ve Mimarlık Üzerindeki Etkileri
Ontario'nun eski Bilgi ve Gizlilik Komiseri Ann Cavoukian, Tasarımdan Doğan Gizliliğin 7 ilkesini resmileştirdi. GDPR uygulamaya konuldu. Her prensip belirli mimari seçimlere dönüşür:
| PbD ilkesi | Madde GDPR | Mimari Desen | Beton teknikleri |
|---|---|---|---|
| Reaktif değil proaktif | Madde 25 | Tehdit Modelleme Gizliliği | Tasarım aşamasında Gizlilik Riski Değerlendirmesi |
| Varsayılan olarak gizlilik | Madde 25(2) | Varsayılan olarak etkinleştirme | Açık onay, varsayılan olarak küçültme |
| Tasarıma entegre | Madde 25(1) | Gizliliğe Gömülü Mimari | Takma ad kullanma, kullanımda olmayan şifreleme |
| Tam işlevsellik | Madde 5 | Sıfır toplamdan kaçınma | Gizlilik + güvenlik birbiriyle çelişmiyor |
| Uçtan uca güvenlik | Madde 32 | Derinlemesine savunma | TLS, şifreleme, anahtar yönetimi |
| Görünürlük ve şeffaflık | Madde 13/14 | Denetim takibi + açıklama | Anonimleştirilmiş günlük kaydı, gizlilik bildirimi |
| Kullanıcı gizliliğine saygı | Madde 7/8/17 | Kullanıcı merkezli kontroller | İzin kullanıcı arayüzü, unutulma hakkı, taşınabilirlik |
Model 1: PA Mikro Hizmetlerinde Veri Minimizasyonu
Minimize etme ilkesi (Madde 5(1)(c) GDPR), toplanan verilerin "yeterli, ilgili ve sınırlı" olmasını gerektirir. işlendikleri amaç bakımından gerekli olması". Bir mikro hizmet mimarisinde bu, kalıba dönüşür Sınırda Veri Minimizasyonu: her hizmet yalnızca gerçekleştirmek için ihtiyaç duyduğu verileri almalıdır onun özel işlevi.
Bir sağlık hizmeti avantajına erişmek için bir kimlik doğrulama hizmetini düşünün. Hizmetin isme ihtiyacı yok yardımdan yararlanma hakkına sahip olduğunu doğrulamak için vatandaşın eksiksiz bilgileri: kendisi ve vatandaş için anonim bir tanımlayıcı yeterlidir hak sahibi olma durumu. Desen aracılığıyla uygulanır Seçici DTO'lar (Veri Aktarım Nesneleri). e projeksiyon sorguları.
# 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()
Model 2: Takma Adlandırma ve Simgeleştirme
Takma ad kullanma (GDPR Madde 4(5)'te tanımlanmıştır), teknikte açıkça belirtilen teknik önlemlerden biridir. 25 beğeni Tasarımdan Dolayı Gizliliğe uygunluğu göstermeye yeterli. Anonimleştirmeden farklıdır: Takma ad verilmiş veriler ayrı tutulan ek bilgiler yoluyla ilgili tarafa kadar takip edilebilirken, anonim veriler saklanmaz olabilir (ve dolayısıyla GDPR'ye tabi değildir).
PA sistemleri için, anonimleştirmeye göre takma ad verme genellikle tercih edilir, çünkü bu, kullanıcı adınızı korumanıza olanak tanır. Sistemlerdeki veri sahiplerinin kimliğini korurken dahili izlenebilirlik (denetim ve uyumluluk için gerekli) ön uçta ve günlüklerde.
# 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"
})
Model 3: GDPR Uyumlu Rıza Yönetimi
Rıza (Madde 7 GDPR) olmalıdır ücretsiz, spesifik, bilgili ve net. KA'lar için çoğu durumda Bazı durumlarda işleme rızaya dayalı olmayıp farklı yasal temellere dayanmaktadır (Mad. 6(1)(e): kamu yararına olan görev, o Sanat. 6(1)(c): yasal zorunluluk). Ancak rıza, seçilen yasal dayanak olduğunda (örneğin iletişimler için) pazarlama, haber bültenleri veya isteğe bağlı işlemler — rıza yönetimi sisteminin kesin gereklilikleri karşılaması gerekir.
Un Rıza Yönetim Platformu (CMP) PA için ezberlemesi gerekiyor: neyin, ne zaman, kiminle kabul edildiği Bilginin hangi kanaldan alınacağına ve iptaline imkan sağlanması da bir o kadar kolay olmalıdır.
-- 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;
Model 4: Otomatik Veri Saklama ve Silme Hakkı
"Depolamanın sınırlandırılması" ilkesi (Mad. 5(1)(e) GDPR) kişisel verilerin saklanmasını gerektirir "Başarıyı aşmayacak bir süre için ilgili tarafların belirlenmesine olanak sağlayacak bir biçimde hangi amaçlarla işlendikleri". Uygulamada her KA sisteminin bir saklama politikası uygulaması gerekir Süresi dolmuş verileri manuel müdahale olmadan silen veya anonimleştiren otomatik.
"Unutulma hakkı" olarak bilinen silme hakkı (Madde 17 GDPR), ek bir karmaşıklık katmanı ekler: sistem, istisnalara saygı göstererek, talep üzerine belirli bir kişinin verilerini silebilmelidir (örneğin, yasal yükümlülüklere uymak için gerekli veriler).
# 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: ne zaman zorunludur ve nasıl yapılandırılır
La Veri Koruma Etki Değerlendirmesi (DPIA, Veri Koruma Etki Değerlendirmesi) zorunludur Sanat uyarınca. 35 GDPR işleme sırasında "hak ve özgürlüklerine yönelik yüksek risk oluşturabilir gerçek kişiler". İtalyan PA için Gizlilik Garantörü, gereken tedavilerin bir listesini yayınladı DPIA zorunludur.
Zorunlu DPIA Gerektiren PA Tedavileri
- Sistematik profil oluşturma vatandaşların sayısı (örn. sosyoekonomik puanlama)
- Büyük ölçekli tedavi belirli veri kategorilerinin (sağlık, adli)
- Sistematik gözetim ortak alanların (video gözetimi)
- Eşleştirme/bağlama sistemleri Farklı kaynaklardan gelen veri kümelerinin
- Savunmasız kişilerin verileri (küçükler, hastalar, sığınmacılar)
- Teknolojilerin yenilikçi kullanımı (Otomatik kararlar için AI/ML Md. 22)
- Uluslararası transfer kişisel verilerin
Yapılandırılmış bir DPIA şunları içerir: işlemenin ve amaçlarının tanımlanması, gereklilik ve orantılılığın değerlendirilmesi, Veri sahiplerinin haklarına yönelik risklerin belirlenmesi ve değerlendirilmesi ile risklere yönelik öngörülen tedbirler (korumalar ve güvenlik mekanizmaları dahil). DPO'nun (Veri Koruma Görevlisi) katılımı zorunludur (Mad. 35(2)) ve tedavi değiştiğinde DPIA güncellenmelidir.
Model 5: GDPR Uyumlu Denetim Günlüğü Kaydı
GDPR'nin hafife alınan bir gerekliliği, sorumluluk (sorumluluk, Madde 5(2)): mal sahibi tedaviye uyum gösterebilmelidir. Bu, bir denetim kayıt sistemi gerektirir. kişisel veriler üzerindeki işlemleri izler ancak paradoksal olarak kendisi bir kaynak haline gelmez Kişisel verilerin aşırı işlenmesi.
GDPR uyumlu bir denetim günlüğü şunları yapmalıdır:
- Kayıt DSÖ Mümkün olduğunda takma adlar veya sistem kimlikleri kullanarak hangi verilere ve ne zaman erişildi?
- Olmak değişmez (yalnızca ekleme) kanıtın bütünlüğünü sağlamak için
- Kendi saklama politikanıza sahip olun (günlükler sonsuza kadar saklanmaz)
- Yetkisiz erişime karşı korunun (ana DB'den ayrı)
- DPO'dan veya Garantör Otoriteden gelen taleplere yanıt vermek için etkili sorguları destekleyin
# 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();
Genel Mimari: Bir KA Hizmetinde Tasarım Yoluyla GDPR
Açıklanan tüm modelleri bir araya getiren Tasarım Yoluyla GDPR uyumlu bir PA hizmetinin mimarisi şunları içerir:
- API Ağ Geçidi: Kimlik doğrulamayı (SPID/CIE) doğrulayan, takma ad kullanan giriş noktası ve talep bağlamında yasal dayanağı yayar (başlık veya ara yazılım yoluyla)
- Takma Ad Kasası: takma ad-kimlik eşlemesi için sınırlı erişime sahip izole hizmet ve her çözümün denetim günlüğü
- Veri minimizasyonlu mikro hizmetler: her hizmet yalnızca gerekli verileri alır, minimum DTO'yu açığa çıkarır, DB'ye projeksiyon sorgularını kullanın
- Rıza Yönetimi Hizmeti: onayları yönetir, yasal dayanakları doğrular, iptali destekler ve veri aktarımı (taşınabilirlik Madde 20)
- Saklama Zamanlayıcısı: saklama ilkelerini uygulayan ve istekleri yöneten periyodik işler iptal etme ve DPO için rapor oluşturma
- Denetim Günlüğü Hizmeti: salt ekleme, ayrı, uygulamadan salt yazma erişimi ve salt okuma erişimiyle DPO/Garantör tarafından
PA'da Tasarıma Göre GDPR için faydalı araçlar ve çerçeveler
- OpenDP: Diferansiyel gizlilik için Python kütüphanesi, anonimleştirilmiş analitikler için kullanışlıdır
- ARX Veri Anonimleştirme Aracı: veri kümesini anonimleştirmeye yönelik açık kaynak araç
- Anahtarlık: Yerleşik izin yönetimi desteğine sahip açık kaynak kimlik sağlayıcısı
- Veri Taslağı: karma ve MinHash için, ölçeklenebilir takma ad vermede kullanışlıdır
- Pg Denetimi: Veritabanı düzeyinde denetim günlüğü kaydı için PostgreSQL uzantısı
- Tasarımcılar İtalya: PA için tasarım gereği gizliliğe ilişkin resmi AgID yönergeleri
- CNIL Tasarım Kılavuzuna Göre Gizlilik: Fransız otoritesinin İtalya'da geçerli pratik metodolojisi
DPO'nun Rolü ve Geliştirme Ekibi ile İşbirliği
Sanat uyarınca. 37 GDPR, Veri Koruma Görevlisinin (DPO) atanması tüm kamu yetkilileri için zorunludur ve kamu kurumları (yargılama işlevlerini yerine getiren mahkemeler hariç). DPO değil yalnızca bir uyumluluk figürü: geliştirme ekipleri için, dahili bir veri koruma danışmanını temsil ediyor. Bir projenin ilk aşamalarından itibaren dahil edilmelidir.
Uygulamada geliştirme ekibi şunları yapmalıdır:
- Kişisel verileri işlerken DPO'yu mimari incelemesine dahil edin
- Mimari Karar Kayıtlarında (ADR) gizlilik tasarımı seçeneklerini belgeleyin
- Tamamlananların kullanıcı hikayesi tanımlarına GDPR uyumluluk kontrollerini dahil edin
- Kişisel verilerin işlenmesini getiren her yeni özellik için Gizlilik Riski Değerlendirmesi yapın
- İşleme Kaydını (Mad. 30) mümkün olduğunca otomatik olarak güncel tutun
Sonuçlar ve Sonraki Adımlar
Tasarım Yoluyla GDPR, geliştirmenin sonunda işaretlenecek bürokratik bir kontrol listesi değildir: mimari bir yaklaşımdır projenin ilk aşamalarından itibaren entegre edildiği takdirde daha güvenli, daha şeffaf ve daha sağlam sistemler üretir. Bu makalede açıklanan modeller — veri minimizasyonu, takma ad kullanma, izin yönetimi, saklama otomatik, denetim kaydı — basit birinden İtalyan PA'nın herhangi bir dijital hizmetine uygulanırlar Sağlık kayıtları gibi karmaşık sistemlere kadar kurumsal bir haber bülteni için onay toplama sayfası elektronik veya dijital ödeme platformları.
Bu serinin bir sonraki makalesinde ikinci PA için erişilebilir kullanıcı arayüzlerinin nasıl uygulanacağını analiz edeceğiz WCAG 2.1 AA standardı: GDPR gibi, onu tasarım aşamasından itibaren entegre edenleri ödüllendiren başka bir düzenleyici gereklilik.
Bu Serideki İlgili Makaleler
- Devlet Teknolojisi #01: eIDAS 2.0 ve EUDI Cüzdan - Avrupa dijital kimliği ve doğrulanabilir kimlik bilgileri
- Devlet Teknolojisi #02: Kamu kimliği için OpenID Connect - SPID, CIE ve en iyi güvenlik uygulamaları
- Devlet Teknolojisi #05: PA - WCAG 2.1 AA uygulaması için erişilebilir kullanıcı arayüzü
- Devlet Teknolojisi #06: Devlet API entegrasyonu - SPID, CIE ve pagoPA







