vet-data-utils-ts 0.5.27 → 0.5.29
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/insurance-consent.d.ts +126 -0
- package/dist/insurance-consent.js +228 -0
- package/dist/provenance.d.ts +2 -1
- package/dist/provenance.js +9 -0
- package/dist/scheduling.d.ts +2 -2
- package/package.json +6 -2
package/README.md
CHANGED
|
@@ -126,6 +126,11 @@ resource-specific standard SearchParameters and preserves agent correlation as
|
|
|
126
126
|
exact code from the FHIR ParticipationRoleType ValueSet and the value is the
|
|
127
127
|
agent's FHIR Reference or URI. The standard `Provenance.agent` and
|
|
128
128
|
`Provenance.agent-type` claims are indexed alongside that correlation claim.
|
|
129
|
+
For a professional, use
|
|
130
|
+
`buildPractitionerRoleReferenceFromAssignmentIdentifier()` with the real
|
|
131
|
+
Occupation/PractitionerRole assignment UUID returned by GW. The role-bearing
|
|
132
|
+
employee URN and role-license hash remain operational authorization identities;
|
|
133
|
+
they are not substituted for the clinical `PractitionerRole` reference.
|
|
129
134
|
|
|
130
135
|
ResearchStudy professional teams use native FHIR R5 Group resources from
|
|
131
136
|
`vet-data-utils-ts/group`: required type and membership codes, the exact twelve
|
|
@@ -141,6 +146,15 @@ future PATCH. The matching `normalize*FlatClaimsResource()` functions reject
|
|
|
141
146
|
nested FHIR persistence fields and unknown claims. Native FHIR JSON remains an
|
|
142
147
|
explicit import, projection or export boundary.
|
|
143
148
|
|
|
149
|
+
Animal-insurance eligibility Consent uses the same boundary through
|
|
150
|
+
`vet-data-utils-ts/insurance-consent`: FHIR-equivalent authorization semantics
|
|
151
|
+
live in canonical flat claims, the complete query-shaped ODRL Agreement lives
|
|
152
|
+
in an `application/odrl+json` attachment, semantic divergence fails closed,
|
|
153
|
+
and native R4/R5 appears only when explicitly requested. Aggregations such as
|
|
154
|
+
"latest date" and "count" remain ODRL-only because FHIR Consent has no native
|
|
155
|
+
field for them. See
|
|
156
|
+
[`docs/insurance-consent-odrl.md`](docs/insurance-consent-odrl.md).
|
|
157
|
+
|
|
144
158
|
Reusable Communication screens receive immutable workflow presets from
|
|
145
159
|
`vet-data-utils-ts/communication`. The research-agreement screen is fixed to
|
|
146
160
|
FHIR `notification` plus HL7 v3 ActReason `HRESCH` and does not expose a topic
|
package/dist/index.d.ts
CHANGED
|
@@ -11,6 +11,7 @@ export * from './health-dcat.js';
|
|
|
11
11
|
export * from './immunization.js';
|
|
12
12
|
export * from './international-health-card.js';
|
|
13
13
|
export * from './index-projection-tags.js';
|
|
14
|
+
export * from './insurance-consent.js';
|
|
14
15
|
export * from './iso-jurisdictions.js';
|
|
15
16
|
export * from './organization-application.js';
|
|
16
17
|
export * from './payment.js';
|
package/dist/index.js
CHANGED
|
@@ -11,6 +11,7 @@ export * from './health-dcat.js';
|
|
|
11
11
|
export * from './immunization.js';
|
|
12
12
|
export * from './international-health-card.js';
|
|
13
13
|
export * from './index-projection-tags.js';
|
|
14
|
+
export * from './insurance-consent.js';
|
|
14
15
|
export * from './iso-jurisdictions.js';
|
|
15
16
|
export * from './organization-application.js';
|
|
16
17
|
export * from './payment.js';
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { ResourceTypesFhirR4 } from 'gdc-common-utils-ts/constants/fhir-resource-types';
|
|
2
|
+
/** W3C ODRL and VetChain profile identifiers used by insurance eligibility consent. */
|
|
3
|
+
export declare const AnimalInsuranceConsentVocabulary: Readonly<{
|
|
4
|
+
readonly OdrlContext: "http://www.w3.org/ns/odrl.jsonld";
|
|
5
|
+
readonly Agreement: "Agreement";
|
|
6
|
+
readonly Read: "read";
|
|
7
|
+
readonly Equal: "eq";
|
|
8
|
+
readonly GreaterThanOrEqual: "gteq";
|
|
9
|
+
readonly LessThanOrEqual: "lteq";
|
|
10
|
+
readonly MediaType: "application/odrl+json";
|
|
11
|
+
readonly Profile: "https://vetchain.app/ns/odrl/animal-insurance-eligibility/v1";
|
|
12
|
+
readonly EligibilitySummaryTarget: "https://vetchain.app/ns/asset/animal-insurance-eligibility-summary";
|
|
13
|
+
readonly FactKindOperand: "https://vetchain.app/ns/odrl/operand/eligibility-fact-kind";
|
|
14
|
+
readonly ClinicalCodeOperand: "https://vetchain.app/ns/odrl/operand/clinical-code";
|
|
15
|
+
readonly DataPeriodStartOperand: "https://vetchain.app/ns/odrl/operand/data-period-start";
|
|
16
|
+
readonly DataPeriodEndOperand: "https://vetchain.app/ns/odrl/operand/data-period-end";
|
|
17
|
+
}>;
|
|
18
|
+
export declare const AnimalInsuranceEligibilityFactKinds: Readonly<{
|
|
19
|
+
readonly LatestEventDate: "latest-event-date";
|
|
20
|
+
readonly EventCount: "event-count";
|
|
21
|
+
}>;
|
|
22
|
+
export declare const AnimalInsuranceConsentErrors: Readonly<{
|
|
23
|
+
readonly InvalidOdrl: "insurance_consent_odrl_invalid";
|
|
24
|
+
readonly OdrlClaimsDiverge: "insurance_consent_odrl_claims_diverge";
|
|
25
|
+
readonly ResearchForbidden: "insurance_consent_research_forbidden";
|
|
26
|
+
readonly FactsRequired: "insurance_consent_facts_required";
|
|
27
|
+
}>;
|
|
28
|
+
/** Reusable values for package, GW and portal contract tests. */
|
|
29
|
+
export declare const ANIMAL_INSURANCE_CONSENT_TEST_DATA: Readonly<{
|
|
30
|
+
readonly consentId: "animal-insurance-consent-test-01";
|
|
31
|
+
readonly consentIdentifier: "urn:uuid:54b4d158-ed78-48b4-b006-84ba5a5d85b4";
|
|
32
|
+
readonly subjectReference: "Patient/animal-beneficiary-test-01";
|
|
33
|
+
readonly controllerReference: "RelatedPerson/controller-test-01";
|
|
34
|
+
readonly insurerReference: "Organization/animal-insurer-test-01";
|
|
35
|
+
readonly managerReference: "Organization/vetchain-consent-manager-test-01";
|
|
36
|
+
readonly enforcerReference: "Organization/vetchain-consent-enforcer-test-01";
|
|
37
|
+
readonly createdAt: "2026-09-08";
|
|
38
|
+
readonly consentPeriodStart: "2026-09-08T00:00:00Z";
|
|
39
|
+
readonly consentPeriodEnd: "2026-10-08T00:00:00Z";
|
|
40
|
+
readonly dataPeriodStart: "2025-09-08T00:00:00Z";
|
|
41
|
+
readonly dataPeriodEnd: "2026-09-08T00:00:00Z";
|
|
42
|
+
readonly actorRole: "http://terminology.hl7.org/CodeSystem/v3-RoleCode|PAYOR";
|
|
43
|
+
readonly action: "http://terminology.hl7.org/CodeSystem/consentaction|access";
|
|
44
|
+
readonly purpose: "http://terminology.hl7.org/CodeSystem/v3-ActReason|HOPERAT";
|
|
45
|
+
readonly scope: "http://terminology.hl7.org/CodeSystem/consentscope|patient-privacy";
|
|
46
|
+
readonly category: "http://loinc.org|59284-0";
|
|
47
|
+
readonly resourceType: "http://hl7.org/fhir/fhir-types|Observation";
|
|
48
|
+
readonly clinicalCode: "http://loinc.org|85353-1";
|
|
49
|
+
readonly secondClinicalCode: "http://loinc.org|8310-5";
|
|
50
|
+
readonly clinicalCodeList: "http://loinc.org|85353-1,http://loinc.org|8310-5";
|
|
51
|
+
readonly status: "active";
|
|
52
|
+
readonly decision: "permit";
|
|
53
|
+
readonly factKind: "latest-event-date";
|
|
54
|
+
readonly forbiddenPurpose: "http://terminology.hl7.org/CodeSystem/v3-ActReason|HRESCH";
|
|
55
|
+
readonly divergentInsurerReference: "Organization/different-animal-insurer-test-01";
|
|
56
|
+
readonly jurisdiction: "CA";
|
|
57
|
+
readonly fhirConsentResourceType: "Consent";
|
|
58
|
+
}>;
|
|
59
|
+
export type AnimalInsuranceEligibilityFact = Readonly<{
|
|
60
|
+
kind: typeof AnimalInsuranceEligibilityFactKinds[keyof typeof AnimalInsuranceEligibilityFactKinds];
|
|
61
|
+
clinicalCode: string;
|
|
62
|
+
}>;
|
|
63
|
+
export type AnimalInsuranceConsentInput = Readonly<{
|
|
64
|
+
id: string;
|
|
65
|
+
identifier: string;
|
|
66
|
+
subjectReference: string;
|
|
67
|
+
grantorReference: string;
|
|
68
|
+
granteeReference: string;
|
|
69
|
+
managerReference: string;
|
|
70
|
+
controllerReference: string;
|
|
71
|
+
createdAt: string;
|
|
72
|
+
consentPeriod: Readonly<{
|
|
73
|
+
start: string;
|
|
74
|
+
end: string;
|
|
75
|
+
}>;
|
|
76
|
+
dataPeriod: Readonly<{
|
|
77
|
+
start: string;
|
|
78
|
+
end: string;
|
|
79
|
+
}>;
|
|
80
|
+
actorRole: string;
|
|
81
|
+
action: string;
|
|
82
|
+
purpose: string;
|
|
83
|
+
scope: string;
|
|
84
|
+
category: string;
|
|
85
|
+
resourceType: string;
|
|
86
|
+
facts: readonly AnimalInsuranceEligibilityFact[];
|
|
87
|
+
}>;
|
|
88
|
+
/** Complete reusable builder input used by downstream GW, SDK and portal tests. */
|
|
89
|
+
export declare const ANIMAL_INSURANCE_CONSENT_TEST_INPUT: AnimalInsuranceConsentInput;
|
|
90
|
+
export type ClaimsFirstAnimalInsuranceConsent = Readonly<{
|
|
91
|
+
resourceType: typeof ResourceTypesFhirR4.Consent;
|
|
92
|
+
id: string;
|
|
93
|
+
meta: Readonly<{
|
|
94
|
+
claims: Readonly<Record<string, string>>;
|
|
95
|
+
}>;
|
|
96
|
+
}>;
|
|
97
|
+
export type AnimalInsuranceOdrlConstraint = Readonly<{
|
|
98
|
+
leftOperand: string;
|
|
99
|
+
operator: string;
|
|
100
|
+
rightOperand: string;
|
|
101
|
+
}>;
|
|
102
|
+
export type AnimalInsuranceOdrlPolicy = Readonly<{
|
|
103
|
+
'@context': typeof AnimalInsuranceConsentVocabulary.OdrlContext;
|
|
104
|
+
'@type': typeof AnimalInsuranceConsentVocabulary.Agreement;
|
|
105
|
+
uid: string;
|
|
106
|
+
profile: typeof AnimalInsuranceConsentVocabulary.Profile;
|
|
107
|
+
assigner: string;
|
|
108
|
+
assignee: string;
|
|
109
|
+
permission: readonly Readonly<{
|
|
110
|
+
target: typeof AnimalInsuranceConsentVocabulary.EligibilitySummaryTarget;
|
|
111
|
+
action: typeof AnimalInsuranceConsentVocabulary.Read;
|
|
112
|
+
constraint: readonly AnimalInsuranceOdrlConstraint[];
|
|
113
|
+
}>[];
|
|
114
|
+
}>;
|
|
115
|
+
/**
|
|
116
|
+
* Builds an atomic claims-first FHIR Consent for one insurer eligibility query.
|
|
117
|
+
* Standard authorization semantics are mirrored in flat Consent claims; the
|
|
118
|
+
* complete query-shaping policy remains an ODRL JSON attachment.
|
|
119
|
+
*/
|
|
120
|
+
export declare function buildAnimalInsuranceEligibilityConsent(input: AnimalInsuranceConsentInput): ClaimsFirstAnimalInsuranceConsent;
|
|
121
|
+
/** Parses the attached ODRL and fails closed unless its authorization semantics match the claims. */
|
|
122
|
+
export declare function validateAnimalInsuranceConsentOdrlParity(resource: ClaimsFirstAnimalInsuranceConsent): AnimalInsuranceOdrlPolicy;
|
|
123
|
+
/** Validates parity, then exports a native FHIR R4 Consent without ODRL-only fields. */
|
|
124
|
+
export declare function projectAnimalInsuranceConsentToFhirR4(resource: ClaimsFirstAnimalInsuranceConsent): Record<string, unknown>;
|
|
125
|
+
/** Validates parity, then exports a native FHIR R5 Consent without ODRL-only fields. */
|
|
126
|
+
export declare function projectAnimalInsuranceConsentToFhirR5(resource: ClaimsFirstAnimalInsuranceConsent): Record<string, unknown>;
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
import { ClaimConsent, ConsentDecisions, ConsentStatuses, } from 'gdc-common-utils-ts/models/consent-rule';
|
|
2
|
+
import { HealthcareConsentPurposes, } from 'gdc-common-utils-ts/constants/healthcare';
|
|
3
|
+
import { ResourceTypesFhirR4 } from 'gdc-common-utils-ts/constants/fhir-resource-types';
|
|
4
|
+
import { consentFlatToFhirR4, consentFlatToFhirR5, } from 'gdc-common-utils-ts/convert/convert-consent';
|
|
5
|
+
/** W3C ODRL and VetChain profile identifiers used by insurance eligibility consent. */
|
|
6
|
+
export const AnimalInsuranceConsentVocabulary = Object.freeze({
|
|
7
|
+
OdrlContext: 'http://www.w3.org/ns/odrl.jsonld',
|
|
8
|
+
Agreement: 'Agreement',
|
|
9
|
+
Read: 'read',
|
|
10
|
+
Equal: 'eq',
|
|
11
|
+
GreaterThanOrEqual: 'gteq',
|
|
12
|
+
LessThanOrEqual: 'lteq',
|
|
13
|
+
MediaType: 'application/odrl+json',
|
|
14
|
+
Profile: 'https://vetchain.app/ns/odrl/animal-insurance-eligibility/v1',
|
|
15
|
+
EligibilitySummaryTarget: 'https://vetchain.app/ns/asset/animal-insurance-eligibility-summary',
|
|
16
|
+
FactKindOperand: 'https://vetchain.app/ns/odrl/operand/eligibility-fact-kind',
|
|
17
|
+
ClinicalCodeOperand: 'https://vetchain.app/ns/odrl/operand/clinical-code',
|
|
18
|
+
DataPeriodStartOperand: 'https://vetchain.app/ns/odrl/operand/data-period-start',
|
|
19
|
+
DataPeriodEndOperand: 'https://vetchain.app/ns/odrl/operand/data-period-end',
|
|
20
|
+
});
|
|
21
|
+
export const AnimalInsuranceEligibilityFactKinds = Object.freeze({
|
|
22
|
+
LatestEventDate: 'latest-event-date',
|
|
23
|
+
EventCount: 'event-count',
|
|
24
|
+
});
|
|
25
|
+
export const AnimalInsuranceConsentErrors = Object.freeze({
|
|
26
|
+
InvalidOdrl: 'insurance_consent_odrl_invalid',
|
|
27
|
+
OdrlClaimsDiverge: 'insurance_consent_odrl_claims_diverge',
|
|
28
|
+
ResearchForbidden: 'insurance_consent_research_forbidden',
|
|
29
|
+
FactsRequired: 'insurance_consent_facts_required',
|
|
30
|
+
});
|
|
31
|
+
/** Reusable values for package, GW and portal contract tests. */
|
|
32
|
+
export const ANIMAL_INSURANCE_CONSENT_TEST_DATA = Object.freeze({
|
|
33
|
+
consentId: 'animal-insurance-consent-test-01',
|
|
34
|
+
consentIdentifier: 'urn:uuid:54b4d158-ed78-48b4-b006-84ba5a5d85b4',
|
|
35
|
+
subjectReference: 'Patient/animal-beneficiary-test-01',
|
|
36
|
+
controllerReference: 'RelatedPerson/controller-test-01',
|
|
37
|
+
insurerReference: 'Organization/animal-insurer-test-01',
|
|
38
|
+
managerReference: 'Organization/vetchain-consent-manager-test-01',
|
|
39
|
+
enforcerReference: 'Organization/vetchain-consent-enforcer-test-01',
|
|
40
|
+
createdAt: '2026-09-08',
|
|
41
|
+
consentPeriodStart: '2026-09-08T00:00:00Z',
|
|
42
|
+
consentPeriodEnd: '2026-10-08T00:00:00Z',
|
|
43
|
+
dataPeriodStart: '2025-09-08T00:00:00Z',
|
|
44
|
+
dataPeriodEnd: '2026-09-08T00:00:00Z',
|
|
45
|
+
actorRole: 'http://terminology.hl7.org/CodeSystem/v3-RoleCode|PAYOR',
|
|
46
|
+
action: 'http://terminology.hl7.org/CodeSystem/consentaction|access',
|
|
47
|
+
purpose: `http://terminology.hl7.org/CodeSystem/v3-ActReason|${HealthcareConsentPurposes.Operations}`,
|
|
48
|
+
scope: 'http://terminology.hl7.org/CodeSystem/consentscope|patient-privacy',
|
|
49
|
+
category: 'http://loinc.org|59284-0',
|
|
50
|
+
resourceType: 'http://hl7.org/fhir/fhir-types|Observation',
|
|
51
|
+
clinicalCode: 'http://loinc.org|85353-1',
|
|
52
|
+
secondClinicalCode: 'http://loinc.org|8310-5',
|
|
53
|
+
clinicalCodeList: 'http://loinc.org|85353-1,http://loinc.org|8310-5',
|
|
54
|
+
status: ConsentStatuses.Active,
|
|
55
|
+
decision: ConsentDecisions.Permit,
|
|
56
|
+
factKind: AnimalInsuranceEligibilityFactKinds.LatestEventDate,
|
|
57
|
+
forbiddenPurpose: `http://terminology.hl7.org/CodeSystem/v3-ActReason|${HealthcareConsentPurposes.Research}`,
|
|
58
|
+
divergentInsurerReference: 'Organization/different-animal-insurer-test-01',
|
|
59
|
+
jurisdiction: 'CA',
|
|
60
|
+
fhirConsentResourceType: ResourceTypesFhirR4.Consent,
|
|
61
|
+
});
|
|
62
|
+
/** Complete reusable builder input used by downstream GW, SDK and portal tests. */
|
|
63
|
+
export const ANIMAL_INSURANCE_CONSENT_TEST_INPUT = Object.freeze({
|
|
64
|
+
id: ANIMAL_INSURANCE_CONSENT_TEST_DATA.consentId,
|
|
65
|
+
identifier: ANIMAL_INSURANCE_CONSENT_TEST_DATA.consentIdentifier,
|
|
66
|
+
subjectReference: ANIMAL_INSURANCE_CONSENT_TEST_DATA.subjectReference,
|
|
67
|
+
grantorReference: ANIMAL_INSURANCE_CONSENT_TEST_DATA.controllerReference,
|
|
68
|
+
granteeReference: ANIMAL_INSURANCE_CONSENT_TEST_DATA.insurerReference,
|
|
69
|
+
managerReference: ANIMAL_INSURANCE_CONSENT_TEST_DATA.managerReference,
|
|
70
|
+
controllerReference: ANIMAL_INSURANCE_CONSENT_TEST_DATA.enforcerReference,
|
|
71
|
+
createdAt: ANIMAL_INSURANCE_CONSENT_TEST_DATA.createdAt,
|
|
72
|
+
consentPeriod: Object.freeze({
|
|
73
|
+
start: ANIMAL_INSURANCE_CONSENT_TEST_DATA.consentPeriodStart,
|
|
74
|
+
end: ANIMAL_INSURANCE_CONSENT_TEST_DATA.consentPeriodEnd,
|
|
75
|
+
}),
|
|
76
|
+
dataPeriod: Object.freeze({
|
|
77
|
+
start: ANIMAL_INSURANCE_CONSENT_TEST_DATA.dataPeriodStart,
|
|
78
|
+
end: ANIMAL_INSURANCE_CONSENT_TEST_DATA.dataPeriodEnd,
|
|
79
|
+
}),
|
|
80
|
+
actorRole: ANIMAL_INSURANCE_CONSENT_TEST_DATA.actorRole,
|
|
81
|
+
action: ANIMAL_INSURANCE_CONSENT_TEST_DATA.action,
|
|
82
|
+
purpose: ANIMAL_INSURANCE_CONSENT_TEST_DATA.purpose,
|
|
83
|
+
scope: ANIMAL_INSURANCE_CONSENT_TEST_DATA.scope,
|
|
84
|
+
category: ANIMAL_INSURANCE_CONSENT_TEST_DATA.category,
|
|
85
|
+
resourceType: ANIMAL_INSURANCE_CONSENT_TEST_DATA.resourceType,
|
|
86
|
+
facts: Object.freeze([{
|
|
87
|
+
kind: ANIMAL_INSURANCE_CONSENT_TEST_DATA.factKind,
|
|
88
|
+
clinicalCode: ANIMAL_INSURANCE_CONSENT_TEST_DATA.clinicalCode,
|
|
89
|
+
}, {
|
|
90
|
+
kind: AnimalInsuranceEligibilityFactKinds.EventCount,
|
|
91
|
+
clinicalCode: ANIMAL_INSURANCE_CONSENT_TEST_DATA.secondClinicalCode,
|
|
92
|
+
}]),
|
|
93
|
+
});
|
|
94
|
+
function encodeBase64Utf8(value) {
|
|
95
|
+
const bytes = new TextEncoder().encode(value);
|
|
96
|
+
let binary = '';
|
|
97
|
+
bytes.forEach((byte) => { binary += String.fromCharCode(byte); });
|
|
98
|
+
return btoa(binary);
|
|
99
|
+
}
|
|
100
|
+
function decodeBase64Utf8(value) {
|
|
101
|
+
const binary = atob(value);
|
|
102
|
+
const bytes = Uint8Array.from(binary, (character) => character.charCodeAt(0));
|
|
103
|
+
return new TextDecoder().decode(bytes);
|
|
104
|
+
}
|
|
105
|
+
function buildPolicy(input) {
|
|
106
|
+
return {
|
|
107
|
+
'@context': AnimalInsuranceConsentVocabulary.OdrlContext,
|
|
108
|
+
'@type': AnimalInsuranceConsentVocabulary.Agreement,
|
|
109
|
+
uid: input.identifier,
|
|
110
|
+
profile: AnimalInsuranceConsentVocabulary.Profile,
|
|
111
|
+
assigner: input.grantorReference,
|
|
112
|
+
assignee: input.granteeReference,
|
|
113
|
+
permission: input.facts.map((fact) => ({
|
|
114
|
+
target: AnimalInsuranceConsentVocabulary.EligibilitySummaryTarget,
|
|
115
|
+
action: AnimalInsuranceConsentVocabulary.Read,
|
|
116
|
+
constraint: [
|
|
117
|
+
{ leftOperand: AnimalInsuranceConsentVocabulary.FactKindOperand, operator: AnimalInsuranceConsentVocabulary.Equal, rightOperand: fact.kind },
|
|
118
|
+
{ leftOperand: AnimalInsuranceConsentVocabulary.ClinicalCodeOperand, operator: AnimalInsuranceConsentVocabulary.Equal, rightOperand: fact.clinicalCode },
|
|
119
|
+
{ leftOperand: AnimalInsuranceConsentVocabulary.DataPeriodStartOperand, operator: AnimalInsuranceConsentVocabulary.GreaterThanOrEqual, rightOperand: input.dataPeriod.start },
|
|
120
|
+
{ leftOperand: AnimalInsuranceConsentVocabulary.DataPeriodEndOperand, operator: AnimalInsuranceConsentVocabulary.LessThanOrEqual, rightOperand: input.dataPeriod.end },
|
|
121
|
+
],
|
|
122
|
+
})),
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
function rejectResearchSemantics(input) {
|
|
126
|
+
if (input.purpose.split('|').at(-1) === HealthcareConsentPurposes.Research
|
|
127
|
+
|| input.resourceType.split('|').at(-1) === ResourceTypesFhirR4.ResearchStudy) {
|
|
128
|
+
throw new TypeError(AnimalInsuranceConsentErrors.ResearchForbidden);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Builds an atomic claims-first FHIR Consent for one insurer eligibility query.
|
|
133
|
+
* Standard authorization semantics are mirrored in flat Consent claims; the
|
|
134
|
+
* complete query-shaping policy remains an ODRL JSON attachment.
|
|
135
|
+
*/
|
|
136
|
+
export function buildAnimalInsuranceEligibilityConsent(input) {
|
|
137
|
+
rejectResearchSemantics(input);
|
|
138
|
+
if (!input.facts.length)
|
|
139
|
+
throw new TypeError(AnimalInsuranceConsentErrors.FactsRequired);
|
|
140
|
+
if (input.facts.some((fact) => !Object.values(AnimalInsuranceEligibilityFactKinds).includes(fact.kind))) {
|
|
141
|
+
throw new TypeError(AnimalInsuranceConsentErrors.InvalidOdrl);
|
|
142
|
+
}
|
|
143
|
+
const policy = buildPolicy(input);
|
|
144
|
+
return {
|
|
145
|
+
resourceType: ResourceTypesFhirR4.Consent,
|
|
146
|
+
id: input.id,
|
|
147
|
+
meta: {
|
|
148
|
+
claims: {
|
|
149
|
+
'@context': 'org.hl7.fhir.api',
|
|
150
|
+
[ClaimConsent.identifier]: input.identifier,
|
|
151
|
+
[ClaimConsent.status]: ConsentStatuses.Active,
|
|
152
|
+
[ClaimConsent.subject]: input.subjectReference,
|
|
153
|
+
[ClaimConsent.date]: input.createdAt,
|
|
154
|
+
[ClaimConsent.decision]: ConsentDecisions.Permit,
|
|
155
|
+
[ClaimConsent.periodStart]: input.consentPeriod.start,
|
|
156
|
+
[ClaimConsent.periodEnd]: input.consentPeriod.end,
|
|
157
|
+
[ClaimConsent.dataPeriodStart]: input.dataPeriod.start,
|
|
158
|
+
[ClaimConsent.dataPeriodEnd]: input.dataPeriod.end,
|
|
159
|
+
[ClaimConsent.grantor]: input.grantorReference,
|
|
160
|
+
[ClaimConsent.grantee]: input.granteeReference,
|
|
161
|
+
[ClaimConsent.manager]: input.managerReference,
|
|
162
|
+
[ClaimConsent.controller]: input.controllerReference,
|
|
163
|
+
[ClaimConsent.actorIdentifier]: input.granteeReference,
|
|
164
|
+
[ClaimConsent.actorRole]: input.actorRole,
|
|
165
|
+
[ClaimConsent.action]: input.action,
|
|
166
|
+
[ClaimConsent.purpose]: input.purpose,
|
|
167
|
+
[ClaimConsent.scope]: input.scope,
|
|
168
|
+
[ClaimConsent.category]: input.category,
|
|
169
|
+
[ClaimConsent.resourceType]: input.resourceType,
|
|
170
|
+
[ClaimConsent.provisionCode]: input.facts.map((fact) => fact.clinicalCode).join(','),
|
|
171
|
+
[ClaimConsent.attachmentContentType]: AnimalInsuranceConsentVocabulary.MediaType,
|
|
172
|
+
[ClaimConsent.attachmentData]: encodeBase64Utf8(JSON.stringify(policy)),
|
|
173
|
+
},
|
|
174
|
+
},
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
function constraintValue(permission, operand) {
|
|
178
|
+
return permission.constraint.find((constraint) => constraint.leftOperand === operand)?.rightOperand;
|
|
179
|
+
}
|
|
180
|
+
/** Parses the attached ODRL and fails closed unless its authorization semantics match the claims. */
|
|
181
|
+
export function validateAnimalInsuranceConsentOdrlParity(resource) {
|
|
182
|
+
const claims = resource?.meta?.claims;
|
|
183
|
+
if (resource?.resourceType !== ResourceTypesFhirR4.Consent
|
|
184
|
+
|| claims?.[ClaimConsent.attachmentContentType] !== AnimalInsuranceConsentVocabulary.MediaType) {
|
|
185
|
+
throw new TypeError(AnimalInsuranceConsentErrors.InvalidOdrl);
|
|
186
|
+
}
|
|
187
|
+
let policy;
|
|
188
|
+
try {
|
|
189
|
+
policy = JSON.parse(decodeBase64Utf8(claims[ClaimConsent.attachmentData]));
|
|
190
|
+
}
|
|
191
|
+
catch {
|
|
192
|
+
throw new TypeError(AnimalInsuranceConsentErrors.InvalidOdrl);
|
|
193
|
+
}
|
|
194
|
+
const permissions = Array.isArray(policy.permission) ? policy.permission : [];
|
|
195
|
+
const codes = permissions.map((permission) => constraintValue(permission, AnimalInsuranceConsentVocabulary.ClinicalCodeOperand)).filter(Boolean);
|
|
196
|
+
const periodsMatch = permissions.every((permission) => constraintValue(permission, AnimalInsuranceConsentVocabulary.DataPeriodStartOperand) === claims[ClaimConsent.dataPeriodStart]
|
|
197
|
+
&& constraintValue(permission, AnimalInsuranceConsentVocabulary.DataPeriodEndOperand) === claims[ClaimConsent.dataPeriodEnd]);
|
|
198
|
+
const coreMatches = policy['@context'] === AnimalInsuranceConsentVocabulary.OdrlContext
|
|
199
|
+
&& policy['@type'] === AnimalInsuranceConsentVocabulary.Agreement
|
|
200
|
+
&& policy.profile === AnimalInsuranceConsentVocabulary.Profile
|
|
201
|
+
&& policy.uid === claims[ClaimConsent.identifier]
|
|
202
|
+
&& policy.assigner === claims[ClaimConsent.grantor]
|
|
203
|
+
&& policy.assignee === claims[ClaimConsent.grantee]
|
|
204
|
+
&& claims[ClaimConsent.actorIdentifier] === claims[ClaimConsent.grantee]
|
|
205
|
+
&& claims[ClaimConsent.decision] === ConsentDecisions.Permit
|
|
206
|
+
&& permissions.length > 0
|
|
207
|
+
&& permissions.every((permission) => permission.target === AnimalInsuranceConsentVocabulary.EligibilitySummaryTarget
|
|
208
|
+
&& permission.action === AnimalInsuranceConsentVocabulary.Read)
|
|
209
|
+
&& codes.join(',') === claims[ClaimConsent.provisionCode]
|
|
210
|
+
&& periodsMatch;
|
|
211
|
+
if (!coreMatches)
|
|
212
|
+
throw new TypeError(AnimalInsuranceConsentErrors.OdrlClaimsDiverge);
|
|
213
|
+
rejectResearchSemantics({
|
|
214
|
+
purpose: claims[ClaimConsent.purpose],
|
|
215
|
+
resourceType: claims[ClaimConsent.resourceType],
|
|
216
|
+
});
|
|
217
|
+
return policy;
|
|
218
|
+
}
|
|
219
|
+
/** Validates parity, then exports a native FHIR R4 Consent without ODRL-only fields. */
|
|
220
|
+
export function projectAnimalInsuranceConsentToFhirR4(resource) {
|
|
221
|
+
validateAnimalInsuranceConsentOdrlParity(resource);
|
|
222
|
+
return consentFlatToFhirR4(resource.meta.claims);
|
|
223
|
+
}
|
|
224
|
+
/** Validates parity, then exports a native FHIR R5 Consent without ODRL-only fields. */
|
|
225
|
+
export function projectAnimalInsuranceConsentToFhirR5(resource) {
|
|
226
|
+
validateAnimalInsuranceConsentOdrlParity(resource);
|
|
227
|
+
return consentFlatToFhirR5(resource.meta.claims);
|
|
228
|
+
}
|
package/dist/provenance.d.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
/** Browser-safe FHIR R5 Provenance flat-claim vocabulary and builders. */
|
|
2
1
|
export declare const FhirR5ParticipationRoleTypeValueSet: "http://hl7.org/fhir/ValueSet/participation-role-type";
|
|
3
2
|
export declare const FhirR5ProvenanceParticipantTypeSystem: "http://terminology.hl7.org/CodeSystem/provenance-participant-type";
|
|
4
3
|
export declare const FhirR5ExtraSecurityRoleTypeSystem: "http://terminology.hl7.org/CodeSystem/extra-security-role-type";
|
|
@@ -23,6 +22,8 @@ export type ProvenanceR5FlatClaimsResource = Readonly<{
|
|
|
23
22
|
claims: Readonly<Record<string, readonly string[]>>;
|
|
24
23
|
}>;
|
|
25
24
|
}>;
|
|
25
|
+
/** Builds the FHIR PractitionerRole reference from the server-issued assignment UUID. */
|
|
26
|
+
export declare function buildPractitionerRoleReferenceFromAssignmentIdentifier(assignmentIdentifier: string): string;
|
|
26
27
|
/** Returns the correlated agent reference claim for one official participation type. */
|
|
27
28
|
export declare function provenanceAgentClaim(code: FhirR5ParticipationRoleTypeCode | string): string;
|
|
28
29
|
/** Returns the system-qualified FHIR token for one official participation type. */
|
package/dist/provenance.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
/** Browser-safe FHIR R5 Provenance flat-claim vocabulary and builders. */
|
|
2
|
+
import { normalizeUuid } from 'gdc-common-utils-ts/utils/normalize-uuid';
|
|
2
3
|
export const FhirR5ParticipationRoleTypeValueSet = 'http://hl7.org/fhir/ValueSet/participation-role-type';
|
|
3
4
|
export const FhirR5ProvenanceParticipantTypeSystem = 'http://terminology.hl7.org/CodeSystem/provenance-participant-type';
|
|
4
5
|
export const FhirR5ExtraSecurityRoleTypeSystem = 'http://terminology.hl7.org/CodeSystem/extra-security-role-type';
|
|
@@ -30,6 +31,14 @@ const standardClaims = ProvenanceR5SearchParameterCatalog.map(parameter => `Prov
|
|
|
30
31
|
const correlatedAgentClaims = FhirR5ParticipationRoleTypeCodes.map(code => `Provenance.agent-${code}-who`);
|
|
31
32
|
/** Standard search claims plus typed-agent correlation claims. */
|
|
32
33
|
export const ProvenanceFlatClaimCatalog = Object.freeze([...standardClaims, ...correlatedAgentClaims]);
|
|
34
|
+
/** Builds the FHIR PractitionerRole reference from the server-issued assignment UUID. */
|
|
35
|
+
export function buildPractitionerRoleReferenceFromAssignmentIdentifier(assignmentIdentifier) {
|
|
36
|
+
const compact = normalizeUuid(assignmentIdentifier);
|
|
37
|
+
if (!compact)
|
|
38
|
+
throw new TypeError('professional_assignment_identifier_invalid');
|
|
39
|
+
const uuid = `${compact.slice(0, 8)}-${compact.slice(8, 12)}-${compact.slice(12, 16)}-${compact.slice(16, 20)}-${compact.slice(20)}`;
|
|
40
|
+
return `PractitionerRole/${uuid}`;
|
|
41
|
+
}
|
|
33
42
|
/** Returns the correlated agent reference claim for one official participation type. */
|
|
34
43
|
export function provenanceAgentClaim(code) {
|
|
35
44
|
if (!FhirR5ParticipationRoleTypeCodes.includes(code))
|
package/dist/scheduling.d.ts
CHANGED
|
@@ -38,7 +38,7 @@ export declare const SchedulingSearchParameterCatalog: Readonly<{
|
|
|
38
38
|
readonly AppointmentResponse: readonly string[];
|
|
39
39
|
}>;
|
|
40
40
|
/** Indexed scheduling claims: FHIR SearchParameters plus the governed generic user-selected extension. */
|
|
41
|
-
export declare const SchedulingFlatClaimCatalog: Readonly<Record<"
|
|
41
|
+
export declare const SchedulingFlatClaimCatalog: Readonly<Record<"Appointment" | "AppointmentResponse" | "Location" | "Schedule" | "Slot", readonly string[]>>;
|
|
42
42
|
export type SchedulingResourceType = keyof typeof SchedulingFlatClaimCatalog;
|
|
43
43
|
export type SchedulingFlatClaimsResource = Readonly<Record<string, unknown> & {
|
|
44
44
|
resourceType: SchedulingResourceType;
|
|
@@ -163,7 +163,7 @@ export declare function buildAppointmentNotificationResource(input: Readonly<{
|
|
|
163
163
|
/** @deprecated Use {@link SlotSearchParameters}. */
|
|
164
164
|
export declare const VeterinarySlotSearchParameters: readonly ["appointment-type", "identifier", "schedule", "service-category", "service-type", "service-type-reference", "specialty", "start", "status"];
|
|
165
165
|
/** @deprecated Use {@link SchedulingFlatClaimCatalog}. */
|
|
166
|
-
export declare const VeterinarySchedulingFlatClaimCatalog: Readonly<Record<"
|
|
166
|
+
export declare const VeterinarySchedulingFlatClaimCatalog: Readonly<Record<"Appointment" | "AppointmentResponse" | "Location" | "Schedule" | "Slot", readonly string[]>>;
|
|
167
167
|
/** @deprecated Use {@link SchedulingResourceType}. */
|
|
168
168
|
export type VeterinarySchedulingResourceType = SchedulingResourceType;
|
|
169
169
|
/** @deprecated Use {@link SchedulingFlatClaimsResource}. */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vet-data-utils-ts",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.29",
|
|
4
4
|
"description": "Browser-safe governed VetChain data contracts",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "Connecting Solution & Applications Ltd",
|
|
@@ -60,6 +60,10 @@
|
|
|
60
60
|
"types": "./dist/index-projection-tags.d.ts",
|
|
61
61
|
"default": "./dist/index-projection-tags.js"
|
|
62
62
|
},
|
|
63
|
+
"./insurance-consent": {
|
|
64
|
+
"types": "./dist/insurance-consent.d.ts",
|
|
65
|
+
"default": "./dist/insurance-consent.js"
|
|
66
|
+
},
|
|
63
67
|
"./iso-jurisdictions": {
|
|
64
68
|
"types": "./dist/iso-jurisdictions.d.ts",
|
|
65
69
|
"default": "./dist/iso-jurisdictions.js"
|
|
@@ -125,7 +129,7 @@
|
|
|
125
129
|
"typescript": "^5.5.4"
|
|
126
130
|
},
|
|
127
131
|
"dependencies": {
|
|
128
|
-
"gdc-common-utils-ts": "2.9.
|
|
132
|
+
"gdc-common-utils-ts": "2.9.12",
|
|
129
133
|
"pako": "^2.2.0"
|
|
130
134
|
},
|
|
131
135
|
"engines": {
|