FHIR versioning with a non-version capable back end

As I’ve mentioned before, FHIR has the concept of versioning baked into it. Providing that the server supports versions, then any resource can be versioned, and older versions retrieved. However, particularly when using FHIR as a proxy server to a back end system, this might not always be the case – as we discovered at Orion during a project to provide FHIR interfaces to an existing product.

However, there are a number of areas where a ‘version specific’ ID is required – for example in the ‘self-link’ of a bundle containing the resource. (The self-link is optional, but desirable). It took a bit of fiddling – and a trip to Grahame via the skype implementers chat – to get this working correctly, so I thought I’d document where we got to (so I can remember next time!).

  • We store the ‘last-modified’ time of the ‘resource’ in the system (eg the last time that the patient was updated). This timestamp becomes the version we expose.
  • If we need to use a version specific reference (like the self-link) then we use the timestamp  – eg: /Patient/100/_history/201301011300
  • In our conformance statement for this resource we set:
    • Read: supported
    • Vread: supported
    • Update: supported
    • Delete: not supported
    • History: not supported
  • When we are returning a resource via a GET (read), then we set the ‘last-modified’ date to the timestamp

Now that we have that:

  • An ‘ordinary’ read will return the current version of the resource
  • If a client does a vread using the current version (e.g. /Patient/100/_history/201301011300) then there is no problem (and this will be what appears in any bundle we return).
  • Should a client have cached an older version, and attempt to vread on that, then we return an error indicating that the older resource version is not available.

In this way our system is compatible with a version-aware client, even though the back end does not support versions.

Simple!

FHIR server exploration tools

Just found this cool tool for exploring a FHIR server. It is hosted by Furore – the guys who also host a public test server, and allows you to view the conformance resource of any publicly accessible server, and then has a simple query builder that assembles a query, and returns all matching resources – displaying the text property.

Grahames test server has a similar facility – in fact allows you to view the resources directly, in XMl & JSON etc – but only operates against his server.

Both are cool tools if you’re starting out…

btw – there are other tools mentioned on the Furore site – a profile editor and a server test tool that you can request from furore…

FHIR XDS – updating a document

It’s not uncommon for a document to need to be updated after it has been posted to a repository and registry. Sometimes new information has come to hand that affects the document, or there may be normal workflow where a ‘draft’ document is saved, and is subsequently updated or finalized, or maybe the original was just plain wrong and needs to be retracted.

None of these are unique to a document of course, but there are some ‘quirks’ – for want of a better word – to the DocumentReference resource for a couple of reasons:

  • It is a resource whose main role is to refer to another entitity – so there are 2 lifecycles to consider.
  • Documents are often summaries of clinical care (e.g. Discharge Summaries, Progress notes, Clinic notes) and it’s very common for clinical decisions to be made on the contents. Keeping an easily accessible (to the end user) ‘audit trail’ of changes is very important for medico-legal reasons.

When thinking about changes to a document, there are 2 ‘types’ of change to consider:

  • Changes to the metadata (e.g. the document type was incorrect)
  • Changes to the content of the document itself.

We’ll consider these separately.

Changes to the metadata

If the change is only to the metadata – the contents of the DocumentReference resource itself, then it can be updated it in the usual way – i.e. retrieve the existing version, make the changes, and PUT the document back. The standard FHIR versioning process will manage the update of the resource. (Resource versioning is not required by FHIR – but highly recommended). There are some caveats to this approach, as mentioned in a minute…

Changes to the document.

This is more tricky. What we need to do is:

  • Update the document in it’s location (e.g. as a binary resource on a FHIR /Binary endpoint)
  • Update the existing DocumentReference resource that points to it, setting the status property to ‘superseded’
  • Create a new DocumentReference resource that references the updated document (and if it’s a FHIR server that we may want to make this a version specific reference), setting the relatesTo.code to ‘supercedes’, and the relatesTo.target as a reference to the original DocumentReference resource
  • We might also want to create a provenance resource to indicate who has made the change.

Because this needs to be managed as a transaction, we’ll use a FHIR bundle and we’ll use the same pattern as when we submitted the document in the first place – i.e. have the repository server manage the updating process. (Other patterns are possible of course).

