Repository navigation
0.0.9
Added
-
The operator views of the operator console (#276). After sign-in, which
now exchanges the code at the provider's token endpoint with the PKCE
verifier and checks the ID Token's signature, issuer, single audience,
expiry andnoncebefore a session begins (the new[oidc]keystoken_endpointand
jwks_uri), the console shows the member endpoints with their membership
standing and last observed health (/members), the integrity incidents
and thecreating_system_idrouting table (/integrity), the stored
queries with their AQL (/stored-queries), and the gateway's
self-description (/federation), each rendered on the server from the
gateway's surface with the operator's own token. A view without a
signed-in session sends the browser to sign-in, and a refusal shows the
gateway's status and stable error code, a401with a link back to
sign-in. The routing table and the stored queries are paged, 100 rows a
page. Withsecure_cookieon, the console's cookies carry the__Host-
prefix, and a new sign-in ends the session the browser held. -
A read-only operator surface on the gateway:
GET {base}/operator/incidents
(each incident kind's count and the last 25 incidents of each kind),
/operator/creating-systems(the routing table) and
/operator/stored-queries(every held version, as the ITS-REST
StoredQuery), admitted only for a token carrying theoperator_scopeits
[[auth.issuer]]entry names as one whole scope token. The last two answer
one page,{"items", "offset", "total"}, under the optionaloffsetand
limitparameters, withlimitat most 100. It answers
routing ids, counts and stored definitions only, and an incident names an
ehr_idonly when it is a bare UUID (§5.4.1, N33). -
ferrofed conformance run --node-profilereports CP-18, CP-19 and CP-27
against every active member (#573; §16.2; N26, N27, N34). The
Federation-Node profile checks are the gateway's own: each member is read
through its node client, with its onward credentials and the outbound
gate, for the patient's EHR by itsehr_idalone, an EHR created with no
subject, and its error statuses for an unknown EHR and an unparsable
query, and the admission check runs as before. The access and consent
checks need a refusal arranged with the node's own policy, so a run
records them not observable with that reason. The harness runs the same
checks against FerroEHR and EHRbase. The run also scores a new track 3
scenario: theENDPOINTattributes a client selects are each row's
endpoint id andsystem_id(§9.4, N12, CP-37). -
Every release attaches the conformance seed data,
ferrofed-conformance-seed-data.json, with its SHA-256 in
ferrofed-conformance-seed-data.json.sha256sum(#573). The file holds the
vendored template and compositionsconformance runwrites, with their
Apache-2.0 licence and notice, and--seed-datatakes it in place of the
vendored directory, checking each file it holds by SHA-256. -
A mutual-TLS token endpoint alias on a host you name (#560; RFC 8705 §5).
A node's[credentials."<id>"]section takesmtls_alias_hosts, each a
host name with an optional port, and afapi2grant that uses mutual TLS
then takes atoken_endpointofmtls_endpoint_aliaseson one of those
hosts, overhttpsalone, as well as on the issuer's origin. An alias on
any other host is still refused before a token request is sent. An entry
that is no host, or the key in a section with nofapi2grant over mutual
TLS, refuses the configuration, naming the key.oauth-server-metadata
0.0.2 addsAliasHostandIssuer::mtls_alias. -
Mutual TLS toward a node and its authorization server, with RFC 8705
client authentication and certificate-bound tokens (#492; §13.1, §13.4,
N25, CP-17; FAPI 2.0 Security Profile §5.3.2.1). A node's
[credentials."<id>"]section takesclient_identity_fileand
trust_roots_file, the keys and the TLS type every identity service
takes, and the node and its token endpoint are reached over one transport
that presents that certificate,httpsunder every profile; a section
may name that material alone. Anoauth2grant, and afapi2grant, may
authenticate withclient_auth = "tls_client_auth"or
"self_signed_tls_client_auth", sendingclient_idand no assertion
(RFC 8705 §2), and withtls_client_certificate_bound_access_tokens = truetake only tokens bound to the certificate (§3): a token whosecnf
names another certificate, in the token response or as a JWT claim, is
refused before the node is sent anything (§3.1, §3.2). It composes with
token exchange per caller, whose actor token the gateway still signs. A
fapi2grant over mutual TLS uses themtls_endpoint_aliasestoken
endpoint (§5), needs the metadata to listtls_client_authand state
tls_client_certificate_bound_access_tokensas the grant uses them, and
needs a client key only for a token exchange. A grant that sets bothdpop_key_fileand certificate binding,
either without a client identity, an identity with no certificate, an
httptoken endpoint or node, and TLS material in a service's own
credentialssection refuse the configuration. RFC 8705 is vendored
underdocs/specs/ietf-oauth/. -
The operator console's skeleton,
app/ferrofed-viewer(#275): a Leptos app
rendered on the server and hydrated in the browser, with a
backend-for-frontend, as its own binary,ferrofed-viewer, and its own
image,ghcr.io/ferrohealth/ferrofed-viewer. It reaches the gateway over
HTTP alone, as any client does, and holds no clinical data. Built so far: a
landing page,GET /healthand thehealthcheckcommand, operator sign-in
at an OpenID Provider with the authorization code grant, anonceand
PKCE, itsstate,nonceand verifier held on the server behind an
opaqueHttpOnlycookie in a bounded, short-lived pool of pending
sign-ins that a flood of login starts cannot grow and that never touches
the separate, bounded pool of signed-in sessions with their idle and
absolute timeouts, configuration refusals that name a key and a line and
never a value, and a typed client of the gateway'sOPTIONS {base}/
and ITS-REST surface called with the operator's own token. Every answer
carries a per-response script nonce in its Content-Security-Policy. The
console reads a TOML file withFERROFED_VIEWER__overrides and a
client_secret_file. The code exchange, the operator views (#276) and the
query console (#277) are planned. The release lane builds, attests and
pushes the image with the same SLSA provenance and SBOM attestations as
the gateway image, CI lints the browser half forwasm32and builds the
site bundle, and the book's "The operator console (planned screens)" page
says what is built and what is planned. -
The NVI localizer authenticates with the Nuts grant (#539; Annex B §B.1,
§B.4; the IG's Localization page, GF-Authentication, GFI-004 and
GFI-005).[nl_gf.nvi.credentials.nuts]takes the table a node's onward
credentials take and runs the same grant: a Verifiable Presentation of the
gateway's credentials for a token bound to itsDPoPkey, cached until 30
seconds before it expires and dropped on the NVI's401. Every search
carries the token with a proof of the key over the search URL without its
query, and a nonce the NVI demands is answered once (RFC 9449 §7.1, §9).
The token goes to the NVI alone. A refused grant leaves the localization
unavailable, so the query fails closed (§14.1). Anoauth2orfapi2
table under[nl_gf.nvi.credentials]is refused, naming its key, since the
IG defines no such grant for the Localization Service. The
nl-generic-functionsNVI client takes an authorizer that makes each
request's headers and is handed the request URL without the query that
holds the pseudonym (0.0.12). -
ferrofed conformance run --config <file>scores a configured deployment
against the Connectathon tracks 1 to 7, 9 and 11 over ITS-REST (#546;
§16.3, §16.4). It starts the gateway in-process from the configuration, or
drives one already serving at--gateway <url>, as a client holding a
bearer token from--token-file. It seeds a synthetic patient in the
urn:oid:2.999arc at every member the deployment's own cross-reference
names, through each node's ITS-REST writes: the patient's EHR, the vendored
template and one vendored composition, three EHRs with no subject, and the
writes the scenarios make. It reads no EHR it did not create and removes
nothing. It refuses to start without--allow-writes, against a profile
other thandevelopmentwithout
--i-understand-this-writes-synthetic-data-to-the-nodes, for a patient
outside the example arc, and for seed files other than the vendored ones,
which it checks by SHA-256. The--gatewayURL and every member endpoint
are held tohttps, orhttpto a loopback host under the development
profile alone, which the report names; the gateway client follows no
redirect, and the caller's token is held as a secret that no report, log
line or error carries. It writes the per-track and per-point report the
harness run writes, with the same columns and results, and reports every
scenario that needs fault injection, node-side capture or a gateway
configured for itnot-runwith the reason, neverpass;--node-profile
adds the admission check of every member as the node profile findings. The
end-to-end tracks call the same scenario checks, and a run against the
harness reads what the harness scores and nothing more. -
An end-to-end check that the
AVGthe gateway declares decomposable in
OPTIONS {base}/is the mean weighted by each node's count (§11.6.3, N39,
CP-10, CP-32), behindFERROFED_E2E. With two values at one FerroEHR node
and one at the other, each node is asked itsSUMandCOUNT, and the
answer equals the mean weighted by the counts each node returns for the
query it was sent, which differs from a mean of the node means. -
The gateway serves the
did:webDID document of each Nuts grant's
holder (#503; Annex B §B.4, Nuts RFC021 §4.2). It is served at the path
the DID resolves to (the did:web Method Specification, Read (Resolve)),
such as/.well-known/did.json, under any base URL, as
application/did+ld+jsonand with no client authentication, like the JWK
Set. The document is built from the holder keys thenutssections name
and nothing else, oneJsonWebKey2020verification method perkid, so
a key change shows up on the next reload with no file to edit. A DID
whose document would sit under{base}/v1/, two DIDs that share one
document path, or two keys under onekidrefuse the configuration.
nl-generic-functions0.0.13 adds thenuts_auth::did_documentmodule,
HolderKey::publicandDid::document_path. -
A differential run against the Federation Tier reference implementation,
behindFERROFED_E2E(#94; §16.3 tracks 1 to 7 and 9). The testkit builds
syntaric/openehr-federation-refat its pinned commit from the vendored
source and the manifest held to its recorded sha256, on digest-pinned Maven
and Java images, and runs it beside FerroFED over the same two FerroEHR
nodes, each gateway behind capturing proxies of its own. Some thirty
requests go to both, and the run compares the status, the federation
headers, the envelope against the vendored schema,meta.federation, the
rows and what reached each node, after normalising only what the
specification leaves free. Every difference is held in a register with its
verdict and where it is recorded: a new or vanished difference fails the
run. Thee2e (containers)job uploads the Markdown and TSV report as the
differential-reportartifact. No difference is a FerroFED defect; three
reference divergences and one specification question are new upstream
reports (#212 T190 to T193). -
A
fapi2grant's client key rotates with an overlap (#514): the new
previous_client_key_filenames the previous P-256 client key, which
the JWK Set at{base}/.well-known/jwks.jsonpublishes after the current
key until it is removed from the configuration. Only the current key
signs. An authorization server that fetches the set during the rotation
verifies both the new assertions and one the previous key signed before
it (FAPI 2.0 Security Profile §5.4.2). A previous key that is no P-256
key, or is the current key, refuses the configuration, naming the key. -
[signing]holds a P-256 key as well as a P-384 key, and reads the
algorithm from the key: a P-256 key signs ES256 and a P-384 key ES384
(RFC 7518 §3.4) (#513). The current key signs the
openEHR-federation-clientconveyance and everyoauth2client assertion
with its own algorithm, and the JWK Set publishes each key with itsalg,
through the same previous-key rotation window, which may cross curves. A
federation whose nodes hold to the FAPI 2.0 Security Profile, which admits
ES256 and not ES384 (§5.4.1), signs with a P-256 key. A key on any other
curve refuses the configuration, naming the key. -
The Federation-Node profile runs against a second CDR product, EHRbase,
behindFERROFED_E2E(#549; §16.2, N26, N27, N34, CP-18, CP-19, CP-27,
CP-33a). The testkit pinsehrbase/ehrbase2.36.0 and the
ehrbase/ehrbase-v2-postgres16.2 database image by digest, each a
docs/VERSIONS.mdrow the versions guard compares, and every node profile
check runs against it in thee2e (containers)job and writes its findings
beside FerroEHR's. For the access check (CP-18) an EHRbase started with
Basic authentication withholds the request path of one EHR from its user
role, the narrowest refusal itssecurity.additionalAuthorizations
expresses; it records no consent decision, so the consent check (CP-19)
reports not observable with that reason. The conformance report shows the
findings of each product side by side under the node class, then each
product's evidence. EHRbase passes the error pass-through and subjectless
EHR checks. It refuses anEHR_STATUSsubject in a namespace such as
urn:oid:2.999.1.1, which the BASEOBJECT_REF.namespacepattern admits.
The admission check therefore creates no test EHR there, and its integrity
conditions fail on that cause. Its EHR read omitsehr_access, which the RM
EHRclass makes mandatory. As at FerroEHR, bothehr_id-scoped query
forms release the EHR whose read the node refuses. The invocation finding
names why an EHR body does not decode. No specification governs which
products the harness runs: our own design. -
Each IHE audit record the gateway makes for a client's request names the
verified caller (#500; PIXm §2:3.83.5.2.1, BALP 1.1.4 §3:5.7.5.4, ITI TF-2
§3.55.5.1.1, IUA ITI TF-2 §3.72.5.1). The ITI-83, ITI-78 and ITI-119
AuditEventcarries the BALPagent:userwith the token'sissand
sub,requestortrue and its purposes of use, and an Application agent
with itsclient_id; the ITI-55 DICOM message carries the Human Requestor
with thesubasUserIDandaud<sub@iss>asUserName, as its one
requestor. A record the gateway makes on its own behalf (the admission
check, the mCSD directory reads, the PMIR subscription and feed) names no
caller. The identity reaches the Audit Record Repository alone: the log
destinations record only whether a record was made for a caller or by the
gateway, and no metric carries it.
ihe-iti0.0.23 takes whom each PIXm, PDQm and XCPD exchange is made for
(ihe_iti::user::OnBehalfOf), and the resolver, localizer and
demographics roles take it too. An ITI-83 answer a localization read is
reused only by the resolution of the same caller, so another caller's
access sends, and records, an ITI-83 of its own. The security event
edge-identity-assertednames the caller bysubject_refand
client_ref, keyed HMAC-SHA256 references stable for the process, in
place of the subject and the client, and a verified caller'sDebug
shows neither them nor the issuer. -
Track 11, the integrity suite, against the two FerroEHR nodes of the
harness behindFERROFED_E2E(#91; §16.3 track 11, §12.5.1, §12.5.2,
§12b, N41, N42, N42a, CP-33, CP-33a). The harness seeds oneehr_idat
both nodes for two different synthetic patients. A read and a query scoped
to it are refused409ehr-id-collisionlisting both claimants, with one
integrity incident, and the proxy journals show the ask-all probe as the
only request either node received. Once two targeted reads teach the
ehr_idindex both claimants, which raises the index-insert alarm once, a
read and two writes are refused the same way and reach neither node. A
versioned write no earlier step of §12.5.1 routes is refused400
target-requiredand probes nobody, although itsIf-Matchnames node
A'ssystem_id. As the federation operator, the harness then applies the
admission check to a FerroEHR candidate deployed with member A's
system_id: recorded under thatsystem_id, the registry load refuses it
as a duplicate, and recorded under one of its own, the check fails the
system_idcondition naming member A. The conformance matrix records
track 11 as covered. -
The Connectathon tracks 1 to 7 and 9 of §16.3 run as scenarios in the
end-to-end harness over two FerroEHR nodes: transparency, resolution
through the PIX Manager, the directed query and the endpoint pin, partial
results under node faults, de-duplication and cross-node shaping,
follow-up routing, onward authentication with consent left to the node,
and the REST surface with its self-description. Track 8 stays deferred,
as the specification marks it provisional (#92). -
scripts/conformance/report.shwrites the report of §16.4 from a test
run: every track and every conformance point as pass, fail, not run,
deferred, not applicable or open, with the issue and reason of each
deferral. CI writes it from the offline and the container runs and uploads
it as theconformance-reportartifact (#92). -
The Federation-Node profile of §16.2 as operator and harness tooling
(#93; N26, N27, N34, CP-18, CP-19, CP-27). The testkit'snode_profile
checks what a member CDR's ITS-REST interface shows of each node
obligation. They check that an EHR, itsEHR_STATUSand its compositions
answer to theehr_idalone, that an EHR created with no subject is read
and queried by itsehr_id, and that an unknownehr_idand an
unparsable query answer the ITS-REST error status. They also check that an
EHR the node's own policy withholds is refused on the read and on both
ehr_id-scoped query forms, and that a consent refusal an operator
arranges is held the same way. Each check records pass, fail or
not-observable with its evidence. The end-to-end run executes every check
against FerroEHR, including a FerroEHR started with Basic authentication
and restricted per-EHR access. It also runs the admission check of §12b.2
against a FerroEHR member. The conformance report shows the Node and
Operator points as their own class, scored from those findings and never
as a gateway pass, and lists every finding per product. -
A PIX Manager can be asked by
POST(#494).[[pixm.manager]]takes
method = "post"beside"get", the default: the gateway then posts the
ITI-83sourceIdentifierandtargetSystemparameters in aParameters
body to[base]/Patient/$ihe-pix(FHIR R4 Operations §3.2.0.1), so the
patient identifier is in no request URL a proxy or an access log records.
getstays the default because PIXm 3.1.0 §2:3.83.4.1.2 prescribes the
GETand requires no Manager to accept aPOST. Any other value refuses
the configuration naming the key. The ITI-83 audit record of aPOSTholds
its request line, media type and body.ihe-iti0.0.22 adds
pixm::InvocationandPixmClient::invoked_by, and the harness PIX
Manager answers a posted query. -
Each regional binding is one Cargo feature of
ferrofed-server:
binding-ihecarries the IHE binding of Annex A ([pixm],[pdqm],
[xcpd],[registry.mcsd],[pmir]and[audit]) andbinding-nlthe
Dutch Generic Functions of Annex B ([nl_gf]and the Nuts grant of
[credentials."<id>".nuts]);[dev]is always built. Both features are on
by default, so the released binary and the container image behave as
before. A build without one refuses its sections as unknown keys (#489). -
The book has a page on adding a country: a specification crate, a binding
module and a feature line (#489). -
The query console of the operator console (#277), at
/query. An AQL
query, or a stored query by name and optional version, runs through the
gateway'sPOST {base}/v1/query/aqlor/v1/query/{name}as the
signed-in operator, with the targeting, dedup and best-effort headers the
gateway's self-description offers. The answer shows the rows, every
endpoint's status, latency and error frommeta.federation, and says in
words whencompleteis false; a504or424all-or-nothing failure
shows its diagnostic envelope, and a refusal its status and stable code.
A patient is named through a parameter in the request body, and nothing
entered in the console reaches a URL, the browser history or a log. A
query runs once the page has loaded; its answer is rendered on the server
with every value a node sent escaped, and is never cached or compressed. -
Operator sign-out in the operator console (#584). The navigation bar's
"Sign out" posts toPOST /logout, which ends the server-side session,
removes the session cookie and, where the new[oidc]key
end_session_endpointnames the provider's end-session endpoint, sends
the browser there with the ID Token hint, the client id and the optional
post_logout_redirect_uri(OpenID Connect RP-Initiated Logout 1.0). The
sign-out and every server function the views and the query console call
are taken only from the console's own pages (Sec-Fetch-Site,Origin
orReferer); any other request is a403before the session is read. -
Browser journeys for the operator console (#608): headless Chrome, driven
over WebDriver from Rust withthirtyfour, signs in at a test OpenID
Provider, opens each operator view and follows its pagers, runs a query
that shows every node's status and whether the answer is complete, sends a
query the gateway refuses, and signs out, against a running gateway over
stub nodes and the console serving its release site bundle. Each journey
fails on any error the browser logs. They run behind
FERROFED_JOURNEYS=1in the newjourneys (browser)CI job, at the Chrome
for Testing releasedocs/VERSIONS.mdpins. -
The conformance statement (#95, #89): a book page under Evaluate that claims
the Federation-Gateway profile of the Federation Tier with AQL 0.9.0 at
commit7162d0c, with every §17 point and §16.3 track and how each is
scored, every deferral with its actor and reason, and the FerroEHR and
EHRbase images the tests ran against. Its generated part and the new page of
marked tests come fromscripts/conformance/matrix.sh --statement-write,
and the docs build and the conformance-matrix guard fail when either
disagrees with the matrix. The guard now refuses aplannedpoint or
track, so a re-pin scores or defers every point it adds. Six rows of the
obligations checklist that still readplannedafter their work shipped now
readtestedand name their tests.
Changed
-
The Licensor and copyright holder of FerroFED's own work is Cadasto B.V., replacing Vernum Projecten B.V. (#602). The licence, its Additional Use Grant and its Change Date do not change. A new guard,
scripts/checks/copyright-holder.sh, fails any first-party header that names another holder. -
The
openehr-*family moves from 0.0.83 to 0.0.84 (FerroEHR #3565,
#574). A re-send answering a node'sDPoPnonce challenge that no proof
could be made for is the node'snode-error, with the node counted as
asked, read from the client'sDpopProof { sent }. The node clients no
longer keep a record of each call's sends.openehr-federation0.0.40
takes the new family. -
The
openehr-*family moves from 0.0.82 to 0.0.83 (FerroEHR #3560,
#566). A deadline that passes before the re-send answering a node's
DPoPnonce challenge is the node'stime-out, with the node counted as
asked, read from the client'sDeadlineElapsed { sent }in place of the
call's prover record (#470). The record still reads a re-send that no
DPoPproof could be made for, which the client reports with no such
field.openehr-federation0.0.39 takes the new family. -
The harness and the quickstart run FerroEHR 4.3.3, pinned by digest at
its new home underghcr.io/ferrohealth, node and database image alike
(#566). That release makes AQL honourEHR_ACCESSon every query form
(FerroEHR #3562), which the node profile's "access decided at the node"
check (CP-18) reads. -
A consent pre-filter that did not ask its service says so, with a closed
reason, in place of answering as one that was asked and denied nothing
(#496). Mitz is not asked about a patient named outside the BSN, such as by
a pseudonymised BSN (reasonnamespace), or for a caller whose token does
not state the requester claims (reasoncaller-claims). Such a call is
counted inferrofed_consent_prefilter_requests_totalwith
outcome="not-asked"and itsreason, no longer asno-signal, and it
leaves the pre-filter's state onGET /health/dependenciesas it was.
The client's answer is unchanged: every candidate is asked, nothing appears
inmeta.federation.consent, and under[federation.consent] disclose = falsethe answer is the one a pre-filter that found nothing gives. -
Two sections that fill a role exactly one may, two resolvers, two consent
pre-filters or two localizers of a binding's own, are refused with one
error that names every section, such as[nl_gf.nvi] and [xcpd] are both localizers; set one, in place of one error per pair. A localizer section
undernode_selection = "ask-all"is refused naming its section, as
before (#489). -
The
configuration resolvedlog line names the compiled bindings, and
each binding logs what it is configured to reach on abinding configured
line of its own; the registry directory, PIX Manager, PMIR and PDQm fields
move from the first line to the IHE binding's (#489). -
A build without a binding feature compiles none of that binding's crate:
binding-iheandbinding-nlturn on newiheandnlfeatures of
ferrofed-identityand annlfeature offerrofed-engine, so
cargo build -p ferrofed-server --no-default-featuresbuilds neither
ihe-itinornl-generic-functions. The registry document in FHIR form
(registry.format = "fhir"), read with the mCSD reader, is part of
binding-ihe(#551). -
The authorization server metadata checks of RFC 8414 move out of
nl-generic-functionsinto a crate of their own,oauth-server-metadata
0.0.1, which the OAuth 2.0 issuer audience, the FAPI 2.0 grant and the
Nuts grant share.nl-generic-functions0.0.11 drops its
oauth-metadatafeature (#551). -
An error that needs a cross-reference resolver names the resolvers the
build carries,[dev] or [pixm]by default and[dev]without
binding-ihe(#551). -
[federation.consent] disclose = falsekeeps a consent exclusion out of
what a client sees, for Regulation (EU) 2025/327 Art 8, under which the
fact that a patient restricted access "shall not be visible to healthcare
providers". A member the consent pre-filter excludes is still never sent a
request, and a federated query reports itnot-resolved, with the same
erroras a member the cross-reference does not know the patient at, so
meta.federation.completestaysfalseand nothing fails. A read of an
EHR by subject that only an excluded member could serve answers
404 subject-unavailable, the same answer as for a subject no member
knows, a new code in the error vocabulary.OPTIONS {base}/declares the
choice asfederation.consent.disclose, the pre-filter metrics still count
every exclusion for the operator, and the default stays the
specification'sconsent-denied(N27a) (#493). The setting covers a
node's own consent refusal too, a403with a code the registry lists in
consent_refusal_codes: a federated query reports the nodenot-resolved
with nolatency_ms, and a read by subject, a routed request and an
ask-all probe answer404 subject-unavailable. On a request under
{base}/v1/ehr/, the creation of an EHR and a DEMOGRAPHIC request, a
node's own404gets that same answer in this mode, so it never stands
for a refusal alone; everysubject-unavailablecarries one fixed
message. The node request metrics now count such a refusal as
consent-deniedon every path, whatever the setting. -
nl-generic-functions0.0.16 addsBSN_SYSTEMSandis_bsn_systemto
identification, besidePSEUDO_BSN_SYSTEMandURA_SYSTEM: the naming
systems of the BSN itself, the IG's$bsnsystem and its OID as a URN and
dotted (#587). -
The changelog is written as fragments (#598). A pull request with a
user-visible effect adds one file underchangelog.d/, named
<issue>-<kebab-slug>.<section>.mdand holding its entry, instead of editing
CHANGELOG.md, so two pull requests no longer conflict on one file. The
release cut runsscripts/release/changelog.sh --assemble <version> <date>,
which writes the fragments and the entries already under[Unreleased]into
the new version's section and removes the fragments. The newchangelog
job of CI runschangelog.sh --checkover every fragment, and the
changelog-guardjob fails a pull request that adds no fragment and leaves
CHANGELOG.mduntouched, unless it carries theno-changeloglabel. -
The operator console serves its site bundle brotli- or gzip-compressed, as
the browser'sAccept-Encodingchooses, withVary: Accept-Encoding, so a
browser downloads about 220 KB of WebAssembly where it downloaded 770 KB;
pages and server function answers stay uncompressed (#600). The release
bundle names no directory of the host that built it: the build remaps the
cargo home, the toolchain and the checkout, and CI fails a bundle that
names a home, runner, registry or toolchain path. -
ferrofed-identitynames the PMIR subscriber's errorihe::pmir::PmirConfigError,
after its module, where it wasLifecycleConfigError, and the log target both
audit log recorders write to isihe::audit::AUDIT_TARGET, where it was
ihe::xcpd::AUDIT_TARGET; its value,ferrofed::audit, is unchanged. In
nl-generic-functions0.0.18,mitz::BSN_ROOTtakes its value from the BSN
OID ofidentification::BSN_SYSTEMS, which is unchanged (#606). -
The operator console refuses to start with
[session] secure_cookie = false
unless its[oidc] redirect_uriis anhttpURL on a loopback host
(localhost,127.0.0.0/8or::1), so a deployed console never sends its
session cookie over plain HTTP; the refusal namessession.secure_cookie
(#615). -
A commercial licence, and any other business or licensing question, goes to
Cadasto B.V., the Licensor, at info@cadasto.com or
https://www.cadasto.com/contact/ (#616). EveryLICENSEcopy names that
contact where it named the maintainer, soopenehr-federation0.0.42,
ihe-iti0.0.25,nl-generic-functions0.0.17 andoauth-server-metadata
0.0.4 carry it. The maintainer stays the contact for technical questions.
The licence terms do not change.
Fixed
- A caller whose token states the requester claims in a form the Mitz
question does not take, or a patient value Mitz does not take as a BSN,
is no longer reported as a Mitz outage, although Mitz was never asked
(#568). The pre-filter answers that it did not ask, with the reason
caller-claims-invalidorpatient-value, so the call is counted as
not-asked,GET /health/dependencieskeeps the pre-filter's state, and
the client's answer carries nometa.federation.consent.error. No claim
value reaches a label, a log line or an error. - A stored-query definition that a PostgreSQL or
redbstore holds is now
checked on every read, as the files backend checks each file (#586). A
row written past the gateway, by a restore, a manual insert or an older
version, that names its patient by a literal or does not admit as a
definition is never served or run: the gateway refuses to start over a
store holding one, and over a shared PostgreSQL store a read, a listing or
an invocation that reaches such a row answers500. The security log
records aheld-definition-refusedevent naming the definition's name and
version, never its text. - The operator console's sign-out reaches the provider's end-session
endpoint in the browser: the Content-Security-Policy'sform-actionnow
names that endpoint's origin beside the console, where before the browser
blocked the redirect the sign-out form is answered with (#608). The console
also serves the brand favicon at/favicon.ico, which every browser asks
for on its first page and which answered404before. - Every operator console page the gateway fills is whole in the HTML the
server sends, so it reads with no script: the pages render once every
answer is in, where before a page could arrive with its loading notice and
the content in a template that only a script moved into place (#608). A
query or a view the gateway refuses, and a query form the console cannot
send, are shown with the gateway's status and code or the field at fault
as before, and the browser no longer logs them as a failed request.