Skip to content

0.1.1

Latest

Choose a tag to compare

@github-actions github-actions released this 01 Oct 17:32
· 9 commits to main since this release
Immutable release. Only release title and notes can be modified.
v0.1.1
11c757c

Added

  • The browser battery drives the published container image (#166).
    scripts/ui-e2e.sh --image REF pulls it, starts it over the same two
    committed templates and the same committed layout, and drives it with the
    same browser, building nothing from the tree. An image that answers
    /health and serves no /ui fails the run naming it, which is the one
    thing the mode exists to catch. It runs only the journeys that hold for
    every release, because the image is usually the last release and the rest
    assert what this tree does. The released workflow runs it weekly.

  • scripts/checks/site.sh, which fails when the published site disagrees with
    the tree it describes (#196). It checks that every version the landing page
    states is the version this tree releases, and that every corpus figure the
    site quotes is the figure the test suite asserts. The landing page said 2658
    fields across 1789 groups against a suite asserting 2621 and 1775, and its
    own meta description, which is what a search result shows, said "Nothing
    renders a form to a clinician yet". Prose stays review-enforced: a sentence
    saying a shipped capability is unbuilt reads exactly like a true one.

  • A partial date is collected one component at a time (#197). Where the
    template pins a precision the field keeps its native picker; where it admits
    several, no native control collects that, and the fallback used to be one
    text box whose placeholder was the ADL pattern YYYY[-MM[-DD]]. It is now a
    labelled box per component, on the precedent of the GOV.UK Design System's
    date input. A number typed short is padded, so 9 for September is written
    09, and a component to the right of an empty one is refused rather than
    closed up: openEHR RM Release-1.1.0 data_types.html section 7.1.2.2 drops
    components from the right and has no shape for a hole in the middle.

  • A group lays its items on a two-column grid from the medium breakpoint up,
    so a form of dates and counts reads across as well as down (#190). Most
    kinds draw one input and share a line; an attachment, a parsable body, a
    choice, an interval and an identifier keep the row, because each draws a
    control inside a control or four boxes of its own. Measured from the
    capture, the two committed corpus forms are 1568 and 2143 pixels tall,
    against 4190 and 3934 when the issue was filed.

  • The renderer reads the layout a person authored, which is half the product
    and until now the browser read none of it (#201). A form is drawn in the
    order they put its items in, under the names and the help text they wrote
    over the archetype's, starting from the values they chose, and an item
    behind a rule appears only while that rule holds. So a form grows as it is
    answered instead of asking every question at once: the family history form
    asks whether a family member has died, and the date and the age at death
    arrive when the answer is yes. No specification governs any of that, and it
    is what the overlay exists to carry.

    The server reads the layouts from FERROCHART_OVERLAYS, a directory of at
    most one overlay per template, and serves each as FormLayout at
    GET /api/templates/{template_id}/layout. A template nobody laid out
    answers with a layout that decides nothing, so a renderer has no absent case
    to tell apart from an unknown template. An overlay that will not read fails
    the startup, as a template that will not compile does, and so do two
    overlays over one template. e2e/overlays/ carries the one authored layout
    this repository ships, and the browser battery drives it.

  • The browser battery opens a section the template says may be absent and
    proves the fields inside it arrive (#202). A form now opens with those
    sections closed, so a battery that stopped at the first screen would never
    see what is in one, and the book would show a form nobody had touched. The
    capture runs the same proof, which is why the picture shows an opened
    section.

  • scripts/checks/changelog.sh, which refuses a release section with two
    headings of one change type (#184). Every pull request adds an entry under
    [Unreleased], and the quick way to do that is to paste a fresh
    ### Changed above the old one; three of those and one release has three
    Changed sections and a reader can no longer find anything. It also checks
    the headings are the six Keep a Changelog names, in the order that
    specification lists them, and that none is empty. Every section in the file
    is normalised to that shape, with no entry reworded.

  • The round trip against a real CDR runs on every pull request (#28). The
    live cases of ferrochart-cdr and ferrochart-server commit a COMPOSITION
    FerroCHART built and validated to a FerroEHR started from the release's own
    compose.yaml, read it back, and compare. They existed, and ran only when
    somebody remembered scripts/test-cdr.sh, so the one lane that can falsify
    the product's central promise was the one lane nothing enforced. A failure
    now prints what the CDR logged, because the container is gone by the time
    anybody looks.

  • The browser battery drives and photographs every screen, not three of
    eight (#192). The form screen with no template named, the three frames on
    the rail whose content is still to come, and an address no route owns are
    all covered, each with a proof of its own: the way out of a dead end, the
    heading and the line under it, and the way back. The first run of the new
    coverage found #191.

Changed

  • The Licensor and copyright holder of the project's own work is Vernum
    Projecten B.V. (#214). Every Licensor:, copyright and
    SPDX-FileCopyrightText line names the company. The licence terms are
    unchanged, and maintainer credit stays a person.

  • The repository moved to the FerroHEALTH organization
    (https://github.com/FerroHEALTH/FerroCHART, #224); the old
    rubentalstra/FerroCHART URLs redirect. The image now publishes to
    ghcr.io/ferrohealth/ferrochart, and the quickstart compose.yaml pulls it
    from there. Every tagged manifest up to v0.1.0 is copied there by digest and
    stays available under ghcr.io/rubentalstra/ferrochart, and its signatures
    name rubentalstra/FerroCHART as the repository that built it. The release
    lanes spell the image owner as a literal, because github.repository_owner
    is now FerroHEALTH and an OCI reference must be lowercase.

  • The published site says what is built (#196). Every page in SUMMARY.md
    was read against the code: the landing page no longer says the product
    renders nothing, the operations card no longer says the routes that do the
    work have not arrived, the status list says the browser reads a layout, the
    build order carries the current figures and names the milestones after it,
    and the renderer page no longer says the browser honours no overlay. The
    book gains the route table the "write your own renderer" page was already
    pointing at, and names the layout as the fourth published document with a
    version line of its own.

  • The frame stops spending a fifth of the window on nothing (#193). A
    320-pixel Inspector panel reading "Select a node to edit its layout" was
    drawn on every screen, including four that have no node to select and
    Layout itself, which says the authoring surface is not built. It arrives
    with the selection that drives it (#27). A breadcrumb of one entry is no
    longer drawn: it named the screen its own heading names, so Layout read
    "Layout" twice. And the three frames say what their screen will do rather
    than citing a tracker issue number at the reader.

  • Everything the project says about itself says what is built (#196). It
    was three releases behind and it understated the product to the people it is
    for. The README said the round trip had never met a real CDR and to treat
    the commit path as untested. The book's front page said the same, and its
    renderer page said no published artefact serves the screens, when the
    release binary embeds the bundle and the image copies that binary. The
    landing page told a reader "the ITS-REST client, the composition builder,
    and the FHIR terminology client are decided and scheduled for v0.0.5; they
    are not written yet", when all three shipped in that release, and its
    machine-readable version said 0.0.3. The build order read as a plan for
    work that has shipped, a health check example answered "version":"0.0.2",
    and an attestation example named a v0.0.5 asset.

    None of it was a version bump: every claim was read against the code. What
    the pages say is missing now is what is missing, which is the layout overlay
    reaching the browser and a form that can commit.

  • An open archetype slot reads as a place to add content, not a warning
    (#180). openEHR AM Release-2.3.0 AOM2.html section 4.5.8 gives
    ARCHETYPE_SLOT the attribute is_closed, "closed to further filling
    either in further specialisations or at runtime", and defaults it to false,
    so a slot that survived into an operational template is one the template
    meant to leave open. It was drawn as a yellow warning, and counted in a
    banner reading "the template left content undetermined", on 116 of the 121
    templates the committed pack compiles. It is a neutral notice now and the
    banner counts only what is genuinely undetermined, which across the whole
    pack is four nodes rather than 1194.

  • The Reference Model's own container is not drawn as a group (#190). RM
    Release-1.1.0 data_structures.html section 4.3 makes ITEM_SINGLE,
    ITEM_LIST and ITEM_TREE the structure an ENTRY attribute holds its
    content in; they exist because the model needs a container, not because
    anybody grouped anything, and the CKM archetypes head them "Tree" and
    describe them "@ internal @". Their contents are drawn where they were, so
    a form loses a nesting level and two meaningless headings. An ITEM_TABLE
    keeps its card because a grid is a shape a person reads, a CLUSTER keeps
    its card because a cluster is the clinical grouping, and a container that
    roots an archetype or repeats keeps its card because it carries something
    of its own. No key, value or composition node changes.

  • A timezone is chosen from the list the platform carries, and resolved to
    the offset at the instant entered
    (#197). It was a free-text field with a
    regular expression, so a person had to know their UTC offset and today's
    daylight-saving state and type +02:00 in a shape the pattern accepted.
    The list is the IANA Time Zone Database, whose registry RFC 6557 puts with
    IANA and which every current browser already carries: ECMA-402 publishes the
    identifiers as Intl.supportedValuesOf('timeZone'). Nothing is vendored,
    so the bundle carries no table. openEHR RM Release-1.1.0 data_types.html
    section 7.2.4 types DV_DATE_TIME on Iso8601_date_time, so the value
    carries an offset rather than a zone name, and Europe/Amsterdam is
    +01:00 in January and +02:00 in July; the offset is resolved for the
    instant the reader entered rather than for today. A platform that does not
    publish the list still gets the offset field.

  • A field that admits several precisions asked for YYYY[-MM[-DD]], which is
    ADL notation printed at a clinician (#197). It now asks for "A year, and a
    month and day if you have them". The pattern still gates what the browser
    accepts; only what a person reads changed.

  • A duration is a number and a unit (#198). "Age at death" drew Years,
    Months, Weeks, Days, Hours, Minutes and Seconds as seven number boxes plus a
    checkbox, for a question a person answers with "82". The family history form
    carried fourteen of those boxes, seven for the age at death and seven for
    the age at onset. It is now one number and one unit, and where the template
    admits a single unit there is no picker at all. A compound duration stays
    reachable behind "and…", so the rare case works and the common case costs
    nothing. The sign is offered only where a range could admit a negative
    duration, so an age bounded at zero no longer asks whether it counts
    backwards.

  • Two parts of a duration naming one unit are refused. assemble writes the
    first match per unit, so the second was being dropped without a word.

  • A form is a list of questions with answers, and most of what it drew was
    neither
    (#190). Four of the five lines a field drew were not the value.

    • A field carries a value or a reason there is none, never both. The
      null-flavour select was drawn full width under every field that offered
      one, which in the committed corpus is nearly every field, so a
      fifteen-field form carried fifteen extra dropdowns reading "No value,
      because: A value is entered". It showed a state openEHR RM Release-1.1.0
      data_structures.html section 5.2.3 forbids, since Inv_is_null_valid
      gives ELEMENT no state carrying the two together. A quiet "No value"
      at the end of the value row now replaces the control with the flavour and
      a way back.
    • A field name is 14px solid ink where it was 12px grey, the same weight as
      the help text under it. The name is what a person scans a form by.
    • The help text sits with the name it describes. Under the control it read
      as a caption for the next field.
    • A value sits in one box, not three. The per-field fieldset keeps the
      accessible name its legend carries and draws no border.
    • A date, a count and a unit stop at 28rem. Prose, an attachment and a
      choice keep the width, because their answers use it.
    • A choice picker is labelled "Kind of value" where it said "Which of
      these", and a repeat is headed "Entry 2" where it said "Occurrence 2".

    Measured in the browser, over the two committed corpus forms: the family
    history summary fell from 4190 to 3086 pixels and the alcohol consumption
    summary from 3934 to 2828, both a little over a quarter shorter. The capture
    prints the height of every screen it photographs, so the figure is read from
    a run rather than estimated.

  • The living style guide is no longer in a clinician's download, and the
    renderer bundle fell from 410995 to 359486 gzipped, a saving of 51506 bytes
    or 12.5% (#154). The design system draws every affordance the kit defines,
    which instantiates every control a second time, and it is a surface for
    whoever works on the kit rather than for a person filling a form. It is
    behind the design cargo feature now, which is on by default: trunk serve
    brings it up at /ui/design and the browser battery photographs it, while
    the release bundle is built --no-default-features. That build answers
    /ui/design the way it answers any address it does not serve, and the rail
    carries no entry for it. The feature is on by default so that an affordance
    the kit defines and nothing draws is still a dead-code error (#186).

  • The renderer says what a field collects instead of naming a Reference
    Model class
    (#178). A choice between unlabelled alternatives offered
    DV_COUNT and DV_QUANTITY as its options and now offers "a whole number"
    and "a measurement"; an undetermined hole read "ITEM_TREE is left
    undetermined." and now reads "The template leaves a group of fields here
    undetermined."; the line under it says what the template does and does not
    admit without spelling ELEMENT or DV_INTERVAL. The class name is a fact
    about the specification, and the audience came to build a form. The
    refusal message built in ferrochart-compose and the unlabelled-field
    fallback are the rest of #178 and are not fixed here.

  • A field the template never labelled says what it collects, and an
    unlabelled archetype root says its concept
    (#178). The fallback was the
    node identifier, so a form drew a heading reading at0004 or
    openEHR-EHR-OBSERVATION.blood_pressure.v2. An archetype identifier names a
    concept (openEHR BASE Release-1.2.0 base_types.html section 5.4.10), so a
    root is now called "Blood pressure"; below one the name leads with the value
    and keeps the code, as "A whole number (at0004)", because the code is what
    tells two siblings apart and dropping it would give a group several fields
    with one name. A browser journey over every screen the battery drives fails
    the build on an openEHR class name or a node code in the text a person
    reads, and skips the monospaced surface where the path deliberately stays.

  • A refusal on a link field read "The Reference Model class requires another
    URI scheme." and now reads "The link has to start with the scheme this field
    takes." (#178).

Fixed

  • The README's quick start runs as written (#213). docker compose --profile demo up failed before starting anything, because Compose resolves
    FERROCHART_CDR_URL and FERROCHART_TERM_URL before it considers a profile;
    the README and the compose header now set both to the demo services in the
    same command.

  • A timezone picked before the date was resolved against the wrong instant
    (#197). A zone is not an offset, and the offset was resolved once, when the
    zone was chosen. A reader who picked Europe/Amsterdam and then typed a
    January date kept whatever offset was in force at the moment they picked. It
    is re-resolved whenever the zone or the instant changes. A browser journey
    pins both halves of the year.

  • A date field spent half its width on a timezone it does not collect (#190).
    The temporal control drew a two-column grid whatever the field admits, so a
    date got one column of it and its placeholder read "Year, then month and day
    if kn". The grid is one column where there is no zone to put in the second.

  • A field the template fixed drew the sentence "The template fixed this
    value" instead of the value, and one the template also said may be absent
    could not be answered at all (#207). A template can narrow a field to one
    value and still leave the element optional, which is how the family history
    template asks whether a family member has died: the question is whether the
    element is recorded, and yes is the only answer it admits. The value the
    constraint names is now read in one place, FieldKind::only_admitted, which
    the derivation and the renderer both use. A fixed field shows the value it
    fixed; an optional one draws a checkbox that records it or leaves the
    element out; a required one is written into the document, so a COMPOSITION
    cannot go out missing a node the template requires.

  • A repeating group inside an occurrence a reader added opened with one
    entry, whatever its template said (#202). The count of occurrences a form is
    showing is seeded from the definition, and a group inside a section nobody
    had opened yet was never seeded, so the lookup answered with a hard-coded 1.
    It answers with what the template requires now. The browser battery found
    this the moment it started opening a section rather than photographing a
    closed one.

  • A section the template says may be absent opens with none of it (#202).
    A repeatable group opened showing max(1) occurrences, so a group whose
    template says 0..* opened one, expanded, with every field inside it drawn.
    openEHR AM Release-2.3.0 AOM1.4.html section 4.3.6 makes occurrences the
    count a node may appear in the data, so a lower bound of zero is the
    template saying none of that section is a complete answer, and the renderer
    was discarding the only statement a template makes about how much of itself
    applies. The family history form met a reader with a family member they had
    not said existed and a clinical history for them. It now opens as a heading,
    a description and "Add one". The floor on removing followed the same rule
    and used to be one whatever the template said, so an optional section, once
    added, could never be put back.

  • A field the template fixed showed no value and offered "No value" beside it
    (#190). "Deceased?" asked a question, answered "The template fixed this
    value, so nothing is entered", and then invited the reader to say there was
    no value. It shows what the template fixed it to now, and a fixed field
    offers no null flavour, because a value the template gave is not one a
    person can decline to give.

  • An address no route owns lost the whole application (#193). It was drawn
    outside the shell, so a reader who mistyped one had no rail, no theme
    control and one link. It is a route inside the shell now, and it points at
    the template library, which is somewhere a reader can act.

  • The form screen asked the server for a template with no name (#191). Landing
    on /ui/forms from the rail sent GET /api/templates//definition and took a
    404, because the guard sat on what the screen draws and not on the request.
    The screen looked right, which is why it went unnoticed until the battery
    started photographing it.

Security

  • rustls moves to 0.23.45 for RUSTSEC-2026-0285, TLS 1.3 handshake
    messages incorrectly accepted across encryption level boundaries (#221).
    The lockfile moves; no source changes.