ehds_logging/lib.rs
1// SPDX-FileCopyrightText: Cadasto B.V.
2// SPDX-License-Identifier: BUSL-1.1
3
4//! The European logging software component of an EHR system (Regulation (EU)
5//! 2025/327 Art 2(2)(o), Art 25(1), Annex II 3.2 to 3.4).
6//!
7//! The Regulation asks an EHR system that gives healthcare providers or
8//! other individuals access to personal electronic health data to record, on
9//! every access event or group of events, who accessed the data, which
10//! natural person, the categories of the data, when, and where the data came
11//! from (Annex II 3.2). This crate is that record and what classifies it:
12//!
13//! - [`record`]: the [`AccessRecord`](record::AccessRecord), with the data
14//! subject and the purpose of use beside the five points of 3.2;
15//! - [`category`]: the Art 14(1) categories and the national categories a
16//! deployment declares;
17//! - [`map`] and [`classify`]: the deployment's map from template and
18//! archetype ids to categories, and the classification of one access by
19//! the model ids of what it reached;
20//! - [`retention`]: how long a record is kept, by its categories and its
21//! origins, never under the three years of Art 9(2);
22//! - [`label`]: the security labels a record carries for its categories and
23//! its origins, so the store that holds it can limit who reads it
24//! (Annex II 3.4);
25//! - [`emergency`]: the purposes of use a deployment declares as asserting
26//! an access in the vital interests of the data subject (Art 11(5)), and
27//! the mark of a record whose accessor declared one;
28//! - [`transformation`]: the record of a semantic transformation an access
29//! applied, which rides on its access record (eHealth Network General
30//! Guidelines Release 3.1 Art 6(3));
31//! - [`sink`]: where records go, and why one could not be stored;
32//! - [`withheld`]: the holds a product keeps on resources it delays the
33//! person's access to (Art 3(3)), and the person's own access trail (Art 9)
34//! read without the records about a held resource until the hold ends;
35//! - `balp` (feature `balp`): the record written as an IHE BALP `AuditEvent`
36//! through `ihe-atna`, and the sink over an `ihe-atna` audit recorder;
37//! - `atna` (feature `atna`): the record written as a DICOM PS3.15 A.5 audit
38//! message from the same exchange, for an ITI-20 syslog sender.
39//!
40//! The crate depends on no interoperability component and on nothing of the
41//! system that builds the records, so the logging component stays independent
42//! of the interoperability component (Art 2(2)(n), (o)).
43//!
44//! # Examples
45//!
46//! ```
47//! use std::collections::BTreeMap;
48//!
49//! use ehds_logging::category::Category;
50//! use ehds_logging::classify::{Basis, Evidence, RootObject};
51//! use ehds_logging::map::{CategoryMap, Declared};
52//!
53//! let templates = BTreeMap::from([(
54//! "Example Lab Report.v1".to_owned(),
55//! Declared::Codes(vec!["Laboratory-Reports".to_owned()]),
56//! )]);
57//! let map = CategoryMap::declare(&[], &templates, &BTreeMap::new())?;
58//! let read = RootObject {
59//! template_id: Some("Example Lab Report.v1".to_owned()),
60//! ..RootObject::default()
61//! };
62//! let classified = map.classify(&Evidence::reached(Basis::Returned, vec![read]));
63//! assert!(classified.categories().contains_key(&Category::MedicalTestResult));
64//! assert!(classified.unclassified().is_none());
65//! # Ok::<(), ehds_logging::map::MapError>(())
66//! ```
67
68#![doc(test(attr(deny(warnings))))]
69
70#[cfg(feature = "atna")]
71pub mod atna;
72#[cfg(feature = "balp")]
73pub mod balp;
74pub mod category;
75pub mod classify;
76pub mod emergency;
77pub mod label;
78pub mod map;
79pub mod record;
80pub mod retention;
81pub mod sink;
82pub mod transformation;
83pub mod withheld;