Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Disclaimer and Consent
All the information on this website is published in good faith and for general information purpose only. SanteSuite Inc. does not make any warranties about the completeness, reliability or accuracy of this information. Any action you take upon the information you find on this website and/or in related documents is strictly at your own risk. SanteSuite Inc. will not be liable for any losses and/or damages in connection with the use of the content.
By using our website and/or related content, you hereby consent to our disclaimer and agree to its terms.
Unless otherwise noted, linked from another author, or hosted/linked on a third party site - all content on this site is licensed under the Creative Commons Share-alike + Attribution (CC-BY-SA) 4.0 license.
For more information see -
Welcome to the SanteSuite Help Portal!
Welcome to the SanteSuite help portal. This portal provides detailed information about the design, configuration and operation of the SanteSuite family of products.
SanteSuite is the collection of software solutions built upon the highly scalable and standards compliant SanteDB Clinical Data Repository (CDR). SanteSuite is designed to operate in an "offline-first" fashion, ideal for frequently disconnected, geographically disperse or low-resource environments. SanteSuite products are also platform agnostic and can be run using common open source infrastructure. SanteSuite solutions provide key digital health infrastructure components for regional or national health systems such as Master Patient/Person Index (MPI) (sometimes known as Client Registry), Master Facility Index (MFI), Master Provider Registry (MPR), National Health Identity Management and Immunization Management Systems (IMS).
SanteDB is a general purpose clinical data repository based loosely on the HL7 Reference Information Model (RIM) which we call the Reduced Reference Information Model (RRIM). SanteDB's CDR has four major platform components:
iCDR - A centralized service for managing data from clinics, tablets, etc. The iCDR provides an implementation of the Reference Information Model (RIM) and offers robust features such as an OAUTH IdP, Audit Repository, versioning, master data management, etc.
dCDR - We call this one a "baby CDR", and provides disconnected access to SanteDB's functions. The dCDR operates completely on its own and offers almost 75% of the functionality of the iCDR. It is the same implementation of the RIM-based information model, and can operate many of the plugins which are developed for the iCDR.
dCDR Gateway - The Disconnected Gateway is a specialized version of the dCDR which combines plugins for HL7v2, ATNA, (and in the future FHIR) and allows clinics who are using third party software such as OpenMRS or OSCAR to leverage dCDR features with standards based interfaces.
SanteDB Act support attribution of the current status of an act using the state machine illustrated in Figure 2.
The states of an act are:
New : Indicates that the act has yet to be reviewed and//or that business processing rules have yet to be executed.
Active : Indicates that an act is currently occurring or being actioned. This state is used, for example, if an encounter is still occurring however has not completed.
Entities also support a basic series of states which identify the current status of the entity in the SanteDB data model. Figure 7 illustrates the states of an entity and the valid transitions.
The states of the entity are:
New : The entity instance was just created, and no processing, storage, or business rules have been executed.
Active : The entity has been persisted, any necessary review and/or processing has occurred, and the entity record is active.
Android / Windows / Linux Apps - These applications are built on the dCDR and provide an extensible user interface platform based on HTML5 and JavaScript. By default, AngularJS is the bundled UI framework, however these applications (and applets) may override this and implement their own interfaces to SanteDB's dCDR services.
SantéIMS, a Digital Public Goods Alliance (DPGA) nominated “global good” (https://digitalpublicgoods.net/registry/), is a proven, purpose-built, person-centered, national-scale immunization management platform that supports planning, end-to-end delivery and realtime reporting of any type or scale of mass vaccination program. SantéIMS comes pre-configured with the standard WHO vaccine schedule but can be configured for any type of program, such as pandemic response for COVID-19 vaccination or HIV inoculation. Its unique, fully integrated design and functionality automates end-to-end vaccination workflows, decision support, and stock management, while at the same time seamlessly automates immunization data feedback loops, aggregate reporting and analytics from local clinic to regional and national levels and beyond. This complete, dedicated vaccination workflow solution has demonstrated significant improvement in efficiency of administering vaccine clinics, simplifies training requirements for staff operating a clinic, speeds up interactions with patients and provides a near real-time national dashboard view of vaccination activity from local clinic to regional and national levels. A purpose-built immunization system such as SantéIMS also enables the implementation of advanced clinical workflows, clinical decision support rules and computable guidelines not often found in general purpose EMRs.
SantéIMS comes pre-configured with the complete WHO vaccine schedule as default, however the schedule and clinical guideline rules are completely customizable to local country or regional needs. SantéIMS supports new clinical workflows such as COVID-19 protocols and can easily be configured support emerging immunization workflows such as HIV and malaria. SantéIMS’s first version (OpenIZ) was funded by PATH (www.PATH.org) in 2016 as part of the Better Immunization Data (BID) initiative and is currently nationally deployed in Tanzania as the Tanzania Immunization Registry (TImR).
Complete : Indicates that the act has occurred. If the act is of a mood code such as intent, request, etc, the complete status indicates that the request or intent is complete and has been fulfilled.
Nullified : Indicates that the act was created in error, and never occurred.
Obsolete : Indicates that the act did occur, however the information is no longer accurate, or has been amended.
Nullified : Indicates that the entity was created in error, the entity never existed.
Obsolete : Indicates that the entity did exist, however it no longer is active.
SanteDB releases have two versions associated with them:
Semantic Version -> Which is used for determining compatibility of assemblies within the SanteDB solutions, dependencies, etc.
Informational Version -> Which is used to describe the overall release.
The semantic versions of SanteDB look similar to this:
Where:
Major: Describes the major release.
Even numbered major versions are release versions
Odd numbered major versions are development versions between releases
SanteDB originally was implemented as a revision of the core OpenIZ backend. This was implemented on .NET Framework 4.5.2, Xamarin and PCL Profile7 assemblies. These versions begin with the major revision 1.x , ending 1.128.0 (Iqaluit).
Since PCL has been deprecated for some time, a refactor of the code to .NET Standard 2.0 was recently performed.
Starting with SanteDB named version Jasper , the entire shared assembly infrastructure has been ported to .NET Standard 2.0. Since these assemblies are incompatible with the PCL infrastructure and .NET 4.5.2, the entire project was upgraded to .NET 4.7 and the major version rev'd to 2.x series.
SanteDB version 3.0 and its related solutions (SanteMPI 3.0, SanteIMS 3.0, SanteEMR 3.0) have many enhancements which improve the efficiency and maintainability of SanteDB products. These features are documented in detail throughout the wiki and tagged with:
In summary the enhancements are detailed in
This section describes the SanteSuite Master Patient Index SanteMPI
SanteMPI is a next generation, fully functional, open-source and standards-compliant Client Registry that was originally developed to support the Canadian national digital health program beginning in 2006. SanteMPI has been enhanced and refined over decades of investment from governments, private sector companies and non-governmental organizations. SanteMPI has been designed to support the longitudinal management of patient data in jurisdictions around the world and has several proven field deployments in low and middle income countries.
A Master Patient Index (MPI), sometimes called a Client Registry (CR), is a foundational piece of any regional or national health system. Fundamentally, a MPI solution seeks to create a single master list of patients across a jurisdiction and to provide a cross-reference of the various identifiers used by local systems in a region to identify a patient. For example, if a patient is registered in Hospital A as patient number 123 and is registered in Primary Clinic B as patient number 456, a Master Patient Index configured in the region will keep track of these various identifiers and provide a list of them to any system on demand. This enables health care providers to see a "longitudinal view" of a patient, that is, all interactions of the patient with various components of the health care system over time.
SantéMPI is a fully functional, national scale, open-source, and standards-compliant Master Patient Index (MPI) / Client Registry (CR) designed for regional and national health system use. SantéMPI was originally developed as a reference implementation to support the Canadian national digital health program administered by Canada Health Infoway (infoway.ca) beginning in 2006. SantéMPI has been enhanced and refined over decades of investment from various government agencies, private sector companies and non-governmental organizations. SantéMPI has been designed to support the longitudinal management of patient data in jurisdictions around the world and has several proven field deployments in low and middle income countries. SantéMPI has proven to be secure, scalable, reliable, performant, fully featured, standards-compliant, inexpensive and easy to support.
The SantéSuite team that developed SantéMPI have also made significant contributions to the underlying international standards used for MPI/CR systems, including the HL7 v2/v3 and HL7 FHIR standards, the OpenHIE Architecture Specification Client Registry solution, and the IHE patient identity mobile profiles (PIXm and PDQm). These contributions have enhanced the standards to allow for the efficient unique identification of patients even while using low resource mobile devices.
SantéMPI implements all existing interoperable specifications and requirements related to Client Registry in the OpenHIE specification. SantéMPI is fully compliant to operate within a health information exchange (HIE) environment as a Client Registry. SantéMPI has been field tested with millions of successful transactions in multiple jurisdictions, and can operate standalone or as a launching point into a health information exchange. By implementing both modern HL7 FHIR standards and the widely deployed existing legacy HL7v2 standards, SantéMPI provides a platform for integrating existing solutions and future solutions. In this context, SantéMPI has demonstrated integrations with WorldVistA EHR, OpenMRS and OSCAR EMR.
SantéMPI leverages the unique online/offline capability and data architecture of SantéDB by building on our lessons learned developing and implementing the MEDIC CR, especially in low resource environments. SantéMPI meets the stated functional requirements of the OpenHIE Specification for a client registry. Key features of SantéMPI that directly address these requirements include:
Online/Offline Capability – Leveraging SantéDB’s Disconnected Clinical Data Repository (dCDR), SantéMPI is unique in being able to operate offline when and where needed via an online/offline MPI gateway to/from a centrally hosted server or cloud hosted CR service. Clients on the offline gateway can use HL7 v2.5 or HL7 FHIR to perform MPI functions while offline. This offline capability has been proven to be incredibly important in low resource environment where brownouts, blackouts and lack of connectivity situations are commonplace.
Privacy & Security by Design – SantéMPI leverages the SantéDB CDR, which implements a robust privacy and security solution allowing for access control and privacy controls based on role, device, and third-party application via a policy based access control scheme. Security and Privacy are designed into the solution, not bolted on as an afterthought.
Interoperability Standards Support – SantéMPI supports a variety of standards for patient registration including IHE PIX/PDQ (for HL7v2) and HL7 FHIR. It also provides a completely open API for further extension. The SantéSuite team has made significant contributions to health information standards, including being early contributors to HL7 FHIR, as well as authoring the IHE profiles for mobile access to patient identifiers and this platform has previously passed IHE and HL7 Connectathons.
Probabilistic Matching – SantéMPI leverages a customizable record linkage algorithm for detecting whether two or more existing records are the same.
Master Data Management – SantéMPI provides basic master data management functionality, allowing a single record of truth to be synthesized from data submitted from local sources.
Administration Management – SantéMPI provides extensive administrative user interfaces to provide a robust administrative solution.
Mobile Registration App – A mobile registration app has been developed to support search and registration of patients in real time in the field, offering the ability to issue a health identifier to a new client. This app also leverages QR codes as temporary health identifier for easy generation and recognition of a health identifier.
SanteMPI bundles together existing functions of SanteDB (MDM, Matching, Entity Linking, etc.) and exposes additional logic on top of those interfaces to ensure it is a PIX/PDQ compliant product. SanteMPI works in both the SanteDB iCDR and the dCDR, that's right, you can run a mini-MPI offline in a local clinic between systems.
The SanteDB Clinical Data Repository (CDR) is designed for large-scale regional/national digital health applications. Solutions running on SanteDB may be deployed in dozens, hundreds or even thousands of clinics across a widespread region. In these scenarios, there will be times where individual clinics or points of service will lose connectivity, and this is especially true in geographically sparse and/or low resource environments. SanteDB was designed from the ground up to support this highly distributed scenario and is equipped with a robust synchronization engine that allows individual clinics to go online and offline as they require, while still allowing users to continue to work in their applications without being uninterrupted and without losing any clinical data. When clinics are able to re-establish connectivity, all transactions are synchronized seamlessly between local data stores and the central repository. Each remotely deployed application instance (for example in a clinic, mobile, or anywhere "out on the field") maintains a local version of SanteDB referred to as the distributed clinical data repository or "dCDR". The main central clinical data repository is referred to as the integrated clinical data repository or "iCDR". There is no predefined limit as to how long dCDR apps are able to work offline before they reconnect with the iCDR.
SanteDB solutions run on top of the CDR and are pre-configured, pre-packaged plugins which extend SanteDB to provide a solution to a clinical problem. SanteDB has several solutions targeted to individual clinical domains and use cases, including national health identifiers, master patient index/client registry solutions, national immunization planning and tracking solutions, a distributed EMR and more. The following diagram illustrates how applications make use of SanteDB by extending the base functionality of the SanteDB Core:
SanteGuard : The SanteGuard solution is a complete audit repository solution. The SanteGuard solution contains:
.NET Based Plugins for the SanteDB dCDR and iCDR which allow SanteDB to accept IHE ATNA messages.
Applet Widgets which extend the other SanteDB solution user interfaces to add detailed auditing information for system administrators.
Extended data storage schemas and plugins to store information related to audit log review workflows.
SanteEMR : The SanteEMR solution is a framework which provides basic EMR functionality such as scheduling, registration, patient management, clinical templates, etc. Included:
Patient Registration and Search Management Workflows
Clinical Templates for birth, death, and basic primary care events.
SanteIMS : The SanteIMS solution provides extended user interfaces and clinical protocol support related specifically to immunizaiton clinics. Included in SanteIMS:
Stock management functionality including adjustments, current balances, and order/fulfillment
Pre-built clinical decision support related to immunization activities.
SanteMPI : The SanteMPI solution provides a combination of pre-configured plugins for the SanteDB CDR to work as an MPI. Inlcuded:
.NET based plugins which modify the behavior of the HL7v2 and FHIR interfaces to implement IHE PIX, PDQ constraints.
Plugins for name aliasing
These solutions provide a basis for community extensions to create branded versions of the underlying applications.
This section provides documentation related to the SanteDB Clinical Data Repository (CDR) and related technologies.
SanteDB is the foundational clinical data repository (CDR) developed by SanteSuite Inc. and leveraged by SanteSuite products. SanteDB is standards-based and highly scalable and is designed for large-scale (regional and national) digital health application deployments.
SanteDB forms the core of the SanteSuite product line and provides a robust, secure, repository for modeling and sharing clinical data.
Although each of the products built upon SanteDB provide the most clinical value, the platform itself provides the fundamental building blocks required to create disconnected, intelligent health applications. Features of SanteDB include:
Openness
100% Open Architecture, any application can play in the SanteDB ecosystem.
Core platform components and community applets are openly documented and source code provided.
SanteDB solutions such as SanteMPI, SanteIMS, and the generic CDR are installed in a similar manner. This section provides resources on the planning, preparation, installation and securing of SanteDB iCDR and dCDR software packages.
When installing SanteDB in a development environment, we recommendfor your iCDR instance and then .
You can then and follow the article to start developing SanteDB applications!
Installing SanteDB in a production environment is an involved process which is dependent on the nature of the environment (hospital, province, national, etc.) as well as the specific requirements of the project management office involved.
The SanteDB has collected a high-level guide to the deployment of the SanteDB services like SanteMPI in our guide.
Determiner codes are used to classify whether a tuple in the entity table represents an actual thing or a classification of things. There are three types of determiner classifications for objects listed in .
Determiner
Description
Example
Specific
The entry in the database represents a one or more occurrences of an entity.
A patient, a facility, an organization, etc.
Kind
The entry represents a classification of entities.
A type of material, a type of organization, a type of device.
Additionally, Acts are classified by Mood via the MoodConceptId. The mood of an act identifies the mood or method of operation of the act, moods include:
Mood
Code
Description
Proposal
PRPS
Indicates that the act was proposed by a system process such as a business rule, or clinical protocol.
Intent
INT
Indicates that a human intends to perform the act in the future, however the act has not yet occurred.
SanteDB software packages support many different environments and use cases. The underlying software is attempting to provide a common structure into which data/processes can be realized. Because of this there are two different distributions of SanteDB software, which can be installed in an operational environment.
The iCDR is typically installed once per application role in a jurisdiction. (See:).
SanteDB iCDR ServerThe dCDR is installed on the client side or in an aggregate setting as a gateway (or mini CDR). The distribution of the dCDR software and its installation is unique to each platform. This wiki covers the configuration of the dCDR to an iCDR instance.
A SanteDB deployment is not like installing Microsoft Office, or a video game. SanteDB is responsible for storing very sensitive personal health information (PHI) and the deployment of SanteDB in any role (MPI, MFR, MPR, SHR, etc.) warrants careful planning and consideration.
This section will guide your through some of the common planning activities that should be undertaken prior to deploying any of the SanteDB solutions/components in your environment.
These test cases are based on the OpenHIE CR tests for HL7v2 transactions, and contain specific hints for SanteMPI.
All tests for HL7v2 should ensure they are using either:
Node authentication - Meaning that an X.509 certificate environment has been configured on the MPI. Note that all device configurations should map the certificate to the credential for the device.
- Meaning that MSH-8 should carry necessary authentication information to authenticate the sending node.
For more information on how HL7v2 messages are authenticated in SanteDB, please consult the wiki article.
SanteGuard is a centralized audit and security repository which is compatible with SanteDB products and as well as any product using OAUTH and IHE ATNA.
SanteGuard is a plugin to SanteDB that integrates a powerful audit trail into the SanteDB system. SanteGuard provides several system interfaces, user interfaces, reports, and an enhanced implementation of the IAuditRepository service. At a high level, SanteGuard:
Allows SanteDB to receive Audit events from external systems using IETF RFC3881 or NEMA DICOM format audits over SYSLOG (TCP, UDP, and STCP).
Operationalizing SanteDB (or any SanteDB solution) is not a trivial task, any large scale deployment of the solution requires planning and coordination between stakeholders. Implementers are encouraged to use formal methodologies for enterprise projects and architecture (examples: , , , etc.) to manage the operationalization of the MPI projects.
Because operationalization is specific to the problem domain, local jurisdiction, size requirements, and other factors, the SanteDB wiki merely provides high level activities for operationalization as a reference. Any of the articles or templates found on the SanteSuite wiki are expected to be adapted by implementers, or to provide SanteDB specific considerations within their existing project management methodology.
The overall operationalization of a SanteDB service can be illustrated with 5 major activities.
Often time acts are related to one another via the ActRelationship entity. Act relationships are important, as typically acts cannot be standalone. For example, one cannot simply “Observe” something without having an encounter. An example of several types of interactions within SanteDB are described below:
Patient Presents to receive an Immunization: In this use case the primary act is a PatientEncounter whereby participants include the clinician performing the vaccination (performer), the patient (record target), the clinic (service delivery location). The patient may be weighed prior to receiving the immunization that represents a component act of type Observation, and the administration of the vaccine represents a substance administration with relations to one or materials administered
You can install SanteDB iCDR on Microsoft Windows or Linux / Unix operations on x86 or ARM. The option to install SanteDB iCDR services on a full operating system is well suited for environments where:
There is a need to finely tune the SanteDB configuration files
There is a predefined TRA and PIA process which requires hardened / vetted operating system installations.
There is existing Operating System environments in place, examples include:
SanteDB is designed to have a common . Because of this, it is important that any jurisdiction adapt this model for their local context, and establish a common understanding of the information which will be captured, shared, and stored in the SanteDB instance.
Develop a minimum dataset for data elements in the CDR, establish common use and definitions, common mappings within the context (i.e. what constitutes a "valid" patient record?)
Identify the identity which can be used in the CDR instance (how are patients identified? how are immunizations identified? etc.) this includes:
This page provides a convenient pre-flight checklist to ensure that you have sufficient assets in place to proceed with planning your deployment of a SanteDB solution.
SanteDB with the MPI plugin (SanteMPI solution) supports the following interfaces for integration:
IHE Patient Identity Cross Referencing for HL7v2 (IHE PIX)
IHE Patient Demographics Query for HL7v2 (IHE PDQ)
IHE Patient Identity Cross Referencing for Mobile (IHE PIXm)
Deployment of SanteDB onto any infrastructure will first involve the the setup of underlying infrastructure assets. SanteDB can run on:
Modern Linux Distributions (installer is written for Ubuntu)
Docker Containers
Microsoft Windows Operating Systems
SanteDB, SanteIMS and SanteMPI are interoperable software solutions for managing clinical data. While a software solution is a means to implement business use cases, it is not the end in itself. Typically the software implements or realizes business processes.
It is important, therefore, to develop a business architecture which describes the human and organizational architecture. This includes:
Documenting new business processes to be used in clinic among the various connected systems.
Document data capture standards, and agreement between organizations on the format and use of each data element (establish a common understanding of data elements from a business use).
Acts in the SanteDB data model represent actions taken by entities to other entities. In this lens, we can say that an act represents everything that “happens” to entities. This mechanism of storage allows the SanteDB data model to adapt to different jurisdictions with relative ease.
There are five different types of acts that are supported by the default SanteDB schema (Figure 1).
Patient Encounters: Represent an act whereby a patient presents, or is intended to present for care.
Observations: Represent an act whereby an entity observes something. Observations can include codified observations such as diagnoses, textual values such as a free-text description of an event, or a quantity such as weight or heart rate.
Existing Application Performance Monitoring software which relies on a specific Operating System
Existing authentication/administration infrastructure (such as Active Directory)
Existing event log / notification shipping in infrastructure.
There are requirements for hardware level isolation of the SanteDB services
There are complex scaling requirements (such as using Windows scaling or clustered file servers)
The environment's use of Windows only features in SanteDB. Windows only features include:
Using Microsoft Message Queue (MSMQ) dispatcher queues
Using Microsoft Windows Event Log notifications for central event monitoring
Using Microsoft Operation Manager to coordinate update and software package installation.
SanteDB supports Installation on Microsoft Windows and Installation on Linux and Unix.
If installing SanteDB iCDR on a native or virtualized operating system environments administrators will need to ensure the following pre-requisites are met:
An appropriate operating system version is installed, patched and ready for installation of the SanteDB iCDR Application Server.
An appropriate database environment (primarily PostgreSQL) is installed, patched and can accept connections from the SanteDB iCDR Application Server.
Quantified Kind
Represents a kind of object which is quantified such as X number of Y.
A dose of vaccine (5ml, etc.)
Event
EVN
Indicates that the act has actually occurred, or is occurring.
Request
RQO
Indicates that a person is requesting that the act occur. It is used to support order workflows.
Promise
PRMS
Indicates that the act represents the promise to fulfill a request.
The SanteSuite community provides ready to deploy virtualization containers for users who wish to use them. Using these images and appliances is well suited when:
A basic installation of SanteDB iCDR is required to perform an evaluation
Development, training or testing environments are desired.
The organization already leverages Docker or Virtualization environments, or does not require vetting/validation of underlying operating system configuration.
Small installations or localized installations of the software are desired
Users are deploying to Software-as-a-service (SaaS) environments and need to quickly roll out instances of the SanteDB infrastructure.
One of the benefits of using an appliance over a native or virtual operating system environment, is the bundling of pre-requisites within the deployment.
Exploring SanteDB's patterns of data storage
SanteDB's iCDR and dCDR platforms are designed to operate like any regular CDR. By default, when you install SanteDB's CDR software, the solution will permit the storage and retrieval of the data. This method of operation is sufficient for deployments where SanteDB is servicing a single purpose, for example: a national immunization registry, where only SanteDB is contributing data to / from the central server.
However, when you want to run SanteDB as an integrator of data (for example, as an MPI or a Shared Health Record (SHR)) this mode of operation is no longer optimal. In the field you will have multiple data sources contributing a variety of information.
SanteDB ships with a matching engine that operates in either deterministic or probabilistic modes, these functions are described in the Matching engine documentation. However, once a match is detected, one of two storage patterns can be used.
When SanteDB's SIM data storage pattern service is enabled, the SIM service will handle the matching and merging of records. In single instance mode, SanteDB's storage engine will flag duplicates (or merge them, depending on your configuration) however will only ever keep one copy of a known good record.
This means, for example, if one system reports a Facility Registration for a facility name "Good Health Hospital", and another reports a facility "Good Health Hospital" that is determined to be a duplicate, SanteDB will flag the two records as duplicates. Once merged, one record is subsumed into the other, the subsumed record is nullified and no longer appears in searches.
When SanteDB's MIM data storage pattern service is enabled, the behavior of the software is quite different. In MIM mode, SanteDB will store all records as a "local" record and tag them as mdm.type=L. The solution then searches for other records which might be duplicated in its data store.
If SanteDB determines no other records match the local record created, it will generate a new master record and tag it as mdm.type=M. Master records aren't really records, rather they are pointers (or an anchor point) where local records are attached.
If the matching system determines that there are potential matches, depending on configuration, it will either link the newly inserted local record to the existing master record which matches, or it will simply mark the record as a candidate local (for later merging).
The sending system has complete authority to update its local records however it wants, it may change names, dates of birth, etc. When an update occurs on a local, the MIM pattern service will re-run the matching rules to determine if the local is still, indeed a match with the master, or if the record could be linked to another master.
When in MIM mode, and a query is run, the MIM persistence service will query for local records which match the specified criteria, and will synthesize a master based on the data elements the requesting system has appropriate access permission for.
Multi-instance mode is very useful for central registries like MPI, MFR, and MPR. It has several benefits over SIM:
Merged records can subsequently be un-merged
It is possible to flag / compartmentalize local records based on their access policies (for example, you can prevent an immunization registry from seeing an HIV programme information)
It allows complete versioning and tracking of updates made to the local record.
When running in MIM mode, it is possible to assign attributes of the various local records into a record of truth. For example, if you collect patient information from several hospitals about a particular patient (say: William Butler in hospital A, Bill Butler from hospital B), it is possible to designate an official record of truth for that patient. A record of truth will always be returned to callers, and prevents the synthesizing of master data records (or rather, it overrides the local fields which have been promoted to record of truth status).
Records of truth cannot be edited by local systems, records of truth can only be edited by the iCDR in which the record resides.
Allows SanteDB to receive Audit events over HTTP using the IETF RFC3881 or DICOM audit format (POX service)
(Future) Allows SanteDB to receive Audit Events using HL7 FHIR
Stores additional information about audits not captured in the default SanteDB audit repository such as SIEM attribute son the incoming Syslog message, versioning of audit events, etc.
Adds several "widgets" to key areas of SanteDB (the patient summary screen for example) which allow administrators to quickly identify who has been accessing a particular patient's data.
(In-Progress) An enhanced audit repository dashboard.
What are the medical (MRNs, insurance, etc.) and non-medical identification (drivers licenses, citizen identifiers, etc.)
Which organizations have the authority to assign/change these identifiers?
What are the validation criteria, patterns, expiration, and versioning policies for each?
Identify standards to be used. It is useful to declare "use FHIR" , however this may not be the best option given the current state of systems. Consider:
What information standards are currently used by existing systems?
What data elements are easily available in each standard?
Identify secondary use and indicators for the software. Understand how the data may be aggregated, reported, shared, or compared over time and plan to implement these as reports or measures.
IHE Patient Demographics Query for Mobile (PDQm)
IHE Patient Master Identity Registry (PIMR)
These tests are based on the OpenHIE testing framework for Client Registry.
Android
These installation procedures assume that readers are familiar with the mechanics of their operational environment of choice such as:
Installation and Removal of Software
Use of the command line
Comfort editing configuration files (XML and JSON)
For each data element in the provided SanteDB information model, review:
The commonality of the data element in your context (how often is it captured? is it useful information to be captured? If asked, would a patient know the information? etc.)
Relevant legislation in the context (is it illegal to capture? if not are there any protections which need to be in place?)
The sensitivity of the information (if we ask patients for this information will they lie? will they offer the information?)
Mapping to local semantics (is the data known as a different name? is there a mapping of semantics?). For example, many implementing jurisdictions may need to map the address hierarchy to match their country context, or some countries may not use family names, etc.
Document the context specific use of each field.
Once complete, the information on this worksheet will make its way into formal specifications (such as IHE ITI TF Volume 4 content, FHIR implementation guides, etc.). This process is not covered on the community wiki.
The SanteDB team has provided a completed worksheet which illustrates the minimum dataset and mappings for Demoland. Changes from the template are highlighted in green.
Revision: Is used to describe patch level. These are usually random (but increasing) values.
[major].[minor].[revision].[build]Privacy and security architecture based on XACML building blocks (though XACML is not used)
Authentication of application, device and users
Break the glass and permission override supported
Full auditing on all platform components (even disconnected clients)
Intelligent Services
Full decision support system provided for expressing care protocols and composing care plans.
Business rules can be customized using data triggers
Full reporting / ad-hoc warehouse available for custom reports
Integrated
Integrated with a variety of services to assist operationalization
Integrated bug submission and tracking with Atlassian JIRA
Integrated SMS delivery with Twilio
Open interfaces provide 1:1 function access to underlying functionality.
Interoperable
Supports HL7 v2.5 and provides customization interfaces for messages
HL7 FHIR STU3 support on select resources
Select support for GS1 BMS XML 3.3 (over REST or AS.2)
Support for IHE ATNA (RFC 3881 or DICOM)
OPENID Connect / OAUTH 2.0 compatible authentication services (password, client_credential, authorization_code and refresh grants) with JWT identity tokens
Many implementations don't start with a concrete idea of what the deployment of SanteDB will be achieving beyond "we need X". The information gathering phase of an operationalization project is intended to establish a concrete consensus among stakeholder of what the SanteDB CDR will be used for.
After the vision for your SanteDB deployment project has been established, and relevant stakeholders are on board, it is time to begin the planning phase of the SanteDB/SanteMPI solution. Depending on how the target context's project management office operates, the process may differ.
Once the project boundaries and overall planning/architecture work has been performed, the task of customizing SanteDB can commence.
See: Developers
The deployment phase of SanteDB involves the installation, configuration, validation and testing of the environment.
See: Deployment for detailed information about deploying SanteDB software.
The rollout phase of SanteDB involves the actual onboarding of users and using the solution in an operational context.
See: Rollout for more information about activities related to rollout of the SanteDB solution.
Patient Presents for Appointment: In this use case, the patient presents for the scheduled appointment. The encounter fulfills the appointment request.
Forecasted vaccination: In this use case a decision support system identifies a patient which needs to receive a vaccine. The forecasting engine may create a PatientEncounter with mood of Proposed that indicates that a computer system is proposing an action to occur. When the patient presents for their vaccination the clinician creates a new PatientEncounter with mood of Event that fulfills the PatientEncounter with mood of Proposed (i.e. the clinician is saying “I am acting on your proposal”).
Formalize inter-departmental or inter-organization processes for sharing, accessing, and disclosing data stored in the common SanteDB infrastructure.
User stories are a great tool for describing how users interact with each system and how each system interacts with each other. User journeys may be documented using BPMN activity diagrams or using a user journey map.
Regardless of the format, the user journey should:
Identify the major steps of the business process being performed.
Identify the goals of the user and the system (what is the user and/or system trying to accomplish?)
Identify the humans involved (or organizations, departments, ministries, etc.)
Identify the systems involved
Illustrate how the humans interact with the systems, and how humans and systems interact with one another.
For example, consider the user journey to issue a new national health identifier to patient for Demoland.
Substance Administrations: A substance administration is representing an act whereby a substance, such as a vaccine is administered to a patient.
Order: An order is a special type of stock act and represents a request by an entity to transfer stock from one place to another.
Procedures: A procedure is a type of act in which the physical state of the record target or target entity is changed.
Financial Transaction: Which is used whenever a financial transaction, or an exchange of financial goods occurs.
SanteDB iCDR and dCDR supports basic subscription management. This facility allows external parties to subscribe (via a subscription) to data persistence events, at which they they will receive a notification (via a channel) using one of the available dispatch formats.
The components of the publish and subscribe architecture are:
Repository Service
The primary persistence repositories. These are responsible for the persisting and loading of data to/from the primary data persistence layer.
Record Merging Service
The service which is responsible for merging and unmerging records, detecting duplicates, etc.
MDM Record Merging SIM Record Merging
The PubSubManager stores data for subscriptions and channels in a concise schema.
Subscriptions are defined with a target resource (such as Patient, Act, Entity, Person, Place, etc.). The subscription defines one or more events and a series of filters which will trigger the issuance of a notification to the receiver.
The following notification events can be subscribed.
A channel defines the mechanism to notify the receiver of the publish notification. The channel specifies the endpoint URL (mailto:, sms:, http:, llp:, etc.) the dispatcher to be used, and any settings. Settings are stored as key/value pairs which, depending on the dispatcher will be used to determine the channel format, authorization, etc.
The persistence layer in SanteDB is largely a maintenance codebase of the OpenIZ persistence layer, which itself was originally written in 2009 for the MEDIC CR and MEDIC SHR. This data layer has over a decade of modifications, changes, etc. to it from a variety of authors during its lifetime.
This has lead to several performance issues with SanteDB, namely:
The intended use of the OpenIZ persistence layer was for synchronization, so objects are deep-loaded in the persistence layer, regardless of whether the caller will use the information. There was no way for the caller to convey to the persistence layer that loading data is not needed.
The persistence layer requires joining of non-versioned attributes to load data (i.e. versioned attributes and non-versioned attributes were stored as a master/detail view). This impacts query performance as the database needs to perform an extra join.
There have been several technology enhancements to the .NET platform since the original design of the persistence layer which would optimize the manner in which database calls can be made.
Missed properties via .LoadProperty() require duplicate hits to the database, regardless if the data persistence layer already made this query and determined there was no matching entries.
To fix this, a new persistence layer (on branch feature/nuado ) has been in development for several months. This new persistence layer:
Performs lazy-loading of records from the database when the caller requests them (i.e. calling Skip(), Take(), Count(), etc. translates directly to SQL statements in the database rather than deep loading
Allows the caller to use the QueryPersistenceContext to control the manner in which properties are loaded based on the caller's use case.
The new persistence layer modifies all the data access classes to use the IQueryResultSet<T> interface. These interfaces support methods for skipping and taking records from the underlining data store in a method which reduces the data loaded from the SQL database.
The code below illustrates the modification of the SQL statement sent to the database by using the result set methods.
Additionally, the application of any data modification processes (such as MDM or policy enforcement) is pipelined. This means that as records are read from the database, each record is operated on by the interested services.
Whenever submitting data to SanteDB's CDR where an element is marked as required, you may submit a null reason (also known as a null flavor). The allowed null flavors are:U
Mnemonic
Description
AskedUnknown
The value was asked for, however the known value could not be collected.
Derived
The value was not supplied because it can be calculated from other data provided.
Invalid
The value was not supplied because the known value would violate business rules.
Masked
Patient Identity Feed – Auto-merge between patients with matching NID (as non medical ID)
This test ensures that the receiver is able to merge patient data from an assigning authority (TEST_A) which has an national identifier (not assigned by central authority as a PID). The demographics data does not match, this is to test that matching is done on explicit identifiers.
Test harness (as TEST_HARNESS_A) sends a registration message for patient Yannick Jones having a date of birth to the month, with NID of NID-000345439 and local identifier of TEST_A of RJ-460.
Receiver Accepts Message with an AA
MSH-5 and MSH-6 matches “TEST_HARNESS_A|TEST”
Test harness (as TEST_HARNESS_B) sends a registration message for patient Yan Jones having a more specific date of birth, with NID of NID-000345439 and local identifier of TEST_B of RB-469.
Receiver Accepts Message with an AA
MSH-5 and MSH-6 matches “TEST_HARNESS_B|TEST”
Test harness verifies the record from TEST_B is linked with TEST_A via the NID
Receiver responds with an AA
Receiver sends exactly one PID segment with identifier RJ-449 in domain TEST_A in one of the PID-3 repetitions
SanteDB is designed with a variety interoperability interfaces and standards, including:
IHE ATNA / UDP
OpenAPI / Swagger 2.0 Metadata Exchange
Each of these interfaces are enabled/disabled based on the role that SanteDB is operating in. For example, if SanteDB needs to act as an MPI then the GS1 and ATNA interfaces are disabled (along with related user interface platforms).
Patient Identity Query – Identifier query with specific request response domains
In this test, the test harness will register a patient with a local identifier (TEST domain). The receiver is the assigning authority for the ECID domain and should generate an ECID by whatever means the software performs this task. The test harness will then ask the receiver to do a cross reference between the TEST domain and the ECID domain. This test ensures that the receiver adheres to the “What Domains Returned” query parameter.
Test harness requests the receiver to explicitly give it the TEST domain identifiers by sending:
Receiver Accepts message with an AA
QAK of OK
Response message contains exactly one PID segment
PID contains exactly one PID-3 having:
Test harness requests the receiver to explicitly give it the domain identifiers from an invalid domain (RANDOM) by sending:
Receiver rejects the message with an AE
Receiver indicates query error with QAK of AE
Receiver indicates the error with ERR having QPD^1^4
Test harness requests the receiver to explicitly give it the domain identifier from a valid domain (NID) for which no identifiers have been associated with the patient by sending:
Receiver accepts the message with AA
Receiver indicates no data found with QAK of NF
No PID segments are sent in the response message.
Patient Identity Feed – Update based on matching NID
This test ensures that the receiver is able to merge patient data from an assigning authority (TEST_A) which has an national patient identifier (assigning authority NID). The demographics data does not match, this is to test that matching is done on explicit identifiers.
Test harness (as TEST_HARNESS_A) sends a registration message for patient Jon [sic] Smith having a more specific date of birth, with NID of NID-000345435 and local identifier of TEST_A of RJ-449.
Receiver Accepts Message with an AA
MSH-5 and MSH-6 matches “TEST_HARNESS|TEST”
Test harness verifies the record was linked with the NID by executing a PIX query
Receiver responds with an AA
Receiver sends exactly one PID segment with identifier RJ-449 in domain TEST_A in one of the PID-3 repetitions
Security Threat and Risk Assessment What are Security Threat and Risk Assessments (TRAs)?
A Threat Risk Assessment (TRA) is the overall activity of assessing and reporting security risks for an information system to help make well informed risk-based decisions. A TRA also documents risk ratings and planned treatments of the risks.
Each risk assessed must consider the likelihood to which a threat may leverage a weakness, the potential impact, and an acknowledgement of what this could mean to the organization. The criticality of an information system and security classification of information stored and handled by the system should be reviewed and considered when conducting a TRA. For each risk that is identified, a planned treatment or acceptance must be documented. Risk findings from the TRA activity should be communicated to the appropriate project sponsors and stakeholders.
TRAs should be completed for new or significantly modified information systems and during planning, development and implementation of an information system. A review and updated TRA should be conducted throughout the life of an existing information system for any significant or material change(s) and must also consider any previously identified risks. For critical systems, a review schedule should also be maintained to ensure that TRAs are periodically conducted throughout the life of an information system.
Each jurisdiction will have a unique security threat landscape and may have specific requirements for TRAs, but we have provided a sample TRA template here that should at least help to start the security conversation in your project.
As always, before making use of any of our resources, please read and accept our disclaimer:
The SanteDB conceptual data model is based on several different resources:
HL7 Reference Information Model (RIM) forms the basis of the core clinical storage engine. SanteDB's implementation keeps the paradigm of Entities Participating in Acts, however removes many of the complex datatypes.
HL7 FHIR forms the basis for the conceptual data model's extension and tagging capabilities, which are used to extend the SanteDB data model.
OpenMRS Concept Dictionary was used as the basis of SanteDB's concept tables.
Clinical data in SanteDB is represented as Entities playing Roles Participating in Acts. This is illustrated in Figure 1.
Entities: An entity represents a person, place, organization, or thing (syringe, antigen, vaccine, etc.). Entities can be related to one another via an entity relationship such as place belonging to an organization or series of materials belonging to a vaccination kit.
Roles: Roles represent a type of part an entity plays. For example, a Person entity may play the role of a provider or a patient.
Participations: Participations are the link between an act and an entity via a role. A participation is used to describe how an entity participates in the carrying out of an act.
In this context we can represent many different clinical scenarios. In order to make conceptualizing data elements in the SanteDB persistence store easier, much data documentation leverages an information model cards as illustrated in Figure 2.
SanteDB Acts and Entities can be templated to ease the creation and reuse of common structures. A template is a particular set of rules and pre-set data elements which are used to perform some use case with the underlying base type.
For example, weight and height are two separate types of a QuantityObservation. By creating a “weight” and “height” template, we allow any business processes or user interface elements to understand the rules for a particular entity. It allows software to understand “what kind” of element it is looking at without having to guess based on type/class/mood/determiner/etc.
Patient Demographics Query – Query by mother’s identifier
This test ensures that the recipient of the query can perform a query by the patient’s mother’s identifier.
Test harness sends a query with mother’s identifier components specified.
Receiver responds with an AA
Receiver sends exactly one PID segment with identifier RJ-440 in domain TEST in PID-3
Test harness verifies the infant record was created in the receiver.
Receiver responds with an AA
Receiver sends exactly one PID segment with identifier RJ-440 in domain TEST in PID-3
An entity within the SanteDB data model is used to represent a person, place, or thing. Entities represent the who, which and where aspects of an action. Entities are further classified into several sub classes illustrated in Figure 1.
Architecturally, SanteDB's data architecture is based around the RIM. SanteDB has a conceptual information model which is implemented in 3 different ways:
Message Models - The representation of the SanteDB Conceptual Information Model as JSON or XML objects which appear on the wire or when using functions from third party technologies like JavaScript. Message models in SanteDB include:
RIM-based XML model (1:1 with conceptual model)
Figure 2 represents a sample information model of a kit of BCG vaccine. The model illustrates how a single tuples in the SanteDB model are related to one another to represent a kit. The material “BCG Vaccine” is comprised of one dose of “BCG Antigen”, one “Syringe”, and one dose of “BCG Diluent”. A box of “BCG Vaccine” represents 25 single doses of “BCG Vaccine” (meaning 25 syringes, 25 antigen and 25 diluent). Finally, from this we can order (via instantiation or inheriting a kind) a kit of GSK 5ml BCG vaccine. This derivation will have the same rules applied (in that this vaccine must have a syringe, antigen, and diluent.
Figure 3 represents a complex scenario of kitting a vaccine and then deriving a specific type of kit. The relationship between the instantiation and the generic concepts of the material would have a type of “Manufactured” meaning the “GSK 5 ml BCG” is a manufactured representation of the generic BCGvaccine.
The SanteDB model also supports more simplistic representation of a “BCG Vaccine” if kits are not required by the jurisdiction that is implementing SanteDB. Figure 4 illustrates a valid representation of BCG in a jurisdiction where only the antigen is tracked.
Use Cases understood and documented
Requirements documented ("what is success?")
Patient Identity Feed – Invalid register patient message
Patient Identity Feed – Full patient record
Patient Identity Feed – Blocks unknown assigning authority
This test ensures that the receiver rejects messages which contain identifiers assigned from authorities which are unknown.
It is expected that a patient identity cross reference manager will ensure that data is valid prior to recording patient registrations and performing cross reference functions.
The lack of configuration for an identity domain being received by an identity source indicates a misconfiguration of the MPI and/or the identity source. This test ensures that configuration is consistent within a jurisdiction.
Patient Demographics Query – Query by date of birth
Patient Identity Feed – Match with mother’s identifier
This test ensures that the receiver is able to match an incoming patient with their mother via the “Mother’s Identifier” property. In this test, the harness with register a patient (the mother) and subsequently will register an infant record (only dob, gender and id) with the mother’s identifier attached. The test will ensure that the link occurred by validating a demographic query contains the mother’s name.
A Privacy Impact Assessment (PIA) is a risk management process that helps institutions ensure they meet regulatory requirements and identify the risks and potential impacts their programs and activities will have on an individuals’ privacy.
Conducting a PIA is a means of helping to ensure compliance with any legal requirements set out in jurisdictional legislation, and the requirements of any organizational policies and directives. Adhering to the requirements will reduce the risk of improper or unauthorized collection, use, disclosure, retention or disposal of personal information.
While programs and activities must comply with legal and policy requirements, they should also be designed to incorporate best practices and to minimize negative impacts on the privacy of individuals. For example, you should work to reduce the risk that an individual may suffer harm, such as identity theft, reputational damage, physical harm or distress, as a result of your program’s handling of their personal information. A PIA may not eliminate such risks altogether, but should help to identify and manage them.
PIAs allow institutions to identify and mitigate risks as early and as completely as possible. They are a key tool for decision-makers, enabling them to deal with issues internally and proactively rather than waiting for complaints, external intervention or bad press.
Each jurisdiction will have a unique privacy landscape and may have specific requirements for PIAs, but we have provided a sample PIA guide and template here that should at least help to start the privacy conversation in your project.
The value is not supplied because the value is sensitive and disclosure may violate privacy.
NotApplicable
The value is not supplied because it is not applicable (for example: Last menstrual period for a man)
NotAsked
The value is not supplied because it was not asked for.
Unavailable
The value is not available at the time of data capture.
NoInformation
The value is not supplied because there is no information supplied. This is the default null flavor to use.
NegativeInfinity
The value is not supplied because it is negative infinity.
Other
The value was not supplied for some other reason.
PositiveInfinity
The value was not supplied because it is positive infinity.
SufficientQuantity
The value is of sufficient quantity to meet a clinical trigger, however the exact value could not be measured (i.e. off-scale 0 or off-scale max)
Trace
The value is above 0, however the exact value is unknown or the equipment could not measure the quantity.
UnEncoded
The value could not be encoded into the message.
Unknown
The value is unknown (not asked, not measured, etc.)
New Processes Mapped
Document Sign-Off Obtained
Operational Architecture / Plan Documented
Document Sign-Off Obtained
Protection of Patient Information Documented
Privacy Impact Assessment Drafted / Reviewed
Deployment Pre-Requisites Procured
Physical, Virtual or Cloud Resources Purchased and Installed
Operating Systems Installed and up to date
Antivirus Software Installed and up to date
Monitoring Software (SIEM or APM) Installed and up to date
Responsible Persons, Initial User Lists, etc. Available
Backup Infrastructure Available and configured
Security Certificates (SSL), Domain Name Registrations, and IP addresses obtained
Network packages / bandwidth obtained
Third party integration services credentials obtained (i.e. network operator services, external registries, e-mail or SMS services, etc.)
MemoryQueryResultSet
Implementation of the IQueryResultSet which operates on an IEnumerable instance. This result set just passes any calls to the underlying enumerable object.
NestedQueryResultSet
Implementation of the IQueryResultSet where a function is called for each retrieved object. This type of result set wrapper is useful when the yield function wishes to modify the result loaded from the wrapped result set.
TransformQueryResultSet
Implementation of a IQueryResultSet which transforms a source record type to a destination record type using a transform function (Func<TSource, TDestination>) to map an object (in a pipelined manner) from A to B.
MappedQueryResultSet
A query result set which wraps an IOrmResultSet . When constructing this instance, the persistence layer should pass an instance of a IMappedQueryProvider which can be called by the ORM layer to skip/take/count and convert records from the data model layer to the business object model layer.
MappedStatefulResultSet
A specialized MappedQueryResultSet which operates on stateful query results from IQueryPersistenceProvider.
PID.3.1.1 = RJ-444
PID.3.4.1 = TEST
PID.3.4.2 = 2.16.840.1.113883.3.72.5.9.1
PID.3.1.1 = RJ-443
PID.3.4.1 = TEST
PID.3.4.2 = 2.16.840.1.113883.3.72.5.9.1
PID.3.4.3 = ISO
Test harness sends an ADT^A01 message with complex data set.
Receiver Accepts Message with an AA
MSH-5 and MSH-6 matches “TEST_HARNESS|TEST”
Test harness verifies demographics data matches by executing a PDQ query with the patient’s identifier.
Receiver responds with an AA
Receiver sends exactly one PID segment with identifier RJ-442 in domain TEST in PID-3
Receiver sends:
PID-5=FOSTER^FANNY^FULL^^^^L
PID-6=FOSTER^MARY^^^^^L
PID-7=1970
PID-8=F
PID-11=123 W34 St^^FRESNO^CA^20495
PID-13=^PRN^PH^^^419^31495
PID-14=^^PH^^^034^059434
PID-15=EN
PID-16=S
In order to mimic a mis-configuration of the client registry, the environment should ensure that the domain TEST_BLOCK and OID 2.16.840.1.113883.3.72.5.9.4 are not present.
Test harness sends ADT^A01 message having the invalid OID in CX.4.2.
Receiver rejects message with error code AE or AR
MSH-5 and MSH-6 matches “TEST_HARNESS|TEST”
Meaning MSA or ERR segment is conveyed showing the error
Response is ACK^A01
Response Version is 2.3.1
Test harness sends ADT^A01 message having invalid assigning authority name in CX.4.1
Receiver rejects message with error code AE or AR
MSH-5 and MSH-6 matches “TEST_HARNESS|TEST”
Meaning MSA or ERR segment is conveyed showing the error
Response is ACK^A01
Response Version is 2.3.1
Test harness sends a query with date of birth precise to the year in which a patient’s date of birth falls.
Receiver responds with an AA
Receiver indicates records found with QAK of OK
Receiver sends exactly one PID segment with identifier RJ-439 in domain TEST in PID-3
Test harness sends a query with date of birth precise to the month in which the patient’s date of birth falls.
Receiver responds with an AA
Receiver indicates records found with QAK of OK
Receiver sends exactly one PID segment with identifier RJ-439 in domain TEST in PID-3
Test harness sends a query with date of birth precise to the day in which a patient’s date of birth falls.
Receiver responds with an AA
Receiver indicates records found with QAK of OK
Receiver sends exactly one PID segment with identifier RJ-439 in domain TEST in PID-3
Test harness sends a query with date of birth precise to the year in which the patient’s date of birth does not fall.
Receiver responds with an AA
Receiver indicates no records found with QAK of NF
Receiver sends no PID segments
Test harness sends an ADT^A01 message with minimal data set containing information for a newborn with only an identifier, gender and date of birth with mother’s identifier.
Receiver Accepts Message with an AA
MSH-5 and MSH-6 matches “TEST_HARNESS|TEST”
Test harness verifies the infant record was created in the receiver.
Receiver responds with an AA
Receiver sends exactly one PID segment with identifier RJ-440 in domain TEST in PID-3
Test harness verifies the infant record has mother’s information attached to it by sending a PDQ message with infant’s identifier.
Receiver responds with an AA
Receiver sends exactly one PID segment with identifier RJ-440 in domain TEST in PID-3
Receiver conveys mother’s name in PID-6 with value of JONES^JENNIFER
Receiver conveys mother’s identifier in PID-21 of RJ-439 in domain TEST
var dpe = ApplicationServiceContext.GetService<IRepositoryService<Patient>>();
// Prepares the statement SELECT * FROM pat_tbl....
var patients = dpe.Find(o=>o.DateOfBirth <= DateTime.Now);
// Executes a SELECT EXISTS (....) rather than loading patients
if(patients.Any()) {
// Modifies the statement above to SELECT * FROM pat_tbl OFFSET 10 ROW TAKE FIRST 10 ROWS ONLY
patients = patients.Skip(10).Take(10);
// Modifies statement above to SELECT COUNT(*) FROM (....)
var patientCount = patients.Count();
}MSH|^~\&|TEST_HARNESS_A^^|TEST^^|CR1^^|MOH_CAAT^^|20141104174451||ADT^A01^ADT_A01|TEST-CR-18-20|P|2.3.1
EVN||20141001
PID|||RJ-460^^^TEST_A||JONES^YANNICK^^^^^L||199004|M|||||||||||NID-000345439^^^NID
PV1||IMSH|^~\&|TEST_HARNESS_B^^|TEST^^|CR1^^|MOH_CAAT^^|20141104174451||ADT^A01^ADT_A01|TEST-CR-18-30|P|2.3.1
EVN||20141001
PID|||RB-469^^^TEST_B||JONES^YAN^^^^^L||19900404|M|||||||||||NID-000345439^^^NID
PV1||IMSH|^~\&|TEST_HARNESS_A|TEST|CR1|MOH_CAAT|20090223144546||QBP^Q23^QBP_Q21|TEST-CR-06-40|P|2.5
QPD|IHE PIX Query|RB-469^^^NID^PI
RCP|IMSH|^~\&|TEST_HARNESS^^|TEST^^|CR1^^|MOH_CAAT^^|20141104174451||ADT^A01^ADT_A01|TEST-CR-09-30|P|2.3.1
EVN||20101020
PID|||RJ-444^^^TEST||BOOP^BETTY^^^^^L||1935|F|||
PV1||IMSH|^~\&|TEST_HARNESS|TEST|CR1|MOH_CAAT|20090223144546||QBP^Q23^QBP_Q21|TEST-CR-10-20|P|2.5
QPD|IHE PIX Query|Q1020|RJ-444^^^TEST^PI|^^^TEST
RCP|IMSH|^~\&|TEST_HARNESS|TEST|CR1|MOH_CAAT|20090223144546||QBP^Q23^QBP_Q21|TEST-CR-10-30|P|2.5
QPD|IHE PIX Query|Q1030|RJ-444^^^TEST^PI|^^^RANDOM
RCP|IMSH|^~\&|TEST_HARNESS|TEST|CR1|MOH_CAAT|20090223144546||QBP^Q23^QBP_Q21|TEST-CR-10-40|P|2.5
QPD|IHE PIX Query|Q1040|RJ-444^^^TEST^PI|^^^NID
RCP|IMSH|^~\&|TEST_HARNESS|TEST|CR1|MOH_CAAT|20090223144546||QBP^Q23^QBP_Q21|TEST-CR-09-10|P|2.5
QPD|IHE PIX Query|Q0910|RJ-443^^^TEST^PI
RCP|IMSH|^~\&|TEST_HARNESS|TEST|CR1|MOH_CAAT|20090223144546||QBP^Q23^QBP_Q21|TEST-CR-09-20|P|2.5
QPD|IHE PIX Query|Q0920|RJ-443^^^RANDOM^PI
RCP|IMSH|^~\&|TEST_HARNESS^^|TEST^^|CR1^^|MOH_CAAT^^|20141104174451||ADT^A01^ADT_A01|TEST-CR-09-30|P|2.3.1
EVN||20101020
PID|||RJ-443^^^TEST||SMITH^STEPHANIE^^^^^L||198306|F|||
PV1||IMSH|^~\&|TEST_HARNESS|TEST|CR1|MOH_CAAT|20090223144546||QBP^Q23^QBP_Q21|TEST-CR-09-40|P|2.5
QPD|IHE PIX Query|Q0940|RJ-443^^^TEST^PI
RCP|IMSH|^~\&|NID_AUTH^^|TEST^^|CR1^^|MOH_CAAT^^|20141104174451||ADT^A01^ADT_A01|TEST-CR-06-20|P|2.3.1
EVN||20101020
PID|||NID-000345435^^^NID^NNXXX||SMITH^JOHN^^^^^L||1980|M|||||||||||
PV1||IMSH|^~\&|TEST_HARNESS_A^^|TEST^^|CR1^^|MOH_CAAT^^|20141104174451||ADT^A01^ADT_A01|TEST-CR-06-30|P|2.3.1
EVN||20141001
PID|||RJ-449^^^TEST_A^PI~NID-000345435^^^NID^PI||SMITH^JON^^^^^L||198005|M|||||||||||||
PV1||IMSH|^~\&|TEST_HARNESS_A|TEST|CR1|MOH_CAAT|20090223144546||QBP^Q23^QBP_Q21|TEST-CR-06-40|P|2.5
QPD|IHE PIX Query|Q0640|NID-000345435^^^NID^PI
RCP|IMSH|^~\&|TEST_HARNESS^^|TEST^^|CR1^^|MOH_CAAT^^|20141104174451||ADT^A01^ADT_A01|TEST-CR-13-10|P|2.3.1
EVN||20101020
PID|||RJ-439^^^TEST||JONES^JENNIFER^^^^^L|SMITH^^^^^^L|19840125|F|||123 Main Street West ^^NEWARK^NJ^30293||^PRN^PH^^^409^30495||||||
PV1||IMSH|^~\&|TEST_HARNESS^^|TEST^^|CR1^^|MOH_CAAT^^|20141104174451||ADT^A01^ADT_A01|TEST-CR-13-15|P|2.3.1
EVN||20101020
PID|||RJ-440^^^TEST||||20141001|M|||||||||||||RJ-439^^^TEST
PV1||IMSH|^~\&|TEST_HARNESS|TEST|CR1|MOH_CAAT|20090226131520-0600||QBP^Q22^QBP_Q21|TEST-CR-13-20|P|2.5
QPD|Q22^Find Candidates^HL7|Q1320|@PID.21.1^[email protected]^TEST
RCP|I|10^RDMSH|^~\&|TEST_HARNESS|TEST|CR1|MOH_CAAT|20090226131520-0600||QBP^Q22^QBP_Q21|TEST-CR-13-30|P|2.5
QPD|Q22^Find Candidates^HL7|Q0740|@PID.6.1^[email protected]^JENNIFER
RCP|I|10^RDMSH|^~\&|TEST_HARNESS^^|TEST^^|CR1^^|MOH_CAAT^^|20141104174451||ADT^A01^ADT_A01|TEST-CR-08-10|P|2.3.1
EVN||20101020
PID|||RJ-442^^^TEST||FOSTER^FANNY^FULL^^^^L|FOSTER^MARY^^^^^L|1970|F|||123 W34 St^^FRESNO^CA^30495||^PRN^PH^^^419^31495|^^PH^^^034^059434|EN|S|||||
PV1||IMSH|^~\&|TEST_HARNESS|TEST|CR1|MOH_CAAT|20090226131520-0600||QBP^Q22^QBP_Q21|TEST-CR-08-30|P|2.5
QPD|Q22^Find Candidates^HL7|Q0740|@PID.3.1^[email protected]^TEST
RCP|I|10^RDMSH|^~\&|TEST_HARNESS|TEST|CR1|MOH_CAAT|20141104174451||ADT^A01^ADT_A01|TEST-CR-03-10|P|2.3.1
EVN||20101020
PID|||RJ-999-2^^^&2.16.840.1.113883.3.72.5.9.4&ISO||THAMES^ROBERT^^^^^L| |1983|M|||1220 Centennial Farm Road^^ELLIOTT^IA^51532||^PRN^PH^^^712^7670867||||||481-27-4185
PV1||IMSH|^~\&|TEST_HARNESS^^|TEST^^|CR1^^|MOH_CAAT^^|20141104174451||ADT^A01^ADT_A01|TEST-CR-03-20|P|2.3.1
EVN||20101020
PID|||RJ-999-2^^^TEST_BLOCK||THAMES^ROBERT^^^^^L| |1983|M|||1220 Centennial Farm Road^^ELLIOTT^IA^51532||^PRN^PH^^^712^7670867||||||481-27-4185
PV1||IMSH|^~\&|TEST_HARNESS^^|TEST^^|CR1^^|MOH_CAAT^^|20141104174451||ADT^A01^ADT_A01|TEST-CR-14-10|P|2.3.1
EVN||20101020
PID|||RJ-439^^^TEST||JONES^JENNIFER^^^^^L|SMITH^^^^^^L|19840125|F|||123 Main Street West ^^NEWARK^NJ^30293||^PRN^PH^^^409^30495||||||
PV1||IMSH|^~\&|TEST_HARNESS|TEST|CR1|MOH_CAAT|20090226131520-0600||QBP^Q22^QBP_Q21|TEST-CR-14-20|P|2.5
QPD|Q22^Find Candidates^HL7|Q1420|@PID.7^1984
RCP|I|10^RDMSH|^~\&|TEST_HARNESS|TEST|CR1|MOH_CAAT|20090226131520-0600||QBP^Q22^QBP_Q21|TEST-CR-14-30|P|2.5
QPD|Q22^Find Candidates^HL7|Q1430|@PID.7^198401
RCP|I|10^RDMSH|^~\&|TEST_HARNESS|TEST|CR1|MOH_CAAT|20090226131520-0600||QBP^Q22^QBP_Q21|TEST-CR-14-40|P|2.5
QPD|Q22^Find Candidates^HL7|Q1440|@PID.7^19840125
RCP|I|10^RDMSH|^~\&|TEST_HARNESS|TEST|CR1|MOH_CAAT|20090226131520-0600||QBP^Q22^QBP_Q21|TEST-CR-14-50|P|2.5
QPD|Q22^Find Candidates^HL7|Q1450|@PID.7^1900
RCP|I|10^RDMSH|^~\&|TEST_HARNESS^^|TEST^^|CR1^^|MOH_CAAT^^|20141104174451||ADT^A01^ADT_A01|TEST-CR-07-10|P|2.3.1
EVN||20101020
PID|||RJ-439^^^TEST||JONES^JENNIFER^^^^^L|SMITH^^^^^^L|19840125|F|||123 Main Street West ^^NEWARK^NJ^30293||^PRN^PH^^^409^30495||||||
PV1||IMSH|^~\&|TEST_HARNESS^^|TEST^^|CR1^^|MOH_CAAT^^|20141104174451||ADT^A01^ADT_A01|TEST-CR-07-20|P|2.3.1
EVN||20101020
PID|||RJ-440^^^TEST||||20141001|M|||||||||||||RJ-439^^^TEST
PV1||IMSH|^~\&|TEST_HARNESS|TEST|CR1|MOH_CAAT|20090223144546||QBP^Q23^QBP_Q21|TEST-CR-07-30|P|2.5
QPD|IHE PIX Query|Q0530|RJ-440^^^TEST^PI
RCP|IMSH|^~\&|TEST_HARNESS|TEST|CR1|MOH_CAAT|20090226131520-0600||QBP^Q22^QBP_Q21|TEST-CR-07-40|P|2.5
QPD|Q22^Find Candidates^HL7|Q0740|@PID.3.1^[email protected]^TEST
RCP|I|10^RDActs: An act represents an action performed. An example of an Act may be an encounter the patient has with a provider to receive a weight or immunization. Acts may be related to one another, for example an encounter may fulfill an appointment, or an observation may be a part of an encounter.
JSON based View-Model (conceptual model with expanded properties to prevent round-trips to the server)
Business Object Model - The BOM in SanteDB is a series of .NET classes which are implementations of the conceptual information model used by all C# plugins
Physical Model - The representation of SanteDB's conceptual data model in a variety of RDMS systems including Firebird, Postgres, and SQLite.
By realizing the SanteDB conceptual model as these three layers, we observe the following benefits:
New physical persistence layers can be added without impacting the XML or JSON objects.
Message formats can be adapted to best suit a message format's strengths without introducing kludge from the persistence / RDBMS layer.
Tracking fields used at the physical layer don't pollute the business object model or message models
We can easily swap each layer independent of one another (add features, remove features, etc.)
SanteDB iCDR and dCDR never store or or directly with external messaging formats inside of the core components. All communications are transformed between components and their destined system software.
Take, for example, a client which is querying the SanteDB iCDR using HL7 FHIR (the pattern is identical regardless of message format).
In this example, the objects are passed as.
Component
Input
Output
Description
FHIR Service
FHIR
BOM
Convers the incoming FHIR message or query to RIM
Converts and resulting response from RIM BOM back to FHIR
Performs necessary actions for privacy enforcement, auditing, etc.
Local Repository
BOM
BOM
Checks configuration/context for applicable storage provider.
Calls triggers for business rules and connected services
Master Data Manager
An entity relationship has two codes which dictate the nature of the relationship between the holder (the entity which owns the relationship) and the target (the entity to which the holder is related). These are the relationshipType and the classificationType.
The relationshipType dictates the primary nature of the relationship, or the role that the target plays in related to the holder. Common relationship types are listed below (the full set is derived from the Concept Set EntityRelationshipType).
Relationship Type
Use
Family Members (Mother, Father, Sister, Brother, Sibling, etc.)
Indicates that the target has a familial relationship with the
holder. In these relationships the target IS A (mother, father, etc.)
to the holder.
Parent / Child
Indicates that the target is a parent or the target is a child of the
holder.
DedicatedServiceDeliveryLocation,
ServiceDeliveryLocation
Indicates that the target is the primary facility at which services are rendered for the holder.
Replaces
The target replaces the holder
The classification of the relationship indicates the nature of the target in relation to the holder. The classification is derived from RelationshipClass. If a classification is not specified, then it is assumed the relationship is not classified caller to interpret the context.
Classification Type
Use
ContainedObjectLink
Indicates that the target object adds further context to the holder,
and that the contained object should not be used on its own without
context of the holder.
ReferenceObjectLink
Indicates that the target object is merely a reference of an independently
submitted source object. These relationships classifications are used, for example, when the target was submitted and can exist independently of the holder (could be in the same same transaction)
PrivateLink
Indicates that the relationship was established for a system purpose, and not by a user or calling solution. Private links are used by the MDM layer, the matching layer, and others to indicate a "do not remove" condition to the persistence layer (i.e. the MDM layer has established this relationship and only the MDM layer can remove it).
PublicContactLink
Indicates that the holder and the target have a direct contact link, that is that the calling system (or an end user using the calling system) may use the relationship to directly contact the source. This is used often in the HL7v2 and FHIR layer for "contacts" (i.e. Mother relationship which can be Contacted)
The TEST_OTHER|TEST device
<dataset id="Test Domain" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://santedb.org/data">
<insert skipIfError="false" skipIfExists="true">
<SecurityApplication xmlns="http://santedb.org/model">
<id>F0FC4322-948D-4986-A06C-DA603A77EDDE</id>
<!-- Secret: TEST_HARNESS -->
<applicationSecret>b5547020757c0efa3f320fbd2a0c43d0628e19b8cd81652523b87d31fc54f5ec</applicationSecret>
<name>TEST_HARNESS</name>
</SecurityApplication>
</insert>
<insert skipIfError="false" skipIfExists="true">
<SecurityDevice xmlns="http://santedb.org/model">
<id>6746d4a7-7522-4334-8299-ffda8ea73202</id>
<!-- Secret: TEST_HARNESS -->
<deviceSecret>b5547020757c0efa3f320fbd2a0c43d0628e19b8cd81652523b87d31fc54f5ec</deviceSecret>
<name>TEST_OTHER|TEST</name>
> application.add TEST_OTHER -s TEST_HARNESS
> device.add TEST_OTHER|TEST -s TEST_HARNESSTest harness sends ADT^A01 message where the CX.4 of the PID is missing.
Receiver rejects the message with an AR or AE
Response is ACK^A01
Response version is 2.3.1
MSA indicates that an assigning authority (PID-3-4) could not be resolved.
PubSub Broker
The publish/subscribe broker is responsible for brokering the publish and subscribe events to/from the manager service. The broker subscribes to events from the repository and merging service, ad then queues these messages on the configured IDispatcherQueueService
Dispatcher Queue
The dispatcher queue service is responsible for interacting with a persistent queue technology and enqueueing and dequeuing those messages.
MSMQ Dispatcher Queue File Dispatcher Queue
PubSub Manager
The pub/sub manager service is responsible for maintaining the registration of subscriptions and the related channel configuration.
Ado PubSubManager
Dispatcher Factory
The dispatcher factory is responsible for constructing dispatcher instances based on a particular outbound message format.
FHIR Message Dispatcher Factory FHIR Rest Hook Dispatcher Factory (coming) HL7v2 Dispatcher Factory
Dispatcher
The dispatcher is the class which is responsible for converting the RIM based internal formatted notification to an appropriate notification in the format specified for the receiver.
FHIR Message Dispatcher FHIR RestHook Dispatcher
Create
Triggered when a subscribed resource's Inserted event is fired.
Update
Triggered when the subscribed resource's Updated event is fired.
Delete
Triggered when the subscribed resource's Obsoleted event is fired.
Merge
Triggered when the subscribed resource's merging service fires the Merged event.
UnMerged
Triggered when the subscribed resource's merging service fires the UnMerged event.
Acts are classified into one of these four types based upon their ClassConcept code. This dictates what type of Act the particular tuple in the database represents.
Act Class
Code
Description
Observation
OBS
Indicates that the act represents a value which was observed.
Substance Administration
SBADM
Indicates that the act represents the administration of a substance to an entity.
The class concept list is extensible.
The primary duty of a centralized CDR (and more specifically an MPI) is to maintain records from various sources of information. Identity of that information (patient identity, place identity, event identity, etc.) within a health enterprise (a hospital, province or state, country, etc.) is of paramount importance.
Furthermore, the governing of those identities should also be considered. For example:
Your Immunization System shouldn't be the source of truth for LTC programme identifiers (correct issuing authority)
You may not want to disclose mental health identifiers to a community outreach application (correct disclosure)
You don't want facility associated identifiers being mistakenly assigned to patients (correct usage)
It is important in any SanteDB deployment (especially for SanteMPI) to perform a survey of identifiers which are used in the context in which the solution will be deployed.
Implementers should note:
The types of medical and non-medical identifiers which are currently in use.
Which organizations are responsible for the maintenance and issuing of the identifier.
The lifecycle of the identifier (i.e. how is a new identifier issued, are the holders authenticated, etc.)
The format and requirements of the identifier (are there check digits, if so what are they?)
SanteDB (and by extension SanteMPI) supports a variety of standards, each of which use different labels to identify an identity domain. For example, in FHIR an identity may appear as:
Whereas that same identifier in an HL7v2 message would appear as:
Or in HL7v3 the identifier may appear as:
To properly ensure cross referencing between each of these interfaces, SanteDB will need to know the URL (used primarily in FHIR), the namespce ID (used primarily in HL7v2) and the OID/Universal ID (used primarily in HL7v3).
Since these all need to be unique, it is a good practice that your scheme for these values encompass the entity which owns the identifier, the programme area or department, and the system. For example, if the Ministry of Health runs an infectious disease programme in which an HIV EMR is used, a good Namespace ID for the MRN form that system may be: MOH_ID_HIV_EMR_MRN
An identity domain worksheet has been created and shared below. This worksheet contains instructions and example data which should assist implementers in the organization of their identity domain planning work.
To use the spreadsheet:
Enumerate the issuing organizations in the implementation context (organizations, ministries, etc.) and complete the Issuing Authority sheet.
Enumerate each of the identification domains which are used in the context to which SanteDB or SanteMPI will be deployed.
Update the cover sheet of your worksheet with relevant metadata about the sheet.
SanteDB's concept dictionary is based heavily on the work done in OpenMRS' Concept Dictionary, the SanteDB concept dictionary is logically made up of four fundamental concepts, described in this page.
In SanteDB, a "concept" is a logical construct for representing the idea of something. Concepts are used within the SanteDB core models to represent these ideas on particular attributes. Examples of concepts may be:
The concept of a "Male", or "Female"
The concept of a "Syringe" (an object used to inject a substance)
The concept of "Oral Polio Vaccine" (an antigen administered orally which protects against polio)
Concepts are assigned a unique mnemonic (a human readable term) and a UUID. Additionally concepts may carry one or more display names.
Concepts can be related to one another via a relationship. The relationship of one concept to another is used to indicate parent/child relationships, specification/generalization, etc. A relationship applies to two concepts and carries a concept relationship classification which can be one of:
Concept sets represent a logical grouping of multiple concepts into a single list of related ideas. Concept sets are useful for driving user interface inputs, or allowing the searching/selection of ideas.
For example, a deployment may use the AdministrativeGender concept set to drive their inputs for selecting gender. Jurisdictions can customize those concepts which are members of this set based on their business requirements.
Reference terms are used for the expression of concept within an external codification system. Reference terms are used to translate concept sets into wire-level codifications of those concepts. This design allows the SanteDB internal data model to maintain integrity with a known internal series of concepts, while mapping those concepts to external code systems which may or may not be subjected to changes (for example: ICD9, ICD10 and ICD11 can be implemented by simply mapping).
This page provides a summary of the SanteDB architecture. A more detailed description of this architecture can be found in the SanteDB Functional Design Specification (http://santesuite.org/assets/uploads/sdb-arch-1.11.pdf)
A general overview and introduction to SanteDB is provided here.
SanteDB is a comprised of several software components which operate together to form the basis of a cohesive digital health infrastructure.
The iCDR server is the central integrated clinical data repository which is used to coordinate the many connected clients in an implementation. Typically an implementation of SanteDB will only ever have one logical iCDR instance (i.e. many physical servers are often deployed for scalability however the logical grouping of iCDR servers is acting as a single iCDR).
The primary responsibilities of the iCDR are:
Maintain a master dataset for the entire deployment of SanteDB in a particular health role.
Facilitate the synchronization and sharing of data between sites within the deployment.
Integrate with upstream services such as audit repositories, client registries, etc.
Distribute "over the air" (OTA) software updates to connected clients and apps
The dCDR clients are the disconnected clients which connect to the central iCDR and are typically embedded in applications used by clinics or mobile applications used by end users. The term dCDR client is used loosely to describe any client which is implemented on the dCDR technology. dCDR clients are deployed in data centers, in clinics, on tablets, etc. A deployment of SanteDB will have multiple, potentially hundreds or thousands of, dCDR clients.
No matter the implementation, the dCDR clients are primarily responsible for:
Providing offline access to relevant subsets of data synchronized and replicated from the central iCDR server
Caching centralized credentials, and providing local clinic-level authentication
Serving out the user interface, reports, and other end-user facing elements
Providing a federation point for other dCDR instances
The dCDR Android Application is an implementation of the dCDR services on the Google Android operating system. The dCDR Android application is used whenever tablet or phone users will require access to the SanteDB infrastructure while operating on poor/slow/unavailable cellular internet connections.
The dCDR Android application only exposes the user interface services, offline gateway services such as FHIR, HL7v2, and ATNA are disabled, as is off-host UI access. When the Android host process launches the dCDR service core, it generates a unique secret for that application run, and expects this in the SDB-Magic header on all requests.
The dCDR Windows and Linux applications are self-contained applications which run the SanteDB user interface, and provide a known web-browser component to render them. Like the Android client, these desktop applications disable all API access and generate unique key which is shared between the web-view control and the dCDR services, and is required to access those services.
The dCDR Gateway is a network service which implements the dCDR functionality and is intended for use in environments where third party applications (or users in a shared local network) require access to offline functionality.
The dCDR Gateway exposes FHIR, HL7v2, ATNA, and API calls to any connected client on a local network. The Gateway provides the services of a SanteDB iCDR instance, where clients connected on the local network have no knowledge of the overall connectivity of the clinic or environment they're operating within. This allows applications to continue to operate in local clinic environments even when connectivity to the iCDR is not available.
The dCDR Web Portal is a specialized dCDR environment which has no offline capability. It is primarily designed to operate as a daemon and to serve out, on the internet, the user interfaces directly connected to the central iCDR. This is the technology used to host the administrative panels, any shared/central infrastructure, etc.
Patient Identity Merge No Assigning Authority
This test will ensure that the client registry appropriately handles a merge condition whereby the local authority has not assigning authority to perform or merge the identifiers provided. This test will also ensure that merges across assigning authorities cannot be performed
Test harness (as TEST_HARNESS_B) sends ADT^A40 message attempting to merge identities from TEST_A domain.
Receiver rejects message with an AE
MSH-5 and MSH-6 matches “TEST_HARNESS_B|TEST”
An ERR segment exists identifying the error
Test harness (as TEST_HARNESS_B) sends ADT^A40 message attempting to merge across domains by instructing the receiver to merge an identifier from TEST_A into TEST_B.
Receiver rejects message with an AE or AR
MSH-5 and MSH-6 matches “TEST_HARNESS_B|TEST”
An ERR segment exists identifying the error
Test harness (as TEST_HARNESS_B) sends ADT^A40 message attempting to merge a patient identifier which does not exist.
Receiver rejects message with an AE or AR
MSH-5 and MSH-6 matches “TEST_HARNESS_B|TEST”
An ERR segment exists identifying the error with HL7 code of 204 (key does not exist)
Patient Demographics Query – Identifier query
This test case ensures that the recipient of the query can perform a patient demographics query based on the PID-3 values provided in an admit message.
Test harness sends a PDQ message containing a patient identifier which is known to the receiver:
Receiver Accepts Message with an AA
QAK segment contains OK
Response contains a PID segment containing:
PID-3=439^^^TEST
Test harness sends a PDQ message containing a patient identifier which is unknown to the receiver:
Receiver accepts the message with AA
QAK segment contains NF
Response contains no PID segments
Test harness sends a PDQ message with an invalid query parameter of @PID.3.4.99
Receiver rejects the message with AR or AE
QAK segment contains AE
Response contains no PID segments
Test harness sends a PDQ message and specifies what domains should be returned in the QPD-8 containing a valid domain of TEST
Receiver accepts message with an AA
QAK segment contains OK
Response contains exactly one PID segment
PID-3 (Exactly one)=439^^^TEST
Test harness sends a PDQ message and specifies what domains should be returned in QPD-8 with a valid domain of NID which has no matching identifiers.
Receiver accepts message with an AA
QAK segment contains NF
No PID segments are returned in the response
Test harness sends a PDQ message and specifies what domains should be returned in QPD-8 with an invalid domain of RANDOM.
Receiver rejects the message with AE
Receiver indicates query error with QAK of AE
No PID segments are returned
Receiver indicates QPD^1^8 in the ERR segment
Entities are further classified by their class code and determiner code. The determiner code of an entity is responsible from differentiating a type of an entity (i.e. antigen, dose number, material type, etc.) and an instance or series of instances of an entity (an actual vial of vaccine, a box of syringes, etc.). Most entities within the SanteDB system are expected to be stored as instances of entities, classes of entities will primarily be restricted to materials whereby a class of antigens (OPV for example) will have both instances (vials of OPV) and sub-classes of representing dose numbers (OPV0 – OPV3). Provides a summary of the entity classes and how they are classified in the data model.
Entity Class
Class Code
Description
Entity
ENT
An entity is the base class used to represent a person/place/thing in the SanteDB data model.
Material
Patient Demographics Query – Query by multiple demographics fields
This test ensures that the recipient of the query can perform a query on a series of demographics fields. The test harness will perform a query on a series of combinations of parameters such as name + gender, name + date of birth, gender + date of birth.
Test harness sends a query with patient’s name and gender which results in a match.
Receiver responds with an AA
Receiver indicates records found with QAK of OK
Receiver sends exactly one PID segment with identifier RJ-439 in domain TEST in PID-3
Test harness sends a query with fuzzy date of birth and patient’s name which results in a match.
Receiver responds with an AA
Receiver indicates records found with QAK of OK
Receiver sends exactly one PID segment with identifier RJ-439 in domain TEST in PID-3
Test harness sends a query with date of birth precise to the day in which a gender which results in a match.
Receiver responds with an AA
Receiver indicates records found with QAK of OK
Receiver sends exactly one PID segment with identifier RJ-439 in domain TEST in PID-3
Test harness sends a query with patient’s name and gender which results in no match.
Receiver responds with an AA
Receiver indicates no records found with QAK of NF
Receiver sends no PID segments
Test harness sends a query with fuzzy date of birth and patient’s name which results in no match.
Receiver responds with an AA
Receiver indicates no records found with QAK of NF
Receiver sends no PID segments
After installing a SanteDB iCDR product, such as SanteMPI or SanteIMS, there is often a need to validate that the software is setup and functioning correctly. This page provides reference materials for running these installation qualification tests.
The Security Administration Testing wiki article provides test steps that users can perform to validate that the security environment of SanteDB is running correctly.
If you're running the iCDR and the web host portal you can use the User Interface Test Cases , if you're operating SanteDB iCDR in a headless environment the Admin Console tests provide equivalent tests using the sdbac tooling.
If you've installed the SanteMPI solution you can use the test cases to validate your configuration of SanteMPI.
The test cases cover:
It is recommended that, after is performed that a complete network scan be performed to ensure that the attack surface area of the environment is minimal.
Perform a security scan of the applications involved (see: ) to ensure SSL, XSS, CORS, and other web security practices have been configured appropriately
Add any blocking scripts to browser headers your Application Firewall may be adding
Ensure proper caching policies and login policies are in place
Perform a network port scan/attach tool to ensure that opened ports and services are minimal (see: )
Ensure that only ports you want opened are open
Ensure that ports that are open are secured.
Use OpenSSL to validate that your SSL certificates are properly configured
The Conceptual Concept Dictionary expressed in the physical data model in ADO.NET providers is illustrated below.
Physical Table
Conceptual Entity
Description
cd_tbl
Non-versioned properties of the concept table.
cd_vrsn_tbl
Versioned properties of the concept table.
You can quickly add test/sample data by copying dataset files into the /santedb/data directory of the docker container either using a custom dockerfile or by mounting a volume from the docker image.
These dataset files can be generated from the sdbac command prompt with the cdr.query command to produce dataset files. Dataset files provide a 1:1 mapping to the underlying CDR storage engine and are expressed in XML RIM objects. Dataset files can include:
Infrastructure elements like Assigning Authorities, Concepts, Extension Types, etc.
Clinical elements like Entities or Acts
For example, to initialize an MPI with an identity domain, and an organization with a custom policy, for a particular use case, create a new dataset file containing the identity domain, organization and custom policy:
The file would be copied into the /santedb/data directory of the santedb-mpi or santedb-icdr container with the following Dockerfile.
You can also seed data into the /santedb/data/fhir directory of the container using a custom dockerfile or by mounting the volume from the docker container.
FHIR resources are limited to only those resources which have a IFhirResourceHandler implementation registered and configured. (TODO: Insert link)
FHIR resources can be in JSON or in XML format, and are simply placed in the directory. The seeder then processes these files on application start and will generate two files:
A file with a .completed extension which indicates that the message contents were successfully processed and included into the SanteDB iCDR database.
A file with a .response extension which is the FHIR response that would have been sent via the REST API. This is useful for diagnosing issues with your FHIR message being seeded.
You can deploy either dataset files or FHIR files onto your running iCDR container by either including the files in a custom Dockerfile such as:
Alternately , you can mount the /santedb/data directory as a volume for your container and copy the files, or you can use a command line interface and docker cp such as:
Steps taken to run the hl7 test cases
Pull santempi repository from github : https://github.com/santedb/santempi.git
Having docker installed, run the following command inside santempi/instant directory where the docker-compose.yml file exists to spin up docker containers.
Get the latest sdbac release from github:
Download the sdbac.zip and extract the files.
1-Run the following commands inside sdbac directory where the sdbac.exe is located or run the sdbac.exe directly.
2-Insert the credentials for Username and Password.
3-Wait for the system to get ready
4-Run the following commands:
To create TEST_HARNESS application run:
To create TEST_HARNESS|TEST device run:
To create TEST identity domain and set the assigned authority to TEST_HARNESS run:
Pull hl7-testing-tool from github:
Run hl7-testing-tool solution with visual studio.
They can be run as an entire test suite or an individual test case or test step.
For a test step to pass all mandatory assertions and at least one of alternate assertions for the same terserstring must pass.
SanteDB 1.x was a near direct refactor of the original OpenIZ core, which had components from the MEDIC Service Core project dating back to 2008/2009. While SanteDB 2.x was a refactor off this .NET Framework and PCL code to .NET Standard, there are still many components and patterns (ghosts) of the original service core code from 2008.
The SanteDB Version 3.x roadmap seeks to fully remove these patterns and re-implement many of the core services. However, this presents a problem in that it makes incremental change difficult, and will break the services. For this reason, much of the Version 3.x roadmap is currently in the design / wishlist phase.
Patent Demographics Query – Query by name
SanteDB's components can be used to enable basic data privacy controls on data stored within the SanteDB solution. SanteDB allows objects such as Entities, Acts and identifiers to be tagged with one or more policies which apply to that particular object.
Whenever an Entity, Act or Assigning Authority (identity domain) is tagged with an access policy (such as provided in the ) the configured Privacy Enforcement Service is called and validate access to the record and to apply any actions to the outgoing (or incoming) data.
Patient Identity Feed – Minimal data set
This test ensures that the receiver does not reject a message containing only an identifier, and one of gender, date of birth, mother’s identifier. This test makes no assertion about merging/matching patients
This test mimics the environment whereby a newborn demographic with minimal patient information (gender and date of birth) can be stored by the client registry and faithfully returned with an appropriate query to the interface.
This test validates the MPI/CR's ability to link a mother's record with a newborn's record, and to query that data back from the MPI. This option uses the Pediatrics Demographics Option in section 8.2.1 of the
There are a variety of ways in which SanteDB can be deployed within your architecture. You can use any of the SanteDB technologies to fill any one of a number of logical roles within your broader e-health strategy.
This page discusses the ways in which SanteDB can be operationalized. It is important to note that these patterns can be mixed, as they leverage common user interface and messaging frameworks.
MSH|^~\&|TEST_OTHER|TEST|CR1|MOH_CAAT|20141104174451||ADT^A01^ADT_A01| TEST-CR-01-10|P|2.3.1
EVN||20101020
PID|||RJ-438^^^&&||JOHNSTON^ROBERT^^^^^L|MURRAY^^^^^^L|19830205|M|||1220 Centennial Farm Road^^ELLIOTT^IA^51532||^PRN^PH^^^712^7670867||||||481-27-4185
PV1||IPatient Encounter
ENC
The act represents an encounter between one or more providers of care and one or more clients of care.
Registration
REG
The act represents a registration whereby new data was collected about an entity.
Account Management
ACCM
The act represents the management (adjustment) of an account.
Supply
SPLY
The act represents the supply of one or more materials to/from one or more entities.
Condition
COND
The act represents a chronic or recurring problem or health condition.
Procedure
PROC
The act represents a clinical procedure which was performed on the client of care.
Battery
BAT
The act represents a series of procedures, observations, administrations, etc.
Transport
TRANS
The act represents the physical transporting of materials to/from one or more entities.
Account
ACCT
The act represents an active account (financial, stock, etc.) on which transactions can be performed.
Financial Transaction
FTRANS
The act represents a financial transaction where monies are exchanged between one or more entities.
Invoice Element
INVE
The act represents a sub-element of a financial transaction.
MAT
A material represents a physical thing to which participates in the delivery of care. For example: a syringe, a box of vaccine, etc.
Manufactured Material
MMAT
A manufactured material represents a material which is manufactured such as diluent, vaccine, syringes, etc.
Place
PLC
A place represents a physical location where health services are provided.
Organization
ORG
An organization represents an administrative structure which employs providers, operates clinics, etc.
Person
PSN
A person represents a human being.
Patient
PAT
Represents a person who receives health services.
Provider
PVD
Represents a person who provides health services.
User
USR
Represents a person who actively uses the system.
Device
DEV
Represents a physical object on which health services data is entered, stored, etc.
Application
APP
Represents a piece of software which is used to access, record or update medical data.




The use of the identifier (billing, identification, tagging, etc.)
The scope of the identifier (what type of objects carry this identifier? Patients, vials, boxes etc.)
Commonality of the identifier
What proportion of the population carries this identifier?
Is it normal for the identifier to be readily available?
Is it culturally acceptable (or legally acceptable) to use this identifier? (for example: disclosure of Social Security Number to a pharmacist)
PID-5=JONES^JENNIFER
PID-6=19840125
PID-5=JONES^JENNIFER
PID-6=19840125
The persistence layer refactor is currently underway and the code for these features can be found at: https://github.com/santedb/santedb-server/tree/feature/nuado
The persistence layer is quite messy, and sub-optimal. It was written (as mentioned) starting in 2009 and has over a decade of modifications, changes, etc. to it. A major refactor of the persistence layer could be performed as part of a v2.5 version which cleans the implementation up. The goals of this work item would be:
Refactor all current persistence classes to use yield returns so on-demand mapping and loading of data is performed.
Refactor process of loading, so that only direct properties are loaded either:
At the persistence layer, do not load any associated properties and rely on callers calling : patient.LoadProperty(o=>o.Names) , which is sub-optimal since it requires establishing a new connection rather than loading on an existing connection (this point may be moot)
At the persistence layer, only load direct associated properties that are commonly used directly. Refactor the current LoadState property to an internal value which allows the persistence layer to indicate a value was loaded and needn't be re-checked.
Refactor and clean up the query writer in OrmLite to use only LINQ mapping and expression tree mapping, rather than converting to/from the HTTP representation.
This would require a complete rewrite of the IQueryHack interfaces which currently allow for the optimization by manually creating SQL. Such an IQueryHack would need to be changed to accept an Expression<T> with the desired filters.
Currently all I/O calls, from the REST layer, to the data access layer are using legacy .NET patterns. This work items seeks to correct this by refactoring all I/O calls to the Task Async Pattern. This will require a complete refactoring of the following core components:
The lightweight REST API I/O calls will need to be refactored to support async/await service implementations. Some work has been done to experiment with this in the v2.x core. The changes made to this layer would not be breaking as the RestSrvr layer is the entry point to much of the iCDR and dCDR core functions.
Notes from the experimentation:
The OperationDispatcher should detect if the bound behavior returns a Task or Task<T> and executes the operation as an await(ed) call.
The OperationDispatcher detected if any of the parameters of the operation were a CancellationToken, and if so, it would pass the cancellation token form the WinHTTP API to the method to indicate a cancel down the call chain.
The actual binding implementation should be added (similar to NancyFX) to allow for piggy-backing on either the WinHTTP , Mono HTTP (used by the dCDR on RPi, Docker, and Android) or Kestrel server (for web-hosting only). Currently the RestSrvr only uses the HttpServer implementation which does not pass the CancellationToken
The entire Repository and DataPersistence service layer would need to be refactored such that they return IAsyncEnumerable<T>. The notes for this feature are:
All I/O calls for insert, save, etc. should return Task<T> and allow the passing of a CancellationToken to allow for cancellation of I/O operations.
Query calls (such as Find and Query) should return IAsyncEnumerable<T> to permit async streams of data from the underlying layer.
The query calls should also be refactored to use yield returns minimizing the computational resources required to process results from the database.
The interface should also permit callers to indicate whether a count of total results is required, or whether simple fuzzy paging (i.e. "there is another page") should be called
Unfortunately this refactor will change the service calls such that any existing code and plugins would break. There are two options the team has discussed:
Create IAsyncX versions of each of the service interfaces (not ideal)
This would mean the creation of an IAsyncDataPersistenceService<T> interface which contains only async versions of the call
This would allow existing plugins to operate, however would add burden to maintenance as each implementer must implement both the regular service provider and the IAsyncX version.
Add Async methods to the existing service definitions
This would add allow existing plugins to continue to operate as normal, however would require any implementations of the existing services to be refactored to add async methods.
This has the same maintenance issues as the IAsyncX method
Currently within SanteDB, simple guard classifications can be done on a classifier property, for example:
However, there is a need to support more complex guard expressions wherein a full HDSI guard expression can be placed into the query builder. For example:
The requirements of this nested guard are:
The builder should be able to express simple guards (the current format) as the current LINQ translation of Telecoms.Where(guard=>guard.UseConcept.Mnemonic == WorkPlace).Any()
The builder should be able to process the complex guards (the new format) as a similar LINQ expression of: Telecoms.Where(guard=>guard.TypeConcept.Mnemonic == "EMAIL" && guard.UseConcept.Mnemonic == "WorkPlace").Any(v=>v.Value == "[email protected]")
The persistence layer and SQL translators will also need to be updated to support this type of expression
There has been discussion within the community to support HL7 FHIR PATH as a mechanism for querying data on the FHIR interfaces. The current implementation of FHIR PATH in C# requires passing of FHIR instances to the filter criteria which acts as a delegate.
This is an inefficient design, rather, the goal of the FHIR PATH implementation is, where possible, to map the expression tree generated by the C# HL7.Fhir.FhirPath assembly into a .NET expression tree. This expression tree should then be passed to the persistence layer to be transformed into SQL, where indexing can be performed.
Currently in SanteDB, it is not possible to import terminology sets via a FHIR interface. The goal is to implement import of ValueSet codes into the SanteDB host. There are several complexities with this:
The value set import would merely result in a series of ReferenceTerms being created in the SanteDB database, these reference terms would not be directly useful by the SanteDB system without a person subsequently mapping these terms to a concept (or creating a concept).
The concept map resource would be difficult to import as they represent maps between reference terms. The concept map resource would require that two reference terms be mapped to one concept, or that the two reference terms, already mapped to difference concepts establish as concept association link.
Currently in SanteDB, the CDSS engine requires expression of business rules logic in HDSI, LINQ, or C# for the when conditions. The rationale for this is that on load these expressions are compiled into delegates in C# which improves execution performance.
The implementation of a CQL interpreter in SanteDB would require one of the following implementation patterns:
The CQL expressions would need to be converted to HDSI or equivalent logic. This is difficult since the structure of a FHIR message is completely different than the structure of a RIM object in the SanteDB database.
The resource in question would need to be converted to FHIR to execute the logic, and the activity definition returned would need to be converted back to RIM. This is also not feasible since the translation of these objects can be slow, additionally it requires the implementation of FHIR activity definitions in the SanteDB platform which is a large undertaking.
Compounding the difficulty of implementing CQL in SanteDB is that there are no implementations of CQL in C# or .NET. This means the SanteDB team would need to implement the entire ANTLR4 grammar of CQL into C# logic.
Test harness sends a PDQ message containing a name which is known to the receiver:
Receiver Accepts Message with an AA
QAK segment contains OK
Response contains a PID segment containing:
Response contains a PID segment containing:
PID-5=JONES^JENNIFER
PID-6=19840125
Test harness sends a PDQ message containing a patient name which is unknown to the receiver:
Receiver accepts the message with AA
QAK segment contains NF
Response contains no PID segments
Test harness sends a PDQ message containing a name which is known to the receiver, and indicates a domains to be returned of TEST in QPD-8.
Receiver Accepts Message with an AA
QAK segment contains OK
Response contains exactly one PID segment containing:
PID-3 (Exactly one)=439^^^TEST
PID-5=JONES^JENNIFER
PID-6=19840125
Test harness sends a PDQ message containing a patient name which is known to the receiver and indicates a domains to be returned which is invalid in QPD-8:
Receiver rejects the message with AE
Receiver indicates query error with QAK of AE
No PID segments are returned
Receiver indicates QPD^1^8 in the ERR segment
Receiver accepts the message with an AA
Receiver indicates query success of OK in QAK
Receiver returns at least one PID segment containing the match for Jennifer Jones
Receiver sends a QRI segment with a QRI-3 indicating pattern match and strength of the match
Test harness sends a PDQ message containing a phonetically equivalent name of a known patient to the receiver:Test harness sends a PDQ message containing a wildcard match which is known to the receiver:
Receiver accepts the message with an AA
Receiver indicates query success of OK in QAK
Receiver returns at least one PID segment containing the match for Jennifer Jones
Receiver sends a QRI segment with a QRI-3 indicating phonetic match and strength of the match
Test harness sends a PDQ message containing a name variant match which is known to the receiver:
Receiver accepts the message with an AA
Receiver indicates query success of OK in QAK
Receiver returns at least one PID segment containing the match for Jennifer Jones
Receiver sends a QRI segment with a QRI-3 indicating variant match and strength of the match
Test harness sends a query to verify there are two Jennifer Jones with identifiers assigned in TEST domain.
Receiver responds with an AA
Receiver indicates records found with QAK of OK
Receiver sends two PID segments one having identifier RJ-439 in domain TEST in PID-3 and another having RJ-999 in domain TEST in PID-3
Test harness sends a merge message and instructs the recipient to merge identifier RJ-999 into record RJ-439.
Receiver responds with an AA
Test harness verifies the identifier was merged using the following PIX query.
Receiver responds with an AA
Receiver indicates data found by sending QAK of OK
Receiver responds with exactly one PID segment having :
One PID-3 containing the RJ-439 identifier in domain TEST
One PID-3 containing the RJ-999 identifier in domain TEST
Test harness verifies old identifier is de-referenced from patient record
Receiver accepts the message with AE
Receiver conveys no data found with AE in QAK
Receiver indicates error by sending an ERR segment with QPD^1^3^1^1
Test harness may send a query to verify there are still two Jennifer Jones in the target (i.e. the old record still exists, but the identifiers were merely merged).
Receiver responds with an AA
Receiver indicates records found with QAK of OK
Receiver sends two PID segments one having identifier RJ-439 and RJ-999 in domain TEST in PID-3 and another having no identifiers in domain TEST in PID-3
All conditions from OHIE-CR-02 should be completed prior to running this test suite.
The test harness sends an ADT^A01 message with the mother's patient demographics
Test harness sends an ADT^A01 message with minimal data set containing information for a newborn with only an identifier, gender and date of birth. The PID-6 (Mother's Maiden Name), PID-21 (Mother's Identifier), and PID-24 (Multiple Birth Indicator).
Receiver Accepts Message with an AA
MSH-5 and MSH-6 matches TEST_HARNESS|TEST
Response is ACK^A01
Response is version 2.3.1
Test harness verifies the infant record was created in the receiver.
Receiver responds with an AA
Receiver sends exactly one PID segment with identifier RJ-441 in domain TEST in PID-3
Test harness verifies the receiver can resolve the newborn demographic based on the identifier of the mother.
Receiver responds with an AA
Receiver sends exactly one PID segment with identifier RJ-441 in domain TEST in PID-3
<identifier>
<use value="usual"/>
<type>
<coding>
<system value="http://terminology.hl7.org/CodeSystem/v2-0203"/>
<code value="MR"/>
</coding>
</type>
<system value="http://emrs.elbonia.elb/programme/hiv"/>
<value value="123457"/>
</identifier> 123457^^^MOHS_EMR_HIV&&ISO^^P<id authority="1.2.3.4.5.6.7.8.9" value="123457" />MSH|^~\&|TEST_HARNESS_A^^|TEST^^|CR1^^|MOH_CAAT^^|20141104174451||ADT^A01^ADT_A01|TEST-CR-17-15|P|2.3.1
EVN||20101020
PID|||RJ-203^^^TEST_A||SMITH^SAM^^^^^L||19890225|F|||||||||||
PV1||IMSH|^~\&|TEST_HARNESS_A^^|TEST^^|CR1^^|MOH_CAAT^^|20141104174451||ADT^A01^ADT_A01|TEST-CR-17-20|P|2.3.1
EVN||20101020
PID|||RJ-292^^^TEST_A||SMITH^SAMANTHA^^^^^L||198902|F|||||||||||
PV1||IMSH|^~\&|TEST_HARNESS_B^^|TEST^^|CR1^^|MOH_CAAT^^|20141104174451||ADT^A01^ADT_A01|TEST-CR-17-25|P|2.3.1
EVN||20101020
PID|||SJ-204^^^TEST_B||SMITH^SAMANTHA^^^^^L||198902|F|||||||||||
PV1||IMSH|^~\&|TEST_HARNESS_B^^|TEST^^|CR1^^|MOH_CAAT^^|20141104174451||ADT^A40^ADT_A40|TEST-CR-17-30|P|2.3.1
EVN||20101020
PID|||RJ-203^^^TEST_A||SMITH^SAM^^^^^L||198902|F|||||||||||
MRG|RJ-292^^^TEST_AMSH|^~\&|TEST_HARNESS_B^^|TEST^^|CR1^^|MOH_CAAT^^|20141104174451||ADT^A40^ADT_A40|TEST-CR-17-40|P|2.3.1
EVN||20101020
PID|||SJ-204^^^TEST_B||SMITH^SAM^^^^^L||198902|F|||||||||||
MRG|RJ-292^^^TEST_AMSH|^~\&|TEST_HARNESS_B^^|TEST^^|CR1^^|MOH_CAAT^^|20141104174451||ADT^A40^ADT_A40|TEST-CR-17-50|P|2.3.1
EVN||20101020
PID|||SJ-204^^^TEST_B||SMITH^SAM^^^^^L||198902|F|||||||||||
MRG|RJ-292^^^TEST_BMSH|^~\&|TEST_HARNESS^^|TEST^^|CR1^^|MOH_CAAT^^|20141104174451||ADT^A01^ADT_A01|TEST-CR-11-10|P|2.3.1
EVN||20101020
PID|||RJ-439^^^TEST||JONES^JENNIFER^^^^^L|SMITH^^^^^^L|19840125|F|||123 Main Street West ^^NEWARK^NJ^30293||^PRN^PH^^^409^30495||||||
PV1||IMSH|^~\&|TEST_HARNESS|TEST|CR1|MOH_CAAT|20090226131520-0600||QBP^Q22^QBP_Q21|TEST-CR-11-20|P|2.5
QPD|Q22^Find Candidates^HL7|Q1120|@PID.3.1^[email protected]^TEST
RCP|I|10^RDMSH|^~\&|TEST_HARNESS|TEST|CR1|MOH_CAAT|20090226131520-0600||QBP^Q22^QBP_Q21|TEST-CR-11-30|P|2.5
QPD|Q22^Find Candidates^HL7|Q1130|@PID.3.1^[email protected]^TEST
RCP|I|10^RDMSH|^~\&|TEST_HARNESS|TEST|CR1|MOH_CAAT|20090226131520-0600||QBP^Q22^QBP_Q21|TEST-CR-11-40|P|2.5
QPD|Q22^Find Candidates^HL7|Q1140|@PID.3.1^[email protected]^NOVALUE
RCP|I|10^RDTESTMSH|^~\&|TEST_HARNESS|TEST|CR1|MOH_CAAT|20090226131520-0600||QBP^Q22^QBP_Q21|TEST-CR-11-50|P|2.5
QPD|Q22^Find Candidates^HL7|Q1150|@PID.3.1^[email protected]^TEST|||||^^^TEST
RCP|I|10^RDMSH|^~\&|TEST_HARNESS|TEST|CR1|MOH_CAAT|20090226131520-0600||QBP^Q22^QBP_Q21|TEST-CR-11-60|P|2.5
QPD|Q22^Find Candidates^HL7|Q1160|@PID.3.1^[email protected]^TEST|||||^^^NID
RCP|I|10^RDMSH|^~\&|TEST_HARNESS|TEST|CR1|MOH_CAAT|20090226131520-0600||QBP^Q22^QBP_Q21|TEST-CR-11-70|P|2.5
QPD|Q22^Find Candidates^HL7|Q1170|@PID.3.1^[email protected]^TEST|||||^^^RANDOM
RCP|I|10^RDEnsure that the following patient is registered in the receiver (can be done with the ADT message provided). Name: Jennifer Jones, id: RJ-439^^^TEST, gender: F, dob: 1984-01-25
EVN||20101020
PID|||RJ-439^^^TEST||JONES^JENNIFER^^^^^L|SMITH^^^^^^L|19840125|F|||123 Main Street West ^^NEWARK^NJ^30293||^PRN^PH^^^409^30495||||||
PV1||IMSH|^~\&|TEST_HARNESS|TEST|CR1|MOH_CAAT|20090226131520-0600||QBP^Q22^QBP_Q21|TEST-CR-15-20|P|2.5
QPD|Q22^Find Candidates^HL7|Q1520|@PID.8^[email protected]^JONES
RCP|I|10^RDMSH|^~\&|TEST_HARNESS|TEST|CR1|MOH_CAAT|20090226131520-0600||QBP^Q22^QBP_Q21|TEST-CR-15-30|P|2.5
QPD|Q22^Find Candidates^HL7|Q1530|@PID.7^[email protected]^[email protected]^JENNIFER
RCP|I|10^RDMSH|^~\&|TEST_HARNESS|TEST|CR1|MOH_CAAT|20090226131520-0600||QBP^Q22^QBP_Q21|TEST-CR-15-40|P|2.5
QPD|Q22^Find Candidates^HL7|Q1540|@PID.7^[email protected]^F
RCP|I|10^RDMSH|^~\&|TEST_HARNESS|TEST|CR1|MOH_CAAT|20090226131520-0600||QBP^Q22^QBP_Q21|TEST-CR-15-50|P|2.5
QPD|Q22^Find Candidates^HL7|Q1550|@PID.8^[email protected]^[email protected]^JENNIFER
RCP|I|10^RDMSH|^~\&|TEST_HARNESS|TEST|CR1|MOH_CAAT|20090226131520-0600||QBP^Q22^QBP_Q21|TEST-CR-15-60|P|2.5
QPD|Q22^Find Candidates^HL7|Q1560|@PID.7^[email protected]^[email protected]^JASON
RCP|I|10^RD<?xml version="1.0"?>
<dataset id="Elbonia Identity Domains" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://santedb.org/data">
<!-- National Health Identifier -->
<insert skipIfError="false" skipIfExists="true">
<AssigningAuthority xmlns="http://santedb.org/model">
<name>Elbonia</name>
<domainName>MOH_NHID</domainName>
<oid>1.3.6.1.4.1.52820.5.0.1.1.1</oid>
<url>http://mpi.moh.gov.elb/identity/moh/nhid</url>
<isUnique>true</isUnique>
<validation>^\d{12}$</validation>
<scope>bacd9c6f-3fa9-481e-9636-37457962804d</scope>
</AssigningAuthority>
</insert>
<update insertIfNotExists="true">
<Organization xmlns="http://santedb.org/model">
<id>fae7b5fb-ea49-4460-9149-f0952efe572a</id>
<classConcept>7c08bd55-4d42-49cd-92f8-6388d6c4183f</classConcept>
<determinerConcept>f29f08de-78a7-4a5e-aeaf-7b545ba19a09</determinerConcept>
<statusConcept>c8064cbd-fa06-4530-b430-1a52f1530c27</statusConcept>
<industryConcept>fdeb2e4e-9e02-4ce3-ab69-cece5ffdee20</industryConcept>
<name>
<use>1ec9583a-b019-4baa-b856-b99caf368656</use>
<component>
<value>Elbonia National Health Insurnace Corporation</value>
</component>
</name>
</Organization>
</update>
<update insertIfNotExists="true">
<SecurityPolicy xmlns="http://santedb.org/model">
<id>fd8c0e00-82fb-11eb-8dcd-0242ac130004</id>
<name>Elbonia Parlimentarian Health Record VIP Access Policy</name>
<oid>2.25.40394829382872728372832</oid>
<isPublic>true</isPublic>
<canOverride>false</canOverride>
</SecurityPolicy>
</update>
</dataset>FROM santedb-icdr:latest
COPY custom.dataset /santedb/data/custom.datasetFROM santedb-icdr:latest
COPY patients.json /santedb/data/fhir/patients.json
COPY identity.dataset /santedb/data/identity.datasetdocker cp patients.json santedb-icdr:/santedb/data
docker cp identity.dataset santedb-icdr:/santedb/dataPatient?telecom[WorkPlace][email protected]Patient?telecom[type.mnemonic=EMAIL&use.mnemonic=WorkPlace][email protected]MSH|^~\&|TEST_HARNESS^^|TEST^^|CR1^^|MOH_CAAT^^|20141104174451||ADT^A01^ADT_A01|TEST-CR-12-10|P|2.3.1
EVN||20101020
PID|||RJ-439^^^TEST||JONES^JENNIFER^^^^^L|SMITH^^^^^^L|19840125|F|||123 Main Street West ^^NEWARK^NJ^30293||^PRN^PH^^^409^30495||||||
MSH|^~\&|TEST_HARNESS|TEST|CR1|MOH_CAAT|20090226131520-0600||QBP^Q22^QBP_Q21|TEST-CR-12-20|P|2.5
QPD|Q22^Find Candidates^HL7|Q1220|@PID.5.1^[email protected]^JENNIFER
RCP|I|10^RDMSH|^~\&|TEST_HARNESS|TEST|CR1|MOH_CAAT|20090226131520-0600||QBP^Q22^QBP_Q21|TEST-CR-12-30|P|2.5
QPD|Q22^Find Candidates^HL7|Q1230|@PID.5.1^[email protected]^ROBIN
RCP|I|10^RDMSH|^~\&|TEST_HARNESS|TEST|CR1|MOH_CAAT|20090226131520-0600||QBP^Q22^QBP_Q21|TEST-CR-12-40|P|2.5
QPD|Q22^Find Candidates^HL7|Q1240|@PID.5.1^[email protected]^JENNIFER|||||^^^TEST
RCP|I|10^RDMSH|^~\&|TEST_HARNESS|TEST|CR1|MOH_CAAT|20090226131520-0600||QBP^Q22^QBP_Q21|TEST-CR-12-45|P|2.5
QPD|Q22^Find Candidates^HL7|Q1245|@PID.5.1^[email protected]^JENNIFER|||||^^^RANDOM
RCP|I|10^RDMSH|^~\&|TEST_HARNESS|TEST|CR1|MOH_CAAT|20090226131520-0600||QBP^Q22^QBP_Q21|TEST-CR-12-50|P|2.5
QPD|Q22^Find Candidates^HL7|Q1250|@PID.5.1^JO*[email protected]^JEN*|||||
RCP|I|10^RDMSH|^~\&|TEST_HARNESS|TEST|CR1|MOH_CAAT|20090226131520-0600||QBP^Q22^QBP_Q21|TEST-CR-12-60|P|2.5
QPD|Q22^Find Candidates^HL7|Q1260|@PID.5.1^[email protected]^JENIPHER|||||
RCP|I|10^RDMSH|^~\&|TEST_HARNESS|TEST|CR1|MOH_CAAT|20090226131520-0600||QBP^Q22^QBP_Q21|TEST-CR-12-70|P|2.5
QPD|Q22^Find Candidates^HL7|Q1270|@PID.5.1^[email protected]^JENN|||||
RCP|I|10^RDMSH|^~\&|TEST_HARNESS^^|TEST^^|CR1^^|MOH_CAAT^^|20141104174451||ADT^A01^ADT_A01|TEST-CR-16-10|P|2.3.1
EVN||20101020
PID|||RJ-439^^^TEST||JONES^JENNIFER^^^^^L|SMITH^^^^^^L|19840125|F|||123 Main Street West ^^NEWARK^NJ^30293||^PRN^PH^^^409^30495||||||
PV1||IMSH|^~\&|TEST_HARNESS^^|TEST^^|CR1^^|MOH_CAAT^^|20141104174451||ADT^A01^ADT_A01|TEST-CR-16-15|P|2.3.1
EVN||20101020
PID|||RJ-999^^^TEST||JONES^JENN^^^^^L||198401|F|||||||||||
PV1||IMSH|^~\&|TEST_HARNESS|TEST|CR1|MOH_CAAT|20090226131520-0600||QBP^Q22^QBP_Q21|TEST-CR-16-20|P|2.5
QPD|Q22^Find Candidates^HL7|Q1620|@PID.5.1^JONES|||||^^^TEST
RCP|I|10^RDMSH|^~\&|TEST_HARNESS^^|TEST^^|CR1^^|MOH_CAAT^^|20141104174451||ADT^A40^ADT_A40|TEST-CR-16-30|P|2.3.1
EVN||20101020
PID|||RJ-439^^^TEST||JONES^JENN^^^^^L||198401|F|||||||||||
MRG|RJ-999^^^TESTMSH|^~\&|TEST_HARNESS|TEST|CR1|MOH_CAAT|20090223144546||QBP^Q23^QBP_Q21|TEST-CR-16-40|P|2.5
QPD|IHE PIX Query|Q1640|RJ-439^^^TEST^PI|^^^TEST
RCP|IMSH|^~\&|TEST_HARNESS|TEST|CR1|MOH_CAAT|20090223144546||QBP^Q23^QBP_Q21|TEST-CR-16-50|P|2.5
QPD|IHE PIX Query|Q1650|RJ-999^^^TEST^PI|^^^TEST
RCP|IMSH|^~\&|TEST_HARNESS|TEST|CR1|MOH_CAAT|20090226131520-0600||QBP^Q22^QBP_Q21|TEST-CR-16-60|P|2.5
QPD|Q22^Find Candidates^HL7|Q1660|@PID.5.1^JONES
RCP|I|10^RDMSH|^~\&|TEST_HARNESS^^|TEST^^|CR1^^|MOH_CAAT^^|20141104174451||ADT^A01^ADT_A01|TEST-CR-05-10|P|2.3.1
EVN||20101020
PID|||RJ-439^^^TEST||JONES^JENNIFER^^^^^M|SMITH^^^^^^L|19840125|F|||123 Main Street West ^^NEWARK^NJ^30293||^PRN^PH^^^409^30495||||||
PV1||IMSH|^~\&|TEST_HARNESS^^|TEST^^|CR1^^|MOH_CAAT^^|20141104174451||ADT^A01^ADT_A01|TEST-CR-05-20|P|2.3.1
EVN||20141001
PID|||RJ-441^^^TEST|||JONES^JENNIFER|20141001|M|||||||||||||RJ-439^^^TEST|||1
PV1||IMSH|^~\&|TEST_HARNESS|TEST|CR1|MOH_CAAT|20090223144546||QBP^Q23^QBP_Q21|TEST-CR-05-30|P|2.5
QPD|IHE PIX Query|Q0530|RJ-441^^^TEST^PI
RCP|IMSH|^~\&|TEST_HARNESS|TEST|CR1|MOH_CAAT|20090223144546||QBP^Q22^QBP_Q22|TEST-CR-05-30|P|2.5
QPD|Q22^Find Candidates^HL7|Q0540|@PID.21.1^[email protected]^TEST
RCP|IIndicates that concept A is a member or sub-concept of concept B. For example, a concept for "Ebola" may be a member of the concept "Hemorrhagic Fever".
Relationship
Description
Same As
Indicates that concept A is the same as concept B. The two concepts can be considered interchangeable (i.e. if a system uses concept A and another system queries using concept B, then concept A and B should be considered equal).
Narrower Than
Indicates that concept A represents an idea which is narrower in scope than concept B. For example, a concept of "Diagnosis-YellowFever" would be narrower than "Diagnosis-Fever"
Wider Than
Indicates that concept A is a broader idea than concept B. This is the inverse of the Narrower-Than relationship.
Negation Of
Indicates that concept A negates concept B.
Inverse Of
Indicates that concept A has the opposite semantic meaning of concept B.
Member Of
Provide a centralized authentication and privacy information distribution point.
Executing data quality checks, business rules, clinical decision support rules, etc. while the central iCDR server is not available
Pub-Sub Behavior Changes
In order to complete this tutorial you will require the following tools:
A setup version of SanteMPI (you can use the Quick Start Guide)
The ONC Patient Matching Challenge Data (https://github.com/onc-healthit/patient-matching)
The SanteDB SDK (you can see Operationalizing SanteDB)
SanteMPI Version 3.x contains the necessary configuration for the ONC patient matching data in a dataset file which can be downloaded from our GitHub page: https://github.com/santedb/santempi/blob/master/data/090-ONC%20Patient%20Matching%20Domains.dataset
Once downloaded, visit the SanteMPI administration console and import the dataset file via CDR Administration > Import Data
Once uploaded - administrators will see the dataaset scheduled for import:
Pressing the Run Scheduled will setup the identity domains.
Following this step, the ONC dataset files can be uploaded, when uploading a dataset file, be sure to set the type of file to ONC Patient Matching Challenge as pictured below:
Once the files are uploaded, you can run the import.
First, we're going to need to prepare our SanteDB server to accept the ONC data, this includes:
Creating the necessary identity domains for the ONC spreadsheets
Setting the matching configuration appropriately
The ONC dataset has two identity domains which need to be created in the SanteDB server. To do this, log into the administrative portal and click on Reference Data then Identity Domains and press Create.
You will need to register two identity domains:
ONC
http://onc.org/eid
2.25.4949384934
true
MRN
http://onc.org/mrn
2.25.17237262721
false
The ONC dataset is a large dataset where the source records (provided in the CSV files) can reliably represent a patient, because of this we can get an added performance bonus by changing our match configuration to source/source mode rather than source/master (since there is nothing that a master record would add in blocking).
To change the match configuration, click on SanteMPI then Match Settings locate the org.santedb.matching.patient.default entry and click View.
On the Blocking tab if we expand a blocking instruction we see the default method of matching is Source/Master:
We can change this by pressing Edit (pencil) and modifying both blocking instructions. After this step the configuration should appear as:
Now that our MPI is setup correctly we should navigate to the directory where the ONC patient source data was cloned. To seed the data more easily, create a new batch file (if on Windows - if on Unix you should create an equivalent shell file) to call the SDK:
The batch file will look at all the CSV files in the current directory and for each one it will:
Start a new process
Call the importer from the SDK with
The CSV file to be seeded
The realm on the local computer
Logged in as "Allison" and "Mohawk123" as password (i.e. this is Allison sending the data to the MPI)
Source format is ONC (opposed to FEBRL)
Enterprise ID is the ONC domain
Medical Record Number field maps to MRN domain
Social Security Number field maps to SSN domain
Now you can open a command prompt and type seed-onc.bat to start the seeding process. There will 9 consoles opened and 9 clients will begin seeding data to the MPI.
The overall health of your deployment can be monitored on the Probes page.
The disclosure validation on the enforcement compares the current security principals effective permission policy set and takes appropriate action (based on configuration) for the disclosure of the record. The actions which may be taken on objects like Entities (Person, Patient, Organization, Place, etc.) or Acts (Substance Administrations, Tests, etc.) are:
Enforcement Action
Description
Audit
The data is disclosed to the caller, however a high priority audit is created and
persisted (and shipped to the central audit repository) indicating the record was
disclosed.
Hide
The data is removed from the result set. There is no indication to the caller that
the data exists. For example: If a search for everyone named John were to return
10 results, however one was protected, then only 9 results would be returned in
the result set.
Redact
Only the data's primary UUID, the status, applicable policies are disclosed to the caller. This means the caller can *see* there is data present, however the caller
cannot determine *what* the data is (note: if the caller determines, based on the policies listed in the object it can BTG then it can take appropriate action to
elevate)
Nullify
Only the data's primary UUID is disclosed. No policy, or status is disclosed.
Error
The CDR will throw a privacy violation error, indicating to the caller that they
have attempted to access information which they do not have appropriate
access permission to.
In addition to entire objects like patients, immunizations, procedures, etc. carrying privacy policies, it is possible to flag identity domains with access/disclosure policies. These policies are enforced on both disclosure and on write, meaning that reading and editing/inserting identities in protected domains is restricted to only principals with appropriate access permissions.
Action
Description
Hide or Nullify
The identifier is removed from the object and is never disclosed to the caller. The caller is unaware that the identifier exists.
Hash
The identifier is disclosed in a hashed form to the caller. The caller is aware of the authority and is presented with a hash which can be used for matching with identifiers in its own data store.
Redact
The identifier is disclosed in a redacted form. The caller is aware the identifier exists
in the identity domain, and is aware of the length of the identifier, however all characters within the identifier are replaced with X. (example: HIV-30493 becomes XXXXXXXXX)
Audit
The identifier is disclosed to the caller in plain form, the caller can see the specific
identifier assigned to the patient. The CDR will dispatch an audit to its internal audit
repository and will ship an audit to the central audit repository for follow up.
You should use the headless server environment virtual appliance when deploying an instance of SanteDB (and related solutions) for light production duty, or development. These virtual appliances include:
Ubuntu Server 20.04
Mono Framework 6.2
PostgreSQL 10
SanteDB iCDR Server
SanteDB Administrative Portal
You should use the developer environment virtual appliances when you need to rapidly onboard developers. These virtual appliances contain not only the SanteDB iCDR and dCDR environments, but the SanteDB SDK tooling, and related software including:
Ubuntu 20.04
XFCE4 Desktop Environment
MonoDevelop
PostgreSQL 10
Visual Studio Code
DBeaver Community Edition
SanteDB iCDR Server
SanteDB dCDR Server
SanteDB SDK
User: sante Password: SanteDB123 After deploying and setting up the OVA, you should either:
Setup a host entry or DNS entry for santempi.local which points to the IP address of the appliance in your environment, or
Edit the /etc/nginx/sites-available/santedb file and edit the server_name to use your own DNS entries
The service requires that port 80 and 8080 be opened to allow for administrative and API access from other hosts respectively.
Setting
Value
SanteDB iCDR Location
/opt/santedb/server
SanteDB dCDR Location
/opt/santedb/dcdr-www
iCDR API Port
http://127.0.0.1:18080
dCDR API Port
http://127.0.0.1:9200
API User
Administrator
You can deploy many of the SanteDB solutions to operate as a standalone interoperable registry / repository of information. In this deployment pattern, SanteDB is used as a headless repository of information and user-facing interaction is provided by third party applications which connect to SanteDB using any one of the standards supported by SanteDB.
In this deployment, the iCDR interface can be interacted with directly (as shown below) or can operate with an intermediary such as EAI/ESB engine.
This model is most effectively used when leveraging SanteDB within a single organization, or within a single site (like a hospital). You can also leverage this solution over the internet, however it is recommended laying the iCDR infrastructure behind an application firewall or integration services.
Examples of third party applications which may integrate with the iCDR engine may include:
Logistics Management Information Systems (LMIS) using the GS1 BMS XML interfaces
Electronic Medical Records (EMR) Systems using the HL7 Version 2x or HL7 FHIR interfaces
Personal Health Records (PHR) using the HL7 FHIR interfaces
Mobile Applications using the HL7 FHIR interfaces
Any connected system requiring central authentication using the OpenID Connect interface
Hospital Information Systems (HIS) using the HL7v2 or FHIR interfaces
Picture Archiving Communication Systems (PACS) using HL7v2 interfaces
In this deployment pattern SanteDB's iCDR is bundled with a web portal solution which allows end-users to directly leverage the SanteDB iCDR features using a web browser.
This solution is most useful when you have robust internet infrastructure and users can easily access internet based resources.
In this deployment pattern, SanteDB acts as a disconnected integrator and CDR for solutions that otherwise lack the ability to interoperate in a disconnected way.
Here, end users within the clinic use already existing software tooling that they are familiar with. These third party systems communicate with the SanteDB dCDR which has been configured to synchronize with the central iCDR interface using a variety of subscription methods.
These clinic systems may require no additional software updates, since the dCDR behaves like a remote endpoint using any one of the standards supported (HL7 v2, HL7 FHIR, etc.). Additionally, the dCDR will execute any business rules which have been configured from the central server while offline. The connection to the iCDR is not necessary to support the operation of the solution.
In this deployment, clinic users leverage the dCDR applications to directly interact with the iCDR interface in an online/offline manner, using the end-user portal written in the SanteDB UI framework.
The software / portal use in this environment can be:
Users using laptops/tablets within a single clinic connected to any configured dCDR instance operating in that clinic (for example, over Wi-Fi), the dCDR interface then communicates with the central iCDR.
Larger clinics with multiple users and devices
Clinics/Hospitals which require a mix of the user portal and third party applications.
Users using the disconnected portal on an Android tablet or phone. The phone/tablet directly synchronizes its data with the iCDR interface when there is an available internet connection.
Community health workers that operate independently offline
Small clinics with only one staff member on one device giving care to patients at a time.
Users using the Windows or Linux user interface. Here the portal operates as a self-contained application on the client and the laptop directly synchronizes with the central iCDR service.
Small clinics with only one staff member giving care to patients
Users connecting using the Android application whereby they may operate in a clinic environment (Wi-Fi against the dCDR) or in the field (offline from the clinic's dCDR). This is a chained synchronization deployment pattern whereby the Android/Windows/Linux app synchronizes against a clinic dCDR, which in turn, synchronizes against the master.
Larger clinic/hospitals where WI-FI may drop in areas of the clinic
Clinics which perform outreach programmes in the community
BOM
BOM
Locates local copy of object for subsequent calls
Isolates the data fields which the caller is permitted to update.
Calls the matching service to detect candidate MASTER records which the record may belong.
Re-writes the object on the persistence pipeline
Matching Service
BOM
BOM
Uses the matcher configuration to establish matches.
Queries / Blocks against the underlying, configured persistence service.
ADO Persistence
BOM
Physical
Translate the business object model into the physical model objects.
Interacts with the underlying storage technology to reliably store, and retrieve data.
Transaction control (appropriate rollback/commit infrastructure)
Performs final data layer check (uniqueness, semantic meaning, etc.)
PostgreSQL
Physical
SQL
Translates the physical object model in SQL INSERT/UPDATE/SELECT statements
Maps query expression trees into SQL
cd_name_tbl
Human readable names of the concept in various languages.
cd_rel_assoc_tbl
Concept relationships table.
cd_rel_typ_cdtbl
Concept Relationship types reference code table.
cd_set_tbl
Concept Set definition table.
cd_set_mem_assoc_tbl
Concept Set Member
Concept Set <> Concept relationship associative table.
cd_ref_term_assoc_tbl
Concept <> Reference Term associated table.
ref_term_tbl
Reference term definition table.
ref_term_name_tbl
Preferred display names of the reference term (when being represented on a standards interface)
cd_sys_tbl
Code system table
SanteDB software can be downloaded via the GitHub pages for each of the projects.
Download Link
Contents
Installation Instructions
The following iCDR server releases can be found via the on GitHub:
Microsoft Windows Installation Package
Linux Distribution (manual install via tarball)
MacOS (manual install via zip)
Additionally, you can download a virtual appliance via an Open Virtual Appliance file:
(useful for running SanteDB in a production environment)
(useful for developers working with SanteDB)
You can also run SanteDB iCDR products in a Docker or Kubernetes environment. For more details see the documentation.
Typically a SanteDB dCDR instance is customized and branded for a particular context. You can download the vanilla (whitelabel) dCDR Android Applications via the project.
The self-contained Windows Application is useful for disconnected environments where larger datasets are required offline and higher burden of data entry is necessary. The Windows Application can be installed via the installers available on the project.
The disconnected gateway service provides a common dCDR instance running on a local area network and allows multiple web-browsers, Android apps, and third party systems (via HL7 or FHIR) to connect to the disconnected environment.
The dCDR can be installed and is tested on:
Microsoft Windows via an installer
Linux or MacOS via a tarball/zip distribution (requires Mono framework)
Raspbian or MacOS M1 ARM processors (requires Mono for ARM)
The dCDR Gateway can be downloaded from the project.
The dCDR WWW service allows operators of SanteDB infrastructure to host dCDR applications (which are typically designed for offline use) to operate in an online-only fashion and allows for access to the user interfaces for broad internet hosting environments.
The dCDR web host is typically used to host administrative panels, reporting portals, etc. The service can be installed on:
Microsoft Windows (via installer)
Linux or MacOS (via tarball - requires Mono Framework)
Docker Containers
The installers can be accessed via the project. The docker instance can be spun up using the santedb-www:latest docker image.
The SanteDB SDK is used by developers to simulate the offline dCDR in a debug-friendly environment. The SDK is documented on the wiki page.
The SDK runs on:
Microsoft Windows (via installer)
Linux or MacOS (via tarball - requires Mono Framework)
It can be downloaded from the project page.
This page describes the planning stages and various deployment scenarios which SanteDB supports.
Patient Identity Feed – Blocks invalid assigning authority
This test ensures that two sources cannot assign identifiers from the other’s assigning domain. In this test, the harness mimics two authorities (TEST_HARNESS_A and TEST_HARNESS_B). They each register a patient and the harness then verifies that TEST_HARNESS_B does not assign an identifier from TEST_HARNESS_A’s identity domain.
While not a hard requirement of the IHE Patient Identity Cross Referencing specification, it is important to ensure that identity sources are governed in a manner which ensures that cross-domain registrations/merges/modifications are performed.
indicates that the association of identity sources with their assigning authority be a supported feature, particularly in section 3.8.4.1.3.1:
openssl s_client -connect demompi.santesuite.net:443 -showcerts
CONNECTED(00000003)
depth=2 C = BE, O = GlobalSign nv-sa, OU = Root CA, CN = GlobalSign Root CA
verify return:1
depth=1 C = BE, O = GlobalSign nv-sa, CN = AlphaSSL CA - SHA256 - G2
verify return:1
depth=0 CN = *.santesuite.net
verify return:1
---
Certificate chain
0 s:CN = *.santesuite.net
i:C = BE, O = GlobalSign nv-sa, CN = AlphaSSL CA - SHA256 - G2@echo off
for %%F in (*.csv) do (
start "Seeding %%F" "c:\Program Files\SanteSuite\SanteDB\SDK\importer.exe" --realm=http://127.0.0.1:8080 --user=Allison --password=Mohawk123 --source="%%F" --dataset=ONC --eid=ONC --mrn=MRN --ssn=SSN
)batch docker compose -f docker-compose.yml upsdbacapplication.add TEST_HARNESS -s TEST_HARNESSdevice.add TEST_HARNESS|TEST -s TEST_HARNESSaa.add -n TEST -o 2.16.840.1.113883.3.72.5.9.1 -u http://ohie.org/test/test -d 'OpenHIE Test Domain' -a TEST_HARNESSNone
No Action is taken
API Password
Mohawk123
SanteDB iCDR Server
SanteDB Administration Console
SanteMPI Server
Web Access Gateway Service
Applet Debugger
Business Rules Debugger
Data Importer
Package Manager






SanteDB Server can be a light process, and requirements for running SanteDB Server will vary depending on your deployment and purpose. At minimum, SanteDB Server requires:
Operating System: Windows Server 2008R2 SP1, Windows 7 SP2, Linux (varies), MacOS 10.9+
RAM: 1 GB RAM minimum (more if using Memory Caching)
CPU: Any (multi-core system recommended)
HDD: 300 MB recommended
SanteDB Server runs on a variety of operating systems and a variety of RDBMS however not all RDBMS modules are available on all platforms.
OS
PostgreSQL
FirebirdSQL
Windows
9.6+, 10
3.0+
MacOS
9.6+, 10
Not Supported
Linux
9.6+, 10
Not Supported
PostgreSQL 9.6 or 10 are recommended for use with SanteDB, and are the only two versions of PostgreSQL with which SanteDB server is tested. Earlier versions of PostgreSQL may be supported, however some features or unexpected behaviors may occur.
Use PostgreSQL when:
You are deploying to a training, testing, or production environment
Your SanteDB server will be accessed by multiple clients
You require the use of third party reporting, ETL, or query tools
You need to support or scale out of your application server
FirebirdSQL 3.0 is also supported on Microsoft Windows based machines (it could be supported on Linux with a few modifications). FirebirdSQL provides a fully ACID compliant RDBMS solution while also being embedded within the SanteDB host process. This allows SanteDB Server to run without requiring setup of a third party database server.
Use FirebirdSQL when:
You are setting up a development or testing server
You need to easily wipe/backup/restore test datasets (you can copy your FDB file and restart the service)
You need to setup a demonstration on a lower powered laptop
You are evaluating a new SanteDB based product and want a quick solution for deployment
SanteDB supports a caching as a query optimization strategy. The SanteDB cache is used to prevent further retrieval of resources from the database system, which is slower than system memory. In SanteDB there are two solutions for caching.
The in-process memory cache is the easiest to setup. It requires no additional software services to be running and allows SanteDB Server to store objects in its own memory space.
Use in-process memory caching when:
You are setting up a development or testing server
You don't want to setup a REDIS environment
You don't need to scale out your application servers.
SanteDB Server also supports connecting to the NoSQL database REDIS. SanteDB Server uses REDIS as a cache solution which can be persisted or in-memory only.
Use REDIS caching when:
You may need to scale out your application servers (i.e. multiple servers accessing the shared REDIS cache)
You are setting up a production, training or staging environment and don't want a cold-start of the SanteDB server to result in cache misses.
SanteDB's iCDR uses code signing in order to verify the identity of publishers of Applets and Plugins. Many community partners use publishing certificates issued by the SanteDB Community Certificate Authority.
When you install the iCDR or dCDR the software needs to register these certificates.
On Microsoft Windows the Configuration Tool registers these certificates into the Local Machine Trusted Authorities store.
On Linux and MacOS you must manually run mono SanteDB.exe --install-certs which will register the certificates into the Mono's Trust Store
On Docker the registration occurs on service startup
On Android the certificates are installed into the device Trust Store
Patient Identity Source for the domain. This is expected to be the MSH-3 Sending Application and the corresponding MSH-4 Sending Facility fields in the HL7 ADT message. (Alternative identification schemes might include IP address of the Patient Identity Source or Node Authentication if the Audit Trail and Node Authentication Integration Profile is used.)
Prior to executing the tests in this test case, the system under test should be configured such that:
Application TEST_HARNESS_A is configured
Application TEST_HARNESS_B is configured
Device TEST_HARNESS_A|TEST is configured
Device TEST_HARNESS_B|TEST is configured
Authority TEST_A with OID 2.16.840.1.113883.3.72.5.9.2 is configured and TEST_HARNESS_A is granted authority to assign identifiers in this domain
Authority TEST_B with OID 2.16.840.1.113883.3.72.5.9.3 is configured and TEST_HARNESS_B is granted authority to assign identifiers in this domain.
<dataset id="Test Domain" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://santedb.org/data">
<insert skipIfError="false" skipIfExists="true">
<SecurityApplication xmlns="http://santedb.org/model">
<id>DE5BEC1E-8C41-4FF1-8E65-A39AC1DDAE60</id>
<!-- Secret: TEST_HARNESS -->
<applicationSecret>b5547020757c0efa3f320fbd2a0c43d0628e19b8cd81652523b87d31fc54f5ec</applicationSecret>
<name>TEST_HARNESS_A</name>
</SecurityApplication>
</insert>
<!-- TEST -->
<insert skipIfError="false" skipIfExists="true">
<AssigningAuthority xmlns="http://santedb.org/model">
<name>OHIE TEST Domain A</name>
<domainName>TEST_A</domainName>
<oid>2.16.840.1.113883.3.72.5.9.2</oid>
<url>http://ohie.org/test/test_a</url>
Test harness (as TEST_HARNESS_A) sends ADT^A01 registering a new patient with an identifier from TEST_A domain.
Receiver Accepts Message with an AA
MSH-5 and MSH-6 matches TEST_HARNESS_A|TEST
Response is ACK^A01
Response version is 2.3.1
Test harness (as TEST_HARNESS_B) attempts to send an ADT^A01 for authority A.
Receiver rejects the message with an AE or AR
An MSA message exists with an appropriate error code
MSH-5 and MSH-6 matches TEST_HARNESS_B|TEST
Response is ACK^A01
Response Version is 2.3.1



Version 3.0 of the SanteDB iCDR, dCDR and related solutions (SanteGuard and SanteMPI) represent a large series of changes from the 2.2x series. Some of the changes have been incorporated from our Version 3 Roadmap.
The larges and perhaps most impactful change in the version 3.0 is a complete refactoring of the entire persistence layer in SanteDB. This refactoring has allowed the SanteDB 3.0 version not only to use the database much more efficiently, but allows callers on the REST APIs to exert more control over how data is loaded.
The new persistence layer interfaces which load data to/from a data source now return an instance of IQueryResultSet. This is a delay expanded IEnumerable. Whenever a sort is applied, or a key is selected a new instance of IQueryResultSet is wrapped around the original. The database command is only executed when data is read from the reader. This also cleans up the calling structure, for example, in version 2.0 to determine if a record exists or to select a single field:
This pattern forced the persistence layer to load the object just to determine a detection.
In the new pattern this is now alleviated with IQueryResultSet:
Callers may also instruct to the data persistence layer the type of load strategy to be used when loading data from the database depending on the intended use of the data.
Data load strategies are:
QuickLoad - Load only core properties, no related entities
SyncLoad - Load only properties which are needed for synchronization
FullLoad - Load all properties directly from the data persistence layer
Loading stratgies are controlled by the DataPersistenceContext :
This method can also be used to control the way that data is deleted from the database.
3.0 introduces new persistence provider which have allowed us to harmonize the dCDR and iCDR persistence layers into a common framework. This means that the iCDR can be run on SQLite, or the dCDR can be run on PostgreSQL!
You can now customize the validation rules used to validate , , and Act Participations on the REST API. This makes it easier to create custom context-specific relationship types and enforce data persistence layer validation of those rules.
The OAUTH infrastructure has been refactored completed to better adhere to OpenID concepts. This refactoring includes:
Separation of the grant type into extendable implementations so users can create custom grant flows or override the SanteDB flows more readily
Separation of token serialization, and encoding allowing for more robust access and identity token passing
Implementation of standardized MFA secret generation using time and hash based one time passwords.
The interfaces which differentiated the iCDR and dCDR have now been combined into a common platform. This completes the refactoring of Portable Class Library code to a common code base. This means that any iCDR code can run (theoretically) in a dCDR or vice versa. It also means that iCDRs can be synchronized with other iCDR instances.
The BI layer has been refactored to include a new feature allowing applets to define . A data mart is a new database (separate from the primary database) which has de-normalized data which can be used for integrating with SanteDB for reporting purposes at the database layer. Uses for data marts include:
Exposing a simpler set of tables for third party reporting tools to consume (such as PowerBI, Jasper, or Tableau)
Isolating BI reports from the primary database allowing for better load balancing on the data infrastructure in SanteDB
Producing regular snapshots of your primary database over time.
BI data marts define a target schema, and data flows to populate that schema witin your applets and are applied on the dCDR and iCDR in the same manner (whether you're using PostgreSQL or SQLite).
Previous versions of SanteDB required system administrators to configure the rules in the primary configuration file. SanteDB 3.0 includes a new function which allows for the export, import and synchornization of data quality rules in the user interface. For more information see: .
Previously SanteDB v1.0, and v2.0 required CDSS rules to be written in an XML grammar and to place those into applet files. This process was tedious and meant that adding new CDSS rules was difficult for end-users and administrators. SanteDB 3.0 enhances this by:
Providing an administrative UI for creating CDSS rules (see: )
Providing a new text-based CDSS grammar that is easier for clinical analysts to write (see: )
REST operations to execute CDSS rules against HDSI objects
SanteDB v1.0 and v2.0 required importing of concept terminologies via console tooling which was cumbersome and difficult to write. SanteDB 3.0 introduces a new concept dictionary management tooling in the administration panel (see: ) and includes the ability to bulk create reference terminologies and concept sets via CSV uploads.
SanteDB v1.0 and v2.0 used to import data between projects and servers, however creation of these files was cumbersome and required manual editing of XML bundles. SanteDB v3.0 now allows export of any result set directly to a dataset file via the $export operation. Additionally, many of the user interfaces in the administrative panel allow for the export of data directly into a dataset from the UI.
It is now possible in SanteDB 3.0 to map any credential (user, application or device) with one or more certificates for either data signatures or authentication. This greatly streamlines the administration of PKI certificates in the SanteDB solution (see: )
SanteDB 3.0's HDSI parsing routines have been completely refactored, and allow for many enhanced queries, including:
Complex guard expressions, for example:
A Consumable relationship with at least 2 doses: participation[relationshipType.mnemonic=Consumable&quantity=>2].player=XXXXX
Either next of kin or any family member: relationship[NextOfKin|relationshipType.conceptSet.mnemonic=FamilyMember].target.name.component.value=Bob
In Version 2.x, the dCDR, while similar in function to the iCDR, was a completely different codebase. Along with harmonizing of the data layer, the SanteSuite team has also harmonized the entire service layer of the dCDR. This means, for example, that the administration console can be connected to a dCDR instance, or, for example, that the web interface can be run directly on the iCDR (we still recommend separating these concerns between iCDR and dCDR). This improvement means it is much easier to write plugins in C# or other .NET technologies.
SanteDB 3.0 introduces a new feature for , which allow developers to specify a simple transform which ingests data from an external file format (CSV, XLS, etc.) and translates data from that external file format into the RIM for import.
The administration panel also includes a UI for to allow administrators to use their UI to import. See:
The administration panel now supports a variety of improvements which make the administration of Places, Facilities, Organizations, and Materials much easier. These improvements allow an adminsitrator to:
Define a political division hierarchy (which can then be used for structured address inputs)
Define facility hierarchy, services, schedules, etc.
Define material classification types, manufacturers, etc.
Whereas version 2.x only permitted a single identity domain scope and assigner to be allocated to an identity domain, version 3.x allow administrators to specify multiple. Additionally, it is now possible for an administrator to configure whether information from a particular application is authoritative in nature or informative for a particular identity domain.
The development of applets has been greatly improved with the new SanteDB.DevTools package. This plugin allows the iCDR to act like the applet debugger in the v2 iCDR. Meaning that you can edit BI reports, business rules, etc. directly in Visual Studio Code and your iCDR instance will load them in real time. We have also added options to the package manager to inspect created packages, making it easier to debug and diagnose packaging issues.
The Conceptual Act Data Dictionary expressed in ADO.NET tables.
Physical Table
Conceptual Entity
Description
act_tbl
This table is used to store the non-versioned aspects of an act. These are things that are not supposed to change over the lifespan of an act
act_vrsn_tbl
This table is used to store the versioned portions of an act. The version sequence column should be a sequence which increments for each tuple (at minimum) or each new version of an object (best option)
The expressed in ADO.NET tables.
Patient Identity Feed – Auto-fill CX.4 data
This test validates that the Client Registry is capable of populating the CX.4.1 from CX.4.2 and CX.4.3 or vice-versa given partial data in the CX.4 field. If configured to allow auto-resolution, then the authority of a message missing CX.4 should be assigned.
The primary basis for this test case is based in the nots for implementing ITI-8 (Patient Identity Feed) from the , specifically section 3.8.4.1.3:
The SanteDB iCDR, dCDR and its related components are designed in a modular fashion. These modules are intended to maximize code reuse, and provide consistent services across the iCDR and dCDR environments.
The overall architecture of the SanteDB iCDR and dCDR repositories illustrated below along with some of the service classifications.
> application.add TEST_HARNESS_A -s TEST_HARNESS
> device.add TEST_HARNESS_A|TEST -s TEST_HARNESS
> aa.add -n TEST_A -o 2.16.840.1.113883.3.72.5.9.2 -u http://ohie.org/test/test_a -d 'OpenHIE Test Domain A' -a TEST_HARNESS_A
> application.add TEST_HARNESS_B -s TEST_HARNESS
> device.add TEST_HARNESS_B|TEST -s TEST_HARNESS
> aa.add -n TEST_B -o 2.16.840.1.113883.3.72.5.9.3 -u http://ohie.org/test/test_b -d 'OpenHIE Test Domain B' -a TEST_HARNESS_BMSH|^~\&|TEST_HARNESS_A^^|TEST^^|CR1^^|MOH_CAAT^^|20141104174451||ADT^A01^ADT_A01|TEST-CR-04-20|P|2.3.1
EVN||20101020
PID|||RJ-439^^^TEST_A||JONES^JENNIFER^^^^^L|SMITH^^^^^^L|19840125|F|||123 Main Street West ^^NEWARK^NJ^30293||^PRN^PH^^^409^30495||||||
PV1||IMSH|^~\&|TEST_HARNESS_B^^|TEST^^|CR1^^|MOH_CAAT^^|20141104174451||ADT^A01^ADT_A01|TEST-CR-04-30|P|2.3.1
EVN||20101020
PID|||NFD-3049542-23^^^TEST_A||JONES^JENNIFER^^^^^L|SMITH^^^^^^L|19840125|F|||123 Main Street West ^^NEWARK^NJ^30293||^PRN^PH^^^409^30495||||||
PV1||I







URI friendly operators: eq, ne, gt, gte, lt, lte, ap
Multi-path OR semantics (rather than the default AND semants) - Example: Patient name or Mother's name: name.component.value||relationship[Mother].name.component.value=Maria
ent_addr_cmp_tbl
This table is used to store entity address components. In order to normalize addresses, the values of the addresses themselves are not stored in this table, rather, stored in a unique datatable.
ent_addr_cmp_val_tbl
N/A
This table stores the unique values of all address components found in the SanteDB system.
ent_addr_tbl
Stores information related to an entity’s physical, mailing or other postal addresses
ent_ext_tbl
Stores the data related to entity extensions. Entity extensions are versioned, additional values for a particular entity.
ent_id_tbl
The entity identifier table is used to store alternate, external identifiers associated with a particular entity
ent_name_cmp_tbl
The entity name component table is used to store the individual components (family, given, prefix, suffix) of an entity’s name.
ent_name_tbl
The entity name table is used to store the names associated with a particular entity. For example, a patient may have a married and maiden name.
ent_note_tbl
The entity note table is used to store freetext notes about a patient.
ent_rel_tbl
Entity relationships are relationships between one or more entities with one another. For example, a service delivery location may have one or more employees.
ent_tag_tbl
Entity tags are non-versioned extensions of an entity. That is their value can change however changes are not tracked over time.
ent_tbl
Represents a non-versioned parts of the core entity such as class, determiner, etc.
ent_tel_tbl
Stores telecommunications addresses related to the entity and their associated type (phone, email, etc) and use (work, home, mobile, etc.)
ent_vrsn_tbl
This table is used to store the data which can change over time for an entity such as status, additional classifier, etc.
mat_tbl
This table is used to store information related to materials.
mmat_tbl
This table is used to store information related to manufactured materials.
org_tbl
This table is used to store information related to organizations, which are groupings of people, places for administrative purposes.
pat_tbl
This table is used to store information related to patients, or those who are receiving care.
plc_svc_tbl
This table is used to store information related to the services which occur at a particular place.
plc_tbl
This table is used to store information about a physical place. In Open IZ places can represent delivery locations (hospitals, clinics, etc.) or administrative units (states, cities, etc.)
psn_lng_tbl
This table is used to store information related to the languages which a person (including patients) speak.
psn_tbl
This table is used to store information related to persons (including patients and providers).
pvdr_tbl
This table is used to store information related to providers (persons who deliver care).
usr_ent_tbl
This table is used to link the security subsystem for users to the clinical subsystem of entities (as entities are the ones who participate in Acts rather than Security Users).
Physical Table
Conceptual Entity
Description
app_ent_tbl
This table is used to describe the clinical attributes of an application such as vendor, version etc. This differs from the security definition of an application. A security application may exist without a clinical application existing.
dev_ent_tbl
This table is used to describe the clinical attributes of a device. For example an insulin pump. Like an application, a clinical device may not be a security device or vice versa. For example when describing an event in which a device was involved , but that device does not need access to the system.
The cases which are tested in this test are:
The client registry can cross reference PID-3-4-1 with PID-3-4-2 and PID-3-4-3 data
Conversely, the client registry can cross reference PID-3-4-2 and PID-3-4-3 with PID-3-4-1
The client registry, when configured, can auto-resolve PID-3-4 when it is missing.
Prior to executing this test, SanteMPI instances should configure:
The TEST_HARNESS application
The TEST_HARNESS|TEST device
The TEST identity domain is created and the authority to assign is set to TEST_HARNESS
The SanteMPI instance is configured such that strictCx4 is disabled
<dataset id="Test Domain" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://santedb.org/data">
<insert skipIfError="false" skipIfExists="true">
<SecurityApplication xmlns="http://santedb.org/model">
<id>F0FC4322-948D-4986-A06C-DA603A77EDDE</id>
<!-- Secret: TEST_HARNESS -->
<applicationSecret>b5547020757c0efa3f320fbd2a0c43d0628e19b8cd81652523b87d31fc54f5ec</applicationSecret>
<name>TEST_HARNESS</name>
</SecurityApplication>
</insert>
<insert skipIfError="false" skipIfExists="true">
<SecurityDevice xmlns="http://santedb.org/model">
<id>508d9d71-54a3-4d67-897a-e2a395961395</id>
<!-- Secret: TEST_HARNESS -->
<deviceSecret>b5547020757c0efa3f320fbd2a0c43d0628e19b8cd81652523b87d31fc54f5ec</deviceSecret>
<name>TEST_HARNESS|TEST</name>
Test harness sends ADT^A01 message where the CX.4.1 of the PID is missing but the message contains CX.4.2 and CX.4.3. The client registry should use the information in the registration of the authority to fill the other components on the validation step of this test.
Receiver Accepts Message with an AA
Response is ACK^A01
Response is version 2.3.1
MSH-5 and MSH-6 matches TEST_HARNESS|TEST
Test harness ensures that patient was registered and receiver has populated CX.4.1 from the CX.4.2 and CX.4.3 values executing.
Receiver Accepts message with an AA
Response is RSP^K23
Response message contains exactly one PID segment
PID-3 of PID segment contains an identifier having:
PID.3.4.1 = TEST
PID.3.4.2 = 2.16.840.1.113883.3.72.5.9.1
PID.3.4.3 = ISO
Test harness sends ADT^A01 message where the CX.4.2 and CX.4.3 of the PID are missing but the message contains CX.4.1
Receiver Accepts Message with an AA
MSH-5 and MSH-6 matches TEST_HARNESS|TEST
Test harness ensures patient was registered and receiver has populated CX.4.2 and CX.4.3 from the CX.4.1 value provided by executing:
Receiver Accepts message with an AA
Response message contains exactly one PID segment
PID-3 of PID segment contains an identifier having:
PID.3.4.1 = TEST
PID.3.4.2 = 2.16.840.1.113883.3.72.5.9.1
PID.3.4.3 = ISO
The test harness sends a patient registration request with no CX.4 populated. Since TEST_HARNESS|TEST is configured to be the only assigner of TEST the client registry must fill the missing components of CX.4.
Receiver accepts message with an AA
MSH-5 and MSH-6 contain TEST_HARNESS|TEST
Test harness ensures that the patient was registered on client registry an CX.4 is populated based on the sender.
Receiver Accepts message with an AA
Response message contains exactly one PID segment
PID-3 of PID segment contains an identifier having:
PID.3.4.1 = TEST
PID.3.4.2 = 2.16.840.1.113883.3.72.5.9.1
PID.3.4.3 = ISO
There are two methods of using services in SanteDB:
Service Locator Pattern (https://en.wikipedia.org/wiki/Service_locator_pattern) - Whereby service instances are located at runtime
Dependency Injection Pattern (https://en.wikipedia.org/wiki/Dependency_injection) - Whereby services instances are injected into the class when constructed.
SanteDB classically used the service locator pattern via the IServiceProvider instance called the ApplicationContext. The application context is responsible for loading the appropriate implementation (or provider) of a particular strategy (or contract) based on the configuration of the environment.
Take, for example, the auditing which is implemented as:
Here, the SecretClass instance relies on the contract IRepositoryService, which may be implemented by an ADO.NET implementation, an RFC3881 implementation and a FHIR implementation. At runtime, when SecretClass wishes to send an audit, it will call the ApplicationServiceContext instance, which will return an appropriate implementation based on the runtime environment.
This means that the implementer of SecretClass doesn't need to worry about which audit service is being used, it merely executes the business function for auditing.
This service pattern, and the fact the solution is implemented in .NET Standard, means that most service implementations can be used in the iCDR and dCDR environments without re-compiling.
Services can also use dependency injection pattern. In this pattern, the service's constructor defines the dependent services which are required for the service implementation to function. The ApplicationContext will inject the current service implementations into the instance on construction.
SanteDB's overall architecture is really a composition of services which have been configured by the developer of the SanteDB solution. For example, SanteMPI may have a different series of services configured to act as an MPI whereas SanteIMS will have different services configured to behave as an EIR (however the two would share services).
Most SanteDB services are implemented assuming a service relationship as illustrated below:
Messaging services represent the primary presentation layer for SanteDB. These services are responsible for:
Handling transport layer security (authentication of clients, tokens, decrypting network traffic, etc.)
Translating messages from a wire-level format (like HL7, FHIR, GS1) into the common information model (RIM)
Performing auditing based on the requirements of the transport standard
Translating responses into appropriate behaviors (like a NACK in HL7v2 or a 422 in HTTP)
The auditing services in SanteDB are responsible for facilitating the audit process. This process in SanteDB includes:
Storing a local copy of the audit information within the SanteDB service (this is really a repository service)
Shipping appropriate audits to centralized infrastructure as required
In SanteDB, the repository service layer is responsible for the "behaviors", or the coordination activities to accomplish a particular task. Repository services:
Ensure that the appropriate authentication context is established and used / shared
Use the policy enforcement mechanism to demand appropriate permission to perform an action
Call necessary business rule triggers for the action being executed
Raise pre/post events which event listeners may use to perform extended behaviors (for example, the MDM layer is implemented in this manner)
Interacting with the data persistence services to store/read data
Messaging services primarily interact with repository services as these services are responsible for abstracting the individual data layer calls.
The policy services in SanteDB consist of:
Policy Information Service - Which stores information about security and data policies in SanteDB such as whether the policy can be overridden, and its place in the policy hierarchy.
Policy Decision Service - Which determines appropriate access decisions (GRANT, ELEVATE, DENY) given a securable (the thing which is being done or acted on) and the principal (the user, app, and device being used).
Policy Enforcement Service - Which takes appropriate actions based on the outcome of the policy decision made. This might be masking data, throwing an exception, etc.
Business rule services are specialized interfaces which can be chained together and act on data before and after a repository service actions it. Business rule services are user defined behaviors and have the ability to:
Validate an object before it is acted on
Modify an object prior to an action (insert, update, etc.) being performed
Call other services (like notifying another system, etc.)
Modify and/or manipulate an object prior to the object being returned to the caller of the repository action (after persisted but before returning).
The data persistence services are typically the "last place" where services in SanteDB can interact with data. Unless services require direct access to the underlying storage technology, all interactions occur via these services. Data persistence services are responsible for:
Translating object to and from the information model into appropriate storage models (SQL tablets, FHIR objects, etc.)
Transactional control of the underlying storage technology (commit, rollback, etc.)
Managing and interacting with the caching services to reduce load on the persistence technology
The caching services are responsible for providing rapid access to cached objects, these services (like REDIS or Memory Caching) reduce load on the persistence layer as they typically provide rapid, non-relational access to models in the information object.
The object-relational-model providers are specialized classes which are used (optionally) by services which must directly interact with database software, however require abstraction on the persistence technology. ORM providers which exist in SanteDB include: PostgreSQL, Firebird, and SQLite, and are responsible for:
Translating object/relational LINQ queries into appropriate SQL syntax for the storage technology
Mapping logical keywords and operators to physical operators in SQL (for example: .Contains() becomes ILIKE in PostgreSQL but LIKE in Firebird)
Committing and rolling back transactions with the database provider
Constructing dynamic SQL operations for result sets for order, count, etc.
The BI services in SanteDB are responsible for interacting with the ORM providers to execute business intelligence assets (queries, views, parameters, reports, etc.) directly with the various connected SQL databases for the service.
Synchronization services are responsible for integrating the SanteDB iCDR and dCDR with upstream services. These services:
Manage the inbound/outbound and dead letter queues for synchronizations
Interact with the persistence layer (bypassing business rules which may already be executed) directly
Manage the retry and conflict resolution notifications process
SanteDB contains hundreds of service contracts for various system tasks which are not covered at a high level on this page. These services can be found on the Service Definitions page.
act_id_tbl
This is an associative table which is used to store identifiers by which an act is referenced externally.
act_ext_tbl
Extensions table.
act_proto_tbl
Act Protocols
Act protocol implementation table.
act_ptcpt_tbl
Act participation table (links acts to entities)
act_tag
Act tags table
act_ext_tbl
Act extensions table (value should be a binary array or BLOB)
act_note_tbl
Act notes
act_pol_assoc_tbl
Act Policies
Policies which apply to the act.
act_rel_tbl
Relationships table. Note that effective/obsolete sequence columns refer to the source act.
sub_adm_tbl
Substance administration child table which is linked directly to the act table.
obs_tbl
Observation child table which is linked to the act table.
qty_obs_tbl
Quantity Observation table which is linked with the observation table.
txt_obs_tbl
Text observations table which is linked with the observation table.
cd_obs_tbl
Coded observations table which is linked to the observation table.
pat_enc_tbl
Patient encounters table which is linked to the act table.
proc_tbl
Procedures tablet which is linked to the act table.
In SanteDB, the physical model is used to express the concrete tables which are created in a SQL based RDBMS to store data on a physical media (disk). Implementers of new SQL based persistence services should try to re-use these mappings in their expression to the physical model.
SanteDB uses the ORM Lite data mapping technology, and the SanteDB.Persistence.Data.Ado assembly contains the ORM lite physical model classes.
SanteDB includes an implementation of a persistence layer which includes support for generic ADO based databases. This provider uses the ADO.NET wrapper to invoke necessary functions and select data from tables. In order to leverage the ADO.NET persistence service, the ADO.NET provider must support:
SQL92 syntax
Limit and offset queries in the form of SELECT FOO FROM BAR OFFSET x LIMIT y
Invoke of Stored Procedures and Functions or equivalent C# logic which implements the functions
Currently SanteDB iCDR works with the following OrmLite data providers:
Regardless of the RDBMS system feeding the ADO provider, it must follow the schema specified in this section.
To implement a new ADO.NET based data provider, implementers will need to:
Write an ORM Lite IDbProvider instance (see an example of the )
Write an ORM Lite IDbConfigurationProvider instance (see an example of the )
The DDL and DML classes for the most recent SanteDB physical model (see an example of the )
See: article for information on patching SQL structures.
The physical schema of the ADO provider is designed such that many different ADO providers can support the data structures. Because of the limitations on some RDBMS systems, the ADO schema uses a short-hand for table names.
The following suffixes are placed on entities in the schema:
Most tables in the SanteDB physical model carry common abbreviations of names. Because of the varied contributors some tables break these rules, however the general principal applies:
Names less than four characters should be represented in full (example: NAME or TAG)
Names which represent a classified object carry their classification, for example:
OBS_TBL => Observation Table
Tables which represent an inheritance are created as discrete tables. Each class in the hierarchy maps to one table in the schema and contain only the attributes of the class.
As an example:
In the database schema this inheritance structure is represented as:
On persistence services which provide versioning (such as those in the iCDR) the tables can be split into two categories:
Versioned Tables -> Acts, Entities and Concepts which track changes to data over time.
Non-Versioned Tables -> Any other class which does not track changes over time.
Because version data is required for interfaces in the iCDR the structures are broken into a primary table and a versioning table, where:
Primary Table: Contains the unchanging attributes of the object
Version Table: Contains the attributes which may be changed on the object. This table contains:
Sequence Identification (used for tracking the order of versions)
For example, ENT_TBL and ENT_VRSN_TBL are related in this manner:
Tables which are associated with a versioned entity should be linked to the primary key of the non-versioned portion of the data, and carry an Effective Version Seq and an Obsolete Version Seq. For example, identifiers for an entity:
When installing SanteDB iCDR server on Linux or Unix based environment you should use the tarballs for the latest version of the SanteDB iCDR server. Each solution within SanteDB iCDR Server has its own distribution which can be downloaded for their own source repository.
The installation process for SanteDB on Linux is the same process as installation on Windows::
Install the software
Copy software program files and pre-requisites
Initiate the configuration process
Configuration of the software
The tarballs provided have been written for and test on Debian based distributions, manual installation for non-Debian based distributions is required.
When running SanteDB iCDR server on Unix based operating systems you will require, at minimum:
One of the following Unix operating systems:
MacOS X 10.9 on M1 or x86 (manual installation)
Ubuntu 16.04 or later (install script)
Debian 9 or later (install script)
Users should be familiar with basic Unix concepts such as:
Un-taring archive files
Basic familiarity with Unix commands
To install the SanteDB iCDR 2.1.140 or higher via the installation script provided, you should first extract the tarball contents:
This will extract the software to the ./santedb-server-2.1.140 directory. You can enter that directory and run the install.sh script:
If you are not running the script as root, the installer will prompt if you would like it to use SUDO. The script will then detect pre-requisites for mono and postgresql. The install script will install mono for you.
Finally, you'll be prompted for an installation target, the default location is /opt/santesuite/santedb/server/, you can accept the default or change the location of installation to suit your policy.
After installation is complete, the default SanteDB publisher certificates will be registered with the Mono trust store and you'll be provided the option to setup SanteDB as a daemon.
When installing the SanteDB iCDR server manually, administrators should ensure that the pre-requisites for SanteDB are installed on their preferred Unix environment:
Once installed, users should create their target installation directory (this tutorial will use /opt/santedb , and should unzip the tarball or zip file to that location.
You then need to install the SanteDB publisher certificates into the Mono certificate store:
Finally, you can run the configuration tool in your installation directory with
You can register SanteDB as a daemon on your distribution of Linux by creating a service definition file. This is done by creating a new file at /etc/systemd/system/santedb.service and using the contents:
After this time you can run systemctl reload-daemons to load your service definition.
SanteDB's configuration tool on linux uses the Mono to GTK+ WinForms implementation. The application is the same application as documented in the documentation.
Details on the initial configuration of SanteDB can be followed from the guide.
Like the Windows installation, the SanteDB, the SanteDB iCDR on Linux needs to be initialized, unlike windows this requires manual stop/start of the service.
If you've installed SanteDB as a daemon the command to stop or start the daemon is:
If you are running SanteDB on a console, you can run:
Once started you can validate connectivity to the SanteDB iCDR server running the SanteDB Administration Console. The Administration console is executed using:
Once the login prompt is available you can login with Administrator and password Mohawk123.
If the option to install the SanteDB iCDR as a Linux daemon was selected during install, then the service can be controlled with systemctl for example:
Stopping the service is done with the same command:
The service can be enabled on startup using:








The figure below illustrates how a remote client can obtain a token from a federated security token service (STS) representing an IPrincipal and pass it to the SanteDB HDS. The creation of a local IPrincipal is controlled by a local IIdentityProviderService implementation. It is imperative that the ACS generate a token format which is suitable for the HDS messaging interface to consume (i.e. the configurations match), otherwise the HDS will have no mechanism for verifying tokens.
Any ACS service can be used with SanteDB, however it is recommended that the ACS being used support the OAuth token service’s password grant and provide client/device authentication via TLS and/or HTTP basic auth.
var exists = persistence.Find(o=>o.UserName == "BOB", 0, 1, AuthenticationContext.SystemPrincipal).Any();
// Executed SQL:
// SELECT * FROM SEC_USR_TBL WHERE USR_NAME = 'BOB' OFFSET 0 LIMIT 1;
var key = persistence.Find(o=>o.UserName == "BOB", 0, 1, AuthenticationContext.SystemPrincipal).FirstOrDefault(o=>o.Key);
// Executed SQL:
// SELECT * FROM SEC_USR_TBL WHERE USR_NAME = 'BOB' OFFSET 0 LIMIT 1;var resultSet = persistence.Find(o=>o.UserName == "BOB", AuthenticationContext.SystemPrincipal);
// No SQL is executed
var exists = resultSet.Any();
// SQL Executed:
// SELECT EXISTS 1 FROM SEC_USR_TBL WHERE USR_NAME = "BOB";
var key = resultSet.Select(o=>o.Key).FirstOrDefault();
// SQL Executed:
// SELECT SEC_USR_ID FROM SEC_USR_TBL WHERE USR_NAME = "BOB" LIMIT 1;using(DataPersistenceContext.Create(LoadStrategy.QuickLoad)) {
// Any data events here will only load core properties#
}> application.add TEST_HARNESS -s TEST_HARNESS
> device.add TEST_HARNESS|TEST -s TEST_HARNESS
> application.info TEST_HARNESS
> aa.add -n TEST -o 2.16.840.1.113883.3.72.5.9.1 -u http://ohie.org/test/test -d 'OpenHIE Test Domain' -a TEST_HARNESS MSH|^~\&|TEST_HARNESS|TEST|CR1|MOH_CAAT|20141104174451||ADT^A01^ADT_A01|TEST-CR-02-10|P|2.3.1
EVN||20101020
PID|||RJ-438^^^&2.16.840.1.113883.3.72.5.9.1&ISO||JOHNSTON^ROBERT^^^^^L|MURRAY^^^^^^L|19830205|M|||1220 Centennial Farm Road^^ELLIOTT^IA^51532||^PRN^PH^^^712^7670867||||||481-27-4185
PV1||IMSH|^~\&|TEST_HARNESS|TEST|CR1|MOH_CAAT|20090223144546||QBP^Q23^QBP_Q21|TEST-CR-02-20|P|2.5
QPD|IHE PIX Query|Q0220|RJ-438^^^&2.16.840.1.113883.3.72.5.9.1&ISO^PI
RCP|IMSH|^~\&|TEST_HARNESS|TEST|CR1|MOH_CAAT|20141104174451||ADT^A01^ADT_A01|TEST-CR-02-30|P|2.3.1
EVN||20101020
PID|||RJ-439^^^TEST||JONES^JENNIFER^^^^^L|SMITH^^^^^^L|19840125|F|||123 Main Street West ^^NEWARK^NJ^30293||^PRN^PH^^^409^30495||||||
PV1||IMSH|^~\&|TEST_HARNESS|TEST|CR1|MOH_CAAT|20090223144546||QBP^Q23^QBP_Q21|TEST-CR-02-40|P|2.5
QPD|IHE PIX Query|Q0220|RJ-439^^^TEST^PI
RCP|IMSH|^~\&|TEST_HARNESS|TEST|CR1|MOH_CAAT|20141104174451||ADT^A01^ADT_A01|TEST-CR-02-30|P|2.3.1
EVN||20101020
PID|||RJ-499^^^TEST||JONES^ROBERT^^^^^L|BUKOWSKI^^^^^^L|19390125|F|||123 Main Street East^^NEWARK^NJ^30293||^PRN^PH^^^409^0394938||||||
PV1||IMSH|^~\&|TEST_HARNESS|TEST|CR1|MOH_CAAT|20090223144546||QBP^Q23^QBP_Q21|TEST-CR-02-40|P|2.5
QPD|IHE PIX Query|Q0220|RJ-499^^^TEST^PI
RCP|I





You should include these as embedded resources in your plugin
You should include all updates , translated to your SQL dialect as well
You should include your own provider's invariant in the header
Implementations of any supported extended functions (such as SOUNDEX, LEVENSHTEIN, etc.) as IDbFilterFunction implementations (see an example FirebirdSQL String Matching Functions)
PATCH_DB_SYSTBL
SUB_ADM_TBL => Substance Administration Table
Association tables which exist only to link together two other tables should have ASSOC in their name
Longer table names are usually acronyms:
CD_TBL => Concept Definition Table
CS_TBL => Code System Table
Table and columns should remove vowels where the removal of vowels do no interfere with understanding the meaning of the column or table:
ENT_TBL => Entity Table
CLS_CD_ID => Class Concept Definition ID
Obsolete time and provenance (who rendered this version obsolete)
Replaced version id (the version that this version replaces)
Database System
Invariant
PostgreSQL 9.4 – 10.0
npgsql
FirebirdSQL 3.0
FirebirdSQL
SQLite 3.3
Sqlite
Suffix
Used For
Example
_TBL
Tables
ENT_VRSN_TBL
_VW
Views
ENT_CUR_VRSN_VW
_CDTBL
Code Lookup Tables
ENT_REL_CLS_CDTBL
_SYSTBL
Internal System Tables
// Entity
public class Entity
{
}
// Person IS A Entity
public class Person : Entity
{
}
// Patient IS A Person
public class Patient : Person
{
}CREATE TABLE ENT_TBL
(
ENT_ID UUID NOT NULL,
...
CONSTRAINT PK_ENT_TBL PRIMARY KEY (ENT_ID)
);
-- PERSON IS A ENTITY
CREATE TABLE PSN_TBL
(
ENT_ID UUID NOT NULL,
...
CONSTRAINT PK_PSN_TBL PRIMARY KEY (ENT_ID)
CONSTRAINT FK_PSN_ENT_TBL FOREIGN KEY (ENT_ID) REFERENCES ENT_TBL(ENT_ID)
);
-- PATIENT IS A PERSON
CREATE TABLE PAT_TBL
(
ENT_ID UUID NOT NULL,
...
CONSTRAINT PK_PAT_TBL PRIMARY KEY (ENT_ID)
CONSTRAINT FK_PAT_PSN_TBL FOREIGN KEY (ENT_ID) REFERENCES PSN_TBL(ENT_ID)
);
CREATE TABLE ENT_TBL (
ENT_ID UUID NOT NULL,
-- NON-VERSIONED PROPERTIES
CONSTRIANT PK_ENT_TBL PRIMARY KEY (ENT_ID)
);
-- ENTITY VERSION TABLE
CREATE TABLE ENT_VRSN_TBL (
ENT_VRSN_ID UUID NOT NULL,
VRSN_SEQ_ID BIGINT NOT NULL, -- THE VERSION SEQUENCEING IDENTIFIER
ENT_ID UUID NOT NULL, -- THE ENTITY THIS VERSION APPLIES TO
CRT_UTC TIMESTAMP NOT NULL, -- THE TIME THE VERSION WAS CREATED
CRT_PROV_ID UUID NOT NULL, -- THE PROVENANCE THAT CREATED THIS
OBSLT_UTC TIMESTAMP, -- THE TIME THE VERSION IS NO LONGER VALID
OBSLT_PROV_ID UUID, -- THE PROVENANCE OF WHAT OBSOLETED THIS
RPLC_VRSN_ID UUID, -- THE REPLACED VERSION
... -- VERSIONED DATA FIELDS
CONSTRAINT PK_ENT_VRSN_TBL PRIMARY KEY (ENT_VRSN_ID),
CONSTRAINT FK_ENT_VRSN_ENT_TBL FOREIGN KEY (ENT_ID) REFERENCES ENT_TBL(ENT_ID),
CONSTRAINT FK_ENT_VRSN_RPLC FOREIGN KEY (RPLC_VRSN_ID) REFERENCE ENT_VRSN_TBL(ENT_VRSN_ID)
);
CREATE UNIQUE INDEX ENT_VRSN_SEQ_UQ_IDX ON ENT_VRSN_TBL(VRSN_SEQ_ID);-- ENTITY IDENTIFIER
CREATE TABLE ENT_ID_TBL (
ENT_ID_ID UUID NOT NULL, -- SURROGATE PRIMARY KEY
ENT_ID UUID NOT NULL, -- THE ENTITY TO WHICH THIS IDENTIFIER IS RELATED
EFFT_VRSN_SEQ_ID BIGINT NOT NULL, -- THE VERSION OF THE ENTITY WHERE THIS ID WAS VALID
OBSLT_VRSN_SEQ_ID BIGINT, -- THE VERSION OF THE ENTITY WHERE THIS ID IS NO LONGER VALID
... -- DATA FIELDS
CONSTRAINT PK_ENT_ID_TBL PRIMARY KEY (ENT_ID_ID),
CONSTRAINT FK_ENT_ID_ENT_TBL FOREIGN KEY (ENT_ID) REFERENCES ENT_TBL(ENT_ID),
CONSTRAINT FK_ENT_ID_EFFT_VRSN_TBL FOREIGN KEY (EFFT_VRSN_SEQ_ID) REFERENCES ENT_VRSN_TBL(VRSN_SEQ_ID),
CONSTRAINT FK_ENT_ID_OBSLT_VRSN_TBL FOREIGN KEY (OBSLT_VRSN_SEQ_ID) REFERENCES ENT_VRSN_TBL(VRSN_SEQ_ID)
) Customizing the behavior of the installed plugins
Entering implementation specific details about the deployment
Running/Initializing the Server
CentOS or RHEL 6 or better (manual installation)
2 Core CPU (4 to 8 Cores recommended)
2 GB RAM (8 or 16 GB of RAM recommended)
300 MB of disk space (1 GB recommended)
When a authentication request is made against the ACS, depending on the type of authentication request (see OpenID Connect) the ACS will call the identity providers to authenticate the identity information provided. The identity providers called are one of:
Application Identity Provider - Authenticates a single piece of software to establish an ApplicationIdentity which identifies the scope of grants permitted to the application identity.
Device Identity Provider - Authenticates the physical device (computer, server, phone, etc.) using either:
Node Based Authentication -> Like an X509 Client Certificate , or
Shared Secret Authentication -> Such as those generated by the secret generator (typically a signed, random 128 bit key)
Identity Provider - Which authenticates the human user which is attempting to establish an interactive session with the server.
The three identities (which are standalone principals in their own right) is then passed to the session provider service which establishes a principal as a combination of the three identities. The session principal contains:
The final list of grants (policies) that the session is permitted to access
The purpose of use, and elevation data (if applicable)
The expiration, establishment time
Depending on the configuration of the iCDR or dCDR the session identity is serialized as either a JSON Web Token (http://jwt.io) or a simple web token which consists of the session identifier and a digital signature (used to validate the session id is not tampered with or guessed).
An interactive session is established when a user enters their username, password and MFA secret. An interactive session will have three identities within the principal:
User Identity representing the authenticated user account
Application Identity representing the authenticated secure client the user used to obtain the session
Device Identity representing the authenticated secure node from which the user authenticated
A non-interactive session is established when a device or application authenticates without the intervention of a user. Non-interactive session may carry either an Application Identity and a Device Identity or simply an Application Identity.
Secrets for all objects in the SanteDB iCDR and dCDR (applications, devices, and users) are peppered.
A pepper is a secret value added to a password before hashing. It can be considered a second salt — another input to change the hash outcome completely. Yet, unlike a salt, it’s not stored in the database along with the hashes.
Whenever you generate a secret (like creating a device, resetting your password, etc.) in SanteDB the authentication architecture will grab a random series of password pepper characters and will add it to your secret, then hash it using the configured hasher, and store the result.
When you authenticate in SanteDB, all possible combinations of pepper are added to your entered credential and hashed, the SanteDB server then compares the peppered hashes with the stored hash to verify your login credentials.
Additionally, your password is re-peppered and re-hashed. This means that the password hashes in SanteDB's security tables change with each authentication.
The enforcement of privacy and policies is handled through a series of services within the SanteDB solution. From a high level, three different types of services are involved:
Policy Information Provider (PIP) - IPolicyInformationService – Is responsible for storing information related to the policies. The information point is responsible for maintaining a list of IPolicy objects which contain the name, oid, handler (C# class which is executed upon policy decision), and elevation control.
Policy Decision Provider (PDP) - IPolicyDecisionService – Is responsible for making a decision related to a policy (or series of policies) for a given securable. The decision outcome is one of the following options:
Deny – The principal has no authorization to access the requested securable or policy.
Elevate – The principal can access the securable or policy however they require additional authentication (such as 2nd level password, TFA, etc.)
Grant – The principal is granted access to the specified securable or policy.
Policy Enforcement Provider (PEP) - – Is responsible for listening to events from the SanteDB system and leveraging the decision and information points to enforce the policy decision. This implementation can vary between jurisdictions however by default involves either the masking (i.e. there is something here you can’t see), redaction (i.e. removal of information), or partial disclosure of records.
The process for enforcement is illustrated below.
SanteDB’s default policy decision service provider operates on a basis of most-restrictive with default DENY. In this evaluation scheme policy decisions are created as follows:
If the principal has no data associated with the policy, the result of the decision is DENY,
If the principal has one rule associated with the policy via role, device, or application then the result of the decision is the rule’s configuration,
If the principal has multiple rule instances configured via role, device or application then the result of the decision is the most restrictive option.
For example, if user jsmith is a member of USERS, CLINICAL and is accessing SanteDB from application ReaderApp.
Policy
From USERS
From CLINICAL
From ReaderApp
Effective Set
Access Administrative Function
DENY
Change Password
When installing SanteDB iCDR server on a Microsoft Windows Server environment you should use the installation package for the latest version of the SanteDB iCDR server. Each solution within SanteDB iCDR Server has its own distribution which can be downloaded for their own source repository.
The installation process for SanteDB on Microsoft Windows is a three step process:
Copy software program files and pre-requisites
Initiate the configuration process
Customizing the behavior of the installed plugins
Entering implementation specific details about the deployment
Running/Initializing the Server
When running SanteDB iCDR server on Microsoft Windows you will require, at minimum:
Microsoft Windows Server 2012 Standard or Microsoft Windows 10
2 Core CPU (4 to 8 Cores recommended)
2 GB RAM (8 or 16 GB of RAM recommended)
300 MB of disk space (1 GB recommended)
Users should be familiar with basic Microsoft Windows concepts such as:
Basic familiarity with the Windows Command Line
Basic familiarity with Microsoft Management Console (MMC)
Basic familiarity with Windows Networking
The installation programs on Windows will:
Install the Visual C++ 2010 redistributable (for C++ libraries)
Install Microsoft .NET Framework 4.8 (if not already installed)
Copies the required files for the selected options to the Installation
Opens Firewall port 8080 and 2100 (for HL7v2) on the Windows Firewall
The installation process is a standard Windows installer experience, administrators can elect to install particular plugins that meet their needs.
The plugins available at the time of writing are enumerated below.
The SanteDB Core option installs the core Windows Service executable (santedb.exe), as well as baseline files such as the API libraries, etc.
The JINT business rules engine allows applets to customize the iCDR and dCDR application behavior by writing .
If your installation of the iCDR will be (CDSS) via the built-in XML protocol format, you should enable CDSS support.
The messaging interfaces option installs the core REST APIs for the iCDR server. These messaging interfaces allow administrators to customize their deployment for scale-out by assigning servers to dedicated roles. For example, in a scaled-out solution an administrator may only install the to the server which controls the cluster, whereas other servers may only install the for clinical data access.
When installed, the SanteDB core business intelligence services for rendering and executing reports from applets will be enabled. The BIS should be installed on servers where you'd like the clients to be able to access shared report definitions.
If you're using a third party reporting tool like Jasper Reports, Crystal Reports, SQL Server Report Services, etc. you do not need to enable this.
Installation of the integration interfaces will allow SanteDB iCDR to interact with third party services using one of the standards based APIs such as:
JIRA Integration (which allow submission of Diagnostic reports from dCDR instances directly into JIRA)
Installation of a TFA provider allows the iCDR to leverage multi-factor authentication workflows using either E-Mail based TFA codes or SMS based TFA codes (via Twilio)
Installation of the MDM plugin copies the necessary plugins to enable the Master Data Management Resource Manager.
The data persistence plugins enable the one or more of the persistence services in SanteDB on the server. The persistence layer plugins supported are:
PostgreSQL Server Plugin
Firebird Plugin
You should install , at a minimum the Memory Caching service plugin to improve the performance of your installation. If you're running SanteDB in a shared environment with multiple servers in a cluster environment, installation of REDIS is recommended.
Installing the Elbonia Quickstart pack will seed your SanteDB instance with sample data from the fake jurisdiction (from Dilbert) of Elbonia.
Configuration of the SanteDB service is covered in a series of discrete wiki articles which cover each configuration option in the platform and their impact on the system.
Configuration of the SanteDB server should be done prior to the first start of the software. The option to start the configuration tool for SanteDB is provided at the end of the SanteDB installation process.
See:
When first configuring SanteDB iCDR server on a Windows environment you will need to select the database persistence technology the server will be using, the options are:
PostgreSQL 9+ : If you're running SanteDB with full functionality, select this option.
Firebird : If you're running SanteDB for a quick demonstration or test, select this option.
Selecting the PostgreSQL provider will expose the connection parameters for PostgreSQL. See for more information on these settings.
Selecting the Firebird provider will expose the connection parameter for Firebird 3.x provider, SanteDB iCDR will assume you're using the embedded version of Firebird. This database connector has three parameters. See connection details in the configuration tool documentation.
If you're running multiple instances of SanteDB on the same server, you will need to install the software in different file locations. When configuring the iCDR on the Windows host you can then set an instance name to isolate the Windows Services and event logs.
SanteDB iCDR server packages may be shipped with one ore more included, you should select an appropriate template for the software solution that this instance of the iCDR will fulfill.
Once you've completed the installation options for the SanteDB server and press Continue you will be prompted to confirm the initial configuration tasks.
You can use the configuration tooling to customize your installation of the SanteDB server. These settings are documented in
Recommended configuration panels and settings to change include:
Changing the Performance/Caching to REDIS caching and setting up REDIS
Turning down the Diagnostics/Logging setting to Warning or Error
After you have applied the configuration from the Configuration Tool, the SanteDB service will automatically restart.
Once started you can validate connectivity to the SanteDB iCDR server by accessing the Start menu and running SanteDB Server Console (localhost) . You should be prompted with a login prompt.
Once the login prompt is available you can login with Administrator and password Mohawk123.
SanteDB runs as a Windows service (equivalent of a daemon). These can be accessed using the services.msc plugin an finding the SanteDB Host Process service. Additionally the service can be restarted from an elevated command prompt using:
This tutorial will provide an overview of how to install and run the SanteDB iCDR MPI solution (SanteMPI) using Docker for a demonstration environment.
The SanteDB CDR requires that any data provided to it by callers conform to the logical information either in XML, JSON or ViewModel formats.
If you need to store data which cannot be captured in the primary information model you can add it with either an extension or a tag.
Extensions are versioned pieces of information which semantically change or modify the data structure, or capture complex data which changes over time. Extensions:
An operational technology architecture differs slightly from a software requirements specification or functional design specification for software. The operational technology architecture is primarily concerned with the operational environment in which SanteDB services will be running.
The documentation prepared for the operational architecture should aim to:
$ tar -xjvf santedb-server-2.1.140.tar.bz2$ cd santedb-server-2.1.140/
santedb-server-2.1.140 $ chmod +x install.sh
santedb-server-2.1.140 $ ./install.sh tar xjvf santedb-server-2.1.140.tar.bz2
mkdir -p /opt/santedb
mv santedb-server-2.1.140 /opt/santedb
cd /opt/santedbsudo mono SanteDB.exe --install-certssudo mono ConfigTool.exe[Unit]
Description=SanteDB iCDR Server
[Service]
Type=simple
RemainAfterExit=yes
ExecStart=/usr/bin/mono-service -d:$INSTALL_ROOT /opt/santesuite/santedb/server/SanteDB.exe --console
ExecStop=kill \`cat /tmp/SanteDB.exe.lock\`
[Install]
WantedBy=multi-user.targetsystemctl stop santedbmono /opt/santesuite/santedb/server/SanteDB.exe --consolemono /opt/santesuite/santedb/server/sdbac.exeSanteDB Administration & Security Console v2.1.131.0 (Queenston)
Copyright (C) 2015 - 2020, SanteSuite Community Partners (see NOTICES)
Access denied, authentication required.
Username:administrator
Password:************
* http://localhost:8080/ami -> v.2.1.116.0 (Queenston)
Ready...
>sudo systemctl start santedb
sudo systemctl status santedbsudo systemctl stop santedb
sudo systemctl status santedbsudo systemctl enable santedb




Create an un-installer which will clean the directory on uninstall
ATNA & DICOM Messaging (which allows for dispatch of audits via NEMA DICOM over Syslog)
This tutorial uses Docker as a basis for illustrating SanteMPI functions. In order to complete this tutorial, users should:
Have Docker installed on the host system (on Windows or Linux)
Have a text editor which can be used to edit the docker YML files
Installed SOAP UI (https://www.soapui.org/downloads/latest-release/)
Downloaded the Installation Qualification Test Suite (https://github.com/santedb/santempi/blob/master/SanteMPI-Test-Cases-soapui-project.xml)
In a text editor, create a new directory and create a new text file called docker-compose.yml in that directory.
First, you will need to create a postgresql service, this is where the SanteMPI database will be stored.
This section:
Creates a new docker service called db from the postgres:latest tag
Exposes the PostgreSQL database on the host on port 5432
Sets the initial postgresql user to santedb with password SanteDB123
Next, declare the santedb-mpi service , this service will host the the actual iCDR which has SanteMPI:
This section of the file:
Creates a service named santedb-mpi in the docker environment
Enables feature via the SDB_FEATURE environment variable (for reference see: Feature Configuration
Instructs the iCDR to enable Master Data Storage for Patient resources
Connects the main database to santedb on the db container.
Connects the audit database to auditdb on the db container
Instructs the iCDR to hide any data which is tagged with a privacy policy (other options are redact, audit, none
Instructs the iCDR to wait 5 seconds before starting (to allow the database to initialize)
Forward/expose the iCDR APIs on port 8080
Finally, create a container which will run the web access gateway using santedb-www:latest
This section:
Creates a service named www which uses the santedb-www image
Forward traffic to the web portal on port 9200
After saving the text file, return to your command prompt and type:
This will start the SanteDB iCDR (running SanteMPI), the web access gateway and database. Initial startup of the SanteMPI container can take upwards of 5 minutes. You will see a log entry which indicates that startup was successful after this time.
You can now configure the web-access gateway, the Configuring the Web Access Gateway article contains detailed instructions on how this is performed.
Once startup is completed, navigate to http://127.0.0.1:9200 in your web browser. You will be prompted for connection details. For the quick start use:
Device ID: quick-web
Realm: santedb-mpi
The rest of the settings can be left as their defaults.
Pressing the Join button will prompt you for a user name and password, use Administrator and Mohawk123 as the password.
You will be managing a SanteMPI server, therefore you will need to instruct the web access gateway that this gateway will be acting in the "SanteDB Master Patient Index Functions" solution.
Since the web access gateway will be acting as an administration panel, you should set the dCDR in online only mode (no disconnected use)
The santedb-www and Web Access Gateway in general lack the SQLite binaries needed to operate in offline mode. If you select offline mode your web container will most likely not start up.
You can accept the defaults for the following screens:
Logging - This screen sets the verbosity of the output to your Docker host log
Application Services - This screen allows for the enabling of third party or additional services which are not required by the web access gateway.
Network - This screen allows you to configure the optimization between the dCDR and iCDR
Full documentation of these settings can be found on the Installing Web Access Gateway and Installing Disconnected Gateway wiki articles.
You can customize the manner in which the SanteMPI user interface behaves by setting one or more User Interface App Settings. For example, the configuration below will only require given and family names to be registered, and will show the normally hidden fields for collecting patient Religion.
Once your settings are saved, the web access gateway will save the settings and restart itself.
You can now log into the web administration console for the Master Patient Index. You can use the administrator/Mohawk123 account to log into the administrative panel.
Since this is a demonstration environment, you will probably want to change the default access policies for Administrators to allow them to see clinical data and perform MDM tasks. This is done by navigating to Security -> Groups and pressing edit on the Administrators group.
You can scroll to Policies and add the following policies to the group:
Unrestricted MDM
Unrestricted Clinical Data
After adding these policies you should observe the policies in the master list of permissions.
The policies associated with your session for Administrator were established when you logged in, you've changed the policy set, however, your session will still have the old policy assignments for your user role. You will need to log out of the user interface to obtain a new session with the new policies.
An easy way to get patients into the SanteMPI instance is to run the Master Patient Index / Client Registry Qualification. These tests will ensure that the MPI is operating correctly (using the default options) and in the process, will create a few test patients.
In the pre-requisites, a link was provided to the SanteMPI Installation Qualification SOAP-UI project. You can launch SOAP UI on your system and import this project.
This will expose a new project in your SOAP UI project with the SanteMPI endpoints (restricted from the Swagger documentation) shown and a test case called Installation Qualification
The installation qualification tool uses PMIR notifications and subscriptions, it is a good idea to start the FHIR Mock service so that your docker container has an endpoint to send these messages to.
Double clicking on the Installation Qualification test suite will open the test steps for the SanteMPI installation qualification. There are 10 tests (all of which are documented in detail on the MPI/CR Test Cases for FHIRpage).
If all tests return green status, it indicates that your copy of SanteMPI is operating as expected for baseline FHIR functions.
After the qualification tooling has been executed, you can now use the SanteMPI Dashboard to navigate the recent patients that were created in the installation qualification tool.
Clone the openhie/instant repo: https://github.com/openhie/instant
Have docker installed - There is a prerequisite documentation on the openhie wiki which explains the docker requirements: https://openhie.github.io/instant/docs/introduction/getting-started
Be familiar with how to create an Instant OpenHIE package: https://openhie.github.io/instant/docs/how-to/creating-packages
The minimum needed to create a package is an instant.json file, a Docker folder, and a Kubernetes folder. The instant.json file will look something like shown below.
{
"id": "santempi",
"name": "client-registry",
"description": "OpenHIE CR Based on SanteMPI",
"type": "infrastructure",
"version": "v2.1.3",
"dependencies": ["client", "core"]
}The docker folder will need the following items:
A compose.sh file
A docker-compose.yml file
Either docker-compose.config.yml files and/or a docker-compose.dev.yml file
Potentially an Importer folder, which while not necessarily required, will make life easier - this would enable you to preconfigure channels, instead of having to manually create them.
The Kubernetes folder will need the following items:
A k8s.sh file
Kubernetes resource files, in our example we have:
db-deployment.yaml
db-service.yaml (These are for the Postgres Image)
santedb-deployment.yaml
santedb-service.yaml (This are for the santedb-mpi image)
santedb-mpi-app-persistentvolumeclaim.yaml, santedb-mpi-config-persistentvolumeclaim.yaml, santedb-mpi-seed-persistentvolumeclaim
Potentially an Importer folder, which while not necessarily required, will make life easier - this would enable you to preconfigure channels, instead of having to manually create them.
Navigate to the OpenHIE/Instant repository. Type the following commands
Next we need to run the images
The above command is specifying to run docker, specifying the package santempi (Which will link to the id property of the instant.json file), and specifying a path of where to find the image.
It make take several minutes to build. And after it's complete, you may need to wait a couple more minutes for the santedb-mpi server to be fully initialized. Once it's done, you should see something that looks like the following:
There are other containers available. These are the minimum required to use the santedb package with the instant openhie project.
You can navigate to http://localhost:9000 and be brought to the login screen.
default username is: [email protected]
default password is: instant101
If you've used the example project, or have used an Importer, you should be able to see santedb channels.
If you are creating a channel manually, click on the green + Channel near the bottom left.
For basic info give a channel name, and a brief description. In this example we are going to use the admin API, so you could call the channel Santedb MPI Admin
For request matching there are two things you need to do
enter a URL pattern (in our case /ami) - make sure you unclick Auto-add regex delimiters
Make the channel public
Finally, for Routes, add a new route with the following info:
Route Name: SanteDB Admin
Host: santedb-mpi (this is referencing the docker container name)
Port: 8080 (this is referencing the internal docker port on the container)
Forward existing Authorization Headers: yes
Click set route.
Navigate to the OpenHIE/Instant repository. Type the following commands
Next we need to run the images
The above command is specifying to run docker, specifying the package santempi (Which will link to the id property of the instant.json file), and specifying a path of where to find the image. The only difference between this and docker, is you're changing the keyword 'docker' to 'k8s'.
The kubernetes deployments will take much longer to build than the docker deployments. Afterwards it will look something like the following image (Note: This might change depending on what packages you're running)
You can navigate to http://localhost:9000 and be brought to the login screen.
default username is: [email protected]
default password is: instant101
Manually Adding Channels
To manually add a santedb channel, once logged in, click on the channel section and the green Channel + button.
Adding a channel is almost identical to docker. (See above) - The differences is when adding a route, instead of using the container name, as in docker, you will need to use the IP Address of the pod.
To obtain the pod:
The pod we want is the santeDB pod, santedb-66bf68f744-xpsnh (This will change as the name is dynamic, but it should be prefixed with santedb)
The above command will display the details of this pod. At the top of the JSON blob you can see the IP Address.
Now you can add the IP Address as the host for the route.
One quick note when manually adding channels, you may need to check to ensure the role has permission to access the channel. You can check by clicking on the Clients tab on the left hand side. Check the role you are attempting to use, if you see an X over the santedb channels, you can click the x and it will change the permission.
We will now test to make sure we can see SanteDB transactions in openHIM. You will need to generate a bearer token in order to successfully access santedb services. We will test with an administrator account, so we will be using the SanteMPI Admin Channel.
To generate a bearer token:
SanteDB requires that you use a bearer token to access services on the SanteDB server. For full documentation see the OpenID Connect Documentation. A quick method to authenticate yourself with:
To test we are going to make API calls using something like Postman, or maybe curl. For this demo I will use postman.
Under the Authorization tab for postman, select type as Bearer Token - In the value, enter the bearer token that you have generated.
We are going to make a simple get request using http://localhost:5001/ami/SecurityUser
You should see a 200 response. Now, go back to the OpenHIM console. You should see transactions being displayed. It will look similar to the image below:
Must have a registered extension type (a valid extension type UUID)
Have effective/obsolete dates which means that they are subject to versioning and may need pruning
Store the extension valid as a serialized BLOB
SanteDB provides several built-in serializers for handling extension data which are used based on the type of data you'll be storing. SanteDB extension data types included within the solution are:
Data Type
Handler
Description
Binary
BinaryExtensionHandler
Stores a variable length byte array as a blob
Boolean
BooleanExtensionHandler
Stores a 1 byte representation of a binary value
Date
DateExtensionHandler
64-bit (8 byte) ticks from UTC of the time stored
Decimal
You can create additional extension data types by implementing the IExtensionHandler interface in a .NET plugin.
SanteDB provides built extension types which are enumerated below.
URL
Type
Use
/core/jpegPhoto
Binary
Stores a JPG photograph of an entity/act
/core/originalDate
Date
Stores the original or amended date an action was supposed to occur.
/core/contactRole
Dictionary
/core/detectedIssue
You can register your own extensions by using the HDSI interface and POSTing a new ExtensionType resource.
Tags are another extension point which can be used to attach metadata to an object during processing, disclosure, or to control some operational process. Tags are not versioned and live throughout the lifetime of the object. Tags can be removed and updated, however the history of these changes are not tracked.
Tags require no formal definition of the tag type, and represent a simple key/value pair on the object.
SanteDB's core plugins affix tags to objects based on the plugins enabled and the status of the object. These tags are described below.
Tag
Values
Use
$mdm.type
M = Master
L = Local
T = Record of Truth
O = Orphan
The MDM service uses the type tagging to convey the type of master data record being provided. It is also used by
callers to instruct the MDM record to perform certain behaviors. For example, sending an update with $mdm.type
of T would instruct the MDM layer that the resource being
pushed is a designated record of truth.
$mdm.processed
True | False
Indicates that the MDM layer has already processed the
object. This prevents duplicate processing of records.
$mdm.resource
Patient | Place ..
Indicates the original type of resource the MDM record is
conveying. This is because MDM Masters are generic Entity
or Act resources with no clearly identified type. The $mdm.resource tag allows callers to understand the original
type of data the master is representing
$generated
Document the physical architecture of the servers, virtual machines, networks, etc. of the operational deployment
Describe the disaster recovery options, backup requirements, and security environment (remote access requirements, etc.)
Enumerate the IP addresses, host names, and network infrastructure of where components of the SanteDB software is operating
Describe the business continuity plans
Describe how the SanteDB infrastructure interfaces with other local systems (peer network addresses, data formats, type of data, etc.)
Describe specific data configurations, concept sets, extensions, locations, etc. found in the country deployment
Document SanteDB server configuration settings.
The operational architecture documentation should summarize the software environment in which the SanteDB server is being operationalized (in the example document, note the summarization of the software components).
The operational documentation should keep discussion of software components and business processes to a brief overview (the majority of your software modifications and flows should be captured in a FDS).
Consider, for example, the software architecture for the Demoland example.
You will note that the software summary is concerned about the overall deployment of the software components onto various server infrastructure, and illustrating how data is shared and flows between these components.
The operational architecture of your SanteDB deployment will be highly variable, based on the intended goals and current ground truth (availability of internet, local system capabilities, clinics, workflows, etc.)
The operational architecture should describe the operational environment on which the SanteDB software solution will be running. Regardless if the system is hosted in an on-premise data centre, as a managed service, in cloud or as Software-as-a-Service (SaaS), system administrators will still require detailed descriptions of the physical environment in order to manage the system.
The system description should include a server deployment diagram (see below for an example), or if using cloud services, how those services are deployed. If the solution is deployed in clinics with special software or hardware, those deployments should also be documented. The goal is the clearly illustrate how the software is deployed so the operators can maintain the system.
Additionally, any hardware specifications or network specifications should be clearly enumerated in the operational documentation. This includes:
The brand name of any equipment being used (example: Lenovo ThinkServer ST550) - this helps maintainers understand how to get support for the hardware.
The configuration of the equipment including any options which were configured (example: 2x Intel Xeon Silver 4220 , 128 GB RAM, 1 PCIe nVME Boot Drive, 2x GBe NIC, etc.). This helps maintainers understand the scope and size of the deployment, as well as providing a concrete list of parts which can (or need) to be reordered in case of failure.
The software environment of the physical equipment such as any operating systems, Security Information and Event Management (SIEM) or Application Performance Management (APM) software, antivirus configuration, etc. This helps maintainers understand the third party software in use in the operational deployment.
The sizing of your physical environment will depend heavily on a variety of factors such as the type of use of the SanteDB product, whether offline mode is leveraged, how many users and systems are connecting to the system, etc.
As a general rule, when deploying SanteDB on a physical environment the iCDR components can be computed as:
iCDR Server CPU
20 concurrent clients = 5 VCPU minimum
iCDR Server RAM
4GB - 8GB
PostgreSQL Server CPU
5 VCPU on iCDR = 10 VCPU
Additional hints for sizing a physical environment:
Buy two of everything instead of one physical server, buy two smaller ones - this is beneficial because:
It provides load balancing opportunities
It provides a failover environment when the hardware fails
Always purchase SSD or NVMe based storage for your database servers (as opposed to spinning/spindle disk types)
Always run your storage in a redundant mode (i.e. run in RAID1, RAID1+0, RAID5+0 or RAID6)
Where possible use PostgreSQL streaming replication on the primary CDR database to balance queries and writes
Where possible use a Storage Area Network with the highest possible Input/Output Operations (IOPS) ratings for throughput
If using a SAN ensure the storage network is on a different NIC than other network traffic
A SAN allows hypervisors to move Virtual Machines (VMs) between hosts to balance load or to provide rapid failover (using technologies such as VMotion)
Always buy spare parts (disks, RAM, network cards, etc.) matching the configuration of the hardware in the original equipment (this provides quick replacement for failed hardware)
Your operational documentation should describe the networking environment used in the deployment. This includes:
IP addresses and host names of each POSE and VOSE in use in your deployment
All ports which are opened on the operating system firewalls (if any) including their port number, protocol and type of data flowing through the port (including if they are secured or not)
How load balancers, SSL termination, or application firewalls are to be configured to handle traffic (example: external host https://mpi.gov.demoland.com:8443 is routed to http://mpi-prod:8080) Tip: offloading encryption to a dedicated endpoint can free application server resources -- for more information see https://www.nginx.com/blog/nginx-ssl/
Any remote access ports which are opened for system administration. This could include SSH access points, Microsoft Remote Desktop, VNC, or even VPN settings which will be used to access the console or host operating systems.
SanteDB often acts as an integration point for many different systems and often plays vital roles in a health system. What happens, however, when that infrastructure is not available?
It is fact of life that servers fail, networks are unreachable, or other any other combination of issues can arise. The operational architecture should at least identify how this will impact business users. For each component in your deployment, the availability section should describe:
The observed impact of an outage of the particular component (for example: how does the system behave when the database server is offline?)
Mitigations that can be taken to prevent or recover from the outage condition
Descriptions of what the business impact of a component being absent would have on users (example: If the one of the SanteMPI host servers is unavailable, what impact would it have on users? What options are there to continue doing business?)
Large deployments often involve a large number of staff, companies, agencies and ministries. It is important that a clear set of responsibilities be established for each. This is important as it allows readers of the operational architecture to understand:
Which partner in the deployment is responsible for which maintenance or corrective activities?
What are the hours of operation (or expected availability) of each partner?
What are the escalation procedures and tiers for supporting the deployment?
In general, we recommend using information technology service management frameworks and best practices published by organizations such as ITIL, ITSM and COBIT to establish a Service Desk process and supporting tools for the ongoing support of the end-users of your solution.
When an issue is detected that impacts business users, they will often need to continue doing their work (even though the software is unavailable). Your operational architecture document should include a business continuity plan. The continuity plan should identify:
What should users do when the system is unavailable? (use a paper based process? replace devices? change sites to a backup installation? etc.)
How should users report their issues when they experience an outage? (Is there a helpdesk? A bug tracker? A support line to call? etc.)
What are the RPO, RTO and MTO values for the deployment? (see below)
What are the procedures (for each component) to recover from a failure condition?
Recovery Time Objective (RTO) – The maximum amount of time that could be tolerated between unexpected failure and the resumption of normal service. (i.e. How long can clinics operate without the system?). RTO dictates the goal for recovering the service operation.
Recovery Point Objective (RPO) – The maximum period of time which data might be lost if service unexpectedly fails. (i.e. How far back can you fail without being a catastrophic loss to business?). RPO usually informs the frequency of your backups and impacts the cost of your backup infrastructure.
Maximum Tolerable Outage (MTO) – The maximum amount of time that the business can tolerate complete outage of the system during normal business days before it becomes impossible to continue doing work.
Software is a living product and evolves over time and it is important to ensure that operating systems, clinical systems, antivirus software, firewalls, etc. are regularly updated to ensure that the latest security and features are present in the environment.
Typically, updates require organizational planning to ensure that maintenance windows do not overlap with business operations, and that any special processes (like backups, snapshots, service stop/start, upgrades, etc.) are done in a particular order.
The operational architecture should describe all of these impacts on the environment, as well as any special procedures that must be followed. For example:
Prior to updating the SanteDB dCDR software in clinics, ensure:
Any OpenMRS servers are shut down and users logged out.
The SanteDB dCDR synchronization center indicates no conflicts and no remaining upload data (in the outbox)
The backup job is run to produce a recent copy of data in the dCDR
Your operational architecture document should describe the security environment which is being used in your deployment. This should include:
How are new devices or applications integrated into the SanteDB infrastructure? What approvals are required and/or sign offs?
How are new users added to the SanteDB infrastructure? What groups are they assigned to? What access controls do they have over the solution and hardware?
What firewalls are in place and/or configured?
How is data encrypted in transit between systems and at rest, including via intermediaries? (example: How are the HL7v2 messages encrypted between a Hospital Information System and the SanteDB iCDR?)
How are systems and users authenticated? What are the policies in the deployment for password and account expiration?
What are the custom policies applied or configured in the operational environment?
The SanteDB team has prepared a template which may be helpful for organizing your Operational Architecture. The document contains instructions and a limited example of content for Demoland to get writers started in authoring operational architectures.
As always, please refer to the Disclaimer.
DENY
Create Role
DENY
Alter Role
DENY
Create Identity
DENY
Login
GRANT
GRANT
GRANT
Unrestricted Clinical Data
GRANT
GRANT
Query Clinical Data
GRANT (implied)
GRANT (implied)
Write Clinical Data
GRANT (implied)
DENY
DENY
Delete Clinical Data
GRANT (implied)
DENY
DENY
Read Clinical Data
GRANT (implied)
GRANT (implied)
Override Disclosure
GRANT
DENY
DENY

The first step to deploying SanteDB solutions is to gather information about problem domain and jurisdiction in which the solution will be deployed.
Identify the people and organizations within the implementation context. Stakeholders include:
Relevant department(s) of the organization
Vendors of existing software solutions within the context
Subject matter experts for the problem domain, relevant standards and SanteDB products
Owners / Operators of health solutions (such as funders, NGOs, hospitals, etc.)
Identify the reason why SanteDB or a SanteDB solution is needed in the context, and what clinical problem is being solved. It is helpful to indicate:
What problems are being solved?
Why do we need to solve them?
What are the timelines in which a solution should/needs to be found?
What are the which apply to the project?
It is useful to prepare a vision statement for the overall deployment of SanteDB project. This vision statement is a short (1 - 2 sentences) statement which encapsulates the project and can be referenced as a guiding raison d'être as the project progresses.
An example for Demoland might be:
The National Client Registry (NCR) will facilitate the implementation of our National Health Identifier Programme (NHIP). NHIP is a keystone to supporting better care through health information exchange throughout Demoland.
Identify a team of people who will be responsible for the process of operationalizing SanteDB in the context. The team which is identified/established ad their roles/responsibilities on the team will be highly variable (based on project).
SanteDB has had some success using the RACI methodology () which identifies team members who are:
Responsible - Completes the tasks or work described
Accountable - Answerable to the project owner/sponsor for the accurate and thorough delivery of the work
Consulted - Subject matter experts or other persons/groups whose opinions are sought
RACI charts are often defined using deliverables/tasks as rows and an organizational chart as columns. This makes it easy for project team members to know what their obligations are for each phase of the project delivery.
The explicit makeup of a SanteDB deployment team will vary, however the community has prepared a list of logical "roles" which should be filled (these may be filled by the same person with the required skills) throughout the project lifecycle.
Engage with relevant stakeholders to perform an environmental scan of the current environment in which the SanteDB system is being deployed. It is important to observe/collect:
Which systems are being used in the context?
What types of data do those systems collect?
What are the processes used by those systems and their users?
What are the operational difficulties that are being encountered? (lack of data, timeliness of access, etc.)
The Asian Development Bank (ADB) has prepared a useful unique health identifier assessment toolkit which may be of use in performing an environmental scan of the current identities and policy frameworks in your jurisdiction.
See:
This page describes the history of the SanteDB project.
SanteDB is the evolution of a reference implementation of the Canadian national digital health platform that originated in a post-secondary institution research lab beginning in 2007. SanteDB was designed with national scale, standards-based digital health applications in mind from the beginning.
The SanteDB suite of products incorporates the full functionality of previous research products such as the MEDIC CR client registry and the OpenIZ immunization management system into a deployment-ready, commercially supported package. A brief summary of the evolution of the products is provided in the following section.
SanteDB is really an evolution of OpenIZ () which itself was an evolution of the MARC-HI SHR RI. The table below illustrates the relative features of each solution.
SanteDB Administration & Security Console v2.1.131.0 (Queenston)
Copyright (C) 2015 - 2020, SanteSuite Community Partners (see NOTICES)
Access denied, authentication required.
Username:administrator
Password:************
* http://localhost:8080/ami -> v.2.1.116.0 (Queenston)
Ready...
>C:\Users\user> NET STOP santedb
C:\Users\user> NET START santedmkdir quickstart
notepad docker-compose.ymlversion: "3.3"
services:
db:
image: postgres
container_name: sdb-postgres
ports:
- "5432:5432"
environment:
POSTGRES_USER: santedb
POSTGRES_PASSWORD: SanteDB123
restart: always
santedb:
image: santesuite/santedb-mpi:latest
container_name: santedb-mpi
environment:
- SDB_FEATURE=LOG;DATA_POLICY;AUDIT_REPO;ADO;PUBSUB_ADO;RAMCACHE;SEC;SWAGGER;OPENID;FHIR;FHIR_AUDIT;HL7;HDSI;AMI;BIS;MDM;MATCHING;IHE_PIXM;IHE_PDQM;IHE_PMIR;IHE_PIX;IHE_PDQ
- SDB_HL7_AUTHENTICATION=Msh8
- SDB_MATCHING_MODE=WEIGHTED
- SDB_MDM_RESOURCE=Patient
- SDB_MDM_AUTO_MERGE=false
- SDB_DB_MAIN=server=sdb-postgres;port=5432; database=santedb; user id=santedb; password=SanteDB123; pooling=true; MinPoolSize=5; MaxPoolSize=15; Timeout=60;
- SDB_DB_AUDIT=server=sdb-postgres;port=5432; database=auditdb; user id=santedb; password=SanteDB123; pooling=true; MinPoolSize=5; MaxPoolSize=15; Timeout=60;
- SDB_DB_MAIN_PROVIDER=Npgsql
- SDB_DB_AUDIT_PROVIDER=Npgsql
- SDB_DATA_POLICY_ACTION=HIDE
- SDB_DELAY_START=5000
ports:
- "8080:8080"
- "2100:2100"
depends_on:
- db
restart: always www:
image: santesuite/santedb-www:latest
container_name: santedb-www
ports:
- "9200:9200"
depends_on:
- santedb
restart: alwaysyamldocker compose -f docker-compose.yml upyarn
yarn docker:buildyarn docker:instant init -t docker santempi -c="<path to santedb package>"whitet@Mohawks-MBP instant % docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
58d391d05922 santesuite/santedb-mpi:2.1.3 "mono /santedb/Sante…" 33 seconds ago Up 28 seconds 0.0.0.0:2100->2100/tcp, :::2100->2100/tcp, 0.0.0.0:8082->8080/tcp, :::8082->8080/tcp santedb-mpi
c27b8358cd41 hapiproject/hapi:v5.2.1 "catalina.sh run" 57 seconds ago Up 54 seconds 8080/tcp hapi-fhir
3056b77f1a9b mysql:5.7 "docker-entrypoint.s…" About a minute ago Up 57 seconds 3306/tcp, 33060/tcp hapi-mysql
161a5071d2ca jembi/openhim-core:5 "docker-entrypoint.s…" About a minute ago Up 47 seconds 0.0.0.0:5000-5001->5000-5001/tcp, :::5000-5001->5000-5001/tcp, 0.0.0.0:5050-5052->5050-5052/tcp, :::5050-5052->5050-5052/tcp, 0.0.0.0:8080->8080/tcp, :::8080->8080/tcp openhim-core
8903414d9b11 mongo:4.2 "docker-entrypoint.s…" About a minute ago Up About a minute 27017/tcp mongo-1
c1e4e3e15802 postgres "docker-entrypoint.s…" 22 hours ago Up 33 seconds 5432/tcp sdb-postgres
7874397ec2ae intrahealth/opencr:6195bd8 "/bin/sh -c 'dockeri…" 22 hours ago Up 37 seconds 0.0.0.0:3004->3000/tcp, :::3004->3000/tcp opencr
e42421df077c intrahealth/elasticsearch:latest "/usr/local/bin/dock…" 22 hours ago Up 42 seconds 0.0.0.0:9200->9200/tcp, :::9200->9200/tcp, 9300/tcp es
b79d9cd172fd jembi/openhim-console:1.14 "/docker-entrypoint.…" 22 hours ago Up 55 seconds 0.0.0.0:9000->80/tcp, :::9000->80/tcp openhim-console
d2a1eb344eee mongo:4.2 "docker-entrypoint.s…" 22 hours ago Up About a minute 27017/tcp mongo-2
a53e45cd7c94 mongo:4.2 "docker-entrypoint.s…" 22 hours ago Up About a minute 27017/tcp mongo-3
whitet@Mohawks-MBP instant %
yarn
yarn docker:buildyarn docker:instant init -t k8s santempi -c="<path to santedb package>"kubectl get podskubectl describe pod santedb-66bf68f744-xpsnhPOST http://localhost:8082/auth/oauth2_token HTTP/1.1
Content-Type: application/x-www-form-urlencoded
X-SanteDBClient-Claim: PolicyOverride=1;PurposeOfUse=EMERG
Host: mpi-test.local:8080
Content-Length: 112
grant_type=password&scope=2.25.3049340304933&username=administrator&password=Mohawk123&client_id=fiddler&client_secret=fiddlerDecimalExtensionHandler
128-bit (16 byte) decimal number
Dynamic
DictionaryExtensionHandler
A JSON structure of any data object
Reference
ReferenceExtensionHandler
A 128-bit UUID pointer to an Entity, Act or Concept
String
StringExtensionHandler
A variable length string stored in the database
Uuid
UuidExtensionHandler
A 128-bit byte array representing a UUID
Dictionary
A structured list of business rules/data quality issues that were detected with an object.
/stock/contrib/gs1/estimatedDeliveryDate
Date
The original time (from the sender of a GS1 message) of estimated delivery date of an object.
/stock/contrib/gs1/shipmentDate
Date
The original shipment date of an action
/stock/contrib/gs1/packgingType
String
The type of packaging (crate, box, etc.) from the GS1 sender
True | False
When retrieving data that was synthesized from other data
records this flag will be TRUE. This indicates that the result
is not an *actual* record, rather it is combined from multiple
local records.
$alt.keys
UUID List
A list of other keys which the resource references may use.
Deprecated.
$pep.masked
True | False
When present in a resource, informs the caller that the
PolicyEnforcementService or PrivacyEnforcementService
has masked/redacted or removed sensitive data from the resource returned. This is an indicator to the caller that they
may need to perform an elevation to unlock all the data.
Note: If the PEP is set to HIDE sensitive data then the resource is not returned in any disclosures, and the $pep.masked flag will not appear.
$pep.method
hash | hide | redact
When present in a resource, informs the caller that the policy
enforcement service took destructive action on the resource
using the specified privacy enforcement method.
Note: The $pep.method of hide on a resource indicates that part of the resource was hidden (usually identifiers)
if the entire resource is hidden, then the tag wouldn't appear
on a resource tag.
$bre.error
String
Used by the BRE engine to convey non-fatal errors to
callers. This is used for diagnosing / logging and catching
upstream errors in business rules.
$sys.reclass
True | False
Used by the persistence layer to determine whether an object is being re-classified (having its type changed).
Normally this would cause an error in the persistence layer
however setting $sys.reclass=true instructs the persistence
layer to change the object's class. This is how, for example,
a Person may be re-classified as a Patient.
$match.score
0.0 .. 1.0
When the resource being conveyed is in the context of another (for example: a sub-resource or link resource) the match score will be added to indicate the strength of the relationship of the resource to the container.



User Champion
Represents the users of the system (clinicians for integrated systems)
Provides insights into on-the-ground practice and workflows
Promotes the project to clinical staff and other users
Supports users through deployment and use.
Enterprise Architect
Follows established processes (CMMI, TOGAF, etc.) to produce overall architecture.
including use cases, system interactions, business processes, etc.
including appropriate structural and content standards, minimum data sets, identification schemes, etc.
Solutions Architect
Designs software architecture for extensions to the SanteDB solution.
Designs software architecture for local systems to integrate with the national (or regional) SanteDB systems.
Liaises with Security, Network and Database personnel to
Developer
Performs code enhancements to SanteDB software (see: )
Works with user champions to gather feedback on changed user-facing elements.
Writes tests and validates software modifications are non-breaking.
Technical Writer
Create user-facing documentation for new screens.
Adapt / Create standard operating procedures to local context
Create training materials (documents, cheat sheets, job aides, videos, etc.) to support local users.
Localization Specialists
Uses the service to translate SanteDB to local language if needed.
Adapts/designs the user interface to match cultural references/norms (iconography, layout, etc.)
Security Analyst
Creates and performs the Threat Risk Assessment
Liaises with the Solution Architect in
Validates the production environment after deployment
Network Administrator
Installs and configures physical hardware including servers, storage arrays, switches, routers.
Configures network firewalls and appropriate software firewalls.
Installs and patches bare-metal and virtual operating environments (POSE and VOSE)
Database Administrator
Installs and configures the SanteDB database environment.
Monitors and modifies database software settings to tune operational environment.
Documents and configures database backup and recovery procedures.
User Success Associate
Monitors the helpdesk and ticketing software for issues.
Provides front-line support to end-users, administrators, and monitors tickets through the lifecycle.
Populates the local deployment knowledgebase to reduce future reliance on helpdesk services.
How are users authenticated or identified?
What non-technical (business) processes are enforced?
Perform Policy / Legislative Scan - Identify, collect, and document the relevant legal statutes, policies, laws, culture norms, etc. which may impact the project.
Project Sponsor / Owner
Makes final decisions for project
Provides local/business context and conveys needs
Liaises with Ministry of Health and other administrators
Promotes the project to peers
Obtains approvals and commitments to plans.
Project Management
Planning and Coordination of Tasks
Shepherding other team members
Gathering status updates
Liaise with project sponsors/owner
Business Analyst
Liaising with in-country vendors / suppliers
Documenting current workflows/data
Performing assessments and documenting requirements.
Producing the Business Requirements Document
Legal Counsel
Provides guidance existing legislation and policies
Writes / Performs Privacy Impact Assessments against integration partners
Creates policy documents and governance procedures.
Reviews/ensures compliance of delivered environment against local legislation.
Administrative Assistant
Scheduling team meetings and events
Coordinates schedules of other team members
Produces meeting notes and records decisions.
Feature
MARC-HI SHR RI
OpenIZ
SanteDB iCDR
Platform Information
Original Release Year
2011
2016
2019
MARC-HI Service Core Generation
PostgreSQL RAM
10 VCPU = 5 GB RAM minimum (more is better to tune max_work_mem)
PostgreSQL Disk
As fast as possible

V1
V2
N/A
Technologies / Frameworks
.NET 2.0
.NET 4.0, Xamarin, AngularJS 1.5
.NET 4.5, Xamarin, AngularJS 1.7
Primary Role(s)
Clinical Data Repository (CDR)
Electronic Immunization Record (EIR)
Clinical Data Repository (CDR)
Deployment / Operationalization
Server Environment(s)
Windows Server 2003+
Windows Server 2008R2+
Windows Server 2008R2+, Linux, MacOS
Client Environments
Android 4.4+, Windows 7+, Linux, MacOS
Android 5.0+, Windows 8+, Linux, MacOS
RDBMS Support
PostgreSQL 9.2
PostgreSQL 9.4, SQLite, MSSQL 2008+
PostgreSQL 10, FirebirdSQL 3.3, Oracle 11g, SQLite
Scale-Out
DB: Streaming Replication, App Server: Round-Robin DNS
DB: Streaming Replication, App Server: Round-Robin DNS
DB: Streaming Replication, App Server: Round-Robin DNS, Role-Based Scale-out
Information Model
Model
Component Model
HL7 RIM
HL7 RIM
Encounters
X
X
Substance Administrations
X
X
X
Observations
X
X
X
Clinical Procedures
X
X
Finance (Account, Invoice, etc.)
X
Patient Administration
X
X
Administrative Units (Place, Organization, etc.)
X
X
Versioning
X
X
X
Extendibility
Clinical Decision Support Engine
X
X
Business Rules / Data Triggers
X
X
Plugins (.NET)
X
X
X
Security / Accountability
ACL Paradigm
Policy-Based
Policy Based w/Override
Authentication Methods
X509 PKI
OAUTH, HTTP BASIC
OAUTH, HTTP-BASIC, X509 PKI
Auditing
RFC3881
RFC3881, NEMA DICOM
RFC3881, NEMA DICOM, HL7 FHIR STU3
Standards & Interoperability
HL7v2.x
X
X
X
HL7v3
X
HL7 CDA
X
HL7 FHIR
DSTU1
DSTU2
R3
Other Interfaces
GS1 BMS XML 3.3
GS1 BMS XML 3.3
Optimization / Extra
HTTP Compression
Responses Only
Bi-Directional BZ2, GZ, DF, LZMA
Bi-Directional BZ2, GZ, DF, LZMA
Data Caching
Memory Cache Only
Memory Cache, REDIS
Memory Cache, REDIS
Matching / Merging Engine
Probabilistic Matching Engine
Master-Data-Model Management
X
Reporting
3rd Party
Jasper Reports, ReportR 1.0
ReportR 2.0






Reviews development activities and training materials for appropriateness.
Validate the deployed/operationalized system matches documented architecture.
Performs routine penetration testing against the production environment
Manages/Maintains security access to physical and/or virtual infrastructure.
Documents and configures server backup and recovery procedures.
Handles onsite support issues such as basic networking and hardware issues in clinic.
The matching engine in SanteDB is a multi-stage process whereby an inbound (or a target record) is compared with the current dataset within the CDR. The matching process occurs in three stages:
Blocking : In the blocking phase records are queried from the CDR's database infrastructure. The blocking phase is used to reduce the total number of records being scored, which can be more computationally expensive.
Scoring : In the scoring stage, the target record is compared to those records retrieved from the blocking phase. Each attribute configured is transformed/normalized and then a score applied for each attribute. Furthermore there are API hooks for implementing partial weighting/partial scoring of an attribute (based on frequency of data in database, NLP, or other future methods)
Classification : In the classification stage, each record's score (the sum of each attribute's score) is grouped into Match, NonMatch, and ProbableMatch. These thresholds are configured.
SanteDB allows for the configuration of multiple match configurations, and allows configuration for the "default" match configuration to be used for regular operation (whenever data is inserted, updated, etc.).
In the blocking phase of the matching execution, the candidate record (named $input) is compared with records persisted in the database using one or more blocking configurations.
A blocking configuration is expressed using the which is translated into SQL. Blocking instructions can use any supported for the selected database.
Records are read from the database (as blocks) with multiple blocks being combined with either an intersect or union function. Blocks can be loaded as either:
SOURCE Records: Whereby the source records are loaded from the database as they were sent. Blocking in this mode is less CPU intensive and less database intensive, however relies on source information as a "picture" of what data is available for a patient.
MASTER Records: Where by the blocks are loaded using the MDM layer and are computed based on existing known and suspected links. This method of blocking more closely resembles what users see in the UI when MDM is enabled, however it does slow down matching performance as each record must be cross-referenced with the master data record. It also allows for matching based on records of truth.
Blocks from each statement are combined together to form a result set (in C# an IEnumerable<T>) which are passed into the scoring stage.
In the example below, the SanteDB matching engine will load records for an $input record by:
If the input record contains an SSN identifier , it will filter records in the database by matching SSN. It will then perform an MDM gather (i.e. the matching mode is performed on MASTER records) , these records will be UNION with
The results of a local query whereby:
If the $input has Given name, then the given name must match, AND
In pseudocode terms, the blocking query for an $input of John Smith, Male, SSN 203-204-3049 born 1980-03-02 would resemble:
During the scoring phase, the records from the blocking stage are compared to the $input record on an attribute by attribute basis using a collection of assertions about the attribute. If all assertions on an attribute evaluate to TRUE then the matchWeight score is added to that records total score, if the assertions are FALSE then the nonMatchWeight score (a negative score) is added to the record's total score.
Overall, the process of comparing a blocked record (named $block) with the $input record is:
The scoring attribute may declare that it depends on another attribute being scored (i.e. don't evaluate the city attribute unless state attribute has passed. If the dependent attribute was not scored as a positive (match) then the current attribute is assigned the whenNull() score.
The attribute path on the configuration is read from both $block and $input.
There can occur instances of either the inbound record or the source records from the database which are missing the specified attribute. When this is the case the attribute's whenNull attribute controls the behavior of the evaluation of that attribute. The behaviors are:
The date_extract is applied to both records and then the assertion of "eq" is applied. The following data transforms are available in SanteDB.
The scores for each of the scored attributes are then summed for each $block record and the block is classified as:
Match: The two records are determined to agree with one another according to configuration. the matching engine is instructing whatever called it (the MDM, MPI, etc.) that the two should be linked/merged/combined/etc.
Possible: The two records are not "non-matches" however there is insufficient confidence that the two are definite matches. Whatever called the matching operation should flag the two for manual reconciliation.
Non-Match: The two records are definite non-matches.
Each data type which is registered in the pattern has a corresponding registered. This job resets the suspected ground truth using the following rules:
After the suspected truth is cleared, the job will begin the process of re-matching the registered dataset for SanteDB. The matching process is multi-threaded, and designed to ensure that the machine on which the match process is as efficient as possible. To do this, the following pattern is used:
The batch matching process registers 4 primary threads on the actively configured thread pool to control the match process:
Gather Thread: This worker is responsible for querying data from the source dataset in 1,000 record batches. The rate at which the records are loaded will depend on the speed of the persistence layer (SanteDB 2.1.x or 2.3.x) as well as the disk performance of the storage technology.
Match Thread: This worker is responsible for breaking the 1,000 record batches into smaller partitions of records (depending on CPU of host machine). The configured matching algorithm is then launched for each record in the batch on independent threads (i.e. matching is done concurrently on the host machine).
Writer Thread: Once the match thread workers have completed their matching task, the results are queued for the writer thread. The writer thread is responsible for committing the matches to the read/write database.
The performance of the batch matching will depend on the speed of the host machine as well as the version of SanteDB that is being used.
SanteSuite's community server was used for testing in the following configuration:
Application Server:
4 VCPU
4 GB RAM
Non-persistent (ram-only) REDIS Cache
The versions of SanteDB tested yielded the following results:
Version < 2.1.160 of SanteDB: ~28,000 records per hour
Version > 2.1.165 of SanteDB: ~50,000 records per hour
Version 2.3.x of SanteDB (internal alpha): ~100,000 records per hour










SanteDB provides several docker containers for SanteDB solutions and services. The docker containers are structured as illustrated.
The docker containers all use the mono:latest as their root container.
santedb_icdr: The generic SanteDB iCDR project running as a docker container with FHIR, HL7, caching, PostgreSQL database support, and everything needed to get the iCDR running quickly.
santedb_mpi: The generic iCDR project with the SanteGuard and SanteMPI plugins enabled.
If the $input has a Family name, then the family name must match, AND
If the $input has a dateOfBirth then the date of birth must match, AND
If the $input has a gender concept then the gender must match
$block or $input attribute value extracted is null. If either is null then the the When Null Actions is taken.The matching engine then determines if any transforms have been configured (see: Transforming Data). This is a process whereby data is extracted, tokenized, shifted, padded, etc. on both the $input and $block variables. The result of each transform is stored as the new attribute value in memory and the next transform is applied against the output of the previous.
Finally the actual assertion is applied. The assertion is usually a binary logical operator (less than, equal, etc.) the result of which results in the matchWeight or nonMatchWeight being applied.
Considers any of the configured aliases for the name meeting a particular threshold of relevance (i.e. Will = Bill is stronger than Tess = Theresa)
abs
Number
Returns the absolute value of a number
dmetaphone
Text
Returns the double metaphone code (with configured code length) from the input string
length
Text
Returns the length of text string
levenshtein
Text
Returns the levenshtein string difference between the A and B values.
sorensen_dice
Text
Returns the Sorensen Dice coefficient of text content A and B values.
jaro_winkler
Text
Returns the Jaro-Winkler (with default threshold of 0.7) between A and B values.
metaphone
Text
Returns the metaphone phonetic code for the attribute
similarity
Text
Returns a %'age (based on levenshtein difference) of string A to string B (i.e. 80% similar or 90% similar)
soundex
Text
Extracts the soundex codification of the input values.
substr
Text
Extracts a portion of the input values
tokenize
Text
Tokenizes the input string based on splitting characters, the tokenized values can then be transformed independently using any of the transforms listed in this table.
timespan_extract
TimeSpan
Extracts a portion of a timespan such as minutes, hours, seconds.
Monitor Thread: The monitoring thread is responsible for updating the status of the job.
Database Server:
12 VCPU
12 GB RAM
RAID 1+0 SSD disk infrastructure (4+4 SSD)
@whenNull
Description
match
When the value is null in $block or $input, treat the attribute as a "match"
(i.e. assume the missing data matches)
nonmatch
When the value is null in either $block or $input, treat the attribute as a non-match
(i.e. assume the missing data would not match)
ignore
When the value is null in $block or $input, don't evaluate the attribute.
(i.e. neither the non-match or match scores should be considered). This is similar to zero however, the entire attribute is removed from consideration. The absolute score is added no value, however the total possible score is reduced.
disqualify
When the value is null in $block or $input disqualify the entire record from consideration
(i.e. it doesn't matter what the other attribute scores are, the record is considered
not a match)
zero
When the value is null in $block or $input the attribute should be scored a 0. This is different than applying the match or non-match weight which will be a positive or negative number respectively. This is similar to the ignore setting except zero does not impact the denominator of the score.
Transform
Applies
Action
addresspart_extract
Entity Address
Extracts a portion of an address for consideration
date_difference
Date
Extracts the difference (in weeks, months, years, etc.) between the A record and B record.
date_extract
Date
Extracts a portion of the date from both records.
name_alias
Remove / Delete:
Keep:
Suspected Client Links (MDM-Candidate links)
Automatic Master Links
Verified Ignore
Verified Matches
System Master Links
Entity Name
The privacy control services actively apply privacy policy protections on outbound messages, and ensure that inbound messages meet the minimum policy level for updating/creating records. For example, this service ensures that masked data, or sensitive data which may be inaccurate (given the submitter's policy set) cannot be recorded, and that any data is masked/hidden from the underlying repository.
The audit repository feature enables the local audit repository on SanteSuite, meaning that audits are stored in the specified audit database.
The ADO data storage service should be enabled if you plan on using the PostgresSQL or another supported database to store data.
The ADO freetext search service enables the full-text indexing feature on the docker container, and is available on SanteDB iCDR versions 2.1.155 and above.
The in-memory caching feature instructs the iCDR container to use a local RAM-based cache (non-shared) for data operations.
The REDIS caching feature instructs the iCDR container to use a shared REDIS cache for data operations.
The core security services should always be enabled, unless you're running a heavily customized version of the iCDR software which supplies its own security services.
The OpenID Connect IDP service enables the OpenID Identity Provider services.
The core HDSI interface should always be enabled if you plan on using any of the SanteDB dCDR services. If you are just using the iCDR for other interfaces, you can disable this interface.
The core AMI interface should always be enabled if you plan on using any of the SanteDB dCDR services or services like the admin console which require API access. If you are just using the iCDR for other interfaces, and have no need to create users, policies, or other assets.
The core BI services allow third party solutions to query and execute reports on the SanteDB server, as well as FHIR MeasureReport resources.
Setting SDB_BIS_MAX_RESULTS will impact server performance. The default size of BI report result sets is 10,000. For reports which require more than 10,000 results, it is recommended that the developer pass the _count parameter to the rendering API.
SanteDB's FHIR resources are enabled using the FHIR feature. The FHIR feature controls the exposed resources (to minimize surface area), location and options for FHIR.
The HL7 Version 2.x interface allows the iCDR docker container to expose HL7 LLP or SLLP traffic to trading partners.
The pubsub feature enables the structured message notification system. This allows third party systems to setup standing queries which SanteDB will "notify" them of whenever new data becomes available.
The record matching plugin registers the SanteDB Matcher plugin in the container. This service is used by other services to match and/or merge data.
The matching modes supported are:
SIMPLE: Simple matching only performs block operations against the database, and performs no scoring. This mode is useful when your duplication detection is light. Records are given a score of 0.0 (not match) or 1.0 (match)
WEIGHTED: Weighted matching uses the SanteDB Matching plugin to perform scoring.
When composing your own image from SanteMPI you can copy match configurations to the ./match directory:
The MDM feature sets up the MDM resource persistence strategy and subscribes one or more resources to one or more match configurations.
The supported resources for MDM management are:
Resource
Description
Person
Places any entity of type Person or its subclasses (Provider / Patient) under MDM storage management.
Patient
Places any entity of type Patient into MDM storage management. This is useful for Master Patient Index or Client Registry scenarios.
Provider
Places any entity of type Provider into MDM storage management. This is useful for centralized Provider Registries.
Material
Places any entity of Material or ManufacturedMaterial into MDM storage management. This includes kinds and instances of materials. Useful for centralized product registries.
ManufacturedMaterial
Places only ManufacturedMaterials into MDM storage management.
The e-mail configuration allows you to configure the SMTP settings for SanteDB to send e-mails. This option is used for MFA codes, administrative alerts, etc.
The signing configuration allows administrators of the Docker server to change how the server software signs tokens.
You can enable specific SanteMPI features by enabling the IHE_* interfaces on the santedb-mpi container.
To enable the $ihe-pix operation in the container:
To enable the PDQm behaviors on the /Patient resource:
To enable the urn:ihe:iti:pmir:2019:patient-feed operation:
To enable the specialized behaviors on ADT messages for IHE PIX for HL7v2
To enable specialized behaviors on QBP messages for IHE PDQ for HL7v2
santedb_dcdr: The disconnected dCDR project
The container structure is as follows:
/santedb - Directory which contains the application code for SanteDB
/santedb/docker.lastconfig - The configuration file (in XML form) which represents the computed configuration file for the last run of the docker host.
/santedb/data - Data seeding directory in Dataset format
/santedb/data/fhir - Data seeding for FHIR files (JSON or XML)
/santedb/applets - Application directory (where compile applets files should be)
/santedb/match - Directory for match configuration source files
/var/log/santedb_yyyyMMdd.log - SanteDB log file for current date
The docker containers are configured using environment variables. Features can be turned on/off using the environment variable SDB_FEATURE environment variable, for example, to enable the core features and ATNA audit shipping:
The features which are available for the default SanteDB docker container are:
Code
Feature
LOG
Core data logging (see: )
DATA_POLICY
Data privacy enforcement (see: )
AUDIT_REPO
Internal security audit repository (see: )
ADO
Core Application Data Objects (ADO.NET) data persistence (see: )
PUBSUB_ADO
Publish / Subscribe Subsystem (see: )
The location of your PostgreSQL server, and the database to use for the container can be specified with the connection string environment variables:
If you are using plugins which require additional named configuration parameters, prefix the configuration with SDB_DB_XXX where XXX is the ID of the connection string the plugin is expecting.
Components within SanteDB iCDR can be configured using environment variables. The syntax of these environment variables is SDB_FEATURE_SETTING , for example, the CACHE feature is configured as:
You can compose a minimal application with either the SanteDB-ICDR or SanteMPI instance using a docker-compose.yml file as shown.
Some directories in the docker image are useful for development purposes. For example, you can configure a volume which exposes a common configuration file set, or common applets. The volumes which can be expose (and their directories) can be done via:
The volumes which are of use for exposing to the host docker environment are:
Path
Use
/santedb/data
Used for seeding data into the SanteDB instance. For example
if you have a development environment where you'd like the same data
seeded into the database on startup you can use this option.
/santedb/config
Used for direct access to the configuration files. You should use this option
if the environment variables for the docker instance are too restrictive.
/santedb/applets
Used for loading applet files which contain user interfaces, BI reports,
business rules, CDSS rules, etc. These applets should be digitally signed
PAK files.
/santedb/match
Stores the match configuration files for the SanteDB matching engine. These
match configuration files control the weight, blocking, and classification subsystem
for the default match algorithm.
You can import additional configuration files and/or use the XML configuration subsystem by creating a new container which is based off the santedb-icdr docker image and including additional configuration files. To do this, collect your configuration file as myconfig.xml in a directory and create a new Dockerfile which starts using this as configuration file:
See the Adding Sample Data article for methods of seeding sample data into SanteMPI.
You can package business rules, business intelligence, and other asset files into your docker container by simply composing them into a PAK file and including them in the /santedb/applets/ directory.
Upon load, the SanteDB iCDR server will load your package files and will load any business rules files required.
In order to run a minimal SanteMPI application, you can exchange santedb-icdr with the santedb-mpi image, and apply the appropriate service configuration.
The SanteMPI container adds the following plugins to SanteDB which can be enabled/disabled with SDB_FEATURE:
Code
Feature
IHE_PDQM
Enables the Patient Demographics Query for Mobile query parameters and extensions.
IHE_PIXM
Enables the Patient Identity Cross Reference ($ihe-pix) FHIR operation
IHE_PMIR
Enables the Patient Master Identity Registry function (urn:ihe:iti:pmir:2019:patient-feed ) FHIR message
IHE_PIX
Enables the IHE PIX (ITI-8 and ITI-9) interfaces for the MPI
IHE_PDQ
Enables the IHE PDQ profile (ITI-21) for HL7v2 interface on the MPI.





The Master Data Management plugin permits your SanteDB CDR instance to store multiple copies of a single record based on the source system which provided the data. The MDM services are available on the following resources:
Patient
Place
Provider
Materials (and Manufactured Materials)
Device Entities
Persons
Within the data storage persistence layer, the MDM plugin will update/create locals using whatever underlying class was sent from the caller. Each caller is provided a complete copy of the record which they can update/edit.
The MDM plugin then determines:
Is there a MASTER record which the IRecordMatching service has identified as positive match?
Is the configuration enabled to automatically link these records?
If no MASTER is found, or the configuration does not permit auto-linking then a new MASTER of the base type is constructed (Entity in case of Patient, Place, Material, etc. or Act in the case of Administration, Procedure, Observation, etc.) and links the LOCAL record to this newly created master instance using the relationship type MDM-MasterRecord.
The master record should have no data associated with it. It is merely an anchor which is used to collect the local records. Typically a master record can have extensions, notes, identifiers, names, etc. associated with it, however these attributes should apply to the anchor point rather than for establishing ROT data.
In the case where a match between a LOCAL and MASTER record is ambiguous (i.e. does is a Probable match or when Auto-Link is disabled) the link between records is considered a candidate and the local is related to the MASTERs which it is a candidate for using the MDM-CandidateLocal relationship type.
In the scenario below, Good Health Clinic has registered John Doe born Jan 1 1980 with ID 1230493. The MDM layer has constructed a master record. A subsequent registration by HIV Health Clinic for John Doe, born sometime in 1980 with ID 3029402 as registered after.
Assuming that the match configuration was setup such that the HIV record had a match score below "DEFINITE" match, the MDM plugin would establish a new MASTER which contains one LOCAL. That LOCAL would also be related to the MASTER from Good Health Clinic with relationship type MDM-CandidateLocal.
This candidate link exists until:
A subsequent update from either the HIV Health Clinic (to record 3029402) or Good Health Clinic (to record 1230493) means that the patients no longer meet threshold for match.
The match configuration is updated, which scores the link below the threshold for probable match.
An administrator establishes a new link between the HIV Clinic and the MASTER of MDM-IgnoreCandidate (which indicates a known false-match).
The MDM solution permits the establishing of a Record Of Truth (ROT). The Record Of Truth is a new local instance which belongs to the SYSTEM and can only be updated when the security principal is permitted MDM Record Of Truth.
A ROT record is a special pointer at a LOCAL whereby the LOCAL points to the MASTER record, and the MASTER points at the ROT with relationship type of MDM-RecordOfTruth.
It is a commonly asked how the solution operates when a sensitive LOCAL record is shared with common health infrastructure. In the case of SanteDB's iCDR, when a MASTER record has multiple LOCALS the information returned to a caller is a synthesized copy of data within the LOCAL records.
The synthetization process uses a most-restrictive policy enforcement mechanism before considering a local for inclusion in the result. In the example illustrated above, the information sourced from the HIV Health Clinic is tagged as TABOO information.
When a caller asks the CDR for the MASTER, the MDM service will call the IPolicyDecisionService and ask for a decision on each of the flagged policies in each of the locals and will return either:
The UNION of data from both Good Health Clinic and HIV Health Clinic when TABOO has a GRANT, or
Only data from Good Health Clinic when TABOO policy outcome is DENY, or
Only the data from Good Health Clinic and an indicator of elevation required (i.e. indicator more data is present) when the TABOO policy outcome is ELEVATE.
The MdmDataManagementService should be configured in your application context. Upon start, this daemon will read the contents of the ResourceMergeConfigurationSection to determine the appropriate instances of MdmResourceListener<T> to construct and register with the provider.
For example, given a configuration as provided below
The MdmDataManagementService on start would register two resource listeners for Patient and Place. It would furthermore, instruct each resource listener to use the specified match configuration for detecting candidate local<>master linkages.
The resource listener instances created by the data management service subscribe to the repository events for the indicated type. The resource listener receives an event broadcast from the repository service whenever an event occurs and takes appropriate actions.
The Saving and Inserting events of the repository service are subscribed on service start. Whenever data through a repository is being actioned the events are raised and the following actions occur on the MDM Resource Listener:
The instances are validated through OnPrePersistenceValidate() method. Here the process ensures:
The caller is not attempting to update a MASTER record. If it is, the appropriate LOCAL for that principal is exchanged.
If the caller is attempting to create a RECORD OF TRUTH , it has appropriate permission to do so
When a repository's Find() or Get() methods are called the repository will call the Retrieving and Querying event handlers. The MDM resource listener for that repository will perform the following operations:
Cancel the default path of the repository
Re-write the HDSI expression tree to query attributes related to the ROT or a LOCAL
The resource listener also subscribes to the Retrieved and Queried event handlers where any local objects which were fetched from the underlying data persistence layer are synthesized using their MASTER links (and appropriate policies applied).
The following section outlines several common behaviors and patterns to assist in understanding how MDM works in SanteDB.
When the CDR receives a request to create a new entity which is under MDM control, as shown below.
The source record is issued a new UUID
The MDM layer will attempt to determine if the source record matches any MASTER records that currently exist within the database (using the resource merge configuration).
If no matching MDM MASTER is found, then the a new MASTER record is created and the SOURCE linked to the MASTER with its own UUID.
Any future queries based on the demographics will result in the MASTER_A record being returned and synthesized from the source records according to the synthesization rules.
When the CDR receives a registration request for a new object which is under MDM control, such as shown below:
The source record is issued as new UUID
The IRecordMatchService is called with the specified configurations. If this process classifies a record as MATCH and AutoLink is turned on for that match configuration
The SORUCE is linked to the MASTER with relationship MDM-Master
A query for EID A123 would now result in a single result with the synthesized data from both sources and links to the sources where the data was obtained.
When the CDR receives a request to create an object with similar attributes however as above, however:
The attribute score from the fuzzy matching engine falls below the threshold of a definite match, or
The automatic linking feature for the match configuration is disabled
Such as the patient illustrated below.
The behavior is as follows:
The SOURCE is issued a new UUID
A new MASTER is created with a new UUID
The SOURCE is linked to the new MASTER
The relationship type is MDM-Master
When the CDR receives a request to update a source record, it does so against the source (or if the update was attempted against the MASTER the SOURCE is created or located). When this occurs, the matching is re-run and if determined that the records now match the relationships are re-calculated.
For example, given this update to SOURCE_C.
The SOURCE_C record would be updated to match and the matching re-run, it may be determined that SOURCE_C is in fact the same person as MASTER_A
In this case, SOURCE_C is DETACHED from MASTER_C and then attached to MASTER_A.
The CDR also provides interfaces for manually reconciling candidate matches. Take for example, an instruction to reconcile SOURCE_C and MASTER_A.
In this method (also known as a LOCAL>MASTER merge) the MDM-Candidate link is translated into a MDM-Master and the classification set to VERIFIED.
Callers can directly manipulate the relationships using the IRepositoryService<EntityRelationship> services to implement custom logic for merging and linking. By default the MDM layer registers IRecordMergeService<T> instances which implement a default behavior for external calls to MERGE data.
A LOCAL>MASTER link operation is initiated by calling Merge() in IRecordMergeService<T> , and passing a UUID of a MASTER record and the linked duplicate UUIDs that are either:
The explicit UUIDs of local records (i.e. the UUID pointing at the local record), or
The UUID of masters where the caller does not have Merge MDM Master permission
This operation works by unlinking the local/duplicate record relationships (of MDM-Master ) and re-establishing the link on the locals to the surviving master. This is a form of linking where neither the master nor the local records are merged.
For example, if a principal has Write MDM Master permission, and issues the following ADT^A40 :
The process would be:
Load the record XXXXX in domain TEST (MASTER)
Load the record YYYYY in domain TEST (MASTER)
Call Merge() for MASTER>MASTER
A MASTER to MASTER merge is the process whereby one master record is merged into another, and all associated LOCAL relationships are migrated to the survivor. Callers may only initiate a master merge when the principal carries the Merge MDM Master policy permission, otherwise an alternate merge strategy is used.
The process for performing a master merge is:
Load record XXXX in domain TEST (MASTER)
Load record YYYY in domain TEST (MASTER)
Call Merge() for MASTER>MASTER
A local merge occurs when a source system indicates it has resolved duplicates in its own database issues an appropriate merge request to the iCDR. The local merge is the default operation whenever the caller is not granted explicit permission to perform MDM merges on the server.
The process for performing a local merge is:
Load record XXXX in domain TEST (MASTER)
Load record YYYY in domain TEST (MASTER)
Call Merge() for MASTER>MASTER
As part of improving documentation of the SanteDB release documentation, each code named release will have its development versions (odd number minor versions) on a single page with the official versions (even number minor versions).
Since this new method of documenting releases has only started with 2.1.170, this page is partial. One should consult the GitHub release schedules for more information.
Release Assets: http://santesuite.org/assets/uploads/santedb/community/releases/2.2.3/
Fixes bug with the deletion of pub-sub subscriptions from the user interface
Fixes un-delete operation on the pub-sub subscription manager
Adds persistent job state service
Adds default implementation of job state service (local XML file - work is being performed on the shared state service).
Release Assets:
This release of SanteDB builds on the fixes in 2.2.0 and corrects adds the following enhancements:
Fixes bug with blocking on metaphone and dmetaphone on PostgreSQL (improper parameter exception)
Adds better descriptions to the SanteGuard view screens for user activity and audit trail.
Updates to the audit detail view which uses the registered resource viewer (in order to open more types of data)
Release Assets:
This is the second official stable release of the .NET Standard version of the SanteDB platform and related assets. The products which are included in the 2.2.0 release of SanteDB are:
SanteDB iCDR Server 2.2.0
SanteMPI iCDR Server 2.2.0
SanteDB dCDR Web Access Gateway 2.2.0
SanteDB dCDR Software Development Kit 2.2.0
This release includes all major upgrades and updates to the SanteDB platform from the 2.1.x Community Technology Preview release streams and is suitable for testing. There will be a normalization period for this release, however, since it is an official release of SanteDB iCDR it will receive an official maintenance branch and will have generally, more stable APIs.
Following the release of the 2.2.0 all future 2.1.x Community Technology Previews will be for the Regina release.
SanteDB/SanteMPI Core iCDR Enhancements
Enhancements to HL7 FHIR interface:
Support for FHIR operations ($operation)
Release Assets:
This is a minor release which correct small performance and caching issues. Included in this fix are:
Addresses over-threading of the rest and internal background job thread pool (adds option to use .NET thread pool for all services)
Addresses under-caching issues where client using If-None-Match would not receive a cached version but would hit the database.
Fixes issues with the new version of NPGSQL related to handing of DateTime and DateTimeOffset
Release Assets:
This version is a patch for the 2.1.170 release. It fixes the following issues found in 2.1.170:
Fixes logic for timer jobs based on calendar to reduce the "greedyness" of the jobs
Fixes display caching issue (was an issue with the BulkPurge function) so new data is properly rendered.
Fixes some threading issues with the .NET ThreadPool on background matching
Release Assets:
Added ability to schedule IJob jobs within the administrative panel
Added job descriptions to the job screen
Added ability to more efficient background matching on the match job
The entity relationship graph on the patient profile screen will show duplicate links
Caching of some entities shows erroneous data on the relationship graphs. Validation of the state at database reveals this is a caching issue.
Running the background matching task in Linux or Docker can result in CPU use at 100% as the ThreadPool and ConcurrentQueue<T> implementations in Mono framework appear to be implemented in a slightly, less efficient manner.
The new version of the SanteDB _any parameter handling uses the free-text engine. In PostgreSQL this method calls the function fti_tsquery function. This function is passed a single text parameter and is expected to return a tsquery structure.
By default, 2.1.170 uses the websearch_to_tsquery method. This search method was introduced in PostgreSQL 11 and converts a search string into a tsquery method. Implementers may wish to change this behavior if:
They are using PostgreSQL < 11
They wish to use other free-text search configurations (other than English)
They wish to support other lexeme or advanced functions.
Implementers can use plain free-text search parsing by altering the function fti_tsquery to use plainto_tsquery as:
Implementers can allow users to access advanced features supported by the PostgreSQL freetext search engine. The method below illustrates taking a search term and splitting the term by spaces and appending each back to a query.
The method above would convert John Smith Lincoln FR-403 to the TSQUERY expression: John & Smith & Lincoln & FR-403 . This simple implementation permits search by prefix/wildcard: Joh:* Sm:* converted to Joh:* & Sm:*.
Users can implement custom search term parsing/filtering based on their use case and context.
The SanteDB matching job has been updated to modify the behavior of the job based on the configuration of the environment it is running in. The table below provides a summary of this change:
When running the background matching job in Docker , users may experience periods of time where the available threads in the thread pool are consumed by the worker tasks. This appears to be the Mono implementation of ConcurrentQueue and/or the method in which Mono allocates threads.
Users may experiment with the MONO_THREADS_PER_CPU environment variable to tune the performance of their deployment.
SELECT *
FROM
masters AS master
LEFT JOIN locals AS local
WHERE
local.identifier[SSN].value = '203-204-3049'
UNION ALL
SELECT *
FROM
locals AS local
WHERE
local.name.component[Given].value = 'John'
AND local.name.component[Family].value = 'Smith'
AND local.dateOfBirth = '1980-03-02'
AND local.gender = 'Male'SDB_DATA_POLICY_FORBID=Patient.religion;Patient.vipStatus=2.25.349498SDB_FEATURE=...;LOG;...
# Set the Logging Level
SDB_LOG_LEVEL=Error|Warning|Informational|LogAlwaysSDB_FEATURE=...;DATA_POLICY;...
# Set the action to apply when sensitive data is disclosed
SDB_DATA_POLICY_ACTION=hide|redact|nullify|error|audit|none
# Set the resources on which policies should be applied
SDB_DATA_POLICY_RESOURCE=Resource=action;Resource=action;...
# Set forbidden properties (properties which should not be disclosed, queried, or collecected
# unless the user has the specified policy OID (if no policy is specified the attribute is forbidden
SDB_DATA_POLICY_FORBID=Resource.property;Resource.property=policyOID;...SDB_FEATURE=...;AUDIT_REPO;...
# Sets the RW connection
SDB_AUDIT_REPO_RW_CONNECTION=connection
# Create Connection Strings
SDB_DB_connection_PROVIDER=Npgsql
SDB_DB_connection=server=x;password=y;SDB_FEATURE=...;ADO;...
# Sets the Read/Write Master Connection
SDB_ADO_RW_CONNECTION=rwconnection
SDB_DB_rwconnection_PROVIDER=Npgsql
SDB_DB_rwconnection=server=x;password=y
# Sets the Read only Secondary Connection
SDB_ADO_RO_CONNECTION=roconnection
SDB_DB_roconnection_PROVIDER=Npgsql
SDB_DB_roconnection=server=x;password=y
# Set whether the provider will use fuzzy totals
# using fuzzy totals increases performance and merely indicates "another page is available"
# rather than counting the total result set size
SDB_ADO_FUZZY_TOTAL=true|falseSDB_FEATURE=...;ADO_FTS;...SDB_FEATURE=...;RAMCACHE;...
# The time that cache entries should remain cached before RAM is cleaned
# in the format DAYS.HOURS:MINUTES:SECS
SDB_RAMCACHE_TTL=0.1:0:0SDB_FEATURE=...;REDIS;...
# The time that cache entries should remain cached before RAM is cleaned
SDB_REDIS_TTL=0.1:0:0
# The address/port of the REDIS server
SDB_REDIS_SERVER=server:portSDB_FEATURE=...;SEC;...
# The password validation/complexity validation regex
SDB_SEC_PWD_REGEX=regular expression
# The length of sessions issued by the service
SDB_SEC_POL_SESSION=0.1:0:0
# The number of invalid authentications before a user/device/application is locked
SDB_SEC_POL_LOCK=4
# Sets the secrets for the SanteDB data signing services
# You can specify either HS256, RS256 or RS512 signing algorithms
# Note: You will need to customize your own SanteDB iCDR instance with a custom
# dockerfile if you choose to use RS256 as the certs need to be installed
# into the mono keystore.
SDB_SIG_default=hs256:A_SECRET_PASSPHRASE_FOR_HMAC256_DATA_SIGNATURES
SDB_SIG_other=rs256:THUMBPRINT_OF_YOUR_RSA_CERT
SDB_FEATURE=...;OPENID;...
# One or more claims which client systems can send. Default are:
# scope;PolicyOverride;ResourceId;PurposeOfUse;FacilityId;OrganizationId
SDB_OPENID_CLAIMS=scope;PolicyOverride;PurposeOfUse
# If you need to use a custom token type
SDB_OPENID_TOKEN=bearer
# When true, allows client_credentials grant without sending an
# X-Device-Authorization header or an X509 client certificate
SDB_OPENID_INSECURE_CLIENT_AUTH=true|false
# The issuer ID of this IdP
SDB_OPENID_ISSUER=myrealm
# The key to use for signing the JWT key. Note: When using HMAC256
# the client secret is used to sign the JWT
SDB_OPENID_JWT_SIG_KEY=xxxx
# Set the address (port/url) where OpenID should be available
SDB_OPENID_LISTEN=http://0.0.0.0:8080/authSDB_FEATURE=...;HDSI;...
# The base URL where the HDSI should be bound
SDB_HDSI_LISTEN=http://0.0.0.0:8080/hdsi
# The authentication scheme to use for the HDSI
SDB_HDSI_AUTH=TOKEN|BASIC|NONE
# Enables or disables CORS
SDB_HDSI_CORS=true|falseSDB_FEATURE=...;AMI;...
# The base URL where the AMI should be bound
SDB_AMI_LISTEN=http://0.0.0.0:8080/ami
# The authentication scheme to use for the AMI
SDB_AMI_AUTH=TOKEN|BASIC|NONE
# Enables or disables CORS
SDB_AMI_CORS=true|falseSDB_FEATURE=...;BIS;...
# The base URL where the AMI should be bound
SDB_BIS_LISTEN=http://0.0.0.0:8080/bis
# The authentication scheme to use for the BIS
SDB_BIS_AUTH=TOKEN|BASIC|NONE
# Enables or disables CORS
SDB_BIS_CORS=true|false
# Sets the maximum number of rows a single BIS report can retrieve from the database
SDB_BIS_MAX_RESULTS=50000SDB_FEATURE=...;FHIR;...
# The base URL where the FHIR should be bound
SDB_FHIR_LISTEN=http://0.0.0.0:8080/fhir
# The authentication scheme to use for the FHIR
SDB_FHIR_AUTH=TOKEN|BASIC|NONE
# Enables or disables CORS
SDB_FHIR_CORS=true|false
# When emitting links for references, the external URL to use
SDB_FHIR_BASE=http://external-url/fhir
# The resources which should be exposed on the FHIR interface
SDB_FHIR_RESOURCE=Patient;Practitioner;Organization;...
# Extensions which should be enabled
SDB_EXTENSION=http://hl7.org/fhir/StructureDefinition/patient-citizenship;http://hl7.org/fhir/StructureDefinition/patient-religion;...SDB_FEATURE=...;HL7;...
# Indicates how the sending application should be authenticated.
# Note: When using SLLP the client certificate is used to authenticate the device
# . this setting impacts how the application is authenticated.
# Note: When using regular LLP, the client and device are authenticated using this
# mechanism
# Values:
# MSH8 - Device authentication occurs via SSL
# if regular LLP, device authentication occurs via MSH-3|MSH-4 and MSH-8
# SFT4 - Device authentication occurs via SSL
# if regular LLP, device authentication occurs via MSH-4 and MSH-8
# and application authentication occurs via SFT-4
SDB_HL7_AUTHENTICATION=MSH8|SFT4|NONE
# The namespace ID where internal UUIDs for patients are exposed (if opted)
SDB_HL7_LOCAL_DOMAIN=MY_DOMAIN
# If PID segment field for SSN is used, maps the value in that field to a domain
SDB_HL7_SSN_DOMAIN=SSN
# The port and protocol to listen on
# LLP = Unsecure LLP
# SLLP = SSL + LLP
# TCP = TCP stream only
# The bind port is also specified here.
SDB_HL7_LISTEN=llp://0.0.0.0:2100
# The amount of time to keep the TCP channel open after sending a response
# this is used in batch or streaming mode.
SDB_HL7_TIMEOUT=100
# If using SLLP, this is thumbprint of the server's certificate
SDB_HL7_SERVER_CERT=thumbprint
# If using SLLP with client authentication via TLS, this is the thumbprint
# of a CA or chain to use for client authentication
SDB_HL7_CLIENT_AUTH=thumbprintSDB_FEATURE=...;PUBSUB_ADO;...
# If the pub-sub subscriptions are being stored in a database different
# than the main database , indicate the name of the connection string here
SDB_PUBSUB_ADO_RW_CONNECTION=connectionStringSDB_FEATURE=...;MATCHING;...
SDB_MATCHING_MODE=WEIGHTED|SIMPLEFROM santesuite/santedb-mpi:latest
COPY ./my_match_config.xml /santedb/match/my_match_config.xmlSDB_FEATURE=...;MDM;...
SDB_MDM_RESOURCE=Patient;Person;...SDB_FEATURE=...;EMAIL;...
# The SMTP server to use for sending mail
EMAIL_SERVER=smtp://server.com:port
# The "from" address for all e-mails being sent by SanteDB
[email protected]
# True if the STMP server requires TLS
EMAIL_TLS=true
# If the SMTP server requires authentication - the username
EMAIL_USER=key_to_authenticate_smtp_if_needed
# If the SMTP server requires authentication - the password
EMAIL_PASSWORD=password_to_authenticate_smtp_if_needed
# The Administrative contacts which should be CC'd on relevant admin events
[email protected];[email protected]SDB_FEATURE=...;SIGN;...
# Set the primary algorithm for the signing of data
SIGN_ALG=HS256|RS256
# Set the secret if using HMAC256 signing
SIGN_HS256_SECRET=A SECRET PASSPHRASE
# Set the subject name of a new self-signed certificate to generate
SIGN_RS256_GEN=SUBJECT_NAME_OF_CERTIFICATE
# Set the thumbprint of an existing certificate to use for signing
SIGN_RS256_CERT=thumbprint of existing certSDB_FEATURE=...;IHE_PIXM;...SDB_FEATURE=...;IHE_PDQM;...SDB_FEATURE=...;IHE_PMIR;...SDB_FEATURE=...;IHE_PIX;...SDB_FEATURE=...;IHE_PDQ;...SDB_FEATURE=AUDIT_SHIPPING;ADO;AUDIT_REPOSDB_DB_PSQL="server=location;user=user;password=password;database=db"
SDB_DB_PSQL_PROVIDER=Npgsql
SDB_DB_AUDIT=" ... "SDB_FEATURE=CORE_CDR,CACHE
# Caching Mode = REDIS | LOCAL
SDB_CACHE_MODE=REDIS
# Pointer to redis server
SDB_CACHE_REDIS_SERVER=sdb-redis:6379
# Expire cache entries after X timestamp
SDB_CACHE_EXPIRE=PT1Hversion: "3.3"
services:
db:
image: postgres
container_name: sdb-postgres
ports:
- "5432:5432"
environment:
POSTGRES_USER: santedb
POSTGRES_PASSWORD: SanteDB123
restart: always
santedb:
image: santesuite/santedb-icdr:latest
container_name: santedb-icdr
environment:
- SDB_FEATURE=LOG;DATA_POLICY;AUDIT_REPO;ADO;PUBSUB_ADO;RAMCACHE;SEC;SWAGGER;OPENID;FHIR;HL7;HDSI;AMI;BIS
- SDB_DB_MAIN=server=sdb-postgres;port=5432; database=santedb; user id=santedb; password=SanteDB123; pooling=true; MinPoolSize=5; MaxPoolSize=15; Timeout=60;
- SDB_DB_AUDIT=server=sdb-postgres;port=5432; database=auditdb; user id=santedb; password=SanteDB123; pooling=true; MinPoolSize=5; MaxPoolSize=15; Timeout=60;
- SDB_DB_MAIN_PROVIDER=Npgsql
- SDB_DB_AUDIT_PROVIDER=Npgsql
- SDB_DELAY_START=1000
ports:
- "8080:8080"
- "2100:2100"
depends_on:
- db
restart: alwaysservices:
# ... truncated for space ...
santedb:
image: santesuite/santedb-icdr:latest
# .. truncated ...
volumes:
- santedb-data:/santedb/data
volumes:
santedb-data:FROM santedb-icdr:latest
RUN mkdir /myproject
COPY myconfig.xml /myproject/myconfig.xml
WORKDIR /santedb
EXPOSE 2100/tcp
EXPOSE 8080/tcp
CMD ["mono","/santedb/SanteDB.Docker.Server.exe","/myproject/myconfig.xml"]FROM santedb-icdr:latest
COPY custom.pak /santedb/applets/custom.pakversion: "3.3"
services:
db:
image: postgres
container_name: sdb-postgres
ports:
- "5432:5432"
environment:
POSTGRES_USER: santedb
POSTGRES_PASSWORD: SanteDB123
restart: always
santedb:
image: santesuite/santedb-mpi:latest
container_name: santedb-mpi
environment:
- SDB_FEATURE=LOG;DATA_POLICY;AUDIT_REPO;ADO;PUBSUB_ADO;RAMCACHE;SEC;SWAGGER;OPENID;FHIR;HL7;HDSI;AMI;BIS;MDM;MATCHING;IHE_PIXM;IHE_PDQM;IHE_PMIR
- SDB_MATCHING_MODE=WEIGHTED
- SDB_MDM_RESOURCE=Patient=org.santedb.matching.patient.default
- SDB_MDM_AUTO_MERGE=false
- SDB_DB_MAIN=server=sdb-postgres;port=5432; database=santedb; user id=santedb; password=SanteDB123; pooling=true; MinPoolSize=5; MaxPoolSize=15; Timeout=60;
- SDB_DB_AUDIT=server=sdb-postgres;port=5432; database=auditdb; user id=santedb; password=SanteDB123; pooling=true; MinPoolSize=5; MaxPoolSize=15; Timeout=60;
- SDB_DB_MAIN_PROVIDER=Npgsql
- SDB_DB_AUDIT_PROVIDER=Npgsql
- SDB_DATA_POLICY_ACTION=HIDE
- SDB_DELAY_START=5000
ports:
- "8080:8080"
- "2100:2100"
depends_on:
- db
restart: alwaysAn administrator manually indicates that the HIV Health Clinic record is a known match to the MASTER (in which case the MDM-MasterRecord link is removed and updated (as shown below).
Call the matching service and attempt to establish whether the LOCAL is a candidate for an existing record
Appropriately obsolete/create resource links between the objects.
Cancels the caller (i.e. overwrites the default call path)
Returns a BUNDLE which is treated as a transaction on the persistence layer.
The classification of this relationship is AUTO
The weighting of the match is stored
The classification of the relationship is AUTO
The SOURCE is linked to the suspected MASTER
The relationship type is MDM-CandidateLocal
The classification of the relationship is AUTO
The score of the match is stored as the relationship strength
MASTER
MASTER
Local Merge
Local/Master Relink
Master Merge
Client has Write MDM Master so record XXXXX remains the target of the merge.
Client does not have Merge MDM Master so record YYYYY is resolved to LOCAL record for TEST_HARNESS at site TEST (LYYYY)
Merge proceeds as LOCAL>MASTER
LYYYY is disconnected from master YYYY
LYYYY is attached to master XXXX
If no further locals point at YYYY it is obsoleted.
Client has Write MDM Master so record XXXX remains target of merge
Client has Merge MDM Master so record YYYY remains source of merge
Merge proceeds:
All MDM-Master associations previously pointing at YYYY are rewritten to XXXX
All identifiers directly on YYYY master record are copied to XXXX
YYYY is obsoleted
Client does not haveWrite MDM Master so a local record for XXXX is resolved (LXXXX)
Client does not have Merge MDM Master so a local record for YYYY is resolved (LYYYY)
If LYYYY and LXXXX were resolved, then the merge occurs:
The record LYYYY is obsoleted
All identifiers from LYYYY are copied to LXXXX so that any query to LYYYY are resolved to the survivor
Victim Type
Survivor Type
No Permission
Write MDM
Merge MDM
LOCAL
LOCAL
Local Merge
Local Merge
Local Merge
LOCAL
MASTER
Local Merge
Local/Master Relink
Local/Master Relink
Adds link to the detailed audit entry in the audit trail and activity tabs
Fixes issue with job scheduling (present in 2.2.0) setting the appropriate type of schedule in the xcron.xml file.
Adds ability to download match configuration source files in XML to port the configuration over to other systems.
Implementations of $match, $validate, $ihe-pix, $process-message operations
Support for FHIR messaging bundles and transaction bundles
Support for FHIR subscriptions and FHIR push notifications
Enhanced support for FHIR resources Patient, RelatedPerson, Organization, Practitioner
Implementation of IHE PMIR messaging
Enhancements to HL7 Version 2 Interface:
Enhanced support for HL7 Z-Segments in messages
Enhanced processing of HL7 datatypes and handling of errors
New MDM Layer
Refactored complete MDM layer to support establishment of ROT from determiner codes
Improved functions for MDM auto-linking and candidate resolution
Support for unlink and re-link operations
Implementation of MDM enhanced HDSI operations $mdm-link, $mdm-rematch, $mdm-ignore.
Enhancements to HDSI
Support for HDSI operations via $operation name
Support for HDSI deep-linked child records (cleaned up implementation to be pluggable)
Enhanced HTTP caching for If-None-Match
Enhancements to matching engine
Implementation of update/save configuration files over HTTP APIs
New blocking algorithms for similarity and similartiy_lev
Added new blocking logic to allow for specifying ignore keys on master or sources
Added diagnostics / debugging / tracing collectors
Enhancements to probes interfaces
New probes implemented for CPU, Memory, ADO.ET connection, thread pooling, etc.
Enhanced thread pools for REST APIs and core functions which can scale-up or scale-down threads (without polluting the .NET threadpool)
Updated documentation of core API classes and interfaces
Automatically seed/create and update/patch database schemas
Enhanced BIS functions for storing materialized
Enhanced IJob management, scheduling and control
New Configuration Tool which can be used for setting/modifying settings on the iCDR host in Windows or Linux
Added classification, strength, and role codes to entity, act relationships and participations.
Implementation of MSMQ queue provider
SanteDB Administrative Interface Enhancements
System Administration Screen Additions
System Probes manager screen
Dispatcher queue management screen
Pub/Sub management screen
Security Administration Enhancements
User, group, device, and application screens now modular (have extension points)
Re-envisioned audit viewing screen and audit center
MPI Management Screens
Enhanced entity relationship diagrams
Master Data Management screens for match/merge/unlink
SanteMPI matches panel
SanteDB dCDR Web Access Gateway Enhancements
Self-restart of web access gateway after configuration
Ability to run in Docker, Linux or Windows service environments
SanteDB dCDR SDK Enhancements
Enhanced pakman.exe manager
Supports local package repository resolution for applet debugger
Supports publish to remote package repository / server
Enhanced applet debugger environment which can load references by name
New vocabulary import tool which can import FHIR>Dataset or CSV>Dataset (for reference terms only)
New patient importer which can import ONC or FEBRL datasets
Fixes issue where scheduled tasks (starting before date of startup) are executed on start rather than waiting until the next execution window
Adds performance probes for:
.NET Thread Pool I/O and Worker Threads
ADO.NET Database Connections (active read/write, statements being executed)
Adds ability to change blocking instructions to operate on MASTER or SOURCE mode
Fixes issues with ignored records when blocking is performed in SOURCE mode
Adds new date_trunc filter expression for HDSI queries. This is more efficient than date_diff in that it allows date column indexes to be used.
Increases performance of levenshtein filter function on PostgreSQL by changing logic from : where levenshtein(column_name, ?) < value to where column_name % ? and levenshtein(column_name, ?) < value which allows PostgreSQL to use the GIN indexing to reduce the number of rows passed to levenshtein function.
IThreadPoolService and changed the way that the probe data is displayed.Added useLowerLayer attribute to the <blocking> instructions in match configuration. This allows for configurations to bypass master synthesization (see notes below)
Added configuration to the match screens in the administrative panel to allow for selection of absolute scoring or normalized scoring.
Added ability to customize the free-text algorithm used for translating search terms into tsquery results (see:
Fixed matching engine bug where the record's self was not excluded from result.
Fixed matching auto-merge bug (see above fix for cause)
There is a display bug for entities which have been auto-merged using the $mdm.auto-link flag where the resulting source record will display multiple relationships (indicating they are active when they are not).
4+ Cores
Single-Threaded Load Multi-Threaded Match
Windows
< 4 Cores
Multi-Threaded Load (PLINQ) Single Threaded Match
4+ Cores
Multi-Threaded Load (PLINQ) Multi-Threaded Match
Docker / Mono
< 4 Cores
Single-Threaded Load Single Threaded Match
Place
Places the Place resource into MDM storage management. This is useful for centralized Geographic or Facility Registries
Organization
Organizations (such as companies, government agencies, etc.) in MDM control.
RAMCACHE
In-Process Memory Cache (see: Configuration Notes)
REDIS
REDIS based shared cache (see: Configuration Notes)
SEC
Core Security Functions (PIP, PDP, PEP)
SWAGGER
OpenAPI / Swagger Metadata Endpoint (see: Configuration Notes)
OPENID
OAUTH 2.0 / OpenID IdP Provider (see: Configuration Notes)
MDM
Master Data Management Functions (see: Configuration Notes)
FHIR
HL7 FHIR Endpoint (see: Configuration Notes)
HL7
HL7 Version 2.x Endpoint (see: Configuration Notes)
HDSI
Core Health Data Service Interface (see: Configuration Notes)
AMI
Administrative Management Interface (see: Configuration Notes)
BIS
Business Intelligence (reporting/query set/etc.) interface (see: Configuration Notes)
MATCHING
Internal SanteDB Matching Engine (see: Configuration Notes)







<section xsi:type="ResourceMergeConfigurationSection">
<resources>
<add type="Patient" matchConfiguration="org.santedb.smpi.matching.default" autoMerge="false" />
<add type="Place" matchConfiguration="org.santedb.shfr.matching.default" autoMerge="false" />
</resources>
</section>MSH|^~\&|TEST_HARNESS^^|TEST^^|CR1^^|MOH_CAAT^^|20141104174451|DEVICESECRET|ADT^A40^ADT_A39|TEST-CR-16-30|P|2.3.1
EVN||20101020
PID|||XXXXX^^^TEST||JONES^JENN^^^^^L||198401|F|||||||||||
MRG|YYYYY^^^TESTCREATE OR REPLACE FUNCTION public.fti_tsquery(search_term_in text)
RETURNS tsquery
LANGUAGE plpgsql
IMMUTABLE
AS $function$
BEGIN
RETURN PLAINTO_TSQUERY('english', search_term_in);
END;
$function$
;
CREATE OR REPLACE FUNCTION public.fti_tsquery(search_term_in text)
RETURNS tsquery
LANGUAGE plpgsql
IMMUTABLE
AS $function$
BEGIN
RETURN TO_TSQUERY('english', ARRAY_TO_STRING(STRING_TO_ARRAY(SEARCH_TERM_IN, ' '), ' & '));
END;
$function$
;
Detailed match overview screen
Resolve/Ignore functions on summary view
Reports for match details including full match export (< 10k rows)
SanteMPI Match Configuration
Edit/View match configuration metadata
Edit/View match blocking configuration
Edit/View match scoring with compete algorithm selection for each attribute
Edit/View match classification stage for classifying results
Test match configuration functions
New free-text and advanced (per-field) search
New power search function

























The data dictionary for entities which store the SanteDB concept dictionary are illustrated below.
The concept class table stores a complete list of concept classifications.
Property
Type
The Concept table stores the key data related to a concept. The Concept table represents immutable concept properties that cannot be changed once a concept is created.
The concept version table is used to store mutable properties of a concept. All edits to a concept’s attributes result in a new version being created in the ConceptVersion table.
The concept set entity is used to represent logical groupings of concepts which are related in some manner. These typically are used to drive validation (i.e. gender field must be bound to a concept in the gender concept set) or data-entry fields.
The concept name table represents a series of human readable names for the concept at a particular version. This facilitates searches as well as translation.
The concept relationship table is used to link concepts to one another. Concept relationships can represent equivalency between concepts, parent/child relationships, etc.
The concept relationship type represents allowed types of relationships that a concept can have.
A reference term represents a wire level code that can be used to represent the concept.
An associative entity that links a concept to one or more reference terms and indicates the strength of the map.
The code system table represents a master list of all code systems from which a reference term can be drawn.
Like the ConceptName table, the reference term display name table is used to identify human readable display names associated with the reference term.

The instant in time when the concept version became active (was created). Should default to the current database timestamp.
CreatedBy
[1..1]
UUID
The user who was responsible for the creation of the version, or the system user if the installation process created the concept version.
ObsoletionTime
[0..1] ? (> CreationTime)
DATETIME
When present, identifies the time when the concept version did become obsolete. This is used whenever a new version is created, the old version is obsoleted.
ObsoletedBy [0..1] ?(ObsoletionTime)
UUID
Indicates the user who was responsible for the obsoletion of the record.
ReplacesVersionId [0..1]
UUID
Identifies the concept version that the current version of the concept replaces.
ConceptClassId [1..1] = Other
UUID
Identifies the classification of the concept as of the version tuple.
Mnemonic [0..1]
VARCHAR
A unique mnemonic used by the system to lookup the concept. The system mnemonic is primarily used for validation purposes where a concept’s identifier does not represent a consistent identifier across deployments.
The URL which defines the concept set.
Oid
[1..1]
VARCHAR
The OID which defines the concept set.
The version of the concept when the concept name was obsoleted.
Name [1..1]
VARCHAR
The human readable display name for the concept.
LanguageCode [1..1] ~ ISO639-2 = en
CHAR
The ISO639-2 language code for the concept display name.
PhoneticCode [0..1]
VARCHAR
The phonetic code for the display name. This is used for phonetic “sounds-like” searches of concepts.
PhoneticAlgorithmId [0..1] ?(PhoneticCode)
UUID
The phonetic algorithm used to generate the phonetic code. This allows deployments to use METAPHONE, SOUNDEX or custom phonetic algorithms appropriate for the language used.
Identifies the version of the source concept where the relationship did become active.
ObsoleteVersionSequenceId [0..1]
UUID
Identifies the version of the source concept where the relationship is no longer active.
RelationshipTypeId [1..1]
UUID
Identifies the type of relationship the concepts have.
The version of the concept where the reference term map became obsolete.
ReferenceTermId [1..1]
UUID
The reference term which is associated with the concept.
RelationshipTypeId [1..1]
UUID
Identifies the relationship (or strength) that the reference term has with the concept. For example: SAME_AS, NARROWER_THAN, etc.
The unique assigning authority of the particular code system. Example CVX or SNOMEDCT
CreationTime [1..1]
DATETIME
The time when the code system entry was created. Default to the current timestamp in the RDBMS.
CreatedBy [1..1]
UUID
The user that was responsible for the creation of the code system.
ObsoletionTime [0..1] ? (>CreationTime)
DATETIME
When populated, indicates the time when the code system record is obsolete.
ObsoletedBy [0..1] ?(ObsoletionTime)
UUID
Identifies the user who was responsible for obsoleting the record.
ObsoletionReason [0..1] ?(ObsoletionReason)
VARCHAR
The textual description as to why the record was obsoleted.
Url [1..1]
VARCHAR
A URI that uniquely identifies the code system. This is primarily used when exposing the code system over REST interfaces.
Version [0..1]
VARCHAR
A textual description of the version of the code system that this record represents.
The human readable name for the reference term.
CreationTime [1..1]
DATETIME
The time when the display name became active.
CreatedBy [1..1]
UUID
Identifies the user that was responsible for the creation of the reference term display name.
ObsoletionTime [0..1] ?(>CreationTime)
DATETIME
When present, identifies the time when the record should no longer be used.
ObsoletedBy [0..1] ?(CreationTime)
UUID
Identifies the user that was responsible for obsoleting the display name.
ObsoletionReason [0..1] ?(CreationTime)
VARCHAR
A textual description as to why the display name was obsoleted.
PhoneticCode [0..1]
VARCHAR
Represents a phonetic code that can be used in “sounds-like” queries.
PhoneticAlgorithmId [0..1] ?(PhoneticCode)
UUID
Identifies the phonetic algorithm that was used to generate the phonetic code. This allows METAPHONE or SOUNDEX or some other custom language appropriate phonetic algorithm to be used.
Description
ConceptClassId [1..1]
UUID
Represents a unique identifier for the concept classification.
Name [1..1]
VARCHAR
Represents a human readable name for the concept classification. Example: Class Codes
Mnemonic [1..1]
VARCHAR
Represents a system mnemonic for the concept class. The mnemonic does not change even if the human readable Name column does.
Property
Type
Description
ConceptId [1..1]
UUID
A unique identifier for the concept.
IsSystemConcept [1..1] = false
BIT
An indicator which identifies whether the concept is a system concept (i.e. no further versions can be created, cannot be obsoleted, etc.).
Property
Type
Description
ConceptVersionId [1..1]
UUID
A unique identifier for the concept version.
VersionSequenceId [1..1]
INT
A sequence identifier for the version which allows for establishing a time-independent record of version order.
ConceptId
[1..1]
UUID
The concept to which the version applies.
CreationTime
[1..1]
Property
Type
Description
ConceptSetId [1..1]
UUID
A unique identifier for the concept set
Mnemonic [1..1]
VARCHAR
The codified name of the concept set (without spaces) used to reference the concept set in queries and paths.
Name [1..1]
VARCHAR
The human readable name of the concept set.
Url
[1..1]
Property
Type
Description
ConceptNameId [1..1]
UUID
A unique identifier for the concept name
ConceptId [1..1]
UUID
The concept to which the concept name applies.
EffectiveVersionSequenceId [1..1]
UUID
The version of the concept when the name did become active.
ObsoleteVersionSequenceId [0..1]
Property
Type
Description
ConceptRelationshipId [1..1]
UUID
The unique identifier for the relationship.
SourceConceptId [1..1]
UUID
The concept that represents the source of the relationship.
TargetConceptId [1..1]
UUID
The concept which represents the target of the relationship
EffectiveVerisonId [1..1]
Property
Type
Description
ConceptRelationshipTypeId [1..1]
UUID
The unique identifier for the concept relationship
Name [1..1]
VARCHAR
The human readable name of the concept relationship type.
Mnemonic [1..1]
VARCHAR
An invariant value that represents the type of relationship typically used by software components.
Property
Type
Description
ReferenceTermId [1..1]
UUID
A unique identifier for the reference term.
CodeSystemId [1..1]
UUID
The code system in which the reference term belongs.
Mnemonic [1..1]
VARCHAR
The wire level code mnemonic for the reference term.
Property
Type
Description
ConceptReferenceTermId [1..1]
UUID
A unique identifier for the concept reference term map
ConceptId [1..1]
UUID
The concept to which the reference term is linked.
EffectiveVersionSequenceId [1..1]
UUID
The version of the concept where the reference term map became effective.
ObsoleteVersionSequenceId [0..1]
Property
Type
Description
CodeSystemId [1..1]
UUID
A unique identifier for the code system entry.
Name [1..1]
VARCHAR
A human readable name for the code system. For example: ICD10
Oid [1..1]
VARCHAR
The object identifier that identifies the code system in an interoperable manner.
Authority
[1..1]
Property
Type
Description
ReferenceTermDisplayNameId [1..1]
UUID
The unique identifier for the reference term.
ReferenceTermId [1..1]
UUID
The reference term to which the display name applies.
LanguageCode [1..1] ~ ISO639-2 = en
CHAR
The ISO639-2 language code that identifies the language in which the display name is represented.
DisplayName [0..1]
DATETIME
VARCHAR
UUID
UUID
UUID
VARCHAR
VARCHAR

The act data model describes the tables and fields required for the tracking of acts in the SanteDB logical model.
The act table is represents the immutable attributes of an act.
Column
Type
A table for storing tags related to acts. A tag represents a version independent piece of data attached to a tag.
The act relationship table is used to track the relationship of acts to one another.
The ActParticipation table is used to track how entities participate in a particular act.
The act identifier table is used to store alternate identifiers for the act. This may include vaccine event identifiers, external order identifiers, etc.
The act extension table is used to store extensions attached to acts.
The observation table is used to store extended values related to observation act types.
The quantity observation table is used to store extended information related to the observations that carry quantified values.
The text observation table is used to store additional information related to a text valued observation.
The coded observation table is used to store additional data related to observations that are coded. Problems and Allergies would qualify as coded observations.
The substance administration table is used to store data related to substance administrations to a patient. This include vaccines or any type of Epupin injections for
The patient encounter table is used to store additional data related to an act that represents a patient encounter.
The act note table is used to store notes associated with an act.
Used to track acts which alter the physical state of an entity (i.e. surgeries, etc.)
Contains the binary data of the tag.
CreationTime [1..1]
DATETIME
Identifies the time when the tag became active, or was created.
CreatedBy [1..1]
UUID
Identifies the user that was responsible for the creation of the tag.
ObsoletionTime [0..1] ?(>CreationTime)
DATETIME
When present, identifies the time that the tag data is no longer valid.
ObsoletedBy [0..1] ?(ObsoletionTime)
UUID
Identifies the user who obsoleted the act tag.
Identifies the time when the act version became active (was created)
CreatedBy [1..1]
UUID
Identifies the user that was responsible for creating the version.
ObsoletionTime [0..1] ? (>CreationTime)
DATETIME
When present, identifies the time when the version of the act is no longer active.
ObsoletedBy
[0..1] ?(ObsoletionTime)
UUID
Identifies the user who was responsible for the obsoletion of the version.
NegationInd [1..1] = false
BIT
When present, indicates that the act’s value is not true. For example, when attempting to convey that a vaccine was not given, the negationInd would be set to true.
TypeConceptId
[0..1]
UUID
Identifies the type of act. This is a type that is a subclass within the major classification. For example, if the class is a substance administration, the type concept may represent an Immunization.
StatusConceptId [1..1] ~ActStatus
UUID
Identifies the status of the act as of the current version.
ActTime [0..1] ?(ActTime | ActStartTime | ActStopTime)
DATETIME
Identifies the time that the act did occurred, should occur.
ActStartTime [0..1] ?(ActTime | ActStartTime | ActStopTime)
DATETIME
Identifies the start time of the act.
ActStopTime [0..1] ?(ActTime | ActStartTime | ActStopTime)
DATETIME
Identifies the stop time of the act.
Identifies the version of the source act where this relationship did become active.
ObsoleteVersionSequenceId [0..1]
UUID
Identifies the version of the source act where this relationship is no longer active.
RelationshipTypeConceptId [1..1] ~ActRelationshipType
UUID
Identifies the type of relationship that the two acts have to one another.
When present, identifies the version of the act when the participation is no longer active.
ParticipationRoleConceptId [1..1] ~ActParticipationType
UUID
Qualifies what role the entity played in the carrying out of the act.
Quantity [1..1] = 1
INT
Identifies the number of entities that are included in the playing of the role.
The actual external identifier value.
EffectiveVersionSequenceId [1..1]
UUID
Identifies the version of the act where the alternate identifier became active.
ObsoleteVersionSequenceId [0..1]
UUID
When present, identifies the version of the act whereby the alternate identifier is no longer active.
A human comprehendible display value for the extension.
EffectiveVersionSequenceId [1..1]
UUID
Indicates the version of the act where this extension became active.
ObsoleteVersionSequenceId [0..1]
UUID
When present, indicates the version of the act where the extension is no longer active.
Identifies the concept that identifies the units of measurement.
Identifies the precision of the dose quantity.
DoseUnitConceptId [1..1] ~UnitOfMeasure
INT
Identifies the dose unit of measure that was given to the patient.
SequenceId [0..1]
INT
Identifies the sequence of this dose if it is a part of a sequence of doses.
The identifier of the entity that wrote the note.
NoteText [1..1]
TEXT
The textual content of the note.
Identifies the body system/part which was the target of the procedure.
Description
ActId [1..1]
UUID
A unique identifier for the act.
TemplateDefinitionId [1..1]
UUID
Identifies the template definition that the particular act implements.
ClassConceptId [1..1] ~ ActClass
UUID
Identifies a concept that classifies the act. This determines the type of act, for example an Observation, PatientEncounter, etc.
MoodConceptId [1..1] ~ ActMood
UUID
Identifies the mood, or method of the act’s performance.
Column
Type
Description
ActTagId [1..1]
UUID
A unique identifier for the tag.
ActId [1..1]
UUID
Identifies the act to which the tag is applied.
Key [1..1]
VARCHAR
A unique key identifier for the type of tag. A tag’s key is used to convey the type of data.
Value [1..1]
Column
Type
Description
ActVersionId [1..1]
UUID
A unique identifier for the version.
VersionSequenceId [1..1]
INT
A sequence identifier for the version which allows for a time independent mechanism for establishing version order.
ActId [1..1]
UUID
Identifies the act to which the version data applies.
CreationTime [1..1]
Column
Type
Description
ActRelationshipId [1..1]
UUID
Uniquely identifies the act relationship.
SourceActId [1..1]
UUID
Identifies the source act of the relationship.
TargetActId [1..1]
UUID
Identifies the target act of the relationship.
EffectiveVersionSequenceId [1..1]
Column
Type
Description
ActParticipationId [1..1]
UUID
Uniquely identifies the act participation.
ActId [1..1]
UUID
Identifies the act that the participation is for.
EffectiveVersionSequenceId [1..1]
UUID
Identifies the version of the act when the participation is active.
ObsoleteVersionSequenceId [0..1]
Column
Type
Description
ActIdentifierId [1..1]
UUID
Uniquely identifies the alternate act identifier.
IdentifierTypeId [0..1]
UUID
Identifies the type of identifier this particular identifier instance represents (order #, etc.)
AssigningAuthorityId [1..1]
UUID
Identifies the authority that assigned the identifier.
IdentifierValue [1..1]
Column
Type
Description
ActExtensionId [1..1]
UUID
A unique identifier for the act extension.
ExtensionTypeId [1..1]
UUID
Identifies the type of extension represented. This includes information on how the extension should be serialized to/from the ExtensionValue column.
ExtensionValue [1..1]
VARBINARY
Carries the value of the extension.
ExtensionDisplay [1..1]
Column
Type
Description
ActVersionId [1..1]
UUID
Identifies the act version to which this extended data applies.
InterpretationConceptId [0..1] ~ActInterpretation
UUID
Identifies the concept that represents the interpretation of the observation.
Column
Type
Description
ActVersionId [1..1]
UUID
Identifies the observation act version to which the quantified observation data applies.
Quantity [1..1]
DECIMAL
A decimal value that contains the value of the observation quantity.
QuantityPrecision [1..1]
INT
Identifies the precision of the Quantity field.
UnitOfMeasureConceptId [1..1] ~UnitOfMeasure
Column
Type
Description
ActVersionId [1..1]
UUID
Identifies the observation version id that this text observation data is attached to.
TextValue [1..1]
TEXT
A textual field that contains the observation data.
Column
Type
Description
ActVersionId [1..1]
UUID
Identifies the version of the observation that this coded observation value data applies.
ConceptValueId [1..1]
UUID
Identifies the concept that represents the value of observation.
Column
Type
Description
ActVersionId [1..1]
UUID
Identifies the act version to which the substance administration data applies.
RouteConceptId [0..1] ~RouteConcept
UUID
Identifies the concept that describes the route that was taken to administer the substance. This may be drawn from the default route if not supplied.
DoseQuantity [1..1]
DECIMAL
Identifies the dosage that was given to the patient.
DoseQuantityPrecision [1..1]
Column
Type
Description
ActVersionId [1..1]
UUID
Identifies the act to which the extended patient encounter data applies.
DischargeDispositionConceptId [0..1] ~DischargeDisposition
UUID
Identifies the disposition in which the patient left the encounter.
Column
Type
Description
ActNoteId [1..1]
UUID
A unique identifier for the note.
EffectiveVersionSequenceId [1..1]
UUID
The version whereby the note became effective
ObsoleteVersionSequenceId [0..1]
UUID
When populated, indicates the version of the act where the note is no longer active.
AuthorEntityId [1..1]
Column
Type
Description
ActVersionId [1..1]
UUID
Points to the version of the Act which this procedure is describing.
MethodCodeId [0..1] ~ProcedureTechniqueCode
UUID
Identifies the formal method for performing the procedure.
ApproachSiteCodeId [0..1] ~BodySiteOrSystemCode
UUID
Identifies the manner in which the target site was approached for the procedure.
TargetSiteCodeId [0..1] ~BodySiteOrSystemCode
VARBINARY
DATETIME
UUID
UUID
VARCHAR
VARCHAR
UUID
INT
UUID
UUID

The SanteDB entity model represents a series of tables which are responsible for the tracking of entities within the SanteDB data model. Entities represent people, places, organizations, things, etc. and are responsible for participating within acts in some capacity.
The entity table is responsible for the storage of immutable attributes of an entity.
Column
The entity tag table is used to store version independent tags associated with an entity. A tag does not result in new versions of the entity and is used to track additional data related to security and/or workflow related metadata.
The entity version table is used to store the mutable attributes of an entity, that is to say, any fields associated with an entity that may evolve over the lifespan of the entity are tracked in this table.
The entity association table is used to associate two or more entities together. An association is made between a source entity and a target entity.
The entity note table is used to store textual notes related to an entity.
The entity address table is used to store address information (physical addresses) related to an entity.
The entity address component table is used to store the address components associated with a particular entity address.
The entity name table is used to store master list of names associated with an entity.
The entity name component table is responsible for the storage of name components that comprise an entity name.
The entity identifier is table is responsible for the storage of alternate identifies associated with the entity.
The entity extension table is used to store additional, clinically relevant, versioned data attached to an entity that cannot be stored in the native data model.
The entity telecommunications address table is used to store data related to telecommunications addresses (email, fax, phone, etc.) for an entity.
The place table represents a specialization of the Entity table which is used to represent physical places such as clinics, outreach activity sites, etc.
The place service table is used to identify the services that are provided at a particular place. Services may include stocking, transfer depots, immunization.
The application entity table is used to store entity data related to an application. An application is a software program that runs on a device. This differs from a security application, in that an application may be referenced clinically without needing access to the SanteDB system. For example: The patient uses MyPHR
The device table is used to store clinical information related to a physical device. Like an application entity, this table is used to describe the clinical attributes of a device used in the provisioning of care. Example: Bob’s Insulin Pump. The insulin pump itself may have no security device as it doesn’t require access to SanteDB.
A material represents a physical thing (syringe, drug, etc.) which participates in an act or is assigned to a person.
A manufactured material is a specialization of a material that is manufactured.
A person is a specialization of Entity that is used to represent a human.
The person language communication table is used to store information related to the person’s language preferences. This can be used by the user interface to determine which language to display, however is also clinically relevant to indicate the language in which a patient wishes to receive communciations.
The organization table represents a specialization of an entity representing a logical organization.
A provider is a specialization of the Person table which is used to store provider related information about a person.
The patient entity is a specialization of the Person table which is used to track primary attributes related to a patient.
A value that carries the data associated with the tag value.
CreationTime [1..1]
DATETIME
Indicates the date/time at which time the tag was created.
CreatedBy [1..1]
UUID
Identifies the user that was responsible for the creation of the tag.
ObsoletionTime [0..1] ?(>CreationTime)
DATETIME
When populated, indicates the time when the tag is no longer associated with the entity.
ObsoletedBy [0..1] ?(ObsoletionTime)
UUID
Identifies the user that was responsible for obsoleting the tag.
Identifies the status of the entity as of the version represented in the tuple.
CreationTime [1..1]
DATETIME
Indicates the time when the entity was created.
CreatedBy [1..1]
UUID
Identifies the user that was responsible for the creation of the entity.
ObsoletionTime [0..1] ?(>CreationTime)
DATETIME
When populated, indicates the time when the entity version became obsolete.
ObsoletedBy [0..1] ?(ObsoletionTime)
UUID
Identifies the user that was responsible for the obsoleting of the record.
TypeConceptId [0..1]
UUID
Indicates the concept that classifies the subtype of entity. For example, an entity may be a provider; however, the sub-type may be a “physiotherapist”.
Indicates the version of the source entity at which time this entity association was created or became effective.
ObsoleteVersionSequenceId [0..1]
UUID
When populated, indicates that the entity association is no longer active, and indicates the version of the source entity where the association ceased to be applicable.
RelationshipTypeConceptId [1..1] ~EntityRelationshipType
UUID
Classifies the relationship between the two entities. Can indicate ownership roles such as “Place OWNS Material”, or relationship “Patient CHILD OF Person”.
Quantity [1..1] = 1
INT
Indicates the quantity of target entities contained within the source entity.
Identifies the entity that was responsible for the authoring of the note.
NoteText [1..1]
TEXT
Indicates the textual content of the note.
Indicates the desired use of the address. Examples include physical visit, vacation home, contact, mailing, etc.
Identifies the entity address to which the entity address component applies.
When populated, identifies the version of the entity where the name is no longer active.
Indicates the entity name to which the name component applies.
When populated, indicates the version of the entity where the identifier is no longer active.
AssigningAuthorityId [1..1]
UUID
Identifies the authority that was responsible for the assigning of the identifier.
IdentifierValue [1..1]
VARCHAR
Indicates the value of the entity identifier.
Indicates the type, or handler, for the extension data.
ExtensionData [1..1]
VARBINARY
Serialized data that contains the raw value of the extension (serialized and de-serialized by the handler).
ExtensionDisplay [1..1]
VARCHAR
A textual, human readable expression of the extension value which can be displayed on reports, etc.
Identifies the intended use of the telecom address. (Example: home, work, etc.)
EffectiveVersionSequenceId [1..1]
UUID
Identifies the version of the entity whereby the telecom address became effective.
ObsoleteVersionSequenceId [0..1]
UUID
When populated, identifies the version of the entity where the telecom address is no longer valid.
The longitudinal position of the place expressed in degrees longitude.
Indicates a concept that describes the service offered.
ServiceSchedule [0..1]
XML
An XML expression of the service schedule.
ServiceScheduleType [0..1]
VARCHAR
Identifies the type of data stored in the service schedule column (iCal, GTS, etc.)
The name of the vendor which distributes the software application (example: “ABC Corp”)
ApplicationId [0..1]
UUID
When populated, links the application entity to a security application.
When populated, identifies the security device associated with the device entity.
Identifies a concept that denotes the form that the material takes. Examples: capsule, injection, nebulizer, etc. For drugs and vaccines, the form will imply the route of administration.
QuantityConceptId [0..1] ~UnitOfMeasure
UUID
Indicates the unit of measure for a single unit of the material. Examples: dose, mL, etc.
Quantity [0..1] = 1
NUMERIC
Indicates the reference quantity in UOM. For example, BCG MMAT is 5 mL of BCG Antigen
IsAdministrative [1..1] = false
BIT
An indicator that is used to identify whether the material is a real material or an administrative material for the purpose of management.
An ISO-639-2 language code indicating the language preference.
PreferenceIndicator [0..1] = False
BIT
Indicates whether the person prefers the language for communications.
When populated, controls the precision of the value in DeceasedTime
MultipleBirthOrder
[0..1]
INT
When populated, indicates the order of the patient in a multiple birth. A non-null value in this column (0 or -1) indicates special indicators that the exact order is unknown, however the patient is part of a multi-birth.
MaritalStatusConceptId
[0..1] ~MaritalStatus
UUID
The codified status of the patient's marital state (example: single, married, divorced, etc.). Drawn from the MaritalStatus concept set.
EducationLevelConceptId
[0..1] ~EducationLevel
UUID
The codified value indicating the patient's highest level of education obtained (college, high school, etc.)
LivingArrangementConceptId
[0..1] ~LivingArrangement
UUID
The codified value indicating the patient's living arrangement (cohabitating, supervised care, etc.)
ReligionConceptId
[0..1] ~Religion
UUID
The codified value indicating the patient's religion. Note that the religion concept may be blocked based on national profiles and local legislation.
EthnicGroupConceptId
[0..1] ~EthnicGroup
UUID
The codified value indicating the patient's ethnicity.
Type
Description
EntityId
[1..1]
UUID
Uniquely identifies the entity within the context of the SanteDB implementation.
TemplateDefinitionId [0..1]
UUID
Identifies the template which the entity instance implements.
ClassConceptId [1..1] ~EntityClassConcept
UUID
Identifies the concept that classifies the entity by a type. The classifier is used to determine “WHAT TYPE” of entity the tuple represents such as a person, material, manufactured material, organization, place, etc.
DeterminerConceptId [1..1] ~EntityDeterminerConcept
UUID
Identifies the concept that classifies or determines the type of entity. This is either an INSTANCE or CLASS concept identifier.
Column
Type
Description
EntityTagId [1..1]
UUID
Uniquely identifies the entity tag.
EntityId [1..1]
UUID
Identifies the entity to which the tag is associated.
Key [1..1]
VARCHAR
Qualifies the type of tag associated with the entity. That is to say, type of tag is represented in the tuple of the determiner.
Value [1..1]
Column
Type
Description
EntityVersionId [1..1]
UUID
Uniquely identifies the version of the entity represented in the tuple.
EntityId [1..1]
UUID
Identifies the entity to which this version applies.
ReplacesVersionId [0..1]
UUID
Identifies the version of the entity that the current tuple is responsible for replacing.
StatusConceptId [1..1] ~EntityStatusConcept
Column
Type
Description
EntityRelationshipId [1..1]
UUID
Uniquely identifies the entity association.
SourceEntityId [1..1]
UUID
Identifies the source of the entity association.
TargetEntityId [1..1]
UUID
Identifies the target of the entity association.
EffectiveVersionSequenceId [1..1]
Column
Type
Description
EntityNoteId [1..1]
UUID
Uniquely identifies the note.
EffectiveVersionSequenceId [1..1]
UUID
Identifies the version of the entity to which the note applies.
ObsoleteVersionSequenceId [0..1]
UUID
When populated, indicates the version of the entity where the note is no longer relevant.
AuthorEntityId [1..1]
Column
Type
Description
EntityAddressId [1..1]
UUID
Uniquely identifies the entity address.
EffectiveVersionSequenceId [1..1]
UUID
Identifies the version of the entity whereby the address information became active.
ObsoleteVersionSequenceId [0..1]
UUID
When populated, indicates the version of the entity whereby the address is no longer applicable.
AddressUseConceptId [1..1] ~AddressUseType
Column
Type
Description
EntityAddressComponentId [1..1]
UUID
Uniquely identifies the entity address component.
Value [1..1]
VARCHAR
Identifies the value of the of the address component
ComponentTypeConceptId [1..1] ~NameComponentType
UUID
Classifies the type of address component represented in the value field. For example: street name, city, country, postal code, etc.
EntityAddressId [1..1]
Column
Type
Description
EntityNameId [1..1]
UUID
Uniquely identifies the entity name.
EntityNameUseId [1..1]
UUID
Classified the intended use of the entity name. Examples: maiden name, legal name, license name, artist name, etc.
EffectiveVersionSequenceId [1..1]
UUID
Identifies the version of the entity when this name became active.
ObsoleteVersionSequenceId [0..1]
Column
Type
Description
NameComponentId [1..1]
UUID
Uniquely identifies the name component.
ValueId [1..1]
UUID
Indicates the phonetic value tuple that stores the name value.
NameComponentTypeConceptId [1..1] ~EntityComponentType
UUID
Classifies the type of name component represented. Examples: first name, title, family name, etc.
EntityNameId [1..1]
Column
Type
Description
EntityIdentifierId [1..1]
UUID
Uniquely identifies the entity identifier.
IdentifierTypeId [1..1]
UUID
Classifies the type of identifier that is represented by the entity identifier. Examples: business identifier, mrn, primary identifier, etc.
EffectiveVersionSequenceId [1..1]
UUID
Indicates the version of the entity when the identifier became active.
ObsoleteVersionSequenceId [0..1]
Column
Type
Description
EntityExtensionId [1..1]
UUID
Uniquely identifies the extension.
EffectiveVersionSequenceId [1..1]
UUID
Indicates the version of the entity when the extension data did become active.
ObsoleteVersionSequenceId [0..1]
UUID
When populated, indicates the version of the entity where the extension value is no longer applicable.
ExtensionTypeId [1..1]
Column
Type
Description
EntityTelecomId [1..1]
UUID
Uniquely identifies the telecommunications address.
TelecomAddressType [1..1] ~TelecomAddressType
UUID
Classifies the type of address represented (example: phone, fax, email, etc.)
TelecomAddress [1..1]
VARCHAR
The value of the telecommunications address in RFC-2396 format.
TelecomUseConceptId [0..1] ~TelecomAddressUse
Column
Type
Description
EntityVersionId [1..1]
UUID
Identifies the version of the entity to which the place data applies.
MobileInd [1..1] = False
BIT
Indicator that is used to identify that a place is mobile.
Lat [0..1]
FLOAT
The latitudinal position of the place expressed in degrees latitude.
Lng [0..1]
Column
Type
Description
PlaceServiceId [1..1]
UUID
A unique identifier for the place service.
EffectiveVersionSequenceId [1..1]
UUID
The version of the place entity where the service entry is active.
ObsoleteVersionSequenceId [0..1]
UUID
When populated, indicates the version of the place entity where the service entry is no longer valid.
ServiceConceptId [1..1] ~ServiceType
Column
Type
Description
EntityVersionId [1..1]
UUID
Identifies the version of the entity to which the application data applies.
SoftwareName [0..1]
VARCHAR
Identifies the name of the software package (“EMR Package” is an example)
VersionName [0..1]
VARCHAR
Identifies the version of the software (example: “1.0”)
VendorName [0..1]
Column
Type
Description
EntityVersionId [1..1]
UUID
Indicates the version of the entity to which the device data applies.
ManufacturerModel [0..1]
VARCHAR
Indicates the name of the manufacturer of the device.
OperatingSystemName [0..1]
VARCHAR
Indicates the name of the operating system installed on the device.
DeviceId [0..1]
Column
Type
Description
EntityVersionId [1..1]
UUID
Identifies the version of the entity to which the material data applies.
ExpiryTime [1..1]
DATETIME
Indicates the time when the material will expire.
ExpiryTimePrecision [1..1]
CHAR
Indicates the precision that the expiry time has.
FormConceptId [0..1] ~MaterialForm
Column
Type
Description
EntityVersionId [1..1]
UUID
Indicates the version of the material to which the specialized data applies.
LotNumber [1..1]
VARCHAR
Indicates the manufacturer lot for the material.
Column
Type
Description
EntityVersionId [1..1]
N/A
The version of the entity to which the person data applies.
DateOfBirth [0..1]
DATE
Indicates the date on which the person entity was born.
DateOfBirthPrecision [0..1]
CHAR
Indicates the precision of the date of birth field.
Column
Type
Description
PersonLanaugeCommunication Id [1..1]
UUID
Uniquely identifies the language of communication.
EffectiveVersionSequenceId [1..1]
UUID
Indicates the version of the person entity whereby the language of communication is effective.
ObsoleteVersionSequenceId [0..1]
UUID
When present, indicates the version of the person entity where the language of communication is no longer effective.
LanguageCommunication [1..1] ~ISO639-2
Column
Type
Description
EntityVersionId [1..1]
UUID
Indicates the version of the entity to which the organization specialization applies.
IndustryConceptId [0..1] ~IndustryConcept
UUID
Indicates the industry in which the organization operates. Examples: logistics, healthcare, etc.
Column
Type
Description
EntityVersionId [1..1]
UUID
Indicates the version of the entity to which the provider specialization applies.
SpecialtyConceptId
[1..1]
UUID
Indicates the primary specialty of the provider at this version of the record.
Column
Type
Description
EntityVersionId [1..1]
UUID
Indicates the version of the entity to which the patient specialization applies.
GenderConceptId
[1..1] ~AdministrativeGender
UUID
Identifies the logical gender concept of the patient. These values are drawn from the administrative gender concept set.
DeceasedTime
[0..1]
DATETIME
When populated, indicates the date/time that the patient was indicated as deceased.
DeceasedTimePrecision
[0..1]
VARCHAR
UUID
UUID
UUID
UUID
UUID
UUID
UUID
UUID
UUID
UUID
FLOAT
UUID
VARCHAR
UUID
UUID
VARCHAR
INT
SanteDB uses object identifiers (OIDs) in one of two registered IANA Private Enterprise Number (PEN) namespaces. The use of these PEN roots depends on the timeframe when the feature was designed:
Features from OpenIZ (SanteDB v1) and SanteDB v2 reside in the PEN for Mohawk College of Applied Arts and Technology / Applied Research: 1.3.6.1.4.1.33349.3.1.5.9
Features from SanteDB v2 and v3 reside in the Fyfe Software Inc. PEN: 1.3.6.1.4.1.52820.5
The root of SanteDB OIDs from the OpenIZ root 1.3.6.1.4.1.33349.3.1.5.9
Privacy and security OIDs assigned in the 1.3.6.1.4.1.33349.3.1.5.9.2 namespace represent policies. These policies are expressed in OIDs as they are hierarchical in nature. The default OIDs in this namespace are:
Concept sets and code systems which are specific to SanteDB existing in the root 1.3.6.1.4.1.33349.3.1.5.9.3 these concept sets are:
Community deployments undertaken by SanteSuite Inc. or SanteSuite partners typically will require OIDs for custom policies, templates, CDSS rules, etc. These OIDs are assigned off the root branch for the deployment in the 1.3.6.1.4.1.52820.5.1 namespace and are.
Clinical templates are structures which dictate the format, entry, and display of clinical data primarily from SanteEMR derivatives (such as SanteIMS). These templates are assigned OIDs from the 1.3.6.1.4.1.52820.5.2 namespace which has five children:
1.3.6.1.4.1.52820.5.2.0 - Templates for Patients
1.3.6.1.4.1.52820.5.2.1 - Templates for Observations
1.3.6.1.4.1.52820.5.2.2
The clinical templates defined by SanteDB community implementations are:
Clinical protocols and libraries exist in the 1.3.5.1.4.1.52820.5.3 namespace, with the following child namespaces:
1.3.5.1.4.1.52820.5.3.1 - Childhood Nutrition, Care & Immunization Decision Support (typically applied only to patients under the age of 5)
1.3.5.1.4.1.52820.5.3.2 - Antenatal Care Decision Support
Identity domain oids reside in the root 1.3.6.1.4.1.52820.5.4 and are further subdivided into:
.1 - Patient domains
.2 - Organization domains
.3 - Material Identity
Deployments
1.3.6.1.4.1.52820.5
2
Clinical Templates
1.3.6.1.4.1.52820.5
3
Clinical Protocols & CDSS Rules
1.3.6.1.4.1.52820.5
4
Identity Domains
Create Identity
1.3.6.1.4.1.33349.3.1.5.9.2.0.5
Create Device
1.3.6.1.4.1.33349.3.1.5.9.2.0.6
Create Application
1.3.6.1.4.1.33349.3.1.5.9.2.0.7
Administer Concept Dictionary
1.3.6.1.4.1.33349.3.1.5.9.2.0.8
Alter Identity
1.3.6.1.4.1.33349.3.1.5.9.2.0.9
Alter Policy
1.3.6.1.4.1.33349.3.1.5.9.2.0.10
Administer Data Warehouse
1.3.6.1.4.1.33349.3.1.5.9.2.1
Login
1.3.6.1.4.1.33349.3.1.5.9.2.1.0
Login as a Service
1.3.6.1.4.1.33349.3.1.5.9.2.2
Unrestricted Clinical Data
1.3.6.1.4.1.33349.3.1.5.9.2.2.0
Query Clinical Data
1.3.6.1.4.1.33349.3.1.5.9.2.2.1
Write Clinical Data
1.3.6.1.4.1.33349.3.1.5.9.2.2.2
Delete Clinical Data
1.3.6.1.4.1.33349.3.1.5.9.2.2.3
Read Clinical Data
1.3.6.1.4.1.33349.3.1.5.9.2.2.4
Export Clinical Data
1.3.6.1.4.1.33349.3.1.5.9.2.999
Override Disclosure
1.3.6.1.4.1.33349.3.1.5.9.2.4
Unrestricted Metadata
1.3.6.1.4.1.33349.3.1.5.9.2.4.0
Read Metadata
1.3.6.1.4.1.33349.3.1.5.9.2.10
Access Client Administrative Function
1.3.6.1.4.1.33349.3.1.5.9.2.5
Unrestricted Data Warehouse
1.3.6.1.4.1.33349.3.1.5.9.2.5.0
Write Warehouse Data
1.3.6.1.4.1.33349.3.1.5.9.2.5.1
Delete Warehouse Data
1.3.6.1.4.1.33349.3.1.5.9.2.5.2
Read Warehouse Data
1.3.6.1.4.1.33349.3.1.5.9.2.5.3
Query Warehouse Data
1.3.6.1.4.1.33349.3.1.5.9.3
Restricted Information
1.3.6.1.4.1.33349.3.1.5.9.2.4.1.0
Write Materials
1.3.6.1.4.1.33349.3.1.5.9.2.4.1.1
Delete Materials
1.3.6.1.4.1.33349.3.1.5.9.2.4.0.1.2
Read Materials
1.3.6.1.4.1.33349.3.1.5.9.2.4.0.1.3
Query Materials
1.3.6.1.4.1.33349.3.1.5.9.2.4.2.0
Write Places & Orgs
1.3.6.1.4.1.33349.3.1.5.9.2.4.2.1
Delete Places & Orgs
1.3.6.1.4.1.33349.3.1.5.9.2.4.0.2.2
Read Places & Orgs
1.3.6.1.4.1.33349.3.1.5.9.2.4.0.2.3
Query Places & Orgs
1.3.6.1.4.1.33349.3.1.5.9.2.0.11
Access Audit Log
1.3.6.1.4.1.33349.3.1.5.9.2.0.12
Administer Applets
1.3.6.1.4.1.33349.3.1.5.9.2.0.13
Assign Policy
1.3.6.1.4.1.33349.3.1.5.9.2.2.5
Elevate Clinical Data
1.3.6.1.4.1.33349.3.1.5.9.2.1.0.1
Login for Password Reassignment
1.3.6.1.4.1.33349.3.1.5.9.2.600
Special Security Elevation
1.3.6.1.4.1.33349.3.1.5.9.2.600.1
Change Security Challenge Question
1.3.6.1.4.1.33349.3.1.5.9.2.1.0.2
Allow Impersonation of Application
1.3.6.1.4.1.33349.3.1.5.9.2.0.4.1
Create Local Users
1.3.6.1.4.1.33349.3.1.5.9.2.0.8.1
Alter Local Users
1.3.6.1.4.1.33349.3.1.5.9.2.0.18
Manage System Backups
1.3.6.1.4.1.33349.3.1.5.9.2.0.18.1
Create System Backup on (Private or Public)
1.3.6.1.4.1.33349.3.1.5.9.2.0.18.1.1
Create Private System Backup
1.3.6.1.4.1.33349.3.1.5.9.2.0.19
Unrestricted Security Certificate Management
1.3.6.1.4.1.33349.3.1.5.9.2.0.19.1
Issue New Certificates
1.3.6.1.4.1.33349.3.1.5.9.2.0.19.2
Revoke Certificates
1.3.6.1.4.1.33349.3.1.5.9.2.0.19.3
Assign Certificate to Security Identity
1.3.6.1.4.1.33349.3.1.5.9.2.0.15
Alter System Configuration
1.3.6.1.4.1.33349.3.1.5.9.2.0.17
Administer Internal Mail / Messages
1.3.6.1.4.1.33349.3.1.5.9.2.0.20
Manage Foreign Data
1.3.6.1.4.1.33349.3.1.5.9.2.500
Export CDR Data
1.3.6.1.4.1.33349.3.1.5.9.2.0.15.1
Unrestricted Match Configuration
1.3.6.1.4.1.33349.3.1.5.9.2.0.15.1.1
Alter Match Configurations
1.3.6.1.4.1.33349.3.1.5.9.2.0.15.1.2
Disable/Enable Match Configurations
1.3.6.1.4.1.33349.3.1.5.9.2.1.0.0
OAUTH Login
1.3.6.1.4.1.33349.3.1.5.9.2.1.0.0.1
OAUTH client_credentials flow permission
1.3.6.1.4.1.33349.3.1.5.9.2.1.0.0.1.0
OAUTH client_credentials flow permission no device cred
1.3.6.1.4.1.33349.3.1.5.9.2.1.0.0.2
OAUTH password flow permission
1.3.6.1.4.1.33349.3.1.5.9.2.1.0.0.2.0
OAUTH password flow permission no device cred
1.3.6.1.4.1.33349.3.1.5.9.2.1.0.0.3
OAUTH authoization code grant flow permission
1.3.6.1.4.1.33349.3.1.5.9.2.1.0.0.3.0
OAUTH authoization code grant flow permission no device cred
1.3.6.1.4.1.33349.3.1.5.9.2.1.0.0.4
OAUTH Password Reset grant (extended permission)
1.3.6.1.4.1.33349.3.1.5.9.2.1.0.0.4.0
OAUTH Password Reset grant (extended permission) no device cred
1.3.6.1.4.1.33349.3.1.5.9.2.0.15.2
Unrestricted Clinical Protocol Configuration
1.3.6.1.4.1.33349.3.1.5.9.2.0.15.2.0
Create Clinical Protocol
1.3.6.1.4.1.33349.3.1.5.9.2.0.15.2.1
Alter Clinical Protocol
1.3.6.1.4.1.33349.3.1.5.9.2.0.15.2.2
Delete Clinical Protocol
1.3.6.1.4.1.33349.3.1.5.9.2.0.14
Unrestricted PubSub Administration
1.3.6.1.4.1.33349.3.1.5.9.2.0.14.1
Create/Alter PubSub Subscriptions
1.3.6.1.4.1.33349.3.1.5.9.2.0.14.2
Disable/Enable PubSub Subscriptions
1.3.6.1.4.1.33349.3.1.5.9.2.0.14.3
Delete PubSub Subscriptions
1.3.6.1.4.1.33349.3.1.5.9.2.0.14.4
Read PubSub Subscriptions
1.3.6.1.4.1.33349.3.1.5.9.2.0.16
Unrestricted Dispatcher Queue
1.3.6.1.4.1.33349.3.1.5.9.2.6
Unrestricted MDM
1.3.6.1.4.1.33349.3.1.5.9.2.6.1
Write MDM Master
1.3.6.1.4.1.33349.3.1.5.9.2.6.2
Read MDM Locals
1.3.6.1.4.1.33349.3.1.5.9.2.6.3
Merge MDM Master
1.3.6.1.4.1.33349.3.1.5.9.2.6.4
Establish MDM Record of Truth
1.3.6.1.4.1.33349.3.1.5.9.2.6.4.1
Edit Existing MDM Record of Truth
Entity Class
1.3.6.1.4.1.33349.3.1.5.9.3.7
Entity Status
1.3.6.1.4.1.33349.3.1.5.9.3.8
Entity Relationship Type
1.3.6.1.4.1.33349.3.1.5.9.3.9
Address Use
1.3.6.1.4.1.33349.3.1.5.9.3.10
Address Component Type
1.3.6.1.4.1.33349.3.1.5.9.3.11
Name Use
1.3.6.1.4.1.33349.3.1.5.9.3.18
Name Component Type
1.3.6.1.4.1.33349.3.1.5.9.3.12
Telecom Address Use
1.3.6.1.4.1.33349.3.1.5.9.3.14
Service Code
1.3.6.1.4.1.33349.3.1.5.9.3.15
Industry Code
1.3.6.1.4.1.33349.3.1.5.9.3.16
Administrative Genders
1.3.6.1.4.1.33349.3.1.5.9.3.17
Role Status
1.3.6.1.4.1.33349.3.1.5.9.3.23
Family members of children
1.3.6.1.4.1.33349.3.1.5.9.3.24
Spousal Family Members
1.3.6.1.4.1.33349.3.1.5.9.3.60
Living Arrangement
1.3.6.1.4.1.33349.3.1.5.9.3.61
Marital Status
1.3.6.1.4.1.33349.3.1.5.9.3.62
Ethnicities
1.3.6.1.4.1.33349.3.1.5.9.3.63
Religions
1.3.6.1.4.1.33349.3.1.5.9.1.39
Allergies and Intolerance Types
1.3.6.1.4.1.33349.3.1.5.9.3.5
Act Interpretation
1.3.6.1.4.1.33349.3.1.5.9.3.19
Reason Codes
1.3.6.1.4.1.33349.3.1.5.9.3.37
Protocol Violation Reason
1.3.6.1.4.1.33349.3.1.5.9.3.50
Protocol Violation - Don't Reschedule
1.3.6.1.4.1.33349.3.1.5.9.3.26
Administration Act Type Codes
1.3.6.1.4.1.33349.3.1.5.9.1.41
Act Types
1.3.6.1.4.1.33349.3.1.5.9.3.66
Place Classifications
1.3.6.1.4.1.33349.3.1.5.9.3.13
Telecom Address Type
1.3.6.1.4.1.33349.3.1.5.9.1.53
Adverse Event Types
1.3.6.1.4.1.33349.3.1.5.9.3.32
AdministrationSite
1.3.6.1.4.1.33349.3.1.5.9.3.88
Body Site Codes
1.3.6.1.4.1.33349.3.1.5.9.3.51
Diagnosis Codes
1.3.6.1.4.1.33349.3.1.5.9.3.44
Causes of Death
1.3.6.1.4.1.33349.3.1.5.9.3.70
Encounter Type Codes
1.3.6.1.4.1.33349.3.1.5.9.3.80
Identifier Type Codes
1.3.6.1.4.1.33349.3.1.5.9.3.59
Language Codes
1.3.6.1.4.1.33349.3.1.5.9.3.65
Master Data Model Relationship Types
1.3.6.1.4.1.33349.3.1.5.9.3.84
Country Codes
1.3.6.1.4.1.33349.3.1.5.9.3.85
Nationality Codes
1.3.6.1.4.1.33349.3.1.5.9.3.77
Occupation Types
1.3.6.1.4.1.33349.3.1.5.9.3.45
Observation Act Types
1.3.6.1.4.1.33349.3.1.5.9.3.53
Problem or Concern Observation Types
1.3.6.1.4.1.33349.3.1.5.9.3.79
Relationship Classification
1.3.6.1.4.1.33349.3.1.5.9.3.29
Route of administration
1.3.6.1.4.1.33349.3.1.5.9.3.48
Security Audit Codes
1.3.6.1.4.1.33349.3.1.5.9.3.35
Units of Measure
1.3.6.1.4.1.33349.3.1.5.9.3.36
Units of Measure for Weight
1.3.6.1.4.1.33349.3.1.5.9.3.75
Units of Measure for Height
1.3.6.1.4.1.33349.3.1.5.9.3.78
VIP Status Codes
1.3.6.1.4.1.33349.3.1.5.9.3.149
Vaccine Support Materials
1.3.6.1.4.1.33349.3.1.5.9.3.49
Material Type Codes
1.3.6.1.4.1.33349.3.1.5.9.3.28
AdministrableDrugForm
1.3.6.1.4.1.33349.3.1.5.9.3.72
Delivery Outcome Codes
1.3.6.1.4.1.33349.3.1.5.9.3.73
Delivery Method Codes
1.3.6.1.4.1.33349.3.1.5.9.3.74
Delivery Location Codes
1.3.6.1.4.1.33349.3.1.5.9.3.86
Detected Issue Type
1.3.6.1.4.1.33349.3.1.5.9.3.30
Subset of Discharge Disposition (HL7)
1.3.6.1.4.1.33349.3.1.5.9.3.47
Subset of Disposition (HL7)
1.3.6.1.4.1.33349.3.1.5.9.3.64
Education Levels
1.3.6.1.4.1.33349.3.1.5.9.3.67
Name Prefix
1.3.6.1.4.1.33349.3.1.5.9.3.68
Name Suffix
1.3.6.1.4.1.33349.3.1.5.9.3.42
Null Reason
1.3.6.1.4.1.33349.3.1.5.9.3.76
Verification Status
1.3.6.1.4.1.33349.3.1.5.9.3.55
Organization Type Concept
1.3.6.1.4.1.33349.3.1.5.9.3.54
Place Type Concepts (Sub-Classes)
1.3.6.1.4.1.33349.3.1.5.9.3.56
Place Entity Class Code Concepts
1.3.6.1.4.1.33349.3.1.5.9.3.87
Procedure Technique Codes
1.3.6.1.4.1.33349.3.1.5.9.3.90
Provider Types for Individuals
1.3.6.1.4.1.33349.3.1.5.9.3.69
Purposes of Use
1.3.6.1.4.1.33349.3.1.5.9.3.46
Reaction Observations
1.3.6.1.4.1.33349.3.1.5.9.3.71
Registration Event Type Codes
1.3.6.1.4.1.33349.3.1.5.9.3.43
Severity Observation Values
1.3.6.1.4.1.33349.3.1.5.9.3.25
Vaccines
1.3.6.1.4.1.33349.3.1.5.9.3.34
Vital Signs
Act1.3.6.1.4.1.52820.5.2.3 - Templates for SubstanceAdminsitration
1.3.6.1.4.1.52820.5.2.4 - Templates for Procedure
1.3.6.1.4.1.52820.5.2.5 - Templates for PatientEncounter
1.3.6.1.4.1.52820.5.2.6 - Templates for stock related data
SanteEMR Birth & Delivery Location
1.3.6.1.4.1.52820.5.2.1.3
org.santedb.emr.observation.birthDeliveryMethod
SanteEMR Birth & Delivery Method
1.3.6.1.4.1.52820.5.2.1.4
org.santedb.emr.observation.birthDeliveryOutcome
SanteEMR Birth & Delivery Outcome
1.3.6.1.4.1.52820.5.2.1.5
org.santedb.emr.observation.birthWeight
SanteEMR Birth Weight Observation
1.3.6.1.4.1.52820.5.2.1.6
org.santedb.emr.observation.heightLying
SanteEMR Height/Length (Lying down)
1.3.6.1.4.1.52820.5.2.1.7
org.santedb.emr.observation.liveBirths
SanteEMR Number of Live Births (Reported)
1.3.6.1.4.1.52820.5.2.1.8
org.santedb.emr.observation.death
SanteEMR Patient Clinical Status = Dead
1.3.6.1.4.1.52820.5.2.1.9
org.santedb.emr.observation.verification
SanteEMR Clinical Status Verification Observation
1.3.6.1.4.1.52820.5.2.1.10
org.santedb.emr.observation.weight
SanteEMR Weight Observation
1.3.5.1.4.1.52820.5.2.2.1
org.santedb.emr.act.registration.birth
Registration of a performed delivery/birth
1.3.5.1.4.1.52820.5.2.2.2
org.santedb.emr.act.registration.death
Registration of a confirmed or suspected death
1.3.5.1.4.1.52820.5.2.3.1
org.santedb.emr.sbadm.supplement
SanteIMS Supplemental (non-tracked material) administration
1.3.5.1.4.1.52820.5.2.3.2
org.santedb.emr.sbadm.immunization
SanteIMS Immunization (tracked material) administration.
1.3.5.1.4.1.52820.5.2.5.1
org.santedb.emr.enc.children.healthyVisit
SanteEMR/IMS Childhood Healthy Visit Encounter (regular encounter for children under 10 for weight/height, immunizations)
1.3.6.1.4.1.52820.5.2.6
org.santedb.ims.container.functionalStatus
SanteIMS functional status observation of a container/fridge.
Clinical Protocol
Administration of routine mabendazole treatment.
1.3.5.1.4.1.52820.5.3.2.1
Clinical Protocol
Administer Bacillus Calmette-Guerin Vaccine to children within 2 days of birth.
1.3.5.1.4.1.52820.5.3.2.2
Clinical Protocol
Administer DTP-Hib-HepB trivalent to children three times. First dose occurring 42 days after birth (recommended between 42-49 days), second and third doses administered 28-35 days after previous dose.
1.3.5.1.4.1.52820.5.3.2.3
Clinical Protocol
When child is under 18 months of age, administer MR1 dose at 274 days after birth, with second dose on or after 18th birthday
1.3.5.1.4.1.52820.5.2.3.2.3.1
Clinical Protocol
Accelerated MR Schedule: When child is older than 18 months and has not received MR1, administer MR1 immediately and administer MR2 1 months after first dose.
1.3.5.1.4.1.52820.5.2.3.2.4
Clinical Protocol
Regular PCV13 vaccination schedule for children under 5 years old.
1.3.5.1.4.1.52820.5.2.3.2.5
Clinical Protocol
Regular Oral Polio Vaccination Computation Schedule
1.3.5.1.4.1.52820.5.2.3.2.6
Clinical Protocol
Oral Polio Vaccine Birth Dose Computation Protocol
1.3.5.1.4.1.52820.5.2.3.2.7
Clinical Protocol
Administration of Human Papilloma Virus (HPV) vaccine after 9 years of age
1.3.5.1.4.1.52820.5.2.3.2.8
Clinical Protocol
Administration of Inactivated Polio Virus Vaccine (IPV)
.4 - Place Identity .5 - Act Identity
1.3.6.1.4.1.33349.3.1.5.9
0
Services
1.3.6.1.4.1.33349.3.1.5.9
2
Privacy & Security
1.3.6.1.4.1.33349.3.1.5.9
3
Concepts & Vocabulary
1.3.6.1.4.1.52820.5
1.3.6.1.4.1.33349.3.1.5.9.2
Unrestricted All
1.3.6.1.4.1.33349.3.1.5.9.2.0
Unrestricted Administrative Function
1.3.6.1.4.1.33349.3.1.5.9.2.0.1
Change Password
1.3.6.1.4.1.33349.3.1.5.9.2.0.2
Create Role
1.3.6.1.4.1.33349.3.1.5.9.2.0.3
Alter Role
1.3.6.1.4.1.33349.3.1.5.9.3.0
Concept Status
1.3.6.1.4.1.33349.3.1.5.9.3.1
Act Class
1.3.6.1.4.1.33349.3.1.5.9.3.2
Act Mood
1.3.6.1.4.1.33349.3.1.5.9.3.3
Act Status
1.3.6.1.4.1.33349.3.1.5.9.3.4
Act Relationship Type
1.3.6.1.4.1.52820.5.1.0
ELB
Demoland MPI
1.3.6.1.4.1.52820.5.1.1
MY
Myanmar National MPI Myanmar OpenMRS Identifiers
1.3.6.1.4.1.52820.5.1.2
SB
Solomon Islands National MPI
1.3.6.1.4.1.52820.5.2.0.1
org.santedb.emr.patient
SanteEMR Generic Patient Registration
1.3.6.1.4.1.52820.5.2.0.2
org.santedb.emr.patient.baby
SanteEMR Newborn Patient Registration
1.3.6.1.4.1.52820.5.2.1.1
org.santedb.emr.observation.cod
SanteEMR Cause Of Death (Suspected) Entry
1.3.6.1.4.1.52820.5.2.1.2
1.3.5.1.4.1.52820.5.3.1.1
Clinical Protocol
Collect weight of children under 5 years of age at minimum, once per month.
1.3.5.1.4.1.52820.5.3.1.2
Clinical Protocol
Collect height and/or length of children under 5 years of age at minimum, once per month.
1.3.5.1.4.1.52820.5.3.1.3
Clinical Protocol
Administration of routine Vitamin A supplements.
1.3.6.1.4.1.52820.5.4.2.1
SIMS_MANUFACTURER
SanteIMS Manufacturer Code
1.3.6.1.4.1.52820.5.4.4.1
PDH_FAC_UNIT_ID
Pacific Data Hub Facility Import Identifier
1
1.3.6.1.4.1.33349.3.1.5.9.2.0.4
1.3.6.1.4.1.33349.3.1.5.9.3.6
org.santedb.emr.observation.birthDeliveryLocation
1.3.5.1.4.1.52820.5.3.1.4
