Skip to content

Commit 6f0ee8e

Browse files
author
records-bot
committed
sync: monorepo @ validator 0.1.8 / validation-types 0.1.2
Snapshot of medvertical/records monorepo state, exported via oss:export-validator. Tracks the npm publication of: @records-fhir/validator@0.1.8 @records-fhir/validation-types@0.1.2 Run npm i @records-fhir/validator@0.1.8 for the matching distribution. The conformance evidence in conformance-results/ matches the published tarball.
1 parent 7648a53 commit 6f0ee8e

234 files changed

Lines changed: 21169 additions & 13358 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ jobs:
4545
For production CI, pin an immutable patch tag:
4646
4747
```yaml
48-
- uses: medvertical/records-fhir-validator@v0.1.7
48+
- uses: medvertical/records-fhir-validator@v0.1.8
4949
with:
5050
paths: resources/**/*.json
5151
profile-url: http://hl7.org/fhir/StructureDefinition/Patient
@@ -58,7 +58,7 @@ Action pinning:
5858
| Goal | Pin in `uses:` | Notes |
5959
|---|---|---|
6060
| Latest stable in current major | `medvertical/records-fhir-validator@v0` | Floating tag, force-moved on stable releases only |
61-
| Exact released version | `medvertical/records-fhir-validator@v0.1.7` | Immutable consumer tag |
61+
| Exact released version | `medvertical/records-fhir-validator@v0.1.8` | Immutable consumer tag |
6262
| Bit-exact reproducibility | `medvertical/records-fhir-validator@<commit-sha>` | Best for audit and forensics |
6363

6464
The `validator-v<semver>` tag is the npm mirror/release-page tag. Use
@@ -67,7 +67,7 @@ The `validator-v<semver>` tag is the npm mirror/release-page tag. Use
6767
### npm Package
6868

6969
```sh
70-
npm install @records-fhir/validator@0.1.7 @records-fhir/validation-types@0.1.2
70+
npm install @records-fhir/validator@0.1.8 @records-fhir/validation-types@0.1.2
7171
```
7272

7373
Validate a resource from Node.js:
@@ -88,7 +88,7 @@ artifacts until their upstream licenses and notices have been reviewed.
8888

8989
## What Is Included
9090

91-
- `@records-fhir/validator` 0.1.7 - Apache-2.0 validation engine.
91+
- `@records-fhir/validator` 0.1.8 - Apache-2.0 validation engine.
9292
- `@records-fhir/validation-types` 0.1.2 - Apache-2.0 validation-domain types.
9393
- Composite GitHub Action at repository root.
9494
- Standalone examples under `packages/validator/examples/`.

packages/validation-types/src/fix-suggestions.ts

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,26 @@ export const FixSuggestions: Record<string, FixSuggestion> = {
8383
why: 'Could not validate against the ValueSet (lookup failed).',
8484
fix: 'Check terminology server connectivity. The code may still be valid.',
8585
},
86+
'terminology-code-invalid': {
87+
why: 'The code is not valid for the declared code system. For UCUM quantities, the code must be a machine-readable UCUM expression, not just the display text.',
88+
fix: 'Replace the code with a valid code from the declared system. If the issue contains a suggestedCode, use that value; for pH this is typically "[pH]".',
89+
example: 'For system "http://unitsofmeasure.org", use code "[pH]" instead of "pH".',
90+
specUrl: 'https://www.hl7.org/fhir/terminologies.html',
91+
patch: { action: 'replace', path: '{{fieldPath}}', value: '{{suggestedCode}}' },
92+
},
93+
'terminology-display-mismatch': {
94+
why: 'The code may be valid, but the display text does not match the terminology server display for that code.',
95+
fix: 'Replace the display with an accepted display from the terminology server, or omit display and let consumers render the code.',
96+
example: 'Keep system/code stable and update only Coding.display.',
97+
specUrl: 'https://www.hl7.org/fhir/datatypes.html#Coding',
98+
},
99+
'terminology-coding-system-valueset': {
100+
why: 'Coding.system must identify the CodeSystem that defines the code. A ValueSet URL describes an allowed set of codes and is not valid as Coding.system.',
101+
fix: 'Replace Coding.system with the canonical CodeSystem URL for the selected code. Keep the ValueSet only in profile bindings or documentation.',
102+
example: 'Use "http://terminology.hl7.org/CodeSystem/v3-MaritalStatus" instead of "http://hl7.org/fhir/ValueSet/marital-status".',
103+
specUrl: 'https://www.hl7.org/fhir/datatypes.html#Coding',
104+
patch: { action: 'replace', path: '{{fieldPath}}', value: '(use the code system URL for this code)' },
105+
},
86106

87107
// -------------------------------------------------------------------------
88108
// Structural
@@ -258,7 +278,7 @@ export const FixSuggestions: Record<string, FixSuggestion> = {
258278
fix: 'Include actual time if available for better precision.',
259279
},
260280
'metadata-tag-missing-code': {
261-
why: 'Tags require a code to be useful for filtering and categorization.',
281+
why: 'Tags are more useful for filtering and categorization when they include a code.',
262282
fix: 'Add a code value to the tag: { system: "...", code: "my-tag" }',
263283
},
264284
'metadata-tag-invalid-system-uri': {
@@ -540,8 +560,8 @@ export const FixSuggestions: Record<string, FixSuggestion> = {
540560
// Profile
541561
// -------------------------------------------------------------------------
542562
'profile-constraint-violation': {
543-
why: 'Profile constraints define additional rules beyond the base FHIR specification.',
544-
fix: 'Review the constraint expression and adjust your resource to satisfy it.',
563+
why: 'Profile constraints define additional rules beyond the base FHIR specification. In document Bundles this can also mean a referenced child resource failed targetProfile matching.',
564+
fix: 'Review the path and details. For targetProfile failures, fix the referenced resource so it conforms to one of the allowed targetProfiles, then revalidate the Bundle.',
545565
patch: { action: 'replace', path: '{{fieldPath}}', value: '(satisfy constraint {{key}}: {{message}})' },
546566
},
547567
'profile-mustsupport-missing': {
@@ -550,9 +570,9 @@ export const FixSuggestions: Record<string, FixSuggestion> = {
550570
specUrl: 'https://www.hl7.org/fhir/conformance-rules.html#mustSupport',
551571
},
552572
'profile-slice-min-cardinality': {
553-
why: 'The profile requires a minimum number of items matching this slice discriminator.',
554-
fix: 'Add more elements that match the slice discriminator (pattern, value, or type).',
555-
example: 'For identifier slices: add identifier with matching system URL',
573+
why: 'The profile requires at least one item matching this slice discriminator. For document Bundles, the missing slice may be caused by an entry that exists but does not conform to the required profile.',
574+
fix: 'Add or repair the element matching the slice. For Bundle.entry:composition, fix the Composition entry and any child targetProfile errors first.',
575+
example: 'For Bundle.entry:composition: include a Composition entry that conforms to the document profile.',
556576
patch: { action: 'add', path: '{{fieldPath}}', value: '(add entry matching slice "{{sliceName}}", min={{min}})' },
557577
},
558578
'profile-slice-max-cardinality': {

packages/validation-types/src/validation-settings.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,10 @@ export {
8787
// Default settings
8888
DEFAULT_VALIDATION_SETTINGS_R4,
8989
DEFAULT_VALIDATION_SETTINGS_R5,
90+
createEhds2026ValidationSettings,
9091
createMii2026ValidationSettings,
92+
HL7_EU_EHDS_2026_PACKAGE_SET,
93+
HL7_EU_EHDS_2026_PACKAGE_VERSIONS,
9194
MII_2026_PACKAGE_SET,
9295
MII_2026_PACKAGE_VERSIONS,
9396
type FhirPackagePin,

packages/validation-types/src/validation/__tests__/mii-2026-preset.test.ts

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
import { describe, expect, it } from 'vitest';
22
import {
3+
createEhds2026ValidationSettings,
34
createMii2026ValidationSettings,
5+
HL7_EU_EHDS_2026_PACKAGE_SET,
6+
HL7_EU_EHDS_2026_PACKAGE_VERSIONS,
47
MII_2026_PACKAGE_SET,
58
MII_2026_PACKAGE_VERSIONS
69
} from '../index';
@@ -32,19 +35,70 @@ describe('MII 2026 validation preset', () => {
3235
expect(settings.profileSources?.packageRegistry).toBe(true);
3336
});
3437

38+
it('stamps explicit MII run metadata and Ontoserver guardrails', () => {
39+
const settings = createMii2026ValidationSettings();
40+
41+
expect(settings.mii).toEqual({
42+
preset: 'mii-2026',
43+
terminologyMode: 'mii-local-blaze',
44+
maxOntoserverRequestsPerRun: 250,
45+
allowHighVolumeOntoserver: false
46+
});
47+
});
48+
3549
it('allows callers to override selected settings without losing package pins', () => {
3650
const settings = createMii2026ValidationSettings({
3751
packageDownload: {
3852
autoDownload: false,
3953
pinnedVersions: {
4054
'de.medizininformatikinitiative.kerndatensatz.laborbefund': '2026.0.1-local'
4155
}
56+
},
57+
mii: {
58+
terminologyMode: 'mii-hybrid',
59+
packageLockHash: 'sha256-demo'
4260
}
4361
});
4462

4563
expect(settings.packageDownload?.autoDownload).toBe(false);
4664
expect(settings.packageDownload?.pinnedVersions['de.basisprofil.r4']).toBe('1.5.4');
4765
expect(settings.packageDownload?.pinnedVersions['de.medizininformatikinitiative.kerndatensatz.laborbefund'])
4866
.toBe('2026.0.1-local');
67+
expect(settings.mii?.terminologyMode).toBe('mii-hybrid');
68+
expect(settings.mii?.packageLockHash).toBe('sha256-demo');
69+
});
70+
});
71+
72+
describe('HL7 Europe EHDS 2026 package lane', () => {
73+
it('keeps the package pin set in sync with the version map', () => {
74+
expect(HL7_EU_EHDS_2026_PACKAGE_SET)
75+
.toHaveLength(Object.keys(HL7_EU_EHDS_2026_PACKAGE_VERSIONS).length);
76+
expect(HL7_EU_EHDS_2026_PACKAGE_SET).toContainEqual({
77+
id: 'hl7.fhir.eu.laboratory',
78+
version: '2.0.0'
79+
});
80+
expect(HL7_EU_EHDS_2026_PACKAGE_SET).toContainEqual({
81+
id: 'hl7.fhir.eu.eps',
82+
version: '1.0.0-alpha'
83+
});
84+
});
85+
86+
it('creates an EHDS preset on top of the MII baseline', () => {
87+
const settings = createEhds2026ValidationSettings();
88+
89+
for (const { id, version } of MII_2026_PACKAGE_SET) {
90+
expect(settings.packageDownload?.pinnedVersions[id]).toBe(version);
91+
expect(settings.packageDownload?.approvedPackages).toContain(id);
92+
}
93+
for (const { id, version } of HL7_EU_EHDS_2026_PACKAGE_SET) {
94+
expect(settings.packageDownload?.pinnedVersions[id]).toBe(version);
95+
expect(settings.packageDownload?.approvedPackages).toContain(id);
96+
expect(settings.hapiConfig?.igPackages).toContain(`${id}#${version}`);
97+
}
98+
expect(settings.hapiConfig?.igPackages).toContain(
99+
'de.medizininformatikinitiative.kerndatensatz.consent#2026.0.1-rc-2'
100+
);
101+
expect(settings.mii?.preset).toBe('ehds-2026');
102+
expect(settings.mii?.terminologyMode).toBe('mii-local-blaze');
49103
});
50104
});
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { describe, expect, it } from 'vitest';
2+
import {
3+
R4_DEFAULT_INCLUDED_RESOURCE_TYPES,
4+
R5_DEFAULT_INCLUDED_RESOURCE_TYPES,
5+
getDefaultValidationSettingsForVersion,
6+
} from '../settings-utils';
7+
8+
describe('validation settings defaults', () => {
9+
it('includes Bundle in default R4 and R5 validation resource types', () => {
10+
expect(R4_DEFAULT_INCLUDED_RESOURCE_TYPES).toContain('Bundle');
11+
expect(R5_DEFAULT_INCLUDED_RESOURCE_TYPES).toContain('Bundle');
12+
});
13+
14+
it('enables Bundle validation in generated default settings', () => {
15+
expect(getDefaultValidationSettingsForVersion('R4').resourceTypes.includedTypes).toContain('Bundle');
16+
expect(getDefaultValidationSettingsForVersion('R5').resourceTypes.includedTypes).toContain('Bundle');
17+
});
18+
});

