Skip to content

Architettura

SaniKey è una CLI Python locale che costruisce un archivio medico per paziente e lo esporta in una struttura USB statica.

Confine del Repository

Il repository GitHub contiene:

  • codice sorgente sotto src/sanikey
  • test sotto tests
  • script sotto scripts
  • documentazione sotto docs
  • esempi sintetici pubblicabili sotto docs/*-example

Il repository non deve contenere dati reali dei pazienti, nomi reali di pazienti, documenti ospedalieri o nomi di directory locali private. Lo stato operativo privato resta fuori dall'albero pubblicato o in directory ignorate come:

  • config
  • patients
  • generated
  • exports
  • logs

config/accounts.toml è privato e non contiene valori di percorso sicuri di default.

Flusso di Elaborazione

La pipeline implementata è:

  1. Caricare e validare config/accounts.toml.
  2. Applicare gli invarianti di privacy per percorsi privati e file paziente ignorati.
  3. Eseguire la scansione dei documenti sorgente configurati, applicando gli eventuali pattern di esclusione.
  4. Caricare i metadati curati.
  5. Aggiornare localmente FI e RCP AIFA per i riferimenti confermati.
  6. Catalogare supporti DICOM e directory di espansione manuale.
  7. Estrarre il testo supportato e preparare rappresentazioni consultabili.
  8. Verificare FI/RCP locali per ogni terapia AIFA.
  9. Se presente parameters.toml, ricavare slice dai testi già estratti usando esclusivamente regole curate abilitate.
  10. Costruire un archivio SQLite per paziente.
  11. Generare export JSON e la lista tecnica dei documenti non apribili.
  12. Generare i file statici del frontend.
  13. Esportare la build in una struttura USB e scrivere i checksum.

Il comando deploy-usb esegue la build dei pazienti abilitati e poi esporta la struttura USB.

Moduli Principali

  • config.py: analizza e valida la configurazione privata degli account.
  • privacy.py: controlla i confini di privacy del repository e i percorsi ignorati.
  • documents.py: scansiona i documenti, calcola digest, estrae testo supportato, applica esclusioni configurate e rileva duplicati.
  • metadata.py: carica metadati curati da file TOML.
  • parameter_slices.py e parameter_rules.py: scoprono candidati dal testo già estratto e applicano regole curate senza inferenze implicite.
  • leaflets.py: ricerca e verifica riferimenti AIFA, scarica FI/RCP locali e registra la data dell'ultimo download riuscito.
  • markdown.py: converte contenuti Markdown curati o documentali in HTML statico con HTML grezzo disabilitato.
  • dicom.py: cataloga supporti DICOM, legge DICOMDIR, raggruppa istanze per StudyInstanceUID e coalesce i record duplicati dello stesso studio prima della persistenza.
  • database.py: scrive l'archivio SQLite.
  • exports.py: scrive export JSON statici e il bundle dati JavaScript per ricerca, timeline e sommari.
  • frontend.py: renderizza l'entrypoint web statico consultabile anche tramite file://.
  • build.py: coordina la pipeline locale di build paziente e la cache incrementale dell'estrazione testo.
  • usb.py: esporta e valida la struttura USB. Controlla anche link frontend relativi, UUID/fstype/spazio dei target fisici configurati e copia con rsync quando disponibile.
  • cli.py: espone l'interfaccia a riga di comando.

Modello di Paziente Configurato

Ogni voce [[person]] contiene:

  • id: identificativo tecnico stabile in minuscolo.
  • display_name: etichetta visualizzata negli artefatti generati.
  • source_documents: percorso ai documenti sorgente, assoluto oppure relativo alla root del repository quando la configurazione e' config/accounts.toml.
  • metadata_directory: percorso ai metadati curati, assoluto oppure relativo alla stessa base.
  • local_build: percorso degli artefatti generati, assoluto oppure relativo alla stessa base.
  • usb_uuid: UUID atteso del filesystem USB o identificativo di deploy.
  • enabled: booleano opzionale, abilitato per default.

Layout della Costruzione Locale

La radice di build locale è configurata per ciascun paziente. Una build genera attualmente:

medical_archive.db
checksums/
exports/
manifests/
reports/
web/

Il database generato e gli export statici sono artefatti derivati e possono essere ricreati dai documenti sorgente e dai metadati curati.

Struttura USB

La radice USB esportata contiene attualmente:

SANIKEY-MANIFEST.json
index.html
patients/
  patient-a/
    dicom-viewers/
    documents/
    rendered-documents/
    technical/
    medical_archive.db
    web/
      index.html

web è il frontend statico generato sulla chiavetta USB. Nel repository corrisponde agli artefatti frontend generati da frontend.py. Le azioni primarie ai documenti sono relative a patients/<id>/web/index.html e puntano a un originale apribile o a ../rendered-documents/.... Gli originali Office restano download secondari sotto ../documents/.... validate-usb rifiuta payload con path assoluti, URL file://, link rotti o terapie AIFA prive di FI/RCP locali. I FI e gli RCP confermati sono copiati separatamente in patients/<id>/medication-leaflets/; l'export clinico usa quei PDF locali e conserva anche i link AIFA per la verifica online. I viewer HTML DICOM riconosciuti durante lo staging vengono copiati sotto patients/<id>/dicom-viewers/ e linkati dal frontend con viewer_href relativi.

Frontend di Consultazione

Il frontend e' una pagina statica consultabile da file://. I dati essenziali sono esportati in web/data.js come JavaScript locale; il browser non deve effettuare richieste fetch() per mostrare la prima schermata.

La UI e' progettata per PC non noti in anticipo:

  • usa HTML, CSS e JavaScript statici;
  • usa asset Material Web locali vendorizzati, senza CDN o build runtime;
  • evita runtime server;
  • su schermi larghi separa risultati/documenti da timeline e sintesi clinica;
  • su schermi stretti adatta header, ricerca e controlli alla larghezza;
  • mantiene la maschera di ricerca e i link alle sezioni in alto durante la consultazione;
  • mostra i risultati di ricerca senza lasciare la timeline davanti;
  • genera link ai documenti originali relativi al frontend USB, non ai percorsi sorgente del computer di build.

I file DICOM sono artefatti tecnici. Il database può conservarli come record, ma il frontend mostra solo schede aggregate per studio DICOM; ISO, archivi e supporti restano nei dettagli tecnici. Quando un supporto contiene un viewer HTML statico, per esempio IHE PDI, l'export copia la subtree necessaria al viewer e la scheda dello studio espone Apri studio DICOM in un tab separato.

Il PC di consultazione non richiede installazioni, applicazioni esterne o servizi locali. Un viewer nativo del CD non viene avviato dal browser. Gli studi senza viewer HTML compatibile ricevono un fallback statico JPEG generato da SaniKey quando le istanze sono decodificabili. Ogni fallback resta consultabile da file:// e non diagnostico. Il media DICOM standard e il suo DICOMDIR sono esportati una volta per supporto e servono al lettore professionale eventualmente gia' presente sul PC.

La personalizzazione UI e' export-time e viene validata dalla configurazione: [global.ui] definisce i default dell'export, mentre [[person]].ui puo' sovrascriverli per un singolo paziente. I valori accettati sono chiusi per mantenere leggibilita' e supportabilita'.

Funzionalità Rimandate

La prima implementazione lascia intenzionalmente fuori ambito diverse funzionalità:

  • provider AI reali
  • espansione automatica o opzionale di ISO e archivi DICOM riconosciuti dal contenuto
  • embedding semantici
  • cifratura USB
  • integrazione FHIR/HL7
  • supporto mobile/PWA
  • sincronizzazione cloud
  • consultazione assistita da AI
  • pacchettizzazione desktop
  • import/export diretto dal Fascicolo Sanitario

Questi elementi sono tracciati come issue GitHub. - rendering.py: copia o converte in PDF le rappresentazioni apribili dal browser per la consultazione offline.