Server v3.0.0#2635
Draft
johngrimes wants to merge 56 commits into
Draft
Conversation
Add viewReference support, Reference-typed patient/group with spec cardinality, Bundle unwrapping in the resource parameter, and 422 for semantically invalid ViewDefinitions on the run operation. Across the run, export, and sqlquery-run operations, reject an explicitly unsupported _format and the unsupported source parameter rather than silently ignoring them. Add a creation-time start timestamp to the async job for later export-manifest timing.
Support view.viewReference resolution to a stored ViewDefinition with per-part exclusivity and presence checks. Rewrite the completion manifest to the SQL on FHIR shape (exportId, status, echoed clientTrackingId and _format, export timing fields, and one output per view with name and location parts), dropping the Bulk Data-style fields. Return a Parameters kick-off acknowledgement for SQL on FHIR async operations while leaving the Bulk Data kick-off body unchanged.
…ery 422 Declare the SQL on FHIR spec canonical OperationDefinition URLs for the viewdefinition-run, viewdefinition-export, and sqlquery-run operations in the CapabilityStatement, and stop serving the Pathling-authored OperationDefinitions for them. Add a regression test pinning the existing 422 response for an unmappable FHIR column type under _format=fhir on sqlquery-run, and integration coverage for the source and _format rejections across all levels and transports.
Update the admin UI manifest parser to read the spec-shaped output location parts (one or more per output) instead of a single url part, emitting one download entry per file so a view that produced several files lists every file. Add an end-to-end check that an invalid custom ViewDefinition surfaces the 422 OperationOutcome message.
Update the run, export, and sqlquery-run operation docs for the new viewReference support, Reference-typed patient/group, Bundle unwrapping, the spec-shaped export manifest and kick-off acknowledgement, the source and unsupported-format rejections, the 400/404/422 status semantics, and the spec conformance canonicals. Credit the additional author on the significantly changed sqlquery providers.
Align the admin UI export end-to-end mocks with the new completion manifest: output download files are carried in location parts, and the non-spec transactionTime and requiresAccessToken fields are removed, so the card-listing tests exercise the location-reading parser.
Strip media-type parameters (e.g. text/csv;charset=utf-8) before matching an explicit _format value across the run, export, and sqlquery-run strict parsers, so a supported media type with parameters is treated as that format rather than rejected with 400, matching the spec's content-negotiation edge case.
The strict SQL validator's expression allow-list omitted the named and positional parameter placeholder expressions, so any parameterised query (using ":name") failed static validation. This blocked runtime parameter binding for $sqlquery-run even though the binding machinery was already present. Add NamedParameter and PosParameter to the allow-list. They are leaf, unevaluable value placeholders bound at execution time, so they carry no code-execution risk.
Implement the SQL on FHIR $sqlquery-export operation, the asynchronous counterpart to $sqlquery-run, at the system, type, and instance levels. Clients can run one or more SQL queries against materialised ViewDefinition tables in the background and download each result as files, following the FHIR Asynchronous Request Pattern. Each query produces one output. Table sources can be supplied at request time, inline or by reference, in addition to being read from server storage. Supported formats are NDJSON (default), CSV, and Parquet, with patient, group, and _since filtering. A failed query fails the whole export. To avoid duplication, extract the shared asynchronous-export machinery into a new operations/export package (a generic completion-manifest builder, a file writer, and a filtered data-source builder) reused by both export operations, and refactor $sqlquery-run onto a shared SqlQueryPipeline that the export also uses. The Admin UI gains an export affordance on the SQL query result card, backed by a reusable export-job card shared with the ViewDefinition export. The operation is declared in the CapabilityStatement against the spec canonical and gated by a new sqlQueryExportEnabled configuration flag. Resolves #2633.
Replace the boolean redirectOnComplete marker on the server's asynchronous machinery with an AsyncPattern enum (STANDARD_ASYNC_PATTERN, BULK_DATA), so the @AsyncSupported annotation reads as a deliberate choice between two named patterns rather than the presence or absence of one behaviour. Correct the Javadoc that misattributed the redirect-based completion to a "SQL on FHIR unify-async" specification, citing the HL7 Asynchronous Interaction Request Pattern instead. Behaviour is unchanged; the existing async tests pass with only their identifiers updated.
isAnyExportEnabled now also covers the SQL on FHIR asynchronous export operations, so the all-exports-disabled case must also disable the viewdefinition-export and sqlquery-export flags, both of which default to enabled.
The SQL on FHIR export integration tests added to the server module push the full build-and-test suite past the previous 30-minute job limit, causing the run to be cancelled before completion. Raise the timeout on the test, pre-release, and release server workflows so the suite has room to finish.
The disabled-operation assertion called doesNotContain on its own, which passes vacuously if the operation list is empty. Assert the still-enabled sqlquery-run operation is present first, so the test proves the list is populated and only sqlquery-export was dropped.
Resolves twelve Netty advisories reported against 4.1.133.Final, spanning HTTP/2 denial-of-service, TLS hostname verification bypass, and DNS resolver issues. All are fixed within the 4.1.x line at 4.1.135.Final, so no move to the 4.2.x series is required. The Netty BOM remains imported ahead of Spring Boot's so the pinned version continues to win.
Addresses CVE-2026-55471, an XML external entity vulnerability in XsltUtilities.saxonTransform via an unhardened Saxon TransformerFactory. HAPI FHIR 8.10.0 still bundles 6.9.4.1, so the existing override of org.hl7.fhir.r4 and org.hl7.fhir.utilities is raised from 6.9.7 to the patched 6.9.10.
Resolves a batch of react-router security advisories by moving to the latest 7.x release. None of the vulnerable code paths (RSC, SSR, data routers, the __manifest endpoint) are reachable from the admin UI, which uses declarative routing only, but upgrading is a low-risk minor bump that clears the findings and lets the react-router suppressions be removed from the Trivy ignore list.
Restore the server image's ability to run as either the FHIR server or a Spark Kubernetes executor, selected by the container's first argument. Spark on Kubernetes launches executor pods with the single argument "executor" and no command override, so the role selection lives in the image entrypoint. A Bash dry-run test covers the role-selection logic without Docker, a network, or a cluster.
Set the dispatching entrypoint as the image's entry behaviour in both the docker and dockerPreRelease profiles, copy it into the image via Jib extraDirectories with executable permissions, and remove the now-dead jvmFlags (Jib ignores them once an explicit entrypoint is set). Run the dispatch test during the test phase of these profiles, gated by skipTests.
The citation pointed to the Spark 4.0.0 entrypoint; the runtime is Spark 4.0.2, whose executor branch is identical.
Restore the dual-role server image for Spark on Kubernetes
The Varnish frontend cache previously inherited Varnish's default 60s first-byte timeout, which caused long-running synchronous Pathling queries to fail with a 503 before the server could respond. Expose the timeout as a PATHLING_FIRST_BYTE_TIMEOUT environment variable, substituted into the backend definition, and surface it through the Helm chart as pathlingCache.firstByteTimeout (defaulting to the previous 60s).
Introduce a recursive dependency resolver that turns a top-level query's relatedArtifact references into a topologically ordered graph of resolved ViewDefinition and SQLView nodes, disambiguating each reference (explicit type prefix, else ViewDefinition-first with a SQLView fallback) and deduplicating shared nodes. The executor materialises the graph bottom-up as request-scoped temp views, rewriting and validating each node's SQL before running the top-level query. A SQLQuery can now compose a stored SQLView.
Add resolver unit tests and end-to-end run coverage for the dependency-graph guarantees: a three-level nested chain resolves in topological order, a diamond shares its node once, the same label denotes different resources in different nodes without collision, and cyclic, self-referential, and over-deep graphs are rejected before any SQL executes.
A SQLView Library is now accepted as the top-level resource of $sqlquery-run and $sqlquery-export, at the system, type, and instance levels, executing as a parameter-less query. Supplying parameters with a parameter-less SQLView is rejected, as is a top-level Library whose type is neither sql-query nor sql-view.
With authorisation enabled, reading a ViewDefinition from storage now requires READ on ViewDefinition and reading a SQLView Library requires READ on Library, enforced at every storage-read seam - the standalone $view-run and $view-export operations, the $sqlquery dependency graph, and the top-level by-reference query - layered on top of the existing per-projected-resource checks. A resource supplied inline in the request body is exempt, as it is not read from storage.
Describe SQLView dependencies and top-level SQLViews on the run and export operations, the reference-resolution and disambiguation rules, the cycle/depth rejections, and the metadata-resource READ requirements. Document the maxDependencyDepth configuration option and the ViewDefinition/Library READ authorities, with the inline-versus-stored distinction. Mark authorship on the new and significantly changed files.
Import java.util.List and java.util.ArrayList in the dependency resolver and its test rather than referencing them inline, for a cleaner reading.
Add a stored SQLView Library bundle fixture (and empty variant) mirroring the existing SQLQuery fixtures, in preparation for surfacing SQLViews in the SQL query form.
Generalise the SQLQuery Library list into listStoredLibraries(typeCode), add the sql-view token filter, and expose a useSqlViews hook so the SQL query form can fetch SQLViews alongside SQLQueries. SQLQuery listing keeps its existing query key and behaviour by delegating to the shared core.
Replace the single Library picker with a grouped picker offering stored SQLQueries and SQLViews, omitting an empty group, and rename the read-only dependency heading from Tables to Views. A selected SQLView runs and exports through the unchanged stored path, resolved as Library/<id>.
On the Select query tab the Runtime parameter values section now appears only when the selected source declares parameters, removing the empty panel for SQLViews and param-less SQLQueries. The Provide SQL tab keeps the section always visible to anchor inline parameter authoring.
Rename the inline Tables editor to Views and let each row reference a stored ViewDefinition or SQLView through a grouped source selector. A collision-safe composite option value carries the source kind so the assembled query emits ViewDefinition/<id> or Library/<id> accordingly.
The stored query picker label changed from "SQL query library" to "SQL query source" when SQLViews joined it; point the export e2e helper at the new accessible name.
The inline editor's add-row, label, and source controls were renamed when SQLView references landed; update the inline-authoring e2e paths to match.
The module-level comment described the search endpoint as listing SQLQuery Libraries only; it now lists both SQLQueries and SQLViews.
The SQL on FHIR ViewDefinition model is a CanonicalResource, but Pathling's stored encoder model dropped its url and version on ingestion. Retain both as additive nullable elements so a ViewDefinition can be matched by its canonical URL when resolving SQL on FHIR dependency references.
A relatedArtifact.resource on a SQLQuery or SQLView is a canonical URL of a ViewDefinition or SQLView, matched against the referenced resource's url rather than decomposed into a logical id. Extract the shared url/version parsing and candidate selection into one helper reused by both the Library and ViewDefinition paths, resolve ViewDefinitions by filtering on the url column, reject non-canonical references at parse time, and reject ambiguous and unresolvable references with named errors. Request-supplied export views are matched and keyed by url, and a url-less supplied view is rejected. Bumps the server's Pathling core dependency to pick up the ViewDefinition url/version retention the resolution relies on.
…n UI The inline SQL authoring form now binds each table source to its canonical URL and emits that URL as relatedArtifact.resource on save, so queries authored in the UI resolve without manual editing. Sources without a URL are listed but disabled with an explanation, and a stored reference that matches no known source is surfaced verbatim with a not-found note.
Update the SQL query run/export documentation and runnable examples to reference ViewDefinitions and SQLViews by canonical URL rather than logical id, note that a referenceable view must carry a url (and that existing ViewDefinitions must be re-ingested), and describe the strict, ambiguous, and not-found error responses.
Align the inline picker's disabled-source note with the wireframe's spaced hyphen instead of an em-dash.
The spring-boot:run goal launched the server without --add-opens=java.base/sun.util.calendar=ALL-UNNAMED, so Spark's date conversion failed with an IllegalAccessException whenever a response contained date values (for example a $sqlquery-run returning date columns). The production entrypoint and the test configuration already supplied this option; only the local run path had drifted. Centralise the server JVM module options into the pathling.runtime.jvmModuleOpts and pathling.test.jvmModuleOpts properties so the run, surefire and failsafe configurations share a single definition, and note the coupling with the production entrypoint that a shell script cannot reference at runtime.
The result card left the "Submitted SQL" section blank when running a stored SQLQuery or SQLView, because the page only captured the SQL text for inline requests. The form already resolves the selected library's SQL, so carry it on the stored request (for display only, since the server still receives just the reference) and recover it through a shared request-to-SQL helper. The helper also decodes the Base64 content as a fallback for inline requests lacking a sql-text extension.
The result card rendered the submitted SQL in an unbounded box, so a long query stretched the card far down the page. Extract the existing SQL preview into a shared, height-bounded component with a copy control and reuse it for both the stored-query preview and the submitted SQL echoed in result and error bodies.
Render each referenced view on a single line, clipping overflow with an ellipsis and surfacing the full reference in a tooltip. Allow the form column to shrink so it shares width evenly with the results column rather than being held open by long references.
The static SQL validator walked only a plan's children, but a WITH node exposes its CTE definition bodies as innerChildren. Relation references inside a CTE body were therefore never checked against the declared-label set. An undeclared table named only inside a CTE (such as an OMOP vocabulary table) slipped past validation and surfaced as an opaque 500 from Spark's analyser instead of a clean rejection. Descend into CTE bodies during the strict walk so these references are rejected early with the same "undeclared table" message as top-level relations.
The SQL validator enforces a strict allow-list of expression types. The || concatenation operator parses directly to a Concat expression rather than an UnresolvedFunction, so it was rejected as a disallowed expression even though the equivalent concat() function call was permitted as a built-in. Add Concat to the allow-list so the two spellings behave consistently.
The string-based url and version setters and the null and empty branches of the corresponding getters, copy, and isEmpty logic were not exercised, dropping new-code coverage below the SonarCloud quality gate threshold. Add unit tests covering these paths.
Support SQLView resources and view composition in SQL on FHIR operations
Bumps jackson-databind to 2.22.0 to address seven advisories (CVE-2026-54512 through CVE-2026-54518). The existing Jackson version pin was being silently overridden by Spring Boot's managed version because the Jackson BOM was imported after spring-boot-dependencies; moving it ahead lets the pin take effect, since the first BOM import wins in Maven.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.