Publishing to crates.io — readiness

Non-normative. This records what stands between the repository's current state and the stated goal of publishing every crate to crates.io. It is a status document like the conformance matrix, not a requirement: the requirements it measures against are O10.10, O10.11, W16.11–W16.15, and C0.11, and the working procedure is agents/release.md.

It is cross-family — the one document in spec/ that is, because publishing is the one activity that treats the whole repository as a single release surface. Family-specific findings still belong in that family's own register.

Superseded by events, 2026-08-22: every crate is published. All 34 packages the gate enumerates now exist on crates.io at the version their source claims, and scripts/check-published-match.sh reports 34 matched, 0 mismatched, 0 skipped. The 21 that had never been published at their current numbers went out in one pass — the 18 port crates at 0.5.0, fhir-store 0.2.0, fhir-loco 0.2.0, fhir 4.1.0 — together with the seven that a serde_json/float_roundtrip change had just made diverge from immutable artifacts (fhir-core 3.2.0 and fhir-r2/r3/r4/r4b/r5/r6 4.1.0, bumped rather than edited, O10.11).

That closes this document's stated goal and changes what it is for. What follows was written while the goal was ahead of the repository; it is kept as the record of what the obstacles were and how each was resolved, not as a description of today. The live gate, not this file, is the thing to trust — it runs against crates.io and this paragraph does not.

Republished in full, 2026-08-26. All 34 crates went out again the same day in one pass at their bumped versions (ports 0.5.1, store/loco 0.2.1, model 4.1.1/3.2.1/1.5.1, reservations 0.0.2), and the gate reports 34 matched, 0 mismatched — the first publication whose hosted CI was green at the moment of upload, closing the "green laptop is weaker evidence" note below for this release.

Republished again, 2026-08-26, second pass. The trademark directive put the fair-use disclaimer into every publishable description, a manifest is packaged source, and O10.11 does not distinguish small changes — so all 34 went out once more (ports 0.5.2, store/loco 0.2.2, model 4.1.2/3.2.2/1.5.2, reservations 0.0.3) and the gate again reports 34 matched, 0 mismatched. The description rule is enforced by scripts/check-trademarks.sh from this pass on.

The publish path is decided, 2026-08-26: a documented laptop step, permanently. The owner ruled out crates.io Trusted Publishing from CI on reliability grounds — GitHub is not dependable enough to hold the publish path, a judgment made hours after an Actions major outage swallowed push events and stalled every hosted run. This is a repository-specific decision, not a statement that Trusted Publishing itself is unready: crates.io support for it is generally available on GitHub Actions and on GitLab.com CI (not self-hosted), and only Codeberg/Forgejo — one of this repository's three mirrors — has no support yet upstream. Both facts and their reconciliation are recorded in spec/trusted-publishing/index.md. Consequences executed the same day: the six inert per-port publish.yml workflows are deleted; the only registry credential is the maintainer machine's ~/.cargo/credentials.toml (verified: GitHub stores no secret and no crates-io environment exists); and this document plus the "Before any release" list in agents/release.md are the whole of the process. The accepted residual — one machine, one person, an unsigned upload path — is recorded in MAINTAINERS.md and stands until evidence reopens the question (RFC.md §10 still solicits it).

Two things the publication does not establish, and which no crates.io upload could:

  • The O10.4c re-shred shipped in the port crates was verified on one developer machine, not in CI. Every port's live suite was run against a local container on 2026-08-21/22 and was green; the hosted live jobs had not run at the moment of publication. A green laptop is weaker evidence than a green pipeline (C0.9, T11.13).
  • Publication is not a conformance claim. The conformance matrix remains the document that says what each port has been shown to do, and it is unchanged by any of this.

