# EHR Retrieval Microservice Technical Design This document describes the technical implementation of the EHR Retrieval Microservice. **Contents** ## Meta - Status: For Review - Authors: Will Drewes - Last updated: 2020-03-13 - Created: 2020-03-13 - [Feature Home](https://science37.atlassian.net/wiki/spaces/TECH/pages/683377151/Medical+Records+Retrieval+-+Version+1.0) - [Feature Activity Diagram](https://science37.atlassian.net/wiki/spaces/TECH/pages/606044170/1UpHealth+Medical+Record+Retrieval+Activity+Diagram) - [Proof of Concept Documentation](https://science37.atlassian.net/wiki/spaces/TECH/pages/568787115/Proof+of+concept ) - [Slides For Overall Backend Design](https://docs.google.com/presentation/d/1SdCwpS-56XGX6t7deoGJU0R5z_uBaYOFKA2G2vXiJTI/edit#slide=id.g70256bda43_0_141) ### Mermaid Diagrams - This document contains [Mermaid](https://mermaidjs.github.io/) diagrams - Install the [Chrome Mermaid Extension](https://chrome.google.com/webstore/detail/github-%2B-mermaid/goiiopgdnkogdbjmncgedmgpoajilohe?hl=en-US) to view diagrams in files on github - Install the [VSCode extension](https://marketplace.visualstudio.com/items?itemName=bierner.markdown-mermaid) ## Glossary | Term | Description | |---------|------------------------| | [FHIR®](https://www.hl7.org/fhir/overview.html) | FHIR (Fast Healthcare Interoperability Resources) Specification, which is a standard for exchanging healthcare information electronically. We will be using the JSON representation of the FHIR® | [EHR](https://www.healthit.gov/faq/what-electronic-health-record-ehr) | "An electronic health record (EHR) is a digital version of a patient’s paper chart. EHRs are real-time, patient-centered records that make information available instantly and securely to authorized users. While an EHR does contain the medical and treatment histories of patients, an EHR system is built to go beyond standard clinical data collected in a provider’s office and can be inclusive of a broader view of a patient’s care. EHRs are a vital part of health IT and can: Contain a patient’s medical history, diagnoses, medications, treatment plans, immunization dates, allergies, radiology images, and laboratory and test results Allow access to evidence-based tools that providers can use to make decisions about a patient’s care Automate and streamline provider workflow" |[1upHealth](https://1up.health/) | 1upHealth provides a common RESTful API across [10,000+ health centers](https://1up.health/health-systems) Access 280 million patients. This API fully supports FHIR® and provides rich programmatic access to electronic medical record data for patients. 1upHealth provides APIs that facilitate redirecting offsite to a provider (e.g. Kaiser Permanente) where they authenticate and grant access before being redirected back to the application where the app can retrieve the FHIR® records using the user's token. The available FHIR® data includes patient demographics, labs, medications, observations, procedures, allergies, and more. ## Tickets | Ticket | Description | | ------ | ----------- | | TBD | User story | | TBD | Backend implementation | ## References - [1upHealth Developer Documentation](https://1up.health/dev) - [1upHealth API Reference](https://1up.health/dev/reference) - [1upHealth Quick Start Guide](https://1up.health/dev/quick-start) - [1upHealth User Management API](https://1up.health/dev/doc/user-management) - [1upHealth Provider Search UI and API](https://1up.health/dev/doc/provider-search-ui) - [1upHealth Provider Connect Provider Search](https://1up.health/dev/doc/connect-provider-search) - [1upHealth Connect Health System EHRs](https://1up.health/dev/doc/ehr-data) - [1upHealth FHIR® \$everything query](https://1up.health/dev/doc/fhir-everything-query) - [1upHealth FHIR® Subscriptions / Alerts](https://1up.health/dev/doc/fhir-subscription) - [1upHealth FHIR® Delete a resource](https://1up.health/dev/doc/fhir-delete) - [1upHealth FHIR® Supported Fhir Resources](https://1up.health/dev/reference/fhir-resources) ## Unknowns | Item | Question | | -------- | -------- | | 1 | Are there any audit trail/log requirements? | | 2 | Does each environment need a different app client and `redirect_uri`? | | 3 | Should the service be responsible for maintaining a reference to the corresponding medical release form (MRF) for each retrieval per provider? | ## Deferred Features | Item | Description | | -----| -------- | | 1 | Manage FHIR® subscriptions | | 2 | Delete participant FHIR® data from 1upHealth | | 3 | Service wraps requests to 1upHealth Provider Search and Connect APIs, abstracting the authentication, authorization, and token refresh and management. This Provides a unified Science 37 API, using only NORA access tokens, such that the client does not have to implement any 1upHealth APIs directly, and any subsequent changes to the 1upHealth APIs can be centrally managed.| ## Risks | Item | Description | |-|-| |1|A third party obtains Science 37's 1upHealth client secret. This is unlikely as long as we ensure that this value is used only on backend servers, stored in parameter store and never exposed.| |2|Once a user has granted access to their EHRs, 1upHealth syncs data from the provider EHR system into a user's FHIR® resources via a backend process every 2 minutes. The $everything (paginated) API call to get all FHIR® resources could be a very long-running process. These processes could be interrupted.| |3|1upHealth access tokens expire after 2 hours. 1upHealth tokens could expire before the user has completed connecting their provider EHR. e.g. the user goes to make a sandwich and comes back. This is unlikely to happen with the short NORA timeout on the patient profile. | ## Purpose This service manages the relationship between participant NORA accounts and their corresponding 1upHealth S37 application connections ***on a per-trial basis.*** Although there could be other EHR integration providers in the future, ***the current implementation only supports the 1upHealth Integration.*** The service maintains a record of every EHR access that the user has granted, allowing it to retrieve and store the FHIR in amazon s3 once they become available. ## Project Phases Due to time and resource constraints, the project must be divided into phases. **Phase 1** Provides a means of managing and authenticating the 1upHealth user and issuing an access token from 1upHealth so that the client can make subsequent calls to 1upHealth API directly. The client is also responsible for checking the validity of the access token and re-authenticating when needed. **Phase 2** Abstracts and wraps all 1upHealth API endpoints and authenticates requests with only the NORA access token such that the client does not even need to be aware that it is using 1upHealth's API. 1upHealth token refresh is handled automatically. 1upHealth access and refresh tokens are encrypted and stored in the microservice database. ## Service Activities: `Note: P1 indicates Phase 1, P2 indicates Phase 2` **Authentication / Authorization** | Phase | Description | | -----| -------- | | 1 | Manages app client credentials for S37’s 1upHealth OAuth 2.0 Application | | 1 | Creates a participant's 1upHealth user in S37's 1upHealth OAuth 2.0 Application| | 1 | Stores the NORA <-> 1upHealth account association | 1 | Authenticates the participant in S37's 1upHealth OAuth 2.0 Application. | 1 | Authorizes user access via NORA JWT Tokens signed by API Gateway containing NORA user-id claim which can be used to associate the authenticated NORA user with the corresponding 1upHealth S37 app user | 1 | Checks if 1upHealth token expired so the client knows that it must re-authenticate. | 2 | Stores 1upHealth access (bearer) and refresh tokens. | 2 | Refreshes 1upHealth User Access Tokens | **Provider Search** It allows the user to search all of the health providers of 1upHealth. A search term can be a doctor's name, clinic, hospital, or address. | Phase | Description | | -----| -------- | | 1 | No service implementation needed. The client uses [1upHealth Provider Search](https://1up.health/dev/doc/connect-provider-search) API directly with 1upHealth access token | | 2 | Service wraps and authenticates requests to [1upHealth Provider Search](https://1up.health/dev/doc/connect-provider-search) API using NORA access token. | **Connect Health System EHRs** Facilitates redirecting to the EHR provider's handshake. This allows the user to click on a provider from the Provider Search results and be redirected to the EHR provider's portal where they log in, grant access to medical records and be redirected back to the S37 1upHealth application's configured `Redirect URL`. | Phase | Description | | -----| -------- | | 1 | No service implementation needed. The client uses [1upHealth Connect Health System EHRs](https://1up.health/dev/doc/ehr-data) API directly with 1upHealth access token | | 2 | Client uses EHR Retrieval Service which wraps and authenticates requests to [1upHealth Connect Health System EHRs](https://1up.health/dev/doc/ehr-data) API using NORA access token. | **Retrieve & Store FHIR Data for Participant** Orchestrates the call to [1upHealth FHIR® \$everything query](https://1up.health/dev/doc/fhir-everything-query) API using the user's access token, and stores the response into specified s3 bucket. | Phase | Description | | -----| -------- | | 1 | When the user is redirected back to S37 1upHealth application's configured `Redirect URL` after granting S37's 1upHealth application access to the medical record resources in the provider's EHR portal. | **Delete Participant FHIR Data from 1upHealth** | Phase | Description | | -----| -------- | | 2 | Deletes the health records from 1upHealth after they have already been stored on s37's servers via the [1upHealth FHIR® Delete a resource](https://1up.health/dev/doc/fhir-delete) API. This ensures that data is not only stored securely within S37 only but also eliminates the storage charges billed by 1upHealth. | **Manage FHIR Subscriptions** | Phase | Description | | -----| -------- | | 2 | Using the [1upHealth FHIR® Subscriptions / Alerts](https://1up.health/dev/doc/fhir-subscription) API, create a subscription to a participant's FHIR records. This means that S37 can be notified for a creation or update event for any FHIR® Resource that matches a FHIR® query. You can make the FHIR® query anything acceptable by FHRI APIs. Periodically (currently in 5-minute intervals), 1upHealth will check for any new or updated resources matching any FHIR® Subscription for a user and post that data to a secure endpoint hosted/specified by S37 | ## NORA EHR Retrieval Use Case Activity Diagram https://www.lucidchart.com/documents/view/55d25569-6612-4e6d-b209-6f8277bab2a8# ## Service Topology ```mermaid graph TD F[NORA Frontend] G[API Gateway] ERS[EHR Retrieval Hapi.JS Service] N[NORA Core] A[Authorization Service] DB(RDS mySQL) 1(1upHealth API) LR(FHIR Retrieval Serverless Workflow) S3(AWS S3) F -.-G G -.- A G -.- N G -.- ERS F -.-1 ERS -.- 1 ERS -.- DB N -.- DB N -.- LR LR -.- DB LR -.-S3 ``` ## Database Migrations ### ehr.Authorizations Schema TBD ### ehr.Connections Schema TBD ### ehr.EhrSystemTypes Schema TBD ### ehr.RetrievalManifest Schema TBD ## REST ### Resources #### 1upHealth Resource An instance contains an association between the 1upHealth [EHR Authorization Type's] user account id and an external id associated with a user in NORA belonging to a trial. Conceptually, we could later add additional resources under the umbrella of EHR to account for other EHR connectors other than 1upHealth. For each trial when a user requests to connect medical records, this resource is created. For phase 2, this resource will also manage 1upHealth access and refresh tokens. #### [EHR] Connection Resource A Connection instance maintains a one-to-many relationship between a 1upHealth [EHR Authorization Type] and EHR providers, for example, UCLA, Kaiser Permanente, etc. This allows a trial user in NORA to become associated with multiple EHR providers. Additionally, the Connection resource maintains the state of the "connection" via a status, for instance: "connected" or "disconnected" Future features could also provide a means for EHR Subscriptions. ## API Endpoints All start with /v1/ehr/ ### 1. Create EHR Authorization #### Description Creates a 1upHealth [EHR Authorization Type's] for a NORA user's associated trial and account identifier, creates a 1upHealth user in the 1upHealth application using the [1upHealth User Management API](https://1up.health/dev/doc/user-management) and client ID/secret, and persists this id and association in the database. #### Roles `Patient` #### Operation `POST 1uphealth/authorizations` Inputs via request body: - trialId: trial for which to associate 1upHealth EHR authorization. For future SaaS roadmaps, this could be whatever identifier identifies the NORA trial. Inputs via request headers: - accessToken: The NORA access token. Express API Gateway will perform the authentication and authorization check to see if the user is authenticated and has permission to access this endpoint. The token is exchanged for a NORA JWT Token (X-JWT) header and the request is proxied it to the service. Response: 201, 400, 403 ##### 201 Response Body: - access_token: the 1upHealth bearer access token - expires_in: seconds until the 1upHealth bearer access token expires. - client_id: the client ID of the app to use when making certain requests to 1upHealth directly. Which client_id to use will depend on the environment in which the service is deployed. Notes: - The userID for the authorization will be referenced from the decoded JWT. ### 2. Callback URL Endpoint #### Description This is the endpoint that will be specified in the OAuth2 Redirect URL for the 1upHealth application. Once a successful provider connection has been made, the provider redirects to this application. This endpoint will create a "connection" resource and facilitate redirecting back to the NORA front-end, where the user will typically complete the medical release form. For more information, see [Slides For Overall Backend Design](https://docs.google.com/presentation/d/1SdCwpS-56XGX6t7deoGJU0R5z_uBaYOFKA2G2vXiJTI/edit#slide=id.g70256bda43_0_141) #### Roles N/A #### Operation /callback Inputs via query string: - state: The `state` parameter is set before the user is redirected to the provider to log in and grant access to Science 37. See https://1up.health/dev/doc/ehr-data#addanoptionalstateparameter for more information. ``` "The state=xyz is stored and passed along with other parameters as JSON Web Token during the flow and is preserved as client_state_param until redirected to the callback URL." ``` This will facilitate being able to persist with the "connection" model and its state. Additional metadata (TBD) can be added to the "state" parameter to prevent abuse of the endpoint, for example, a timestamp or unique string. Response: 302 Redirect to {NORA_ENVIRONMENT_HOST}/portal/profile/{profileId} Response Query Parameters: TBD