Opens in a new tab
Epidemiology & Technology

Running WHO ICD-11 and DORIS Natively In-Process in Rust — Zero Docker, and 100% Offline

As countries transition their Civil Registration and Vital Statistics (CRVS), Medical Certification of Cause of Death (MCCD), and Verbal Autopsy (VA) systems to the World Health Organization’s International Classification of Diseases, 11th Revision (ICD-11), two official WHO software engines play a central role:

  1. WHO ICD-11 API & Offline Coding Tool (2.6.0, 2026-01 MMS Release): Provides lexical/flexisearch lookup, stem-code and postcoordination cluster validation (1B12.2&XA0G74), diagnostic autocoding, and the Embedded Coding Tool and Browser.
  2. WHO DORIS (1.2.0 — Digital Open Rule Integrated Cause of Death Selection) & CoDEdit: Applies the official WHO mortality selection and modification rules (SP1–SP8, M1–M4) to Part 1 and Part 2 of a death certificate to determine the single Underlying Cause of Death (UCOD), while running CoDEdit plausibility checks on age, sex, maternal, perinatal, and external-cause fields.

Docker Isn’t Always an Option

For local/offline deployments, WHO distributes the ICD-11 API and DORIS engine as a Docker container (whoicd/icd-api:2.6.0). While convenient in cloud Kubernetes clusters, a Docker container poses major friction for offline Primary Health Centers (PHCs), desktop clinical coding workstations, and air-gapped hospital servers:

  • Requires Docker Desktop / Docker Engine: Field workstations and locked-down hospital PCs rarely permit background hypervisors or root Docker daemons.
  • Published as linux/amd64 Only: On Apple Silicon Macs (aarch64-apple-darwin) and ARM64 Linux devices, running whoicd/icd-api:2.6.0 requires QEMU/Rosetta x86_64 CPU emulation inside a Linux VM.
  • No Built-In Cryptographic Pinning or PII Guardrails: Clinical applications need deterministic verification that the underlying classification protobufs (*.pbf), DORIS rule tables (Rules.json), and assemblies have not been tampered with, and must guarantee that patient identifiers (names, phone numbers, Aadhaar/national IDs) never cross into the coding engine.

Wait — what is actually inside whoicd/icd-api:2.6.0?
Under the hood, WHO’s ICD-API.dll, DorisRuleEngine.dll, OCT.dll, ICDTextAnalyzers.dll, and Expressions.dll are portable, architecture-independent AnyCPU CIL (.NET 8) assemblies! They do not contain x86_64-specific machine code at all.

That insight led us to build who-icd11-api — a native Rust in-process DLL host, pure-Rust OCI/CDN bootstrapper, and zero-Docker server for WHO ICD-11 2.6.0 and DORIS 1.2.0.


How who-icd11-api Works

1. Native In-Process .NET Hosting via libhostfxr (src/hostfxr.rs)

Instead of spinning up a Docker container or compiling C# code at build time, who-icd11-api dynamically loads the host platform’s native .NET 8+ runtime (libhostfxr.dylib on macOS Apple Silicon/Intel, libhostfxr.so on Linux, or hostfxr.dll on Windows) directly inside the Rust process via libloading:

  1. Zero dotnet build Required: Our 13 KB unmanaged C-ABI bridge (DigitvaIcd11Bridge.dll) is pre-compiled AnyCPU CIL and embedded directly inside the Rust crate via include_bytes!.
  2. Direct [UnmanagedCallersOnly] Function Pointers: Rust calls hostfxr_initialize_for_runtime_config and load_assembly_and_get_function_pointer to obtain raw C-ABI function pointers into the hosted WHO assemblies.
  3. Native ARM64 & x86_64 Execution: On Apple Silicon (M1/M2/M3/M4) and ARM64 Linux, the .NET JIT compiles WHO’s ICD-API.dll and DorisRuleEngine.dll directly to native ARM64 instructions with zero x86_64 emulation overhead.

2. Pure-Rust Zero-Docker Bootstrapper with Cryptographic SHA-256 Pinning (src/bootstrap.rs)

