⚠️ 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.
| Overview | Patients | Drug interactions | Clinical decision support |
|---|---|---|---|
![]() |
![]() |
![]() |
![]() |
| 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.
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 |
┌─────────────────────── 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.
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:3200The project is configured for max-strict TypeScript (strict,
noUncheckedIndexedAccess, exactOptionalPropertyTypes, verbatimModuleSyntax).
A change is not done until npm run gate is green.
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.
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.md
— do not file vulnerabilities as public issues.
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.
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.