So our bundle will contain:

  • The updated document as a base-64 encoded binary resource. It will have a real ID so the server knows to update it
  • The original DocumentReference resource, with updated status. It will also have a real ID so the server knows to update it
  • The new DocumentReference resource – largely a copy of the original with the relatesTo property set. It will have a ‘cid:’ ID so the server knows to add it as new.
  • Optionally a provenance resource with the details of who made the change – and when. The provenance resource refers to the resource being changed (not the other way around) so it will have 2 targets – the 2 DocumentReference resources that are effected in this transaction. It also has a cid: ID.

The repository server will process the bundle as described above.

Although this second approach is more complex, it does make it quite obvious that a significant change has occurred. For this reason, some metadata changes – such as a change of subject or author – might be better managed this way rather than a simple update to the DocumentReference resource. It’s up to you…

All of this does raise an interesting point that we didn’t think about when considering how to query the registry for documents (i.e. a query against /DocumentReference) – the response will include DocumentReference resources that have been superseded as well as current ones.

If we don’t add the status parameter in the query, then we will get back all DocumentReference resource’s – so we will need to check this value when assembling the list of documents for the consumer (Of course, we may want to do this anyway so that we can place some visual indication in the display that changes have occurred – it’s up to the implementer, as it should be…)

Otherwise we can be explicit that we only want current documents, so the examples we gave in the previous post becomes:

GET  http://registryserver/DocumentReference?subject= 100&status=current&period > 2013-01-01

and

GET  http://registryserver/DocumentReference?subject= 100&status=current&type= http://loinc.org|34108-1

And as a last word, and following on from the post that Keith Boone made about task orientated services, we may choose to define specific service end points for this functionality (and even for the ‘add document’ scenario), perhaps:

  • /service/document/new
  • /service/document/update

both of which receive the bundles we’re described.

Task orientated Services in FHIR

Last year New Zealand published a number of documents that were distilled from the Interoperability Reference Architecture we published the previous year. One of them was about the utility services that we envisaged would be needed to support the National strategy around health information interoperability, and the following diagram was included to show how we described a service based layer (we called it an HIE – which has a different meaning in the US) providing access to regional data repositories for shareable clinical data.

HIE

I’ve always believed that FHIR was an excellent candidate for this layer – and so I was especially pleased to see this  post from Keith Boone describing how FHIR could support Task orientated services as well as Entity services – just as we had envisaged (though I’d have different examples for the entity services these days)!

It will be interesting to see if the FHIR core team look at standardizing the common interfaces (like the admission services that Keith mentioned), or whether that will be left to individual implementers…

Getting documents from a FHIR XDS infrastructure

So far in our little mini series on FHIR and XDS we’ve had an overview of how FHIR resources support a document sharing infrastructure, looked at how a document creator can create and submit documents to a repository and/or registry, and spent a bit of time talking about the DocumentReference resource.  Time to think about the consumer of these services.

There are 2 main scenarios that we want to support:

  • Getting a list of documents for a patient (with various search parameters – e.g. a date range, type of document etc.) and displaying the metadata in a list to the consumer
  • Retrieving a particular document to view

Getting the list of documents

Let’s think about the first scenario, and to keep it simple we’ll aim to retrieve all the documents for a patient. Given that the metadata about the document is represented by a DocumentReference resource hosted by the registry server we are using, then this is obviously going to be a query against the DocumentReference endpoint. There are a couple of ways we could to this, and the way we choose depends on whether the have the patients ID or their identity (in fact, it’s exactly the same issue as the document creator had – so refer to that post for more discussion on this).

If we know the patient ID (let’s say it’s 100), then our query will be something like:

GET  http://registryserver/DocumentReference?subject= 100

(assuming that the patient identity is also on the registry server – if not then the patient ID would need to be the absolute reference to the patient resource).

If we don’t have the patient ID, but we do have an identifier (e.g. PRP1660) then we have a couple of options (as always!):

  • Look up the patient ID by a query against the Patient endpoint first
  • Query the DocumentReference with the patient identifier using a chained query, like so:

