- When running tasks (for example build, lint, test, e2e, etc.), always prefer running the task through
nx(i.e.nx run,nx run-many,nx affected) instead of using the underlying tooling directly - You have access to the Nx MCP server and its tools, use them to help the user
- When answering questions about the repository, use the
nx_workspacetool first to gain an understanding of the workspace architecture where applicable. - When working in individual projects, use the
nx_project_detailsmcp tool to analyze and understand the specific project structure and dependencies - For questions around nx configuration, best practices or if you're unsure, use the
nx_docstool to get relevant, up-to-date docs. Always use this instead of assuming things about nx configuration - If the user needs help with an Nx configuration or project graph error, use the
nx_workspacetool to get any errors
This is an Nx workspace designed to host a FHIR application stack.
This is an Nx workspace. Prefer running tasks through nx instead of underlying tooling.
# Install dependencies
bun install
# Start both server and frontend
bun serve
# Build all projects
bun run build
# Run all tests
bun run test# Run server directly with Maven
cd server && mvn spring-boot:run
# Run a single test class
cd server && mvn test -Dtest=OrderSelectServiceTest
# Run a single test method
cd server && mvn test -Dtest=OrderSelectServiceTest#testMethodName
# Build server WAR
cd server && mvn clean package -DskipTests# Run frontend dev server (port 3000)
cd frontend && bun dev
# Run frontend tests
cd frontend && bun test
# Lint/format
cd frontend && bun check # biome check
cd frontend && bun lint # biome lint
cd frontend && bun format # biome format
# Build and copy to server static resources
nx run frontend:copy-to-server- Path:
server/ - Type: Java / Maven / HAPI FHIR
- Description: The backend FHIR server.
- Structure:
src/main/java/ca/uhn/fhir/- HAPI starter code (do NOT modify)src/main/java/org/hl7/davinci/- Custom implementation code (all custom code goes here)api/- REST controllers for non-FHIR APIs (/api/crd/,/api/dtr/,/api/pas/)cdshooks/services/- CDS Hook implementations:OrderSelectService,OrderSignService,OrderDispatchService,AppointmentBookService,EncounterStartService,EncounterDischargeServicecdshooks/shared/- Shared CDS Hooks utilitiescommon/- Shared utilities (PlanDefinitionService,FhirCodeExtractor,FhirUtil,CrdConstants)config/- Spring configurationcql/- CQL file resolution and ELM compilationdatainitializer/- Startup resource loading and CQL compilationdtr/- DTR questionnaire pipeline (resolver, assemblers, response builder, session store,DtrConstants)pas/- PAS$submitand$inquireoperations: validation, coverage evaluation, response building, pended resolutionproviders/- Custom FHIR resource providersscenarios/- Test scenario generation from library PlanDefinitions, with sub-packagescrd/,dtr/,pas/
- Path:
frontend/ - Type: TanStack React Router SPA
- Description: Contains a frontend application for viewing and searching FHIR resources from the server.
- Path:
docs/ - Type: Markdown files
- Description: Contains project documentation, requirements, and design documents. Built using MkDocs.
- Path:
library/ - Type: FHIR Library resources and CQL files
- Description: Contains CQL libraries and associated FHIR resources for clinical decision support.
- Build Integration:
- Maven copies
library/contents totarget/classes/library/during build - For production, resources are bundled into the JAR/WAR
- External libraries from other repositories can also be bundled via Maven resources
- Maven copies
- Structure:
- Each subdirectory represents a library (e.g.,
HomeOxygenTherapy/) *.cqlfiles contain the CQL logicLibrary-*.jsonfiles are FHIR Library resources that reference the CQL filesPlanDefinition-*.jsonfiles define how the libraries are used
- Each subdirectory represents a library (e.g.,
- CQL File Resolution:
- Library JSON files can reference CQL files using
content.urlwith just the filename - The CQL file must be in the same directory as the Library JSON
- During server startup, the CQL content is automatically loaded and embedded
- Alternatively, Library resources can use base64-encoded
content.datadirectly
- Library JSON files can reference CQL files using
Test request fixtures for CRD, DTR, and PAS are auto-generated from library PlanDefinition metadata rather than hand-maintained as JSON files.
LibraryScenarioScannerscans thelibrary/directory for PlanDefinition + Questionnaire pairs, extractingScenarioMetadata(focus codes, hook triggers, order types, questionnaire URLs)- Each IG has a scenario service and request builder pair in
scenarios/crd/,scenarios/dtr/,scenarios/pas/sub-packages that transform metadata into valid request JSON TestRequestFileGeneratorruns at build time (process-classesphase via Maven exec plugin) and writes generated files totarget/test-requests/
target/test-requests/
dtr/
home-oxygen-therapy-canonical-request.json
home-oxygen-therapy-order-request.json
...
crd/
order-sign/
home-oxygen-therapy-order-sign.json
...
order-select/
...
appointment-book/
...
order-dispatch/
...
Spring services (CrdScenarioService, DtrScenarioService, PasScenarioService) expose the same generated content via REST endpoints. These scan the FHIR database at request time, so they reflect the current server state.
| Endpoint | Description |
|---|---|
GET /api/crd/scenarios |
List all CRD test scenarios |
GET /api/crd/scenarios/{id}/hooks/{hookName} |
Raw CDS Hooks request JSON for a hook variant |
GET /api/dtr/scenarios |
List all DTR test scenarios |
GET /api/dtr/scenarios/{id}/requests/{type} |
Raw FHIR Parameters JSON for a DTR variant |
GET /api/pas/scenarios |
List all PAS test scenarios |
GET /api/pas/scenarios/{id}/variants/{variantId} |
Raw FHIR Bundle JSON for a PAS variant |
Adding a new PlanDefinition + Questionnaire to library/ automatically generates DTR and CRD test fixtures at build time and makes them available via the REST API. No manual fixture authoring needed.
Some test fixtures remain hand-crafted in src/test/resources/cdshooks/ because they test edge cases not derivable from PlanDefinition metadata: error/validation scenarios, multi-order requests, encounter-based hooks, and visit-limit exceeded cases.
This server implements the Da Vinci Burden Reduction implementation guides. Always consult these when implementing features:
| IG | Build URL | Key Sections |
|---|---|---|
| CRD (Coverage Requirements Discovery) | https://build.fhir.org/ig/HL7/davinci-crd/en/ | Hooks, Cards, CodeSystem |
| DTR (Documentation Templates and Rules) | https://build.fhir.org/ig/HL7/davinci-dtr/en/ | Specification, Expected Systems |
| PAS (Prior Authorization Support) | https://build.fhir.org/ig/HL7/davinci-pas/en/ | Specification |
| CDS Hooks | https://cds-hooks.org/specification/current/ | Discovery, HTTP Response |
Important: This server is a payer implementation. It does NOT implement provider/EHR-side functionality like DTR SMART apps.
| Component | Location | Purpose |
|---|---|---|
| Hook Services | server/src/main/java/org/hl7/davinci/cdshooks/services/ |
Individual hook implementations (OrderSelectService, OrderSignService, etc.) |
| Shared Logic | server/src/main/java/org/hl7/davinci/cdshooks/shared/ |
Base classes, resource resolution, coverage info handling |
| Configuration | server/src/main/java/org/hl7/davinci/cdshooks/CdsHooksConfig.java |
Spring configuration for CDS hooks |
| CRD Scenarios | server/src/main/java/org/hl7/davinci/cdshooks/CrdScenarioService.java |
Generates CRD test scenarios from PlanDefinition metadata |
| CRD Request Builder | server/src/main/java/org/hl7/davinci/scenarios/CrdRequestBuilder.java |
Builds CDS Hooks request JSON from ScenarioMetadata |
| CRD REST API | server/src/main/java/org/hl7/davinci/api/CrdScenarioController.java |
REST endpoints under /api/crd/ |
- Create a new service class extending
CdsServiceBase - Annotate with
@CdsServicespecifying hook name, prefetch templates - Implement
getHookName(),validateResourceContext(),selectContextResources() - The service is auto-discovered via Spring component scanning
Use CrdConstants.CARD_TYPE_SYSTEM for source.topic:
coverage-info,insurance,network,cost,therapy-alternatives-req, etc.- See CRD CardType ValueSet
| Provider | Operation | Notes |
|---|---|---|
ClaimSubmitProvider |
Claim/$submit |
PAS prior authorization submission |
ClaimInquiryProvider |
Claim/$inquire |
PAS authorization status inquiry |
QuestionnairePackageProvider |
Questionnaire/$questionnaire-package |
DTR questionnaire packaging |
DtrQuestionnaireNextQuestionProvider |
Questionnaire/$next-question |
DTR adaptive questionnaire |
LogQuestionnaireErrorsProvider |
Questionnaire/$log-questionnaire-errors |
Stub -- throws NotImplementedOperationException |
| Component | Location | Purpose |
|---|---|---|
| Submit Provider | providers/ClaimSubmitProvider.java |
Thin REST layer for $submit |
| Inquiry Provider | providers/ClaimInquiryProvider.java |
Thin REST layer for $inquire |
| Submit Service | pas/PasSubmitService.java |
Orchestrates submit: validates, detects type, routes to handlers, stores Claim, builds response |
| Inquiry Service | pas/PasInquiryService.java |
Query-by-example search against stored ClaimResponses |
| Bundle Validator | pas/PasBundleValidator.java |
Validates request bundles per PAS IG structural constraints |
| Reference Resolver | pas/PasBundleReferenceResolver.java |
Resolves Patient/Organization/Coverage references from bundles |
| Coverage Evaluator | pas/PasCoverageEvaluator.java |
Bridges CRD PlanDefinitions to X12 review action codes (A1/A3/A4) |
| Response Builder | pas/PasResponseBuilder.java |
Constructs conformant ClaimResponse bundles with auth numbers |
| Pended Resolution | pas/PasPendedResolutionService.java |
Schedules one-shot auto-approval tasks for pended items |
| Extensions | pas/PasExtensions.java |
PAS extension URLs, profile URLs, X12 review codes, builder helpers |
| Properties | pas/PasProperties.java |
Config: pas.pended-resolution-delay-seconds, pas.authorization-number-prefix |
PasBundleValidatorvalidates the request bundle structurePasBundleReferenceResolverresolves Patient/Organization/Coverage from the bundlePasSubmitServicedetects submission type (INITIAL/RENEWAL/UPDATE/CANCEL) via structural Claim properties (presence ofClaim.related), notmeta.profile- Routes to type-specific handlers
PasCoverageEvaluatorevaluates coverage using the same PlanDefinitions that drive CDS Hook cards, translating CRD outcomes to X12 review action codes: A1=Certified, A3=Not Certified, A4=PendedPasResponseBuilderconstructs the ClaimResponse bundle with authorization numbers- Items evaluated as A4 (Pended) are tagged with an internal meta tag;
PasPendedResolutionServiceschedules one-shot tasks to auto-approve afterpas.pended-resolution-delay-seconds
- Pended ClaimResponses are tagged with
http://example.org/fhir/us/davinci-pas/internal-tags/pended-resolution PasPendedResolutionServiceusesTaskSchedulerto schedule one-shot resolution tasks- On server restart, it rescans for tagged ClaimResponses and reschedules or immediately resolves them
- Tags are removed via
metaDeleteOperation(necessary because HAPI JPA treats tags as additive across versions)
- Create a directory under
library/(e.g.,library/MyNewRule/) - Create the CQL file (
MyNewRule.cql) with coverage logic - Create a Library resource (
Library-MyNewRule.json) referencing the CQL - Create a PlanDefinition (
PlanDefinition-MyNewRule.json) with:useContextfor order codes (focus) and payor identifiers (program)triggerwithtype: named-eventandname: order-selectororder-signactionreferencing the Library
PlanDefinitions are matched based on:
- Order code:
useContextwithcode.code = "focus"and value matching the order's code - Payor identifier:
useContextwithcode.code = "program"and value matching Coverage.payor - Hook type:
action.trigger.namematching the hook (e.g.,order-select)
- Documentation for CQL authoring can be found at the following links:
- Shared CQL libraries are located in
library/common/and should be used as much as possible to avoid duplication - Newly identified redundant CQL should be refactored into
library/common/as appropriate - If possible, add symlinks to the new CQL in the
input/cql/directory for VS Code extension support and edit these instead of the originals
CQL should output a FHIR Extension matching ext-coverage-information. The extension is extracted from the RequestGroup returned by PlanDefinition/$apply.
FHIR URL constants (profiles, extensions, code systems) are organized by implementation guide into dedicated classes. New constants should be placed in the class matching their IG.
| IG | Class | Package | Contents |
|---|---|---|---|
| CRD | CrdConstants |
common |
Coverage info extension, doc reason code system, card type system |
| DTR | DtrConstants |
dtr |
Questionnaire/QR profiles, DTR + SDC extensions, CQL expression URLs, adaptive mode header, canonical prefixes |
| PAS | PasExtensions |
pas |
PAS extension URLs, profile URLs, X12 review codes, extension builder helpers |
CrdConstants is in common/ because CRD constants are referenced from both the cdshooks and dtr packages. DTR and PAS constants live within their respective packages.
- Main:
server/src/main/resources/application.yaml - CDS profile:
server/src/main/resources/application-cds.yaml(loads CQL IGs, stricter ValueSet expansion) - Test:
server/src/test/resources/application-test.yaml - VSAC integration: set
VSAC_API_KEYenv var (bean activates conditionally) - DTR adaptive config:
dtr.adaptive.next-question-url - DTR warmup:
dtr.valueset-warmup.enabled(pre-expands ValueSets at startup) - PAS config:
pas.pended-resolution-delay-seconds(default 15s),pas.authorization-number-prefix(defaultAUTH-)
| Profile | Default | Purpose |
|---|---|---|
boot |
Yes | Spring Boot embedded Tomcat (development) |
jetty |
No | Replace Tomcat with Jetty (mvn -Pjetty spring-boot:run) |
- Do NOT modify HAPI starter code in
src/main/java/ca/uhn/fhir/- place custom code inorg.hl7.davinci - Payer-only scope - This server implements payer operations; DTR app launch URLs are provider-side concerns
- CodeSystem for card types - Use
CrdConstants.CARD_TYPE_SYSTEM, not hardcoded URLs - Coverage extension - Always include required elements:
coverage,covered,date,coverage-assertion-id - IG constants - Place new FHIR URL constants in the correct IG constants class (see table above), not inline in consuming classes
- PAS reuses CRD PlanDefinitions - Coverage logic is shared between CRD and PAS via
PasCoverageEvaluator - PAS submission type detection - Structural (presence of
Claim.related), not profile-based - H2 in-memory database - Data is transient and reloaded each startup