Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sync consideration update #464

Merged
merged 6 commits into from Nov 29, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
86 changes: 57 additions & 29 deletions FHIR-fhircast.xml
Expand Up @@ -15,52 +15,80 @@
<page key="NA" name="(NA)"/>
<page key="many" name="(many)"/>
<page deprecated="true" key="profiles" name="(profiles)"/>
<page key="launch-scenarios" name="App launch scenarios and session discovery"/>
<page deprecated="true" key="launch-scenarios" name="App launch scenarios and session discovery"/>
<page key="4-1-launch-scenarios" name="Application Launch Scenarios and Session Discovery"/>
<page key="artifacts" name="Artifacts Summary"/>
<page key="change-log" name="Change log"/>
<page key="6_change-log" name="Change Log"/>
<page deprecated="true" key="change-log" name="Change log"/>
<page key="conformance" name="Conformance"/>
<page key="content-sharing" name="Content Sharing"/>
<page key="content-sharing" name="Content Sharing"/>
<page key="7_design-notes" name="Design notes"/>
<page key="7_design-notes" name="Design Notes"/>
<page key="diagnosticreportevents" name="DiagnosticReport Events"/>
<page key="diagnosticreport-close" name="DiagnosticReport close event"/>
<page key="diagnosticreport-select" name="DiagnosticReport select event"/>
<page key="diagnosticreport-open" name="DiagnosticsReport open event"/>
<page key="diagnosticreport-update" name="DiagnosticsReport update event"/>
<page key="3-6-2-diagnosticreport-close" name="DiagnosticReport close Event"/>
<page deprecated="true" key="diagnosticreport-close" name="DiagnosticReport close event"/>
<page key="3-6-4-diagnosticreport-select" name="DiagnosticReport select Event"/>
<page deprecated="true" key="diagnosticreport-select" name="DiagnosticReport select event"/>
<page key="3-6-1-diagnosticreport-open" name="DiagnosticsReport open Event"/>
<page deprecated="true" key="diagnosticreport-open" name="DiagnosticsReport open event"/>
<page key="3-6-3-diagnosticreport-update" name="DiagnosticsReport update Event"/>
<page deprecated="true" key="diagnosticreport-update" name="DiagnosticsReport update event"/>
<page key="encounterevents" name="Encounter Events"/>
<page key="encounter-close" name="Encounter close event"/>
<page key="encounter-open" name="Encounter open event"/>
<page key="event-format" name="Event format"/>
<page key="event-library" name="Event library"/>
<page key="eventmaturitymodel" name="Event maturity model"/>
<page key="eventnotification" name="Event notification"/>
<page key="event-template" name="Event template"/>
<page key="3-4-2-encounter-close" name="Encounter close Event"/>
<page deprecated="true" key="encounter-close" name="Encounter close event"/>
<page key="3-4-1-encounter-open" name="Encounter open Event"/>
<page deprecated="true" key="encounter-open" name="Encounter open event"/>
<page key="2-3-Events" name="Event Format"/>
<page key="3_Events" name="Event Library"/>
<page key="3-1-2-eventmaturitymodel" name="Event Maturity Model"/>
<page key="2-5-EventNotification" name="Event Notification"/>
<page key="3-1-1-template" name="Event Template"/>
<page deprecated="true" key="event-format" name="Event format"/>
<page deprecated="true" key="event-library" name="Event library"/>
<page deprecated="true" key="eventmaturitymodel" name="Event maturity model"/>
<page deprecated="true" key="eventnotification" name="Event notification"/>
<page deprecated="true" key="event-template" name="Event template"/>
<page key="extensions" name="Extensions"/>
<page key="event-definitions" name="FHIRcast Event Definitions"/>
<page key="specification" name="FHIRcast specification"/>
<page key="2_Specification" name="FHIRcast Specification"/>
<page deprecated="true" key="specification" name="FHIRcast specification"/>
<page key="GetCurrentContext" name="Get Current Context"/>
<page key="glossary" name="Glossary"/>
<page key="heartbeat" name="Heartbeat event"/>
<page key="3-2-2-heartbeat" name="Heartbeat Event"/>
<page deprecated="true" key="heartbeat" name="Heartbeat event"/>
<page key="imagingstudyevents" name="ImagingStudy Events"/>
<page key="imagingstudy-close" name="ImagingStudy close event"/>
<page key="imagingstudy-open" name="ImagingStudy open event"/>
<page key="3-5-2-imagingstudy-close" name="ImagingStudy close Event"/>
<page deprecated="true" key="imagingstudy-close" name="ImagingStudy close event"/>
<page key="3-5-1-imagingstudy-open" name="ImagingStudy open Event"/>
<page deprecated="true" key="imagingstudy-open" name="ImagingStudy open event"/>
<page key="infrastructureevents" name="Infrastructure Events"/>
<page key="introduction" name="Introduction"/>
<page key="multi-anchor-considerations" name="Multi-anchor considerations"/>
<page key="multitab-considerations" name="Multi-tab considerations"/>
<page key="fhircast-oauth2-scopes" name="OAuth2 authorization scopes"/>
<page key="4-5-multi-anchor-considerations" name="Multi-anchor Considerations"/>
<page deprecated="true" key="multi-anchor-considerations" name="Multi-anchor considerations"/>
<page key="4-4-multitab-considerations" name="Multi-tab Considerations"/>
<page deprecated="true" key="multitab-considerations" name="Multi-tab considerations"/>
<page key="2-2-FhircastScopes" name="OAuth 2.0 Authorization Scopes"/>
<page deprecated="true" key="fhircast-oauth2-scopes" name="OAuth2 authorization scopes"/>
<page deprecated="true" key="open-issues" name="Open Issues"/>
<page key="patientevents" name="Patient Events"/>
<page key="patient-close" name="Patient close event"/>
<page key="patient-open" name="Patient open event"/>
<page key="3-3-2-patient-close" name="Patient close Event"/>
<page deprecated="true" key="patient-close" name="Patient close event"/>
<page key="3-3-1-patient-open" name="Patient open Event"/>
<page deprecated="true" key="patient-open" name="Patient open event"/>
<page key="RequestContextChange" name="Request Context Change"/>
<page key="Scenarios" name="Scenarios"/>
<page key="security-considerations" name="Security considerations"/>
<page key="4-3-security-considerations" name="Security Considerations"/>
<page deprecated="true" key="security-considerations" name="Security considerations"/>
<page key="session-discovery" name="Session Discovery"/>
<page key="subscribing-and-unsubscribing" name="Subscribing and unsubscribing"/>
<page key="syncerror" name="Sync error event"/>
<page key="synchronization-considerations" name="Synchronization considerations"/>
<page deprecated="true" key="subscribing-and-unsubscribing" name="Subscribing and unsubscribing"/>
<page key="2-4-Subscribing" name="Subscribing to Events"/>
<page key="3-2-1-syncerror" name="Sync error Event"/>
<page deprecated="true" key="syncerror" name="Sync error event"/>
<page key="4-2-syncconsiderations" name="Synchronization Considerations"/>
<page deprecated="true" key="synchronization-considerations" name="Synchronization considerations"/>
<page key="table-of-contents" name="Table of Contents"/>
<page key="userhibernate" name="User hibernate event"/>
<page key="userlogout" name="User logout event"/>
<page key="3-2-4-userhibernate" name="User hibernate Event"/>
<page deprecated="true" key="userhibernate" name="User hibernate event"/>
<page key="3-2-3-userlogout" name="User logout Event"/>
<page deprecated="true" key="userlogout" name="User logout event"/>
</specification>
2 changes: 2 additions & 0 deletions _genonce.sh
Expand Up @@ -14,6 +14,8 @@ fi

