MedBook
Cartella clinica elettronica self-hosted FHIR R4 + GDPR, per cliniche e medici di base in EU
- Stato
- WIP
- Licenza
- EUPL-1.2
- Categoria
- Healthcare
- Aggiornato
Stato del progetto
Descrizione
MedBook è un sistema di cartella clinica elettronica (EHR) self-hosted progettato per cliniche piccole-medie, ambulatori specialistici e medici di base in area EU che vogliono possedere i propri dati pazienti senza dipendere da SaaS cloud (USA-based). L'architettura è Clean Architecture 4-layer Spring Boot 3.4 con domain JPA-agnostic, frontend Angular 21 zoneless con standalone components e signals, con le rotte cliniche renderizzate esclusivamente nel browser, persistenza PostgreSQL 16 con cifratura applicativa AES-256-GCM (Google Tink) sui campi sensibili e audit a tre livelli. Il modello dati è progettato attorno a FHIR R4 (Patient, Practitioner, Observation, Condition, MedicationStatement, AllergyIntolerance, Procedure, DiagnosticReport) con mapping JPA entity ↔ FHIR Resource via HAPI FHIR library, garantendo interoperabilità con sistemi sanitari nazionali. La sicurezza è first-class: Keycloak SSO con OIDC, RBAC (medico, infermiere, segretaria, admin), registro degli accessi a tre livelli — versionamento, catena HMAC con sigillo giornaliero, registro del database — perché le tabelle di versionamento da sole non sono immutabili, session timeout configurabile, password policy NIST 800-63B compliant. Il consenso GDPR è gestito tramite uno schema dedicato (granular consent per categoria di dati: anamnesi, allergie, esami, terapia farmacologica), con revoca tracciabile. Il consenso non regola la cura, che si fonda sull'art. 9(2)(h) GDPR: governa il dossier condiviso e le condivisioni esterne. Alla richiesta di cancellazione di una cartella clinica soggetta a obbligo di conservazione la risposta ordinaria è il diniego motivato ex art. 17(3)(b)/(c), non l'anonimizzazione. License EUPL-1.2 per allineamento esplicito allo standard EU public sector. Il progetto è disegnato per l'integrazione con il FSE 2.0 e in previsione dell'EHDS: nessuna conformità è dichiarata prima che sia stata verificata. Deploy via Docker Compose o systemd unit, target medico singolo o cluster di 2-20 utenti concorrenti. La filosofia è 'data sovereignty by design': i dati vivono sulla VPS del cliente, niente analytics esterne, niente telemetry, niente CDN per i bundle medici.
Funzionalità chiave
Modello dati FHIR R4 nativo
JPA entity mappate a FHIR Resource (Patient, Observation, Condition, MedicationStatement) via HAPI FHIR, export bundle JSON/XML standard.
Audit a tre livelli, non solo versionamento
Ogni accesso tracciato (operatore, momento, azione, motivo). Envers versiona, ma non è di per sé immutabile: chi ha permessi di scrittura sulle tabelle di versionamento le altera. Perciò l'audit è a tre livelli, con catena HMAC, sigillo giornaliero e revoca dei permessi di modifica.
Keycloak SSO + RBAC granulare
OIDC integration, 4 ruoli predefiniti (medico/infermiere/segretaria/admin), permission matrix configurabile, session timeout per ruolo.
GDPR consent management
Consenso granulare per categoria di dati e revoca tracciabile, distinti dalla base giuridica della cura, che è l'art. 9(2)(h) e non il consenso. Export dei dati su richiesta dell'interessato.
Frontend Angular 21 zoneless
Standalone components, signals reattivi, prerender per le sole pagine pubbliche. Nessun dato clinico è renderizzato lato server: le rotte cliniche sono a rendering nel browser, verificato in build. I token non raggiungono mai il browser (pattern BFF, sessione HttpOnly).
Cifratura applicativa AES-256-GCM
Campi sensibili cifrati nell'applicazione con AES-256-GCM (Google Tink), dati associati legati alla riga, gerarchia di chiavi per struttura. Non pgcrypto: una chiave passata come argomento SQL finisce nelle statistiche delle query e nei log. Ricerca sul codice fiscale via blind index HMAC, per sola uguaglianza esatta.
Backup automatici cifrati
pg_dump notturno cifrato GPG, retention configurabile, opzione Hetzner Storage Box, test restore guidato in documentazione.
Deploy systemd hardened
Unit systemd con NoNewPrivileges, ProtectSystem=strict, PrivateTmp, no Docker required, alternative Docker Compose se preferito.
Tech stack
- Spring Boot 3.4
- Java 21
- Angular 21
- PostgreSQL 16
- HAPI FHIR R4
- Keycloak
- Hibernate Envers
- Google Tink
- Docker Compose
Casi d'uso
- Ambulatorio medico di base che vuole digitalizzare cartelle pazienti senza affidarsi a SaaS US-based
- Clinica specialistica piccola (2-20 utenti) con esigenza di FHIR R4 export per laboratori e specialisti esterni
- Studio dentistico o fisioterapista che gestisce anamnesi e piani terapeutici con vincoli GDPR stringenti
- Ricercatori medici che hanno bisogno di un EHR open-source per studi clinici locali piccoli
Roadmap
- v0.1.0 Pianificata
Core EHR: Patient + Practitioner + Audit
- Modello FHIR Patient + Practitioner mappato JPA
- CRUD endpoint con Keycloak SSO + RBAC base
- Hibernate Envers audit trail attivo su entity sensibili
- Frontend Angular login + dashboard paziente
- v0.5.0 Pianificata
Observation + Condition + Medication
- FHIR Observation + Condition + MedicationStatement
- Export FHIR bundle JSON/XML via endpoint /fhir/Patient/{id}/$everything
- Cifratura applicativa AES-256-GCM su anamnesi e allergie
- GDPR consent UI + revoca + DSAR export
- v1.0.0 Pianificata
FSE 2.0 IT integration + Production deploy
- Connettore FSE 2.0 IT (gateway nazionale)
- Backup automatici cifrati + test restore
- Documentazione MkDocs completa + deploy guide VPS
- Audit di sicurezza pre-release + penetration test (deferito post-MVP)
A chi è rivolto
Quick Start
Avvia il progetto localmente in pochi comandi.
# Quick start (work-in-progress: nessun codice applicativo ancora rilasciato)
# git clone https://github.com/fedcal/MedBook.git
# cd MedBook
# cp .env.example .env # configura DB, Keycloak, gestore delle chiavi
# docker compose up -d # postgres + keycloak + medbook-backend + medbook-frontendContribuisci al progetto
MedBook è open source. Apri una issue, proponi una pull request o lascia una stella su GitHub: ogni contributo, anche piccolo, è benvenuto.
- ⭐ Lascia una stella se ti è utile
- 🐛 Segnala bug o proponi feature via issue
- 🔧 Invia pull request con fix o miglioramenti
- 📣 Condividi il progetto se lo trovi interessante