Assessed: 2026-08-01, against the tree as it then stood; P-1 restated 2026-08-06 after both former scaffolds reached Store level (F-65, F-68 — the four days between assessments invalidated P-1's whole premise, F-76). Method: cargo package --list on representative crates; cargo metadata on every workspace; the crates.io API for all 32 package names; anonymous HTTP for every declared repository URL.

The 34 crates#

Thirty-four [package] manifests, in four families. Fuzz crates are publish = false by design and are excluded.

The count changed on 2026-08-02: fhir-store was split in two. The name now belongs to the engine-agnostic persistence core (chain, Audit, AccessRecord, the result types — F-45), and the HTTP server it used to name is fhir-loco. Both names were checked and are unregistered.

Family Crates Names on crates.io
Model (fhir/) 14 all under current names since 2026-08-10 (the 11 renamed release crates re-registered; old fhir-release-* versions remain, immutable)
Databases (fhir-<engine>/) 18 all 18 published at 0.4.0 — measured live 2026-08-10; an earlier revision of this table said "available", which had gone stale
Persistence core (fhir-store/) 1 published at 0.1.0 (same correction)
HTTP surface (fhir-loco/) 1 published at 0.1.0 (same correction)

The database-family correction was found the hard way: the first hosted CI runs (2026-08-10) ran each port's published-divergence gate (O10.11, F-35's script as a workflow step) and it failed on every crate this session touched — the shared-core path_bound change alone diverged all six -map and -gen crates from their published 0.4.0. The tree now clears every published number again: the eighteen port crates at 0.5.0 in lockstep (a public map-model field was added — breaking at 0.x), fhir-store 0.1.1, fhir-loco 0.2.0. Publishing those versions remains owner-gated; the gate only requires that a published version match its source, which a bump satisfies.