echo "$txoption"

export JAVA_TOOL_OPTIONS='-Dfile.encoding=UTF-8 -Djava.awt.headless=true'

publisher=$input_cache_path/$publisher_jar
if test -f "$publisher"; then
java -jar $publisher -ig . $txoption $*
Expand Down
1 change: 1 addition & 0 deletions input/pagecontent/2-6-RequestContextChange.md
Expand Up @@ -18,6 +18,7 @@ Field | Optionality | Type | Description
`id` | Required | *string* | Event identifier, which MAY be used to recognize retried notifications. This id SHALL be uniquely generated by the Subscriber and could be a UUID. Following an accepted context change request, the Hub MAY re-use this value in the broadcasted event notifications.
`event` | Required | *object* | A JSON object describing the event as defined in [Event Definition](2-3-Events.html).

A Subscriber that initiates a context change and receives a `syncerror` related to a context change event it sent, SHOULD resend this event at regular intervals until sync is reestablished or another, newer, event has been received. It is recommended to wait at least 10 seconds before resending the event. Note that such resend will use the timestamp of the original event to prevent race conditions.
### Request Context Change example

#### Request
Expand Down
19 changes: 10 additions & 9 deletions input/pagecontent/4-2-syncconsiderations.md
@@ -1,12 +1,12 @@
<img src="Info_Simple_bw.svg.png" width="50" height="50">
This page contains guidance to implementers and is not part of the [normative-track](2_Specification.html).
This page contains guidance to implementers and is not part of the [normative-track](2_Specification.html); however, implementers are strongly encouraged to read and understand its content towards successful synchronization.
<p></p><p></p>