packages/validation-types/src/validation/dtos.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,7 @@ export interface ValidationMessageGroupDTO {
144144
serverId?: number; // Server ID (for single-server queries, or first seen for multi-server)
145145
resourceType?: string; // Primary resource type for this issue group
146146
resourceTypeCounts?: Record<string, number>; // Per-type resource counts (e.g. { Patient: 5, Encounter: 3 })
147+
validationEngineVersion?: string; // Engine version observed for the affected resource/aspect results
147148
}
148149

149150
/**
@@ -180,6 +181,7 @@ export interface ResourceMessagesDTO {
180181
text: string;
181182
signature: string;
182183
createdAt: Date;
184+
validationEngineVersion?: string;
183185
}[];
184186
}[];
185187
}

packages/validation-types/src/validation/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,10 @@ export type {
103103
export { PERFORMANCE_LIMITS } from './settings';
104104

105105
export {
106+
createEhds2026ValidationSettings,
106107
createMii2026ValidationSettings,
108+
HL7_EU_EHDS_2026_PACKAGE_SET,
109+
HL7_EU_EHDS_2026_PACKAGE_VERSIONS,
107110
MII_2026_PACKAGE_SET,
108111
MII_2026_PACKAGE_VERSIONS,
109112
type FhirPackagePin,

packages/validation-types/src/validation/settings-defaults.ts

Lines changed: 105 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,15 +94,33 @@ export const MII_2026_PACKAGE_SET: FhirPackagePin[] = Object.entries(
9494
MII_2026_PACKAGE_VERSIONS
9595
).map(([id, version]) => ({ id, version }));
9696

97+
export const HL7_EU_EHDS_2026_PACKAGE_VERSIONS = {
98+
'hl7.fhir.eu.extensions.r4': '1.3.0',
99+
'hl7.fhir.eu.base': '2.0.0',
100+
'hl7.fhir.eu.laboratory': '2.0.0',
101+
'hl7.fhir.eu.eps': '1.0.0-alpha',
102+
'hl7.fhir.eu.hdr': '0.1.0-ballot',
103+
'hl7.fhir.eu.imaging': '1.0.0-ballot',
104+
'hl7.fhir.eu.health-data-api': '1.0.0-ballot',
105+
} as const;
106+
107+
export const HL7_EU_EHDS_2026_PACKAGE_SET: FhirPackagePin[] = Object.entries(
108+
HL7_EU_EHDS_2026_PACKAGE_VERSIONS
109+
).map(([id, version]) => ({ id, version }));
110+
97111
const MII_2026_IG_PACKAGES = MII_2026_PACKAGE_SET.map(({ id, version }) => `${id}#${version}`);
112+
const HL7_EU_EHDS_2026_IG_PACKAGES = HL7_EU_EHDS_2026_PACKAGE_SET.map(
113+
({ id, version }) => `${id}#${version}`
114+
);
98115

99116
export type Mii2026ValidationSettingsOverrides = Omit<
100117
Partial<ValidationSettings>,
101-
'packageDownload' | 'profileSources' | 'hapiConfig'
118+
'packageDownload' | 'profileSources' | 'hapiConfig' | 'mii'
102119
> & {
103120
packageDownload?: Partial<NonNullable<ValidationSettings['packageDownload']>>;
104121
profileSources?: Partial<NonNullable<ValidationSettings['profileSources']>>;
105122
hapiConfig?: Partial<NonNullable<ValidationSettings['hapiConfig']>>;
123+
mii?: Partial<NonNullable<ValidationSettings['mii']>>;
106124
};
107125

108126
/**
@@ -527,7 +545,7 @@ export const DEFAULT_VALIDATION_SETTINGS_R5: ValidationSettings = {
527545
};
528546

529547
/**
530-
* Create an R4 validation settings preset for the MII 2026 package set.
548+
* Create an R4 validation settings object for the MII 2026 package set.
531549
*
532550
* The preset keeps the standard Records validator behavior but pins every
533551
* MII package version used by the 2026 conformance target so automatic package
@@ -568,10 +586,20 @@ export function createMii2026ValidationSettings(
568586
cachePath: settings.hapiConfig?.cachePath ?? '/tmp/fhir-packages',
569587
enableBestPractice: settings.hapiConfig?.enableBestPractice ?? true
570588
};
589+
settings.mii = {
590+
preset: 'mii-2026',
591+
terminologyMode: 'mii-local-blaze',
592+
maxOntoserverRequestsPerRun: 250,
593+
allowHighVolumeOntoserver: false
594+
};
571595

572596
return {
573597
...settings,
574598
...overrides,
599+
mii: {
600+
...settings.mii,
601+
...overrides.mii
602+
},
575603
packageDownload: {
576604
...settings.packageDownload,
577605
...overrides.packageDownload,
@@ -591,3 +619,78 @@ export function createMii2026ValidationSettings(
591619
}
592620
};
593621
}
622+
623+
/**
624+
* Create an R4 validation settings object for EHDS-oriented data tests.
625+
*
626+
* The EHDS lane builds on the MII 2026 baseline because German EHDS pilots
627+
* need the same local terminology and KDS package behavior, then adds the
628+
* HL7 Europe package pins used by cross-border EHDS scenarios.
629+
*/
630+
export function createEhds2026ValidationSettings(
631+
overrides: Mii2026ValidationSettingsOverrides = {}
632+
): ValidationSettings {
633+
const settings = createMii2026ValidationSettings();
634+
const approvedPackages = new Set([
635+
...(settings.packageDownload?.approvedPackages ?? []),
636+
...HL7_EU_EHDS_2026_PACKAGE_SET.map(({ id }) => id)
637+
]);
638+
639+
settings.packageDownload = {
640+
versionPolicy: settings.packageDownload?.versionPolicy ?? 'prefer-stable',
641+
pinnedVersions: {
642+
...(settings.packageDownload?.pinnedVersions ?? {}),
643+
...HL7_EU_EHDS_2026_PACKAGE_VERSIONS
644+
},
645+
approvedPackages: Array.from(approvedPackages),
646+
requireApproval: settings.packageDownload?.requireApproval ?? false,
647+
autoDownload: settings.packageDownload?.autoDownload ?? true
648+
};
649+
650+
settings.hapiConfig = {
651+
enabled: settings.hapiConfig?.enabled ?? false,
652+
timeout: settings.hapiConfig?.timeout ?? 30000,
653+
igPackages: [...MII_2026_IG_PACKAGES, ...HL7_EU_EHDS_2026_IG_PACKAGES],
654+
useProcessPool: settings.hapiConfig?.useProcessPool ?? true,
655+
poolSize: settings.hapiConfig?.poolSize ?? 3,
656+
cachePath: settings.hapiConfig?.cachePath ?? '/tmp/fhir-packages',
657+
enableBestPractice: settings.hapiConfig?.enableBestPractice ?? true
658+
};
659+
660+
settings.mii = {
661+
preset: 'ehds-2026',
662+
terminologyMode: settings.mii?.terminologyMode ?? 'mii-local-blaze',
663+
packageLockHash: settings.mii?.packageLockHash,
664+
maxOntoserverRequestsPerRun: settings.mii?.maxOntoserverRequestsPerRun,
665+
allowHighVolumeOntoserver: settings.mii?.allowHighVolumeOntoserver
666+
};
667+
668+
return {
669+
...settings,
670+
...overrides,
671+
mii: {
672+
...settings.mii,
673+
...overrides.mii,
674+
terminologyMode: overrides.mii?.terminologyMode ?? settings.mii.terminologyMode,
675+
preset: 'ehds-2026'
676+
},
677+
packageDownload: {
678+
...settings.packageDownload,
679+
...overrides.packageDownload,
680+
pinnedVersions: {
681+
...settings.packageDownload.pinnedVersions,
682+
...overrides.packageDownload?.pinnedVersions
683+
},
684+
approvedPackages: overrides.packageDownload?.approvedPackages ?? settings.packageDownload.approvedPackages
685+
},
686+
profileSources: {
687+
fhirServer: overrides.profileSources?.fhirServer ?? settings.profileSources?.fhirServer ?? true,
688+
simplifier: overrides.profileSources?.simplifier ?? settings.profileSources?.simplifier ?? true,
689+
packageRegistry: overrides.profileSources?.packageRegistry ?? settings.profileSources?.packageRegistry ?? true
690+
},
691+
hapiConfig: {
692+
...settings.hapiConfig,
693+
...overrides.hapiConfig
694+
}
695+
};
696+
}

0 commit comments

Comments
 (0)