One Care Record, Two National FHIR Profiles: an NZ Base + JP Core Overlay

How ParkinSync validates one synthetic weekly care record against both HL7 NZ Base and JP Core through a single fail-closed overlay, verified by an ephemeral HAPI round trip in CI.

Synthetic data only. Not a clinical claim, not a conformance certification, and not a production FHIR server.

Most FHIR examples stop at base R4. Real health systems don’t. New Zealand expects HL7 NZ Base, Japan expects JP Core, and the same care record has to be legible under both without being forked into two divergent codebases.

ParkinSync’s FHIR track is a small, deliberate answer to that: one synthetic weekly care record, derived into national Bundles through a single shared overlay, and validated against NZ Base and JP Core inside CI. It is intentionally not a clinical system. The interesting part is the discipline, not the scale.

The trap: one profile per country, forked forever

A national profile (NZ Base, JP Core) is a set of constraints layered on top of base R4 — required elements, bindings, meta.profile tags, extra categories. The naive path is to fork: an NZ builder, a JP builder, each drifting from the other. Two months later they disagree about what “the same” record means.

The alternative is to keep one base representation and apply national requirements as a thin, explicit overlay — and only where a profile actually demands one.

The overlay contract

The base is standard FHIR R4 (modelled with fhir.resources 6.4.0, the last release in that line to target R4.0.1). From one synthetic weekly Bundle, a single shared, fail-closed overlay derives the national variants:

  • NZ Base 3.1.0 — profile validation for Patient and MedicationStatement.
  • JP Core 1.2.0 — profile validation for Patient and a VitalSigns Observation.

Two rules keep it honest:

  1. Add a profile only where the national profile requires one. JP Core requires a vital-signs category on the Observation, so the overlay adds the JP Core vital-signs category while retaining the standard FHIR category — additive, not destructive. But JP Core does not require an overlay on MedicationStatement, so that resource is left at base R4 rather than tagged for the sake of symmetry. The overlay does the minimum the profile asks for and nothing more.

  2. Fail closed. If a derived Bundle doesn’t validate against its declared profile, CI fails. The overlay cannot “mostly pass.” This is the same principle the rest of the product uses for unauthenticated access and gated deletion: the safe default is refusal, not a silent shrug.

This mirrors an architecture decision the ecosystem already made elsewhere — integrate the data, not the screens. Here it is integrate at the profile boundary, not by cloning the model.

Proving it: an ephemeral HAPI round trip

Schema validation alone doesn’t prove a server will accept the record. So CI stands up a disposable, runner-local HAPI FHIR server, submits the synthetic weekly transaction Bundle, and does a semantic read-back of 30 resources — testing the client-assigned logical IDs against one pinned HAPI configuration.

Pinned and disposable are the point. The server exists only for the length of the job, against one known configuration, and is gone afterwards. It demonstrates the round trip without implying that any particular production server, terminology stack, or national endpoint is in scope.

Boundaries I kept explicit

Interoperability posts tend to overclaim, so the README states the limits and CI enforces them:

  • Synthetic data only. No patient, no clinical review, no regulatory certification.
  • No production FHIR server. The HAPI instance is ephemeral CI scaffolding.
  • National patient summaries and identity resolution are out of scope. NZ Base + JP Core here demonstrate the overlay pattern, not a national integration.
  • Upstream metadata honesty. JP Core declares jpfhir-terminology.r4#1.4.0 while the official terminology archive identifies itself as jpfhir-terminology#1.4.0; CI uses an unchanged-content cache alias rather than pretending the mismatch doesn’t exist.

Those aren’t disclaimers bolted on at the end. They’re the reason the round trip is trustworthy: a green check that names what it does not prove is worth more than a demo that quietly proves less than it claims.

Why bother, at this size

Because the pattern is what survives, not the sample. Two things generalise from a fifteen-resource synthetic Bundle:

  • National-profile awareness is a first-class design input, not a post-launch retrofit. Building the NZ Base and JP Core overlays from one base representation means a third jurisdiction is another thin overlay, not another fork.
  • Conformance belongs in CI. A profile the pipeline doesn’t validate is a profile you’ll break on your next refactor. Fail-closed validation turns “we support NZ Base” from a slide into a check that goes red when it stops being true.

It’s a small track. But it’s the shape I’d want at scale: one record, one overlay contract, national requirements applied exactly where they’re required, and a red build the moment any of that stops holding.

ParkinSync is one of the care tools I build at veai.jp/apps.

Thanks for reading — built with care, for caregivers.