FHIRcast describes a mechanism for synchronizing distinct applications. Sometimes things go wrong, and applications fail to synchronize or become out of sync. For example, the user within the EHR opens a new patient's record, but a Subscriber fails to process the update and continues displaying the initial patient.

### Scenarios

Depending upon the expectations of the user and the error handling of the applications in use, this scenario is potentially risky. Identified below are four distinct synchronization scenarios, ranging from lowest level of expected synchronization to highest. Each scenario suggests a level of risk resulting from potential context synchronization failure, based upon the user's ability to distinguish between disparate applications. Implementers must assess and determine the appropriate response to potential synchronization failure given their application's workflows and users.
Depending upon the expectations of the user and the error handling of the applications in use, this scenario is potentially risky. Identified below are several distinct synchronization scenarios, ranging from lowest level of expected synchronization to highest. Each scenario suggests a level of risk resulting from potential context synchronization failure, based upon the user's ability to distinguish between disparate applications. Implementers must assess and determine the appropriate response to potential synchronization failure given their application's workflows and users.

Also note that synchronization failure is a worst-case scenario and should rarely occur in production.

Expand Down Expand Up @@ -82,7 +82,6 @@ However, as noted in above scenarios, there may be risk associated with the end

There are in some cases good reasons for a Subscriber not to follow the subscribed context and this section will outline some of the recommended approaches.


#### Blocking action on Subscriber preventing context synchronization

