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
- return normalized.startsWith(fullHl7Prefix)
699
- ? HealthcareAllRolesByClaim[`v3-RoleCode|${normalized.slice(fullHl7Prefix.length)}`]
700
- : undefined;
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
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gdc-common-utils-ts",
3
- "version": "2.9.7",
3
+ "version": "2.9.9",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },