A weekly summary of chat.fhir.org to help you stay up to date on important discussions in the FHIR world.
Hi, we would like your opinion about doing a track on the Connectathon about our FHIR Questionaire/Reponse end-to-end encryption. (developer.openhealthhub.com). Should this be interesting for the community? Thank you in advance!
I don't think we would do a full track on that, but we could possibly talk about it as part of the regular Questionnaire track...
@Martijn Verhoeven There are usually a number of open time slots in the Questionnaire track. If would like to give a presentation during the connectathon, just let me know. I can put you on the schedule (which I haven't drawn up yet). Of particular interest I would think would be your "Improve Designer" which I think is a questionnaire builder.
Paul Lynch said:
Martijn Verhoeven There are usually a number of open time slots in the Questionnaire track. If would like to give a presentation during the connectathon, just let me know. I can put you on the schedule (which I haven't drawn up yet). Of particular interest I would think would be your "Improve Designer" which I think is a questionnaire builder.
Hi Paul, that would be great, Our Improve Designer is indeed the questionnaire builder which publish the questionnaires on our end-to-end encrypt hub.
Martijn Verhoeven said:
Paul Lynch said:
Martijn Verhoeven There are usually a number of open time slots in the Questionnaire track. If would like to give a presentation during the connectathon, just let me know. I can put you on the schedule (which I haven't drawn up yet). Of particular interest I would think would be your "Improve Designer" which I think is a questionnaire builder.
Hi Paul, that would be great, Our Improve Designer is indeed the questionnaire builder which publish the questionnaires on our end-to-end encrypt hub.
@Martijn Verhoeven I was just working on the Connectathon track schedule (https://confluence.hl7.org/display/FHIR/Connectathon+Session+Capture+29, filter by "Questionnaire"). We have two general demo slots where anyone who cares to can show and present a demo. Typically this means people have at least 15 minutes, usually 20 or so. I will be adding a sign-up page so people get an idea of how many others will demoing in each slot. Also, as you can see from our schedule, there is plenty of open space, so if you would like a longer, dedicated demo slot, we can add one.
Great Paul, we will discuss this with our team and comeback asap.
Hi Paul, we would like to present/demo in the next Connectathon if possible.
By "next" do you mean the one that starts later today, or the one in May?
Paul i think May would be preferable ;)
Good morning-- Just a reminder that the first, "welcome" session of the Questionnaire track is starting in a few minutes. You should be able to find it in Whova.
The Questionnaire track kick-off call for the May connectathon will be on 4/28, 5p.m.-6p.m. U.S. Eastern Time (GMT-4) Link: https://hl7-org.zoom.us/j/8583747934?pwd=VnZiWFZsNm1TSk5QWmZlbVJyQVZGdz09. (In other words, the standard time and link for the weekly Questionnaire work group conference call.)
The Questionnaire track kick-off call for the May connectathon has moved to a new time (same date): 10 a.m.-11 a.m. U.S. Eastern Time (GMT-4) Link: https://hl7-org.zoom.us/j/8583747934?pwd=VnZiWFZsNm1TSk5QWmZlbVJyQVZGdz09.
Just a reminder that the kick-off meeting for the Questionnaire track starts at 10:00 a.m. ET (in 22 minutes). https://hl7-org.zoom.us/j/8583747934?pwd=VnZiWFZsNm1TSk5QWmZlbVJyQVZGdz09
We might need a new link. Stay tuned.
Here is the recording of the kick-off meeting (thanks Lloyd!) which unfortunately I started a bit late: https://hl7-org.zoom.us/rec/share/vZsyH69mYtCeAR9Tcz7zwvMVsJdhK99Xg_1l-s9od2dmq458ketGWasoIR7gdIhW.ZrUcQpSUmavHLGo9
Just a reminder that the NLM Questionnaire Tools presentation is starting.
@Marcel Hofman Will you be demonstrating in the Questionnaire track? I am interested in seeing visualization (Jupiter notebook) - to view QRs, basic analysis & graphs
If you would like to demo, please see if either of the two slots at https://confluence.hl7.org/pages/viewpage.action?pageId=94655636 will work for you (and sign up if you don't mind). If neither slot will work, we can find some other time. There is plenty of room in the schedule.
@Diane Yes, I will demonstrate the visualization of FHIR data during the workshop. It's a basic visualization script where you can add all fancy things to, to manage expectations
Reminder: The first demo session today is starting in 5 minutes (10:00).
Reminder: There is a second demo session scheduled for 4:00 (in 12 minutes). No one has signed up on the schedule (https://confluence.hl7.org/pages/viewpage.action?pageId=94655636) to actually do a demo in this slot, so the schedule is quite open if someone has something they would like to share.
Here are the recordings from the connectathon. Somehow the dates & times on the recordings are different from the actual dates & times from the sessions, which I guess is why they were not on the Whova session pages.
Initial track proposal is here: https://confluence.hl7.org/display/FHIR/2022-09+Questionnaire
Thanks, Lloyd. So, is the idea really to have everyone in one big room crowded around tables? I am wishing there were a virtual option. BTW, current COVID data for Baltimore is here: https://coronavirus.baltimorecity.gov/
Yes, that's the plan. I don't know how much space we'll have between tables, and I certainly plan to bring my N95s to the meeting. Certainly people can try to participate over Zulip as they did in the pre-Covid connectathon days, but there will be no technical support, no simulcast, etc.
Would such participation still count for publication requirements?
Sure. Interoperability checks don't have to even happen at a connectathon at all. What matters are:
In person vs. virtual doesn't matter.
Lloyd McKenzie said:
Yes, that's the plan. I don't know how much space we'll have between tables, and I certainly plan to bring my N95s to the meeting. Certainly people can try to participate over Zulip as they did in the pre-Covid connectathon days, but there will be no technical support, no simulcast, etc.
I was trying to think whether some hybrid of in-person and virtual would be possible. I have seen that work with an Owl cam, but I think the Questionnaire track would need its own room for that to work, or there would be too much background noise and movement.
Right. And the hotel rental (done over 18 months ago) was for one big room and a few conference rooms. Much of the feel of the physical connectathon is also the ability to move from table to table to find people to ask questions or overhear something at another table and jump into the discussion. So there's never been any plan for the connectathon to split into a whole bunch of small rooms. With the big room, trying to do audio just doesn't really fly. It'll still be possible to participate remotely via Zulip and cloud-based solutions, but it won't really be practical to participate in discussions. We might be able to make audio work in one of the breakout rooms, but even that can be touch & go, depending on the room layout and the quality of audio equipment (and whatever we use, one of the participants would need to provide - HL7 won't be supplying any).
The kick-off meeting for the Questionnaire track will be held during the weekly FHIR-I Questionnaire call, on Thursday 9/15 (next week) at 5:00 E.T. Call connection details are at https://www.hl7.org/concalls/CallDetails.cfm?concall=59433.
Due to Thursday being a travel day for a some people, we will reschedule the kick-off meeting the previous day, 9/14, but at 5:30 PM ET.
The Questionnaire track currently has two scheduled break-outs:
1) SDC (Structured Data Capture) IG Walk-through at 10 AM ET on Saturday
2) A demo session for Questionnaire tools or track-related progress, at 2 PM ET on Sunday
Just a reminder that the Questionnaire track kick-off is in 5 minutes, at https://www.hl7.org/concalls/CallDetails.cfm?concall=59433.
Due to the late start of the connectathon, we are moving the SDC IG walkthrough to 1:00 p.m. (same room - "Federal Hill")
I'm here, just waiting downstairs till the test line goes down.
I'm working on my Definition based extract operation implementation.
Paul Lynch said:
Due to the late start of the connectathon, we are moving the SDC IG walkthrough to 1:00 p.m. (same room - "Federal Hill")
FYI, Federal Hill a room behind the initial check-in desks.
Just a reminder that we have our demo break-out session at 2:00 in the Federal Hill room. Please sign up (https://confluence.hl7.org/pages/viewpage.action?pageId=108316727) if you would like to demo something Questionnaire-related.
I've heard that someone out there may be working on exporting REDCap to FHIR, looking to connect.
@Eric Puster - I'd be interested in knowing what you hear. We have some partners on a project implementing questionaires in RedCAP, and we're going to have to figure out what to do w/ their data at some point... So, we're not really working on it, but we'd like to have a pathway to share with them.
@David Hay @Michael Lawley is there anything you've tried out that you could share?
@Bill Lober I know that it isn't a simple problem, but I'm wondering if someone has already been cracking away on the framework. We have a situation where there are many research sites that need to export data to a common data repository, and a good deal of the data is captured in REDCap.
Paul Lynch said:
Just a reminder that we have our demo break-out session at 2:00 in the Federal Hill room. Please sign up (https://confluence.hl7.org/pages/viewpage.action?pageId=108316727) if you would like to demo something Questionnaire-related.
One last reminder for this demo session at 2. There is another meeting in the 1-2 slot, so we might have to wait until 2 to get into the room.
Paul Lynch said:
One last reminder for this demo session at 2. There is another meeting in the 1-2 slot, so we might have to wait until 2 to get into the room.
I had a request for the slides, and put them on the track page as an attachment: https://confluence.hl7.org/pages/viewpageattachments.action?pageId=134938749
Redmatch for RedCAP to FHIR: https://ontoserver.csiro.au/site/our-solutions/redmatch/
Open Source and with a VSCode plugin
This is super cool! It may be my lack of familiarity with RedCAP lingo, but when I read "transform REDCap forms into FHIR" I was expecting that "form" meant (the equivalent of) Questionnaire -- but this about translating (the equivalent of) Questionnaire Responses into clinical resources. Similar in spirit to what SDC calls "form data extraction"?
Not sure if there's any way the redmatch tagline could/should address this distinction (might be a tall order while keeping the tagline short and impactful, and the "issue" may be entirely on my end ;-)).
EDIT: The tagline at https://github.com/aehrc/redmatch is actually clearer on this point than the tagline at https://aehrc.github.io/redmatch/index.html (which tripped me up)
A rules-based transformation engine that allows exporting data in REDCap as FHIR resources.
vs
Redmatch is a tool designed to transform REDCap forms into FHIR resources.
@Josh Mandel - We've been pretty interested in loading "answers" into QuestionnaireResponse resources.
We have thought of this as an issue of mapping flat "answers" (from our PRO systems, as well as data exported from Epic, and other sources), into QR resources. But, we also do a fair amount of mapping of other flat and relational data into FHIR: Dx -> Conditions, Lab Results -> Observations, meds, etc... So, I think there's another aspect to this besides relational/table to object mapping (and specifically FHIR mapping).
Thanks to time spent talking about SDC over the weekend (thanks @Paul Lynch @Lloyd McKenzie @Vadim Peretokin @Cooper Thompson @Isaac Vetter !) I've been thinking more about extraction, and about the clinical utility of "answers" vs the extractions from those answers. In other words - what do I really want to expose from a PRO session? Do we want the answers to the questions or the conclusions/observations from those answers - some of which may well be answers. I think this (so-far internal) debate might inform how we capture HIV PRO responses (from one of our research network partners who is committed to asking questions and recording answers in RedCAP).
More on this another time. Right now I'm falling asleep after all that lunch! I made the mistake of attending a Q3 session meeting in a room that had a couch...
But, I very much appreciate Eric's raising the topic, and the link from Michael on the CSIRO work in progress.
From a clinical perspective, we want both. Once I had an encounter with a patient that filled out a depression survey form and scored very bad. When I asked about their mood, they denied any negative feelings. But then I was able to discuss each question on the survey as they had answered it, and then they admitted the answers had been accurate. On other occasions I have had patients answer survey questions inaccurately because of literacy issues, and being able to pinpoint the questions that triggered conclusions allow me to fact check.
That being said, clinicians want the conclusion first. If something seems off, then more detail is needed.
I tend to think of QuestionnaireResponse as "source of truth"/raw data that is relevant from a provenance perspective and sometimes is the only thing needed in very tight/small circle exchanges where everyone knows the forms, they're all standard, and you don't need to filter on the data (at least not over a REST interface). Some systems won't have any need to have the raw/source-of-truth data
All of the other resources are the true 'interoperability' resources - the ones that pretty much anyone, anywhere can use to access and understand the data, with no need to understand the form (or even know that the data came from a form at all). However, they can also be bulkier. If you need to query/analyze the data over REST or if the data needs to be shared with a wider community, you need this.
We are trying to decide whether to plan a Questionnaire track for the January connectathon. If that is something you would attend at least part of, could you let us know 1) if it would be your primary track; or 2) you would expect to drop in for some discussion. Thanks!
Paul Lynch said:
We are trying to decide whether to plan a Questionnaire track for the January connectathon. If that is something you would attend at least part of, could you let us know 1) if it would be your primary track; or 2) you would expect to drop in for some discussion. Thanks!
Just wanted to bring this to everyone's attention again, since the deadline for scheduling a track is tomorrow....
I may be a remote attendee, so unlikely to be a co-track lead.
#2 for me, I hope to be dropping in
I am still interested to enable LHC Forms for valueReference.
e.g.
item.answerOption[+].valueReference = Reference(PlanDefinition/chloride-serum) "Chloride [Moles/volume] in Blood"
item[=].item[=].item[=].item[=].item.answerOption[=].valueReference.type = "PlanDefinition"
item[=].item[=].item[=].item[=].item.answerOption[=].valueReference.display = "Chloride [Moles/volume] in Blood"
The purpose would be to choose an item displaying "Chloride [Moles/volume] in Blood" as Reference
@Marcel Hanselmann Were you saying you would plan to attend the Questionnaire track at the FHIR connectathon to help work on that issue?
Kickoff recording is here: https://hl7-org.zoom.us/rec/share/PA-zkqbtDvqcmKX2PuM1EQbT2VfrQ-WVXvW-Buiy8u-oTC1AWIavU9FyYrPnPaz0.TqFIj0lb9g8hxSQp
Although I am not in New Orleans for the Connectathon, I am available here on-line if anyone would like to work on something together or has questions about the LHC-Forms Questionnaire widget (https://lhcforms.nlm.nih.gov/lhcforms), the NLM Form Builder (https://lhcformbuilder.nlm.nih.gov/), or our SDC Questionnaire app (https://lhcforms.nlm.nih.gov/sdc).
Big welcome to those attending!
Thanks Brian,
This is Nebojsa form Optum.
We have stood up observation based extraction endpoint for the connectathon
https://optumcds-apis-connectathon.azure-api.net/sdc/QuestionnaireResponse/$extract
Does anyone have a data (QuestionnaireResponses) we can try against the SDC engine ?
You might also be interested in this repo
https://github.com/aehrc/smart-forms/tree/main/packages/sdc-populate
They also have an SDC renderer in react.
Reviewing some modular forms done by one of the implementers at the connectathon they have a use case where they are doing an enbableWhen using fields from other forms assembled together.
It works in the assembled context, but my thought was that as a server I wouldn't be able to validate that module as it can't see that linkId outside itself until it's assembled.
Do others think this is an issue too?
The solution we had to resolve this would be to use a variable (which is well defined in passing down to children) and the enableExpression instead of the regular enableWhen.
This then poses the question can the root definition read linkIds from fields in the component questionnaire?
Unfortunately, I can't join the connectathon this time.
Here you can find my implementation of the Questionnaire form in React and TypeScript https://github.com/beda-software/fhir-emr/blob/master/web/src/components/BaseQuestionnaireResponseForm/index.tsx#L53
It supports population and extraction, and may other useful features from SDC.
@Ilya Beda does it support fhirpath and cql expressions?
@Eric Haas
FHIRPath is supported. CQL isn't.
Hi Brian at al,
Here is the summary from our end (Rajesh & Nebojsa)
image.png
Thanks!
(can you put the text version of that last image to ease formating?)
Summary
Goal :
Optum team at the Questionnaire track participated with $extract operation implementation (observation based extraction).
We were looking to advance our understanding of the spec and address any gaps in our implementation.
What was achieved:
Propose SOA / micro services based architecture and assign roles and responsibilities in accordance with the SDC IG.
Amazing collaboration effort with Brian and Liam. we got better understanding of the roles defined in SDC spec
Work through the details how to support isSubject extension.
Familiarise with https://github.com/aehrc/smart-forms project and operation $populate implementation.
Architecture proposal and POC for $populate implementation as a backend service
Support $populate with a end to end POC
The kick-off meeting for the Questionnaire track of Connectathon 35 will be during the SDC workgroup call, 2023-12-14, 5p.m. ET, https://hl7-org.zoom.us/j/8583747934?pwd=VnZiWFZsNm1TSk5QWmZlbVJyQVZGdz09 .
Also, while the session capture page is having some problems, I have temporarily put the track schedule on the track page: https://confluence.hl7.org/display/FHIR/2024+-+01+Questionnaire#id-202401Questionnaire-TrackSchedule
Just as a heads up, my interest is in working with apps that can render a Q. I've got an app that can generate Q based on an underlying model so would like to test that against different renderers. I haven't included any pre-pop stuff as yet - but that's another area of interest. Feel free to reach out ahead of the event if you like so we can get things started...
Hi @David Hay
I am not participating in the event but you can try https://emr.beda.software/ as a form renderer.
You can add Questionnaires in aidbox directly https://aidbox.emr.beda.software/ui/console#/entities/Questionnaire
Please feel free to reach me directly in case of any questions.
Thanks Ilya! I'll see how I go...
Hi @David Hay
I'm also not participating, but you can take a look at this tool that can render a Questionnaire: https://github.com/asbi-cds-tools/questionnaire-to-survey
Here's a react app that uses the tool: https://github.com/ccsm-cds-tools/ccsm-cds-dashboard
Much appreciated!
@David Hay The lead developer for LHC-Forms renderer, @Ye Wang, will be at Questionnaire track (as will I).
Excellent! Is there a web accessible UI that I can use ? eg send a Q somewhere or expose one via a url?
Yes, you can try our Questionnaire Viewer: https://lhncbc.github.io/questionnaire-viewer/
FYI, I have moved the first Questionnaire track session (the "welcome" session) to 9:30 in anticipation of there being a general connectathon session (which is not yet in whova) from 9:00-9:30.
Just a reminder that the track will start at 9:30... assuming I or @Brian Postlethwaite can get the session started.
That's a 1/2 hour from this message
:+1:
And we're on!
The SDC IG walk-through with @Lloyd McKenzie starts 10 minutes from now at 1:00 p.m.
This is the link to the Template based Questionnaire data extraction into other resources is.
https://jira.hl7.org/browse/FHIR-39498
Anyone wanting to experiment with it, let me know.
There is now a page for signing up for the two demo slots tomorrow: https://confluence.hl7.org/pages/viewpage.action?pageId=217351215 . If you have something Questionnaire related you think might be of interest, please sign up.
Demo of Questionnaire-related tools from NLM will be starting at 3:05. (7 minutes from now.)
I've signed up to do an intro to the fhirpath-lab to show off some of the lesser known features...
excellent!
@David Hay has uncovered a bug in the invariants in R4b/R5/R6 que1a...
Can you spot it? (context is Questionnaire.item - but that's not the problem)
(type='group' and %resource.status='complete') implies item.empty().not()
hint: https://hl7.org/fhir/valueset-publication-status.html
I'll log it.
FHIR-43667 - Thanks David :smiling_face:
:)
@Sean Fong Was using the CSIRO renderer (inside Brians lab) and the following Qitem ought to provide a tooltip shouldn't it? It does work in the LNC renderer...
{
"text": "Patient",
"linkId": "dhtest1.Demographics.SectionPathologyPatient.Patient",
"type": "string",
"definition": "SectionPathologyPatient.Patient",
"item": [
{
"text": "tooltip",
"linkId": "dhtest1.Demographics.SectionPathologyPatient.Patient-tt",
"type": "display",
"extension": [
{
"url": "http://hl7.org/fhir/StructureDefinition/questionnaire-itemControl",
"valueCodeableConcept": {
"coding": [
{
"system": "http://hl7.org/fhir/questionnaire-item-control",
"code": "flyover"
}
]
}
}
]
}
]
}
Questionnaire Template Item discussion and example(s)
https://hackmd.io/@brianpos/SJMJqv4FT
@Grey Faulkenberry template based pre-pop.
Got some examples of your stuff and if what we'd be able to adopt?
Discovered: issue with DomainResource dom-3 FHIR-43690
Paul Lynch said:
There is now a page for signing up for the two demo slots tomorrow: https://confluence.hl7.org/pages/viewpage.action?pageId=217351215 . If you have something Questionnaire related you think might be of interest, please sign up.
Our first demo slot starts at 10:00, (about 10 minutes from now). @Brian Postlethwaite will be demoing his FHIRPath Lab tools.
The 2:00 check-in session just started ... a couple of minutes late.
There is one more check-in session starting at 5:15 if anyone has questions or something to discuss.
The link to the lab works a charm!
Screenshot-2024-01-18-at-11.32.57AM.png
feel free to use this image in the report out...
The 'View in FHIRPath Lab' link invokes the lab...
David Hay said:
Sean Fong Was using the CSIRO renderer (inside Brians lab) and the following Qitem ought to provide a tooltip shouldn't it? It does work in the LNC renderer...
{ "text": "Patient", "linkId": "dhtest1.Demographics.SectionPathologyPatient.Patient", "type": "string", "definition": "SectionPathologyPatient.Patient", "item": [ { "text": "tooltip", "linkId": "dhtest1.Demographics.SectionPathologyPatient.Patient-tt", "type": "display", "extension": [ { "url": "http://hl7.org/fhir/StructureDefinition/questionnaire-itemControl", "valueCodeableConcept": { "coding": [ { "system": "http://hl7.org/fhir/questionnaire-item-control", "code": "flyover" } ] } } ] } ] }
Apologies, I'm currently on leave so will be slow in replying.
Seems like it's not implemented in the CSIRO renderer yet - I will add it to the to-do list!
Thanks @Sean Fong ! Is the todo list publically available? Be good to know what is planned...
David Hay said:
Thanks Sean Fong ! Is the todo list publically available? Be good to know what is planned...
At the moment its on a private CSIRO JIRA project. I'm thinking of putting it up on GitHub projects so it can be publicly accessible, perhaps a Kanban board or some sorts. Looks like a good time to open it up.
Will start working on it once I'm back mid-February!
Brian Postlethwaite said:
Grey Faulkenberry template based pre-pop.
Got some examples of your stuff and if what we'd be able to adopt?
Sorry, been on vacation. Are you asking for examples of questionnaires, or specifically questionnaires that have pre-populated answers pulled from elsewhere?
I thought you'd tried out some template base extract techniques.
That's probably more generous than what I've done. Most of what I've tried so far has been extracting a field here and there for a specific purpose. The most advanced one I've tried is just a patient registration, that prefills with the patient's information, and then extracts it again after its been edited.
patient_registration.json
Thanks heaps.
Hello,
Thomas from Germany here, happy to participate in this Connectathon. First-Timer on a WGM :)
I'm here too if others are wondering about!
Questionnaire assemble/CQL discussion in Salon B
@Thomas Debertshäuser You may have left your european power adapter at the Questionnaire table...
Just a reminder that tomorrow @10 there will be a demo session for Questionnaire-related stuff in Salon B. We'll divide up the time amongst those would who like to present something.
I'll have some updated displays on the pre-populate form test work that I've been adding to the fhirpath-lab, and maybe show some of the Generative AI chat functionality that's in there (if others are interested).
We usually have a break-out session for an in-depth walk-through of the Structured Data Capture IG. Are people interested in that this time around? It is short-notice, but there is an available slot we could use in Salon C at 11, if there is interest.
Aidbox Forms Builder - https://formsdemo.edge.aidbox.app/ui/sdc#/forms/builder?mode=public-builder
A couple of people asked to see the slides from my presentation at the Questionnaire track demo break out session, so I am attaching those here.
2024-05-NLM-Questionnaire-Tools.pdf
@Thimo Hölter In case you want to look at some of the other available tools :)
Hey there, anyone considering coming along to the September FHIR Connectathon and doing the Questionnaire track as their primary track - we had very few in Dallas and wondering if we should run the track again.
Brian Postlethwaite schrieb:
Hey there, anyone considering coming along to the September FHIR Connectathon and doing the Questionnaire track as their primary track - we had very few in Dallas and wondering if we should run the track again.
I am still pondering whether I am able to make my way to Atlanta, but in case everything works I will likely only attend the WGM.
We have decided to hold the Questionnaire track again in September. The track kick-off call will held during the regular FHIR-I/Questionnaire call on Thursday, September 12th, the details of which are at https://www.hl7.org/concalls/CallDetails.cfm?concall=72727 (though please note that the time is 5 p.m. ET, not EST as it says there).
For those attending the Connectathon, I've schedule a breakout session for Questionnaire-related demos on Sunday at 10:00 a.m. The room name is "Dogwood B".
I'll be showing the definition based extraction stuff David Hay and I have been working on.
If I can come in remotely I can give a demo of the Questionnaire authoring side
Will see what we can organize.
Does anyone have CQL (w/ ELM) Questionnaires we can play with?
Suggest checking at the Burden Reduction table
New issue idenfitied FHIR-48334 ($extract to get otpional questionnaire parameter)
Feature request for $extract definition approach FHIR-48337
@Brenin Rhodes @Brian Kaney
FHIR-48335 Definition based pre-population logic (smile already has a cut of this)
@Paul Lynch could you bring up this ticket during the Questionnaire session?
FHIR-48350 Specifically render a dialog for questionnaire item
@Fikri Milano Sure, we can try to discuss at the connectathon, but also we will take up the issue in the SDC workgroup call.
The Questionnaire Demo breakout session is at 10:00 in Dogwood B, which is on the M1 level, around the corner from Cottonwood and next door to the invitation only track. If anyone would like to demo something Questionnaire related, just watch the demos, or eavesdrop on the other meeting, come and join us.
Thanks Paul!
FHIR-I received a request for an extension to express concept properties in the Coding datatype.
FHIR-44935 - Specifying a drug code's "sub-type" in a medication resource (e.g., RxNorm SBD)
The goal is to enable the communication of a concept property in a resource and enabling a system to further understand the meaning of the code without needing the concept definition (e.g. CodeSystem or performing a $lookup).
The current extension proposal mirrors the CodingSystem.property
and CodeSystem.concept.property` includes:
The question is
CodeSystem.concept.property.code
and CodeSystem.concept.property.value
or it is an error)I probably missed the context for this. Classically these attributes have been firmly on the terminology side of the "terminology model / information model" divide. FHIR explicitly solves this discovery problem with CodeSystem.property
.
without always needing to consult a drug database
Looking up terminology information can be done in pure FHIR. Furthermore, all the concepts and first-party properties in RxNorm can fit in a few MB (https://github.com/jmandel/fhir-concept-publication-demo/blob/154980b56ceef8a928123019b881cd318b769be5/CodeSystem-rxnorm-03072022.json.gz has much more in 6MB)
Denormalizing these properties into Coding
s in every instance feels super brittle to me.
Better to get developers used to working with terminologies, and make this really easy. It should be a one-liner (and avoids the need to convince every trading partner to populate special redundant extensions in all of your instance data).
We have suggested that, but the use case (and thus the request for an extension), is to allow these properties to be sent in an instance where the receiving system does not have access to a terminology server or any other lookup. The specific use case was "is this RxNorm code a branded product or not?" Rather than creating a pharmacy-specific extension that would contain the RxNorm TTY, we asked for a generic extension that would any code property to be returned if needed.
This was discussed over a couple of weeks in FHIR-I (and has been bounced between WGs). This was the direction that was proposed during a recent call.
I suppose it is good that it is now posted here to generate some more conversation on the matter.
As for the use case/need, I will let @Frank McKinney , @Vitaliia Muzyka, and @James Patterson
But as Jean mentions, there was a need to know whether a code is a brand name or generic (other something else) and in an example provided in the ticket they may have both as RxNorm codes under a single CodeableConcept.
in an example provided in the ticket they may have both as RxNorm codes under a single CodeableConcept.
they can only have both codes in a CodeableConcept if the codes describe the same concept, though specificity is allowed to differ. Properties are clearly not different specificities
did anyone consider including a contained fragment of the code system?
both codes do describe the same concept, just at different levels.
ALOPRIM 500MG Injection is a Branded Drug or Pack
allopurinol 500MG injection is an equivalent code but representing the Clinical Drug or Pack
allopurinol 500MG is an equivalent code representing a Clinical Drug Component.
All three of those codes represent the same drug but at different levels of specificity. If I'm given 1721586, 252931, and 1721589 as codes in a Medication, how can I tell which is the code for the branded drug vs the clinical drug vs the clinical drug component?
We can convey whatever the easiest method to that is to the requester, but it seemed the simplest was to return an extension with the TTY for each code.
@Jean Duteau For clarity, when you say "return an extension", it sounds to me like that would fit for the context of an API call (i.e. from a terminology server) - but I'm presuming that it probably would be more accurate in this case to express it as "include an extension"?
you have to assume for this use case that the receiver has no access to a terminology server, so the original instance would include this extension to differentiate between the three codes. Pharmacy assumed that this wasn't a pharmacy-specific use case and that you might want to return properties of codes from other code systems, i.e. LOINC, rather than have the receiver have to do a lookup.
the receiver has no access to a terminology server,
so starting with your hands tied behind your back. I really doubt the wisdom of this assumption.
Pharmacy assumed that this wasn't a pharmacy-specific use case
so far it has been
If I'm given 1721586, 252931, and 1721589 as codes in a Medication, how can I tell which is the code for the branded drug vs the clinical drug vs the clinical drug component?
Why does it matter?
the reason I ask is because the assumption seems to be that some dumb software without terminology support gets this thing, and it needs to differentiate between the different kinds of code, but just telling it which is which allows it to do something useful with the codes, but still without terminology support.
That smells badly
we were told that they didn't have access to a terminology server and we were told that it mattered. If you'd like to argue the use case with them, I'll gladly put them in touch with you.
well, at some point we have to say no to stupid non-functional requirements driving ever stupider solutions
put a MedicationKnowledge resource in there, and they can get everything they want.
e.,g. a terminology server is the solution to this problem, so why won't they use one?
#Medication > FHIR representation to signify brand vs. generic
To clarify a little further, the inclusion of the medication is being provided as part of an oncology focused genetics test report, so the current mentality is that the receiving organization shouldn't really need to perform any lookups or dig into RxNorm. The information should be served up and ready for a physician to use based on some basic visualization of what's in the FHIR resources.
Yes, but to find it the consumer of our FHIR details needs to integrate with RXNorm API, and they are not happy with it. They want to understand it from FHIR data, without additional integration
I'm maybe stupid or something, but you can serve it up with a terminology server. And why did they say the RxNorm API? That's not the only terminology server in town
They want to understand it from FHIR data, without additional integration
they can. it's called a FHIR terminology server. They want to do less work
but this did come up in Australia, btw, also in the same context.
You don't even need a "server" - it's just a lookup table.
Otherwise where do we stop? Include every property of a code just in case a downstream client might want it?
if you look at http://hl7.org.au/fhir/4.1.0/StructureDefinition-au-medication.html, you'll see the extension they used to differentiate the different AMT classes
it would be interesting to know if this has come up in other jurisdications. Has Pharmacy looked at that?
How it originally came up was wanting a meds terminology neutral classification of drugs - so I get the same classification no matter whether the actual meds code is RxNorm, AMT, dm+d, etc
except that is Australian specific, so dm+d and rxnorm seem out of scope
I was thinking of the work that predated but informed that. It kind of traces back to this: https://github.com/AuDigitalHealth/medserve/blob/master/medserve-fhir-extensions/src/main/java/au/gov/digitalhealth/medserve/extension/MedicationType.java
It's completely reasonable for a system to want to be able to represent the properties of a code on the Coding. "I don't have a tx server" is only one. (And it's a valid use-case - legacy, light clients like phones, etc.) Other possibilities are a need to persist the data or to hold it on the FHIR object in-memory after having hit a tx server. So defining a standard extension on Coding (or code?) for properties seems both reasonable and useful to me.
Grahame Grieve said:
if you look at http://hl7.org.au/fhir/4.1.0/StructureDefinition-au-medication.html, you'll see the extension they used to differentiate the different AMT classes
AU approach was actually proposed in that generic vs brand thread, and it should have got more attention.
Adding a property in Coding would solve medication class problem for RxNorm, but not for SNOMED for example, because there are different medication concepts in SNOMED but there's no such property.
I personally don't like the idea of having properties in Coding, because I think people will use it to fill the gap in terminology and invent their own properties, which may or may not conflict with the real ones. But if we have that extension, I'd prefer strong validation to discourage creativity.
Playing Devil's Advocate for a bit, I can see the arguments being put forward for such properties also being used to justify including mapped codes (e.g., with a relationship of related-to).
Also, CodeSystem supplements provide the work-around for people to "invent their own properties", so if we're to have strict validation we'll also need to point at the source supplement(s).
From what I understood, and reading the above, I'd like to confirm that we all thought / agreed this was a terminology issue. The question was "how to transmit this information" and we realized that this information was/could be in the concept, not newly/locally generated information.
The need was not "how to express the concept properties in a coding?", but "_if_ for some reason we _need_ to transmit this one property of a coding along with the code, do we invent our extension?"
I'd like to confirm that we all thought / agreed this was a terminology issue
I'm not convinced that this is the case
it has come up repeatedly with medication codes, but not, so far as I am aware, for anything else. And the Australian extension was/is intended to be CodeSystem independent
But I'd like to hear from affiliates other than Australia too
I mean, when the discussion came up, we understood that these are concept properties. the use case can be pharmacy-driven, or pharmacy-only, but this is about terminology and concept properties.
I think it's not.
I think the guidance that makes sense to me would be is:
you shouldn't be in a position where you really need this, but if think you need it, please realize these are still concept properties, not extra elements in a prescription and if you do want to send it, put it here in this place, because at least everyone knows what you are talking about and the terminology validation can check if there is any issue.
I think Term Type is a property of an Medication product
these are still concept properties, not extra elements in a prescription
But if you can express the idea independent of code system, how are they concept properties?
how independent of code system?
So far, the Kiwi solution has been to implement this via Code System properties and Medication Resource Extensions - depending on the use case.
how independent of code system?
Could be completely. You could use the Australian extension with a code system that has no inherent knowledge of the kind of code . You just have to determine it yourself
Another use case for it is dose form properties. For generating PhPIDs only certain dose form properties are used, not dose form concept code itself. This would theoretically mean, that the Coding itself would be empty and only this extension would be filled in (4 times).
In a way I see the point in doing this, but it would not be possible to validate this in any way, so it's still a very edgy case with no cross-implementation value.
if the code for "Fluoxetine 4 MG/ML Oral Solution [Prozac] is an SBD, that will be in the concept in the code system, i assume.
@Peter Jordan are you using an an extension because you consider it an attribute of the product, not a property of the code?
Jose Costa Teixeira said:
if the code for "Fluoxetine 4 MG/ML Oral Solution [Prozac] is an SBD, that will be in the concept in the code system, i assume.
Only for RxNorm. SNOMED, for example, does not have a property for this.
In order to have a standard way of expressing medication concept type, AU extension works better.
Jose Costa Teixeira said:
Peter Jordan are you using an an extension because you consider it an attribute of the product, not a property of the code?
It's an attribute of an NZMT concept (as is the concept identifier). The underlying relational structure of NZMT and AMT provides these attributes and distinctions (e.g., generic and brand medications are held in separate tables).
ok, but I think I am missing something then. Either "term type" is a property of the concept in the code system, and that is why we say use terminology services for that (and hence the request to have those in a standard extension if needed), or we say "this is not related to the concept code at all".
i think i read those 2 above, and don't see how to reconcile it, but maybe it's late and i'll see better tomorrow
There are 2 perspectives. The terminology one renders these attributes as code system properties, the medication/formulary perspective maps them to extensions of a Medication resource. Therefore, to take one example, the underlying NZMT/AMT Type (MP, MPUU, MPP, TP, TPUU, TPP or CTPP) can be represented in two different ways in FHIR depending on which resource is being requested (CodeSystem or Medication).
Jose Costa Teixeira said:
ok, but I think I am missing something then. Either "term type" is a property of the concept in the code system, and that is why we say use terminology services for that (and hence the request to have those in a standard extension if needed), or we say "this is not related to the concept code at all".
Yes, we're mixing two topics.
1) If information exists in the terminology as a property, you could use a terminology service for that, and it's questionable if having this extension is necessary.
2) If we talk about medication concept type, then not all medication terminologies have that information as a property. In that case, this extension on Coding will be of no help for you.
Peter Jordan said:
There are 2 perspectives. The terminology one renders these attributes as code system properties, the medication/formulary perspective maps them to extensions of a Medication resource. Therefore, to take one example, the underlying NZMT/AMT Type (MP, MPUU, MPP, TP, TPUU, TPP or CTPP) can be represented in two different ways in FHIR depending on which resource is being requested (CodeSystem or Medication).
And if they are properties of a concept in a codesystem, you don't put them inside coding, but make an extension on the outer object (medication)? that feels weird (even if it is valid, but I wonder if that is what you mean)
Rutt Lindström said:
1) If information exists in the terminology as a property, you could use a terminology service for that, and it's questionable if having this extension is necessary.
It is questionable if that extension is necessary in a system. But if the information is sent, do we want to say "we don't acknowledge this as common so use your own extension"? or we'd say "we don't think this is necessarily a good idea from a data integrity perspective, but if you do, at least do it here, because then you have a chance at validation"
2) If we talk about medication concept type, then not all medication terminologies have that information as a property. In that case, this extension on Coding will be of no help for you.
if it's not there, it doesn't need to be sent. Or are we looking at the cases that the information is there, but not as a property?
The NZ extensions are on the Medication Resource, not the terminology resources. We now have a single source of truth for FHIR Medication Resources which is the NZ Formulary. I'm not sure what you mean by 'outer objects'. This is about use cases and the best solution for each use case - i.e. if a user requires more information about a Medication than the code, description, code system & version what's the best means of obtaining that? If the client is requesting lists to populate selection drop-downs, they are likely to be getting that from Terminology Server. If they are after detailed information, such as active ingredients for drug to drug interaction checking or contra-indications, they would probably request medication resources from a Formulary API.
@Jose Costa Teixeira weird that your having this difficulty when there's Observation.bodySite, Observation.method, etc. Doesn't seem to different to me
BTW, I'm agnostic on whether it's a good idea to create this extension, but I take Grahame's practical point about where code system information would come from if it's not being requested from a TS or a more general FHIR server with easy access to one.
The more I think about this, the more I think the solution (to having the information locally available) is to have a contained MedicationKnowledge resource (and for this use-case, populate productType)
Michael Lawley said:
The more I think about this, the more I think the solution (to having the information locally available) is to have a contained MedicationKnowledge resource (and for this use-case, populate productType)
Maybe when the FMM Level of this resource has risen beyond 0 (R4) and 1 (R5). It's too immature to implement in production systems at the moment.
Michael Lawley said:
The more I think about this, the more I think the solution (to having the information locally available) is to have a contained MedicationKnowledge resource (and for this use-case, populate productType)
Hell no.
For this use-case there would only need to be two populated elements: MK.code and MK.productType - that seems pretty low-risk
Seems much cleaner that using a contained CodeSystem fragment
contained fragment?
So, expressing additional information about the concept (e.g. transmitting one property of the concept) is so strange that we don't even want to include it as a possible extension?
I think we should not say "you cannot replicate information that belongs on a terminology server" because that server or that information may not be there.
If we had a standard extension, we could have some validation of the content, some advice about when (not) to use it.
anyone can define their own extensions. But this one is certainly throwing up some challenges that make me sympathetic to the idea that HL7 shouldn't define it globally.
The request comes from an accelerator, which makes things a little more challenging process wise
What is the downside to defining it globally? It's not clear to me from the thread.
I guess I'd ask the same question as Lloyd does above... what the downside would be to define a standard way to include a code system property with a coding, for situations where it would be useful.
I understand that this fits the RxNorm use case that started the discussion and wouldn't fit all code systems or needs. But it does seem to fit the requester's need pretty well.
Regarding the request coming from an accelerator, I've heard this desire expressed on FHIR implementation projects as well (also related to RxNorm).
Do you end up making an extension for every different property of every different code system and limiting their use to just that code system?
LOINC property X, can only specify if system = LOINC
SNOMED property X, can only specify if system = SNOMED
RXNORM property X, can only specify if system = RXNORM
Also, I think you might need to be careful of licensing. Some properties might not be shareable with non-license holders. Saying, "here's how you share property X of LOINC, but you can only share with licensees." Seems like a good way to, "just to be safe don't populate that."
why wouldn't a common extension work that is just a name/value pair. extension[propertyname] and extension[propertyvalue]?
What value set would you bind the code to, the allowed values as defined by LOINC or the allowed values defined by SNOMED.....?
what code?
there is no (predefined) valueset for code system properties
Wouldn't there have to be so that when you saw:
{ url: "CodeSystem Property X",
value[], "7" }
you'd have somewhere to go to know what 7 means?
yes. so, there would be a codesystem "rxnorm properties"
but the common extension, if we have one, would not use that valueset
it's the same with codesystem.concept.property.code for which there is no valueset
If you’re going down this route, why not a complex extension ext-code system-property, with subextension property
of valueCoding, and another subextension value
with valueCoding? valueString?
i think that is the idea
Oh, I interpreted the above as the property would be in the extension canonical.
Isn't that type of key-value pairing an anti-pattern in FHIR? I am guessing that is some of the pushback. If you have specific need of specific properties, those can be defined in a simpler way.
I am undecided myself yet, but thought I would raise the question =)
Jose Costa Teixeira said:
it's the same with codesystem.concept.property.code for which there is no valueset
Properties for individual code systems can be also expressed in TerminologyCapabilities.codeSystem.version.property - but that resource is only likely to be available on a Terminology Server. In the FHIR spec, information on external code system specific properties is held in the Using [code system] With FHIR Pages - moved to THO in R5.
It's one thing to determine where to place property names & values in payloads, but the practical consideration to overcome is where that information will come from.
the assumption is that this information is coming from a terminology service (reference/master data) but is persisted in the transactional data (medication lists or prescriptions). My leaning is still to prefer an extension that is clearly linked to terminology, if that is the case, rather than an extension on medication - the latter I think will lose the link to the concept property
What if we completely untied this conversation from Medication?
Let's just discuss the original question that was an extension on Coding for communicating concept properties. And most importantly, how this should be validated.
@Jose Costa Teixeira What you're saying is implying that you'd like a strong validation that could be checked against a terminology server.
How about the dose form attributes case that I mentioned earlier: when you only want to store concept properties but you don't actually want to have the concept itself (because you would have several matches for the properties provided)? Should that be allowed?
How about codesystem supplements? Should you be allowed to add something from a codesystem supplement that is maybe only available for you?
Rutt Lindström said:
Jose Costa Teixeira What you're saying is implying that you'd like a strong validation that could be checked against a terminology server.
Not that far - I don't think it means I want a strong validation. But I think it would be good to not give that up.
when you only want to store concept properties but you don't actually want to have the concept itself (because you would have several matches for the properties provided)?
that is not this use case. I don't think i'd do that. Even in the use case i imagine when that could be used, I wouldn't use this extension.
Should that be allowed?
I didn't propose that, but don't see if it should be forbidden of if it adds anything
How about codesystem supplements? Should you be allowed to add something from a codesystem supplement that is maybe only available for you?
yes.
Seems like it needs to be done carefully where a property might overlap with a defined data element in the Resource. e.g Anywhere where FHIR has something like a 'code' element and a less granular 'category' element. Potentially, someone could use a is-a property that puts a category code into the extension instead of using category. I have not looked carefully but there could be much worse examples... @Corey Spears has this been considered? what is the thinking to avoid redundant locations for information?
The current proposal is a global extension with Context of Coding:
Extension: ConceptProperty
Context: Coding
Description: "Used to specify a codesystem-specific property value of a coding"
* extension contains PropertyName 1..1 and PropertyValue 1..1
* extension[PropertyName] ^short = "the codesystem-specific name of the property, eg. CLASS, TTY"
* extension[PropertyName].value[x] only string
* extension[PropertyName] ^short = "the value of the property, eg. RAD, SBD"
* extension[PropertyValue].value[x] only string
Property values are typed - why would you only use valueString here?
Also, what about subproperties?
String can have a value set attached to it if someone wanted to further constrain the extension. Since the Coding will state its code system, the set of properties (and sub-properties) is constrained by that code system. But I don't think we can constrain it at the core level. Can we make a value set of all properties of all code systems?
String can have a value set attached to it if someone wanted to further constrain the extension
that doesn't answer @Michael Lawley's question about property data types
Since the Coding will state its code system, the set of properties (and sub-properties) is constrained by that code system
indeed, 'constrained', but that's not the same as 'equal', as several code systems have properties from different code systems
But I don't think we can constrain it at the core level. Can we make a value set of all properties of all code systems?
No, because many properties don't have formal code systems assigned. For instance, with RxNorm, SBD is very much not a valid RxNorm code, but has no other code system defined for it
right, that's why I believe that the core extension has to be strings which can be constrained with a value set for specific purposes if needed.
but I believe that alternate suggestions that satisfy the use case would be just as acceptable
Apologies for reviving this topic. If I need to send the concept property with the resource without querying the terminology server, it appears there are 3 potential options mentioned in this thread, if I understand correctly:
If I have to do it today, which option would you recommend as best practice?
to do what exactly?
@Grahame Grieve to create a resource that has an element of the Coding data type, which contains values from a CodeSystem property—not just the code and display.
For example, suppose I create an Observation with a LOINC code, but I want the code element to also include a COMPONENT property from that LOINC code.
I think my advice will vary depending on what property, but in general, consumers of the information will find it a lot easier if you have extensions for the specific properties you want to add - e.g. a LOINC system extension
Thanks @Grahame Grieve You mean like this ? (I think it's the one Jean proposed)
{
"resourceType": "Observation",
"code": {
"coding": [
{
"code": "15074-8",
"system": "http://loinc.org",
"display": "Glucose [Moles/volume] in Blood",
"extension": [
{
"url": "http://extension",
"extension": [
{
"url": "name",
"valueString": "COMPONENT"
},
{
"url": "value",
"valueString": "Glucose"
}
]
...
}
"valueString": "PROPERTY" seems off
Thanks @Jose Costa Teixeira It should be component. I edited it.
the types are definitely wrong; the component should be a code, and the type of value should be whatever it's defined as in LOINC
I guess that the next question to consider is how the use of this extension would be defined in a Profile.
not different to any other extension in that regard
The broad range of potential property types and values is different to that of many extensions. Defining which properties to return for each individual code system could be challenging, unless the use case requires just a single, common property such as 'parent' or 'child'.
The broad range of potential property types and values is different to that of many extensions.
well, that's why I think all this is a bad idea, but I'm trying to resist revisiting that subject.
Defining which properties to return for each individual code system could be challenging
well, what properties can be returned and their data types is already defined by the code system itself. Choosing what to pollute the instance with would have to be driven by the use case
Just noting also that the value of the property COMPONENT for 15074-8 is the code LP14635-4, not the string "Glucose"
thanks - I missed that
Thanks everyone :folded_hands: I edited as suggested.
Base on the discussion here, can I summarize it like this?
Keep the Coding element simple then query more properties from a terminology server is a better approach than try to include properties into the instance. But if it's really need to be included, use extension at the Coding element.
{
"resourceType": "Observation",
"code": {
"coding": [
{
"code": "15074-8",
"system": "http://loinc.org",
"display": "Glucose [Moles/volume] in Blood",
"extension": [
{
"url": "http://extension",
"extension": [
{
"url": "name",
"valueCode": "COMPONENT"
},
{
"url": "value",
"valueCoding": {
"code": "LP14635-4",
"system": "http://loinc.org",
"display": "Glucose"
}
}
]
...
}
you need to have the same property type as the definition of the property in the code system
I see. Thanks :big_smile::folded_hands:
In this case, I checked with LOINC. It's really a Coding type for this property. But I understand that it can be different in other CodeSystem.
{
"resourceType": "CodeSystem",
...
"url": "http://loinc.org",
...
"property": [
{
"code": "COMPONENT",
"uri": "http://loinc.org/property/COMPONENT",
"description": "First major axis-component or analyte: Analyte Name, Analyte sub-class, Challenge",
"type": "Coding"
},
...
]
}
This is one of those cases where Regenstrief's server and documentation differ from what HL7 / THO have said (https://build.fhir.org/ig/HL7/UTG/LOINC.html#loinc-properties):
COMPONENT code First major axis-component or analyte: Analyte Name, Analyte sub-class, Challenge
Both Ontoserver and tx.fhir.org currently treat COMPONENT as code-typed, not Coding-typed.
Also, I presume that "http://extension"
is just a placeholder URI for the purposes of a brief example?
Are you referring to the type of the Property Name or the Property Value. Taking an example from a lookup request on 100312-8...
{
"name": "property",
"part": [
{
"name": "code",
"valueCode": "COMPONENT"
},
{
"name": "value",
"valueString": "Person or persons that makes sure there is enough food, medicines or any other things needed in house"
}
]
}
The type of the property value.
Not sure what server is returning a String value for COMPONENT, but that is clearly incorrect
Really? That value doesn't look like a code to me.
That's the display for LP432343-4 which is what should be returned
That example is simply reflecting what's in the LOINC Core Table which doesn't contain pointers to the Parts Table. I'd get the same string value from a $lookup request on that LOINC Part Code. Either way, my feeling is that the description is more useful to a client - so the best solution is probably to use the Coding Data Type and show the Part Code and Description.
Michael Lawley said:
Also, I presume that
"http://extension"
is just a placeholder URI for the purposes of a brief example?
Yes, it's just a placeholder.
But thanks for pointing out that the Regenstrief server may have a different implementation compared to other servers. I wasn't aware of this until now.
Michael Lawley said:
Also, I presume that
"http://extension"
is just a placeholder URI for the purposes of a brief example?
The initial question is whether hl7 defines that extension. I think it it good to do so because then there is agreement and documentation of what is discussed here
Peter Jordan said:
That example is simply reflecting what's in the LOINC Core Table which doesn't contain pointers to the Parts Table. I'd get the same string value from a $lookup request on that LOINC Part Code. Either way, my feeling is that the description is more useful to a client - so the best solution is probably to use the Coding Data Type and show the Part Code and Description.
@Steven Wagers I'd agree with Peter, what are we doing at LOINC FHIR server?
@Robert McClure here is how the component is represented on our FHIR server when you do a lookup for 100312-8
{
"name": "property",
"part": [ {
"name": "code",
"valueCode": "COMPONENT"
}, {
"name": "value",
"valueCoding": {
"system": "http://loinc.org",
"code": "LP432343-4",
"display": "Person or persons that makes sure there is enough food, medicines or any other things needed in house"
}
} ]
}
When I look at the IPS specification, and the landscape in which IPS will be used, I think that there's a piece of the puzzle missing, to make handling the IPS with the challenges it brings consistent and manageable
I believe that we can do something about this, which is to make our normal process for handling IPS documents to wrap them in a zip file with a little simple manifest file. This gives us a place to handle encryption and signatures and also to manage the issues of transformation of the document while retaining integrity, all of which are important
here's a very rough first draft of a wrapper specification:
note that the spec proposes an additional way of wrapping the IPS, which is to put the wrapping zip file in an PDF itself, so that all platforms can render the IPS, even if they know nothing about IPS
IHE already has specs like XDR to do this - why create yet another option if we already have DocumentReference to express almost everything in your newly proposed manifest ?
I don't believe that XDR does this. it does something similar
if you think it does everything, feel free to explain how
Standards like IHE XDR and DICOM Part 10 serve to convey a document/image and associated metadata/manifest. The FHIR equivalent of XDR (@John Moehrke ) is based on the use of DocumentReference and List for manifest/metadata identification. I don't see why FHIR Documents / this use case shouldn't be covered by that solution, which is based on years of implementation experience. You propose something new, so I'm afraid the burden is upon you to show what's so radically new about this use case that it can't be supported by a tried-and-tested solution and that it needs something new. Maybe it does, maybe it doesn't - I haven't done a detailed analysis. In general it's desirable to look at existing solutions first before creating something new, and to only reject that if one has a very good reason to do so.
Well I did look but they’re doing something different, in that they propose an enterprise solution for document management. This is a very different situation and I’m at a loss to see why you think they compare
The only similarity is that there’s a manifest but it does different thinsg
Closer to XDM... but agreed that IHE has not addressed the xdm usecases yet. No one has asked. Glad to work together.
true. XDM is the closest, and it's the same idea in principle. But I looked at my old friend the XDM manifest, and it just didn't address those use cases.
Y - I meant XDM, I did use the wrong acronym. If your new use case is "This gives us a place to handle encryption and signatures and also to manage the issues of transformation of the document while retaining integrity, all of which are important" - I do believe transformation is already covered by DocReference. Encryption and Signatures - not sure how that would be covered.
There's also the Standard Personal Health Record specification that deals with similar topics. Ping @Abbie Watson
I don't believe it does. I read it. and couldn't find any overlap with what this does
A comprehensive explanation of the encryption options are described in DEN (unfortunately still TI) - https://www.ihe.net/uploadedFiles/Documents/ITI/IHE_ITI_Suppl_DEN.pdf
For whole XDM encryption, IHE encapsulates it in S/MIME option from ATNA - https://profiles.ihe.net/ITI/TF/Volume1/ch-9.html#9.2.6.5
For document by document encryption, IHE uses DEN - https://www.ihe.net/uploadedFiles/Documents/ITI/IHE_ITI_Suppl_DEN.pdf
For document by document signature, IHE uses DSG - https://profiles.ihe.net/ITI/TF/Volume1/ch-37.html
These are not FHIR specific, but work equally with FHIR objects as with anything else. This is a strength, in that it enables one infrastructure to be used regardless of the content encoding.
This said, i do like the Secure Health Card solution for purely and portable FHIR content. Really wish this was a formal project.
it will be a formal project
Smart Health Cards and Smart Health Links, that is.
I'd like the IPS wrapper to be too, but that's not at all assured, since i just proposed it
I agree that XDM covers encryption, but I don't think it has quite the same simplicity and certainly not aligned with JWE/JOSE
I agree. just trying to be clear.
why would SHC not be enough? Why is there something specific for IPS wrapper?
also, note there is a proposal to update DSG to include json signatures, would need participation to help bring this forward.
SHC doesn't resolve all the other parts. SHC is enough for the parts it does, except that you don't always want verification (or don't have the infrastructure to set it up) and you don't want to duplicate that content
doesn't SHC and SHL together do the trick?
do what trick?
SHC and SHL don't deal with the packaging part at all. Only the access part, and I've tried to use SHC and SHL where I can.
SHL is a transfer spec, i don't see how you could use it as a storage spec
though if this is adopted, we would add this as a new content type in SHL - accessing the SHL gets you this wrapper instead of the naked bundle (which is how it works now)
Maybe I'm missing the use case. If I'm thinking about (a) validation, wrapping in a SHC gets us there. If I'm thinking about (b) encryption, that really is a transport question, so using a SHL gets us there (with JWE). I don't see where we need to define an encryption story for the data beyond transport --- we don't do that for other things (e.g., I'm an EHR and I receive an IPS, I need that data decrypted and then put it into my own store with my own protections).
I think there's a use case for encryption, which is where someone is holding an IPS on behalf of someone else who holds the passphrase
that's not an EHR use case, but it's a common patient right in mixed patient/health system scenarios around the world
100% buy that --- but that still works if the data is in a SHL. I actually implemented a version of this in my baby SHL host (see here).
well I don't understand that. A SHLink is a reference to a thing somewhere else, so how can it that protect the thing?
because unless I missed something, the data is not in the SHL
"somewhere else" is relative.
I think there's a use case for encryption, which is where someone is holding an IPS on behalf of someone else who holds the passphrase
SHLinks meets this use case by allowing a (potentially key-less) web service like Sean's example to "hold... the IPS" (i.e., encrypted as a JWE) "on behalf of someone else who holds the passphrase" (in the form of the SHLink).
I cannot get my head around that workflow
Hmm. Maybe it's easier to talk about a step-by-step workflow.
I mean, I understand that workflow from a SHL perspective for the transfer part.
what I don't understand is to how to bend that into shape for the kind of use case I'm thinking about, where I just have an IPS, I'm not transferring it
If you aren't transferring it, why do you need a healthcare specific interoperability standard to encrypt it for local storage? Why not just rely on your local wallet or application level storage choices?
that question doesn't make any sense to me
it's still encrypted.
You mean to say that whoever gave it to you... gave it to you in this encrypted format?
yes. you don't yet have the passphrase, and maybe you never will in your workflow.
someone else will retrieve it from you and reunite it with the passphrase
You talking about giving patients artifacts that they can't and might never be able to read?
I'm not sure whether to say yes or no to that. Storage proxies. e.g. holding a IPS for someone else, like a family member
The only point of acting in that "holder" role is to facilitate a transfer (since by definition you can't do anything with it). In which case, I'm back to the SHL scenario which does this just like you describe.
Maybe i'm just stupid, because I don't see how it does
This'll take me a minute to get the bullets right, but I'll try to stage out a sequence of events for what I think we're discussing...
Organization A would like to store some encrypted data to facilitate transfer. It accomplishes this by encrypting the IPS and sending to a storage proxy that supports a SHLink hosting.
Organization A can then share the SHLink with anyone who is supposed to be able to read the data.
the passcode grants you access to it or not. Period. There's no way to share a still encrypted artifact that will later be decoded. I just can't see that in the spec
It accomplishes this by encrypting the IPS
bingo. That's what I'm describing.
It's not meaningful to share it before the point that you can decrypt it. You're literally not sharing anything except a pointer where you can't tell whether it is valid or not. You might as well be holding on to an empty pointer at that stage.... Which you can model with SHL as " I haven't shared it yet but I will soon"
but you can in what I wrote
because it's only partially encrypted.
because that's what gives workflow robustness
I'm trying to infer your workflow. I think it involves sending an encrypted payload to the patient together with a non-encrypted payload. And the patient might or might not be able to read the encrypted part. But they can still forward it to someone else who might be able to read it behind their back?
no you're thinking about it wrong. The patient has the passphrase. They can read it. But their storing proxies (other systems or people) might not
I'm afraid now I'm lost. I'm going to just stand by for a bit and see if you two find the disconnect, because again I think you just described a SHL workflow.
I'm not seeing it either :/
so you should say :
And the system might or might not be able to read the encrypted part. But it can still forward it to another system that might be able to read it at the behest of the patient ?
again I think you just described a SHL workflow.
what? I can't see it. the passcode gives you access or not
If the patient has access to their full record, they can create a SHL any time they want to share an encrypted subset.
That SHL can be sent to whoever is supposed to be able to access the encrypted subset.
what about proxies? I guess they just don't exist in your world because you haven't thought the full workflow through
Can you explain?
BRB
Can you say more about the role of proxies in this workflow? Which workflow participants need to be aware of proxies specifically?
Returning to this @Josh Mandel and @Sean Nolan.
I am thinking about the IPS workflow like this:
In the case of a passcode, the patient agrees at the source that the IPS will be passcoded, or decides to apply the passcode on the national repository (that workflow already exists with CDA) and then that passcode applies to all uses of the document, whether it's obtained directly from the national repository, or it's shared directly by the patient, or if the patient has it in their own local repository - even then, it's still passcoded unless the patient chooses to remove the passcode
(oh and like SHLinks, which features in some of the transfers above, a passcode encrypted document has a label, but I think it should also have branding)
Thanks Grahame. Before I respond, can you confirm that the difference you're calling out here is that, in your scenario, the artifact (the IPS) has an intrinsic "passcode" that stays with it. Like a password-protected zip file. Is that a fair summary?
(just in concept, not implementation)
in your scenario, the artifact (the IPS) has an intrinsic "passcode" that stays with it. Like a password-protected zip file. Is that a fair summary?
yes, that is it in concept
it's not incompatible with a passcode to retrieve that IPS. That might be a different passcode
Thanks! Super-helpful.
In a SHL-based implementation of what you describe, your "passcode" is the key used to encrypt the IPS.
(For simplicity I'm going to assume a U-flag SHL because there's only one file to worry about, but the same approach works with any SHL. I'm also ignoring the SHL-protocol passcode but it's just a second-factor and also doesn't change the approach.)
The patient receives (by QR or download or API) a SHL (shlink:/...) in which the URL points either to the institution or a national repository. Either way the file at that URL is the IPS, encrypted using the key in the SHL.
The patient can share that SHL with anyone they want to be able to download the IPS, or they can download and decrypt it themselves.
Nobody that is not holding the SHL will be able to read the contents of the IPS, because the key within the SHL is the passcode. As a proxy, the national repository MAY or MAY NOT also be given a copy of the SHL, per policy.
In this scenario, the passcode is "intrinsic" to the IPS because it is encrypted. That encrypted file can live anywhere. Theoretically it could move anywhere so long as the url in the SHL is updated to match.
But when it comes time to USE the data it has to be decrypted anyways. And the patient can do that, as can anyone they have shared the SHL with. And once that data is decrypted, it's up to the holder to keep it safe either by destroying it after use, or re-encrypting it with whatever means they use for that kind of thing. They could even generate new SHLs with their own key and encryption if that makes sense (e.g., combining their IPS and other data into a new, aggregated SHL).
I really think we're covering the same surface area here, but please let me know where that's not the case if so. Thanks!
I'm trying to understand this. The first observation I make is that in this arrangement, the patient can not transmit the passcode verbally; it can only be done by the QR Code, which is their effective passcode
the second is that in this arrangement, all documents are fundamentally encrypted always, so the only way to access is with the key.
in this arrangement, the patient can not transmit the passcode verbally; it can only be done by the QR Code
QR code or SMS, email, or any format that allows pasting of text (links)
but not verbally, which is the anticipated workflow in Australia, at least
further, I observe that the entire IPS is encrypted - without the SHL, not only do you not have the key, you don't have the label either
In Australia that verbal communication is like "Hey doc, I'm going to let you access my IPS in the national repository. Just go there and use my passcode: doN0H4rm"?
well, more like the doc says, "hey, there's a summary in your patient record that's PIN protected, want to tell me the pin?"
And that PIN is used to prevent the national repository from seeing the data, or just to prevent random doctors from seeing the data?
I'm trying to map this model onto my use case, but it feels incredibly fragile to me - the key has to be managed, and it's all workflow dependent, because it's not a property of the document itself.
that PIN is used to prevent the national repository from seeing the data, or just to prevent random doctors from seeing the data?
both.
So a simple PIN won't do, for keeping the information hidden from the national repository operators... short pin is brute forceable
e.g. how would I email someone the document that's passcode protected?
Josh Mandel: So a simple PIN won't do, for keeping the information hidden from the national repository operators... short pin is brute forceable
That's a very technical response, which is completely true, but also not relevant at the policy level
That's a very technical response, which is completely true, but also not relevant at the policy level
Policies need to be grounded in technical reality
yes but not completely
Both of your observations are correct --- if a voice-sharable PIN is a requirement, then you'd want another solution. But per Josh's comment the security of that doesn't seem realistic. I personally wouldn't want to be the person who recommended to the national govt that they secure their records with a voice-sharable PIN.
That's the problem in reverse: they made a policy that was impossible. That's not the case here
I personally wouldn't want to be the person who recommended to the national govt that they secure their records with a voice-sharable PIN.
but nevertheless, that's regulation here in Australia. Sneer as much as you like, making this work is a precondition
Here you seem to be talking about a policy that only works if the technology can support short easy to remember and easy to communicate PINS that also provide strong encryption that is not reversible
emailing an SHL - how does that mean that they need a passcode from me to read the document?
As Sean noted above, the best analogy for your PIN in SHL Is the decryption key itself.
(We do have something called a passcode that can provide additional production, but it's probably going to confuse this discussion more than it helps.)
If that's the case, all I can say is --- good luck Australia and let's not drag the rest of the world down by making that an international recommendation! Seriously, I'm not trying to be obnoxious here, this is just Security 101.
only works if the technology can support short easy to remember and easy to communicate PINS that also provide strong encryption that is not reversible
You said it only works that way. I didn't. What I've learnt is that if the technology puts a road-bump in the way, then the law can depend on the roadbump, and that is sufficient
anyway, what I see is that you're not interested in a workflow that doesn't meet your technical preconceptions of how it works
I'm very interested in these workflows. I am just not sure the extent to which they need to be standardized, given that they depend on interacting with one centralized system that people already have accounts in.
I will consider further. But I find the idea of separating the key and the document like this deeply disturbing from an architectural viewpoint - it feels to me like it will always be fragile and less resilient. But I can see that I have failed to make the case so far.
Grahame Grieve said:
I don't believe it does. I read it. and couldn't find any overlap with what this does
SPHR support for IPS is staged in pull request #12. Just needs a vote to bring it in.
https://github.com/HL7/standard-personal-health-record-ig/pull/12
Preview of the resulting SPHR conformance statement to external IGs is here:
https://build.fhir.org/ig/HL7/standard-patient-health-record-ig/branches/international-patient-summary/conformance.html
Once pulled in, SPHR is intended to detail the .zip functionality, encryption, and other details described above.
@Jürgen Brandstätter
Hi all! Could you help me to understand some use cases of Smart on FHIR (v1)?
I have a FHIR Server on [base-url]
and an Authorization Server on [auth-server]
. And a user has an access to couple of Patients resources and their clinical data (pt-1 & pt-2).
1) Let's suppose that the user provided a grant to 3rd party app within next scope 'patient/Patient.read patient/Observation.read patient/Observation.write' and patient=pt-1 in context. As a 3rd party, what responses should I expect?
GET [base-url]/Patient/pt-1
GET [base-url]/Observation?subject=pt-1
GET [base-url]/Patient/pt-1/Observation
GET [base-url]/Patient
GET [base-url]/Patient/pt-2
GET [base-url]/Observation?subject=pt-2
GET [base-url]/Observation?subject=pt-3
GET [base-url]/Observation
POST [base-url]/Observation
subject:
reference: Patient/pt-2
I believe that the first three requests should return 200 OK + data, and the rest of them 403 Unauthorized. Right? Or it depends on something?
2) Let's say we have not Observation, but CommunicationRequest resource. Which are search parameters available for 3rd party app within patient/CommunicationRequest.read scope? subject, sender, recipient, requester?
3) I'm thinking of building a tenant-based FHIR API which uses user-id as url prefix for every request.
[base-url]/user/<user-id>/Patient/pt-1 => 200 OK
[base-url]/user/<user-id>/Patient/pt-2 => 200 OK
[base-url]/user/<user-id>/Patient/pt-3 => 404 Not Found
I would say I have a lot of logical FHIR Servers on top of physical one. In case of EHR launch I could provide different iss parameters depending on the user who launched the app, so it could help me simplify access control module.
But I can't find an answer if it's possible to make something similar in case of Standalone launch. It seems like 3rd party app should know the only base-url and use it for every user? Is it possible to subsistute [base-url] somehow while launching?
For (1): in our server they are all 200 OK, they just return only the data of pt-2, so GET [base-url]/Observation?subject=pt-2 returns an empty bundle
(2) Which search parameter are available is unrelated to the scopes
(3) Don't think that would work, clients expect a fixed URL to connect to
(1.1) We have the same solution for now, but I'm not sure if it's correct using Authorization header as an implicit parameter for business logic. Will my server be conformant with FHIR Specification (which is RESTful) if it provides different responses on the same url depending on Authorization header? I believe, that according to REST, the role of Access Conrol is only accept/reject requests, but not influence on the result. So, I would say that in this case our FHIR Servers are not conformant with FHIR Specification. Is it correct, or I miss something?
(1.2) And what about saving resources (POST/PUT/PATCH)? Should my FHIR Server set reference to the patient implicitly or validate and require correct reference value in the body?
(2) From the smart app developer point of view, how should I understand which endpoints (or/and search parameters) are available within a specific scope I got from user? Does specification have this answer, or I have to adopt my application to every specific FHIR Server?
(3) I feel that the specification tries to connect Smart App Developer and FHIR Server Developer and it provides a concrete authentication flow. But as a Smart App dev, once I have a token, I don't see my capability within my scopes. And as FHIR Server dev I don't see a standard way to provide such capabilities.
So, once FHIR Server provided 'patient/Patient.read patient/Observation.*' scope, does it obligated to accept requests to [base-url]/Patient/<pt-id>, [base-url]/Observation
, etc?
Will my server be conformant with FHIR if I just say in documentation, that within patient/...
scopes smart app should use another base-url. e.g. [base-url]/patient/<pt-id>
([base-url]/patient/«pt-id>/Patient/<pt-id>, [base-url]/patient/<pt-id>/Observation
).
policies are important. principles of REST do not override policies.
In general with smart, it is okay for a server to reject a query prospectively/statically because of scopes. It is also okay for a server too simply redact results because of scopes. We don't have prescriptive behavior on this. The only thing it's not okay to do is return data beyond what the scopes allow.
The question of what endpoints are available is somewhat orthogonal to your scopes. For example, a server might advertise in its documentation or in its capability statement that it supports a "batch" endpoint; if it does, clients can call this end point with requests that are consistent with the available scopes. If it does not, clients can't.
I wonder SMART on FHIR based on baseUrl convention instead of more flexible HATEOAS. Why server after auth could not just return explicit baseUrl for the client with access_token ?
{
access_token: ....
fhirBaseUrl: ....
}
Compartments like /Patient/<id>/{metadata,Observation,Encounter} look like good fit for SMART Clients and Servers.
Thank you! I do missed that part in Access Denied Response Handling chapter.
Just to clarify, if I have a FHIR Server which is rich on capability, it is ok to restrict some access depending on client type, not only scopes provided to that client, isn't it?
That would work for areas like the patient compartment where fhir explicitly defines some context, but the mapping breaks down pretty quickly too. For example even with "patient" compartments, a smart app authorized to access data about a given patient might be able to see certain data outside of a compartment, such as data directly linked from or needed to interpret the data in the compartment. So passing the patient id (or fhirContext[] as array of references as proposed in SMARTv2) has been a flexible choice.
Michele Mottini said:
For (1): in our server they are all 200 OK, they just return only the data of pt-2, so GET [base-url]/Observation?subject=pt-2 returns an empty bundle
Should not server respond with 403 for (1)?
Josh Mandel said:
That would work for areas like the patient compartment where fhir explicitly defines some context, but the mapping breaks down pretty quickly too. For example even with "patient" compartments, a smart app authorized to access data about a given patient might be able to see certain data outside of a compartment, such as data directly linked from or needed to interpret the data in the compartment. So passing the patient id (or fhirContext[] as array of references as proposed in SMARTv2) has been a flexible choice.
What is fhirContext?
We are thinking about "poko yoko" for Smart on FHIR apps - i.e. implicitly inject patient id into all search and even CRUD operations.
@Josh Mandel what is your opinion about such an implicit server behavior?
nicola (RIO/SS): Michele Mottini said:
For (1): in our server they are all 200 OK, they just return only the data of pt-2, so GET [base-url]/Observation?subject=pt-2 returns an empty bundle
Should not server respond with 403 for (1)?
From the SMART spec perspective, both of these are OK behaviors.
What is fhirContext?
See FHIR-32253; this is being added to resolve SMARTv2 ballot feedback
nicola (RIO/SS): We are thinking about "poko yoko" for Smart on FHIR apps - i.e. implicitly inject patient id into all search and even CRUD operations.
I like this, but there are edge cases where it'll prevent access that a client should have (e.g., with patient/*.cruds
access, you might still be allowed to issue a query like GET /Observation/123
where the subject of the observation is something other than the patient (say, a patient's device or location).
Michele Mottini said:
For (1): in our server they are all 200 OK, they just return only the data of pt-2, so GET [base-url]/Observation?subject=pt-2 returns an empty bundle
I think for (1) - 403 is more honest - otherwise, the client may be confused and interpret the empty response as a lack of data
I think no error is better. Using 403 is actually _leaking_ the information that there is data that the client cannot see
Yep, if they're fishing for information, a 200 tells them nothing, a 403 says there's data which is a problem from a privacy point of view
AND this is why the actual value returned should be driven by POLICY. http://hl7.org/fhir/security.html#AccessDenied
i’m reviewing smart on FHIR (EHR launch) implementation (based on oauth 2.0 authorization code flow) where the EHR launches the application calling a launch URL specified in EHR configuration. The launch url contains a launch token in the query parameter and then the application exchanges the launch token along with the client identification parameter to get an authorization code and eventually access token from the authorization server.
My concern is that an attacker can steal or copy a valid launch token which hasn’t been used before and get an authorization code from the EHR authorization server, this is because the server cannot determine if the entity redeeming the launch token is the same user for whom the token was originally generated. There is no mechanism for the server to verify the identity of the redeemer and ensure only the right user receives the authorization code. Is this a valid threat or am I missing something?
For reference, Epic’s implementation is based on SMART on FHIR, an industry standard through HL7, link- https://fhir.epic.com/Documentation?docId=oauth2§ion=EmbeddedOauth2Launch
(deleted)
Don't ask the same question multiple times please?
The launch token is not a security feature, is just a way to convey context from the EHR to the app.
The step of the workflow after receiving the launch
parameter is to authorize with the auth server. So at that point the auth server will know who the user is and can verify that the launch
value they submitted was associated with them.
Are you both saying that the context communicated from EHR to the external app does NOT include the logged in user session? Meaning- the practitioner would have to enter their credentials into the browser again?
My understanding up to this point has been that the launch parameter kinda doubles as an "SSO" credential so if the EHR is a thick client and/or mobile app- the practitioners EHR session would be extended into the browser.
If I'm right about that- that's where I can definitely see some security challenges to mitigate (which i've seen strategies for)- but first wanted to confirm my understanding.
(deleted)
(deleted)
The launch parameter is opaque to the app and doesn't include identifiable information.
The EHR should not treat this as a credential, or an access grant, but rather as a correlation handle for an authorization that's happening in the usual way (authorization code flow).
There is probably more guidance that we could provide (potentially: cross check any launch context with the permissions of the authorizing user) but since we don't mandate the semantics of this field, we leave it to EHRs to use it as they deem appropriate.
The threat model is: an app or user can mess with this value before it's supplied to the authorize endpoint, and the EHR should be robust to that.
that would be a good security consideration to mention, in addition to a warning to make sure the value is opaque. EHR can handle that in many ways that don't need to be elaborated upon (e.g., signed, a hash, nonce, etc).
Currently we document:
In an EHR launch, an opaque handle to the EHR context is passed along to the app as part of the launch URL
Opaque identifier for this specific launch and any EHR context associated with it
opaque is read by some as okay to include understandable stuff, with expectation the user will not look closely. Much like an OID, UUID, or URL. So we might want to be more specific than opaque. No idea what words better explain that the value must not be understandable by the client.
must not be tamperable
Maybe this?
Servers should design their launch
parameter implementation with the assumption that malicious actors may attempt to replay, tamper with, or infer sensitive information from these values. Key security properties to consider include uniqueness, integrity verification, and protection against information disclosure. Implementers should ensure their design is robust against scenarios where the launch
parameter might be intercepted, manipulated, or forged before being presented to the authorization endpoint.
The attack I've described above is NOT a replay/tamper attack, let's say the launch token is a random value and it can only be used once. A bad actor could still get access to a valid token and then can try to use it to associate wrong account with the patient record, or it could be intentional as well where a user shared their token with another individual. I think it is important to mention that the EHR system should have some logic implemented to verify the identity of the redeemer of the launch token when issuing the authorization code.
Since the launch token is sent as a query parameter in the URL to the authorization server, it is susceptible to leakage, for e.g, when using referer header, this information will be leaked if a user visits subsequent pages controlled by the attacker. The launch token is not transmitted securely to the authorization server. It should maybe use back channel for it.
Thanks for the clarification, @Josh Mandel - spending most of my time in the standalone flow- i was not aware that the user will re-authenticate in the browser during an EHR launch flow. That helps a ton, as it means that we can at least trust that the user is valid, and the EHR can then ensure that the launch context is valid for that user (as called out), and underlying permissions are enforced as well.
brg-shrngi said:
The attack I've described above is NOT a replay/tamper attack, let's say the launch token is a random value and it can only be used once. A bad actor could still get access to a valid token and then can try to use it to associate wrong account with the patient record
The launch value doesn't associate accounts with records. Do you think it would help to add the following to the suggestion above?
Sservers must not treat the launch parameter as conferring access rights; authorization decisions should be based on the authenticated user's permissions, not solely on the presence or content of a launch token.
it won't hurt to say that, even though it should be obvious
Josh Mandel said:
The launch value doesn't associate accounts with records.
The launch token doesn't directly establish the association but it helps getting the authorization code and access token which can be used for establishing the association.
I think we should also share that the launch token is susceptible to leakage (because it is transmitted in URL), and we can maybe suggest some mitigations for e.g., by asking the user to sign in again
I'm not following what the launch token has to do with the authentication context. The launch already/always includes an authentication step.
"leakage" is already covered by the proposed language
assumption that malicious actors may ...
The phrase "infer sensitive information from these values" implies that if the token contains sensitive information, there’s a risk of leakage. It’s important to highlight that the token itself could be compromised, even if it’s designed to be random, unique and used only once. The client application needs a mechanism to send contextual information to the EHR authorization server for verification. This will ensure that the entity redeeming the launch token is the same user for whom the token was originally generated.
I am not sure I follow what you're suggesting here. Are you proposing that we add additional explanatory language or are you proposing that the specification needs new functionality?
We should add some explanation to clarify the language ensuring that readers are aware not only of the security risks but also of the potential impacts of this implementation.
Regarding functionality, I see a security flaw in this algorithm. I think we can implement a mechanism to link the requests to one another. For instance, the OAuth authorization code flow helps mitigate authorization code injection attacks, where a malicious actor could swap authorization codes to log into someone else's account by using PKCE parameters to protect the token exchange flow. We can use a similar approach for the launch token, by using code verifier and code challenge in the requests to ensure that the entity redeeming the token is the same entity who started the flow. Additionally, we can also recommend that the launch token should be transmitted via a back channel, which is a more secure option for sending the token to the authorization server.
Alternatively, we could remove the launch token step from this flow and instead obtain user consent directly in the EHR application. However, this might make the process similar to a standalone launch. Please let me know if my understanding is incorrect here.
We already have pkce. I can't tell if you're advocating for that or for something analogous that runs in parallel.
I'm not sure I understand the actual threat you were describing.
I understand this implementation is based on OAuth authorization code flow but it adds a step where launch token is required to be sent to the authorization server. PKCE parameters are not used when launch token is being exchanged
with the server hence this step is vulnerable to code injection attacks. PKCE is used in the later steps where request is being sent for authorization code and access tokens.
That's accurate re: PKCE.
I think the concern you are articulating is a kind of substitution attack on the launch
value. But substituting a different launch value should never enable an app or user to accomplish anything that they could not accomplish before. It does not authorize the app to see any new data, does not leak sensitive information to the app, etc.
Given the advice we drafted above, what is the residual threat that we need to mitigate?
it's not a security threat, but it might be a clinical threat - mixing contexts - specially in the case where patient-banner is true - could result in disastrous clinical outcomes
on the other hand, it really seems like a marginal threat in practice
The user tricking herself is not a threat. And if the app wants to trick the user about context, it can simply lie, not without actually manipulating the context; the user doesn't see this information directly, but only as mediated through the app's UI.
This is true, but @snahil is elucidating a risk that an attacker could intercept and change the launch context between the EHR and the launched app, so that an app that is (rightly) trusted to not do things like actually does that anyway
I think it is a possible theoretical attack but wow a lot of work for a limited outcome.
Let’s consider an example: Alice gains access to the launch token issued for user Bob. She generates a linking request from her client application, intending to send a launch token to the EHR authorization server. However, Alice swaps the original launch token with the one she stole from Bob. When the EHR authorization server receives the request, it has no way to determine whether the request is coming from Alice or Bob becuase it only receives the launch token (no other information). It verifies the launch token and issues an authorization token. Alice then uses this authorization token to obtain an access token, allowing her to link her account to Bob's patient record and gain access to all of Bob's data.
nah, not that
the launch token does not allow her to link her account to bob's record. The approval for that is in the AS, independent of the launch context
Launch tokens are not authorization grants. The server does not issue an authorization token on the basis of the fact that a launch token was provided in request. The server issues an authorization token only when a valid authorization code is provided, and an authorization code is only available to Alice if she has successfully authenticated and authorized the app to launch.
The threat Grahame Is describing makes More sense to me, but it involves a third party being able to intercept an app launch... At which point the user's device or session or app is compromised (i.e., similar threats could be carried out without having to go through this injection dance).
I agree that if you're compromised, you're compromised, and there's very higher gain threats than the one I described in that case
but I was thinking that there's a chance that you could inject a proxy with a DNS poisoning attack that can get at the launch context and not get at any other part of the request. In which case, my attack becomes the worst thing you can pull off.
But if you have a proxy that can MITM the SSL and get at the launch, this comes back to 'you're compromised', with all the consequences of that
Josh Mandel said:
The server issues an authorization token only when a valid authorization code is provided, and an authorization code is only available to Alice if she has successfully authenticated and authorized the app to launch.
Alice has a valid user account in the client application and successfully logged in and authenticated. She then authorized the app to launch but used Bob's launch token in her request instead. @Josh Mandel why do you think this scenario is not possible?
Thank you for sharing that case report BTW -- terrifying stuff. AI summary:
This case involves the death of Paul Lau due to a medication error at Macquarie University Hospital in 2015. The error occurred when an anesthetist, Dr. Kim, mistakenly prescribed high-dose opioids intended for another patient to Paul Lau's electronic medical record. This is a clear example of a context error in healthcare IT systems.
For what it's worth, this is part of the reason that we did not try to tackle communication of context switches to a smart app once it has launched (rather, we provide a mechanism where the app can be closed and relaunched in another context).
Alice has a valid user account in the client application and successfully logged in and authenticated. She then authorized the app to launch but used Bob's launch token in her request instead.
I'm following along so far. In this scenario, Alice has gained access to a launch token that was issued in association with Bob's session. According to the guidance above, this is not going to give her access to anything she would not otherwise be able to access.
We could encourage the EHR to bind the launch token to a user context, and to reject an authorization request if the user does not match the initial context. I'm not sure what this buys us but we could incorporate that into the proposed language with a sentence like
Furthermore, servers should bind launch parameters to a particular user and reject authorization requests where the authenticating user differs from the user bound to the launch parameter.
Thank you, this language would surely help readers to understand the security risk and its potential impact.
Josh Mandel said:
According to the guidance above, this is not going to give her access to anything she would not otherwise be able to access.
To address your concern, once Alice obtains Bob's launch token, she can create a valid account linking request using that token and send it to the server. A valid launch token signals to the authorization server that the user has consented to account linking and is requesting an authorization code. However, the server has no way to verify whether the request is coming from Alice or Bob, as it only receives the launch token without any identifying information. If the launch token is valid, the server issues an authorization code for Bob, which is then sent to Alice. She can use this authorization code to obtain an access token for Bob. She then uses the access token to send a linking request that includes her account information and Bob's access token. The server, recognizing the access token as belonging to Bob, mistakenly links Bob's patient record to Alice's account.
Stealing a launch token from another user can have a cascading effect, potentially leading to unauthorized access to that user's authorization code and access token. I would like to share that we were able to successfully test this scenario in Epic's sandbox environment for EHR launch.
She then uses the access token to send a linking request that includes her account information and Bob's access token.
We do not define an account linking request, and no launch
that Alice presents to the authorization server can cause her to have access to data she would not otherwise have. This is because the launch value is not an authorization grant.
I'm still not convinced that servers need to bind launch values to user sessions. I say this with an understanding of the dangers of session fixation attacks and of the effects that cascading assumptions can have in the overall security of a system.
I don't mind incorporating the guidance above, but I don't think we should imply that a server cannot be secure without this binding -- unless of course someone can explain why this is the case.
In the scenario described above, what do you think Alice would need in addition to Bob's launch token to obtain his authorization code and eventually his access token?
She would need her own account to authenticate to the system, and then she would approve access and then the app would get an access token bound to her account.
She could not receive an access token bound to Bob's account.
(not without being able to authenticate as Bob)
@Josh Mandel are you referring to the step "Authorize app (MAY include end user authentication and end user authorization)" in the flow diagram linked here - http://hl7.org/fhir/smart-app-launch/2021May/#smart-authorization-sequence ? The explanation says "The authorization decision is up to the EHR authorization server, which MAY request authorization from the end-user."
But the above link is from May 2021, the latest doc here (https://build.fhir.org/ig/HL7/smart-app-launch/app-launch.html#response-4) doesn't have this step or any flow diagram but it only says "The authorization decision is up to the EHR authorization server which MAY request authorization from the end-user".
Is there any reason why the step says "MAY" instead of "MUST" ?
I believe the wording should be changed to "The server MUST seek authentication and/or authorization from the end user before issuing the authorization code to the application."
The color on this is that there is always an authentication step but it may be automatic if the user already has a session established -- and ditto for authorization. Both of these steps occur but they may not involve any user interaction. This is a very common case for the ehr launch because ehrs don't want to interrupt their users with a reauthentication step or a reauthorization step every time an app is launched. Policies can drive the authorization (e.g., remembering previous decisions or implementing an organizational choice).
Nevertheless, the launch will fail if Alice is not authenticated properly.
A user may not always have an active session with the EHR, especially when sending request from a mobile app. Therefore, the standard should mandate an authorization step. This step can be implicit if the user already has an active session with the EHR server, or explicit if not. The May 2021 version was clearer, as it included this step in the flow diagram.
If they don't have an active session, then the authentication is explicit
Hi all. I won't be attending since I'm at our conference, Health Innovation Summing this week where there's been a lot of interest in SQL on FHIR!
Here's a draft agenda for you all.
See you next week!
timestamp
, commit version
, etc) and add a link back to the README from the UI to let people know how to add new implementationsDid we intend for the (US) meeting time today to change? I see the invitation 1 hour later than it was last week, which I assume has to do with daylight savings time disparity between US time zones and elsewhere.
where is the invitation?
Some kind of calendar invitation that Nikolai manages.
@Nikolai Ryzhikov
@Grahame Grieve Please check your email
Is the meeting on now, or in 50 minutes?
In 50 min
wait what? that's not what my diary says - I'm with Josh
(now that I have it)
Oh
Do you want to start it now?
In my calendar it is in 50 min
well, I would, because I standing clash in an hours time, but it's not up to me
did you exit daylight savings already?
btw, also note, ends Oct 3
It would be good to schedule the meeting in a US time (as far as I'm concerned). We fall back this Sunday.
I hoped google calendar will handle it. So shall we start it now?
I vote for starting now
Google calendar will " handle it" We need a firm decision about what "it" means. Google calendar by default will keep the event pinned to the time zone that you define when you create it. That currently is Western European standard time.
@Ryan Brush @Dan Gottlieb @John Grimes 🥞 @Grahame Grieve FYI
https://us02web.zoom.us/j/85735001855?pwd=OFNOa1dUcWhSdVdOQ1luNG8xcVdCZz09
Today's meeting agenda:
DevDays session (application due 1/31)
- Commit to Milestone #1 complete?
Focused sessions to schedule
- SQL on FHIR+OMOP
- SQL Generation
- Roadmap Visioning
Add Ad-hoc working sessions?
Guys, I made some breaking changes with the tests folder, as we agreed on the last meeting. Let's discuss it on today's meeting
For now, test jsons are directly in the /tests/
folder (and generated by js - it is probably temporal) I haven't yet migrated everything - but 90% of previous tests.
I made some breaking changes with the tests folder, as we agreed on the last meeting. Let's discuss it on today's meeting
I won't be able to join until ~midway, but it'd be good to highlight if there are any breaking changes to the semantics of tests, vs just changes to the folder structure?
anyone else having problems with the zoom link?
Hi all. I'd like to focus on clarifying this item:
@Ryan Brush Post a Zulip thread on outstanding item on declaring "Intents" in the VD itself. "shareable in profile" how to declare intent and enforce.
Also, pls vote in the scheduling polls:
https://chat.fhir.org/#narrow/stream/179219-analytics-on-FHIR/topic/SoF.2BOMOP.20discussion.20scheduling.20poll
https://chat.fhir.org/#narrow/stream/179219-analytics-on-FHIR/topic/SQL.20on.20FHIR.20on.20SPARK.20scheduling.20poll
Sounds good to me. Also, following up on the discussion last week, I started looking at the json schema guidance and columnar schema guidance pages in the IG. Both have a lot of very prescriptive guidance (e.g., field capitalization, pre-extracting contained resources) which seems unnecessary given how we're now using ViewDefinitions as an abstraction layer. Additionally, most of the columnar page is applicable to non-columnar data stores that support hierarchical structures, and parts of it should probably move into the parquet schema IG we discussed last week.
I'm wondering if it makes sense to extract the general guidance from these pages into a "data layer guidance" page instead, and highlight some of the issues folks may face when building a FHIR data layer (e.g., contained resources, id conflicts, recursion, extensions, choice types, date precision, float precision, terminology, etc) and potential approaches to addressing them. We could also just consider leaving data layer guidance out for now as out of scope for v1 of the IG. It would be good to discuss briefly today if there's time.
Today's proposed meeting agenda:
(I won't be able to join today, but I'd be supportive of filtering by resource type within a view.)
Are we starting now or in an hour?
Link for meeting - https://us02web.zoom.us/j/85735001855?pwd=OFNOa1dUcWhSdVdOQ1luNG8xcVdCZz09
Hello all, for today I'd like to focus on:
@John Grimes 🐙 's list below:
If we get to them:
* How to allow for Extensibility e.g. FP fns outside of the spec, custom functions
* broader discussion VD multiple resource targeting
I just want to make sure I'm in the right zoom waiting roomI
@Nikolai Ryzhikov Will you be joining today?
Will this link work, or do we need to use an alternate one: https://us02web.zoom.us/j/85735001855?pwd=OFNOa1dUcWhSdVdOQ1luNG8xcVdCZz09
I think @Arjun Sanyal is going to create a new link and post here
I joined Arjun's link but am waiting to be admitted
Oh, sorry guys - I'm on DMEA
@Alex Walley Here is a link to the edge version of the FHIRPath spec: https://build.fhir.org/ig/HL7/FHIRPath/
@John Grimes 🐙 Thank you! This makes more sense and these examples are helpful
I see here that it says the literals required from the FHIRPath implementation are String, Integer, and Decimal...does this mean the FHIRPath implementation doesn't have to deal with Date, DateTime, and Time?
This is the Bulk Data Stream
https://chat.fhir.org/#narrow/stream/179250-bulk-data
(Dan posted that he's going to post the new meeting schedule shortly) cc: @Bashir Sadjad
Let's switch from zoom to something where we can have multiple hosts!
I appears as though SMART App Launch 2.2 has R5 dependencies for the FHIR extensions (hl7.fhir.uv.extensions).
These are the current IG dependencies:
"dependencies" : {
"hl7.fhir.r4.core" : "4.0.1",
"hl7.fhir.uv.extensions" : "5.1.0-snapshot1",
"hl7.terminology" : "5.5.0"
},
however, for R4 compatibility, I would expect them to be:
"dependencies" : {
"hl7.fhir.r4.core" : "4.0.1",
"hl7.fhir.uv.extensions.r4" : "5.1.0",
"hl7.terminology.r4" : "5.5.0",
},
Has this previously been raised? I'm happy to raise a Jira ticket if needed.
The IG is designed to work with R4 and later. I don't think there is anything to correct; but the next publication (2.3 or 3.0, there's no definitive plan yet) will incorporate the latest.
If you encounter any compatibility issues please do report
There does seem to be a compatibility issue here as there is a mismatch in the fhirVersion between the SMART App Launch IG and the FHIR Extensions Pack dependency.
image.png
https://hl7.org/fhir/smart-app-launch/STU2.2/#package-dependencies
AU Core as a R4 IG has referenced SMART App Launch 2.2 but this is causing issues as it is introducing R5 dependencies. AU Core also has a dependency on the FHIR Extensions Pack however it is referencing the R4 version ( hl7.fhir.uv.extensions.r4)
image.png
The latest Smart App Launch package, hl7.fhir.uv.smart-app-launch 2.2.0, is also unavailable in the NPM package registry. As a result, AU Core cannot be published due to a missing dependency error. Is there a reason why Smart App Launch 2.2.0 isn't available in the NPM registry?
Processing meta feed entry: HL7 Australia
Processing: http://hl7.org.au/fhir/package-feed.xml
Downloading package: hl7.fhir.au.core version: 0.4.0-preview
Publishing to: https://packages.simplifier.net
Error: Missing dependency: hl7.fhir.uv.smart-app-launch@2.2.0
Feed HL7 Australia processed.
@Grahame Grieve is there a reason https://registry.fhir.org doens't have the SMART 2.2 release?
(Or can you point us in the right direction to inquire?)
start by looking in #tooling/Package Crawlers . Is it in registry2.fhir.org/packages?
The FHIR Extensions package 5.1.0-snapshot1 that SMART App Launch 2.2.0 references is also not in the package registry, and I suspect that missing dependency may be preventing SMART App Launch 2.2.0 from publishing?
Changing the SMART App Launch dependency to hl7.fhir.uv.extensions.r4@5.1.0 would resolve that missing dependency issue and also fix the FHIR version mismatch issue.
AU Core has now resolved its dependency issues with SMART App Launch by downgrading the dependency from SMART App Launch 2.2.0 to 2.1.0
@Grahame Grieve
2.2.0
release.... but https://registry.fhir.org/ does not know about 2.2.0
.
What is the normal process by which an HL7-published package makes it into the registry, and is it possible to re-trigger this or review logs?
I meant packages2.fhir.org. The normal process is that the registries pick it up out of the rss feeds, and it has been published correctly since one of them picks it up. usually if it doesn't appear in registry.fhir.org, it's in the logs which are in #tooling/Package Crawlers
@Ward Weistra can you investigate?
You can find some messages on smart in the feed: https://chat.fhir.org/#narrow/stream/328836-tooling.2FPackage-Crawlers/topic/stream.20events/search/hl7.2Efhir.2Euv.2Esmart-app-launch. But the real message on why 2.2.0
is not being imported is probably hidden behind [message truncated]
.
@Grahame Grieve One way to get that list cleaned up would just to add notForPublication
= true
so they get skipped.
The reason hl7.fhir.uv.smart-app-launch@2.2.0
gets refused at the door is probably because it depends on hl7.fhir.uv.extensions@5.1.0-snapshot1
which is not in the registry :detective:
I assume http://hl7.org/fhir/extensions/5.1.0-snapshot1/package.tgz is being refused because it claims to be a different version in the package.json
: 5.1.0-cibuild
.
Thanks Ward for the analysis!
@Grahame Grieve what's the right way to address the Extensions publication? Does it require a fix to the 5.1.0 package.json?
@Ward Weistra
One way to get that list cleaned up would just to add
notForPublication
=true
so they get skipped.
but that's in the npm itself. Not so easy for me. Should we add that to the rss feed as well?
ok, well, I'll work on that.
in the meantime, I think I fixed this up? give it a few hours and we'll see
I inadvertently assumed you would put the notForPublication
flag in the feed, and not in the package, since it's a very relative concept.
So I already implemented that. But shouldn't we just put packages that are not for publication in a different feed -- a not-for-publication-feed?
I don't put packages that are not intended for publication in any feed, and it's presently an error if they are rom my pov
@Ward Weistra proposed to use it to suppress errors from the #tooling/Package Crawlers topic. but the thing is, different crawlers get different errors, so I think that on reflection, it's not something to solve in the feed
@Ward Weistra what if you process the feed backwards instead of forwards - we'll get the most recent errors...
I think we deliberately process the packages in the version order at least, to have them published in the right order. If we can't solve this on a feed-level, we've been thinking to resort to a kinda package 'black list' on our side then, where we just configure: "If package + version combination is in this list, just ignore it and don't try to process".
So has SMART App Launch:
image.png
By the way, there's still also quite some real issues to fix in that feed:
List of issues
I fixed my issues. :tada:
@Ward Weistra
Error: Name should contain at least 1 dot. Each segment 2+ characters
I don't think that this is something that we agreed on.
@Grahame Grieve , I think the package specification states:
"Each package SHALL have globally unique identifier for the package in the NPM System. A package name consists of two or more namespaces separated by a dot. Each namespace starts with a lowercase alphabet character followed by zero-or-more lowercase alphanumeric characters or dashes."
Each segment 2+ characters
this bit.
but ok, hl7.fhir.us.core.3.1.1 is not legal, but we used it anyway.
We'll fixed to allow namespaces with single lowercase alphabet character
Error: Should contain at least 1 dot. Each segment should start with a lowercase alphabet character.
but why?
As a note, there is nothing published with this package yet (first things are in ballot now), so if we wanted to change the 'magic' URL (or remove it in favor of aliasing), we can probably get away with that within the next few months.
Grahame Grieve said:
but why?
As you pointed out, the specification states it should be "Each namespace starts with a lowercase alphabet character followed by zero-or-more lowercase alphanumeric characters or dashes"
So we are following the package specification now. We were enforcing that each segment should be at least 2 lower case alphabet characters before.
which specification?
doesn't look like that's inherent in the npm spec
Grahame Grieve said:
which specification?
The FHIR Packages spec, see the definition for "name" in https://build.fhir.org/packages.html#2.1.10.2
so I failed to read that and we went ahead and published the offending package, and so it would be really good if you could load it anyway, even though it doesn't meet the rules
I'm also sorry I missed that when we discussed this name. But I wouldn't just change the package spec because of our omission. The error message has been reported ever since it was published too.
Let's file a FHIR-I ticket if we really want to change that, but preferably just update the package name and dependent packages.
@Ward Weistra I can't "just update the package name" because the packages that depend on it are already published
I see hl7.fhir.us.core.v311
is published now? https://simplifier.net/packages/hl7.fhir.us.core.v311
(deleted)
In reviewing the Sept 2024 ballot I have found value sets and code systems in IGs intended for implementation with the "Experimental" flag set to true. Granted they are early in development, but looking at the content represented in the value set it is clear that the codes can be used and are expected to be used. A Code system example of this is Healthcare Capacity Reporting Code System. A particularly egregious occurrence of this can be seen in the Information Recipient Extension that binds the Clinical Document Participant Types Value set value set REQUIRED but the value set is marked Experimental.
In both the code system example and the value set example the use of the Experimental flag only confuses implementers. I suspect the "information" intended to be conveyed is already communicated by the maturity of the resource and the fact that this is an early IG.
I'd like others to comment if they agree with me on this and would like to push IG authors to stop using Experimental when the content is actually just an early initial attempt at real stuff. @Grahame Grieve @Lloyd McKenzie could we put in publisher warnings on experimental code systems and value sets? Particularly when publishing. Particularly when bound REQUIRED?
I noticed this on some other resources. I think authors are incorrectly using experimental=true to mean really, really draft (or even the same as draft), rather than the defined meaning of "for test purposes."
ShareableValueSet and ShareableCodeSystem profiles had it mandatory, so several authoring tools have insisted having it filled in with something. A draft value set is not automatically experimental, but authors mark it as such "just in case". And then it gets forgotten.
I think nothing should get into THO with "experimental=true". The only things in other IGs where it would be true is if it's an example and not intended for real use.
So, add warning for experimental resources and a FMG/TSMG waiver needed?
I would say that THO should error on experimental. Other IGs should error on experimental that isn't marked as an example, and warn on examples that aren't marked as experimental.
hmm. I thought I already had a warning when something not experimental refers to an experimental value set
. would like to push IG authors to stop using Experimental when the content is actually just an early initial attempt at real stuff.
I think there's cases where content or even the value set it self is experimental, even while it's clearly in the space of something that is intended to be implemented, so I suspect that we shouldn't have hard policies about that
and I don't think that they should be errors, or if so, not until later in the process, and we aren't executing on IG maturity yet
If it is an error, I would request that be done in the HL7 template, rather than IGPublisher or the base template. I can imagine people wanting to publish experimental resources even if we don't agree with that decision.
I can do errors that are driven by HL7 policy in the validator, there's already a few like that, where the rules don't apply to content published by other organizations
Oh, I thought those were driven by the template. That works for me too.
so it turns out that the validator has not been checking the experimental flag on bindings, so from the next version:
Grahame Grieve said:
Is that warning for any binding to an Experimental flagged value set that is not experimental? If so that is fine but far from meeting my concerns. We should be warning on all experimental value sets and code systems in ballots and published IGs. And an error when a required binding to an experimental value set.
a warning when binding to an experimental value set from a profile that's not experimental
I don't believe that it should be an error - it's not always wrong
Grahame Grieve said:
I don't believe that it should be an error - it's not always wrong
It would be wrong when the binding is required.
really? always wrong? why does binding strength make a difference to whether it's experimental?
Perhaps in part we are quibbling over where to communicate "experimental", a required binding to something that is never to used in a real system seems like technical testing, not standards IG. I just think that type of combination is a nonsense thing for an HL7 IG. By that I mean more than something purely for technical work. I'd like to hear from others on this.
It's totally fine for an experimental profile to have a required binding to an experimental value set (and code system). I.e. you just have something made up as an example for all three.
'experimental' should jive with 'example'.
There’s two levels here. First, should there be non-example experimental resources. Second, should a non-experimental resource be able to reference an experimental resource (value set, profile, extension,…).
I think the validator discussion above is only addressing (part of) the second. Is there a validation warning (HL7 error?) of the first?
I don't think non-example experimental makes sense. You could have 'draft' non-examples if you want to say "this is intended for real use, but isn't ready yet". But if it's not an example and it's not draft, I don't think it has any business being experimental.
I suppose you could have an example binding to an experimental value set. I.e. "Here's a set of codes to give you an idea of what kinds of concepts you could represent, but you shouldn't actually use these codes". That's the only use-case I can think of.
I am still not clear on the difference between experimental
, draft
, and FMM. For example, I might argue that everything that is not a release publication should be marked experimental
because they are not intended for production use.
Do we just have too many ways of saying the same thing?
Experimental = not for real use (now or ever)
Draft - in development, not yet ready for use
FMM 0 - should be same as status = draft
FMM 1+ (status should be active or retired) and indicates the degree of adoption and stability of this thing that is ready for use
status of retired = this thing should no longer be used
Something that's experimental shouldn't have an FMM
Well, I can see why everyone is confused at least. Having a structure with a flag experimental
and the short of For testing purposes, not real usage
, gave me the expectation that it aligned with my use of the term experimental: that something is not ready for production yet.
I am not sure reading the longer descriptions that there is anything to actually indicate that meaning. I definitely cannot see anything that indicates we can never change the value (e.g., in a future version).
experimental vs draft really does need to be made more clear.
I definitely cannot see anything that indicates we can never change the value
We have never said that
Lloyd McKenzie said:
Experimental = not for real use (now or ever)
I assume I am misreading that then - what is the intention?
Gino Canessa said:
Well, I can see why everyone is confused at least. Having a structure with a flag
experimental
and the short ofFor testing purposes, not real usage
, gave me the expectation that it aligned with my use of the term experimental: that something is not ready for production yet.
I think the idea behind experimental is that you want to be able to send it to a system for test purposes and be able to quarantine it.
However, why canonical resources are special in this regards, compared to regular resources which don't have the experimental flag, I'm not sure.
I assume I am misreading that then - what is the intention?
the intention of the author is that it won't change. Unless the author changes their mind. We would expect that to be unlikely, but not wrong
Elliot Silver said:
I think the idea behind experimental is that you want to be able to send it to a system for test purposes and be able to quarantine it.
I was under the impression the best practice for that was using the Core Security Label of HTEST
.
Grahame Grieve said:
I assume I am misreading that then - what is the intention?
the intention of the author is that it won't change. Unless the author changes their mind. We would expect that to be unlikely, but not wrong
Fair enough - it sounds like the intention for experimental
is a classification-type element (like abstract
or kind
) and not a status element (like status
), and thus explicitly not a lifecycle state that will end in a production structure?
I think we definitely need a ticket to clarify - has someone filed one already?
thus explicitly not a lifecycle state that will end in a production structure
yes, that's the intent
and I agree with @Robert McClure that it's not being used correctly in these cases. I have added two things:
If I say "this is experimental" then you should assume "there's no intention I'll ever use this in production", not "it's not yet ready for production". If I change my mind and decide "you know what, I think this actually should be used in production", then I could drop the experimental flag. That's very different from draft non-experimental which is saying "I intend this to be used in production, but it's not ready yet".
Lloyd my confusion is that 'experimental', in my experience in software, is a status. It is equivalent to saying something is alpha/beta/etc.. E.g., something that is not ready for production yet (not that any such labelling actually prevents it from being production - to the consternation of software developers everywhere :-)
I even have a branch in a repo named experimental
that I am merging into the main
branch this week. It was experimental while we figured out if it could work, and since it does it is no longer experimental =). The intention was to see if something would work - but the intention was always to promote it if it did.
My understanding through this thread is that StructureDefinition.experimental
is classifying a structure as a type of definition that is never expected to move into production. That is new to me, and given that this thread is about overuse, I assume will be new to many others.
*edit: to clarify - I am familiar with 'experimental' things that are just Proof of Concepts or other such terms. This is just not language I associate that way (and assume others have not either).
I agree that the element name isn't the best for what it represents, but we're past the point where we can change it.
Agreed - we should update the descriptions to clarify and was wondering if anyone in the thread has filed a ticket already (was discussed) or if I should.
Not I :smile:
Lloyd McKenzie said:
I don't think non-example experimental makes sense. You could have 'draft' non-examples if you want to say "this is intended for real use, but isn't ready yet". But if it's not an example and it's not draft, I don't think it has any business being experimental.
I suppose you could have an example binding to an experimental value set. I.e. "Here's a set of codes to give you an idea of what kinds of concepts you could represent, but you shouldn't actually use these codes". That's the only use-case I can think of.
Can I ask that we don't have a Warning when we have example binding strength with an experimental valueset? We created some ValueSets as experimental and used example binding for two three reasons:
a) give the community an idea of what we are looking for
b) get feedback
c) there is not a definitive list of codes that we can find or agree on just yet
By using example, I feel we are saying 'we really don't know if this is right yet, but maybe these work, give us some feedback please'? So flagging that as a Warning seems wrong.
Reminder: on Dec 22, 2017 the FHIR R4 ballot cycle commences with a draft for comment ballot. Please note the following:
We therefore looking for good review on this draft for comment ballot on the following things:
- what content has been selected for normative
- how the normative status is presented (clearly, hopefully)
- the technical content of the normative material
- any suggestions for content that needs further implementation experience in the next few months
We need you @all to comment on this stuff. And if you want to do that, you have to sign up for the HL7 ballot at http://www.hl7.org/participate/onlineballoting.cfm?ref=common by Dec 21st - that's a week away. Please do that and comment on the normative preparations.
If you want to comment now, the normative preparations are mostly done, and visible at build.fhir.org. Any comments received before the ballot are most appreciated. Note that there following things have been added:
- every page has a status bar now
- normative markers for normative content and resources (see http://build.fhir.org/documentation.html, http://build.fhir.org/resourcelist.html, http://build.fhir.org/terminologies-systems.html, and http://build.fhir.org/terminologies-valuesets.html_
- status markers on elements and operations (see http://build.fhir.org/bundle-definitions.html#Bundle.signature and http://build.fhir.org/codesystem-operations.html#compose)
- a dependency analysis for resources (see e.g . http://build.fhir.org/patient-dependencies.html)
- a description of the ballot: http://build.fhir.org/ballot-intro.html
Two questions:
http://build.fhir.org/terminologies-systems.html
, is that correct?Bundle.signature
allow marking parts of normative conent as "trial use", is that the intent? So there will be a "super normative" when all parts of a normative resource are normative? Or will there always be non-normative parts in normative resources?Please discuss on implementers or social
Further Ballot related announcement:
Note: although this is the offiical basis for the New Orleans we know that some tracks and some attendees will be using past versions of FHIR
Last announcement: https://onfhir.hl7.org/2017/12/21/fhir-r4-ballot-community-consultation/ - note: this has some community consultation items in there
The end of ballot sign up is approaching - you have 4 days (until end of Sep 23rd US eastern) to sign up to vote on the following ballots:
Core: (posted at http://hl7.org/fhir/2018Sep/ballot-intro.html)
R4 General (Trial Use)
R4 Infrastructure Normative
R4: Observation Normative
R4: Patient Normative
R4: Terminology and Conformance Normative
International IGs:
- International Patient Summary
- LOINC – IVD Test Code (LIVD) Mapping
- Point-of-Care Device (PoCD)
- Potential Drug-Drug Interaction (PDDI) Clinical Decision Support (CDS)
- Validated Healthcare Directory
- Structured Data Capture (SDC) (delayed)
US Realm IGs
- Electronic Case Reporting (eCR)
- Coverage Requirements Discovery
- Data Exchange for Quality Measures
- Bidirectional Services eReferrals (BSeR)
- Occupational Data for Health (ODH)
- Breast Cancer Data (delayed)
- Patient Reported Outcomes (PRO) (delayed)
- Women’s Health Technology Coordinated Registry Network (CRN) (delayed)
Notes:
Note that the core ballots are all cycle #2 ballots. What this means is that the scope is limited to the changes made from the 2018-May ballot cycle. Feedback not related to changes made will most likely be found "not related" and/or deferred to consideration as part of R5
I don't believe that this limitation applies for any of the IGs
Note that we had previously announced that the normative ballot cycle #2 ballots would be closed pool, limited to the people who signed up for ballot #1. It turns out that this is not the case, so if you were signed up for ballot #1, and you want to vote again you need to sign up for ballot #2 again. And if you didn't sign up to ballot #1, you can sign up anyway
This ballot, if any substantive changes are made to the normative packages, then they will fail normative and fall back to trial-use status. Also, if this ballot fails - that is, the ballot pool votes negatively on the changes since ballot #1, then they will fall back to trial-use. Please join and vote in favor of closing out R4
I wrote "Sep 23" above, but it was meant to be Aug 23. Sorry if that caused any confusion
further information about the ballot: all the ballot content that is opening on time is now ready.
FHIR core ballots: http://hl7.org/fhir/2018Sep
FHIR Igs (International)
FHIR Igs (US Realm)
In addition, I have posted the final version of STU 3 for QI Core here: http://hl7.org/fhir/us/qicore/2018Sep
http://hl7.org/fhir/us/qicore/2018Sep returns a 404
that's because I meant to write http://hl7.org/fhir/us/qicore/STU3
Excuse my ignorance - does this mean the occupationalData will only available as a resource to use in the US? The elements within it look laregly transferable (am UK based).
That's it's balloted as US realm means that it has terminology bindings or other considerations that are applicable only in the US. The resources on which it is based are part of the FHIR spec, so can be used universally, but to use it in the UK there would likely need to be UK-specific bindings and/or considerations. Does that help?
Discussion should happen on the #implementers thread, not here.
After create a tracker for ballot comment, do I need to choose an item from Ballot dropdown? I don't see 2018-Sep in the list.
No. No user should ever touch the ballot dropdown. It'll be populated by the automatic load process from your submitted ballot spreadsheet that references the gForge tracker item.
Reminder to everyone that the Normative and STU ballots on the core specification as well as a number of the implementation guides are due at end of day (midnight Eastern) on Monday Sept. 24. There's another subset that close on the Sunday right before the WGM. Happy balloting this weekend... :)
At present, some of the FHIR Normative ballots have less than a 30% response rate. If, by midnight Eastern tonight we don't have at least a 50% response, the ballots will fail. We do have the ability to do a one-time extension to allow additional submissions to come in, but doing so will make it difficult to triage the comments for consideration in Baltimore which in turn puts other aspects of the publication timeline at risk. (And if we don't make 50% by the end of any extension period, we fail with no further recourse.)
TL/DR: Get your ballot responses in ASAP!
Thanks for everyone getting their ballots in. It turns out that the scare was due to an error in the ballot website's summary screen. While the summary screen shows that we're short of 40% participation, the detail screens show that we're actually approaching 80% participation. So there will not be an extension. There's just over 4 hours to get in your ballot comments if you want them to be considered as part of the ballot response.
Looks as if that summary page is still counting all the duplicate entries that have produced multiple emails to participants over the past few weeks.
HL7 Announcement of Formation of Regular Cycle Consensus Groups for 2022May - sign up for ballot pools at www.hl7.org/permalink/?BallotDesktop or review the list of items open for enrollment at https://confluence.hl7.org/x/6rdiBQ.
Ballot consensus pool enrollment for regular cycle May ballots closes next Thursday, March 31 - sign up now!
HL7 Announcement of Formation of Regular Cycle Consensus Groups for 2022May - sign up for ballot pools at www.hl7.org/permalink/?BallotDesktop or review the list of items open for enrollment at https://confluence.hl7.org/x/6rdiBQ.
Ballot voting for early May 2022 cycle ends Wednesday March 23 - don't forget to vote!
HL7 Announcement of Formation of Regular Cycle Consensus Groups for 2022 September cycle - sign up for ballot pools at www.hl7.org/permalink/?BallotDesktop or review the list of items open for enrollment at https://confluence.hl7.org/x/rK-PBw.
Seeking Interested Participants to Help Us Fulfill Balance of Interest for Normative Ballots for Regular Cycle Consensus Groups for 2022Sep: http://www.hl7.org/documentcenter/public/ballots/2022SEP/Announcements/2022SEP_Balance_of_Interest.pdf
HL7 Announcement of Regular Cycle Ballot Openings for 2022 September Ballot Cycle: http://www.hl7.org/documentcenter/public/ballots/2022SEP/Announcements/HL7_Announcement_of_Ballot_Openings_for_2022SEP_Ballot_Cycle.pdf
HL7 Announcement of Formation of Late Cycle Consensus Groups for 2022Sep Cycle (HL7 FHIR® Release 5, HL7 Standard: Version 2.9.1, HL7 Cross Paradigm Implementation Guide: Sex and Gender Representation, Release 1): http://www.hl7.org/documentcenter/public/ballots/2022SEP/Announcements/2022SEP_Announcement_of_Formation_of_Late_Cycle_Consensus_Groups.pdf
2023Jan NIBs without using the NIB site on the HL7.org web page.
Many have asked when the NIB site would open, as during the extended period for the 2022 September ballot cycle where voting ends on Friday October 14, I had indicated that I would open the NIB form for 2023 January on Saturday October 15th.
- HOWEVER -
We’re finding that access to that NIB form during the HL7 AMS migration (requiring log in to the HL7.org website) is going to be problematic.
Therefore, I’ve created a simple empty form at https://confluence.hl7.org/display/HL7/2023JAN+NIB+form+template that can be used to submit the NIB information.
Please make a copy of the page to your work group’s Confluence space, fill it in, and send me the page link once completed. I can create the NIB records on the back end without interfering with the AMS migration.
This still only allows a short time for NIB submissions prior to the deadline of October 30 so please get your information to me as soon as you can.
Final content deadline this Sunday December 4th for HL7 2023 Jan ballot
HL7 Announcement of Ballot Openings for 2023 January Ballot Cycle: http://www.hl7.org/documentcenter/public/ballots/2023JAN/Announcements/HL7_Announcement_of_Ballot_Openings_for_2023Jan_Ballot_Cycle.pdf
HL7 Announcement of Formation of Consensus Groups for 2023 May cycle: https://confluence.hl7.org/x/kKhUCQ
Reminder: next Thursday is the last day to sign up for a consensus group (join a ballot pool) for the 2023 September cycle. THIS Sunday is the final content deadline for developers.
HL7 Announcement of Ballot Openings for 2023 September Ballot Cycle: http://www.hl7.org/documentcenter/public/ballots/2023SEP/Announcements/HL7_Announcement_of_Ballot_Openings_for_2023SEP_Ballot_Cycle.pdf
HL7 Announcement of Formation of Early Consensus Group for 2024 January Ballot Cycle: https://confluence.hl7.org/x/XM0FCw
HL7 Announcement of Formation of Regular Cycle Consensus Groups for 2024 January: https://confluence.hl7.org/x/zwgtD
2024May Announcement of Formation of HL7 Consensus Groups: consensus group enrollment now available! See https://confluence.hl7.org/display/HL7/2024May+Announcement+of+Formation+of+HL7+Consensus+Groups or https://www.hl7.org/documentcenter/public/ballots/2024MAY/Announcements/2024MAY_Announcement_of_Formation_of_Consensus_Groups.pdf
2024Sep Announcement of Formation of HL7 Consensus Groups: consensus group enrollment now available! See the ballot desktop at https://www.hl7.org/documentcenter/public/ballots/2024SEP/Announcements/2024SEP_Announcement_of_Formation_of_Consensus_Groups.pdf
Or the Confluence page listing at https://confluence.hl7.org/display/HL7/2024Sep+Announcement+of+Formation+of+HL7+Consensus+Groups (allows sorting).
2024 Sep Ballot Results are available at https://www.hl7.org/documentcenter/public/wg/tsc/HL7_Sep_2024_Ballot_Results.zip
Wondering how to interpret Substance.instance
-- which is defined as "Is this an instance of a substance or a kind of one". I thought documenting a kind of a FHIR instance is what profiles are for?
hi Brian,
When the value is "instance" it means that this resource data (which could also be called a resource instance, but that is an unhelpful coincidence) represents an actual substance entity, that exists in the real world and could be touched (probably) e.g. an actual lump of sugar.
Alternatively it is a type (kind) of substance e.g. the concept of sugar.
Of which you could then have instances.
So kind means this resource (instance) is the wikipedia page about sugar. Sugar info.
Instance means this resource (instance) is about some sugar. Actual sugar.
Profiles are nice computable way to say how you want your "instances" of any resource to look. I suppose there are instances of resources (data), and kinds of resources (as in the FHIR spec), and then there are instances of substances (lumps etc.) and kinds of substances (types, definitions).
But wouldn't the concept of sugar be represented as a profile (which is an instance of a structure definition :)) where the code is set to mean sugar? Also noteworthy that as far as I am aware, this flag does not appear on other resource types (including Medication).
I bring this up because I am just noticing this was changed in R5.
We use profiles to describe how we want our instances to look (e.g. the concept of blood pressure is a profile, and the actual reading is an instance of Observation that conforms to that profile), and we also use R4 Substance + profiles. This new pattern of a boolean to modify the nature of the resource seems different than how it is handled in the rest of FHIR.
Only if you want to specify how a single resource should be in a profile. Sugar is one of a million substances. You don't want a profile for all of them, any more than you would have a profile of for patient John Smith. If there were 100 variations of Sugar, then you may want a "sugar substances profile", so that all varieties of sugar are done similarly, eg using the "international classification of sugar codes". But otherwise it doesn't make sense to have a profile for one single resource instance
You could have a profile of BP, it is true, because that is very common, and there are only 20 or so vital signs and we want all the millions of instances to all look the same. But equally, we don't have a profile for every clinical condition in the world (all the hundreds of thousands of SCT codes).
If you have lots of people making sugar instances and there is something special about them that differs from how salt is represented, then sure, make a profile. Bit this is a totally different issue to Substance.instance. They are not the same concept at all.
Profiles add documentation, essentially. Substance.instance is a property of the data, that tells people what sort of thing it refers to (like Patient.gender). It is nothing to do with profiles.
Okay. I am still not seeing how they are different. Or why this pattern then would not apply to Medication. Also, in CPG we use Structure Definitions as first class resources, not just documentation (Case Feature Definitions).
I think the same thing was considered for Medication, but it just didnt make it to be an actual property.
To be consistent, Medication could have one. We were doing some revision on Substance, and at that time the instance vs kind was being discussed and it seemed good to make it explicit. That didn't happen with Medication, but it could have.
Then also for Specimen, Body Structure, Claim, etc. they would all need this boolean right?
These 2 resources are the only ones that I can think of that can be both instances or kinds.
No because there is e.g. SpecimenDefinition
For some resources they can only be instances, and a different resource does the work of the definition. Substance (and Medication) are unusual in that respect.
Medication is somewhat different to Substance too. Medication can be stated at various levels of completeness. But I think using it as a true "definition" is less common, and not really needed. Because drugs tend to be defined by code systems (RxNorm etc), not resources.
And there is no perceived need for BodyStructure definition. there is only one body, I guess, and the medical knowledge about say, livers, is not typically captured in FHIR. That would be in the literature.
Substances are more of a changeable thing, and have electronic catalogues, with supporting data about each substance. You don't tend to get electronic catalogues of body part, except in terminology.
You could have Claim definitions I suppose. But who is making processable electronic definitions of claim types?
The point I was making is structure definitions allow us to define the definitions of types of resources already. I am still not seeing the need for that boolean, but will think about it more.
This is not meta data about a resource - which is what SD is for. This is perhaps meta data about a resource instance.
There is a clear distinction in the use. It is not possible to do the job of Substance.instance with a profile.
All an SD can do is say how to use the resource. This would be like trying to use a profile to say if an individual patient was male. Can't be done. Saying how male patients are represented can be done. Saying if a patient is male cannot be done.
Defining the concept of sugar can be done in a structure definition. Definition a real pile of sugar can be done with an instance of Substance that conforms to that profile?
Again, that's the approach we use in CPG (case feature definitions are structure definitions)
But you cannot change from a kind to an instance using a profile. Any more than a profile can flip male to female.
You could define a new whole resource using an SD e.g. SubstanceInstance, but that is not FHIR. Basically put the instance flag into the name of the resource.
A resource type can have resource instances. Maybe that is what you are thinking. But this is not that concept.
The phrase "definition of a real pile" is a little strange though. It would be an instance of a real pile. We don't tend to say "a definition of a patient John Smith".
By analogy with Patient, if there was a Patient.instance flag, set to type "kind" it might be used to define, say what "US citizens" were like. You could then make a FHIR data set of different nationalities, as actual FHIR resources, saying what the postal address would be (an address in the US probably).
It is true that you could do the same thing with FHIR profiles (and we do e.g. US Core).
But FHIR profiles are not user editable data. Substance catalogues are sets of user editable data about kinds of substances. New ones come along all the time. Users can add new substances to the catalogue.
But users cannot add a new type of patient. They cannot add "Tuvalu citizen". That can only be done as a profile, by standards makers, not by users.
Maybe that is where the similarity and confusion is.
Admittedly you could in theory use StructureDefinitions as end-user editable definitions and let users create new nationality profiles as FHIR instances. Then drive validation off those. FHIR does eat its own dogfood, so resource profiles are already resources.
But because national profiles are relative static, and more sophisticated, we (certain people) do this "offline" using profile tools and repositories.
Substance catalogues are not static though, and are meant to be end user edited. So they are good for being represented in (end-)user data, not profiles.
So FHIR does definitions in two ways I suppose, as resources (usually with a whole separate resource e.g. SpecimenDefinition, PlanDefinition etc, but not always - regrettably I would say), and as StructureDefinitions/profiles.
It was originally, methodologically, thought that having two resource "flavours" was overkill, I think. Later the paradigm of having both {Resource} and {Resource}Definition seemed to take hold e.g. ObservationDefinition is a relative newcomer. And exists even though we have plenty of BP profiles...
I agree there is tension/overlap/confusion between the patterns of (resourceType)Definition and Structure Definition. And as you said these definition resource types are a relative newcomer. But now this boolean for instance seem an even newer newcomer and now a third pattern to consider.
You could have a catalog of StructureDefinitions about Observations -- or a catalog of ObservationDefintions (same with SubstanceDefinitions or SDs about Substance). You could also have tools to make managing a catalog of SDs accessible, since structure definitions are data, and there is nothing in FHIR spec that restricts what kind of end-user can create structure definitions.
I did not have an assumption that certain resource types are off limits for users in the FHIR specification. In clinical reasoning, we create structure definitions as part of routine authoring, with tooling support, even though many of the teams we work with are not federal agencies. I am not sure the level of sophistication we have, but they are kinda sophisticated :)
It's not really all that new. This flag has around since the early days of R5. Almost 5 years. But the resource has had this feature since DSTU2 (and had an optional backbone about it). It could always be a kind or an instance. It just was not so explicit til R5.
Sure, some end users can create profiles. Nothing is off limits, no hard edges. Some create complex quality measures and plan definitions. But a list of substances with a few properties is sort of in a different category I suppose. They are not deeply FHIR oriented, unlike say a profile (though complexity can indeed be hidden).
Profiles are "FHIR like", they are about data constraints. Substance types are very much in user space (chemists).
I think one thing that is missing from this discussion is that whether an instance claims conformance to a profile or whether it is conformant to a profile, doesn't change the meaning of the resource. A Patient resource that meets the Tuvalu patient profile doesn't need to shout can do so without adding the claim that it meets that profile. And if it does claim that profile, it can't change the meaning of the resource.
The other thing is that profiles (realized in StructureDefinitions) can't be used most places that a Substance can be used. I can't just plop the sugar profile in somewhere that I want to say "use Dememera." Those places are looking for a Substance.
I think it is valid to say that if a Patient is conformant to US Core, it means it is a US Core Patient. And if an Observation conforms to blood pressure profile, that Observation means a blood pressure. In this sense, the structure definition uses conformance rules to express meaning, and the Patient or Observation are the instances of it.
I think you can make reference to a sugar profile by either an invariant rule or using the artifact-reference extension (as seen in CRMI, and the FHIR extension pack).
E.g. those places can be expressed as referring to a substance that means Sugar
But in R6 with SubstanceDefinition I am guessing the Substance.instance bool will go away? In this case the substance of sugar will be via SubstanceDefinition, and the case of a pile of sugar it will be Substance with instantiates[x] to that definition?
That is a possible way to do this. But SubstanceDefinition was not intended to totally replace Substance[instance=kind]. Personally I would quite like that, but the thinking was that for simpler and legacy systems that are using Substance for that already, they can keep doing that. SubstanceDefinition is for serious catalogues that need a lot of info. Substance is still there for simpler cases. I actually doubt that anyone is using Substance for that, but you never know. We already had a presumed legacy when the bigger requirements that led to SubstanceDefinition came along. We didn't want to fill up Substance with all the stuff in SubstanceDefinition, but some use cases do need it. So we have two worlds. I would consider deprecating Substance.instance, and making it always an instance. But it may break someone somewhere and stop them going to R6, without API level changes.
Brian Kaney said:
I think it is valid to say that if a Patient is conformant to US Core, it means it is a US Core Patient.
I like to think of a profile as one of those children's block toys, where you have various shaped blocks and various shaped holes to push them through. If an instance conforms to a profile, it meets all the constraints of the profile. If a block can go through the hole, it meets the constraints of the hole. Just because I can slide the cylinder though the square hole doesn't mean you can start calling it a cube.
Rik Smithies said:
Personally I would quite like that, but the thinking was that for simpler and legacy systems that are using Substance for that already, they can keep doing that.
Substance.instance data type changed drastically from R4 -> R5. Since practically speaking many are skipping 5 and will be going right to 6, it could be a good idea to remove that boolean in R6..
Elliot Silver said:
Just because I can slide the cylinder though the square hole doesn't mean you can start calling it a cube.
Sure you can ;) given the context of use - but if you care about the shape than your conformance would need to define it -- "a small cylinder means it fits in a hole" vs "a small cylinder means it fits in a hole, and that hole is round, and the edges of the cylinder are all equidistant from the hole edge".
re removing the flag, that would break any R4 data that used this resource for kinds of Substance. So while it may be good for some, it could be very bad for others. What's the big problem with the flag anyway?
In R4 https://hl7.org/fhir/r4/substance.html Substance.instance
is a complex type:
Yes indeed. It's definitely a change. Is it hard to support do you think? Is it the fact that it's changed from a backbone to a plain attribute? Or is it that the concept of instance is not right for you.
Hi, We are in the process of integrating Tasks into our EHR system and have some inquiries related to our requirements:
The Provider initiates an order from the portal, which then undergoes physician approval. Following approval, it proceeds to the fulfillment agent for order fulfillment. Once fulfilled, it moves to the Lab side for report generation. After the report is generated and sent to a physician for approval. Once approved, the order status transitions to completed, and the report is sent to the Patient.
Could you kindly recommend a workflow to manage this scenario using the Task system?
Additionally, we have a few specific questions:
How can we connect Tasks and PlanDefinition?
If multiple Tasks are associated with a PlanDefinition, how can we execute them sequentially?
The approach to handling tasks for a PlanDefinition depends on the organization linked to the ServiceRequest. For instance, if Organization A has ORDER1, it may not necessitate physician approval. However, in the case of Organization B, physician approval might be required. How should we manage this situation effectively?
We have various statuses for ServiceRequest, such as "Waiting for approval" and "Shipment received at the lab." How can we effectively manage and display these statuses to patients on a patient portal?
Your guidance on these matters would be greatly appreciated.
"The Provider initiates an order from the portal, which then undergoes physician approval." - are the provider and physician different? If so, who is the provider?
In any case, this bit would typically just be having a draft Request resource which eventually becomes 'active' when the physician signs it.
There would be a Task requested by the physician system with a performer of the lab. The lab would either accept or reject. Once accepted, the lab could choose to surface sub-tasks that deal with the different steps (specimen collection, test run, analysis, report generation), but often there wouldn't be a benefit to surfacing this in FHIR. Once the report is signed off it would be attached as a Task.output to the original Task and the Task marked as 'completed'. (In theory, a preliminary unsigned version of the report and/or some of the preliminary Observations could have been attached to the Task earlier if there's a need for the ordering clinician to see preliminary results.)
Once the EHR receives the completed report, the system could throw a Task in the physicians task list asking them to review the report. Once reviewed, the ServiceRequest would either be marked as 'complete' (if the physician is satisfied) or a new Task generated pointing back to the original ServiceRequest and indicating what additional needs to be done.
The ServiceRequest would never reflect the status of "work in progress". The ServiceRequest is either draft, active, or completed. All downstream information about what's happening at the lab is reflected on the Task, not the ServiceRequest. (The lab has no authority to change the ServiceRequest instance at all.)
Lloyd McKenzie said:
"The Provider initiates an order from the portal, which then undergoes physician approval." - are the provider and physician different? If so, who is the provider?
In any case, this bit would typically just be having a draft Request resource which eventually becomes 'active' when the physician signs it.
There would be a Task requested by the physician system with a performer of the lab. The lab would either accept or reject. Once accepted, the lab could choose to surface sub-tasks that deal with the different steps (specimen collection, test run, analysis, report generation), but often there wouldn't be a benefit to surfacing this in FHIR. Once the report is signed off it would be attached as a Task.output to the original Task and the Task marked as 'completed'. (In theory, a preliminary unsigned version of the report and/or some of the preliminary Observations could have been attached to the Task earlier if there's a need for the ordering clinician to see preliminary results.)Once the EHR receives the completed report, the system could throw a Task in the physicians task list asking them to review the report. Once reviewed, the ServiceRequest would either be marked as 'complete' (if the physician is satisfied) or a new Task generated pointing back to the original ServiceRequest and indicating what additional needs to be done.
The ServiceRequest would never reflect the status of "work in progress". The ServiceRequest is either draft, active, or completed. All downstream information about what's happening at the lab is reflected on the Task, not the ServiceRequest. (The lab has no authority to change the ServiceRequest instance at all.)
The provider is also Practitioner but at admin level, who can also create ServiceRequest
I'm not understanding that answer. Are the provider and physician the same individual or different? (Practitioner or PractitionerRole would be used for any of the participants in this case.)
Yes, they are same but they have different roles asssined in PractitionerRole.
We have three portals Patient portal where patients can login and view their order and reports, The Provider portal where physician, fulfillment agent and provider admin can login and perform different roles and the Lab portal where lab technician generates reports
So you have the same person who must sign into the system with two different roles to activate an order?
No, different person with different roles
Ok. So once the draft order is created, you could have a Task created that seeks sign-off from the individual with authority. Or you could just tag the order (meta.tag) to indicate that it's ready for signing.
It would be a separate Task from the one that seeks fulfillment though.
Essentially, we are a laboratory with three distinct portals. Let me provide a detailed explanation.
There are two primary scenarios for order creation:
Scenario 1: Patient-Initiated Order
Scenario 2: Provider-Initiated Order
These two scenarios illustrate our order creation and processing workflow across our portals.
Request for physician to activate draft order would be a Task. Once the ServiceRequest is active, there would be a 'fulfillment' Task initiated from the provider to the lab. How things are handled behind the scenes in the lab is up to you in terms of report generation. The report would be sent to the provider as a response to the fulfillment Task. If there's a need for the provider to approve making the report available to the patient, that would be a third task.
How can we automate task based on the PlanDefinition and ActivityDefinition
Can you explain more of what you mean?
Is there any way to define task define fhir or we have to do business logic on our end
Is there any way we can create task based on the definition like PlanDefinition and ActivityDefinition.
As our order creation is automated with the selected PlanDefinition
We have PlanDefinition created for each test and based on that we show questionnaire to patient and create orders
Is there any way we can automate the task creation for order based on the PlanDefinition
It's certainly possible to generate Tasks from PlanDefinitions - the same as any other Request.
How can I do that. Is there any guidelines regarding this
@Bryn Rhodes is probably the best person to advise here.
The general idea is that the PlanDefinition is a hierarchy of actions that would each be applied based on whether the condition
element evaluated to true when the PlanDefinition is "realized". The PlanDefinition/$apply operation is what applies a PlanDefinition to a given patient.
The trigger definition defines when the PlanDefinition should be applied (simplest case is to use a named-event, which for something liked decision support we just map to the CDS Hooks hook definition).
Each action in the PlanDefinition specifies the activity to be performed as the definition
element, usually an ActivityDefinition that is realized as part of the PlanDefinition/$apply processing.
There's documentation on PlanDefinition and ActivityDefinition $apply here: https://hl7.org/fhir/plandefinition.html#12.23.4.3
There's also the Clinical Guidelines IG which defines profiles that support various types of clinical activities and modeling the definition, realization of that definition as a proposal, and then planning/ordering/performing each activity: https://build.fhir.org/ig/HL7/cqf-recommendations/profiles.html#activity-profiles
As expected, this (being tracking of a workflow) comes up quite often in various scenarios. I know many of the FHIR servers now support PlanDefinition$apply but are there are tools and guidelines for how these should be executed/run (e.g several BPMN engines around and also orchestrators such as Apache airflow)?
@Bryn Rhodes
There is a mapping that is proposed in the CPG between PlanDefinition and BPMN constructs: https://hl7.org/fhir/uv/cpg/documentation-methodology.html
State in CPGs is typically represented with patient data though, so the expressions are evaluated with respect to the patient's current record.
Bryn Rhodes said:
The trigger definition defines when the PlanDefinition should be applied (simplest case is to use a named-event, which for something liked decision support we just map to the CDS Hooks hook definition).
While working on the CDSS visual authoring tool wireframe using the Immunization DAK, I've noticed some potential issues with the WHO-designed BPMN:
The current design addresses all immunizations together, which makes sense conceptually.
IMMZ.png
However, this approach could lead to complexity issues:
To address these concerns, I am wondering if this alternative approach could be possible:
I am wondering if whether PlanDefinition actions can create such named events, as this would enable my proposed solution.
note: @Bryn Rhodes do you have the link where you define the different resource/stage that you presented in the WHO calls so I could align the BPMN (could not find them back with google) ?
I may be very wrong here, but isnt't that related to the strategy vs pathway split? strategy would be about "what vaccinations you're supposed to have" and pathway would be for each vaccination". I don't remember if there is something about merging them back together to a RequestOrchestration (or CarePlan?)
Other way around, the pathway is about the overall guideline, while strategy would be for focusing on a particular area or event, with recommendations being the lowest level, focusing on a particular recommendation statement. In immunization, I would think the strategy would be about the encounter, while the recommendations would be about the individual vaccinations.
@Jose Costa Teixeira so point is the ability to trigger a named-event from an action to create CPG specific HOOK, in the case of immunization you may need several of them to allow sub PDs/IG per vaccine to connect to the main flow.
The strategy would reference all the recommendations, so there isn't a need for an event, rather the encounter includes references to all the immunizations.
Is that what you're looking for Patrick?
Bryn Rhodes said:
Other way around, the pathway is about the overall guideline, while strategy would be for focusing on a particular area or event, with recommendations being the lowest level, focusing on a particular recommendation statement. In immunization, I would think the strategy would be about the encounter, while the recommendations would be about the individual vaccinations.
exactly but the recommendation is only one if the activities , in WHO flow there is more than one activities
I think this is what you're referring to: https://hl7.org/fhir/uv/cpg/documentation-approach-12-conceptual-knowledge-architecture.html
Bryn Rhodes said:
I think this is what you're referring to: https://hl7.org/fhir/uv/cpg/documentation-approach-12-conceptual-knowledge-architecture.html
it is similar approach but my question is more on how to created a FHIR planDefinition that will trigger name-event/cds-hooks. I had a look on the CDS hook profile but I am not sure if it listen to cds hooks or generate hooks:
here an example on how I see things on a L4:
Determine required vaccination
action will trigger an custom cds-hook/trigger "immz-determine-required-vaccination" that will result of starting all the PD with the matching trigger (we can also imagine that it trigger an external CDS-Hooks), then all the result of the "immz-determine-required-vaccination" triggered PD will be collected and use as a result (if any) of the initiating actions: we will have the "draft administer vaccince" resource that will be added to the request groupimmz-check-vaccine-contraindications
Is it possible to propose a new item control called 'dialog'? To specifically display choices in a pop up dialog.
https://hl7.org/fhir/extensions/CodeSystem-questionnaire-item-control.html
Sure, but when would you need a dialog box to display answer options for question?
For context:
It's simply a design decision, a client asked for a dialog.
And we're planning to use the 'dialog' control type in the Android FHIR SDK.
In the SDK, we have a hardcoded logic that says, if there are at least 10 options, then use a dialog. But we'd like to specifically use a dialog by declaring an item control type extension, so even if the options are less than 10, we can still use a dialog.
I would have said, if there are 10 options or more, use a drop down list, but maybe a dialog like that is right for the context of a phone app.
So, when you say "dialog", you mean specifically a dialog with checkboxes/radio buttons, and not a dialog showing a drop down list? I am just wondering if the dialog gets used for other control types sometimes.
In a phone you could make that decision anyway without having something in the item.
The UI hints are just that, and depending on the context/features/capabilities of the renderer and it's input mechanisms, those sorts of things could be done.
To me they are declaring what could be appropriate, and in some cases not appropriate.
If you're saying an auto-complete, you're giving a pretty strong indication that it's probably not going to be good to use radios...
So, when you say "dialog", you mean specifically a dialog with checkboxes/radio buttons
@Paul Lynch if options are defined, yes.
@Brian Postlethwaite
But it would also makes sense to use dialog
control type to display something else.
Let's say if we add a dialog
control type to a group, that means, whatever items are inside the group, will be displayed in a dialog. The trigger in showing that dialog can be a button.
There are an awful lot of complexities in that.
This is an example in FHIR doc where it tries to display a content to a dialog, it's not possible to do that in all renderer, since the example is not really using anything similar to dialog
control type.
https://build.fhir.org/ig/HL7/sdc/examples.html#using-contextexpression
I think defining dialog
control type would allow other renderers to specifically display a dialog in such scenario, no?
Dialogue then needs buttons, what's on them, what's the behaviour when you click them, OK, cancel, does cancel throw away the data, does that mean you need a new copy of that part. When would dynamic expressions using that data be fired etc...
I guess the question is where the line is drawn between what goes in the sdc ig and what is considered implementation. But I don't really feel dialog is a step forward in terms of "specificity" of the sdc ig - for example, we do have collapsible
which is a very specific ui treatment.
Fikri Milano said:
Brian Postlethwaite
But it would also makes sense to usedialog
control type to display something else.
Let's say if we add adialog
control type to a group, that means, whatever items are inside the group, will be displayed in a dialog. The trigger in showing that dialog can be a button.
I think the benefit in displaying options or questions in a dialog is probably specific to phone UIs, but then probably other renderers could ignore it.
One concern I have is that currently itemControl's cardinality is 0..1, which means if you said an item was 'dialog', you couldn't say anything else about it (e.g., use checkboxes or a dropdown).
@Paul Lynch would it makes sense to you if we have the dialog as it's own extension?
So in an item, we can declare both the dialog extension and itemControl extension
I don't suppose you're coming to the connectathon on the weekend by chance @Fikri Milano
I don't, how do I join?
It's an in-person event in Atlanta (USA)
I couldn't join, too expensive '-'
I thought it's an online call.
Fikri Milano said:
Paul Lynch would it makes sense to you if we have the dialog as it's own extension?
So in an item, we can declare both the dialog extension and itemControl extension
In case anyone has comment about this, please let me know
We do have online calls on Thursday afternoons (5 Eastern), but not this week or next week due to travel and the meeting next week.
Fikri Milano said:
Paul Lynch would it makes sense to you if we have the dialog as it's own extension?
So in an item, we can declare both the dialog extension and itemControl extension
Yes, that sounds better.
Lloyd McKenzie said:
We do have online calls on Thursday afternoons (5 Eastern), but not this week or next week due to travel and the meeting next week.
@Fikri Milano : https://www.hl7.org/concalls/CallDetails.cfm?concall=72728. "5 p.m. EST" should say "ET" (eastern time). It looks like you are 11 hours ahead of ET, so I can see that would be difficult time to meet for you, unfortunately.
Thanks all, it will be super early for me (4 AM), but I'll drop by if I do have the chance.
For the dialog extension, I'll create a jira ticket for now, and share the link here
Enjoy the event :D
Here's the Jira ticket https://jira.hl7.org/browse/FHIR-48350
cc @Jing Tang
It seems to me adding a 'dialog' code in the itemControl is a better solution. 'dialog' is essentially same as 'page' and 'tab-container' in that they are all containers of one or more items. They apply to the group items but not the question items.
A message was moved here from #questionnaire > Connectathon track by Ye Wang.
Yeah, that's what I initially thought, open for discussion. Feel free to leave a comment on the Jira ticket too
Dialog, to me, says "pop-up", and that's not what we're going for here...
Right, the implementation of a dialog/pop-up will be tricky. A lot of more details are needed to decide when to bring up the dialog, how to reopen the dialog once it's closed, and whether it is modal or not, etc.
And what happens if cancelled
I understand your concerns.
Would having more indicators to the extension make it more possible to add the dialog
to FHIR?
Lloyd McKenzie said:
Dialog, to me, says "pop-up", and that's not what we're going for here...
Is it because of the concerns mentioned by @Ye Wang and @Brian Postlethwaite ? Or is it something else?
When rendering an IPS document, IPS viewers are able to do a much better job if there's a map between the section entry resources and the narrative html elements that represent it
a typical situation might be that there's a list of items, which each item in the list is associated with an underlying allergyIntolerance resource
or maybe there's a table of observations
if a renderer knew which <li> or <tr> was associated with a particular resource, it could add links, mouse-overs etc that added reference, provenance information, or it could switch displays between consumer and clinician friendly, for interest
NZ has a particular interest in this after the connectathon of the last two days. And the spec does describe how to do this in the Composition resource
<div xmlns="....">
<table class="grid">
<tr idref="t1"><td>something...</td></tr>
<tr idref="t2"><td>something else...</td></tr>
</table>
</div>
and then:
"section" : [{
"title" : "Active Problems",
"code" : {
// snip
},
"text" : {
// as above
},
"entry" : [{
"id" : "t1",
"reference" : "Condition/eumfh-39-07-1"
}]
},
// etc
@John D'Amore I'd like IPS to mention the pattern and have a worked example. (but not to require it; that belongs in IPS profiles)
A message was moved here from #IPS > A referencing case of a patient summary document instance in by Grahame Grieve.
@Grahame Grieve
Currently the IPS reference server uses a different pattern utilizing the narrativeLink extension to accomplish this (http://hl7.org/fhir/StructureDefinition/narrativeLink). We did it that way since that's how we read the narrative guidance around the narrativeLink and originalText extensions (https://build.fhir.org/narrative.html#linking). I agree we should incorporate examples of this into the next IPS release (note reference server was still a work in progress when 1.1 came out).
We do reference back indirectly to the base FHIR spec somewhat in this section (https://build.fhir.org/ig/HL7/fhir-ips/design.html#narrative-and-language-translation), but also agree we could clarify that further.
hmm. it's the same use case? Got an example?
I didn't use that because it's a reference from a resource to a composition, and it'll be different for each occurrance of the same resource in different IPS documents, even if the resource hasn't otherwise changed .
and because you sure don't want to update .meta.lastUpdated but you kind of need to.
the id/idref solution is neater in that it's all in the composition
through I agree it's what the spec describes more clearly
This is just a random example from the IPS reference server hosted by HL7, not necessarily a good example: https://hl7-ips-server.hl7.org/fhir/Patient/49/$summary
It does follow the pattern of placing the ID in the <tr> which is a practice used by a lot of CDA examples gong back awhile. I agree that the section.entry.id pattern looks cleaner (i.e. it's not stuck in an extension). I'll try to raise this for discussion on next IPS weekly call
Yes, let's talk about this. The next call is in just over 2 hours from now.
another reason for me to prefer the id/idref model: there might be multiple references in the narrative to the same resource (different language sections), and it's cleaner this way too
yet another: the example document you referred to has multiple matching targets for the narrativeLink extensions.
This topic was extensively discussed at the FHIR Connectathon 37. I'll tag participants in this post, but the consensus was that id/idref patterns should be the preferred mechanism for narrative linking in IPS generation. A few consequences/considerations of this decision:
THanks to those who contributed in the discussion. @Peter Jordan @Giorgio Cangioli @Rob Hausam @Darren Liu @Martin Kaye @Andrew Liu @Hanhong Lu @Abigail Nicolas @James Agnew
@Lisa Nelson this is your answer, I think
do we have an example?
Hoping to have an example in IPS before end of day today! Going to try to adapt this one https://terminz.azurewebsites.net/fhir/Patient/$summary?profile=http://hl7.org/fhir/uv/ips/StructureDefinition/Bundle-uv-ips&identifier=https://standards.digital.health.nz/ns/nhi-id|AAA1234&_format=json @Peter Jordan
ok I'll check it shortly
{
"resourceType": "Bundle",
"id": "NZ-IPS-20231009024857",
"language": "en-NZ",
"identifier": {
"system": "urn:oid:2.16.724.4.8.10.200.10",
"value": "59f51f0b-2005-485c-858e-3d3ae9657287"
},
"type": "document",
"timestamp": "2023-10-09T02:48:57.4219686+00:00",
"entry": [
{
"fullUrl": "https://terminz.azurewebsites.net/fhir/Composition/d2d5d4dd-4e86-41c6-98d2-e412882e9b4c",
"resource": {
"resourceType": "Composition",
"id": "d2d5d4dd-4e86-41c6-98d2-e412882e9b4c",
"meta": {
"versionId": "1"
},
"language": "en-NZ",
"text": {
"status": "generated",
"div": "<div xmlns='http://www.w3.org/1999/xhtml' lang='en-NZ' xml:lang='en-NZ'>International Patient Summary for <span idref=\"AAA1234\">James Judge</a></div>"
},
"identifier": {
"system": "urn:oid:2.16.840.1.113883.2.18.7.2",
"value": "59f51f0b-2005-485c-858e-3d3ae9657287"
},
"status": "final",
"type": {
"coding": [
{
"system": "http://loinc.org",
"code": "60591-5",
"display": "Patient summary Document"
}
]
},
"subject": {
"reference": "Patient/AAA1234"
},
"date": "2021-05-03",
"author": [
{
"reference": "Organization/03993b0c-87ae-478b-8556-8c52a68c3486"
}
],
"title": "International Patient Summary",
"confidentiality": "N",
"attester": [
{
"mode": "professional",
"time": "2021-05-03",
"party": {
"reference": "PractitionerRole/1153dc30-cf69-402f-9522-132ec9ec14ac"
}
}
],
"custodian": {
"reference": "Organization/15d2d767-48ba-4222-a1ca-8fa34393aed4"
},
"relatesTo": [
{
"code": "transforms",
"targetIdentifier": {
"system": "urn:oid:2.16.840.1.113883.2.18.7.2",
"value": "59f51f0b-2005-485c-858e-3d3ae9657287"
}
}
],
"event": [
{
"code": [
{
"coding": [
{
"system": "http://terminology.hl7.org/CodeSystem/v3-ActClass",
"code": "PCPR"
}
]
}
],
"period": {
"end": "2021-05-03"
}
}
],
"section": [
{
"title": "Allergies and Intolerances",
"code": {
"coding": [
{
"system": "http://loinc.org",
"code": "48765-2",
"display": "Allergies and adverse reactions Document"
}
]
},
"text": {
"status": "generated",
"div": "<div xmlns='http://www.w3.org/1999/xhtml' lang='en-NZ' xml:lang='en-NZ'>There is no information available regarding the subject's allergy conditions.</div>"
},
"entry": [
{
"reference": "AllergyIntolerance/d46cc177-5660-46cc-9f55-6c28e1bc3bba"
}
]
},
{
"title": "Problem List",
"code": {
"coding": [
{
"system": "http://loinc.org",
"code": "11450-4",
"display": "Problem list - Reported"
}
]
},
"text": {
"status": "generated",
"div": "<div xmlns='http://www.w3.org/1999/xhtml' lang='en-NZ' xml:lang='en-NZ'>There is no information available about the subject's health problems or disabilities.</div>"
},
"entry": [
{
"reference": "Condition/20a587fa-239f-49c2-a3c8-ff2f2a18b654"
}
]
},
{
"title": "Medication Summary",
"code": {
"coding": [
{
"system": "http://loinc.org",
"code": "10160-0",
"display": "History of Medication use Narrative"
}
]
},
"text": {
"status": "generated",
"div": "<div xmlns='http://www.w3.org/1999/xhtml' lang='en-NZ' xml:lang='en-NZ'>There is no information available about the subject's medication use or administration.</div>"
},
"entry": [
{
"reference": "MedicationStatement/4e348646-0375-486a-a33d-d19801e6c7f7"
}
]
},
{
"title": "Immunizations",
"code": {
"coding": [
{
"system": "http://loinc.org",
"code": "11369-6",
"display": "History of Immunization Narrative"
}
]
},
"text": {
"status": "generated",
"div": "<div xmlns=\"http://www.w3.org/1999/xhtml\">\r\n <table>\r\n <thead>\r\n <tr>\r\n <th>Vaccine</th>\r\n <th>Status</th>\r\n <th>Occurance</th>\r\n <th>Route</th>\r\n <th>Dose #</th>\r\n <th>Series</th>\r\n </tr>\r\n </thead>\r\n <tbody>\r\n <tr>\r\n <td>Influenza, seasonal, injectable</td>\r\n <td>Completed</td>\r\n <td>2020-07-03</td>\r\n <td>Injection, intramuscular</td>\r\n <td>2</td>\r\n <td>45y (Eligible condition (Influenza))</td>\r\n </tr>\r\n <tr>\r\n <td>Influenza, seasonal, injectable</td>\r\n <td>Completed</td>\r\n <td>2019-06-03</td>\r\n <td>Injection, intramuscular</td>\r\n <td>1</td>\r\n <td>45y (Eligible condition (Influenza))</td>\r\n </tr>\r\n </tbody>\r\n </table>\r\n</div>"
},
"entry": [
{
"reference": "Immunization/c5efb4c3-91cf-4f63-b176-a697215d727a"
},
{
"reference": "Immunization/f58b2627-eeac-4280-8475-195ae422aa2d"
}
]
}
]
}
},
{
"id" : "AAA1234",
"fullUrl": "https://terminz.azurewebsites.net/fhir/Patient/AAA1234",
"resource": {
"resourceType": "Patient",
"id": "AAA1234",
"text": {
"status": "generated",
"div": "<div xmlns='http://www.w3.org/1999/xhtml' xml:lang='en-NZ'>Name: James Judge</div>"
},
"identifier": [
{
"system": "https://standards.digital.health.nz/ns/nhi-id",
"value": "AAA1234"
}
],
"name": [
{
"use": "usual",
"family": "Judge",
"given": [
"James"
]
}
],
"telecom": [
{
"system": "phone",
"value": "tel:+6478532279",
"use": "home"
}
],
"gender": "male",
"birthDate": "1985-04-25",
"address": [
{
"use": "home",
"type": "physical",
"line": [
"Bleak House",
"3 Worcester Drive",
"Rototun
Here is a link to an example using id/idref pattern adapted from @Peter Jordan server. I will go ahead and file a task for the validator to be updated since this does add a new warning since the idref is not contained in the resource which it references (but it is an the bundle) https://raw.githubusercontent.com/jddamore/IPSviewer/refs/heads/main/samples/connectathon_samples/NZ_Peter_Jordan_AAA1234.json
Discussed and JIRA tracker added here: https://jira.hl7.org/browse/FHIR-48338 @Grahame Grieve will make a task to update the validator behavior which currently returns a warning when including idref inside composition to a resource.id in the Bundle
2 example IPS instances on Terminz are now decorated (? ) with the atomic resource reference ids in the TR elements of the XHMTL narrative.
I added a test case to the validator test cases for this yesterday:
there's two links in there, one is AAA1234, which is valid. The other is AAA1234X which is not (it is a validator test case). Both are on line 23 (@Lisa Nelson )
I am looking for a way to generate resources (valid, invalid, in small or large quantity) by using the most efficient approach possible.
I want to create a resource in a way that is as simple and compact as
createResource("Patient", {"id"="p1","gender"="male", "name.text"="Mickey Mouse", "identifier.value"="123"}
or , of course,
createResource("""
Instance: myPatient
InstanceOf: Patient
* gender: #male
* name.text = "Mickey Mouse"
* identifier.value = "123"
"""
)
I would like the generation to be fast, and I don't need all the validation and package loading that comes with sushi. It should be light because I want to add it to another package that I plan to keep small.
Which of the client libraries could help here?
If the goal is as lean as possible and you do not care about data variability, I would just use variables and string templating for a JSON string. E.g. something like:
string[] genders = ["male", "female", "other"];
string[] givenNames = ["Mickey", "Donald"];
string[] familyNames = ["Mouse", "Duck"];
int i = 0;
foreach (string familyName in familyNames)
{
foreach (string givenName in givenNames)
{
string patient = $$$"""{"id":"{{{Guid.NewGuid()}}}", "gender":"{{{genders[i % genders.Length]}}}", "name":[{"family":"{{{familyName}}}", "given":["{{{givenName}}}"]}]}""";
i++;
}
}
jInja2, python dicts
I use csv to enter the data and pandas to process them as variables only downside here is a lot of braces
This must be flexible - in one line I may be creating a patient with name only, in another i may be creating a patient with everything.
I have jinja2 feeding into sushi, that makes the authoring really easy and sushi handles all the fhir aspects. But I don't think it's the leanest approach
I don't know if this is possible:
Can I write something very compact like
id|Patient.name.text|Patient.name.given|Patient.name.family|Patient.gender
|---|---|---|---|---|
001|John Doe|John|Doe|male
|002|Jane|Jane||female
and use the Sushi libraries without having to actually run the entire sushi thing, just the resource instance creation (no validation, no package downloads etc)?
At that point I imagine its easier to get a AI to interpret it into fsh and then go from there.
Isn't there some tool that does that for CSV files?
well, I have one but runs sushi command line. taking the entire baggage - packages etc.
Jens Villadsen said:
At that point I imagine its easier to get a AI to interpret it into fsh and then go from there.
This is for a pipeline, and I don't think an AI would do things well and consistently in the pipeline, right?
do you want a random set or a static set of resources?
Static
Well not random
Determined
Eventually things like "patient with 9 months of age'
In a previous job we had defined a sort-of DSL for this kind of example resource generation (in a spreadsheet). We had a mechanism for doing date-relative stuff (like 9 months ago [i.e. from today], values and units for Observations, etc.
Maybe this could be done using a Cucumber tool (Gerkin syntax) where you define some basic given/when/then statements for the kinds of resources you want to generate, then write some code "behind" to generate the resources from that.
Well, the reason I am asking is because I want to add thar data generation function to a gherkin setup
"001|John Doe|John|Doe|male" ? - a compact format.. like HL7 v2 ? ;-)
or markdown-like tables (same thing but sounds less archaic) ;)
the function that reads this can call a javascript (or other) function to generate the resource. I am chekcing what options and libraries are out there
I think the suggestion to have it in gherkin sounds nice - but I wouldn't put it into the CI chain. I would instead use it to generate fsh files and then the CI chain can be left untouched
I see no reason to add that sort of new functionality to the chain. Piggyback on what you have and add an instrumentation layer/generation logic ahead of that
add the generation as a (reusable) github action or something ...
I mentioned "Ci chain" - but i didn't mean the IG ci build, but another test workflow.
got it
hence my idea to see if we could convert fsh files to fhir resources inside a javascript procedure, but without loading all the packages, running all the validation...
Hmm, that sounds interesting. I remember seeing discussions about the fact that the FSH to FHIR generation process was relatively slow with all the validation and ValueSet expansion (if I remember right) in Sushi 3.x. If you had tooling that could do this faster (of course w/o validation) that could make things much faster.
@John Silva I'm not entirely in favor of catering for something that doesn't add validation
in testing, i do want to add wrong data
e.g.
Test posting of a patient without required element. Result should be error
Hi, I'm currently part of a project where we plan to model some of the more niche DICOM fields in FHIR. We already found the DICOM FHIR package but noticed that while it includes all the ValueSets defined in DICOM, the "enums" defined as value lists for some DICOM fields are not included. E.g. https://dicom.nema.org/medical/dicom/current/output/chtml/part03/sect_C.11.html#sect_C.11.1.1.2 : OD, HU, US etc. look like they should be represented in FHIR using Coding, but since they are currently not defined in the DICOM CodeSystem we are unsure how. Can we use the http://dicom.nema.org/resources/ontology/DCM System URL? Is there a standardized way to "build" system URLs for DICOM fields with value lists? Has anyone tried to use these values in FHIR before?
@David Clunie this is a question for you, I think
Somebody would have to do the mapping between the strings (CS VR in DICOM) and some coding scheme, like implementations do with Modality (0008,0060) that is a string in DICOM, but is represented as a CodeableConcept in FHIR ImagingStudy (which even though it uses a value set defined in DICOM as a Context Group for other purposes, isn't actually used for (0008,0060)). DICOM isn't going to go back and re-engineer or re-document the hundreds of these CS data elements and value sets, so don't hold your breath.And no, you can't use the DCM system URL unless the code value is already defined in PS3.16 Annex D.
that kind of leaves implementers in a hard place, David. Could we define a URL like http://dicom.nema.org/resources/ontology/{X,Y} such that if there are codes defined informally for a field, then for this case, http://dicom.nema.org/resources/ontology/0008,0060 identifies the codes that go in the element 0008,0060?
It may not be that simple - the permissible string values depend on the context of use of the data element (e.g., different places in nested sequences, different IODs). Also, are you just looking for a place to find a list of possible string values, or a URL to use as an alternate representation of that string (which would potentially conflict with whatever URL was canonically defined to represent the meaning of the concept, if a proper mapping were to be done). The example Noemi cited actually has the same values (with the same meaning) for two different data elements (Rescale Type and Modality LUT Type), which is another factor (or refactor, if you will excuse the pun).
the URL in this case is a CodeSystem URL, so it just differentiates the codes from each other. The fact that the different contexts of use have different permissible values is a value set thing, and less of an immediate challenge
The example Noemi cited actually has the same values (with the same meaning) for two different data elements (Rescale Type and Modality LUT Type), which is another factor (or refactor, if you will excuse the pun).
My proposal means that they are effectively cloned - the same value gets two different URLs for the two different place it's used, even though it has the same meaning. That's sub-optimal, but I proposed that based on the fact that you said DICOM (reasonably) didn't want to reengineer, so I assumed that wrangling the coded meanings like that was out of reach
@Jonathan Whitby
A solution with an URL scheme like the one proposed by @Grahame Grieve ( http://dicom.nema.org/resources/ontology/{X,Y} ) would work for us (unless i'm missing something). Is there any way to make this an "official" solution, describe it e.g. in the FHIR spec or on the DICOM page?
I think it's up to DICOM. @David Clunie is that something that DICOM would consider?
Unlikely because I think it is a terrible idea (vide supra); FHIR can do what it wants, but you would have to find a DICOM champion to go further on our side, and you can't use the "dicom.nema.org" domain.
well, what do people do then?
PS. I think you are over-engineering this - I am not sure that struggling to use CodeableConcept for something that doesn't already have codes (or URLs for those codes) is a practical solution - you could just treat these as strings and leave the enumeration restriction handling to the implementation (or the other standard, i.e., DICOM).
we wouldn't usually do this - we'd usually define the codes properly. But that could be done, sure
That's my whole point - if you are not prepared to do the work of defining the codes "properly" (meaningful code system, meaningful codes, meaningful URIs, with definitions, no duplicates, etc.), then I suggest that you don't make up a mechanical scheme that may be syntactically correct but undermines what is arguably the purpose of using codes in the first place - I don't think CodeableConcept should be used as an unwieldy substitute for a small set of enumerated string values that are not re-used in a more general context. Why doesn't FHIR have enums that are not codes? If you want to mechanically translate the entire DICOM standard, or just all its data elements and values, into a FHIR representation, then good luck with that, but that hasn't been WG20/IIs approach up to this point (rather they have tried to define EHR meaningful specific resources for specific use cases in a relatively selective and disciplined manner; the Modality codes were a special case in one such resource (ImagingStudy)).
@Grahame Grieve I empathize with @David Clunie on this. I am working with a group of people discussing a proposed DICOM representation in RDF (including URIs and the potential URI-ification of Enums). Everything needs to be considered in the context of the whole of DICOM specification lest issues occur downstream. For example, a cleverly crafted JSON-LD context will RDF-ize an official DICOM JSON document, but upon further examination, falls apart as JSON-LD processing removes nulls from literal arrays which destroys the DICOM positional semantics and/or ordering. I would not piecemeal this.
I am unclear where these enums need to be used in existing FHIR. So I presume you are not trying to use them in existing FHIR.
If you are going to create a FHIR extension, you can create that FHIR extension using datatype code, and replicate the enums as FHIR extension enums. Meaning, FHIR has enums for code datatype. Just not for any coding or codeableConcept.
if you do this, then the replicated enums in FHIR will be completely indistinguishable from those in DICOM. Hence the whole benefit and drawback of enums.
@David Clunie it's not me, it's @Noemi Deppenwiese so maybe some explanation is at hand from Noemi.
I don't think CodeableConcept should be used as an unwieldy substitute for a small set of enumerated string values that are not re-used in a more general context. Why doesn't FHIR have enums that are not codes?
No, I wouldn't look to use CodeableConcept either, but no one mentioned that. I'd use code
, but the definitional infrastruture still wants there to be a formal code system and value set underlying that, which leads to this question.
Anyway, Noemi, you have your answer, I guess. The committee isn't motivated to help you out, so you can make up your own url
are you just looking for a place to find a list of possible string values
I think defining a CodeSystem with all the CS enumerated values would be a good place to start. Given the challenges, we don't need to define the ValueSets for each element now. (We can address that later, if needed.)
Actually, we don't even need all the enumerated values listed, we can do content=not-present
. As long as there is a canonical URL that implementers know defines "DICOM enumerated values", then the implementer can use the values they need, or define their own value sets for their needs.
I think the real issue at this point is that there needs to be a canonical URL that DICOM and HL7 agree will identify the values, rather than HL7 defining one and DICOM later defining another. It can be an HL7 url or a DICOM url, as long as both groups agree that will be the canonical URL used.
http://dicom.nema.org/resources/ontology/defined-terms
?
doesn't there need to be more than one, because dicom will use the same code string with different meanings in different places?
John Moehrke said:
I am unclear where these enums need to be used in existing FHIR. So I presume you are not trying to use them in existing FHIR.
If you are going to create a FHIR extension, you can create that FHIR extension using datatype code, and replicate the enums as FHIR extension enums. Meaning, FHIR has enums for code datatype. Just not for any coding or codeableConcept.
We are planning to create extensions, but even with the code data type, we would still need a system url in order to create a ValueSet and a binding for that element (unless i'm missing something?). So, at this point i see two options for our project: A) Define our own system URL or B) use strings. While B) would probably be less work for us, it might not work well / at all with our existing infrastructure/ federated search framework (@Lorenz Rosenau ). I can see your point about these codes not being relevant outside of DICOM, so i guess an option C would be to map everything to something like SNOMED CT and have all sites use these codes instead of DICOM, however i don't think this is a realistic scenario in our setting (and mapping all codes would be even more work than A).)
A) Define our own system URL
you can
or B) use strings
you can do that too, and still bind to a code system.
In fact, you can use code data type, and bind to a code system. The advantage of that approach is that your fictional URL doesn't appear in the instance, so if and when either HL7 or DICOM does something about this, your instances don't change, just the background machinery
option C would be to map everything to something like SNOMED CT
seems unlikely you'll find the SCT concepts you need - these are very situational codes
as Grahame has just emphasized, if you use code you define the enums. yes you will have to create a system value, but that system value never appears anywhere except in the definition of the extension to support linking the enums to the extension. It will not appear in any data. Thus it is indistinguishable from using DICOM enums in the data.
Grahame Grieve said:
doesn't there need to be more than one, because dicom will use the same code string with different meanings in different places?
Maybe. My initial thought is that any term used in more than one place will have similar, if not the same, meanings and the definition (if we provide it) could be general enough to cover all meanings. I can't imagine that they'd have completely different meanings, although I suppose the only way to know would be to build the list.
Looking at it another way, is there any information lost if we use one code system? I expect the codes would only be used in the context of an attribute, so the meaning should be clear.
My initial thought is that any term used in more than one place will have similar, if not the same, meanings and the definition
that's certainly not how v2 codes worked. "M" had all sorts of meanings
I suppose that is possible.
I just had a quick and there are a few places with numeric enumerated values, where, e.g., 1 means something different from place to place. (Bits per pixel, samples per pixel, etc.) But I think we can ignore those since they are used in numeric data types. I’m not sure how to quickly find others.
Someone would need to cross reference the 4000 times enumerated terms appear in the standard with use in a CS (and possibly a couple of other) data type and collate those that appear more than once to see if the meanings differ.
Oh well, it was a nice idea.
right. as David said:
DICOM isn't going to go back and re-engineer or re-document the hundreds of these CS data elements
@Gino Canessa @Bas van den Heuvel
Hi. Anyone facing the following error response from AWS HealthLake FHIR Search api, when chaining with other resourceType?
I'm trying to get all the observation with Patient gender.
[GET] endpoint:
https://healthlake.<aws-region>.amazonaws.com/datastore/<data-store-id>/r4/Observation?patient.gender=male&_count=10
Response:
{
"resourceType": "OperationOutcome",
"issue": [
{
"severity": "error",
"code": "not-supported",
"diagnostics": "Search parameter gender for resource type Patient resulted in more than 100 hits. Please provide more precise queries."
}
]
}
I tried with multiple chaining for more precise query like patient with gender and patient with name, however im getting the same response.
gender + name:
https://healthlake.<aws-region>.amazonaws.com/datastore/<data-store-id>/r4/Observation?patient.gender=male&patient.name=sachin&_count=10
Are you sure this server support forward parameter chaining ? Does it support the patient search parameter on Observation ? If not you're effectively searching for all observations, and for sure there'll be more than 100..
It appears the count=10 is not being used. I would try to add a few more parameters. If it works for your usecase filtering with a date of service could be helpful.
Clint Johnson said:
It appears the count=10 is not being used. I would try to add a few more parameters. If it works for your usecase filtering with a date of service could be helpful.
I'm getting same error response with and without _count
_count doesn't have any impact on the number of matches, that's only about the 'max page size'. So you should see the same number of matches (and hence: the error), _count has no impact on that..
René Spronk said:
Are you sure this server support forward parameter chaining ? Does it support the patient search parameter on Observation ? If not you're effectively searching for all observations, and for sure there'll be more than 100..
AWS does support forward chaining as per this doc https://docs.aws.amazon.com/healthlake/latest/devguide/search-parameters-advanced.html
Yes observation support patient
and it supports subject
as well
GET Observation?patient.gender=male&patient.name=sachin is certainly valid FHIR. If this were to be a common name, or we're dealing with a chronic patient, there could be > 100 observations. In general, searching by identifier is better than searching by name. You could try and add the date of the observation ('today') as a search parameter in an attempt to get the server to respond with a lower number, or even zero, matching Observations.
Observation?patient.name=XXZZQQWWRRAA is very likely to result in zero matches. Why would you want zero matches? Because then you'd know the search parameters to work. If you get a Bundle response you can study its 'self' link to see which parameters have been used/processed by the server.
Yes, tested with patient.name and its working (which has 19 hits), however adding patient.gender parameter throws same "Search parameter gender for resource type Patient resulted in more than 100 hits. Please provide more precise queries."
Searching by identifier will always work, but our users expecting to search based on other parameters, so i'm looking into capability. Thanks for sharing your thoughts @René Spronk
Ok, so name gets 19 hits (in your example) and by also adding gender it seems to respond > 100 ? It should be <= 19 if you add additional search criteria, so if it states 100 that would be a server-side error.
René Spronk said:
Ok, so name gets 19 hits (in your example) and by also adding gender it seems to respond > 100 ? It should be <= 19 if you add additional search criteria, so if it states 100 that would be a server-side error.
EXACTLY.
Expecting <=19 records, but it gives 100 hits error. I have reported this to AWS Support and they are investigating it.
I bet they translate
patient.family=Sachin&patient.gender=male
into
patient in (all patients with family=Sachin) and patient in (all patients with gender=male)
instead of
patient in (all patients with family=Sachin and with gender=male)
and so they get more than 100 matching in the second 'in'
From the error message it sounds like AWS has implemented the same limitation that the Google server has on chaining, so I can take a guess at what is happening. This is an implementation pattern for servers that don't support joins in their search index (usually because they're using a document-based search stack) to provide limited chaining.
Each clause independently expands into a subquery, in this case Patient?gender=male
and Patient?name=sachin
. Each of these subqueries returns results which are substituted into the main query, usually by resource ID, so the parent query becomes Observation?patient=[id1,id2,id3,...]&patient=[idA,idB,idC,...]
. Because the parent query might need to be paginated and the result depends on the intersection across all pages of each subquery, it is infeasible to also paginate the subqueries and their results must be limited to something that doesn't need pagination. This is what the 100 limit is indicating - Patient?gender=male returns more than 100 results (not surprising) so regardless of whether other criteria narrow the result later, this part of the query becomes a bottleneck that cannot be handled.
Paul Church said:
From the error message it sounds like AWS has implemented the same limitation that the Google server has on chaining, so I can take a guess at what is happening. This is an implementation pattern for servers that don't support joins in their search index (usually because they're using a document-based search stack) to provide limited chaining.
Each clause independently expands into a subquery, in this case
Patient?gender=male
andPatient?name=sachin
. Each of these subqueries returns results which are substituted into the main query, usually by resource ID, so the parent query becomesObservation?patient=[id1,id2,id3,...]&patient=[idA,idB,idC,...]
. Because the parent query might need to be paginated and the result depends on the intersection across all pages of each subquery, it is infeasible to also paginate the subqueries and their results must be limited to something that doesn't need pagination. This is what the 100 limit is indicating - Patient?gender=male returns more than 100 results (not surprising) so regardless of whether other criteria narrow the result later, this part of the query becomes a bottleneck that cannot be handled.
Thanks, Yeah it makesense, I might get back to my team about this. And complex queries cant be handled with this limitations
What are other options or ways to achieve such scenarios as part of querying?
Most of these limitations can be worked around by either doing multiple queries or inverting the direction of the join. In this case if you did Patient?gender=male&name=sachin
that would return a small result set, which you could then substitute into Observation?patient=[list of result IDs from first query]
.
Meaning that simpler queries win out because not only will they work when the next server doesn't support the complete, complicated query syntax. They will also work when the complicated queries have a limitation.
This does mean that implementing all the resource traversal logic falls on you, but maybe that isn't such a bad thing. "Why are we getting all this data when we don't use it?"
You might also get some advantage of parallel threads. Instead of 1 query that returns 100,000 rows... maybe the 1st query gives you 19 patients and then you can do 19 separate queries to get 5k rows each.
You might get an advantage on retry logic, 1 query that returns 100k fails you restart 100k. But if one of the 5k queries fail you just retry that 5k.
You might get advantage on JIT retrieval. User does the query, sees that they only care about patient #6, so you only need to do the patient #6 5k query rather than doing the 100k query and throwing away 95k resources that didn't match the patient they actually wanted to review.
To be clear, it is not all upsides. Doing queries remotely and aggregating the results locally does:
I am not saying there are other options in this case, just noting that it is not a scenario of "doing this all client side is better anyway" =)
Reading https://build.fhir.org/ig/HL7/fhir-ips/OperationDefinition-summary.html, it notes:
This operation returns an IPS document in response to a POST request
As the parameters (currently) are both primitive types, implementers may choose to also support GET, correct? (https://www.hl7.org/fhir/operations.html#executing)
When an operation has affectsState = false, and the parameters are all primitive datatypes with no extensions (as is the case with the example above), it may be invoked using GET as well.
We did discuss this a year or so back. I think the answer was that best practice is that it would be a POST (since that allows most flexibility) but that if servers support the operation as a GET, that's not prohibited (even if not good form). It falls into the same category as some prior discussions on other operations. I think both work on the HAPI reference implementation. @Peter Jordan do I remember you having a preference on this for your server?
just to be bit annoying - if GET is allowed (which I believe is perfectly valid) then so must HEAD be allowed (according to the spec)
I apologize for the potentially stupid question, but which spec @Jens Villadsen ? (quite a few layers of specs involved here :) )
FHIR spec
It doesn't seem like servers need to support HEAD according to that section.
But perhaps I assumed you meant server support requirements when you did not mean that.
Hmm ... I actually meant server side... But I see your point
I think that text should be updated
It is valid for clients to issue a HEAD request, but the server can reject it in any valid HTTP way (which, there are at least 2 ways, perhaps more).
John D'Amore said:
We did discuss this a year or so back. I think the answer was that best practice is that it would be a POST (since that allows most flexibility) but that if servers support the operation as a GET, that's not prohibited (even if not good form). It falls into the same category as some prior discussions on other operations. I think both work on the HAPI reference implementation. Peter Jordan do I remember you having a preference on this for your server?
My server only supports GET requests for $summary. While this might not be in line with the specification, I generally only support POST requests for operations in which one of the input parameters is a resource.
@Peter Jordan may I ask why?
@Jens Villadsen sure! Having used REST, in other domains, before FHIR, I guess that I still find it non-intuitive to use a verb that basically equates to a Create Request for a Read Request (and I note that, judging from some posts on LinkedIn, others find it so). However, I can change that if required.
Some operations are idempotent of which it makes a lot of sense Id say
Not sure that GET v POST would much difference to that on my Server (which I'll update to support POST for requests not containing resources). Of course, there are other practical reasons for using POST for read requests (long query strings, attempts to hide patient identifiers from logs, etc.)
Clarification - a POST operation request will work on my Server if the request parameters are contained in a Parameters Resource! I think I need another cup of coffee before starting work today. :blush:
Back to this (and I missed the ballot signup - but here it goes anyways): v1.1 technically allowed GET https://hl7.org/fhir/uv/ips/OperationDefinition-summary.html but was flawed in that sense that the Identifier
type complex and not simple, and hence cannot passed along in a GET. Now, the ballot version (https://build.fhir.org/ig/HL7/fhir-ips/OperationDefinition-summary.html) has corrected this and made the identifier work as a token type, but for some version stated that the operation is ALWAYS POST?!! What is up with that?
FYI @João Almeida
@John D'Amore none of the jira issues referenced in https://github.com/HL7/fhir-ips/commit/6a56a5fcc6fa35d4ff96ab822bd6a935613bb1f6 - (https://jira.hl7.org/browse/FHIR-40223, https://jira.hl7.org/browse/FHIR-40240, https://jira.hl7.org/browse/FHIR-39598) mentions anything about the operation being limited to POST
- yet, the text changed to "This operation returns an IPS document in response to a POST request". Why?
Jens, we re-did the description in a collaborative IPS call in July. We agree that we did not mean to imply a POST would be exclusively used (and many vendors at connectathon have been supporting GET). We discussed this briefly today and have filed a technical correction (with correpsonding commit) to address:
It's surprisingly difficult to 'search for all AuditEvents that are about the reading of AuditEvents' - Any suggestions beyond something like https://hapi.fhir.org/baseR4/AuditEvent?action=R&entity:AuditEvent.action=C,R,U,D,E (note that entity:AuditEvents attempts to scope it down to AuditEvents about AuditEvents, the .action=C,R,U,D,E should always be true). My search url results in zero matches - which may indeed be the answer, but it's more likely that my search url could be improved upon..
can you explain a bit more? I thought you were asking about AuditEvent records that indicate that someone has searched on AuditEvent resources? Thus those AuditEvent records that have a .entity.query has a search path including AuditEvent... Which some have identified this is hard as the .query element is base64 encoded... which is why in IHE-BALP, I recommend that the cleaned search be also included in .entity.description. You would need to add a search parameter to search .description.
https://profiles.ihe.net/ITI/BALP/StructureDefinition-IHE.BasicAudit.Query.html
Good use-case to drive changes in R6... lets figure this out.
the .query element has never been intended for this kind of use. It has been designed to hold exactly what was requested so that malicious (Security or Privacy) intent.
I added an issue to BALP -- https://github.com/IHE/ITI.BasicAudit/issues/104
and added this to FHIR R6 - https://jira.hl7.org/browse/FHIR-48324
Doing this for searches is tricky, and e.g. Firely Server also includes AuditEvents in a response to $everything. I assume that if we did a search there'd be an AuditEvent for the search, followed by 1or more AuditEvents related to the 'reads' of the matching resources. The latter may not actually be the case, so doing a straight search for reads won't work.
okay, so you are looking for AuditEvents for searches. Not necessarly searches on AuditEvent.
This is why I profiled this in IHE-BALP; to give consistent logging, so that one could search the AuditEvents consistently.
and given that a FHIR search, returns the resources, then it is uncommon for a read of the resource.
Side note: _type is a search parameter defined for all resource types, so I tried https://hapi.fhir.org/baseR4/AuditEvent?action=R&entity._type=AuditEvent - but that's not supported.
I'm seeking to answer the question 'how often do users perform a GET for AuditEvents (on a server that does use/support FHIR AuditEvents)' ?
René Spronk said:
Side note: _type is a search parameter defined for all resource types, so I tried https://hapi.fhir.org/baseR4/AuditEvent?action=R&entity._type=AuditEvent - but that's not supported.
entity.what._type ?
The way it's worded https://hl7.org/fhir/R4/search.html#_type it's not a parameter on a specific resource. It's a general purpose parameter on the general search.
Instead of doing /baseR4/Observation you could do
/baseR4?_type=Observation,Condition&_id=12
To get the Observation with id 12 and Condition with id 12 in the same query.
We ended up adding this search parameter:
{
"resourceType" : "SearchParameter",
"id" : "AuditEventResourceType",
"text" : {
"status" : "generated",
"div" : "<div xmlns=\"http://www.w3.org/1999/xhtml\"><p class=\"res-header-id\"><b>Generated Narrative: SearchParameter AuditEventResourceType</b></p><a name=\"AuditEventResourceType\"> </a><a name=\"hcAuditEventResourceType\"> </a><a name=\"AuditEventResourceType-en-US\"> </a><h2>resource-type</h2><p>Parameter <code>resource-type</code>:<code>string</code></p><div><p>Extra search parameter enabling search (and sort) on Resource types</p>\n</div><table class=\"grid\"><tr><td>Resource</td><td><a href=\"http://hl7.org/fhir/R4/auditevent.html\">AuditEvent</a></td></tr><tr><td>Expression</td><td><code>AuditEvent.entity.detail.where(type = 'ResourceType').valueString</code></td></tr><tr><td>Multiples</td><td><ul><li>multipleAnd: It's up to the server whether the parameter may repeat in order to specify multiple values that must all be true</li><li>multipleOr: It's up to the server whether the parameter can have multiple values (separated by comma) where at least one must be true</li></ul></td></tr></table></div>"
},
"url" : "http:trifork.com/eir/SearchParameter/AuditEventResourceType",
"version" : "0.9.0-273540f-20240827095832",
"name" : "resource-type",
"status" : "active",
"date" : "2024-08-27T08:08:21+00:00",
"publisher" : "Trifork",
"contact" : [
{
"name" : "Trifork",
"telecom" : [
{
"system" : "url",
"value" : "https://trifork.com"
}
]
}
],
"description" : "Extra search parameter enabling search (and sort) on Resource types",
"code" : "resource-type",
"base" : [
"AuditEvent"
],
"type" : "string",
"expression" : "AuditEvent.entity.detail.where(type = 'ResourceType').valueString"
}
-to be able to filter on resource type
One interesting nuance is that there is a :[type]
modifier on reference searches, so I'm pretty sure you can do AuditEvent?entity:AuditEvent=something
- the problem is that you can't omit the =something
and just filter by the type of the reference using that modifier.
..hence my trickery with ?entity:AuditEvent._id:missing=false - "_id:missing=false" is always true for all FHIR resources. The additional parameter used by Jens would be the best solution I've seen so far.
When converting the CQL to ELM, Please let me understand how can unit testing be performed?
Say for an example, the CQL has inequality operator and hence the engine will perform visit for InEqualityExpression.
Now here, When Elm is being generated, how can i write test cases to ensure that the resulting expressions have correctly generated the localId or locator etc w.r.t the CQL
@Kashish Please create a new topic if your question is unrelated to an existing topic. Your question is probably best asked in the #cql channel on this forum, please create a new topic in that channel.
I welcome issues written against IHE-BALP as a way to define these improvements for a FHIR R4 environment, AND right now would be a good time to put in jira tickets against FHIR core AuditEvent so that these can be more core fixed for FHIR R6. Please be specific on what the use-case need is, and if you have a solution to recommend that would be fantastic.
John Moehrke said:
I added an issue to BALP -- https://github.com/IHE/ITI.BasicAudit/issues/104
I did enter this one in BALP. If you have comments you can add them as comments. If you have more to be fixed in BALP, please add more issues (If you don't have IHE github access, let me know)
John Moehrke said:
and added this to FHIR R6 - https://jira.hl7.org/browse/FHIR-48324
similarly, I created this jira ticket against FHIR R6. again, comments welcome. And more jira tickets are welcome.
@Carmela Couderc suggests that the VSAC package I produce need not include value sets with a VSAC value set status of "Deprecated
" or "Not Maintained
"
This is a change I can make easily, but does anyone see any pitfalls with me doing that?
Just because VSAC deprecated a value-set, does that automatically mean there are no more users of it (or needing validation against it)?
that's the question. I think that there shouldn't be
just because they are deprecated for Now and Future use; does not mean they were not valid in the Past. We can't have data considered invalid because it shouldn't be created today, when it was created 5 years ago.
@John Moehrke how does that apply to value sets?
validating old data... did the value used back then exist in an old valueset?
Wouldn't that be dependent on an older version of the VSAC package?
okay
I just know I have old data that I need to put into FHIR format... and it is using codes that were valid then... so I guess I am more interested about code management than valueset management. Seems they are related
and... it is very unlikely that tx.fhir.org will have the vsac valueSet from 20 years ago... unless we are agreeing to add all historic valueSets.
I am not sure that continuing to publish new versions of the package with value sets from 20 years ago is better than keeping them in a terminology server.
I am writing a brand new IG... dealing with conversion of historic data... so it is NOT an old package, it is a new package that needs OLD valueSets.
Sure. And if you (or anyone else) want to use old value sets, you need to reference old packages.
I do not think we want our policy to include publishing old versions of content because people might find them useful. It would be like asking US Core 8 to include all the canonical definitions from every earlier version so that people can reference the newest package and use the old definitions.
I don't disagree... but today, when the code is not found the validator throws an ERROR. A warning I could justify why it is okay. I do have a justification for the ERROR, but the ERROR does not go away. So, then if we are not going to include old codes/valuesets... then Please change a missing code to a warning, not an error.
maybe we need a way in an IG to indicate that the valueset is historic, and thus missing codes should be warnings.. vs a new IG that really wants CURRENT valueset, and thus a missing code is an error.
@John Moehrke your issue is about code systems not value sets
my urgent problem could be fixed by a codeSystem owner including deprecated codes, marked as deprecated. agree.
I am not convinced that a change to a valueset to exclude codes doesn't behave the same. (not convinced due to not experienced it)
reducing vsac to only active value sets halves it's size to 7254 value sets (right now)
so, what do you think of my idea that I should be able to indicate that I am using an old (undefined) valueSet, so therefore have missing codes as warnings rather than errors?
not much. what's the value set got to do with it?
Hi there! I was wondering if these two parameters are still supported.
java -jar publisher.jar -source [source] -destination [dest]
as described here: https://confluence.hl7.org/display/FHIR/IG+Publisher+Documentation#IGPublisherDocumentation-ValidatingwithoutpublishingMy output :point_right:
-simplifier
parameter as described here: https://confluence.hl7.org/display/FHIR/IG+Publisher+CLI#IGPublisherCLI--simplifierMy output :point_right:
Does anyone know what this is supposed to do?
I'd have to look into it.
-simplifier is intended to be for the private simplifier interface. It's not tested by you or us, so I'm not surprised it's broken. Should I fix it?
same for the other
We're working on hanging the IG Publisher in Simplifier, as part of our Quality Control system. The issues generated by it would be added to the Issues tab to work on or automatically close later.
We're generating an IG resource based on the Simplifier implementation guide so the IG Publisher knows how to find all the resources, listing all resources and the dependencies and such.
We can just remove/not store the generated guide in this case. Was just wondering if it would be faster or simpeler not to. Also not sure if it would generate less good validation in that case.
Grahame Grieve said:
-simplifier is intended to be for the private simplifier interface. It's not tested by you or us, so I'm not surprised it's broken. Should I fix it?
So what is it supposed to do or produce?
the intent is that you (well, Simplifier) provide source - a folder containing resources including an IG resource. The IG publisher does QA on all those resources, and then returns a file - format yet to be decided - that has a list of all the discovered issues in those files
(a) is that the kind of interface you want for
on hanging the IG Publisher in Simplifier, as part of our Quality Control system
(b) what do you want returned? The easiest thing for me to return is a bundle of operation outcome resources as already produced by the IG publisher (qa.xml, I think)
though it doesn't have to be xml
Yes, it will help us to have a parameter to just do validation. The bundle with operation outcome resources will suit us just fine.
ok. I'll work on it. I'll let you know when I think it's good
is a command line interface enough? Or do you want a JNI ready interface?
the JNI interface idea is way more complex, but you can get better performance by preloading things
Thanks Grahame, let's start with a command line interface. We can optimize later if it is needed.
do you want to share a sample what you generate with me of so I can be sure I'm getting it right?
No problem. I will create a zip file with some example input data we use and post it here tomorrow.
Here is the test data we use. It is based on our ACME project on Simplifier (https://simplifier.net/acmebaseprofilesr4). There is a resource without an id that stops the publisher from generating the ig but I think the validation only option should report that in the qa output. We are still in the POC stage so any feedback on how to improve our data or process is welcome.
Did you make any progress on this Grahame?
thanks for reminding me. From the next release, if you run with the parameter -ig {folder}
for the folder you sent me, and also the parameter -simplifier
, you'll get this output:
While reviewing this tracker I had a thought that maybe we should instead of trying to create a query to locate the context to apply the extracted content, just use a reference/Id field that is to be the resource ID of the resource to be updated.
If it is empty, then that's a create, if its populated, its an update.
We can then populate it with pre-pop if we need to, or use other dynamic expressions to populate it if needed.
Then the existing extension http://hl7.org/fhir/StructureDefinition/questionnaire-referenceResource
and/or http://hl7.org/fhir/StructureDefinition/questionnaire-referenceProfile
could be used to indicate the type of the resource too.
Something along the lines of this:
{
"resourceType": "Questionnaire",
"id": "example-questionnaire",
"status": "draft",
"title": "Example Questionnaire - super simple intake form",
"extension": [
{
"url": "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-itemExtractionContext",
"valueString": "Q1"
}
],
"item": [
{
"linkId": "Q1",
"text": "Patient Reference",
"type": "reference",
"extension": [
{
"url": "http://hl7.org/fhir/StructureDefinition/questionnaire-hidden",
"valueBoolean": true
},
{
"url": "http://hl7.org/fhir/StructureDefinition/questionnaire-referenceResource",
"valueCode": "Patient"
}
]
},
{
"linkId": "Q2",
"text": "What is your name?",
"type": "string",
"definition": "http://hl7.org/fhir/Patient#Patient.name.text"
}
]
}
The itemExtractionContext extension points to the question linkID of the question that has the target resource context in it.
This could be an item in the group, thus each iteration of the group would be considered another resource context, or at the root you can refer to a specific question to use.
Those following along...
I've drafted my thoughts in more detail on how my proposal for this would work, and hope to do a POC on it next week...
https://hackmd.io/@brianpos/definition-based-extract
For convenience link to the jira issue FHIR-41508
I don't understand point #2 - how can you have a Reference to something that doesn't exist yet (i.e. on a create)?
Point 2 indicates which property defines the resource ID. If the answer to that item has a value, then it indicates an update, if its empty, then its the create.
This is the key point to the approach.
It seems rather weird to me to need a question with an empty answer to support 'create'.
Its the absense of an answer, not an empty answer.
I guess if you don't have a value for the expression, then it is always a create. - maybe permit a boolean option just to permit its presence to indicate always create.
But then you still need to indicate the type of the resource that you want to create somwhere.
My inclination is to have the target profile to be the value of the expression and just have a question with the answer be the 'id' if there's an existing id. Reference is pretty complex. 'id' is simple.
Unless you're trying to support creating different instances on different servers?
Why would we use a simple string to store the reference to a resource to update when we have the reference datatype which is explicitly intended for that?
And we could also have finders to be used in a UI to permit selection by a user too?
target profile the result of an expression? That seems odd.
Sorry, meant extension, not expression. Whether 'Reference' makes sense sort of depends on whether a user is looking it up or whether you're finding the resource from a search based on population context. I'm expecting the latter to be more common
In either case, they can populate the reference with it, just as you would with pre-pop - and I have in the examples there.
I like that it re-uses existing capabilities too which could be very appropriate.
This would even support the selection of resources to maintain too!
e.g. Select some RelatedPerson resources and permit updates to them.
Another tracker that might help others implementing server side that also want to do some testing...
FHIR-48301
Here's the rough code that is in progress to implement this.
https://gist.github.com/brianpos/80587755f0f432f411918801e4f75aa3
Once I'm happy we have a decent story here it will move into my open source StructuredDataCapture package
https://github.com/brianpos/fhir-net-web-api/tree/develop/src/Hl7.Fhir.StructuredDataCapture
It has been pushed to https://fhir.forms-lab.com for testing with the fhirpath-lab (and anyone else that wants to try it out)
Currently working on the lab to make that experience a little better too.
Looking for others interested in testing/discussing the definition approach at the connectathon (and here)
@David Hay and I are getting some more reference examples together and finding a few rough edges in the spec.