You do not even need Docker installed to obtain the WHO DLLs or offline 2026-01 data. When who_icd11_api::ensure_runtime_bundle runs on a fresh machine:

  1. Direct OCI Layer Streaming in Pure Rust: Authenticates against registry-1.docker.io, fetches the whoicd/icd-api:2.6.0 OCI Image Index and manifest, streams the compressed /usr/share/icdapi layer blob over HTTPS (ureq + flate2 + tar), and strips Linux-only native RID entries from ICD-API.deps.json so the bundle runs portably on macOS, Linux, and Windows.
  2. Offline 2026-01_en & DORIS 1.2.0 Data Acquisition: Downloads the official 2026-01 MMS/ICF Protobuf release (icd11_2026-01-17_release-icf-mms_en.pbf.gz), Lucene/Protobuf search index (ix_(2026-01-17)_foundation-icf-mms_en_v5.7.pbf.zip), and DORIS knowledge base (DORIS_v2.1_1.2.0.zip) directly from WHO’s CDNs.
  3. 89 Pinned SHA-256 Cryptographic Digests: Before loading a single assembly, Rust verifies the SHA-256 digest (sha2::Sha256) of all 79 .dll files in the bundle (PINNED_DLL_SHA256), the embedded bridge DLL, and all 10 offline WHO data & DORIS rule files (PINNED_DORIS_FILES_SHA256). Any byte mismatch aborts initialization immediately.
ArtifactPinned Version / SourceVerified SHA-256 Digest
OCI Image Indexwhoicd/icd-api:2.6.01b77eb6dc43e0c65a12e9e9340ad178493c93488e728d0d936507cc57ada1b7c
OCI /usr/share/icdapi Layerregistry-1.docker.iod4527f82f3377c545daf8ff6de89dff08d1467970ed1343b96c8a1a515860663
ICD-API.dllWHO ICD-11 API 2.6.00ab8e927fd4201526c1eac3792c8608fbf873d00c2c87c0d5065a97abb56011b
DorisRuleEngine.dllWHO DORIS 1.2.0c3c17cf191e3b2c0190aaef77f933d7bd81f0cdede0636d086737497437104fb
OCT.dllWHO Offline Coding Tool 2.6.00c761cdd87d8f4a3494d9775a18c69cab4ff8cd112481b19882ccc9f88df3ab9
DigitvaIcd11Bridge.dllEmbedded C-ABI Bridge 1.0.01783241ff66b061c4a15eeae66a07d29f4391848b6dce844859f807a3d850953
icd11_2026-01-17_release-icf-mms_en.pbf.gzicdcdn.who.int (2026-01_en)2fd67533b4c838723bd68b833a98ee6dab284339a6262f3f972251e97c331901
ix_(2026-01-17)_foundation-icf-mms_en_v5.7.pbfExtracted Index PBF (v5.7)cb64df32bb077a126ad339bab0fe61018cc857616293c7f3bcf974dcaaacbdaa
DORIS_v2.1_1.2.0/Rules.jsonExtracted DORIS 1.2.0 Rules6fc6c900c911dd582a6401e9aafeebe12892600126c915b9fc6ae5746ff1d6fa

3. Complete Clinical & Mortality Coding Pipeline in Rust (Icd11Engine)

who-icd11-api exposes both a high-level Rust API (Icd11Engine) and a standalone drop-in HTTP server (who-icd11-server):

  • Stem & Postcoordinated Cluster Resolution (codeinfo):
    Resolves single ICD-11 codes (BA41.Z -> Acute myocardial infarction, unspecified) and complex postcoordinated expressions (1B12.2&XA0G74 -> stem 1B12.2 + anatomy XA0G74), returning canonical stemId URIs and axis maps.
  • Lexical/Flexisearch (search) & Diagnostic Autocoding (autocode):
    Maps free-text clinical phrases ("acute myocardial infarction") directly to ICD-11 codes (BA41.Z) and Foundation/MMS URIs.
  • Foundation / MMS Entity Inspection (entity):
    Returns full postcoordinationScale axis definitions (required vs. allowed postcoordination axes and valid subtree URIs).
  • End-to-End Death Certificate Processing (process_certificate, doris, codedit):
  1. V1–V6 Certificate Normalization (normalize_certificate & drop_inapplicable_sections): Automatically strips inapplicable sections before calling DORIS — e.g., dropping FetalOrInfantDeath for ages > year, dropping DeathWithin24h for ages > days (P7D), dropping MaternalDeath for males or non-pregnant females, and stripping external-cause details when MannerOfDeath == 0 (Disease).
  2. URI & Code Verification (verify_certificate_codes): Verifies every condition code on Part 1 and Part 2 against codeinfo before mortality rule execution.
  3. DORIS 1.2.0 Underlying Cause Selection & CoDEdit Quality Audit: Executes both DorisRuleEngine.dll and CoDEdit and wraps the output with canonical SHA-256 certificate_digest and result_digest hashes for tamper-evident clinical audit logs.
  • Built-In Non-PII Clinical Boundary (src/privacy.rs):
    Automatically inspects every JSON payload and search string and rejects any request containing personal or civil-registration identifier keys (name, informant_phone, address, aadhaar, abha, identifiers, crs_number, mccd_number) or embedded 12-digit Aadhaar / 10-digit phone numbers (Icd11Error::PiiBoundaryViolation).
  • Embedded Coding Tool (/ct) & ICD-11 Browser (/browse):
    who-icd11-server also serves WHO’s interactive web-based Embedded Coding Tool (/ct/2026-01/mms/en) and ICD-11 Browser (/browse/2026-01/mms/en) locally for physician coding UIs.