The 2026-08-10 rename changed this table's meaning (owner-directed: fhir-release-N → fhir-rN, matching the module names). Measured live against crates.io the same day:

  • Registered and published under unchanged names: fhir 3.0.0, fhir-core 3.0.0, fhir-derive-macros 1.2.0. All three now carry local changes, so all three were bumped — fhir 3.1.0 (the r4b feature), fhir-core 3.0.1, fhir-derive-macros 1.3.0 (the r4b version token) — keeping P-4/O10.11 (an immutable published version must match the source that claims it).
  • Registered and published under the old names only: fhir-release-2 …-6 at 3.0.0 and the reservations fhir-release-1, -7…-10 at 0.0.1. Those published versions are immutable and stay up; whether to publish a deprecation notice on them is an owner decision.
  • Published under the new names the same day (owner-directed), in dependency order and verified against the live registry: fhir-r2…-6 and fhir-r4b first registered at 3.0.0, the five reservations at 0.0.1 (the last four through crates.io's new-crate rate limit), the facade at 3.1.0. The F-87 fix followed the same afternoon: the six release crates republished at 3.0.1 and fhir-derive-macros at 1.4.0, so no published version silently loses a choice element. The F-86 fix closed the day: the six release crates and the facade at 4.0.0 together (breaking — 0..* primitives are now fhir_core::PrimVec<T>, R6.7a), fhir-core 3.1.0, fhir-derive-macros 1.5.0. Publishing the chain surfaced a real ordering knot: fhir-core's dev-dependency on the facade carried a version, which a published crate must resolve from the registry — a cycle, since the facade depends on fhir-core. It is now path-only, like the release crates' equivalent, which cargo strips at publish.

scripts/check-published-match.sh still enforces the invariant: a crate whose current name+version is on crates.io must match it byte for byte; the renamed crates are reported as not-yet-published skips, never silently.

Blockers#

Ranked by what they would cost if published as-is.

P-1 — The scaffold ports ship a store that does not exist, and a MySQL DDL emitter — OVERTAKEN BY EVENTS, 2026-08-06#

The section below recorded a real 2026-08-01 state and a real owner decision; neither premise survived the week. It is retained in summary because the decision ("publish scaffolds, mitigate in metadata") remains the precedent for any future scaffold — but every factual claim it rested on is now false:

  • fhir-oracle-map/src/ddl.rs is a real Oracle emitter, executed live against 26ai with 0 invalid objects (F-08 fixed 2026-08-03; the MySQL tokens survive only in doc comments and the test that forbids them).
  • fhir-oracle-store (2,598 lines) and fhir-mssql-store (3,296 lines) are real stores, live-verified — Store level, not Scaffold (F-68, F-65).
  • The "SCAFFOLD" description strings this section prescribed became the defect: four of the six manifests still carried them after the stores landed, which is exactly the above-the-level/below-the-level mismatch C0.11 exists to prevent, inverted. Corrected 2026-08-06 (F-76): fhir-oracle-store's description now records Store level with its evidence; the -map/-gen descriptions no longer claim a MySQL emitter or a missing store; fhir-mssql-map's "never run against a green CI gate" is gone (tests/upgrade.rs runs the DDL live).

What survives of the original finding: the six ports remain unpublished, and if published, the 0.4.0 line's changelogs must still say what each version could and could not do — that obligation is unchanged.

P-2 — The port version number contradicted its own changelog — RESOLVED#

Severity: High. O10.11 — a published version must match the source that claims it.

Four sources said 0.4.0 and one said 0.1.0:

Source Said
all six Cargo.toml version = "0.1.0"
all six Cargo.lock 0.4.0, for all three crates of each port
all six CHANGELOG.md, top entry ## 0.4.0 — tamper evidence that survives the database (2026-07-27)
agents/release.md "All six currently sit at 0.4.0"

Owner chose 0.4.0 (2026-08-01). Applied to all six [workspace.package] blocks and to the eighteen [workspace.dependencies] sibling pins, which carried the same stale 0.1.0.

The lock files then confirmed it mechanically. Re-resolving all six workspaces after the change produced zero Cargo.lock modifications: the locks already said 0.4.0, so the manifests were the stale side. Had 0.1.0 been correct, all six locks would have been rewritten.

One thing to carry into the first release. None of the four changelog releases ever reached crates.io — all eighteen port crate names are still unregistered. The first publication will be 0.4.0 with no 0.1.x–0.3.x beneath it on the registry. That is legal and not unusual, but a reader comparing the changelog against the registry sees three entries with no artifact, so each changelog should say where those releases lived. Left for the release itself rather than guessed at here.

P-3a — fhir-loco's advisories — RESOLVED#

loco-rs 0.16.4 -> 1.0.1, which needed no source changes: a clean rebuild of all targets compiled with zero errors. One advisory cleared outright (fxhash, dropped by scraper 0.25); the remaining quick-xml DoS pair is blocked on a loco release admitting opendal 0.58, and is documented in deny.toml with its exposure argument and that argument's limit. All four cargo deny categories are green.

A regression this uncovered, which was mine. Seven of the eight tests failed after the upgrade — not because of loco, but because the P-6 asset move had changed assets/'s location and fhir-loco/tests/requests/fhir.rs still read the old path. It was invisible because that crate's tests were never run after that move. The same gap this register keeps finding elsewhere, committed here. Fixed, along with the matching path in its README; all 8 pass.

P-3 — fhir-loco could not be published as written — RESOLVED#

Severity: Medium. It carried publish = false, had no description, license, keywords, categories, or readme, and its two dependencies on the sibling port were path-only, where Cargo requires a version on every non-dev dependency at publish time.

All fixed: publish = false removed, the metadata added, and both dependencies (and both dev-dependencies) now carry version = "0.4.0" alongside path — path wins locally, the registry version is what ships.

cargo publish --dry-run now fails on exactly one thing, which is the correct remaining state:

error: failed to prepare local package for uploading
Caused by:
  no matching package named `fhir-sqlite-map` found
  location searched: crates.io index

That is publication order, not a manifest defect: fhir-sqlite-map and fhir-sqlite-store have to reach the registry first. The manifest itself is clean.

No rust-version was added at the time. That gap (RV1.4 unmet) closed 2026-08-29: this crate now declares rust-version = "1.96", measured against loco-rs and axum with cargo +1.96 check --all-targets --locked before being written down, per agents/release.md and RV1.5. See spec/rust-msrv-n-minus-2/.

P-4 — fhir-derive-macros has diverged from its published 1.1.0#

Severity: High (raised from Medium once measured). Violates O10.11 now, not at some future release.

Local version is 1.1.0; crates.io already has 1.1.0, and versions are immutable. The question was whether the source had changed. It has. Measured by packaging the local crate and diffing it against the registry copy fetched through cargo:

src/lib.rs
published 1.1.0 554 lines
local 1.1.0 758 lines
difference 206 added, 2 removed

The addition is the qty-3 invariant support — a QUANTITY_TYPES list and the field-matching helpers around it. Cargo.toml.orig is byte-identical between the two, so nothing signals the divergence in the metadata.

This is precisely the failure agents/release.md describes, already happening: every local build resolves the path dependency and never fetches the registry copy, so this workspace is green against 758 lines while anyone writing fhir-derive-macros = "1.1.0" gets 554. The tree and the artifact of the same name are different code, and nothing in CI checks it.

Fixed: bumped to 1.2.0, along with its six dependency pins in fhir and fhir-r2 … -6. 1.2.0 is the honest number — the change adds validation behaviour rather than altering existing behaviour.

And the gate that would have caught it now exists: scripts/check-published-match.sh (F-35).

P-4a — The reservation crates had diverged too#

This entry previously said the opposite, and was wrong. It claimed the five reservation crates were byte-identical to their published copies. That was based on comparing src/ trees and manifests-minus-the-license-line — a narrower check than the claim implied. Running the new O10.11 gate, which compares every packaged file, found two things that comparison had missed:

  • fhir-r1's README.md had gained a "What is actually available" section describing which releases are modelled. Not in the published 0.0.0. Pre-existing, unrelated to any change made during this audit.
  • All five manifests carry a license line changed by the P-7 harmonization — which means that harmonization created four new O10.11 violations, on top of the one it exposed.

Both are the same defect as P-4: a changed tree on an immutable published number. Fixed by bumping all five to 0.0.1. They are workspace members only — nothing depends on them — so the bump is inert.

The general point stands and is worth keeping: the quintuple governs the source from now on and does not reach artifacts already on crates.io. fhir-core 2.2.0 and fhir 2.1.0 keep the terms they shipped with. The difference is that for the reservations, a 0.0.1 now exists to carry the new licence, where before this entry assumed none was needed.

P-5 — Declared repository URLs did not resolve — RESOLVED#

Severity: Medium. Every crate pointed at a repository that returned 404 anonymously, in three different flavours:

Declared Crates Status
fhir-rust-crate/fhir-rust-crate 11 404 — and the org itself does not exist
joelparkerhenderson/fhir-rust-crate 1 404 — user exists, repo does not
fhir-rust/fhir, …/fhir-<engine> ×6, …/fhir-store, …/fhir-loco 21 404 each

The diagnosis that mattered was not "they 404" but why. Checking the org rather than only the repos showed:

200  github.com/fhir-rust            <- the org is public
200  github.com/fhir-rust/fhir-rust  <- the monorepo is public
404  everything else

So these were not private repositories an anonymous check cannot see. They were per-crate URLs from the layout that preceded the monorepo — one repository per port — describing a structure that no longer exists. The same fossil as F-11 and F-39, in a third place.

Disposition: FIXED. All 33 crates now declare https://github.com/fhir-rust/fhir-rust/, which returns 200 and matches git remote get-url origin exactly. That is not merely a URL that resolves: it is the honest one, because this is a monorepo and one URL describes it.

Verified by resolving cargo metadata across all nine workspaces — 33 crates, one distinct repository value, no exceptions. The homepage field on fhir carried the same stale URL and was corrected with it.

Why it was worth fixing for something cargo publish never checks. crates.io renders this as the "Repository" link on every crate page and docs.rs resolves "Source" through it — a 404 there is the first thing a cautious reader clicks, on crates that handle PHI. O10.10 requires an SBOM per release whose whole purpose is tracing an artifact to its source, and a dead repository link undercuts precisely that. It was also already live: the published fhir 2.1.0, fhir-core 2.2.0 and fhir-derive-macros 1.1.0 point at an org that does not exist, and will keep doing so until each is republished.

The same fossil in the documentation, also fixed. All six doc/containers.md files told a reader to find the FHIR® packages at ../fhir-rust-crate/… or under a specific developer's home directory. Both are the paths that made every spec-dependent test skip while reporting success (F-39, F-42). They now name ../fhir/doc/fhir-specifications, which is what the code resolves, and say what the old entries cost.

P-6 — The published crates could not obtain a map at all — RESOLVED#

Severity: High. RelMap::from_gz_bytes was the only constructor and the maps lived outside every package root, so cargo add fhir-sqlite-map fhir-sqlite-store produced two crates that could not shred, reconstruct, init, put, or get anything. cargo package --list reported zero asset files in both.

Fixed on the owner's decision: include_bytes! behind per-version features, matching the shape fhir/'s release crates already use.

  • assets/ moved into the map crate, since include cannot escape a package root.
  • RelMap::bundled("r5") returns a ready map; features r3, r4, r5, with r5 default. bundled_versions() reports what a build carries.
  • The store crates forward the same features.

Verified: fhir-sqlite-map packages 19 files, 2.6 MiB including all three maps; bundled() yields 117 / 146 / 158 resources for R3 / R4 / R5; clippy is clean at four feature combinations including --no-default-features; and the map and store README examples were compiled against the real crates.

Stated limit: the features gate compilation, not download. A .crate is static, so all three maps ship (~2.5 MB) however few are enabled. Making the download opt-in would take separate data crates. The caveat lives in bundled's doc comment.

This also removes the constraint this entry previously placed on publishing: the store crates are no longer unusable-as-published, so the only remaining naming question is P-1's, which is decided.

P-7 — Split licensing inside the model family — RESOLVED#

Severity: Medium. Was: fhir and fhir-derive-macros declared the five-license form while fhir-core and fhir-r1 … -10 declared bare MIT, and the HTTP crate declared none at all. The facade's declaration did not describe the set it pulls in.

Harmonized to the quintuple on the owner's instruction. All 32 packages now declare, identically:

MIT OR Apache-2.0 OR BSD-3-Clause OR GPL-2.0-only OR GPL-3.0-only

Twelve manifests changed — fhir-core, the ten fhir-r*, and fhir-store. Verified by resolving cargo metadata across every workspace: 32 packages, one distinct licence string. cargo deny check licenses re-run on fhir/ and fhir-sqlite/ — ok in both; the OR expression satisfies a permissive-only allowlist because at least one option (MIT, Apache-2.0, BSD-3-Clause) is allowed, and OR lets the recipient choose.

A root LICENSE.md now states the grant once for the whole repository — there was none before, though the README declared the five.

Two things it deliberately does not do:

  • It does not relicense what is already published. A crates.io version is immutable, metadata included, so the releases of fhir, fhir-core, fhir-derive-macros, and fhir-r1 … -10 that predate this stay under the terms they shipped with. The quintuple applies from each crate's next version.
  • It does not add licence texts to the crate packages. See P-9.

P-9 — No crate shipped a licence text — RESOLVED#

Severity: Low. cargo package includes only what is inside the crate directory. The six ports kept LICENSE-APACHE and LICENSE-MIT at the port root, one level above crates/<name>/, and fhir/LICENSE.md sat at its workspace root — so all 32 packages shipped the license field and none of the five licences it names.

Fixed. LICENSE.md — the repository's canonical statement of the quintuple — now sits in every crate directory. The eleven crates in fhir/ that declare an explicit include list (fhir-core, fhir-r1 … -10) had it added there too, since an include list means nothing is packaged by default.

Verified across all 32, not sampled: each cargo package --list contains LICENSE.md. 32 ship it, 0 missing.

Nothing about this blocked publication — crates.io requires the field, not a file, and the SPDX expression is the operative grant either way. It is a completeness fix: the licence now travels with the artifact instead of only with the repository.

P-10 — The map assets were half-moved and uncommitted, and cargo publish refused — RESOLVED#

Status: RESOLVED 2026-08-02. Committed on branch commit-map-assets — 48 files changed: 24 added at the new path, 24 removed from the old.

cargo package would not run on any of the six ports:

error: 12 files in the working directory contain changes that were not yet
committed into git:
crates/fhir-sqlite-map/assets/CHECKSUMS.txt
crates/fhir-sqlite-map/assets/fhir-sqlite-relmap-r3.json.gz
crates/fhir-sqlite-map/assets/fhir-sqlite-relmap-r4.json.gz
crates/fhir-sqlite-map/assets/fhir-sqlite-relmap-r5.json.gz

This was a half-committed move, not simply a missing git add — and the first write-up of this entry said the latter, which was wrong in a way that mattered. P-6 relocated the assets from fhir-<engine>/assets/ to fhir-<engine>/crates/fhir-<engine>-map/assets/, so that RelMap::bundled() could reach them from inside the crate that actually ships. Neither side of that move was committed:

Path On disk In git
fhir-<engine>/assets/ (old) absent tracked
crates/fhir-<engine>-map/assets/ (new) present untracked

Nothing in .gitignore covered either. The asymmetry is what made the third consequence below worse than "no assets": a clone got 15 MB of assets at the path nothing reads, and none at the path assets_root() points to. Files present, in the wrong place, is a harder failure to diagnose than files absent.

Three consequences, in increasing order of how quietly they failed:

  1. cargo publish stopped with the error above. Loud, and the easiest to notice.
  2. --allow-dirty made it proceed, and the assets were in the package list — so the escape hatch worked and hid the problem rather than surfacing it.
  3. A fresh clone had no usable assets. RelMap::bundled() (P-6) reads them and assets_current.rs gates on them, both at the new path — where a clone had nothing. On a clean checkout the drift gate had nothing to compare against — the T11.12 failure shape: a check that cannot run looks exactly like a check that passed.

That third one is why this was a blocker rather than a nuisance. P-6 resolved "the published crates could not obtain a map at all" by bundling the maps; bundling files that are not in the repository resolved it only on the machine that generated them.

Resolved by committing the move — 24 files added at the new path, 24 removed from the old — the owner having chosen that over the alternative — generating at build time — which P-6 had already rejected because it needs the FHIR specification packages present at build time and a published crate has no way to obtain them.

All 18 checksums were verified against their files before the commit, and again in the clean checkout afterwards.

Verified in a clean checkout, not in the working tree. Running cargo package where the assets had just been written would prove nothing about a clone. A detached worktree at HEAD was used instead, and there all six ports package without --allow-dirty, each carrying four asset files:

postgresql  ok, 4 asset file(s) in package
sqlite      ok, 4 asset file(s) in package
mysql       ok, 4 asset file(s) in package
mariadb     ok, 4 asset file(s) in package
mssql       ok, 4 asset file(s) in package
oracle      ok, 4 asset file(s) in package

The maintenance cost this accepts: gzip is not diffable, so every regeneration replaces the blob wholesale — ~2.5 MB of churn per port, and a review that cannot see what changed. G2.2a compares decompressed content rather than the container (F-41), so the gate still tells the truth about drift; it is the human diff that is opaque.

The standing rule this leaves behind: cargo package must succeed without --allow-dirty before anything is published. Nothing should be published on the strength of a dry run that had to be told to ignore the working tree — that flag is what kept this defect invisible.

Order of publication#

Dependencies first. The split and the rewiring (F-45) added a step and made one crate a hard prerequisite for eighteen others.

  1. fhir-store — the persistence core. Nothing in the database family can publish until it is on the registry: all eighteen port crates now depend on it by version, so this is no longer convenient ordering but a gate.
  2. Model — fhir-core and fhir-derive-macros, then fhir-r2 … -6 (each depends on both), then fhir (depends on all). The five reserved 0.0.0 crates need nothing. Independent of step 1.
  3. Databases, per port and independently of the others (W16.11) — fhir-<engine>-map, then fhir-<engine>-gen (depends on map), then fhir-<engine>-store (depends on map and on fhir-store, and dev-depends on gen, which must therefore already be on the registry for the verification build).
  4. fhir-loco — last. It depends on fhir-sqlite-map and fhir-sqlite-store, so it follows the whole of step 3 for that port.

All six ports are in step 3 — P-1 is overtaken (both former scaffolds are Store level now), and each port's honesty rests on description and README staying current with the matrix (F-76 is what happens when they do not).

A consequence of step 1 worth naming. A change to the engine-agnostic half now needs a fhir-store release before any port can take it. That version coupling is what bought the removal of six copies, and it is the reason the previous design preferred duplication plus a gate. The trade is recorded in F-45.

Dry runs#

cargo publish --dry-run --allow-dirty on every crate that can be dry-run — those whose dependencies already exist on the registry, or which have none.

Crate Result Packaged
fhir-store clean 9 files, 17.3 KiB compressed
fhir-postgresql-map clean 19 files, 2.5 MiB compressed
fhir-sqlite-map clean 20 files, 2.5 MiB
fhir-mysql-map clean 20 files, 2.5 MiB
fhir-mariadb-map clean 20 files, 2.5 MiB
fhir-mssql-map clean 20 files, 2.6 MiB
fhir-oracle-map clean 19 files, 2.5 MiB
fhir-derive-macros clean 7 files, 10.8 KiB
fhir-core clean 19 files, 46.3 KiB
fhir-loco fails on order only — see P-3 —
fhir-<engine>-store ×6 fails on order only — they now need fhir-store and their own map/gen on the registry first —

The map crates grew from ~30 KiB to ~2.5 MiB when the bundled maps moved inside them (P-6). That is the cost of cargo add producing a working engine, and it is the same 2.5 MiB whichever version features are enabled.

Everything else — the -gen and -store crates, and the rest of the model family — cannot be dry-run until its dependencies exist on the registry. Cargo resolves version from crates.io during the verification build, not from path.

A clean dry run means the package is well-formed. It means nothing else. fhir-oracle-map passes, and src/ddl.rs — verified present in its file list — is the MySQL emitter (P-1, F-08). The mechanical gate cannot see that, which is why C0.11 and the conformance matrix exist. Read this table as the absence of one class of packaging defect, not as readiness.

What is not assessed here#

  • Whether the crates build, test, and clippy clean — that is the green gate, run per family, not a publishing question.
  • Release checksums for published artifacts — these only exist once something is published.

O10.10's other three are now done and recorded in F-43: cargo deny (advisories, licenses, bans, sources) across all eight workspaces, cargo audit, and a CycloneDX SBOM for every crate. All workspaces are green on all four categories, fhir-loco included since the loco-rs 1.0.1 upgrade (P-3a).

Trademarks#

HL7®, and FHIR® are the registered trademarks of Health Level Seven International and their use of these trademarks does not constitute an endorsement by HL7.

Edit this page on GitHub — the repository is the source of truth; this site renders it.