Skip to content

SafetyMP/Asclepius

Asclepius — FHIR-native Clinical Data Platform

CI CodeQL OpenSSF Scorecard License: Apache-2.0 Node

⚠️ NOT FOR CLINICAL USE. Asclepius is a reference implementation that demonstrates the architecture of a FHIR-native clinical data platform. It is not HIPAA-certified, not a regulated medical device, and its drug-interaction knowledge base is intentionally incomplete. Do not store, process, or base clinical decisions on real patient data with this software. See the regulatory disclaimer below.

A from-scratch, layered implementation of the pillars of a clinical data platform, built to be correct and testable rather than feature-complete. Every architectural choice is documented with first-principles reasoning and an honest "better tool for production" callout in Architecture Decision Records.

Asclepius FHIR console — overview, patients, drug interactions, and clinical decision support (synthetic demo data)

Screenshots

Overview Patients Drug interactions Clinical decision support
Overview Patients Drug interactions Clinical decision support
Validate resource
Validate resource

The clinical reference console in web/ explores the FHIR API locally. Run npm run dev for the API (port 8787), then cd web && npm install && npm run dev on port 3200. Regenerate visuals with cd web && npm run screenshots; see docs/assets/README.md.

Synthetic demo data only — NOT FOR CLINICAL USE.

Status

This is a reference implementation — core pillars are built and tested; see the Status table below for what exists today.

Pillar Implementation Status
FHIR R4 resource model Hand-authored zod schemas (single source of truth → inferred TS types); 9 resources, primitives, datatypes, Bundle, OperationOutcome ✅ Built
Storage ResourceRepository port + in-memory versioned adapter (immutable snapshots, history, soft delete) ✅ Built
Storage (persistent) SQLite adapter via better-sqlite3 (WAL, JSON columns); selected by STORAGE=sqlite ✅ Built (ADR 0004)
FHIR search Hand-built query-plan compiler (param types, modifiers, prefixes) + executor (path extraction, per-type matching, reference chaining, _sort/_count/_page) ✅ Built
REST API Hono HTTP adapter: create/read/vread/update(+create-on-update)/delete, ETag/Location/versioning, instance + type history Bundles, search (GET ?params + POST _search → searchset Bundle, incl. reference chaining + self/next/prev pagination links), OperationOutcome errors ✅ Built (ADR 0005)
Validation zod structural validation + profile-level rules (Patient identity, Observation code system, MedicationRequest medication[x]); $validate operation (POST /{Type}/$validate) + create/update gating ✅ Built
Clinical Decision Support Composable rule DSL (pure functions PatientContext → CdsCard[]) + CDS Hooks endpoint (POST /cds-services/:id); MVP rules: drug-allergy + warfarin-NSAID bleeding risk ✅ Built (ADR 0007)
Drug–drug interactions In-memory knowledge base (6 RxNorm interactions) + bidirectional checker; POST /MedicationRequest/$check-interactions endpoint + DDI CDS rule ✅ Built
AuthN/AuthZ JWT (HS256, jose) + SMART-style scope middleware (system/Patient.read, user/*.write); dev-only /auth/token issuer (prod-disabled). Patient-compartment filtering + role-based overrides deferred ✅ Built (ADR 0008)
Audit Hash-chained, append-only, tamper-evident log (SHA-256 chain; in-memory + SQLite adapters; every request recorded via middleware) ✅ Built (ADR 0009)
Web console Next.js reference UI in web/ — patient search, DDI check, CDS, validation, dev auth (BFF → FHIR API) ✅ Built

Architecture (ports & adapters)

        ┌─────────────────────── HTTP (entry) ────────────────────────────────┐
        │  adapter/http · adapter/auth · adapter/audit                       │
        └───────────────────────────────┼───────────────────────────────────┘
                                        │ depends on ports only
        ┌───────────────────────────────▼───────────────────────────────────┐
        │  service: search · validation · cds · ddi   (application logic)    │
        └───────────────────────────────┼───────────────────────────────────┘
                                        │ depends on domain only
        ┌───────────────────────────────▼───────────────────────────────────┐
        │  domain: fhir resources · value objects · OperationOutcome         │
        └───────────────────────────────┼───────────────────────────────────┘
                                        │ port interfaces
        ┌───────────────────────────────▼───────────────────────────────────┐
        │  adapter/storage: in-memory · sqlite   (port implementations)      │
        └───────────────────────────────────────────────────────────────────┘

Target layered architecture — the Status table is the source of truth for what is implemented today.

Dependencies point inward: domain depends on nothing; service depends on domain + port; adapters depend on port + domain. src/app.ts is the single composition root that wires adapters to services.

Getting started

Requires Node.js ≥ 22 (see .nvmrc for the dev version).

npm install              # dependencies (builds better-sqlite3's native module)
npm run dev              # run via tsx (no compile step), hot reload — http://127.0.0.1:8787
npm test                 # run the test suite
npm run gate             # format:check → lint → typecheck → test → build

# Optional: clinical reference console (requires API above)
cd web && npm install && npm run dev   # http://localhost:3200

The project is configured for max-strict TypeScript (strict, noUncheckedIndexedAccess, exactOptionalPropertyTypes, verbatimModuleSyntax). A change is not done until npm run gate is green.

Why these tools (and where there's a better one)

Every component choice is documented with its first-principles rationale and an honest "better tool for production" callout in docs/adr/. Summary:

  • TypeScript — models FHIR's structural types; compiler verifies shape. Production FHIR servers: Java (HAPI) or .NET (Firely).
  • zod — single source of truth for types + runtime validation. Full FHIR profiling: Firely validator.
  • In-memory + SQLite — zero-config real persistence + fast tests. Scale: Postgres + JSONB/GIN.
  • Hono — web-standard, portable, fast. Larger ecosystem: Fastify.
  • Hand-built search — the hard core; no library does FHIR search correctly. Scale: Elasticsearch.
  • CDS rule DSL — testable pure functions. Production: CQL.
  • JWT + scopes — models FHIR's resource/action access. Production: full SMART-on-FHIR OAuth2 via a real IdP.

See docs/adr/ for the full reasoning on each.

Contributing

Contributions are welcome. Please read CONTRIBUTING.md (the npm run gate requirement, code style, and the ADR-first decision process) before opening a pull request. For security issues, see SECURITY.mddo not file vulnerabilities as public issues.

Regulatory disclaimer

Asclepius is a reference / educational implementation. It is not a certified medical device, is not HIPAA- or HITRUST-compliant, and carries no warranty of fitness for any clinical purpose. The DDI knowledge base is intentionally incomplete; missing interaction data is a patient-safety hazard. Never connect this software to real clinical systems, pharmacies, or EHRs, or use it to store or make decisions about real patient data.

License

Licensed under the Apache License, Version 2.0. See LICENSE and NOTICE.md. Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, express or implied.

About

Asclepius — a FHIR-native clinical data platform (reference implementation, NOT for clinical use).

Topics

Resources

License

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors