Repository navigation
4.3.2
Added
-
openehr-querycan rewrite, locate and bind a query (#3505, #3506,
#3507, #3508).visit::Visitandvisit::VisitMutwalk every node of the
AST, so a consumer finds, replaces or removes aWHEREcondition without
its own recursive walk. EveryIdentifiedPathand everyWHEREcondition
carries anast::Span, the byte range it was written at, so a diagnostic
can point at a predicate without repeating its literal; spans take no part
in equality.bind::bindsubstitutes ITS-RESTquery_parametersinto the
AST as typed literals the printer escapes, at every position the grammar
admits a parameter, and reports an unbound, unknown, duplicate or
unbindable parameter by name, never by value. The opt-infederation
feature addsfederation::parse_federated, which lifts a
FROM ENDPOINT p [ … ]orORGANISATION [ … ]directive out of a query
and parses the rest as strict AQL. Breaking:WhereExpr::Identifiedand
IdentifiedPathgained the span (WhereExpr::identifiedand
IdentifiedPath::newbuild them without one). -
openehr-itspublishes the server router and the intermediary seams
(#3509, #3510, #3511, #3512, #3514). Underrest-server, each API group's
servermodule carries the trait, one success enum per operation (the
documented2xxanswers with theirLocation,ETagand other headers)
androuter(api), an axum router binding everyROUTESentry to its trait
method. A method refuses withrest::runtime::Refusal, anApiErrorplus
the headers its answer needs: the currentETagon a412, or the
OpenAPI-declared headers of a demographic409/412through the generated
headers structs (Refusal::with_headers). Either renders as the ITS-REST
ErrorJSON body.rest::server::router(api)mounts all six groups at
once, andrest::server::with_fallbacksmakes an unknown path answer404
and an undeclared method405withAllow, both with theErrorbody.
rest::routes::lookupmatches a method and path to its operation and path
parameters without reading the body, andClient::forwardsends a request
once and returns every answer as received, so an intermediary passes bodies,
LocationandETagthrough byte for byte.CredentialsProviderresolves
the credential before every attempt and hears about a401, for tokens that
refresh.CallOptionsgives a generated client a deadline and extra headers
per call (with_options); the remaining budget reaches the engine as
RequestTimeout, and an elapsed deadline isClientError::DeadlineElapsed.
Breaking: the server traits moved into<group>::serverand return
Result<success enum, Refusal>, and the response headers structs moved
fromclientto the group module. The nineopenehr-*crates step to 0.0.74. -
The
openehr-itsITS-REST client carries what a consumer meets on first
adoption (#3487). The commit operations (COMPOSITION, EHR_STATUS, the
directory, EHR creation, the demographic parties and relationships) take
the committal-metadata headers the ITS-REST overview defines and the
OpenAPI declares no parameter for:openehr-version,
openehr-audit-details(one field line per value) and, on the COMPOSITION
and CONTRIBUTION commits,openehr-template-id. Every documented4xx
outcome carries the answer body as anErrorBody: the bytes as received,
decoded as the ITS-RESTErrorwhen they are one, so a422's
validationErrorsreach the caller;ClientError::Unauthorized,
Forbidden,ServiceFailureandUndocumentedStatuscarry the same body.
A400whose body carriesmessagealone decodes as theErrorwith an
emptyvalidationErrors. A path parameter keeps:literal, so a version
uid is sent as the specification writes it.Credentialshold their secret
in asecrecy::SecretString(redactedDebug, zeroed on drop), with
Credentials::basicandCredentials::bearerconstructors. The nine
openehr-*crates step to 0.0.72. -
openehr-itsships an ITS-REST client (#3485). The newrest-client
feature adds a generated client per ITS-REST 1.1.0 API group
(rest::generated::<group>::client) over a hand-written runtime
(rest::client: theTransportengine trait, the shippedreqwestengine,
Basic and Bearer credentials, the retry budget andClientError). Each
operation takes its parameter struct, withPrefer,If-MatchandAccept
as fields, and answers an outcome with one variant per status the OpenAPI
documents for it; declared response headers such asETagandLocation
come back in a typed struct. Any other status is
ClientError::UndocumentedStatus, and401,403and5xxare their own
errors. Idempotent requests are retried after a transport failure or a
5xx; aPOSTis sent once. A create operation also answersNoContent,
the204the ITS-REST overview prescribes underPrefer: return=minimal
although the OpenAPI lists201alone. FerroBRIDGE keeps its hand-written
client until it moves to this one (its issue #276). The DTOs, parameter
structs and route tables move to a
newrestfeature over serde andhttpalone, which bothrest-serverand
rest-clientbuild on, so a client never compilesaxum.fullnow
includesrest-client. The nineopenehr-*crates step to 0.0.71. -
A CI guard keeps the Apache-2.0 crates free of BUSL-1.1 code:
scripts/checks/licence-boundary.shrefuses a normal or build dependency,
or a feature, fromopenehr-base,openehr-lang,openehr-term,
openehr-rm,openehr-amoropenehr-itsonopenehr-query,
openehr-adloropenehr-sdt, and alicensefield that changes side.
Changed
-
The repository moved to the FerroHEALTH organization
(https://github.com/FerroHEALTH/FerroEHR, #3516); the old
rubentalstra/FerroEHRURLs redirect. Images and the Helm chart now publish
toghcr.io/ferrohealth/ferroehr,ghcr.io/ferrohealth/ferroehr-viewer,
ghcr.io/ferrohealth/ferroehr-postgresand
oci://ghcr.io/ferrohealth/charts/ferroehr, and the compose files, the chart
and the book name those references. The v4.3.1 images and chart are copied
there by digest. Everything published up to v4.3.1 stays available under
ghcr.io/rubentalstra, and its signatures namerubentalstra/FerroEHRas the
repository that built it. The roadmap board is now
https://github.com/orgs/FerroHEALTH/projects/2. The nineopenehr-*crates
step to 0.0.75 for their newrepositoryfield. -
The dependency set moves forward in one step. OpenTelemetry goes to
0.33 (opentelemetry,opentelemetry_sdk,opentelemetry-otlp,
opentelemetry-prometheus) withtracing-opentelemetry0.34; the OpenAPI
stack toutoipa6,utoipa-axum0.3 andutoipa-swagger-ui10;
jsonschemato 0.58,sevenz-rust2to 0.23,lapinto 4.12 andconfig
to 0.15.27. The bundled PostgreSQL image is rebuilt on the current
postgres:18.6upstream digest (sha256:5a5a84b1…), a same-version respin
with rebuilt base packages. The nineopenehr-*crates step to 0.0.73. -
FerroTERM moves to 0.1.5 everywhere the product pins it. The quickstart
overlaydocker-compose.terminology.yml, the hosted sandbox compose file, the
Helm chart (terminology.image.digestand the pinned version its tag default
and Artifact Hub annotation read) and the integration test that starts the
real server all name
ghcr.io/rubentalstra/ferroterm:0.1.5@sha256:61a2d4aefc4a48e9e90b9a698a64bdfeb7ef6443744a1fe50972099456891fe9,
the index digest read from GHCR. That release adds the history interaction,
_summaryand_elementson read, a 406 on an unacceptableAccept, refuses
a write that would duplicate a canonical, and states the position of a
refused expression constraint on theOperationOutcome. The chart version
becomes 10.1.3; an install that pins the chart keeps running the image it
pinned. -
openehr-itsis split in two, and the wire layer is Apache-2.0 again
(#3482). The new crateopenehr-sdt(BUSL-1.1) holds the hand-written
Simplified Formats (FLAT, STRUCTURED, Web Template, TDD import), the
template-independent RM-instance validation and the SMART on openEHR scope
grammar.openehr-itskeeps the ITS wire layer: the generated canonical JSON
dispatch, the canonical XML codecs, the ITS-REST contract, the OPT 1.4 and
AOM2 archetype XML codecs, and the hand-written runtimes, canonical JSON entry
points and wire-validation dispatcher they need. From 0.0.69 it is published
under Apache-2.0, so a consumer of canonical JSON takes on no BUSL-1.1 code.
Rust callers importopenehr_sdt::flat,openehr_sdt::rm_instanceand
openehr_sdt::smart_scopesin place ofopenehr_its::flat,
openehr_its::rm_instanceandopenehr_its::rest::smart_scopes. Theflat
andcachefeatures leftopenehr-itsforopenehr-sdt; a
wasm32-unknown-unknownconsumer ofopenehr-itsnow selects
default-features = false, features = ["opt14"], andopenehr-sdtwith
default-features = falsecompiles to the scope grammar alone, with no
dependency. Published versions keep their licence:openehr-its0.0.60 to
0.0.67 stayBUSL-1.1 AND Apache-2.0. -
The published
openehr-*crates are nine, and all step to 0.0.69 (#3482).
openehr-sdtwas first published alone at 0.0.68, built against the 0.0.67
siblings; it joins the lockstep line at 0.0.69 and publishes after
openehr-itsand beforeopenehr-adl. -
FerroTERM moves to 0.1.4 everywhere the product pins it (#3474). The
quickstart overlaydocker-compose.terminology.yml, the hosted sandbox
compose file, the Helm chart (terminology.image.digestand the pinned
version its tag default and Artifact Hub annotation read) and the
integration test that starts the real server all name
ghcr.io/rubentalstra/ferroterm:0.1.4@sha256:f3b5f35a60d99d5c837125e5f8cf39d8eeecf9f69dbc79b9a526cc45aa706470,
the index digest read from GHCR. That release reloads its served set without
a restart, treats an index root's child directories as releases, ships the
ferroterm-syncservice, and carries the standard concept status properties
on locally authored code systems. The chart version becomes 10.1.2; an
install that pins the chart keeps running the image it pinned.
Fixed
-
Two
500answers from theopenehr-itsREST server runtime carry a fixed
message (#3518). An illegal response header and an answer body that does
not serialize put the header name or the serde error into the body the client
received; both now answer with a fixed text. -
The app and viewer images rebase onto a distroless base with the fixed
OpenSSL (#3504).gcr.io/distroless/cc-debian13:nonrootmoves to
sha256:e792ab3d…, which carries thelibssl3t64update from DSA-6531-1
(CVE-2026-75804, CVE-2026-84782). The image scan refused the previous base
with both findings at HIGH, so themainimages went untagged until this
change. -
An AQL path predicate whose node boolean opens with a parameter or an
archetype id parses (#3513):CLUSTER k[$node and name/value='x']and
[openEHR-EHR-CLUSTER.device.v1 or at0001]were refused, though the
grammar inQUERY/docs/AQL/master07-grammar.adocadmits both. -
The
no attribution in commitsCI job no longer refuses the
Co-authored-by: dependabot[bot]trailer GitHub writes when it squash-merges
a Dependabot pull request, which had failed the last three pushes tomain.
The commit-msg hook keeps that line too.