.. _releases: Release notes ============= .. note:: openFHIR Sandbox is usually on latest version of openFHIR. To see the exact version of the sandbox, go to https://sandbox.open-fhir.com Release 3.0.2 (2026-10-03) -------------------------- Added ^^^^^ * Karolinska / INCA mapping suite (``engine-enterprise/src/test/resources/karolinska``): FHIRConnect mappings for the Region Stockholm chemotherapy ordination and administration templates (and the MDK recommendation) to the RCC ``INCA läkemedel`` FHIR IG 0.5.0 Bundles, with bidirectional, coverage, repetition, synthetic round-trip and IG profile-validation tests; decisions, open questions and engine proposals in its ``README.md`` * profile validation against a client IG in tests uses ``hapi-fhir-validation`` (test scope only) * the INCA Bundle profiles need ``contained_to_separate_bundle_entry = false`` on the tenant (closed ``Bundle.entry`` slicing) * every code translation is a local ConceptMap (``terminology/*.json``) rather than inline terminology or a system-rewriting ``manual``: Cytodos route and form, MDK treatment intention and timing, the openEHR ISM state to FHIR ``status`` table, and ``"*"`` system-only rewrites for ATC and ICD-10. The tenant needs the ``terminology`` licence option * ``karolinska.postman_collection.json`` loads the whole suite into a running engine over REST and maps the client's own compositions through it; regenerate with ``gen_postman_collection.py`` beside it. It ships without credentials: set ``client_id`` / ``client_secret`` in Postman per customer, or bake them into an uncommitted copy with ``--client-id`` / ``--client-secret`` (or the ``OPENFHIR_CLIENT_ID`` / ``OPENFHIR_CLIENT_SECRET`` environment variables) * queue support: the engine can subscribe to Kafka topics carrying FHIR payloads and/or openEHR compositions (mixed in one topic or one topic per kind), translate each message and publish the result to another topic (``OPENFHIR_MESSAGING_ENABLED``, see :doc:`messaging`) * needs the new ``messaging`` license option; enabling it without one fails startup. Existing licenses do not carry it and must be re-issued * the tenant is fixed per subscription; the result is the bare Bundle / composition, with status, issues (``OperationOutcome``) and the source position in ``openfhir-*`` headers * delivery is at-least-once: caller errors are dead-lettered straight away, transient failures are retried with backoff and then dead-lettered, and the subscription keeps consuming * ``GET /status`` reports ``messaging.enabled`` and, per subscription, its state and processed / partial / dead-lettered counters * operational templates can now be resolved directly from an integrated openEHR CDR instead of being uploaded into the engine (``OPENFHIR_CDR_ENABLED``, see :doc:`integrations`), making the CDR the single source of truth * supports no authentication, HTTP Basic and OAuth2 client credentials; only ADL 1.4 templates are fetched, and the engine never writes to the CDR * when enabled, the local template store is not consulted for mappings: ``POST/PUT/DELETE /opt`` return ``409``, ``GET /opt`` returns an empty array, and ``*.opt`` files are skipped by the bootstrap scan * a CDR outage fails the mapping request with a clear error instead of falling back to a stale local template * configurable globally or per tenant through the ``cdr_opt_source`` tenant property * ``POST /opt/$refresh?templateId=...`` evicts a cached template cluster-wide so it is re-fetched; ``GET /status`` reports ``cdr.enabled``, ``cdr.baseUrl`` and ``cdr.reachable`` .. note:: Set a finite ``OPENFHIR_CACHE_OPT_TTL`` when enabling this — the default ``-1`` never expires and there is no local upsert to evict on. * updated dependency on `open-fhir-core `_ * a runtime failure inside a single mapping no longer fails the whole ``$tofhir`` / ``$toopenehr`` request as an opaque ``500``: it is reported as an ``OperationOutcome`` issue of severity ``error`` naming the model mapper, archetype, mapping and the openEHR/FHIR paths being processed; the remaining mappings still run and the partial result is returned (see :doc:`restful_apis`). The issue ``code`` is ``processing`` / ``structure`` when the cause is yours to correct (the message is echoed), and ``exception`` for an engine fault, where ``diagnostics`` carry a reference id and the detail stays in the engine log * ``OPENFHIR_OPERATIONS_OUTCOME_VERBOSITY`` controls what the ``$tofhir`` / ``$toopenehr`` ``OperationOutcome`` carries: ``all`` (default), ``errors`` (failed mappings only) or ``none`` (no ``OperationOutcome``), so the response stays small for inputs that skip many elements; the engine log is unaffected * ``$tofhir``: a ``fhirCondition`` whose ``targetRoot`` is the mapped CodeableConcept's ``coding`` (or the mapped Coding itself) now selects which of a ``DV_CODED_TEXT``'s codings — its own code and its TERM_MAPPING targets (``_mapping:N/target``) — are written, with the same ``one of`` / ``not of`` condition that already filters codings in the ``$toopenehr`` direction; it used to be a no-op outbound. Matched after terminology translation, so the criteria are FHIR systems (``http://snomed.info/sct`` after a ``"*"`` passthrough ConceptMap). A selection, not a gate: when no coding satisfies the condition the codings are written unchanged. See :doc:`fhirconnect`, "Selecting a coding with fhirCondition" Changed ^^^^^^^ * ``GET /status`` masks the values of secret-looking properties (``password``, ``secret``, ``jaas``, ``token``, ``key``, …) and the password of credentials embedded in a URI as ``******``; the endpoint is unauthenticated and used to print them in clear (see :doc:`restful_apis`) * ``POST /terminology/fhir/ConceptMap`` now returns the stored ConceptMap (with its assigned ``id``) as ``application/fhir+json`` in the ``201`` response, the same way ``PUT`` and ``GET`` serve it; the ``Location`` header is unchanged * updated dependency on `open-fhir-core `_ * the legacy ``/openfhir/*`` endpoints fail fast on the first failed mapping and return the same descriptive message as their ``400`` text body * ``$toopenehr`` failures inside custom mapping code are no longer swallowed and only logged; they are reported like any other mapping failure, and a mapping code that is not registered or declines to map is reported as a warning * ``$tofhir`` nested mappings (``followedBy`` / ``reference`` / ``slotArchetype``) now report their warnings; they used to be lost * a FHIRPath expression in a model mapping that cannot be evaluated in the ``$toopenehr`` direction (unknown function, malformed condition path, unresolvable ``resolve()``) is reported as a ``warning`` / ``incomplete`` issue naming the mapping, the expression and the FHIRPath engine's message, instead of only a log line * the ``$toopenehr`` "matched the mapping criteria but nothing could be mapped" warning is now raised only when a mapping found no data at its FHIR path or its data produced no openEHR value; it names those mappings with their FHIR paths, the model mapper and archetype, and quotes the FHIR JSON of the element they were evaluated on (truncated at 2000 characters). Elements a mapping was never meant to match (a slot rejected by its mapper's preprocessor condition, a reference of another resource type, a filtering condition that matched nothing, a manual FHIR-value mapping) no longer produce a warning, so a Bundle fanned out over several slot mappings is no longer reported once per slot per entry Fixed ^^^^^ * terminology service: a ConceptMap translation now picks the ``group`` by the coding's system alone. Groups whose ``source`` matches the system (and ``target`` the requested target system) are used exclusively; the lookup by code across all groups only runs when no group matches by system. Previously both were OR'd together, so a code that is identical on both sides of a bidirectional map (the same SNOMED CT id under two terminology ids) matched the forward and the reverse group at once, logged ``More than one mapped entry found``, and resolved to whichever group came first in the document — one direction was always wrong. See :doc:`terminology`, "How a ConceptMap is resolved" * a ``"*"`` (system-only) translation keeps the source coding's display instead of returning none: ``$tofhir`` keeps ``coding.display`` and the openEHR return leg keeps ``|value``, so an open code set (ATC, ICD-10) whose ``terminology_id`` differs from the FHIR ``system`` can be mapped with a two-group ``"*"`` ConceptMap instead of a ``manual`` system rewrite (needs the ``open-fhir-core`` change below) * ``$translate`` with a ``sourceCodeableConcept`` returns the translated codings; it used to return the input codings unchanged, and read the wrong request parameter * on PostgreSQL a ConceptMap larger than 4096 characters could not be stored — ``POST /terminology/fhir/ConceptMap`` failed with ``500`` ``value too long for type character varying(4096)``. The column is now ``text`` (Flyway migration ``V10``, applied automatically on start-up) * every entry of a produced Bundle now carries a ``fullUrl`` and a legal resource id, regardless of the ``contained_to_separate_bundle_entry`` tenant property. With the property set to ``false`` — required when a profile's Bundle slicing is closed — entries used to come out with no ``entry.fullUrl`` at all, and a resource created behind a ``resolve()`` kept the internal ``#`` id it is instantiated with, which the HL7 validator rejects as ``Invalid Resource id`` and ``bdl-*``. The leading ``#`` is now stripped and a missing ``fullUrl`` is set to ``urn:uuid:``; an id that is already absolute is used as the ``fullUrl`` as is, and resources nested behind a reference keep their local ``#`` reference so they stay contained. ``transaction`` and ``batch`` Bundles are left alone, since their entries are addressed by ``entry.request.url``; every other type is normalised, including a Bundle whose ``type`` a root mapper writes through a ``manual`` — that value reaches the output but not the instance the post-processor inspects * updated dependency on `open-fhir-core `_ * the populators hand the source coding's display to the terminology translator, so a system-only translation no longer loses it (``TerminologyTranslatorInterface`` gained ``default`` display-carrying overloads; existing translators keep working unchanged) * ``$tofhir``: a TERM_MAPPING target whose ``target|terminology`` carries a version (``http://snomed.info/sct@20240101``) now yields a coding with that ``version``, as the element's own code already did * ``$toopenehr``: the additional codings of a CodeableConcept are written as TERM_MAPPINGs under the flat key ``_mapping:N|match``; the engine wrote ``_mapping:N/match``, which the flat format does not know, so the TERM_MAPPINGs came out with ``match: "?"`` (unknown). They now carry ``match: "="`` (equivalent) — check any consumer that keyed on ``?`` * ``$toopenehr`` of a FHIR enumeration (``MedicationAdministration.status`` and the like) into a ``DV_CODED_TEXT`` / ``CODE_PHRASE`` now takes ``|value`` from the display of the mapping or ConceptMap target, so an ISM state mapped ``completed -> 532`` comes out as ``|code: 532``, ``|value: completed``. Where the translation names no display, ``|value`` falls back to the translated **code**, and only to the enumeration's own value when nothing was translated — a mapping of ``permit -> at0035`` with no term still yields ``|value: at0035``, never the untranslated FHIR token * a bare resource posted to ``$toopenehr`` (not wrapped in a Bundle) is now mapped as documented when its type matches the one the mapping starts from, instead of returning an empty Composition; previously this only worked for model mappers without a preprocessor FHIR condition * a mapping request naming an operational template that was never uploaded now returns ``400`` with an ``OperationOutcome`` naming the template, instead of ``500`` with a ``NullPointerException`` * input that contains none of the resource type a template starts from (for example a lab report mapping given an ``Observation`` but no ``DiagnosticReport``) is now reported as a warning with an empty result, instead of failing with ``Index 0 out of bounds for length 0`` * a non-repeating hierarchy node in a model mapping no longer fails with ``Range [0, -1) out of bounds`` * an operational template that is stored but no longer parses is reported as ``500`` naming the template, separately from the missing-template case * unexpected errors on the ``$tofhir`` / ``$toopenehr`` operations no longer echo internal exception text back to the caller; the response carries a reference id and the detail stays in the engine log * an ``openehrCondition`` can now narrow on an attribute of an RM data value (``DV_*``) that the flat format represents as a pipe attribute, written as the RM path the same way a ``DV_CODED_TEXT`` is narrowed on ``defining_code/code_string``: ``DV_IDENTIFIER`` (``targetAttribute: "type"``, ``"issuer"``, ``"id"``, ``"assigner"``), ``DV_QUANTITY`` and the other quantified types (``"magnitude"``, ``"units"``, ``"precision"``, ``"numerator"``, ``"denominator"``), ``CODE_PHRASE`` (``"code_string"``, ``"terminology_id"``), ``DV_TEXT`` (``"formatting"``, ``"language"``, ``"encoding"``), ``DV_ORDINAL`` (``"ordinal"``, ``"symbol"``) and the encapsulated types (``"formalism"``, ``"media_type"``, ``"size"``, ``"charset"``, ``"uri"``); each may also be spelled out through the element's value (``"value/type"``). Such a condition used to exclude every occurrence of the targeted element, so a cluster holding several identifiers could not be narrowed down to one of them — for example selecting only the HSA id out of a care unit that also carries an organisation number. Where the flat name differs from the RM one the mapping is applied (``units`` → ``|unit``, ``code_string`` → ``|code``, ``terminology_id`` → ``|terminology``, ``media_type`` → ``|mediatype``) * ``$tofhir``: a mapping whose FHIR path walks *through* a single-valued element that an earlier walk already built — a sibling mapping, or an earlier occurrence of the same one — now continues into that element instead of replacing it, so what was there is kept. A repeating openEHR element mapped to ``$resource.code.coding`` yields one ``code`` carrying all its codings rather than only the last, and a ``manual`` on ``$resource.identifier.system`` no longer discards the ``identifier`` a sibling mapping filled, so a ``type: NONE`` parent is no longer required to merge them (it remains the order-independent way). Lists still append on every walk, and a Reference is still replaced when walked through (a ``$reference`` mapping, or a path continuing with ``resolve()``), so an identifier-only Reference is still superseded by the resolved one. Check existing mappings for a writer that was *redundant* with an earlier one — it was masked by the replacement and now adds a second entry, e.g. a ``manual`` adding the ``KVZ10`` type coding to an identifier whose ``DV_IDENTIFIER`` already carries that type; guard such fallbacks with an ``openehrCondition`` (``targetAttribute: "type"``, ``operator: "empty"``) Release 3.0.1 (2026-09-09) -------------------------- Changed ^^^^^^^ * bumped OSS version to 3.0.1 to incorporate fixes made in OSS https://github.com/openFHIR/openfhir/releases/tag/3.0.1 Release 3.0.0 (2026-09-04) -------------------------- Changed ^^^^^^^ * terminology concept maps are now bootstrapped by the same scan as model mappers, context mappers and operational templates, instead of by a separate runner that applied each file only once, ever * editing a bootstrapped concept map and re-scanning now updates it in place under the same id, and an unchanged one is skipped — the create / update / skip semantics the other three file types already had * ``POST /$bootstrap`` now picks up ``*.json`` files, and concept maps appear in its summary counts and per-file breakdown; previously they were skipped silently * ``GET /health`` readiness now covers the concept-map part of the startup scan as well * concept maps are only bootstrapped when the license includes the ``terminology`` option; without it ``*.json`` files are skipped and the rest of the scan is unaffected * a concept map and a mapping file that share a name in different sub-folders no longer adopt each other's ledger entries * migration (Postgres ``V9`` / Mongock ``V7``) tags the ledger entries written by the previous terminology runner, so concept maps bootstrapped before this release are recognised and updated in place on the first scan after the upgrade rather than being re-created * updated dependency on `open-fhir-core `_ to **3.0.0** * bootstrap extension points widened so a distribution can add its own bootstrapped file types; no behaviour change in core Release 2.2.3 (2026-08-17) -------------------------- Added ^^^^^ * ``POST /$bootstrap`` endpoint for re-running the bootstrap directory scan without restarting the engine; returns a summary of created, updated, unchanged and failed files, and ``409 Conflict`` if a scan is already in progress * ``GET /bootstrap`` endpoint returning the bootstrap ledger of the logged-in user: which files have been bootstrapped, from which path, and which entity each one created Changed ^^^^^^^ * updated dependency on `open-fhir-core `_ to **2.2.5** * bootstrapped files are now tracked by content hash and re-applied in place under the same entity id when their content changes, instead of being bootstrapped only once; unchanged files are skipped and new files are created * bootstrap ledger entries are keyed by the file path relative to the bootstrap directory, so identically named files in different sub-folders no longer collide * ``GET /health`` now returns ``503 STARTING`` until the startup bootstrap scan completes and ``200 UP`` afterwards, making it usable as a "safe to send traffic" gate * ``unidirectional`` can now be declared in the header (``spec``) of a mapping file, applying to the whole file; a ``unidirectional`` on an individual mapping still takes precedence * added support for mapping openEHR ``PARTY_PROXY`` data types, to and from a FHIR ``Reference`` and ``Identifier`` * dose and rate Ranges (``DV_INTERVAL``) are no longer dropped from ``dosage.doseAndRate`` * values no longer leak between FHIR list entries when repeated slot archetypes feed the same list * corrected administration duration for minute-denominated infusion rates * non-daily and weekly dosage schedules are now reconstructed as ``timing.repeat`` instead of appearing only as text in ``dosage.text`` * openEHR ``null_flavour`` on an ELEMENT is now reconstructed as a FHIR ``data-absent-reason`` extension on the primitive it maps to * resolved a ``NullPointerException`` on conditions that had not been amended against a web template * sub-directories whose name ended in ``.yaml``, ``.yml`` or ``.opt`` are no longer processed as mapping files themselves * KDS v1.0 mappings added to the test suite, covering the composition mappings against the FhirConnect v1.0 release * the bootstrap ledger is now tenant-scoped, so ``GET /$purge`` clears the bootstrap entries of the logged-in user's tenant as well, meaning that tenant's bootstrapped files are created again on the next startup Release 2.2.2 (2026-06-16) -------------------------- Changed ^^^^^^^ * updated dependency on `open-fhir-core `_ to **2.2.4** * added support for hardcoded AQLs via the ``_query`` option in context mappings, allowing predefined AQLs to be returned directly when an incoming ``toAql`` request matches a defined rule (rules support matching on operations such as ``$summary``, on resources with query parameters such as ``Observation?category=height``, and on resource-only matches). See :doc:`AQL Generation & Configurable Queries ` * added support for mapping openEHR ``DV_ORDINAL`` data types * corrected AQL path generation for ``CodedText`` and ``CodePhrase`` coded data points * deprecated fields (such as ``fhirCondition`` and ``criteria``) are now excluded from model mapping serialization Added ^^^^^ * certain RESTful endpoints required by the Atlas 2.0.0 Release 2.2.1 (2026-05-19) -------------------------- Changed ^^^^^^^ * updated dependency on `open-fhir-core `_ to **2.2.2** * resolved issue with ad-hoc Composition generation when sections had names resulting in empty AQL paths * ``fhirCondition`` operators ``one of`` and ``not of`` now evaluate correctly even with matching subpaths * ``fhirCondition`` operator ``type`` now functions as a filter in mappings rather than only conditioning entire operations * ``spec.fhirConfig.structureDefinition`` now implicitly validates incoming resource types during FHIR→openEHR conversions * added ``coded_text_value`` leaf type support when multiple type options exist * improved RM type propagation when mappings contain only ``manualMappings`` as children * corrected population of coded text manual mappings when field type is ``TEXT`` * implemented post-processing logic ensuring Bundles conform to ``document`` type with required profiles and identifiers (IPS) * added narrative generation templates for medical devices and procedures * initial implementation for openEHR ``DV_PARSABLE`` data type (assumes ``text/html`` formalism) * docker image now supports nonarm cpus Release 2.2.0 (2026-05-04) -------------------------- .. warning:: **Breaking change:** all openFHIR-specific configuration properties are now required to be nested under the ``openfhir.`` key. The following properties must be updated in your ``application.yaml`` or environment variable configuration: .. list-table:: :header-rows: 1 :widths: 50 50 * - Old key - New key * - ``db.type`` - ``openfhir.db.type`` * - ``bootstrap.dir`` - ``openfhir.bootstrap.dir`` * - ``bootstrap.recursively-open-directories`` - ``openfhir.bootstrap.recursively-open-directories`` * - ``protected`` - ``openfhir.protected`` * - ``license`` - ``openfhir.license`` * - ``terminology.*`` - ``openfhir.terminology.*`` * - ``app.cluster.*`` - ``openfhir.cluster.*`` Added ^^^^^ * ``GET /status`` now returns additional diagnostic information: * ``properties`` — all configuration properties the engine is currently running on, allowing operators to verify that properties were properly picked up * ``cache`` — per-cache entry counts and configured TTL for ``fhirConnect``, ``opt``, and ``tenant`` caches * database indexes for both MongoDB and PostgreSQL, significantly improving query performance * ``DELETE /opt/{id}`` endpoint for deleting Operational Templates * ``DELETE /fc/model/{id}`` endpoint for deleting FHIR Connect model mappers * ``DELETE /fc/context/{id}`` endpoint for deleting FHIR Connect context mappers * Cross-version FHIR support: openFHIR now supports mapping to and from STU3, R4, R4B, and R5 within a single deployment. The target FHIR version is declared once in the FHIRConnect context mapping (``spec.version``) as per the FHIRConnect spec. No changes are required for existing R4 mappings. New mappings targeting other versions simply declare ``spec.version: STU3`` (or ``R4B`` / ``R5``) in their context file. * narrative generation as a programmed mapping (``mappingCode: "generateNarrative(entry, profile)"``), allowing HTML narratives to be produced for FHIR resources during openEHR → FHIR mapping Fixed ^^^^^ * ``GET /opt/{id}``, ``GET /fc/model/{id}``, and ``GET /fc/context/{id}`` now return ``404 Not Found`` when the requested resource does not exist, instead of ``200`` with an empty body * GET ``/opt?templateId=`` now properly filters by a templateId (before it returned all operational templates) * ``IParser`` (HAPI FHIR) instances are no longer shared across threads; a new parser is created per call via ``FhirContext.newJsonParser()``, resolving a thread-safety issue under concurrent load Changed ^^^^^^^ * updated dependency on `open-fhir-core `_ to **2.2.1** * all openFHIR-specific configuration properties are now nested under the ``openfhir.`` key (see breaking change above) * caching now defaults to infinite TTL (``-1``) instead of 300 seconds; entries are evicted explicitly on upsert Performance ^^^^^^^^^^^ * performance benchmarks conducted across 6 hardware configurations show improvements compared to 2.1.0: * throughput improved by **11.6% – 36.7%** across all configurations * mean response time improved by **5% – 72%** across all configurations * error rates improved in 5 of 6 configurations (up to 50% reduction) * most notable gains on PostgreSQL with 4 CPUs / 8 GB memory: mean response time reduced by 72%, max response time from 30s to 6s Release 2.1.0 (2026-04-07) ---------------------------------------- .. warning:: **Breaking change:** a ``preprocessor.fhirCondition`` that previously caused a mapping to be applied in the openEHR → FHIR direction will no longer do so (`#35 `_). If your mappings relied on this behaviour, an explicit manual mapping must be added to reproduce the previous result. Added ^^^^^ * ability to collect execution metrics * performance benchmarks were conducted on this release across 8 hardware configurations. Results show more than 20× improvement in mapping throughput and latency compared to previous versions. See :doc:`Performance ` for the full analysis. * ability to set up openFHIR Enterprise in a HA mode. See :doc:`High Availability ` Fixed ^^^^^ * performance optimizations, increasing performance results by approximately 20x compared to previous version * `criteria` are properly evaluated when multiple (previously only 0th criteria was evaluated) * preprocessor fhircondition no longer results in a mapping going openehr->fhir [#35](https://github.com/openFHIR/openfhir/issues/35) Changed ^^^^^^^ * updated dependency on `open-fhir-core `_ to **2.1.0** * `bootstrap.recursively-open-directories` now defaults to true, meaning openfhir engine will go through all directories and subdirectories of the bootstrap location to find mappings and contexts Release 2.0.4 (2026-03-23) -------------------------- Changed ^^^^^^^ * updated dependency on `open-fhir-core `_ to **2.0.5** Added ^^^^^ * ``CodedText`` <> ``Enumeration`` mapping * terminology is properly handled when terminology is added in extension model mapping (do note that merging of terminology doesn't work yet, meaning it can't be present both on core and on extension model mapping and the one set in extension will be applied) * IPS postprocessor for IPS composition mappings * DV_TEXT can implicitly be mapped to/from DV_CODED_TEXT Fixed ^^^^^ * when mapping to FHIR ``Enumeration`` that's a List (like ``AllergyIntolerance.category``), this is now properly mapped and serialized (previously HAPI serialization was throwing errors) * criterias are properly evaluated when multiple (previously only 0th criteria was evaluated) * some terminology bugs when the right system wasn't found when mapping from FHIR bound codes (without a system) Release 2.0.3 (2026-03-21) --------------------------- Changed ^^^^^^^ * updated dependency on `open-fhir-core `_ to **2.0.3** Added ^^^^^ * ``DV_TEXT`` now maps to ``CodeableConcept.text`` * ability to transform discrete ContentItems on the fly * EHR ID is now replaced with the EHR ID coming in the request during ``toAql`` translation * IPS tests Fixed ^^^^^ * manual mappings may produce duplicate results due to incorrect manual mapping construction * FHIRPath with FHIR conditions was in some cases wrongly constructed, resulting in missing mappings * ``$reference`` can now be suffixed with further AQL path when necessary * AQL generation now falls back to archetype-only AQL when no param matches * logging when something goes wrong in ``toAql`` now works correctly (previously stacktrace was not logged) Release 2.0.2 (2026-03-15) --------------------------- Changed ^^^^^^^ * updated dependency on `open-fhir-core `_ to **2.0.2** Added ^^^^^ * tests for toAql translation * ability to translate separate ContentItems not necessarily the whole Composition Fixed ^^^^^ * toAql now properly exposed via RESTful API (``/openfhir/toaql``), but still a BETA feature Release 2.0.1 (2026-03-14) --------------------------- Changed ^^^^^^^ * updated dependency on `open-fhir-core `_ to **2.0.1** Added ^^^^^ * BETA feature of translation of FHIR Search to AQL (see https://github.com/openFHIR/openfhir/discussions/12) * ``GET /status`` endpoint now returns a JSON response with ``engineVersion`` and ``openFhirVersion`` fields Fixed ^^^^^ * when a duplicate OPT is trying to be created, server now responds with 400 not 500 * fixed ``DV_TEXT`` (String) to CodeableConcept mapping (now maps to ``CodeableConcept.text``, before it didn't map at all) * when there is more than 1 possible rmType, engine now correctly finds the right one (when openEHR -> FHIR, this is done by deducing rmType based on the data; when going FHIR -> openEHR it is based on FHIR type) Release 2.0.0 (2026-03-06) --------------------------- .. important:: with this version of openFHIR, docker images changed from `openfhir/openfhir` to **openfhir/openfhir-enterprise**. Old image name now reflects the open sourced version of openFHIR. Added ^^^^^ * documented overview of enterprise vs open source features (:doc:`enterprise`) Changed ^^^^^^^ * improvements throughout the codebase, reflecting in a new open source version (https://github.com/openFHIR/openfhir) as well as this one now tightly related to the open sourced one * image name changed on dockerhub from `openfhir/openfhir` to **openfhir/openfhir-enterprise** Fixed ^^^^^ * trying to persist a duplicate operational template now responds with 400 instead of 500 Release 1.2.9 ------------- Fixed ^^^^^ * fixed bug where openEHR to FHIR mappings produced too many resources when mappings were referenced both from ``slotArchetype`` as well as from the content of a ``start`` archetype * fixed ``PUT /terminology/fhir/ConceptMap/{id}`` returning ``201 Created`` instead of ``200 OK`` on update Release 1.2.8 ------------- Added ^^^^^ * enhanced Terminology API with additional endpoints for ConceptMap management: * ``GET /terminology/fhir/ConceptMap`` now supports searching all ConceptMaps without a URL parameter, returning a properly structured FHIR Bundle with type ``searchset`` * support for searching ConceptMaps by canonical URL using ``?url=`` query parameter * proper support for ``context.start`` field in context mappers (see `#160 `_) * the ``start`` field now correctly identifies which archetype within the composition content should be used as the starting point for mapping * previously, the engine would ignore the context.start and map directly from the root or from the content Fixed ^^^^^ * fixed bug in Terminology API where ``GET /terminology/fhir/ConceptMap`` without parameters would fail to return all available ConceptMaps * fixed ``openEhrCondition`` not being applied correctly in manual mappings (see `#168 `_) .. warning:: **Breaking Change:** The proper enforcement of ``context.start`` may cause existing mapping files to fail if they specify an incorrect or non-existent start archetype. If your mappings break after upgrading, look for the following log entry: .. code-block:: text context.start archetype '' not found within composition content. Available starts are: To fix this, update your context mapper's ``context.start`` field to match one of the available archetypes listed in the error message. Release 1.2.7 ------------- Added ^^^^^ * support for mapping XhtmlNode elements Fixed ^^^^^ * root archetypes within a template are now part of mapping as well and not skipped Release 1.2.6 ------------- Added ^^^^^ * support for custom date range for multiple resources, courtesy of psyp1x (see: https://github.com/medblocks/openFHIR/issues/89) * support for NullFlavours, courtesy of psyp1x (see: https://github.com/medblocks/openFHIR/issues/93) Fixed ^^^^^ * fixed behavior when a mapping of type `reference` was a followedBy mapping with a different openehr path than the parent, which in some cases caused data points to be overwritten Release 1.2.5 ------------- Fixed ^^^^^ * release 1.2.4 introduced a change that contained Resources were separate Bundle entries, however placeholder references had a prefix of `#`. This has been changed now and placeholder references behave according to: https://smilecdr.com/docs/fhir_standard/transactions.html#placeholder-ids Release 1.2.4 ------------- Added ^^^^^ * tenant entity in the database for tenant-specific configuration; this comes together with a CRUD on `/tenant` endpoint, protected by users that have `tenant.crud` scopes * configurable behavior per-tenant whether Resources created as part of `$reference` mapping (https://sevkohler.github.io/FHIRconnect-spec/build/site/FHIRconnect/v1.0.0/types-of-mappings/concept-type/Reference.html) are included as contained Resources or separate bundle entries. Default behavior (and that of sandbox) is that Resources are now included as separate Bundle entries, which is different than how engine behaved up until now Fixed ^^^^^ * when OPT is updated through a RESTful API, cache is cleared up, fixing an issue of stale OPT being used for mapping (restart of an engine is still required is OPT is updated directly in the database) Release 1.2.3 ------------- Added ^^^^^ * ability to use FhirPath concatenation when going openEHR -> FHIR, for example suffixing ``fhir: "$resource.context.related.reference & '^^^^urn:ihe:iti:xds:2016:studyInstanceUID'"`` or prefixing ``fhir: "'prefixOfInstitution'&$resource.custodian.as(Reference).display"`` * ``/openfhir/tofhir`` can now handle array of Compositions in a canonical format, rather than just a single one. When an array is provided, openFHIR expects payload to be an array of Compositions in a canonical format (not flat) and of the same template (if they're not, they will all attempted to be mapped base on a templateId on the 0th Composition in the array). Results of mappings from those multiple compositions will be added to the returned Bundle.entries. * support Identifier to String, see: https://github.com/medblocks/openFHIR/pull/140 (thanks @subigre) Fixed ^^^^^ * when Insights fail, they fail gracefully now and dont impact successfulness of a mapping Release 1.2.2 ------------- Added ^^^^^ * ability to map DV_ORDINAL to/from Coding/CodeableConcept and with that, |ordinal values to inline terminology Fixed ^^^^^ * Bundle type now defaults to ``collection`` when returned in openEHR —> FHIR Release 1.2.1 ------------- Added ^^^^^ * insights now include mapper name as well Fixed ^^^^^ * if fhirCondition as a preprocessor includes multiple 'one of' criteria, these now properly result in 'or' statements Release 1.2.0 ------------- Added ^^^^^ * compliance to FHIR Connect spec version 1.0.0 with implicit typing ('type' in model mapper is no longer required, types are implied based on RMType and data type on data values being mapped). At the moment, explicit typing is still supported, but will be removed in future versions. Fixed ^^^^^ * proper serialization to YAML when requesting YAML representation of model/context mappers (with Accept: application/x-yaml) Changed ^^^^^^^ * snake-yaml de/serialization replaced with jackson yaml Release 1.1.2 ------------- Fixed ^^^^^ * prevent overriding of recurring elements when they reference a different parent openehr path within a followed by Release 1.1.1 ------------- Added ^^^^^ * ``hierarchy`` to the model schema, although not yet implemented/supported by the engine * ``created`` and ``updated`` (timestamp) added to all database entities Changed ^^^^^^^ * if constructed FHIRPath during runtime of the engine is invalid, mapping now gracefully fails and logs a warning/error instead of failing altogether Fixed ^^^^^ * manual mappings, if present in followedBy statements, are now applied on all parent occurrences instead of only the last one * proper handling of ``$openehrRoot`` and ``$archetype`` * fixed behavior of the engine when parent path had multiple fhir where clauses Release 1.1.0 ------------- Added ^^^^^ * Introduced the preprocessor : The ``spec.fhirConfig.conditions`` have been relocated to ``preprocessor.fhirConditions`` in accordance with the FHIR Connect v1.0.0 specification. All existing mappings have been automatically migrated to comply with this update. No further action required on users. .. raw:: html
Before
        spec:
        ...
          fhirConfig:
              structureDefinition: http://hl7.org/fhir/StructureDefinition/Observation
              condition:
                  - targetRoot: "$resource"
                    targetAttribute: "code.coding.code"
                    operator: "one of"
                    criteria: "[$snomed.364075005,$snomed.78564009,$loinc.8867-4]"
            
