AQL for getting a list of deleted compositions

Can I use AQL to get a list of deleted compositions?

regards

Iā€™m not an AQL user, but I think that in theory yes you should be able get them, through VERSION and its lifecycle_state attribute.
On the other hand I am curious about the use-case you have, and if some other REST API ways (which we donā€™t have yet) might suit better.

1 Like

Thanks. Any thoughts on what the path for lifecycle_state?.

The use case is for audit purposes to get a list of deleted compositions. If we cannot get this list, what is the purpose of maintaining the versions of a deleted composition? Unless we keep a list somewhere outside, we will never be able to know that they exist for any audit or forensics.

regards

That AQL I would guess it should contain something like:

....
FROM EHR e
    CONTAINS VERSION v [LATEST_VERSION]
        CONTAINS COMPOSITION c
WHERE 
    v/lifecycle_state/defining_code/code_string = 523
...

About the use-case, I think it sounds very much reasonable, and is exactly for what I was looking as a feedback to improve REST specifications, as alternative to get this data without the of AQL. For instance in this case a GET /ehr/{ehr_id}/composition?lifecycle_state=deleted (thus retrieve all deleted compositions) or a GET /admin/ehr/{ehr_id}/contribution?audit_details.change_type=deleted(admin-level get all contribution that were about content soft delete) might make some sense. Any suggestion ?

Thank you very much. I will try this out

As for you suggestions on REST APIs, I think they both are very good suggestions.

  1. GET /ehr/{ehr_id}/composition?lifecycle_state=deleted will be useful at runtime for audits and review in the context of a patient. However this can return an array of empty compositions(maybe even versioned compositionIds). Our current get composition API returns one composition. In fact as a general practice openEHR REST APIs seem to operate only on a single resource. So we may have to think of a new set of apis that operate on an array.
  2. GET /admin/ehr/{ehr_id}/contribution?audit_details.change_type=deleted This is another interesting idea for a system wide monitoring & administration. In fact this can be extended to include other change_types and also additional query params such as ehr_id to make it more generic. However the REST specs currently do not seem to have any admin APIs and so this has to be considered in the context of a broader admin functionality. Currently implementers such as EHRBase seem to have their own strategies around admin operations. Some level of standardization on this can also be considered

regards

1 Like

Hi,
On a related note,
As per specs, when we do a get on a deleted composition, we return 204 with no content. The response does not explicitly inform that the composition is deleted and the user has to infer that it is deleted from the null body response.

This, I feel is counter intuitive for users. Normally REST APIs either responds with 404 not found or in systems that version data, explicit message that it has been deleted(FHIR). Any thoughts on this?

regards

ā€œ204 No Content is returned when the resource identified by the request parameters (at specified version_at_time) time has been deleted.ā€

IMO there is nothing to infer, the rule is clear: 204 implies itā€™s deleted.

404 seems incorrect in this context since the COMPO exists.

Personally, I donā€™t see an issue with the current spec.

Though, if we would like to do GETs on deleted COMPOs and get some content, thatā€™s a new requirement. One workaround is that: if you have the VERSION.uid of the deleted COMPO, you could GET the previous version that will have content, and since the DELETE doesnā€™t change the content, thatā€™s the content of the deleted COMPO. A more secure way to get the previous version is to use the ā€œGet versioned COMPOSITION revision historyā€ endpoint. Another way would be to have an admin endpoint to read deleted COMPOs, this currently doesnā€™t exist AFAIK.

Hope that helps.

Best,
Pablo.

1 Like

For what itā€™s worth @Dileep, Iā€™m on your side on this!!

https://openehr.atlassian.net/browse/SPECITS-50

As @Pablo has said, strictly speaking, the 204 behaviour is correct, and I understand that FHIR does the same thing on a DELETE.

However, I and others have found that it does cause regular confusion in dev community, esp in the context of POSTs because the ā€˜minimalā€™ response header does allow no content to be returned, and ā€˜minimalā€™ has never been standardised.

The answer might be to add a ā€˜standardā€™ response type as a default, which requires some kind of minimal content to be returned, typically the ID of a new EHR or Composition, or the name of the committed Template and will therefore generate a 201.

Iā€™m not so sure about DELETE

but Iā€™d still favour some sort of ā€˜standardā€™ response that indicates that the Delete has been successful along with an explicit response and a 200. If people want to use minimal with no-content, thatā€™s fine but it really seems quite counter-intuitive for a lot of devs.

1 Like

If there is a requirement to explicitly get deleted locatables, COMPOs etc. I think the ADMIN API would be a better place than a GET in the normal API. My rationale is: with the current specs itā€™s clear in which conditions the GET returns No Content and that is for DELETED COMPOs. So if the contents of the DELETED COMPO are required, I would say the reason might be more for management/audit purposes than normal API interaction (CRUD), thatā€™s why I think the ADMIN API is a better place for this requirement. Though as said before, by using the previous version the contents can be retrieved (see my previous comment).

Iā€™m not sure why developers get confused around this, the spec IMHO is clear and unambiguous, it just needs to be read in full, and of course if there are doubts, there is a friendly community here to help out :slight_smile:

1 Like

Hi,
I fully agree that the specifications mention returning 204 for deleted compositions and since 204 specs does not allow content, our specs are conforming to the RFC. Where I beg to differ is if this response is self explanatory for all developers.

In that I believe that the specifications can be updated to make it more intuitive for app developers who consume and work with this API. I also believe that HAPI FHIRā€™s handling of the same situation is more elegant. It returns 410 Gone with a body with more details(screenshot attached) , which informs that the resource is Gone(different from 404) to the user.

This also aligns with the openEHR deletion strategy, where once deleted, the composition is not accessible via the GET and QUERY interfaces, which makes it literally gone for all practical purposes.

regards

(attachments)

2 Likes

That was not really what I was suggesting. For Posts/Puts it does make sense to me that we should (as default) expect the PII to return some sort of acknowledgement of success along with the ID of the created object.

For DELETE, a simple notification of suces as per the FHIR example, would be sufficient.

I know that 204 is ā€˜correctā€™ but like it or not quite a few of us are finding that it is confusing developers, particularly those increasing numbers who are not well versed in openEHR or the A:I. THey just donā€™t expect it to work this way, based on prior experience.

My suggestion is that we need to agree on ā€˜actualā€™ minimal content as the default response to most API calls. No-content 204 responses are still acceptable but as a choice.

The bigger problem here is that a deleted version does not technically contain a composition (v/data is empty for such a version), so this would return nothing. At least our (Better) implementation works that way. A further problem there is that you can not then query for, say, all deleted composition of a certain template_id, because there is no c/archetype_details/template_id/value. There is a trunk_lifecycle_state on a VERSIONED_OBJECT (like VERSIONED_COMPOSITION) though, see Common Information Model. (Itā€™s defined as a function, but we expose it as an attribute.) So you can do:

SELECT c
  FROM VERSIONED_OBJECT vo
  CONTAINS VERSION v[all_versions]
  WHERE vo/trunk_lifecycle_state/defining_code/code_string = 523

This, however, will give you all the versions of such compositions. You are probably only interested in the last version before the act of deletion, which we make possible in a non-standard way through is_last_version AQL function by adding another where condition is_last_version(s, includingDeleted = false).

3 Likes