Many applications go into edit mode or start a modal dialog that locks the system from changing context without user intervention. Examples can be when modifying texts, reports, annotating images or performing administrative tasks. The application may then decline to follow the context of the topic to which the Subscriber is subscribed to prevent loss of end user data.
Expand All @@ -91,7 +90,7 @@ Many applications go into edit mode or start a modal dialog that locks the syste
|System|Failure mode|Possible actions|
|--|--|--|
| Subscriber | Modal dialog open in UI, unable to change case without losing end user data | Present end user with clear indication that contextual synchronization is lost. Respond with a http status code of 409 conflict. |
| Subscriber | Unable to change context | Respond with a http status code of 409 conflict|
| Subscriber | Unable to change context | Respond with a http status code of 409 conflict. |
| Subscriber | Ask user whether context can be changed, user refuses. | The Subscriber responds to the initial event with a 202 Accepted and sends a `syncerror` when the context change is refused, stating the source and reason for change. |
| Subscriber | Ask user whether context can be changed, user does not react in time. | The Subscriber responds to the initial event with a 202 Accepted. When the user does not respond within 10 second, it sends a `syncerror`. Context change is refused, stating the source and reason for change. |
| Hub | One of the Subscribers cannot follow context | Update all Subscribers with a syncerror event |
Expand All @@ -113,8 +112,9 @@ This error scenario is the Hub losing contact with a Subscriber. This may be due
{:.grid}
|System|Failure mode|Possible actions|
|--|--|--|
| Subscribing Client | No event received from Hub within the heartbeat time-out. | Present a clear indication to the end-user that the connection has been lost. Resubscribe to the topic. If supported by the Hub, receive [current context upon resubscription](2-4-Subscribing.html#current-context-notification-upon-successful-subscription). |
| Hub | Subscriber failed to respond to an event | Update all Subscribers with a syncerror event using information from the subscriber.name field from the original subscription of the Subscriber which failed to respond to an event |
| Subscribing Client | No event received from Hub within the heartbeat time-out. | Present a clear indication to the end-user that the connection has been lost. Resubscribe to the topic. If supported by the Hub, receive [current context upon resubscription](2-4-Subscribing.html#current-context-notification-upon-successful-subscription) or retrieve the context manually using [Get Current Context](2-9-GetCurrentContext.html). |

| Hub | Subscriber failed to respond to an event | Update all Subscribers with a syncerror event using information from the `subscriber.name` field from the original subscription of the Subscriber which failed to respond to an event |

#### Race condition during launch

Expand All @@ -136,7 +136,8 @@ The Subscriber's subscription has expired causing it no longer receive event. Th
{:.grid}
| System | Failure mode | Possible actions |
|--|--|--|
| Subscriber | Subscription has expired | Present a clear indication to the end-user that the subscription has expired. Resubscribe to the topic. If supported by the Hub, receive [current context upon resubscription](2-4-Subscribing.html#current-context-notification-upon-successful-subscription).
| Subscriber | Subscription has expired | Present a clear indication to the end-user that the subscription has expired. Resubscribe to the topic. If supported by the Hub, receive [current context upon resubscription](2-4-Subscribing.html#current-context-notification-upon-successful-subscription) or retrieve the context manually using [Get Current Context](2-9-GetCurrentContext.html).

| Hub | None | The hub cannot distinguish between an intentional and unintentional subscription expiration. So the Hub cannot mitigate this situation.|

#### Race condition between context changes
Expand Down Expand Up @@ -177,15 +178,15 @@ A Subscriber that initiates a context change and receives a `syncerror` related

#### Subscriber that follow context change

A Subscriber that follows context change should monitor new events or re-sends of the old event. When an event is received with a timestamp equal or newer than the event that caused the `syncerror`, it shall assume sync is restored unless a new `syncerror` is received.
A Subscriber that follows context change should monitor new events or re-sends of the old event. When an event is received with a timestamp equal or newer than the event that caused the `syncerror`, it assumes sync is restored unless a new `syncerror` is received.

#### Subscriber that lose the connection to the Hub

Subscriber that lose the connection to the Hub should resubscribe to the topic. Once resubscribed and the most recent relevant event has been received, the Subscriber can assume that sync is restored.

#### Hubs

A Hub that sends a `syncerror` event (e.g. after it is not able to deliver an event) MAY resend this event regularly until the sync has been reestablished or a newer event has been received.
A Hub that sends a `syncerror` event (e.g. after it is not able to deliver an event) may resend this event regularly until the sync has been reestablished or a newer event has been received.

### Open topics

Expand Down
3 changes: 1 addition & 2 deletions input/pagecontent/4-3-security-considerations.md
@@ -1,5 +1,5 @@
<img src="Info_Simple_bw.svg.png" width="50" height="50">
This page contains guidance to implementers and is not part of the [normative-track](2_Specification.html).
This page contains guidance to implementers and is not part of the [normative-track](2_Specification.html).
<p></p><p></p>

FHIRcast enables the synchronization of healthcare applications user interfaces in real-time through the exchange of a workflow event to a small number of disparate applications. The notification message which describes the workflow event is a simple json wrapper around one or more FHIR resources. These FHIR resources can contain Protected Health Information (PHI).
Expand Down Expand Up @@ -31,7 +31,6 @@ FHIRcast builds on SMART by introducing a new [syntax for standard OAuth 2.0 sco

### WebSocket Security Considerations


Subscribers SHOULD only use and Hub's SHOULD only accept connections made over the secure _wss://_ WebSocket protocol and not the unsecured _ws://_ WebSocket protocol.

The WebSocket standard defines an `Origin` header, sent from the client to the server and intended to contain the url of the client. Subscribers using WebSockets may be running in a Web browser, in which case the Web browser enforces origin reporting to the Hub, or native applications in which the origin reported to the Hub can not be trusted. Therefore, a Hub exposing a WebSocket connection MUST not rely upon the origin sent by the Subscriber.
Expand Down