-
Notifications
You must be signed in to change notification settings - Fork 61
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'master' into propose-allergyintolerance-create-hook
- Loading branch information
Showing
39 changed files
with
4,271 additions
and
1,216 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
name: Publish docs | ||
|
||
on: | ||
push: | ||
branches: [ master ] | ||
pull_request: | ||
types: [opened, synchronize] # This will trigger the workflow only when a PR is opened or updated with new commits | ||
|
||
jobs: | ||
build: | ||
|
||
runs-on: ubuntu-20.04 | ||
|
||
steps: | ||
- uses: actions/checkout@v2 | ||
|
||
- name: Set up Python 3.6 | ||
uses: actions/setup-python@v2 | ||
with: | ||
python-version: 3.6 | ||
|
||
- name: Setup dependencies | ||
run: pip install -r requirements.txt | ||
|
||
- name: Generate docs | ||
run: mkdocs build --verbose --clean --strict | ||
|
||
- name: Deploy | ||
if: github.event_name == 'push' && github.ref == 'refs/heads/master' | ||
uses: peaceiris/actions-gh-pages@v3 | ||
with: | ||
github_token: ${{ secrets.GITHUB_TOKEN }} | ||
publish_dir: ./site | ||
cname: cds-hooks.org |
This file was deleted.
Oops, something went wrong.
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
# Implementation Best Practices | ||
|
||
This page serves as best practice guidance for CDS Hooks implementers. The best practices outlined here are not mandatory implementation rules; rather, they are suggested guidance. This is a living, in progress document and the best practices outlined here should not be considered absolute or complete. | ||
|
||
## Security | ||
|
||
The CDS Hooks security model requires thought and consideration from implementers. Security topics are never binary, are often complex, and robust implementations should factor in concepts such as risk and usability. Implementers should approach their security related development with thoughtful care. | ||
|
||
The CDS Hooks specifications already provides some guidance in this space. The information here is supplemental to the existing specification documentation. | ||
|
||
The CDS Hooks security model leverages several existing RFCs. These should be read and fully understood by all implementers. | ||
|
||
- [rfc7519: JSON Web Tokens (JWT)](https://tools.ietf.org/html/rfc7519) | ||
- [rfc7517: JSON Web Key (JWK)](https://tools.ietf.org/html/rfc7517) | ||
- [rfc7515: JSON Web Signature (JWS)](https://tools.ietf.org/html/rfc7515) | ||
- [rfc7518: JSON Web Algorithms (JWA)](https://tools.ietf.org/html/rfc7518) | ||
|
||
### CDS Clients | ||
|
||
Implementers of CDS Clients should: | ||
|
||
**Maintain a allowlist of CDS Service endpoints that may be invoked.** | ||
|
||
Only endpoints on the allowlist can be invoked. This ensures that CDS Clients invoke only trusted CDS Services. This is especially important since CDS Clients may send an authorization token that allows the CDS Service temporary access to the FHIR server. | ||
|
||
**Issue secure FHIR access tokens.** | ||
|
||
*If* a CDS Clients generates access tokens to its FHIR server, the tokens should: | ||
|
||
- Be unique for each CDS Service endpoint. | ||
- Be very short-lived. | ||
- Provide the minimum necessary access for the CDS Service. This includes both SMART scopes as well as the patient(s)/data that can be accessed. | ||
|
||
**Audit CDS Service's access to data*** | ||
|
||
Regardless of the use of prefetch or more typical FHIR RESTful APIs, CDS Clients should audit and report on data access. | ||
|
||
### CDS Services | ||
|
||
#### JWT | ||
|
||
Upon being invoked by a CDS Client, the CDS Service should first process the given JWT to determine whether to process the given request. In processing the JWT, CDS Services should: | ||
|
||
1. Ensure that the `iss` value exists in the CDS Service's allowlist of trusted CDS Clients. | ||
2. Ensure that the `aud` value matches the CDS Service endpoint currently processing the request. | ||
3. Ensure that the `exp` value is not before the current date/time. | ||
4. Ensure that the `tenant` value exists in the CDS Service's allowlist of trusted tenants (may not be applicable to all CDS Services). | ||
5. Ensure that the JWT signature matches the public key on record with the CDS Service. See additional notes below. | ||
6. Ensure that the `jti` value doesn't exist in the short-term storage of JWTs previously processed by this CDS Service. | ||
|
||
Once the JWT has been deemed to be valid, the `jti` value should be stored in the short-term storage of processed JWTs. Values in this storage only need to be kept for the maximum duration of all JWTs processed by this CDS Service. If the CDS Clients are adhering to best practices, this should be no more than an hour. | ||
|
||
Verifying the JWT signature is a critical step in establishing trust of the caller of the CDS Service. As part of the allowlist of trusted CDS Clients, information on the public key(s) used by the CDS Client should also be stored. In some cases, this public key may be shared out-of-band. In other cases, the public key may be available at a remote endpoint and cycled on a regular basis. It is this latter case in which CDS Services should maintain their own rotating cache of public keys for the CDS Client. | ||
|
||
CDS Services should never store, share, or log JWTs to minimize the risk of theft and replay attacks. Information within the JWT (for instance, `iss`, `tenant`, `jti`) can be logged safely and is especially useful for analytics. | ||
|
||
If a CDS Service deems a JWT to be invalid for any reason, it should not leak the details of why the JWT failed validation back to the caller. If the caller were a malicious threat actor, leaking detailed information as to what was invalid may give the threat actor guidance on how to shape future attacks. Instead, responding to the request with a HTTP 401 Unauthorized response status code without any additional information is recommended. | ||
|
||
#### FHIR Access | ||
|
||
CDS Services should never store, share, or log the FHIR access token (`fhirAuthorization.access_token`) given to it by the CDS Client. The access token should be treated as an extremely sensitive, transient piece of data. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
# Change Log | ||
|
||
## CDS Hooks 1.1 | ||
### Non-compatible (breaking) changes | ||
The CDS Hooks project team strives to not brek backward compatibility between versions of the CDS Hooks specifications to aid both in interoperability | ||
and to prioritize existing implementations. In cases where this isn't possible, changes made in the CDS Hooks 1.1 specification that break backward compatibility are documented below. | ||
|
||
* CDS Clients may now paginate search results in prefetch. Previously, CDS Clients were not permitted to return partial search results using the [typical FHIR pagination mechanism](https://www.hl7.org/fhir/http.html#paging). When using prefetch, CDS Services should expect to receive continuation links which enable access to the remainder of the search results over REST. |
Binary file not shown.
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
# CDS Hooks Cheat Sheet | ||
|
||
Whether for general development or distribution at events, it's helpful to have a concise "cheat sheet" as a reminder of essential structures and syntax. The [Markdown version](./cheat-sheet.md) in this folder is meant to provide the *source of truth content* for such a doument, leaving further formatting and arrangement up to the consumer. | ||
|
||
A rendered version created by [Firely](https://fire.ly/) based on the markdown is also available within this folder and linked to in the navigation section. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,186 @@ | ||
# Overview | ||
|
||
![alt text](https://raw.githubusercontent.com/cds-hooks/docs/master/docs/images/overview.png "Overview Diagram") | ||
|
||
# Links | ||
|
||
* Spec: https://cds-hooks.hl7.org/1.0/ | ||
* Sandbox: http://sandbox.cds-hooks.org/ | ||
* Quick Start: https://cds-hooks.org/quickstart/ | ||
|
||
# CDS Service Discovery | ||
|
||
`GET {baseUrl}/cds-services` | ||
|
||
## Response Body | ||
|
||
services - An array of **CDS Service**s | ||
|
||
### CDS Service: ### | ||
|
||
Field | Optionality | Summary | ||
------|-------------|------------ | ||
`hook` | REQUIRED | hook this service should be invoked on | ||
`title` | RECOMMENDED | human-friendly name of this service | ||
`description` | REQUIRED | description of this service | ||
`id` | REQUIRED | {id} portion of service URL: {baseUrl}/cds-services/{id} | ||
`prefetch` | OPTIONAL | Object containing key/value pairs of FHIR queries that this service is requesting the CDS Client to include on service calls | ||
|
||
## Example | ||
|
||
<pre> | ||
{ | ||
"services": [ | ||
{ | ||
"hook": "hook-noun-verb", | ||
"title": "CDS Service Example", | ||
"description": "An example of a CDS Service that returns a card", | ||
"id": "patient-greeter", | ||
"prefetch": { | ||
"patientToGreet": "Patient/{{context.patientId}}" | ||
} | ||
} | ||
] | ||
} | ||
</pre> | ||
|
||
# CDS Service Request | ||
|
||
`POST {baseUrl}/cds-services/{id}` | ||
|
||
## Request Body ## | ||
|
||
Field | Optionality | Summary | ||
------|-------------|------------ | ||
`hook` | REQUIRED | hook that triggered this CDS Service call | ||
`hookInstance` | REQUIRED | UUID for this hook call | ||
`fhirServer` | OPTIONAL | base URL for CDS Client’s FHIR server | ||
`fhirAuthorization` | OPTIONAL | structure with **FHIR Authorization** information for the above url | ||
`context` | REQUIRED | hook-specific contextual data | ||
`prefetch` | OPTIONAL | FHIR data prefetched by the CDS Client | ||
|
||
### FHIR Authorization ### | ||
|
||
Field | Optionality | Summary | ||
------|-------------|------------ | ||
`access_token` | REQUIRED | OAuth 2.0 access token | ||
`token_type` | REQUIRED | fixed value: `Bearer` | ||
`expires_in` | REQUIRED | lifetime in seconds of the access token | ||
`scope` | REQUIRED | scopes the access token grants to the CDS Service | ||
`subject` | REQUIRED | OAuth 2.0 client id of the CDS Service’s auth server registration | ||
|
||
## Example ## | ||
|
||
<pre> | ||
{ | ||
"hook": "hook-noun-verb", | ||
"hookInstance": "d1577c69-dfbe-44ad-ba6d-3e05e953b2ea", | ||
"fhirServer": "https://fhir.client.com/version", | ||
"fhirAuthorization": { | ||
"access_token": "opaque-token", | ||
"...": "<snipped for brevity>" | ||
}, | ||
"context": { | ||
"userId": "Practitioner/example", | ||
"...": "<snipped for brevity>" | ||
}, | ||
"prefetch": { | ||
"patientToGreet": { | ||
"resourceType": "Patient", | ||
"...": "<snipped for brevity>" | ||
} | ||
} | ||
} | ||
</pre> | ||
|
||
# CDS Service Response Body | ||
|
||
Field | Optionality | Summary | ||
------|-------------|------------ | ||
`cards` | REQUIRED | an array of **Card**s with a combination of information, suggested actions, and links | ||
|
||
## Card | ||
|
||
Field | Optionality | Summary | ||
------|-------------|------------ | ||
`summary` | REQUIRED | <140-character summary sentence for display to the user inside of this card | ||
`detail` | OPTIONAL | optional detailed information to display (GitHub Flavored Markdown) | ||
`indicator` | REQUIRED | urgency/importance of what this card conveys (`info/warning/critical`) | ||
`source` | REQUIRED | grouping structure for the **Source** of information displayed on this card | ||
`suggestions` | OPTIONAL | array of **Suggestion**s for changes in the context of the current activity | ||
`selectionBehavior` | OPTIONAL | intended behavior of the suggestions. If suggestions present, value must be `at-most-one` | ||
`links` | OPTIONAL | array of **Link**s to suggest an app or other additional information | ||
|
||
## Source | ||
|
||
Field | Optionality | Summary | ||
------|-------------|------------ | ||
`label` | REQUIRED | short, human-readable label to display source of the card’s information | ||
`url` | OPTIONAL | optional absolute URL to load to learn more about the organization or data set | ||
`icon` | OPTIONAL | absolute url for an icon for the source of this card (100x100 pixel PNG without any transparent regions) | ||
|
||
## Suggestion | ||
|
||
Field | Optionality | Summary | ||
------|-------------|------------ | ||
`label` | REQUIRED | human-readable label to display for this suggestion | ||
`uuid` | OPTIONAL | unique identifier for auditing and logging suggestions | ||
`actions` | OPTIONAL | array of suggested Actions (logically AND’d together) | ||
|
||
## Action | ||
|
||
Field | Optionality | Summary | ||
------|-------------|------------ | ||
`type` | REQUIRED | type of action being performed (`create/update/delete`) | ||
`description` | REQUIRED | human-readable description of the suggested action | ||
`resource` | OPTIONAL | FHIR resource to create/update or id of resource to delete | ||
|
||
## Link | ||
|
||
Field | Optionality | Summary | ||
------|-------------|------------ | ||
`label` | REQUIRED | human-readable label to display | ||
`url` | REQUIRED | URL to GET when link is clicked | ||
`type` | REQUIRED | type of the given URL (`absolute/smart`) | ||
`appContext` | OPTIONAL | additional context to share with a linked SMART app | ||
|
||
## Example | ||
|
||
<pre> | ||
{ | ||
"cards": [ | ||
{ | ||
"summary": "<140 char Summary Message", | ||
"detail": "optional GitHub Markdown details", | ||
"indicator": "info", | ||
"source": { | ||
"label": "Human-readable source label", | ||
"url": "https://example.com", | ||
"icon": "https://example.com/img/icon-100px.png" | ||
}, | ||
"suggestions": [ | ||
{ | ||
"label": "Human-readable suggestion label", | ||
"uuid": "e1187895-ad57-4ff7-a1f1-ccf954b2fe46", | ||
"actions": [ | ||
{ | ||
"type": "create", | ||
"description": "Create a prescription for Acetaminophen 250 MG", | ||
"resource": { | ||
"resourceType": "MedicationRequest", | ||
"...": "<snipped for brevity>" | ||
} | ||
} | ||
] | ||
} | ||
], | ||
"links": [ | ||
{ | ||
"label": "SMART Example App", | ||
"...": "<snipped for brevity>" | ||
} | ||
] | ||
} | ||
] | ||
} | ||
</pre> |
Oops, something went wrong.