\ \ .. raw:: html
Now
        spec:
        ...
          fhirConfig:
              structureDefinition: http://hl7.org/fhir/StructureDefinition/Observation
        preprocessor:
          fhirConditions:
              - targetRoot: "$resource"
                targetAttribute: "code.coding.code"
                operator: "one of"
                criteria: "[$snomed.364075005,$snomed.78564009,$loinc.8867-4]"
            
\ \ \ Changed ^^^^^^^ * The RESTful API endpoints (``/fc/model``, ``/fc/context``) now return and accept model/context mappers directly, without any additional wrapper. `Example:` When retrieving a model mapper (``GET /fc/model/{id}``) for an update, you can now use the entire response payload as the PUT body. .. raw:: html
Before (context example)
          {
            "id": "67e8351186096400101ba5ae",
            "fhirConnectContext": {
              "grammar": "FHIRConnect/v1.0.0",
              "type": "CONTEXT",
              "metadata": {
                "name": "Growth chart",
                "version": "1.0.0"
              },
              "spec": {
                "system": "FHIR",
                "version": "R4"
              },
              "context": {
                "profile": {
                  "url": ""
                },
                "template": {
                  "id": "Growth chart"
                },
                "archetypes": [
                  "openEHR-EHR-OBSERVATION.body_weight.v2",
                  "openEHR-EHR-OBSERVATION.height.v2",
                  "openEHR-EHR-OBSERVATION.body_mass_index.v2",
                  "openEHR-EHR-OBSERVATION.head_circumference.v1"
                ],
                "start": "openEHR-EHR-OBSERVATION.body_weight.v2"
              }
            },
            "user": "123",
            "organisation": "123"
          }

      
\ \ .. raw:: html
Now (context example)
        {
            "id": "67e8351186096400101ba5ae",
            "grammar": "FHIRConnect/v1.0.0",
            "type": "context",
            "metadata": {
                "name": "Growth chart",
                "version": "1.0.0"
            },
            "spec": {
                "system": "FHIR",
                "version": "R4"
            },
            "context": {
                "profile": {
                    "url": ""
                },
                "template": {
                    "id": "Growth chart"
                },
                "archetypes": [
                    "openEHR-EHR-OBSERVATION.body_weight.v2",
                    "openEHR-EHR-OBSERVATION.height.v2",
                    "openEHR-EHR-OBSERVATION.body_mass_index.v2",
                    "openEHR-EHR-OBSERVATION.head_circumference.v1"
                ],
                "start": "openEHR-EHR-OBSERVATION.body_weight.v2"
            }
        }
      
\ \ Fixed ^^^^^ * ``$fhirRoot`` is now correctly processed if set in a mapper ``fhirCondition.targetRoot``