Skip to content

0.1.0

Choose a tag to compare

@github-actions github-actions released this 05 Sep 22:59
· 226 commits to main since this release
Immutable release. Only release title and notes can be modified.
v0.1.0
71b21de

Added

  • FERROTERM_BASE_URL: the URL clients reach the server at, stated per version as CapabilityStatement.implementation.url and in the terminology capabilities. A server behind a reverse proxy answers on an address it never sees, so the endpoint is configured rather than guessed from a socket or a forgeable header; a deployment that names none states no URL. compose.yaml gains a proxied profile: Caddy terminates TLS in front and the server publishes no host port.
  • GET /metrics: the Prometheus exposition of the requests answered (a counter and a duration histogram per method, matched route, and status) and the code system versions loaded (one gauge each). The route is off the FHIR base path, so a scrape is never a terminology request, and the labels name the matched route rather than the URI, so the series count stays bounded whatever codes clients ask about.
  • X-Request-Id on every response: the client's own value when it sent a usable one, a fresh UUID otherwise, and the same id in the request's log line. An id that is empty, over 128 characters, or not printable ASCII is replaced rather than echoed.
  • $batch-validate-code on ValueSet and CodeSystem, on every served version: one POST carries the shared inputs once, a validation parameter per validation, each a Parameters of that validation's own inputs, and the answer repeats validation in the same order with that validation's $validate-code outputs. A validation states its own value for an input the request also states, and a validation the server cannot run answers an OperationOutcome in its own slot while the others still answer. No OperationDefinition declares the operation anywhere, so the contract is the terminology ecosystem suite's cases, whose batch/batch-validate now passes on /r4b, /r4 and /r5.
  • The fuzz targets under fuzz/: every parser an untrusted input reaches (ECL, the FHIR JSON and XML bodies, the SNOMED CT implicit ?fhir_vs= and ?fhir_cm= forms, and the RF2 file names, effective times, and identifiers) is fed arbitrary bytes by cargo-fuzz, weekly in CI and by hand for longer runs. The seeds are committed; a crash uploads the input that reproduces it.

Fixed

  • The terminology capabilities no longer claim SNOMED CT post-coordination. CodeSystem.compositional is "The code system defines a compositional (post-coordination) grammar" and TerminologyCapabilities.codeSystem.version.compositional is "If the compositional grammar defined by the code system is supported", two different statements that one flag answered, so a client was told it could send expressions and then got "no such concept" for every one. A provider now declares the grammar and this server's support for it separately: SNOMED CT defines the grammar and this server evaluates none, UCUM, BCP 13, BCP 47, and the ICD-11 linearizations parse the grammars they declare, and a CodeSystem resource that declares a grammar is served without one. A post-coordinated code is refused as a grammar this server does not evaluate (not-supported) rather than as a concept the edition lacks.
  • A code system the deployment loaded reads at its own id and is found by a search. GET CodeSystem/{id} on the id the server prints at startup was a 404 and GET CodeSystem?url=… answered total 0, while the capability statement declared read and search-type and the configuration page documented the id, so a documented instance path addressed nothing. Every loaded version now answers both, under every version prefix: a system held behind an index answers its definition with content = not-present, and one loaded as a CodeSystem resource answers with the content it declared. A supplement stays applied to the system it supplements and is not served as an instance.
  • CodeSystem/{id}/$lookup answers under /r5 and /r6, whose OperationDefinition declares the operation at the instance level. The engine refused the instance level on every version; the level is now the served version's own declaration, so /r4 and /r4b, which declare the type level only, still offer no such route.
  • A SNOMED CT implicit value set or concept map based on a non-default edition answers when several editions are loaded. The FHIR SNOMED CT page lets any edition version stand as the base URL, and the edition in the base decides the membership, but the server only asked the default version of the system, so every ?fhir_vs form and ?fhir_cm= on another loaded edition was refused as a malformed URI. The registry now asks every loaded version, default first, so the bare http://snomed.info/sct base still answers from the default edition. A base naming an edition version no loaded version serves is a not-found on that version rather than vs-invalid.
  • $translate over a SNOMED CT map reference set returns a target Coding carrying both a system and a code. R4B needs ConceptMap.group.target, the "absolute URI that identifies the target system that the concepts will be mapped to", unless the target value set names a single system or every target equivalence is unmatched, and an implicit map states neither. RF2 records the scheme nowhere on a member row, so the reference set names it: the ICD-10 extended map (447562003), the ICD-9-CM equivalence map (447563008), the ICD-O map (446608001), the CTV3 map (900000000000497000), and the US Edition's ICD-10-CM map (6011000124106) each state the URI FHIR publishes for their scheme, on the served ConceptMap and on every match. A map reference set outside that table answers not-supported instead of a code with no system. An association reference set names SNOMED CT on both sides, whichever reference set it is.
  • The LOINC and RxNorm builds name a property key they never registered instead of reporting "too many concepts": a defect in the build no longer surfaces as a capacity error. The RxNorm relationship-type lookup is split the same way, and TooMany keeps its own meaning.
  • An expression constraint of deeply nested brackets no longer takes the server down. The ECL parser descends with the grammar, so an unbounded nesting exhausted the stack and aborted the process, which no OperationOutcome survives; the parser now refuses past sct_ecl::NESTING_LIMIT (64) and the server answers the refusal as an OperationOutcome. Found by the ecl_parse fuzz target.

Changed

  • A flat $expand answers in the order the compose selected: the includes in order, each include's named concepts as it named them, each filter's concepts in the code system's own order, and the first occurrence winning where includes overlap. count and offset page over that order. No FHIR version fixes the order of an expansion, and ValueSet.compose.include.concept says an expansion typically follows the compose; a compose of one filter still pages off the selection bitmap without reading a concept. The ICD-11 postcoordination axis now answers in the WHO's own scale order, which the terminology ecosystem suite's icd-11/expand-pcs-count and icd-11/expand-pcs-offset cases assert together.