Open source
The validation engine, in the open.
The same eight-aspect engine that powers Records, published under Apache-2.0. Pure TypeScript, no JVM, no server, no account. You can inspect its dated conformance evidence yourself.
100.0%
Parity in the pinned report
536/536
Comparisons passed in that report
0
Differences in that report
A pinned Java-parity measurement.
In the published 23 July 2026 report, Records matched the Java validator's expected OperationOutcome on all 536 in-scope JSON resource comparisons.
Measured by Records 0.9.5 on 2026-07-23 against FHIR/fhir-test-cases at commit 8923095. Both the suite and the commit are public, and the source artifact is conformance-results/report-2026-07-23.json. The current npm package is v0.6.2; because it postdates this report, the measurement is presented as dated evidence rather than a live guarantee for every later build.
A second reference: the MII lane
Beyond the HL7 suite, Records is measured against the official mii reference validator: 231/231 reference cases matched on 2026-07-23, with 22 classified skips outside the measured lane.
What the number does and does not mean
It means: in the pinned report, Records matched the Java validator on all 536in-scope FHIR JSON resource validation comparisons — with 0 runtime skips and 0 differences. It does not mean support for every one of the 969 entries in the upstream manifest. 433 entries sit outside this lane, and they are listed below rather than folded into a friendlier percentage.
What sits outside the lane
Every one of the 433 excluded manifest entries, and why. A conformance number is only useful if its boundary is published with it.
| Excluded | Cases | Status |
|---|---|---|
| XML resources | 299 | The XML adapter ships; its Java-baseline score is a separate lane. |
| Adjacent standards (CDA, HL7 v2, CDS Hooks, SHC, XVer, DSIG, JSON5) | 68 | Each needs a dedicated module and its own score. |
| Legacy FHIR versions (DSTU2, STU3) | 47 | Out of scope unless legacy support becomes a product target. |
| Disabled upstream (`use-test: false`) | 17 | Excluded by the upstream manifest itself. |
| No Java baseline declared | 1 | An upstream teardown workaround, not a validator comparison. |
| Logical model test | 1 | Awaiting a logical-model validation lane. |
XML parsing, NDJSON input, and the FHIR Schema path all ship in the engine. They are reported as their own lanes rather than blended into the headline, because a single averaged percentage across unlike test classes is not a measurement.
Resolve, validate, explain
Most validators do the middle step. The value is in the two around it.
- Step 1 of 3.
Resolve
Select the FHIR release, the declared and configured profiles, IG packages, terminology sources, and custom rules — before a single check runs.
A finding is only comparable if the basis that produced it is fixed.
- Step 2 of 3.
Validate
Run the eight aspects against the resolved basis. Each aspect is independently configurable by severity and strictness.
Aspects stay separable, so a terminology problem never hides behind a structural one.
- Step 3 of 3.
Explain
Keep severity, resource and element path, the rule or canonical source, the package version, and the configuration fingerprint attached to every finding.
An error message without its basis cannot be acted on or re-checked.
Eight aspects, independently configurable
Each aspect can be enabled, tuned by severity, and read on its own. That separation is what makes a result diagnosable instead of just red.
| Structural | JSON structure, required fields, cardinality, type constraints |
| Profile | StructureDefinition conformance and discriminator-based slicing |
| Terminology | CodeSystem and ValueSet bindings, local expansion with server fallback |
| Reference | Reference existence, target type checking, circular detection |
| Invariant | FHIRPath constraints declared on StructureDefinitions |
| Custom rules | Your own FHIRPath business rules, plus advisor overrides |
| Metadata | `meta` completeness and security labels |
| Anomaly | Statistical outliers across a resource population |
Three ways to run it
Apache-2.0, v0.6.2 on npm. FHIR R4, R4B, R5, and R6.
In a terminal — no install
npx -p @records-fhir/validator records-fhir-validator ./fixtures --fail-on=warningIn TypeScript
import { recordsValidator } from '@records-fhir/validator';const issues = await recordsValidator.validateRequest({ resource: { resourceType: 'Patient', id: 'example' }, profileUrl: 'http://hl7.org/fhir/StructureDefinition/Patient', fhirVersion: 'R4',});In GitHub Actions
- uses: medvertical/records-fhir-validator@v0 with: paths: resources/**/*.json fhir-version: R4 fail-on: errorWhere the engine ends and Records begins
The boundary is deliberate and stated here rather than discovered later.
Apache-2.0
In the open engine
- The eight-aspect validation runtime
- StructureDefinition loading from FHIR packages
- FHIRPath invariant execution and slicing
- Terminology, reference, metadata, and Bundle validators
- OperationOutcome conversion, CLI, and GitHub Action
Commercial
In Records
- Continuous validation against live FHIR servers
- Baselines, deltas, and drift detection over time
- Quality gates, triage, and cross-server comparison
- Evidence reports with the reproducibility contract
- Workspaces, RBAC, and on-prem deployment
A validator answers is this valid now? Records answers the question a running system actually has: will we know when it stops being valid? The engine is the honest half of that — take it, embed it, fork it. The half that watches it over time is the product.
Start with the engine. Stay for the loop.
Validate a file in the next minute, then see what continuous validation adds on a real public FHIR server.