Quick Start & Rust Code Example

1. Bootstrap & Run the Standalone Server (Zero Docker)

git clone https://github.com/drguptavivek/who-icd11-api.git
cd who-icd11-api

# 1. Bootstrap the portable DLL bundle + WHO 2026-01 & DORIS 1.2.0 data in pure Rust (no Docker required)
cargo run --release --bin who-icd11-server -- --bootstrap

# 2. Run the integration test suite (verifies all 79 DLLs, 10 data files, and 6 WHO DORIS reference certificates)
cargo test -- --nocapture

# 3. Launch the local drop-in WHO ICD-11 + DORIS HTTP server on 127.0.0.1:8382
cargo run --release --bin who-icd11-server -- --port 8382Code language: PHP (php)

2. Use Icd11Engine Directly In-Process in Rust

use serde_json::json;
use who_icd11_api::{Icd11Engine, SearchOptions};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Initializes (or reuses) the in-process WHO ICD-11 2.6.0 + DORIS 1.2.0 DLL host
    let engine = Icd11Engine::global()?;

    // 1. Autocode a clinical diagnosis phrase
    let auto = engine.autocode("acute myocardial infarction", None, None, None)?;
    println!("Autocoded URI & Code: {} -> {}", auto["theCode"], auto["foundationUri"]);

    // 2. Resolve a postcoordinated cluster expression
    let info = engine.codeinfo("1B12.2&XA0G74", None)?.unwrap();
    println!("Stem code: {}, Anatomy axis: {}", info["stemCode"], info["specificAnatomy"]);

    // 3. Run full V1-V6 normalization + DORIS 1.2.0 UCOD selection + CoDEdit audit on a death certificate
    let payload = json!({
        "schema_version": 1,
        "client_revision": 1,
        "certificate": {
            "ICDVersion": "ICD11",
            "AdministrativeData": { "Sex": 1, "EstimatedAge": "P44Y" },
            "Part1": [{
                "Conditions": [{
                    "Text": "Respiratory tuberculosis",
                    "Code": "1B10.Z",
                    "LinearizationURI": "http://id.who.int/icd/release/11/2026-01/mms/882244568/unspecified",
                    "Interval": "P14D"
                }]
            }]
        }
    });

    let result = engine.process_certificate(&payload, None, "rust-dll-2.6.0")?;
    println!("Selected Underlying Cause (DORIS): {}", result["doris"]["result"]["code"]);
    println!("CoDEdit Issue IDs: {}", result["codedit"]["result"]["issueIds"]);
    println!("Audit Digest: {}", result["result_digest"]);
    Ok(())
}Code language: PHP (php)

Credits, Acknowledgments & References

1. World Health Organization (WHO) ICD-11 & DORIS Team

  • World Health Organization (WHO): Classifications and Terminologies Unit (Division of Data, Analytics and Delivery for Impact) for developing and maintaining the International Classification of Diseases, 11th Revision (ICD-11) (2026-01 MMS Release), the ICD-11 API & Embedded Coding Tool (2.6.0), the DORIS (1.2.0 — Digital Open Rule Integrated Cause of Death Selection) mortality rule engine, and CoDEdit electronic death certificate verification tools.
  • WHO Family of International Classifications (WHO-FIC) Network & Mortality Reference Group (MRG): Specification and curation of the ICD-11 mortality selection and modification rules (SP1–SP8, M1–M4) implemented in DORIS.
  • CDC Foundation and University of New South Wales for support to DigitVA development
  • Indian Council for Medical Research’s support for Implementation and scaling up of model to achieve universal coverage with physician ascertained cause of death at district-level in India

2. Links & References

WHO ICD-11 API & Embedded Coding Tool: icd.who.int/icdapi

Repository & Source Code: github.com/drguptavivek/who-icd11-api

WHO ICD-11 Reference Guide & Mortality Rules: World Health Organization. ICD-11 Reference Guide (Section 2.21: Coding Instructions for Mortality — Selecting the Underlying Cause of Death). Geneva: WHO; icd.who.int/icd11refguide

WHO DORIS Documentation: World Health Organization. Digital Open Rule Integrated Cause of Death Selection (DORIS). icd.who.int/doris

Related Posts