FHIR Validator
ActionsAbout
Pure TypeScript FHIR validator for CI pipelines, GitHub Actions, and standalone Node.js use. It validates FHIR JSON resources against StructureDefinitions, FHIRPath invariants, terminology bindings, references, slicing, extensions, Bundle rules, metadata, and optional custom rules without requiring a JVM, database, or Records server.
Use the floating major tag for the latest stable validator in the current major line:
name: Validate FHIR
on:
pull_request:
push:
branches: [main]
jobs:
fhir:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: medvertical/records-fhir-validator@v0
with:
paths: |
examples/**/*.json
test/fixtures/**/*.json
fhir-version: R4
fail-on: errorFor production CI, pin an immutable patch tag:
- uses: medvertical/records-fhir-validator@v0.5.0
with:
paths: resources/**/*.json
profile-url: http://hl7.org/fhir/StructureDefinition/Patient
fhir-version: R4
fail-on: errorAction pinning:
| Goal | Pin in uses: |
Notes |
|---|---|---|
| Latest stable in current major | medvertical/records-fhir-validator@v0 |
Floating tag, force-moved on stable releases only |
| Exact released version | medvertical/records-fhir-validator@v0.5.0 |
Immutable consumer tag |
| Bit-exact reproducibility | medvertical/records-fhir-validator@<commit-sha> |
Best for audit and forensics |
The validator-v<semver> tag is the npm mirror/release-page tag. Use
v<semver> or a commit SHA for GitHub Action pins.
npm install @records-fhir/validator@0.5.0 @records-fhir/validation-types@0.1.6Run the CLI against one file or a folder:
npx -p @records-fhir/validator records-fhir-validator ./patient.json
npx -p @records-fhir/validator records-fhir-validator ./fixtures --fail-on=warning
npx -p @records-fhir/validator records-fhir-validator ./patient.json --format=json
npx -p @records-fhir/validator records-fhir-validator ./fixtures --summary-only --output validation-report.jsonUseful CLI options:
| Option | Default | Purpose |
|---|---|---|
--profile-url <url> |
base profile for each resourceType |
Validate every resource against one canonical profile. |
--fhir-version R4|R4B|R5|R6 |
R4 |
Select the public FHIR version. |
--fail-on error|warning|none |
error |
Control the process exit threshold. |
--format text|json |
text |
Print human-readable lines or structured JSON. |
--output <file> |
stdout | Write validation output to a file. Parent directories are created. |
--summary-only |
off | Omit per-issue output and print only aggregate counts. |
--include <glob> |
**/*.json |
Include matching JSON files when walking folders. Repeatable or comma-separated. |
--exclude <glob> |
none | Exclude matching JSON files when walking folders. Repeatable or comma-separated. |
CLI exit codes:
| Code | Meaning |
|---|---|
0 |
Validation completed and did not meet the --fail-on threshold. |
1 |
Validation completed and met the --fail-on threshold. |
2 |
Invalid CLI input, unreadable paths, no matched JSON files, or output write failure. |
Validate a resource from Node.js:
import { recordsValidator } from '@records-fhir/validator';
const issues = await recordsValidator.validate(
{ resourceType: 'Patient', id: 'example' },
'http://hl7.org/fhir/StructureDefinition/Patient',
'R4',
);Optional offline profile packages can be loaded through the package APIs. The default public repository export intentionally excludes bundled third-party IG artifacts until their upstream licenses and notices have been reviewed.
The validator emits structured issues that are intended for CI annotations, database storage, and UI display:
{
"severity": "warning",
"code": "terminology-binding-preferred",
"path": "Patient.gender",
"message": "Code is outside the preferred value set."
}The CLI text mode prints one issue per line and exits according to
--fail-on. JSON mode returns { summary, results }, where each result
includes file, resourceType, profileUrl, and issues. With
--summary-only, JSON mode returns only { summary }.
@records-fhir/validator0.5.0 - Apache-2.0 validation engine.@records-fhir/validation-types0.1.6 - Apache-2.0 validation-domain types.- Composite GitHub Action at repository root.
- Standalone examples under
packages/validator/examples/. - Boundary audit and smoke-test scripts.
- Public conformance evidence artifacts under
conformance-results/.
Records itself is commercial closed-source software. This repository contains only the open-source validator packages extracted from Records.
This public repository must not contain the Records web application, Records API server, database schema, migrations, repositories, governance reports, customer integrations, environment files, or commercial deployment configuration.
@records-fhir/bundled-profiles is intentionally excluded from the default export until all bundled upstream FHIR and implementation-guide artifact licenses have been reviewed. Re-run the export with --include-bundled-profiles only after that review.
The validator packages are designed for standalone embedding. Host applications can provide optional profile, rule, persistence, and logging integrations through explicit package APIs.
Use this project when you need a TypeScript-native validator that runs in Node, CI, GitHub Actions, or product backends without starting the Java validator. It is strongest for FHIR JSON resource validation, StructureDefinition constraints, slicing, references, terminology checks, and structured issue metadata that downstream applications can store or display.
It is not a universal FHIR ecosystem implementation. XML resources, CDA, HL7 v2, CDS Hooks, SHC, DSIG, JSON5 harnesses, legacy STU3/DSTU versions, logical models, and site-level MII certification are outside the current headline support scope unless called out by a dedicated conformance lane.
The package supports public FHIR versions R4, R4B, R5, and R6.
R4B routes through the R4 internal validation path because R4B is a maintenance
release of R4 with compatible StructureDefinition and FHIRPath context for this
validator mode.
Current HL7 FHIR/fhir-test-cases JSON resource validation status:
- Upstream manifest entries: 969 at pinned commit
8923095fc5e3750025f7dd71988c9e89083b1487. - Pre-filtered out before validation: 433, including one entry without a
declared
javabaseline:(default)/zzz, an upstream platform-specific teardown workaround rather than a validator comparison case. - Candidate JSON comparison set: 536 entries with a declared
javabaseline. - Runtime skipped from the headline lane: 0.
- Executed and compared against Java
OperationOutcome: 536. - 536 passed; no executable parity differences remain.
- Headline JSON resource parity: 100.0%.
Reproduce the headline lane locally with:
npm run conformance -- --tx-server none --output-file conformance-results/report-local.jsonCurrent and scoped evidence artifacts:
conformance-results/validator-claims-2026-07-23.mdconformance-results/report-2026-07-23.jsonconformance-results/mii-triangulation-2026-07-23.jsonconformance-results/fhir-schema-dual-path-all-2026-07-23.jsonconformance-results/fhir-schema-dual-path-actions-2026-07-01.mdconformance-results/hl7-validator-testkit-2026-05-20.jsonconformance-results/baseline-backlog-discovery-2026-05-03.json
The 433 pre-filtered entries are not counted as failures because they do not
exercise the thing this harness measures: JSON FHIR resource validation with a
Java OperationOutcome baseline. They include XML resources, older FHIR
versions, unsupported modules (SHC, CDA, CDS Hooks, JSON5, XVer, DSIG, HL7 v2),
disabled upstream tests, logical models, or entries without a declared Java
baseline.
The upstream manifest now supplies resolvable Java outcomes for every headline
candidate, and all 536 executable comparisons match the normalized Java
result. The historical --include-baseline-backlog artifact is
retained for provenance but is not the current headline measurement.
The scope expansion plan is tracked in
docs/conformance-scope-roadmap.md.
The HL7 manifest is broader than "validate one FHIR JSON resource and compare the validator output." It also contains test assets for other formats, protocols, historical versions, and adjacent standards. Counting those as validator failures would make the metric less honest: it would mix unsupported product scope with actual JSON resource validation correctness.
| Excluded class | Why it is not part of this score | What would be needed to include it |
|---|---|---|
| XML resources | The package currently validates parsed JSON resources. XML requires parsing, XML-specific diagnostics, and stable XML-to-resource location mapping. | Add an XML parser/normalizer and an XML-aware diagnostic mapper, then run XML fixtures as a separate conformance lane. |
| CDA, HL7 v2, CDS Hooks, SHC, DSIG, JSON5, XVer | These are adjacent standards or special harnesses, not plain FHIR JSON resource validation. Some are transformation/signature/protocol tests rather than resource validation tests. | Build dedicated modules and dedicated conformance harnesses for each format/protocol. |
Older FHIR versions (3.0, 3.0.1, 1.4) |
The validator package targets R4, R5, and R6. Legacy STU3/DSTU-era behavior differs enough that it should not be silently mixed into the R4 score. | Add explicit legacy-version support and report it as a separate compatibility score. |
| Upstream-disabled tests | The upstream manifest marks them with use-test: false, so the reference suite itself does not treat them as active comparison cases. |
Re-enable only if upstream enables them or if this project defines its own expected baseline. |
| Logical model tests | Logical models are not ordinary FHIR resource-instance validation cases. | Add logical-model validation support and a separate result category. |
| Missing Java baselines | The comparison metric is Java parity. Without an expected Java OperationOutcome, there is no objective diff target. |
Generate and commit Java baselines, or define a Records-owned expected baseline with a different metric name. |
.fml / .ndjson payloads |
They pass the manifest filter but are not single JSON resource documents. | Add FML/NDJSON-specific loaders and compare them in dedicated lanes. |
For that reason, the headline number should be read as:
Records matches the Java validator on all 536 currently in-scope FHIR JSON resource validation comparisons.
It should not be read as:
Records implements every format, protocol, legacy version, and adjacent standard represented somewhere in the upstream manifest.
Spec dispatch coverage for the measured R4 base package constraints is 100%.
MII conformance is measured in a separate lane from the HL7
FHIR/fhir-test-cases score. The current scoped MII-2026 reference run was
generated on 2026-07-23 against the official MII FHIR Validator container
mii-fhir-validator:0.0.1-alpha.7. It matches the
reference validator on 231/231 measured resources from the refreshed MII 2026
corpus under the mii-2026-reference profile scope and mii-local-blaze
terminology mode, with 22 classified skips: 12 corpus/profile-drift skips and
10 reference-terminology-incomplete skips. The run prewarmed 128/128
reference-scope profiles before executing the cases. The source-repository
report is conformance-results/mii-triangulation-2026-07-23.json.
This is a scoped parity claim for the measured package-example corpus. It is not an MII certification claim and does not imply full site-level MII Must-Support readiness.
FHIR Schema is being evaluated as a cleaner intermediate representation for
the same StructureDefinition semantics, not as a replacement for conformance
evidence. The current engine remains StructureDefinition-first. The FHIR Schema
graph path runs in parallel and is compared against both the current
StructureDefinition path and Java/reference OperationOutcome evidence where a
reference report exists.
The current all-scope MII dual-path lane covers 555 real fixtures. Of those, 512
have Java/reference coverage through the attached Java CLI supplement
conformance-results/fhir-schema-reference-cli-supplement-all-2026-07-01.json.
The final report is
conformance-results/fhir-schema-dual-path-all-2026-07-23.json.
The lane reports 418 clean cases, 71 exact Graph/Records comparable matches, 11 graph-only cases, 0 Records-only cases, 0 divergent cases, 55 missing-profile cases, and 0 execution errors. Twelve normalized issue-key gaps across the 11 graph-only cases are explicitly deferred because their reference-slice discriminators require external targets unavailable to the standalone fixture; Records reports those slices as unverifiable instead of declaring the resources invalid. No other Java-confirmed runtime gap remains. This lane is an implementation-reduction and convergence signal; it does not broaden the public headline parity claim beyond the explicitly measured FHIR JSON comparison lanes.
The package-level README contains the fuller API guide:
packages/validator/README.md.
npm install
npm run typecheck
npm run build
npm run oss:audit-validator
npm run oss:smoke-validator- Publish
@records-fhir/validation-types. - Publish
@records-fhir/validator. - Publish
@records-fhir/bundled-profilesonly after third-party license review.
Apache-2.0 for the validator packages unless a package-level notice states otherwise. Bundled third-party FHIR artifacts retain their upstream licenses and notices.
FHIR Validator is not certified by GitHub. It is provided by a third-party and is governed by separate terms of service, privacy policy, and support documentation.