gdc-common-utils-ts 2.9.7 → 2.9.9
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
CHANGED
|
@@ -553,6 +553,9 @@ The canonical API contract should live in JSDoc on exported code. The README act
|
|
|
553
553
|
signing key separate. The organization, EHR/portal or individual remains
|
|
554
554
|
the document author; a registered PractitionerRole or RelatedPerson is the
|
|
555
555
|
attester, including for content entered by that authenticated person.
|
|
556
|
+
- [`normalizeClinicalCreatorBinding(...)`](src/utils/fhir-ips-creator-identity.ts)
|
|
557
|
+
- Accept stable UUIDs and governed bare role codes at the BFF boundary, then
|
|
558
|
+
add canonical UUID URNs and HL7/ISCO coding systems before transport.
|
|
556
559
|
- [`src/examples/frontend-session.ts`](src/examples/frontend-session.ts)
|
|
557
560
|
- Frontend profile/session bootstrap examples.
|
|
558
561
|
- [`src/examples/lifecycle.ts`](src/examples/lifecycle.ts)
|
|
@@ -695,9 +695,10 @@ export function getHealthcareRoleByClaim(claim) {
|
|
|
695
695
|
if (direct)
|
|
696
696
|
return direct;
|
|
697
697
|
const fullHl7Prefix = `${HL7_CODING_SYSTEM_V3_ROLE_CODE}|`;
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
698
|
+
if (normalized.startsWith(fullHl7Prefix)) {
|
|
699
|
+
return HealthcareAllRolesByClaim[`v3-RoleCode|${normalized.slice(fullHl7Prefix.length)}`];
|
|
700
|
+
}
|
|
701
|
+
return Object.values(HealthcareAllRolesByClaim).find((descriptor) => normalized === `${descriptor.codingSystem}|${descriptor.code}`);
|
|
701
702
|
}
|
|
702
703
|
export function getHealthcareProfessionalRolesBySector(sector) {
|
|
703
704
|
return HealthcareProfessionalRolesBySector[sector] || {};
|
|
@@ -106,6 +106,30 @@ export type ClinicalCreatorBinding = ClinicalCreatorChannelAliases & Readonly<{
|
|
|
106
106
|
/** Canonical governed ISCO/HL7 role claim; ONESELF is the subject relationship. */
|
|
107
107
|
role: string;
|
|
108
108
|
}>;
|
|
109
|
+
/**
|
|
110
|
+
* High-level creator input accepted from SDK/BFF code.
|
|
111
|
+
*
|
|
112
|
+
* Stable person, assignment and individual-owner identifiers may be either a
|
|
113
|
+
* UUID or an already canonical `urn:uuid`. The role may be a governed bare
|
|
114
|
+
* code or its governed coding-system claim. Callers never concatenate wire
|
|
115
|
+
* prefixes themselves.
|
|
116
|
+
*/
|
|
117
|
+
export type ClinicalCreatorBindingInput = ClinicalCreatorChannelAliases & Readonly<{
|
|
118
|
+
kind: FhirIpsCreatorKind;
|
|
119
|
+
actorIdentifier: string;
|
|
120
|
+
authorIdentifier: string;
|
|
121
|
+
ownerIdentifier: string;
|
|
122
|
+
role: string;
|
|
123
|
+
}>;
|
|
124
|
+
/**
|
|
125
|
+
* Normalizes high-level creator identity before persistence or transport.
|
|
126
|
+
*
|
|
127
|
+
* Personal owners are canonical UUID URNs. Professional owners remain their
|
|
128
|
+
* legal Organization DID/URN. Bare personal and professional role codes are
|
|
129
|
+
* resolved through the governed HL7/ISCO catalog and emitted with their
|
|
130
|
+
* canonical coding system.
|
|
131
|
+
*/
|
|
132
|
+
export declare function normalizeClinicalCreatorBinding(input: ClinicalCreatorBindingInput): ClinicalCreatorBinding;
|
|
109
133
|
export type AuthenticatedClinicalCreatorEvidence = Readonly<{
|
|
110
134
|
actorDid?: string;
|
|
111
135
|
verifiedContactIdentifiers?: readonly string[];
|
|
@@ -3,6 +3,7 @@ import { getHealthcareRoleByClaim } from '../constants/healthcare.js';
|
|
|
3
3
|
import { isStableActorIdentifier } from './actor-identifier.js';
|
|
4
4
|
import { normalizeUuid } from './normalize-uuid.js';
|
|
5
5
|
import { HL7_RELATED_PERSON_FUNCTIONAL_ROLES } from '../constants/hl7-roles.js';
|
|
6
|
+
import { UrnPrefixes } from '../constants/urn.js';
|
|
6
7
|
import { CompositionAttesterModes, } from '../models/interoperable-claims/composition-claims.js';
|
|
7
8
|
export const FhirIpsCreatorKinds = Object.freeze({
|
|
8
9
|
IndividualSubject: 'individual-subject',
|
|
@@ -118,6 +119,29 @@ export function buildFhirIpsCreatorAuthor(input) {
|
|
|
118
119
|
],
|
|
119
120
|
};
|
|
120
121
|
}
|
|
122
|
+
/**
|
|
123
|
+
* Normalizes high-level creator identity before persistence or transport.
|
|
124
|
+
*
|
|
125
|
+
* Personal owners are canonical UUID URNs. Professional owners remain their
|
|
126
|
+
* legal Organization DID/URN. Bare personal and professional role codes are
|
|
127
|
+
* resolved through the governed HL7/ISCO catalog and emitted with their
|
|
128
|
+
* canonical coding system.
|
|
129
|
+
*/
|
|
130
|
+
export function normalizeClinicalCreatorBinding(input) {
|
|
131
|
+
const actorIdentifier = canonicalUuidUrn(input.actorIdentifier, 'actorIdentifier');
|
|
132
|
+
const authorIdentifier = canonicalUuidUrn(input.authorIdentifier, 'authorIdentifier');
|
|
133
|
+
const ownerIdentifier = input.kind === FhirIpsCreatorKinds.Professional
|
|
134
|
+
? requireReference(input.ownerIdentifier, 'ownerIdentifier')
|
|
135
|
+
: canonicalUuidUrn(input.ownerIdentifier, 'ownerIdentifier');
|
|
136
|
+
const role = canonicalRoleClaim(input.role);
|
|
137
|
+
return {
|
|
138
|
+
...input,
|
|
139
|
+
actorIdentifier,
|
|
140
|
+
authorIdentifier,
|
|
141
|
+
ownerIdentifier,
|
|
142
|
+
role,
|
|
143
|
+
};
|
|
144
|
+
}
|
|
121
145
|
/** Builds the stable actor-and-role pair consumed by Consent permission rules. */
|
|
122
146
|
export function buildClinicalCreatorPermissionActor(binding) {
|
|
123
147
|
requireUuidUrn(binding.actorIdentifier, 'binding.actorIdentifier');
|
|
@@ -160,6 +184,27 @@ function requireUuidUrn(value, label) {
|
|
|
160
184
|
}
|
|
161
185
|
return normalized;
|
|
162
186
|
}
|
|
187
|
+
function canonicalUuidUrn(value, label) {
|
|
188
|
+
const normalized = String(value || '').trim().toLowerCase();
|
|
189
|
+
const uuidValueInput = normalized.startsWith(UrnPrefixes.Uuid)
|
|
190
|
+
? normalized.slice(UrnPrefixes.Uuid.length)
|
|
191
|
+
: normalized;
|
|
192
|
+
if (!/^(?:[0-9a-f]{32}|[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})$/.test(uuidValueInput)) {
|
|
193
|
+
throw new TypeError(`${label} must be a UUID or urn:uuid identifier.`);
|
|
194
|
+
}
|
|
195
|
+
const hexadecimal = normalizeUuid(uuidValueInput);
|
|
196
|
+
if (!hexadecimal) {
|
|
197
|
+
throw new TypeError(`${label} must be a UUID or urn:uuid identifier.`);
|
|
198
|
+
}
|
|
199
|
+
const uuid = [
|
|
200
|
+
hexadecimal.slice(0, 8),
|
|
201
|
+
hexadecimal.slice(8, 12),
|
|
202
|
+
hexadecimal.slice(12, 16),
|
|
203
|
+
hexadecimal.slice(16, 20),
|
|
204
|
+
hexadecimal.slice(20),
|
|
205
|
+
].join('-');
|
|
206
|
+
return `${UrnPrefixes.Uuid}${uuid}`;
|
|
207
|
+
}
|
|
163
208
|
function uuidValue(identifier) {
|
|
164
209
|
return identifier.slice('urn:uuid:'.length);
|
|
165
210
|
}
|
|
@@ -189,3 +234,7 @@ function requireRoleCoding(roleClaim) {
|
|
|
189
234
|
display: functionalRole.display,
|
|
190
235
|
};
|
|
191
236
|
}
|
|
237
|
+
function canonicalRoleClaim(roleClaim) {
|
|
238
|
+
const descriptor = requireRoleCoding(roleClaim);
|
|
239
|
+
return `${descriptor.system}|${descriptor.code}`;
|
|
240
|
+
}
|