Topics discussed:
- Nikolai's objection to the
$runparameter design was aesthetic and he said so: a Parameters resource is already a name/value pair, so passing query parameters as name/value pairs inside it means writing name, name, value — key-values stuffed into key-values. The alternative, an OperationDefinition per query the way FHIR's named queries work, felt too heavy and drags in min/max and other properties you don't want. It resolved when someone found that CQL's evaluate operation already types a parameter asParameters, even though Parameters is a resource type and not a data type. If it's an official hack it isn't a hack any more, so the decision was to align with CQL. Separately,SQL query $exportwas ticketed as the asynchronous counterpart to the synchronous$run. - Running arbitrary SQL safely is harder on some engines than others. Postgres has read-only connections natively — no DDL, no inserts, no index creation. Spark has nothing equivalent: you can tell DDL and DML apart from the logical plan, but plenty of things that are neither still have side effects, including arbitrary UDFs and calling Java methods through reflection. Hence a whitelist approach — enumerate what's allowed rather than chase everything that isn't — which is more work but fails safe. The suggestion was that the spec carry an implementation note warning about this, since it will hit every implementer immediately.
- Authorisation is the unsolved one. If your server enforces scopes at the top, that has to hold inside this operation too, and enforcing it on an arbitrary SQL query is not obvious. The Aidbox trick is to turn each query into an operation with its own endpoint and then apply access policies to that — which points at each query being its own operation rather than one generic one, except FHIR still has no standard way to say a custom operation is allowed. The other direction is view-level scopes: resource-type permission inherits to every view derived from that type, and you can narrow from there to specific de-identified views. Where it breaks down is combining a view permission with a row filter — you have access to the view, but should only see patient one's rows.
- A gap someone identified in SMART App Launch: there's no
group/scope, even though bulk export is group-scoped and research runs on cohorts of patients who consented. For the cohort app people have in mind — assemble ViewDefinitions, run SQL over them, apply permissions across the whole lot — that's the missing piece. The caveat raised is that a Group resource stops being usable once the cohort is large enough, so what you really want is criteria-based membership rather than a list, which few have implemented. - Security labels came up as an orthogonal layer that solves the sophisticated cases: tag the data, enforce the tags server-side, and because labels aren't bound to resource type you can express "hide all my mental health information" across everything at once. It's an extra layer of indirection that collapses into a simple query parameter at the end. The catch, as someone put it, is that all the complexity moves to whoever labels the data — you need a labelling service and a rules engine somewhere, and the classic test is that you can hide a depression diagnosis while the medications still give it away. Related: the Permission resource was maturity level zero in R5 and has vanished from the R6 build, part of a broader trend of moving immature things out of core into incubators.