GET http://registryserver/DocumentReference?subject.identifier= PRP1660

Note that the server is not obliged to support chained queries – check their conformance resource to see if they do. Also, I didn’t include the identifier system in the query – depending on the implementation I may need to do so. Chained queries make a clients life easier (but a servers life harder) – but as the FHIR philosophy is to make it as easy for clients as possible, it’s to be hoped that servers do support that capability.

In either case, the result will be a bundle of DocumentReference resources – the difference between the two being that if we specified the patient ID, then we know that all the DocumentReference resources are for the right person. If we used the identifier, then we are trusting that the identifier is unique (which means that we should probably not be lazy and include the system in the query).

But what if we want a more targeted search? Perhaps we’re only interested in documents created in the past year, or only outpatient summaries?

Well, checking the defined search parameters for DocumentReference we see a period parameter (date of the service) and a type parameter (document type) which would seem to suit our purpose, so (assuming we have the Patient ID):

GET  http://registryserver/DocumentReference?subject= 100&period= >= 2013-01-01

and

GET  http://registryserver/DocumentReference?subject= 100&type= http://loinc.org|34108-1

And of course we can mix and match parameters as we need to (provided the server supports them as documented in their conformance resource)

Retrieve a particular document.

So now we have a list of documents which we can display to our user, how do we retrieve a particular document for them? Well, hopefully the DocumentReference resource that describes the document we want has the location property. Then it’s just an HTTP call away. If the repository where the document is stored doesn’t support a direct GET, then you’ll need to drop back to the XDS ‘Retrieve Document’ profile, the access details for which should be on the DocumentReference.service property.

Assuming you can make a GET call, the repository should include the HTTP standard headers in the response like content-type (which is also recorded in the DocumentReference.mimeType property of course), so rendering by the viewer should be straightforward. Of course, it can get a lot more complex than that – especially in the case of a structured document like a CDA or FHIR-document, when specialized client-side renderers (like XSLT stylesheets) will be required. The metadata in the DocumentReference resource (and possibly HTTP headers)  should indicate what renderer is going to be needed, so all should be well.

Note that the GET call will return the document directly, whatever it is – eg a PDF or CDA document – not a FHIR resource of any sort.

A short (and grossly incomplete) comment on FHIR security.

FHIR itself doesn’t define security protocols – rather it provides the ‘hooks’ that a security framework can use when deciding whether to deliver up a particular document – or even whether to include the document metadata in the original list of documents.

There is an assumption that anyone accessing any of these services is authenticated (identified) and oAuth is the recommended (though not mandated) way to do this.

FHIR supports the concepts of tags – that can be applied to any resource, and allow a privacy policy framework to apply rules when determining whether to deliver up information p and those rules can become arbitrarily complex.  In addition, the DocumentReference resource has the specific confidentiality property that can also be used.

There is also the SecurityEvent resource (analogous to the IHE ATNA profile) that can be used to record significant events such as the release of a document to a viewer. This resource can then be used as the basis of functionality such as “Who has viewed my data?”, and can be created at any time that is appropriate in the overall workflow. The provenance resource indicates the context in which a resource was obtained – e.g. the person who created it.

So, it is the responsibility of the governing body for the document sharing infrastructure to make these policy decisions – and to enforce them! And the IHE ‘Affinity Domain’ concept is a good source of information.

Incidentally, for health security issues in general, check out John Moehrkes blog as a good source of inspiration!

We’re getting towards the end of our little mini series – one of the longer ones so far! We’ll wrap up the loose ends in the final post – in particular we need to think about the best approach when a document source needs to update a document it has already sent to a repository.

FHIR Connectathon: Sample data

