Skip to content

Releases: Vernum-Projecten/Veredictum

0.1.6

Choose a tag to compare

@github-actions github-actions released this 21 Sep 13:32
Immutable release. Only release title and notes can be modified.
v0.1.6
07c5e5d

Changed

  • The repository moved to the Vernum-Projecten organisation, and the
    container image moves with it (#567).
    The console image publishes as
    ghcr.io/vernum-projecten/veredictum; the old
    ghcr.io/rubentalstra/veredictum keeps the tags it already carries and
    gains no new ones, so a deployment pinned to it stays on 0.1.5 until it
    moves. docker/docker-compose.yml, the hosted overlay and its
    env.example name the new reference, and the image's
    org.opencontainers.image.source label points at the new repository, which
    is what links the package to it. The registry's own trust anchor moves too:
    a reproduced or console-tier record is issued by a workflow under
    Vernum-Projecten/Veredictum, and a submission naming the old repository is
    refused.
  • The copyright holder of Veredictum's own work is Vernum Projecten B.V.
    (#556). LICENSE and NOTICE name the company beside the Veredictum
    contributors; the Apache-2.0 terms are unchanged, and maintainer credit
    stays a person. The FerroEHR party statement the test fixtures carry
    names the company as vendor, as FerroEHR's own statement now does.
  • The hosted instrument's box grew from a Hetzner CPX12 (1 vCPU, 2 GB) to a
    CX33 (4 vCPU, 8 GB), and its concurrency cap moved with it: the official
    instrument at console.veredictum.eu now drives two runs at once, with the
    queue covering everything past the cap as before (#523). The README's
    stated conditions and the committed deploy posture describe the new
    machine.

Fixed

  • The console's body limit reached only the five server-owned routes, so every
    #[server] endpoint kept axum's 2 MiB default and a paste past it was cut
    off by the transport before the page that judges it ever saw it. Each
    endpoint now carries a cap derived from the number its own code enforces, so
    every payload an endpoint accepts reaches the code that judges it, and a size
    refusal within the transport cap is that endpoint's own sentence (#496).
  • A finished run's elapsed time on the console's live screen kept growing on
    every read, because the snapshot derived it from the wall clock instead of
    the run's own completion instant. A terminal run (finished, cancelled,
    expired, or failed) now reports the fixed duration it actually took (#464).

Security

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

0.1.5

Choose a tag to compare

@github-actions github-actions released this 01 Sep 07:41
Immutable release. Only release title and notes can be modified.
v0.1.5
d30b078

Added

  • Every declared fact in a results document says where it came from (#461).
    Two members in results.json, both published in
    schemas/results.schema.json. tech_profile.source reads declared when
    the party statement's its-rest entry named the recorded format list, and
    defaulted when no declaration named this ITS and every format the
    instrument speaks was recorded instead. ambiguity_dispositions now carries
    what the campaign applied: one record per option_select register arm the
    ICS declared, in the register's authored order.

    What it closes: a run that declared no technology profile published five
    formats, canonical-xml among them, and nothing in the document said whether
    that was a claim or a fallback. The recorded list is what the verdict
    pipeline selects gating records with, so the two carry different claims. The
    dispositions were a hardcoded empty list on a run that drove both arms of
    fifteen register-tracked option families, and the empty list is now the
    honest record of a campaign that answered none.

    One constructor assembles the document for both campaign seams, the live run
    and the re-judgement of a recording, so a member added to one is a compile
    error at the other rather than a silent difference between two records.

    Absence is unknown, never a value. A document written before a member existed
    carries none, and scripts/checks/registry-rederive.sh reports the absence
    and recomputes anyway. Members that contradict each other are refused:
    replay --against refuses a record reading tech_profile.source: declared
    beside selection_basis: statement_blind, because no re-judgement
    reconstructs a campaign that had no declaration to read a profile from.

  • A results document names the statement that selected it (#490). New
    statement_digest member in results.json: the leading 8 bytes of the
    SHA-256 over the party statement's bytes as they sit on disk, 16 lowercase
    hex characters, the same shape ixit_digest already published. A reader
    holding the declaration a record was driven under recomputes it with
    sha256sum statement.json | cut -c1-16. run and replay both write it,
    and schemas/results.schema.json publishes it.

    What it closes: a record identified the claim it was selected under by
    selection_basis and the declared its-rest format list, so two different
    statements declaring the same formats were one value. replay --against now
    refuses a re-judgement handed a statement the record does not name, and the
    refusal prints both digests. The console tier's whole claim is that CI
    re-derives the verdicts from the recorded exchanges, and a re-derivation
    under somebody else's claim is not a re-derivation of that record.

    Absence is unknown, never a match. A campaign no statement selected writes no
    digest, which selection_basis: statement_blind already says out loud, and a
    document written before the member existed carries none either. A
    re-derivation of such a record is reported and recomputed rather than
    refused, so scripts/checks/registry-rederive.sh keeps re-deriving every
    record published before this release.

  • A red run exports the evidence behind its own rows (#463). New subcommand
    veredictum evidence, which carves a named set of a finished run's recorded
    exchanges out of its transcript.json and writes them as one bundle. It reads
    no statement: sealing a record needs a claim, and reading the exchanges a run
    recorded does not, which is exactly the case when a run has gone red. One
    command turns the red rows into a triage input:

    veredictum evidence --transcript run/transcript.json \
        --results run/results.json --failing --out run/evidence.json

    --failing selects every failed and errored case the results record
    names; --only <CASE> (repeatable) and --filter <SUBSTRING> name a set
    directly, and the three union. Each exported case carries the outcome row the
    run recorded beside its requests and responses, so a reader holds one
    document rather than two.

    An export that would carry nothing is refused, exit 2, with no file
    written. A selection matching no recorded case names what was asked for and
    what the transcript actually carries; a selection whose every case recorded
    nothing names those cases. A selection that half-matched still exports, and
    the bundle's without_exchanges names every case it could not carry, so a
    partial answer never reads as a complete one. This is what the first live
    triage's hand-written extraction got wrong: it produced 130,761 empty objects
    and zero scalar values, valid JSON of the right shape and size with nothing
    in it, and nothing said so.

    The authorization request header's value is withheld by the export itself,
    whatever the transcript held, pinned by a test over a run driven with a
    credential. Response bodies are the wire's own bytes and can carry real
    patient data, so the bundle is operator-controlled output like the transcript
    it comes from.

    The console offers the same document on a red run: the results screen's
    Evidence for a triage section downloads it from /export/evidence.json,
    and says which of the two reasons applies when it cannot — no row went red, or
    the run was driven without recording its wire.

    schemas/evidence-bundle.schema.json is the published shape, drift-guarded
    like every other emitted schema.

Changed

  • The command reference and the engine pin are generated (#466). The CLI
    surface is what clap declares, and three documents used to restate it by hand
    under a guard that compared subcommand names. Now
    the command reference is rendered
    from veredictum <command> --help by scripts/render/commands-md.sh, the
    hand-written notes per command sit beside it in website/book/commands/, and
    scripts/checks/cli-surface.sh refuses a committed page the generator does
    not reproduce. So a flag's help text reaches the published page in the change
    that edits it. The binary's own header listing and the root CLAUDE.md table
    are gone; both point at --help and at that page.

    The console's ENGINE_PIN is emitted by a new
    app/veredictum-console/build.rs out of the manifest's exact crates.io pin,
    so the version the chrome displays cannot disagree with the version the
    console links, and a release cut moves one line instead of two.
    results.example.json gains the drift gate it never had: it carried a
    version two releases old, and scripts/checks/example-results-drift.sh now
    holds the committed copy to its generator's output.

  • The proforma stays, the answers leave (#465). ISO/IEC 9646-7 splits an ICS
    in one place: every cell of the proforma belongs to its specifier except the
    support and supported-values columns, which belong to the supplier of the
    implementation, and ISO/IEC 17050-1 is titled a supplier's declaration of
    conformity. This repository was committing two filled-in declarations, one of
    them about EHRbase, a product nobody here speaks for. Both are gone. The
    proforma stays exactly where it was: artifacts/vocab/capability_matrix.yaml,
    43 rows with a specification citation each.

    What this changes for anyone driving the instrument. validate sweeps no
    party/ directory any more and gains --statement <FILE>, which runs the
    static conformance review of ISO/IEC 9646-1 and -7 over one submitted
    declaration: a claimed capability with no verdict-bearing case, a Signing
    claim whose ixit declares no posture, a served-extension family the wire
    surface does not carry. Every one of those checks survives unchanged; only its
    input moved from a committed fixture to a supplied document. The summary line
    now counts capability rows where it counted party statements, and the
    console's instrument page does the same. workload-coverage and the
    hollow-battery half of claim-completeness are re-grounded on the matrix, so
    the catalogue side of both is enforced over all 43 rows whatever anybody
    claims — measured by experiment before anything was removed: emptying one
    capability's battery is still caught, by capability-depth, naming the row
    and the shortfall.

    The console stops offering a list of committed declarations to attach. The
    claim is the submitter's, so the paste box and the compose-from-tiers button
    are the only ways one enters, and the endpoint that read a statement from a
    client-supplied path is gone with the tree it read from. The published image
    no longer carries /work/party and VEREDICTUM_PARTY is retired.

    The reproduced tier's question is answered in registry/RULES.md rather
    than left open: without a supplier declaration there is no claim and so no
    conformance verdict, so a reproduction either cites a declaration the supplier
    published or publishes a survey labelled as an observation. Neither committed
    topology cites one, so both dropped their statement, and the lane refuses to
    bundle a reproduction rather than inventing a claim. The submission criteria
    an entry is scored against are unchanged, so the rules version is unchanged.

    One filled-in declaration survives as a named test fixture,
    fixtures/declaration/, for a product that does not exist. The SMART lane's
    committed test issuer moved beside it as fixtures/smart-test-issuer/,
    contents and warnings untouched.

Fixed

  • A case declaring no capability is refused at authoring time (#500). The
    two readers of a case's capabilities list disagreed about the empty one:
    the runner drove such a case against a server, and the verdict pipeline
    deselected it because no claim intersects an empty list. The row burned a
    server's time and bore no verdict. An empty list is now illegal: the
    published case-core schema carries minItems: 1 on capabilities, so
    validate report...
Read more

0.1.4

Choose a tag to compare

@github-actions github-actions released this 31 Aug 11:30
Immutable release. Only release title and notes can be modified.
v0.1.4
ad5eb70

This release builds the hosted instrument and everything that judges what it
produces: console.veredictum.eu on a box this repository provisions, several
people driving the catalogue at once, a submission opened by the instrument's own
App identity, CI that re-derives a submitted record's verdicts before anything is
signed, and a signing key that exists only in a protected environment.

No record has travelled that path yet. Nothing has been driven at
console.veredictum.eu, submitted, re-derived, signed and verified offline as one
sequence. Every part of it is tested on its own and the parts have not been run
in series, so read this as the pipeline arriving rather than as a result. The
first record is what v0.1.5 exists to produce.

Added

  • One image, carrying the data it judges against (#420). The published
    image now holds the catalogue, the vendored specification oracle and the party
    declarations at /work, so docker compose up grades a server in an empty
    directory and the hosted instrument mounts nothing. It replaces a second image
    whose only content was those three directories copied over the release, and
    whose data came from whichever branch last built it — so the official
    instrument was pairing a released engine with an unreleased catalogue. An
    operator who wants their own trees bind-mounts over the baked paths, which
    still takes precedence. The image declares
    eu.veredictum.image.carries-catalogue, and the hosted deploy refuses an
    image that does not, so an older release cannot reach an instance that would
    find /work empty.
  • The registry signing key exists, and its public half is committed
    (#403).
    registry/keys/registry-signing.pub.asc is what a reader checks a
    published console record against, with the instrument through
    veredictum verify-record or without it through gpg --verify. The primary
    key certifies and an ed25519 subkey signs, so a verified record names the
    subkey fingerprint. The secret half is in the registry-signing environment
    and nowhere else: it was generated in a throwaway keyring, never entered a
    personal one, and that environment carries required reviewers plus a branch
    policy naming main alone. Before it was used, the engine's own signing and
    verification code was run over this exact key material, because the committed
    test keypair is RSA and an EdDSA key would otherwise have reached production
    on a path nothing here had exercised.
  • A finished run submits itself to the registry (#391). The console's
    /run/submit screen states what the run knows — the endpoint it drove, when
    it started, the catalogue revision, the engine version — and collects the
    disclosure the submission rules make mandatory, the conflict-of-interest
    sentence included. An empty mandatory value is refused by name before
    anything is opened. The instrument then writes the entry and the five record
    files through its own GitHub App identity: blob, then tree, then commit, then
    ref, so the commit GitHub signs is the one that lands, and a commit reported
    unverified pushes no branch at all. The submission arrives on
    console-run/<run-id> and carries no provenance block, because the
    re-derivation lane writes that after it has recomputed the judgement. The App
    identity is VEREDICTUM_GITHUB_APP_ID, VEREDICTUM_GITHUB_APP_KEY,
    VEREDICTUM_GITHUB_INSTALLATION_ID and VEREDICTUM_REGISTRY_REPO; any of
    them unset is a first-class state that explains what to configure and offers
    no button. No credential the run was driven under reaches the branch, pinned
    by a gate over a run driven with one.
  • A recorded run can be re-judged from its own transcript: veredictum replay (#392). The transport is now the only seam between the driver and
    the wire, so a replay answers every composed request out of the recording and
    reaches its outcomes through the same request composition, response
    classification and assertion evaluators the live run used. With --against
    it holds a submitted results.json to what the recorded exchanges support and
    names every row that differs. A case whose recording runs out, or whose replay
    composes a request the recording does not carry, records a transport failure:
    a verdict is never reproduced over evidence nobody has.
  • The console tier's lane (#392). scripts/checks/registry-rederive.sh
    re-derives a console submission's outcomes from its transcript and its
    verdicts from its outcomes; .github/workflows/registry-console.yml runs
    that gate, then seals the record from a protected environment and writes the
    provenance block the instrument is not allowed to write for itself. A record
    altered after the run fails the gate, which is pinned by a test.
  • A conformance entry may carry the statement it was judged against, so a
    claim that lives nowhere else is still one anybody can recompute against. A
    console entry must carry it, with the transcript and the ixit.
  • Two people can drive the hosted console at once (#389). The one job slot
    is a map keyed by the run id, so several runs execute side by side and every
    seam addresses a named run instead of asking whether one exists. Two drive at
    once, a start past that ceiling is accepted and QUEUED with its place and an
    estimated wait, one address gets one run in flight and a second start is
    answered with the run it already has, a run past thirty minutes of wall clock
    is ended by the console with its partial record discarded, and finished runs
    are evicted from memory oldest-first while their artifacts stay where the run
    wrote them. The connection draft is per submitter too, so two visitors
    composing a connection no longer overwrite each other. The caps are named in
    one place and are starting values to re-measure on the chosen host.
  • VEREDICTUM_CLIENT_IP_HEADER (#389). Behind a proxy the peer address is
    the proxy, so the console reads a forwarded client address only from the
    header the operator names; unset, it uses the socket peer and reads no
    forwarded header at all.
  • VEREDICTUM_POSTURE, and the targets a public instance refuses (#390).
    A hosted console drives whatever endpoint a visitor names, so it can be
    pointed at addresses only it can reach. Set the variable to hosted and the
    console refuses loopback, RFC 1918 private, link-local, unique-local,
    unspecified, multicast, RFC 6598 shared and broadcast targets in both address
    families, the IPv4-mapped IPv6 forms included, before any socket opens; the
    name is resolved first and every address it answers with is checked, because
    a hostname under the visitor's control resolving to a private address is the
    whole attack. The
    refusal names the address, the family and the RFC that defines it, and it
    reaches the visitor as a notification. Both seams that reach a
    visitor-named endpoint are covered: the reachability probe, and the run
    start before the engine is spawned. Unset or local refuses nothing, so an
    operator keeps driving a CDR at localhost; any other value refuses to
    start, because a public instance that read a typo as local would drive
    whatever a visitor named.
  • Per-address rate limits on the probe and the run start (#390). They read
    the same submitter identity the concurrency caps use, and a refusal states
    when the visitor may try again.
  • The registry publishes a third kind of entry: console (#393). A run
    performed at console.veredictum.eu, the official hosted instrument, against
    an endpoint the submitter named. Its verdicts are re-derived here from the
    transcript the submission carries, and the record is signed only after they
    match, with a key held in a protected CI environment that the instrument
    cannot reach. Every field of a console provenance block is written by that
    lane rather than by the instrument, so a performer cannot state its own
    provenance. registry/RULES.md states what the kind attests and what it
    cannot — it cannot attest the environment, because the submitter chose the
    endpoint — and the conformance board labels and orders the new rows.
  • The hosted posture travels inside the image (#423). The published image
    now carries deploy/hosted/docker-compose.yml and deploy/hosted/Caddyfile
    at /app/posture/, and the one command the hosted box's deploy key may run
    extracts them from the image it just pulled and installs them. Before this,
    a committed change to either file reached the box only when somebody copied it
    there by hand. A posture change now arrives the way a catalogue change does,
    at a release, with the provenance of the artifact it travelled in, and the
    deploy key gains nothing: it still runs one script and writes no arbitrary
    file. An extraction that comes out empty stops the deploy, a candidate compose
    file docker compose config refuses to parse is never installed, each
    replaced file is kept as .prev, and a changed Caddyfile restarts the caddy
    service — a bind-mounted file's contents changing does not recreate the
    container that mounts it, so without that restart a proxy change served
    nothing.

Changed

  • Every reader-facing page describes the hosted instrument as what it is
    (#395).
    console.veredictum.eu is the official conformance instrument: a run
    performed there is an official run, and the record it produces is re-derived
    and signed here. The README, the landing page and the book say that, along
    with the one thing such a record cannot attest — the submitter chose the
    endpoint. Running the instrument yourself publishes your own claim, which the
    same pages now describe as a different question rather than a lesser one.
    scripts/checks/hosted-instrument-language.sh refuses the words "demo" and
    "sandbox" on every surface a reader meets, as whole words, so demonstration
    and the CSP directive name are untouched.
  • **The hosted instrument runs on a box this re...
Read more

0.1.3

Choose a tag to compare

@github-actions github-actions released this 30 Aug 18:08
Immutable release. Only release title and notes can be modified.
v0.1.3
2afe985

Changed

  • The console speaks about the console (#382). Every screen that printed a
    command line or pointed at a terminal now states what it did itself: the
    verify page's "check it without this page" box, the benchmark pages' three
    command boxes, the empty-state hint that told a reader to run bench, and
    the verdicts line about "the bodies the command line writes". Documents that
    leave the console keep their verification instructions, because their reader
    is holding a record rather than looking at a screen.

Fixed

  • Every server function answered 404 in the published image (#381). A
    server-function URL is xxh64 over the crate's absolute manifest directory
    unless SERVER_FN_OVERRIDE_KEY says otherwise, and the release pipeline
    builds the two halves in different places: the server binary inside a job
    container, the WASM bundle on the host runner. The 0.1.2 image therefore
    registered one set of paths and requested another, so every call the
    hydrated console made fell through to the not-found page. A workspace
    .cargo/config.toml fixes the key for every build, and the image smoke now
    diffs the shipped binary's path set against the shipped bundle's and
    refuses any difference.

0.1.2

Choose a tag to compare

@github-actions github-actions released this 30 Aug 16:46
Immutable release. Only release title and notes can be modified.
v0.1.2
c323f04

Added

  • The hosted console is documented where readers look (#374): the README,
    the landing page and the book's entry pages name
    https://console.veredictum.eu as the no-install path, with its ephemeral
    lifecycle stated plainly.
  • The two 409 delete-conflict ETag outcomes assert the W/ weakness
    indicator behind applies: { its_rest: ">=1.1.0" }, the same sentence and
    gate as the thirteen 412 outcomes #360 ratcheted (#361).
  • The error-response surface the released ITS-REST actually pins gains its
    coverage (#340).
    A new present-with-body header matcher carries the
    Resources.md §JSON Format MUST in its own shape — the header is asserted
    when the response carries a content body and carries no criterion when it
    does not — and the demographic create binding's 400 outcome now declares it
    for Content-Type, with the media type itself grounded on the OAS
    (specifications/responses/400.yaml, content: application/json) because
    the docs text names no media type for an error body. Register AMB-217 is
    untouched: the error body's members stay unpinned. The new
    create_party-error_body_content_type case and the
    error-body-content-type wire-surface element name the behaviour, so a red
    row localizes to it.
  • One header may declare several expectations. The outcomes.*.headers
    value now accepts a sequence beside the single form, so two rules of
    different strength or different dating on the same header each keep their own
    ground. Every 412 outcome that expects the latest version_uid in ETag
    now also asserts the W/ weakness indicator behind
    applies: { its_rest: ">=1.1.0" }, which ratchets that MUST from one
    binding to thirteen.
  • The archetype-root invariants reach every top-level class the release
    makes a root (#339).
    Two refusal cases with their invalid corpus twins:
    an EHR_STATUS whose root archetype_node_id contradicts its
    archetype_details.archetype_id (RM EHR_STATUS is unconditionally an
    archetype root), and a directory FOLDER whose archetype_node_id is empty
    (Archetype_node_id_valid binds every LOCATABLE). Template-level
    validation of EHR_STATUS and FOLDER commits has no released wire binding —
    the only released 422/template sentence reaches COMPOSITION and the
    DEVELOPMENT demographic surface — so that boundary is register entry
    AMB-230, reported upstream (#355), never an invented expectation.
  • The hosted console (#348). The released container image serves the
    public reading surface at console.veredictum.eu on Vercel: the catalogue,
    the party statements and the specification oracle, baked into the image
    from the checkout. The posture is view-only by construction, because the
    image ships no engine binary. Deploys ride the project's Deploy Hook only —
    a real release pings it after the image tags apply, a posture push and a
    manual dispatch redeploy the same image — and the verification polls the
    served engine X.Y.Z footer, never a bare 200.
  • The dump/load authorization refusals drive without a declared
    dump_location: the refusal is a role or authentication decision taken
    before any path is consulted, so a literal placeholder location suffices
    and the boundary is testable on every party that declares the admin split
    (#286).
  • Signing-on posture profiles (#335). Every bench pack defines
    minimal-signed-digest and minimal-signed-pgp beside minimal, so a CDR
    that signs versions out of the box benches without switching a shipped
    feature off; the canaries keep refusing any declaration the deployment
    contradicts. Pack versions move with the definition (community-vitals
    and aql-mix to 1.1.0, smoke to 1.2.0) and the generated pack manifest
    and methodology page follow.
  • bench warns once when a credential rides a plain-http base URL that is
    not loopback; the run proceeds, because the operator names the transport
    and a local quickstart is legitimately http://localhost (#296).

Fixed

  • The image carries the engine (#375). Every published image so far held
    only /usr/local/bin/veredictum-console, and the console spawns the pinned
    veredictum binary to drive a run — so the compose quickstart's console
    served its screens and failed every run it started. Both build paths now
    ship the engine beside the console at /usr/local/bin/veredictum, the
    runtime names it in VEREDICTUM_ENGINE, and the release smoke asks the
    pulled image for veredictum --version and refuses anything but the
    released version. Proving that on the from-source path exposed a second
    break in the same build: .dockerignore excluded assets/, which the
    console compiles against twice over — its public/ entries are symlinks
    into assets/brand/, and its export module reads the seal-card master
    through include_str! — so --target runtime-from-source had been failing
    to compile at all. assets/brand/ is re-included. The hosted console at
    console.veredictum.eu gains the engine with it (owner ruling): a visitor
    can drive a real run against a CDR they control, writing into a /work/out
    the overlay creates for the console's own uid, and that output is gone at
    the next deploy.
  • The published image hydrates (#369). The per-architecture ssr binary
    was compiled without LEPTOS_OUTPUT_NAME in the compiler's environment, so
    leptos's option_env! probe baked a _bg wasm URL into it while the site
    bundle ships the cargo-leptos-named veredictum-console.wasm — every
    published image to date served its pages SSR-only and 404'd its own client
    bundle on each load. The compile step now carries the name, and the image
    smoke fetches every /pkg/ asset the served page references, so the class
    cannot ship green again.
  • One judgement per sealed record (#243). Preparing the console's export
    ran the full judgement five times over the same run — once per fact the
    summary, the seal card, the badge and the HTML report each asked for — and
    reading the export section ran it twice more. One judgement of a
    1,147-outcome campaign costs about 2.7 seconds on an unloaded developer
    machine and far more on a busy one, so the repeats were most of the wait
    between the engine's manifest and the rendered files. The judgement now runs
    once and feeds all of them. What the bundle contains is unchanged: the same
    manifest, the same signature, the same three presentation files.
  • The book's console screenshots stop changing on every capture pass
    (#243).
    A capture pass now serves the console in capture mode, where the
    run clock, the record digest and the signing time render as fixed stand-ins,
    so six images no longer churn with no interface change behind them. The mode
    changes what the screen displays and nothing that is written, sealed or
    signed, and it is off in every ordinary run.
  • An XML response body is refused as unjudgeable instead of read as an empty
    document (#285).
    The driver collapsed every body it could not parse as JSON
    into a plain string, so an XML-negotiated read reached the field,
    equivalent, instance_of, result_set and signature families as a value
    with no members and each one reported the asserted fact absent — a failed row
    charged to a server that answered exactly as it was asked to. Canonical XML
    and canonical JSON are separate bound document forms (ITS-REST
    specifications/docs/overview/Resources.md §Data representation) and this
    runner parses the JSON binding only, so those families now take the
    inconclusive channel with the served media type named, and the version
    family refuses the same way when its ORIGINAL_VERSION envelope read comes
    back unparsed. Nothing narrows on the JSON path, xml_root and returns
    keep grading the served text, and a uid_pattern judged off the resolved
    identity still gates.
  • A lifecycle_state assert reads an IMPORTED_VERSION through the version
    it wraps (#322).
    The judge read the property off the top level of the
    served envelope, which an imported version cannot carry: released ITS-JSON
    components/RM/Release-1.1.0/Common/IMPORTED_VERSION.json requires
    contribution, commit_audit and item under
    additionalProperties: false, and RM common
    UML/classes/imported_version.adoc §Functions effects lifecycle_state ()
    from _item.lifecycle_state_. A conformant server was charged a failed row
    for answering exactly as the release binds it. The row now resolves the fact
    through item, a wrong term still fails, and change_type keeps reading the
    wrapper's own commit_audit, which is a real property of the class.
  • The measured path stops substituting silently for a defect (#293). A
    workload stage naming an operation the vocabulary does not carry is now a
    named finding at the schedulable filter, so a typo'd op fails loud
    instead of dropping its journey from the mix and quietly shrinking the
    offered load. The corpus stride forms its product in u128, where the
    widest operand pair needs 96 bits, so the overflow fallback that stopped
    striding past ~6.9e9 arrivals is gone rather than proven unreachable. The
    capture store's cleanup path recovers a poisoned shard the way its read
    path already did, so a worker that panics mid-window cannot leak every
    instance hashing to that shard.
  • The latest-version-uid ETag comparison names the object it is about
    (#235).
    The driver kept one last_version_uid slot for the whole row, so
    a row that wrote object A and then provoked an error on object B graded B's
    entity tag against A's uid. The slots are now per versioned object, keyed by
    the object_id of the committed OBJECT_VERSION_ID (BASE base_types
    master05 §Syntaxes), and the object a step addresses is read from the path
    parameters the request was built from, falling back to the If-Match the
    request sent for the directory and ehr_status routes that carry no uid...
Read more

0.1.1

Choose a tag to compare

@github-actions github-actions released this 30 Aug 06:15
Immutable release. Only release title and notes can be modified.
v0.1.1
e8ed516

Added

  • A public results registry with signed submissions and two labelled tiers
    (#158).
    Published results now live in one append-only tree, conformance and
    benchmark alike, and every entry carries who submitted it, what they
    disclosed, the artifacts it stands on by digest, and how far anyone here
    verified it.
    • schemas/registry-entry.schema.json is the versioned entry format, emitted
      from the code like every other published schema. The disclosure is
      mandatory: the submitter and their relationship to the system, the
      deployment with its image digests, the instrument version, the machine, what
      was switched on behind the result, and the interest the submitter holds in
      the outcome. schemas/registry-topology.schema.json is the second new
      schema, for the deployments the reproduction lane may compose.
    • The tier is the discriminant of the entry's provenance block, so it cannot
      be claimed without the evidence its variant requires. reproduced names a
      workflow of this repository, its run, and the attestation predicate;
      self-reported names the scheme, the signature, the artifact it covers and
      the command that checks it. No signing key exists in this repository or in
      its Actions
      , and the gate refuses one committed under the registry.
    • .github/workflows/registry-reproduce.yml is the tier-1 lane: it composes a
      topology declared under registry/topologies/, drives the catalogue, and
      attests the run, the judgement and the images that actually answered from
      the workflow's own OIDC identity through Sigstore. It composes nothing a
      submitter wrote, and it does not gate a merge.
    • scripts/checks/registry-submission.sh is the submission gate, wired into
      CI as its own tier: append-only over the entries and their evidence, the
      schema and the rules, id uniqueness, every artifact digest recomputed, the
      supersede edges resolved, the pairing with the benchmark board's records,
      and both boards held to what is committed.
    • Two rendered boards, kept separate on purpose. conformance-board.html is
      new and reads its numbers out of each entry's own verdicts.json;
      benchmarks.html now takes its tier badge from the registry instead of
      printing one constant. Both carry the standing boundary: an entry is a
      report, never a certificate.
    • registry/RULES.md is the published submission contract, covering the two
      tiers, the mandatory disclosure, append-only with supersede-by-reference,
      the dispute path, and the standing authorization a hosted-endpoint
      reproduction needs.
  • The Robot-battery coverage gaps close on released ground (#220). Eleven
    cases and one binding variant, each derived from the released text rather
    than from the foreign suite's expectation.
    • AQL LIKE gains its escape row: master03 §LIKE states "To match a literal
      ? or *, the respective character in a pattern must be escaped by using
      the backslash \ character", so an escaped wildcard selects only the
      literal character while the unescaped twin still matches the whole set.
    • ORDER BY and the aggregates gain their non-numeric rows: a DV_DATE_TIME
      and a DV_TEXT path sort ascending by default, descending on DESC, and
      resolve a tie on the leftmost expression with the next one; MIN/MAX
      return the edges of a non-numeric ordered set in the input's own type and
      COUNT returns an Integer over the same argument.
    • A result_set assertion may declare cells: instant, and the two
      non-numeric query cases above declare it on their date/time rows. ITS-REST
      docs/overview/Resources.md §Datetime format assigns the query path only
      a SHOULD ("Retrieval or querying those resources SHOULD return date,
      datetime, or time values in the (original) format provided by underlying
      backend engine"), and BASE iso8601_timezone.adoc §Description makes Z
      "a literal meaning UTC …, i.e. timezone +0000", so a served +00:00 is
      the same fact as a committed Z. Under the mode the row gates on the
      instant and the run prints the tolerated respelling as an observed: line
      beside the tally. The default is unchanged exact-lexeme comparison, which
      is what tests the unconditional write-path sentence one line above the
      SHOULD; match: count refuses the modifier, because it compares no cell.
    • SUM and AVG declare Integer or Real input and assign nothing outside
      it, so register entry AMB-227 (option_select, upstream #229) records the
      silence and twin cases pin the two branches a party may declare,
      aql-nonnumeric-aggregate-refused and aql-nonnumeric-aggregate-executed.
      No case asserts a value the released text leaves unassigned.
    • The is_modifiable refusal reaches the update and delete routes. The
      composition and directory PUT and DELETE are refused on a deactivated EHR
      under register AMB-82, each row verifying through a read that the refused
      write committed nothing, and the positive twin proves the RM carve-out:
      the EHR_STATUS of a deactivated EHR is still writable, which is the only
      route by which an EHR is reactivated.
    • RESULT_SET metadata is judged exactly as far as the released ground
      reaches. The docs text calls every member "optional (implementation
      dependent)" and the released schema permits additional members, so nothing
      is required; what a service does serve is held to its declared shape by a
      new absent_or_matches field predicate, which passes on an absent member
      and judges a present one.
    • The catalogue carries 1130 cases and 249 bindings; the AqlBasic,
      CompositionOps, DirectoryOps and EhrStatus depth floors move to 52,
      63, 95 and 52.
  • The content-validation chapter reaches inside the data structure (#220).
    Nine cases close the constraint axes the chapter never carried. A dedicated
    CONT-DV_TEXT-validate_pattern runs a real regular expression through
    C_STRING.pattern on a DV_TEXT, the sibling the DV_URI and DV_EHR_URI cases
    already had. Four cardinality cases constrain the member container of each RM
    container class — ITEM_TREE.items, ITEM_LIST.items, ITEM_TABLE.rows and
    CLUSTER.items — over all six intervals and member counts 0, 1, 3 and 6;
    CLUSTER.items is 1..1 in the RM, so a zero-member CLUSTER is refused even
    under an unbounded cardinality, which is the one place the four classes
    differ. CONT-ELEMENT-value_null_flavour_existence puts
    C_ATTRIBUTE.existence on both ELEMENT attributes and pins the invariant
    that ties them: exactly one of value and null_flavour is present, so
    committing both or neither is refused. Three CONT-ITEM-type_* cases narrow
    an ITEM_TREE member slot through C_OBJECT.rm_type_name across the abstract
    ITEM class and its CLUSTER and ELEMENT subtypes. The catalogue carries 1128
    cases, and the ArchetypeValidation depth floor moves to 134.
  • A client body uid never survives a content-object commit (#202).
    Register entry AMB-226 (fixed_handling, upstream #221) records the silence
    the released text leaves on composition_create, directory_create and
    ehr_status_update: none of the three says what a service does with a
    client-supplied body uid, and none declares a conflict response to refuse
    with, where the CONTRIBUTION create states the rule and the COMPOSITION
    update states a match rule against the URL identifier. The commit succeeds
    and the served identity is the server-minted OBJECT_VERSION_ID. Three
    cases pin it — I_EHR_COMPOSITION.create_composition-client_supplied_uid,
    I_EHR_STATUS.clear_ehr_queryable-client_supplied_uid and
    I_EHR_DIRECTORY.create_directory-client_supplied_uid — each asserting the
    commit is accepted, that the version identity the response names is not the
    client's value, and that the client's own identifier addresses nothing
    afterwards.
  • The web console reads bench records (#166). A /benchmarks surface
    lists every bench-result*.json under the mounted output directory, and
    takes uploaded ones through a plain HTML form that needs no JavaScript. An
    uploaded batch is transient and swept on a timer, because the console stores
    nothing of its own. A record opens in full: the pack and the machine that
    offered the load, the posture block with every item labelled verified or
    declared-only, whether the record is submittable and which requirement it
    misses, the cross-repetition percentiles in microseconds with the millisecond
    reading beside them, the failed-arrival reading of every repetition and phase
    on the target and on each baseline, the same-machine baselines with their
    pinned images and recipe, and the relative index the record derived. Two or
    more records align side by side, and the pack, host, posture, scale and
    submittability mismatches are stated above the numbers rather than left for a
    reader to notice. Every figure carries the discipline that produced it, and
    the benchmark-versus-conformance boundary statement renders verbatim from the
    record on every one of those views. The per-operation HdrHistogram V2
    encodings are tabulated rather than drawn: decoding one is the engine's own
    histogram reader, which the console reaches once its engine pin carries the
    bench module (#179).
  • is_modifiable judges the whole CONTRIBUTION, in any member order
    (#201).
    No released text says when EHR_STATUS.is_modifiable is evaluated
    relative to a commit, so register entry AMB-225 records the atomic-set
    reading and the schedule gates on it: a content member is refused exactly
    when the EHR is deactivated and the change set carries no EHR_STATUS
    member setting is_modifiable = true, whatever position the members hold.
    Two new cases close the open corners — a mixed set whose status member keeps
    is_modifiable = false is refused whole, and an EHR_STATUS-only set is
    ...
Read more

0.1.0

Choose a tag to compare

@github-actions github-actions released this 27 Aug 23:33
Immutable release. Only release title and notes can be modified.
v0.1.0
79e2599

The first stable release: the milestone closed at zero open issues, and
the pre-release alpha line ends here.

Added

  • Scope builds the claim from CNF tiers (#100). The run wizard's Scope
    screen gains a row of tier checkboxes — CORE, STANDARD, OPTIONS, SEC-BASIC —
    each carrying the capabilities the capability matrix puts in that tier and
    the number of catalogue cases those capabilities gate. Both counts come from
    the published library's own tier_members walk, the one every profile
    verdict is computed from, so the row cannot drift from the answer the
    judgement gives. Composing writes an ad-hoc statement into the same paste box
    the vendor path uses: the product identity from the Connect step, the checked
    tiers as claimed profiles, their required capabilities as the claimed
    capabilities, the schedule release read from the committed statements under
    the mounted party tree, and the spec-component versions derived from the
    catalogue's own applies floors. The operator reads the document before
    saving it, and it is then validated, stored and written into the run's output
    directory exactly like a pasted one, so a verdict stays a pure function of a
    statement. Option branches stay undeclared, because only the party running
    the server knows which branch it realizes.
  • The console exports a signed record, and anyone can check one (#68). The
    verdicts screen gains one step that hands the finished run to the pinned
    instrument's own verdicts --sign-key: the rendered documents, a digest
    manifest over them, and a detached OpenPGP signature over that manifest. The
    console seals nothing itself. Beside the sealed set it renders three files a
    party publishes, each carrying the record digest prefix that ties it to the
    signed bytes — the brand's seal card with its three slots filled from the
    record, a compact badge SVG with copy-paste markdown and HTML snippets, and
    a self-contained HTML report of the results and verdicts surfaces whose
    footer carries the full digest, the signer fingerprint and the signing time.
    All three are pure functions of the record, so the same bundle reproduces
    the same bytes. The whole bundle downloads as one archive.
  • /verify is a public record check (#68). No run, no server and no
    account: upload a bundle and the published library recomputes every digest
    its manifest names and checks the detached signature. A tampered file names
    itself. The upload is a plain HTML form posting to a server route, so it
    works with no JavaScript at all; uploaded bundles are transient and swept on
    a short timer. The honesty box renders on every outcome — a valid signature
    proves integrity and origin since signing, not the run's conditions, not the
    system under test's identity claims, not the catalogue's coverage — and the
    page prints the veredictum verify-record equivalent beside it, so nobody
    has to trust the console to check the console.
  • The export surfaces carry the openEHR trademark acknowledgment and the
    independence disclaimer visibly (#94).
    The seal card renders it in its
    caption area and the report in its footer, because those are what a party
    publishes.
  • run --record-exchanges persists the wire (#96). The flag writes
    transcript.json beside results.json: per case, in send order, the
    request line, request headers and request body, and the response status,
    headers and body. It is off by default, and persistence is a serialization
    of exchanges the driver already holds, so a recorded run sends nothing extra
    and reaches the same verdicts as an unrecorded one. The artifact records a
    SUT's response bodies verbatim, so it can carry real patient data: it is
    operator-controlled output, never a log, and the authorization request
    header's value is withheld. With --sign-key the sealed record manifest
    covers the transcript.
  • run-transcript.schema.json joins the published schema set. The run
    transcript is its own artifact family, separate from the verification pack's
    replay transcript.schema.json, which requires an adjudicated verdict per
    entry and carries no request side at all.
  • The console records and reads the wire. Scope gains a "Record the wire
    exchanges" checkbox, off by default with the clinical-data caution beside
    it, and the results drawer renders each recorded exchange as request and
    response panes. A run driven without the flag says so where the wire would
    be.

Changed

  • A measured population now varies leaf by leaf, so earlier measured records
    are not comparable with later ones (#137).
    The performance pack used to
    stamp each composition with only the event-context times and the composer
    name, so every composition of a population carried identical clinical values.
    A server storing that population can share structure, index entries and cache
    pages that a real population would never let it share, which flattered every
    number measured over it — records produced before this change are flattered
    in exactly that way, and a number from one of them must not be compared with
    a number produced after it. The pack now reads the leaf constraints the
    operational template itself declares and redraws every numeric leaf inside
    its own permitted range: DV_QUANTITY magnitudes against the
    C_DV_QUANTITY interval declared for the leaf's units, and DV_COUNT
    magnitudes against the C_INTEGER range declared for a DV_COUNT
    magnitude. A leaf whose permitted range the template does not declare, and
    every coded, textual and date-time leaf, keeps its committed value, so no
    arrival can send an instance the template refuses. The draw is seeded from
    the template key and the arrival index, so the same run reproduces the same
    population byte for byte.
  • perf_run::pack::PackTemplate carries a constraints field. The library
    type gains the leaf ranges read out of its operational template, which is a
    breaking change for anything constructing the struct literally.
  • The console answers an unknown address with a real page (#84). A path
    outside the route tree used to render the bare string "Page not found."
    with no chrome, no title and no way back. It now renders inside the
    console's own sidebar and toast chrome, sets its own title, names the path
    that missed, and offers the instrument and the catalogue as routes out. The
    HTTP status is unchanged at 404.
  • The console ships a full icon set (#84). favicon.ico,
    apple-touch-icon.png, icon-192.png, icon-512.png and a web manifest,
    every one of them rendered from the two brand SVG masters by
    scripts/render/brand-icons.sh so the mark cannot fork. The image serves
    them from the same public/ mount as the seal.
  • Every run-wizard mutation reports both outcomes as a notification.
    Saving the scope, previewing the selection, starting a run and cancelling
    one each raise a toast on success and on failure, with the failure copy
    naming the object, the instrument's own diagnostic verbatim, and the next
    action. The detailed inline panes stay beside them, which is where a
    schema finding or a per-chapter breakdown is read line by line.
  • The console reads two new environment variables. VEREDICTUM_SIGN_KEY
    names the armored OpenPGP secret key the export seals with, and
    VEREDICTUM_VERIFY_KEY names the public half. Both are optional and both
    unset is a first-class state the surfaces explain rather than an error. The
    export asks for the public key too because it verifies its own bundle before
    stating who signed it and when: it never prints a signing time it has not
    checked. A passphrase reaches the spawned instrument through
    VEREDICTUM_SIGN_PASSPHRASE and its child environment only — never a
    signal, a file, a command line, or a log line.

Fixed

  • Issue numbers inherited from FerroEHR now say so (#123). Three
    ambiguity-register.schema.json and wire-surface.schema.json descriptions
    carried bare #2545, #2546 and #271, which resolve to unrelated issues
    on this repository's tracker; they read FerroEHR#NNNN now, as do the
    runner comments and the generated wire-surface coverage report that carried
    the same ids. Description text only: no schema keyword, type or constraint
    moved.
  • validate --write-report writes somewhere that exists (#91). The
    coverage report's path was climbed out of the spec tree
    (<specs>/../../conformance/coverage-report.md), which matched the old
    mono-repo layout and, at this one, resolved to a repository-root
    conformance/ directory that has never existed. The report is now derived
    from the artifact root it describes and lands at
    <ROOT>/coverage-report.md, so it follows the catalogue rather than
    wherever the specs happen to be mounted. coverage_report_path takes the
    artifact root and returns a plain PathBuf, since the derivation can no
    longer fail.

0.1.0-alpha.6

0.1.0-alpha.6 Pre-release
Pre-release

Choose a tag to compare

@github-actions github-actions released this 27 Aug 17:01
Immutable release. Only release title and notes can be modified.
v0.1.0-alpha.6
5187066

Fixed

  • The release pipeline locates the dependency SBOM instead of assuming its
    depth (#109 aftermath).
    cargo-cyclonedx writes the instrument's SBOM
    beside its crate manifest, except when the workspace member's version
    matches a published crates.io version, when it writes to the workspace
    root — both observed first-hand. The binaries lane searched a fixed depth,
    found nothing at the alpha.5 cut, and both binary legs failed; it now
    searches both locations and excludes the console crate's SBOMs by path.

0.1.0-alpha.4

0.1.0-alpha.4 Pre-release
Pre-release

Choose a tag to compare

@github-actions github-actions released this 27 Aug 07:30
Immutable release. Only release title and notes can be modified.
v0.1.0-alpha.4
178dc77

Added

  • A committed example results document, examples/results.example.json,
    generated by the crate's own machinery (cargo run --example make_example_results, deterministic): schema-valid, invariant-checked,
    with a real embedded HDR V2 histogram and a verdict computed against the
    catalogue's POC case. It doubles as reader documentation for the results
    schema and as a real seed for the party_document and hdr_v2 fuzz
    targets, which previously started from mutations.
  • A deliberate library API, veredictum::pipeline, so the engine is
    consumable by something other than the command line. It carries one seam per
    whole operation — catalogue validates an artifact tree, conformance
    drives it against a running system under test, judgement computes the
    verdicts and renders the submission set, assets renders the published
    visuals and the schema set, and measured runs the class window, the stress
    ladder and the AQL probe. Every seam returns typed values: a validation
    carries its findings and the tree it loaded, a run carries the results
    record and its outcome tally, a judgement carries the verdict report and its
    documents as named bodies, and the measured window reports its progress as
    typed events. Nothing returns console text, so a consumer renders its own
    views over the same facts the command line prints. The veredictum binary
    is now a clap front end over exactly those seams; its behaviour, its output
    and its exit codes are unchanged.
  • A documentation website at https://veredictum.eu, built from website/ and
    deployed to GitHub Pages by a new Docs workflow. The root serves a
    hand-written landing page in the project's own brand palette, and /docs/
    serves an mdBook with five chapters: an introduction, installation, running
    the instrument, a command reference covering every subcommand with its real
    flags, the conformance method (the attribution law, positive and negative
    testing, the ambiguity-register lifecycle), and catalogue authoring. The site
    loads nothing from an external host, renders in both light and dark, and takes
    its palette from the brand tokens. scripts/site/build.sh assembles the same
    tree locally that the workflow deploys, the CNAME for the custom domain
    included. A pull request touching the site builds, lints and link-checks it
    without deploying.
  • The vendored CKM ADL 1.4 archetype pack is exercised in this repository, by
    tests/it/corpus_packs.rs on every cargo nextest run. All 944 ADL 1.4
    exports are decoded as UTF-8 and required to open with an archetype (…)
    header declaring adl_version=1.4 and to declare the archetype id their file
    name carries; all 944 AM 1.4 XML twins are read to end of input and required
    to root at archetype in http://schemas.openehr.org/v1 with that same
    identity; both counts are pinned against the pack's own inventory record. The
    pack had no exerciser here — its only one was an ADL-engine parse gate in the
    repository this instrument was split out of, and this repository ships no ADL
    parser. The pack stays as reserve material for wire batteries the catalogue
    has not authored yet, and the exercise is at the byte level, which is what the
    instrument can perform first-hand.
  • The ADL 2 pair pack and the CKM Operational Template breadth pack gain the
    same byte-level exercisers, so every vendored corpus tree in this repository
    now has one. The pair pack's 654 files are all read and refused when empty,
    its 322 ADL 2 sources are checked for adl_version=2.0.6 and its 330 ADL 1.4
    twins for adl_version=1.4, each against the archetype id written inside it,
    and the 321 archetypes upstream published in both dialects are proven to pair
    with a twin in the same directory. The files that do not pair are pinned as
    what they are: one ADL 2 template, which the archetypes-only 1.4 half has
    nothing to hold, and nine ADL 1.4 archetypes this snapshot never converted.
    The template pack's 305 exports are each parsed to end of input and checked
    to root at template in http://schemas.openehr.org/v1 carrying a template
    id, and its file list is compared against the record's own vendored table
    rather than against its count alone.
  • A fuzzing lane over the readers that parse text or bytes the instrument did
    not write, in its own nightly fuzz/ workspace: six libFuzzer targets
    covering the ${…} reference and identifier grammars, the decision-table
    literal grammar, the citation reader, a case core end to end through YAML and
    the published schema into the typed model, the IXIT, statement and results
    documents a party publishes, and the HDR histogram V2 decode path a measured
    verdict is re-derived from. Seeds come from the catalogue and the party
    declarations already committed here; recorded findings live in
    fuzz/regressions/ and are re-checked by every run. The harnesses compile on
    the pull-request path as a gating CI job, and a weekly campaign fuzzes each
    target with its corpus kept between runs. fuzz/README.md carries the threat
    model and the commands, .claude/rules/fuzzing.md the discipline and the
    crash-to-regression-test procedure.
  • veredictum::load::yaml_str_to_value parses artifact YAML from a string under
    the same budget and duplicate-key refusal the file reader uses, and
    veredictum::validate exposes citation_clauses, expand_braces and
    section_candidates, so a consumer can read a citation the way the validator
    does.
  • A published VEX record under security/vex/, in OpenVEX format: the
    distroless base's adjudicated OpenSSL finding as a hand-authored statement
    beside its .trivyignore.yaml twin, and the Rust advisories deny.toml
    accepts as a GENERATED document whose id set cannot drift from the gate —
    scripts/security/vex-generate.sh refuses on any disagreement and the CI
    guard tier regenerates and diffs on every pull request. The scheduled
    published-image scan applies the documents, and
    scripts/security/scan-images.sh reruns that exact scan locally.

Changed

  • The container image is the web console now. ghcr.io/rubentalstra/veredictum
    ships the new veredictum-console Leptos server (app/veredictum-console,
    a second workspace package that never publishes to crates.io) instead of the
    CLI, per the ruling recorded in docker/Dockerfile when the image first
    shipped: the CLI payload was a placeholder, and its no-toolchain paths are
    cargo install veredictum and the attested release binaries. Start the
    console with docker run --rm -p 127.0.0.1:3000:3000 -v "$PWD:/work" ghcr.io/rubentalstra/veredictum:<tag>; it binds loopback through the
    publish flag because the console has no login. The server answers
    /healthz, the image bakes a HEALTHCHECK that probes it (the binary is
    its own probe, because distroless carries no curl), and the binary drains
    in-flight requests on SIGTERM, so docker stop ends it gracefully. The
    image build properties are unchanged: pushed by digest, smoke-driven and
    scanned before any tag applies, SLSA provenance and an SBOM attested on
    the digest, :latest moving only on a release tag.
  • The CKM template breadth pack is re-vendored. CKM published new asset
    versions of ips-problem-list and ips-allergies-and-intolerances on
    2026-08-19, so those two exports carry different bytes. The library is still
    305 vendored templates beside the one private-incubator template that answers
    404 without an account.

Fixed

  • Three ways a document the instrument was JUDGING could stop the instrument,
    all found by the new fuzzing lane on its first local campaign. A
    decision-table cell nesting 4000 lists deep, or chaining 4000 ordinal tuples,
    ran Literal::from_text off the stack; a Rust stack overflow aborts rather
    than unwinding, so a validator run died instead of reporting a finding. And a
    113-byte citation carrying 22 {a,b} groups in one path hint asked citation
    resolution for four million strings, hanging the run: the 32-variant ceiling
    was applied across a clause's tokens but not within one. Literal nesting is
    now bounded at literal::MAX_NESTING and brace expansion at
    validate::MAX_CITATION_VARIANTS, both refusing with a typed finding. The
    grammars' own forms are unaffected — a literal reaches three levels and an
    authored shorthand names two or three sibling documents.
  • The README quoted 1107 spec-cited cases, which was the file count under
    artifacts/schedule/. The instrument reports 1103, because the four
    schedule/performance/ journey definitions load as measured-workload
    definitions and are not case cores. The page now carries the number
    validate prints and says where that number comes from.
  • Re-running scripts/vendor/ckm-archetypes.sh would have regressed two facts
    in the pack's PROVENANCE.md: the corrected mixed-licence count, and now the
    exerciser. The script emits both, so the record survives a refresh.
  • The SonarQube lane no longer runs on a Dependabot pull request. SONAR_TOKEN
    is an Actions secret and a Dependabot run reads a separate store, so every
    such run failed on the missing secret. The lane is advisory and gates no
    merge, so skipping it costs nothing.

0.1.0-alpha.3

0.1.0-alpha.3 Pre-release
Pre-release

Choose a tag to compare

@github-actions github-actions released this 26 Aug 19:06
Immutable release. Only release title and notes can be modified.
v0.1.0-alpha.3
e6f8e77

Fixed

  • The image vulnerability gate refused to tag the 0.1.0-alpha.2 image, so that
    release published its binaries and its crate but no pullable image tag. The
    finding was real: libssl3t64 in the distroless base, CVE-2026-14456, HIGH,
    with a Debian fix the base image has not been rebuilt against — the current
    :nonroot digest still carries the vulnerable version, so a base bump does not
    resolve it and a distroless image has no package manager to upgrade it in a
    layer of our own.

    It is adjudicated as unreachable rather than suppressed, on the shipped
    binary's own ELF header: its dynamic dependencies are libgcc_s, libm and
    libc only. TLS is rustls and the JOSE signing is aws-lc-rs, so nothing this
    project builds links OpenSSL, and the image is distroless — no shell, no
    package manager, no second executable that could load the library. The entry
    lives in a new .trivyignore.yaml, scoped to that one package by PURL, with
    the evidence and a three-month expiry, so it has to be re-argued rather than
    quietly becoming permanent.

Added

  • scripts/checks/image-labels.sh, in the ungated guard tier. The base image
    digest is declared in three places — the runtime FROM, the Dockerfile's
    base.digest label, and the release pipeline's labels: input, which is the
    copy the published image actually carries because it overrides the Dockerfile's
    — and an automated base bump edits only the first. Without the guard, merging
    one publishes an image whose base.digest names a parent it was not built on.
    It also checks that every shared OCI key agrees between the two declaration
    sites, and refuses to pass vacuously if the publishing lane it expects is
    absent.
  • ARCHITECTURE.md at the repository root: the instrument's design record,
    moved here from the FerroEHR mono-repo where it was written. It is the design
    authority for the machinery — the artifact set and the case-core field
    definitions, the operation bindings, the outcome taxonomy and the ambiguity
    register, the assertion vocabulary, verdict computation — and it carries the
    population-anchored performance-class model with its journey decomposition,
    plus the evidence base and the ISO/IEC 9646 and CASCO grounding the scheme is
    built in. Names and paths were adapted to this tree; the substance is
    unchanged.
  • The GHCR image-pulls badge in the README, now that the package exists.
  • A Dependabot ignore for rand major bumps. The dev-dependency exists to hand
    pgp's signing call an RNG, and pgp 0.20 is on rand_core 0.6, so a major
    bump does not compile. Patch and minor bumps within the pin are still proposed,
    and advisory-driven updates are unaffected.

Changed

  • The container image states in its own header that its current payload is a
    placeholder: it ships the CLI today and becomes the web UI's image when that
    lands (#6). The CLI's own distribution channels are cargo install veredictum
    and the prebuilt binaries on each release.
  • The distroless base moves to the current :nonroot digest
    (sha256:a77defd6…). This is not a security fix — the new digest carries
    the same libssl3t64 version, verified by scanning it — it is base currency,
    so the image is not built on a two-month-old parent.