As part of the planning for the next FHIR connectathon, we want to make better sample data available for participants to build applications against – and, of course, to continue to exercise the specification. For the last event, I wrote an application using one of the open-source clients that has been developed (in this case the c# client by Ewout Kramer of Furore) and suggested that I could enhance that with more data.

It was suggested that I take the data on this page to use as the clinical scenarios.

I was blown away by this for a couple of reasons:

  • First the amount of work that my colleagues have put in to creating it
  • And secondly – just how far FHIR has come in being able to represent real-world clinical data.

If anyone still has lingering doubts about whether FHIR is going to be ‘fit for purpose’, then these scenarios should remove all doubt…

It’s going to be a reasonable amount of work to do properly – especially as we want to use this to test the FHIR document architecture, but should be do-able, and I’ll keep you appraised on progress…

(btw – I stuck a # in front of the FHIR so it shows up as a hashtag in twitter – if anyone knows how to get wordpress to automatically add the # when sending a notification then let me know)….

The FHIR DocumentReference resource

In the previous FHIR-XDS post we discussed how a document source actor (ie a system that creates a document) could create a document and DocumentReference resource and send them to the Repository server. (Actually, we described a couple of ways that this could be done – and there are a few subtleties yet to discuss about server behaviour – but we’ll hold that for later).

However, we didn’t have a lot of time to talk about the DocumentReference resource itself. This resource represents the metadata about the document and allows a consumer to search the registry (or any server hosting these resources) to retrieve matching documents. From these results, a consumer can then generate a list of documents so that a consumer can select one to view.

The documents themselves can be of any allowed type (CDA, PDF, FHIR document, text etc) and can be stored on any server accessible via HTTP – and they do not need to be FHIR servers. It is quite legitimate for a DocumentReference resource to refer to a static document on any server (or, for that matter, a URL that generates a document ‘on the fly’, though you’d want some way to persist the generated document for medico-legal reasons as described in the ‘IHE on-demand document‘ profile). And, if one is being particularly pedantic, then even HTTP is not really required – you could use FTP or any other supported protocol.

It is important to note that although the DocumentReference resource was developed to support some of the requirements of an XDS infrastructure, it is not restricted to that purpose and can be used in any situation where the business requirement is to create a ‘list of available documents’, from which one or more can be chosen for viewing.

In fact, the FHIR specification defines a specific XDS profile that describes how the DocumentReference resource is to be used in the context of an XDS installation – for example some fields that are optional in the resource, are required when acting as a proxy to XDS. The link also gives guidance for mapping between XDS and FHIR elements, including fields required for XDS that are not in the DocumentReference and so represented by extensions.

The following description refers to the generic DocumentReference resource. Note that there are a number of properties whose value should come from a ValueSet defined by the governance body that oversees the overall installation (an Affinity Domain in XDS-speak – though the affinity domain covers much more than just code sets). We will talk a bit more about ValueSet’s after this list.

  • The masterIdentifier is the identifier of the document as created by the source. It is version specific – i.e. a new one is required if the document is updated (We’ll talk about updating documents in a separate post).
  • There can be any number of other document identifiers that make sense. For example, there might be a version independent identifier here.
  • The subject is who the document is about. Generally this is a patient, but the specification also supports a Practitioner, a Group or a Device.
  • The type and class indicate what kind of document this is- (eg a discharge summary). A ValueSet should be defined for each. (Note that ‘class’ has been called ‘sub-type’ in some versions of this resource)
  • There is at least one author, which is a Practitioner.
  • There can be an Organization which is the custodian of the document – responsible for maintaining the document
  • There’s a policyManager link to a URL that describes the access policies to the document.
  • The authenticator of the document can be an Organization or a Practitioner.
  • The created date is when the document was created (not necessarily related to the period of the service that the document may describe – this is in the context.period element).
  • The indexed date which is when the DocumentReference resource was created.
  • The status allows minimal workflow of this DocumentReference resource (NOT the underlying document). Options are current, superseded or error. We’ll talk more about this status when we talk about updating a document in a later post.
  • The docStatus and supercedes allow a document to be updated (superseded) or otherwise have it’s status changed. This is a CodeableConcept, and so can accommodate a specific workflow defined by the affinity domain such as preliminary, final, amended or whatever, as documented in the ValueSet.
  • The description is the title of the document. If you’re displaying list of documents then this would be a good property to use.
  • The Confidentiality property allows a privacy policy to control the access to a document. The policy can also use the generic tags functionality in FHIR.
  • The PrimaryLanguage element indicates exactly that – no surprises here. It is a code, and is bound to the IETF Language tag.
  • mimeType and format indicate how the document is represented – eg xml, pdf, msword etc.
  • Size allows a client to estimate download time of the document, and the hash can ensure integrity.
  • The Location is a URI that indicates from where the document can be downloaded. This does not need to be a FHIR server. The client will (generally) not know what this is when creating the resource as it will be related to the ID that the server assigns. However, either it or the service property is required, so it may be necessary to create a ‘dummy’ resource using the cid: prefix so the server knows it is not real – or define a service. You would define a local policy to describe this, which could be identified in the policyManager link above.
  • The service is used if the location is not known. You would use this if you weren’t using simple FHIR REST, so for the moment we’ll ignore it.
  • The context allows you to specify the clinical context of the document – at least the context that is useful in searching or displaying the document list. The period that the document refers to and the facility type are present, but you can add codes that make sense here as well.

For reference, the following fields need to have their options defined by the governing body using a ValueSet. These can either be defined directly in the ValueSet or be a sub-set of an external Terminology like LOINC or SNOMED.

  • type
  • subtype
  • docStatus
  • confidentiality
  • mimeType
  • format
  • context.code
  • context.facilityType

The recommended way to document this is to create a Profile resource that describes the implementation, and refers to the appropriate ValueSets – with the whole lot being saved in FHIR server/s so that they can be easily located. The option below shows a minimal profile that sets the ValueSet for the confidentiality property.

<Profile xmlns="http://hl7.org/fhir">
     <text>
         <status value="additional"/>
         <div xmlns="http://www.w3.org/1999/xhtml">Minimal profile for confidentiality codes in DocumentReference</div>
     </text>
     <name value="Elbonian XDS Profile"/>
     <status value="draft"/>
     <structure>
         <type value="DocumentReference"/>
         <name value="XDSDocumentReference"/>
         <element>
             <path value="DocumentReference.confidentiality"/>
             <name value="ConfidentialityOptions"/>

             <definition>
                 <short value="Confidentiality Code options"/>
                 <formal value="Confidentiality Code options"/>
                 <min value="1"/>
                 <max value="1"/>
                 <isModifier value="false"/>
                 <binding>
                     <name value="List of confidentiality options"/>
                     <isExtensible value="false"/>
                     <referenceResource value="/ValueSet/ConfidentialityOptions"/>
                 </binding>
             </definition>
         </element>
     </structure>
 </Profile>

and the ValueSet that it references could look like:

<ValueSet xmlns="http://hl7.org/fhir">
     <text>
         <status value="additional"/>
         <div xmlns="http://www.w3.org/1999/xhtml">The value set for confidentiality codes in the elbonian document sharing
         project. The codes are defined directly by the valueset, rather than references to an external terminology</div>
     </text>
     <name value="ConfidentialityOptions"/>
     <description value="ConfidentialityOptions"/>
     <status value="draft"/>
     <!-- Define the  options in the resource rather than an external terminology-->
     <define>
         <system value="http://fhir.moh.elbonia.com/confidentiality"/>
         <concept>
             <code value='N'/>
             <display value="Normal"/>
             <definition value="That the document is of normal confidentiality - is able to be viewed for any authenticated user"/>
         </concept>
         <concept>
             <code value='H'/>
             <display value="High"/>
             <definition value="Then the document is Highly confidential - eg Mental health - and can only be viewed by people authorized to access documents at that level"/>
         </concept>
     </define>
 </ValueSet>

Finishing up…

In the previous post I promised that I would talk about the DocumentManifest resource. This is a new addition to the FHIR family, and has been introduced to support the ability for a document source to submit a collection of documents in a single batch as XDS does.

In truth, I’m not entirely clear how this resource should be used. It does have the recipient element, which provides the basis for a notification system, but beyond that the main value would seem to be that there can be more than a single document in a batch submission to the Repository server. I’ll update the post when I learn more.

So, we have saved a document in the repository and updated the registry. In the next post, we’ll switch our attention to the Document Consumer and discuss how to query the registry for documents, and to get the actual document itself.