gdc-common-utils-ts 2.9.26 → 2.9.28

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.
@@ -31,6 +31,21 @@ export declare const HL7_V2_0203_IDENTIFIER_CODES: Readonly<{
31
31
  readonly DonorRecord: "DR";
32
32
  readonly PatientIdentifier: "PI";
33
33
  }>;
34
+ /**
35
+ * HL7 v2-0203 organization identifier codes used by governed legal identities.
36
+ *
37
+ * `BN` is a governed extension for jurisdictions whose official legal identifier
38
+ * is a business number. It is intentionally kept separate from the HL7 codes.
39
+ */
40
+ export declare const HL7_V2_0203_ORGANIZATION_IDENTIFIER_CODES: Readonly<{
41
+ readonly TaxIdentifier: "TAX";
42
+ readonly EmployerNumber: "EN";
43
+ }>;
44
+ export declare const GovernedOrganizationIdentifierCodes: Readonly<{
45
+ readonly BusinessNumber: "BN";
46
+ readonly TaxIdentifier: "TAX";
47
+ readonly EmployerNumber: "EN";
48
+ }>;
34
49
  export type Hl7V20203IdentifierCode = typeof HL7_V2_0203_IDENTIFIER_CODES[keyof typeof HL7_V2_0203_IDENTIFIER_CODES];
35
50
  /**
36
51
  * Private identifier types accepted when deriving an opaque hosted-individual
@@ -31,6 +31,20 @@ export const HL7_V2_0203_IDENTIFIER_CODES = Object.freeze({
31
31
  DonorRecord: 'DR',
32
32
  PatientIdentifier: 'PI',
33
33
  });
34
+ /**
35
+ * HL7 v2-0203 organization identifier codes used by governed legal identities.
36
+ *
37
+ * `BN` is a governed extension for jurisdictions whose official legal identifier
38
+ * is a business number. It is intentionally kept separate from the HL7 codes.
39
+ */
40
+ export const HL7_V2_0203_ORGANIZATION_IDENTIFIER_CODES = Object.freeze({
41
+ TaxIdentifier: 'TAX',
42
+ EmployerNumber: 'EN',
43
+ });
44
+ export const GovernedOrganizationIdentifierCodes = Object.freeze({
45
+ ...HL7_V2_0203_ORGANIZATION_IDENTIFIER_CODES,
46
+ BusinessNumber: 'BN',
47
+ });
34
48
  /**
35
49
  * Private identifier types accepted when deriving an opaque hosted-individual
36
50
  * multihash. These values govern normalization only and are never serialized
@@ -1,15 +1,14 @@
1
1
  // Copyright 2026 Antifraud Services Inc. under the Apache License, Version 2.0.
2
2
  import { ServiceCapability } from '../constants/service-capabilities.js';
3
- import { HealthcareConsentPurposes, ISCO08_CODING_SYSTEM } from '../constants/healthcare.js';
4
- import { SecureIdTypesIndividual } from '../constants/identity-identifiers.js';
3
+ import { HealthcareActorRoleCodes, HealthcareConsentPurposes } from '../constants/healthcare.js';
5
4
  import { DataspaceSectors } from '../constants/sectors.js';
6
5
  import { ClaimConsent } from '../models/consent-rule.js';
7
6
  import { ClaimInterTenantAccessContract } from '../models/inter-tenant-access-contract.js';
8
7
  import { BundleEntryClaimsContext } from '../models/communication-attached-bundle-session.js';
9
8
  import { buildInterTenantAccessContractCredential, buildInterTenantAccessContractResource, getInterTenantAccessContractBlockchainReference, } from '../utils/inter-tenant-access-contract.js';
10
- import { buildOrganizationAuthorizationUrnCds, buildOrganizationMemberAuthorizationUrnCds, } from '../utils/organization-authorization-urn.js';
11
- import { buildProfessionalDidWeb, buildSecureIdValueMember } from '../utils/did.js';
12
- import { EXAMPLE_API_ORGANIZATION_DID, EXAMPLE_CONTROLLER_DID, EXAMPLE_HEALTHCARE_ACTOR_ROLE_PHYSICIAN, EXAMPLE_JURISDICTION, EXAMPLE_RESEARCH_API_ORGANIZATION_DID, EXAMPLE_RESEARCH_TENANT_IDENTIFIER, EXAMPLE_SECTOR, EXAMPLE_TENANT_IDENTIFIER, } from './shared.js';
9
+ import { buildOrganizationAuthorizationUrnCds, buildOrganizationEmployeeAuthorizationUrnCds, } from '../utils/organization-authorization-urn.js';
10
+ import { buildProfessionalDidWeb } from '../utils/did.js';
11
+ import { EXAMPLE_API_ORGANIZATION_DID, EXAMPLE_CONTROLLER_DID, EXAMPLE_HEALTHCARE_ACTOR_ROLE_PHYSICIAN, EXAMPLE_JURISDICTION, EXAMPLE_KYC_CONTROLLER_USER_UUID, EXAMPLE_RESEARCH_API_ORGANIZATION_DID, EXAMPLE_RESEARCH_TENANT_IDENTIFIER, EXAMPLE_SECTOR, EXAMPLE_TENANT_IDENTIFIER, } from './shared.js';
13
12
  /**
14
13
  * Shared synthetic inter-tenant contract fixtures reused by GW and SDK tests.
15
14
  *
@@ -112,14 +111,10 @@ export const EXAMPLE_INTER_TENANT_ACCESS_CONTRACT_CONSUMER_ORGANIZATION_URN = bu
112
111
  identifierType: 'TAX',
113
112
  identifierValue: EXAMPLE_RESEARCH_TENANT_IDENTIFIER,
114
113
  });
115
- export const EXAMPLE_INTER_TENANT_ACCESS_CONTRACT_CONSUMER_MEMBER_URN = buildOrganizationMemberAuthorizationUrnCds({
114
+ export const EXAMPLE_INTER_TENANT_ACCESS_CONTRACT_CONSUMER_MEMBER_URN = buildOrganizationEmployeeAuthorizationUrnCds({
116
115
  organizationUrn: EXAMPLE_INTER_TENANT_ACCESS_CONTRACT_CONSUMER_ORGANIZATION_URN,
117
- memberId: buildSecureIdValueMember({
118
- secureIdTypeMember: SecureIdTypesIndividual.Email,
119
- privateIdValueMember: EXAMPLE_INTER_TENANT_ACCESS_CONTRACT_CONSUMER_PROFESSIONAL_EMAIL,
120
- }),
121
- roleType: ISCO08_CODING_SYSTEM,
122
- roleValue: EXAMPLE_HEALTHCARE_ACTOR_ROLE_PHYSICIAN,
116
+ employeeUuid: EXAMPLE_KYC_CONTROLLER_USER_UUID,
117
+ roleCode: HealthcareActorRoleCodes.GeneralistMedicalPractitioner,
123
118
  });
124
119
  export const EXAMPLE_INTER_TENANT_ACCESS_CONTRACT_CONTEXT_WITH_URNS = Object.freeze({
125
120
  ...EXAMPLE_INTER_TENANT_ACCESS_CONTRACT_CONTEXT,
@@ -8,13 +8,13 @@ import { ResourceTypesFhirR4 } from '../constants/fhir-resource-types.js';
8
8
  import { BirthSex, GenderIdentity } from '../constants/identity-gender.js';
9
9
  import { IdKind, SecureIdTypesIndividual } from '../constants/identity-identifiers.js';
10
10
  import { HL7_CODING_SYSTEM_V3_ROLE_CODE } from '../constants/hl7-roles.js';
11
- import { HealthcareActorRoles, HealthcareBasicSections, HealthcareConsentPurposes, HealthcareDocumentTypes, ISCO08_CODING_SYSTEM, } from '../constants/healthcare.js';
11
+ import { HealthcareActorRoleCodes, HealthcareActorRoles, HealthcareBasicSections, HealthcareConsentPurposes, HealthcareDocumentTypes, } from '../constants/healthcare.js';
12
12
  import { CommunicationCategoryCodes } from '../constants/communication.js';
13
13
  import { LOINC_SYSTEM_URL } from '../models/clinical-sections.js';
14
14
  import { CommunicationClaim } from '../models/interoperable-claims/communication-claims.js';
15
15
  import { buildHostedProviderDidWeb, buildIndividualDidWeb, buildIndividualMemberDidWeb, buildSecureIdValueIndividual, buildSecureIdValueMember, buildProfessionalDidWeb, buildProviderSectorDidWeb, } from '../utils/did.js';
16
16
  import { encodeHexToMultibase58btc } from '../utils/multibase58.js';
17
- import { buildOrganizationAuthorizationUrnCds, buildOrganizationMemberAuthorizationUrnCds, } from '../utils/organization-authorization-urn.js';
17
+ import { buildOrganizationAuthorizationUrnCds, buildOrganizationEmployeeAuthorizationUrnCds, } from '../utils/organization-authorization-urn.js';
18
18
  import { MedicationStatementClaim, MedicationStatementClaimsFhirApiExtended, } from '../models/interoperable-claims/medication-statement-claims.js';
19
19
  import { medicationStatementFlatToFhirR4 } from '../utils/clinical-resource-converters.js';
20
20
  /**
@@ -265,14 +265,10 @@ export const EXAMPLE_HEALTHCARE_ACTOR_ROLE_RECEPTIONIST = 'ISCO-08|4226';
265
265
  export const EXAMPLE_HEALTHCARE_ROLE_PHYSICIAN_TEXT = 'physician';
266
266
  export const EXAMPLE_INDIVIDUAL_CONTROLLER_ROLE_TYPE = HL7_CODING_SYSTEM_V3_ROLE_CODE;
267
267
  export const EXAMPLE_INDIVIDUAL_CONTROLLER_ROLE_VALUE = EXAMPLE_ORGANIZATION_CONTROLLER_ROLE;
268
- export const EXAMPLE_PROFESSIONAL_AUTHORIZATION_URN_CDS = buildOrganizationMemberAuthorizationUrnCds({
268
+ export const EXAMPLE_PROFESSIONAL_AUTHORIZATION_URN_CDS = buildOrganizationEmployeeAuthorizationUrnCds({
269
269
  organizationUrn: EXAMPLE_PROVIDER_ORGANIZATION_AUTHORIZATION_URN_CDS,
270
- memberId: buildSecureIdValueMember({
271
- secureIdTypeMember: SecureIdTypesIndividual.Email,
272
- privateIdValueMember: EXAMPLE_EMAIL_PROFESSIONAL,
273
- }),
274
- roleType: ISCO08_CODING_SYSTEM,
275
- roleValue: HealthcareActorRoles.GeneralistMedicalPractitioner,
270
+ employeeUuid: EXAMPLE_KYC_CONTROLLER_USER_UUID,
271
+ roleCode: HealthcareActorRoleCodes.GeneralistMedicalPractitioner,
276
272
  });
277
273
  export const EXAMPLE_RELATED_PERSON_ROLE = 'v3-RoleCode|RESPRSN';
278
274
  export const EXAMPLE_SECURE_ID_VALUE_INDIVIDUAL = buildSecureIdValueIndividual({
@@ -576,8 +576,19 @@ function resolveDate(resourceType, claims, resource) {
576
576
  AllergyIntoleranceClaimsFhirApi.OnsetDateTime,
577
577
  ]) || resolveFhirDate(resourceType, resource);
578
578
  }
579
+ const resourceDate = readCanonicalClaimValue(claims, `${resourceType}.date`);
580
+ if (resourceDate)
581
+ return resourceDate;
582
+ if (resourceType === ResourceTypesFhirR4.Observation) {
583
+ const effectiveDateTime = readCanonicalClaimValue(claims, ObservationClaim.EffectiveDateTime);
584
+ if (effectiveDateTime)
585
+ return effectiveDateTime;
586
+ }
587
+ const nativeDate = resolveFhirDate(resourceType, resource);
588
+ if (nativeDate)
589
+ return nativeDate;
579
590
  const genericDate = findBySuffix(claims, '.date');
580
- return genericDate || resolveFhirDate(resourceType, resource) || undefined;
591
+ return genericDate || undefined;
581
592
  }
582
593
  function resolvePeriodStart(resourceType, claims, resource) {
583
594
  if (resourceType === ResourceTypesFhirR4.Consent) {
@@ -8,7 +8,7 @@ export type OrganizationAuthorizationUrnCdsInput = Readonly<{
8
8
  jurisdiction: string;
9
9
  /** Version of the stable CDS identifier grammar. Defaults to v1. */
10
10
  version?: string;
11
- /** Governed legal identifier type such as TAX, EIN or BN. */
11
+ /** Governed legal identifier type such as TAX, EN or BN. */
12
12
  identifierType: string;
13
13
  /** Canonical value issued by that jurisdiction's identifier authority. */
14
14
  identifierValue: string;
@@ -22,6 +22,14 @@ export type OrganizationMemberAuthorizationUrnCdsInput = Readonly<{
22
22
  /** Coded role value serialized as the final compact path segment. */
23
23
  roleValue: string;
24
24
  }>;
25
+ export type OrganizationEmployeeAuthorizationUrnCdsInput = Readonly<{
26
+ /** Existing canonical organization URN. Its official identifier is preserved byte-for-byte. */
27
+ organizationUrn: string;
28
+ /** Employee UUID, either bare or prefixed with `urn:uuid:`. */
29
+ employeeUuid: string;
30
+ /** Bare ISCO-08 code. The fixed coding system is implicit in this grammar. */
31
+ roleCode: string;
32
+ }>;
25
33
  export type MemberAuthorizationUrnInput = Readonly<{
26
34
  organizationUrn?: string;
27
35
  identifierType?: string;
@@ -52,7 +60,7 @@ export declare function buildOrganizationAuthorizationUrn(input: OrganizationAut
52
60
  * Format:
53
61
  * `urn:cds-<jurisdiction>:<version>:organization:<identifier-type>:<identifier-value>`
54
62
  *
55
- * Jurisdiction is mandatory because identifier schemes such as BN, EIN and
63
+ * Jurisdiction is mandatory because identifier schemes such as BN, EN and
56
64
  * TAX are interpreted by different national/subnational authorities.
57
65
  */
58
66
  export declare function buildOrganizationAuthorizationUrnCds(input: OrganizationAuthorizationUrnCdsInput): string;
@@ -62,6 +70,17 @@ export declare function buildOrganizationAuthorizationUrnCds(input: Organization
62
70
  * the compact role convention used by member did:web paths.
63
71
  */
64
72
  export declare function buildOrganizationMemberAuthorizationUrnCds(input: OrganizationMemberAuthorizationUrnCdsInput): string;
73
+ /**
74
+ * Appends an employee identity and role to an existing legal-organization URN.
75
+ *
76
+ * Format:
77
+ * `urn:cds-<jurisdiction>:v1:organization:<type>:<official-id>:member:<uuid-base58btc>:<isco-08-code>`
78
+ *
79
+ * The UUID is encoded from its 16 raw bytes. It is neither hashed nor encoded
80
+ * from its textual representation. The organization URN is never rebuilt or
81
+ * lowercased, so the authority-issued legal identifier remains unchanged.
82
+ */
83
+ export declare function buildOrganizationEmployeeAuthorizationUrnCds(input: OrganizationEmployeeAuthorizationUrnCdsInput): string;
65
84
  /**
66
85
  * Accepts either the legacy `TYPE|VALUE` input or an already-canonical
67
86
  * `urn:org:...` identifier and always returns the canonical URN form.
@@ -1,5 +1,6 @@
1
1
  // Copyright 2026 Antifraud Services Inc. under the Apache License, Version 2.0.
2
2
  import { ClaimsOrganizationSchemaorg } from '../constants/schemaorg.js';
3
+ import { encodeHexToMultibase58btc } from './multibase58.js';
3
4
  const ORGANIZATION_URN_PREFIX = 'urn:org:';
4
5
  const CDS_ORGANIZATION_URN_PATTERN = /^urn:cds-([a-z]{2}(?:-[a-z0-9]{2,3})?):(v[1-9][0-9]*):organization:([a-z][a-z0-9-]*):([^:]+)$/;
5
6
  const BARE_MULTIBASE_PATTERN = /^z[1-9A-HJ-NP-Za-km-z]+$/;
@@ -38,7 +39,7 @@ export function buildOrganizationAuthorizationUrn(input) {
38
39
  * Format:
39
40
  * `urn:cds-<jurisdiction>:<version>:organization:<identifier-type>:<identifier-value>`
40
41
  *
41
- * Jurisdiction is mandatory because identifier schemes such as BN, EIN and
42
+ * Jurisdiction is mandatory because identifier schemes such as BN, EN and
42
43
  * TAX are interpreted by different national/subnational authorities.
43
44
  */
44
45
  export function buildOrganizationAuthorizationUrnCds(input) {
@@ -78,6 +79,36 @@ export function buildOrganizationMemberAuthorizationUrnCds(input) {
78
79
  }
79
80
  return `${organizationUrn}:member:${memberId}:${roleValue}`;
80
81
  }
82
+ /**
83
+ * Appends an employee identity and role to an existing legal-organization URN.
84
+ *
85
+ * Format:
86
+ * `urn:cds-<jurisdiction>:v1:organization:<type>:<official-id>:member:<uuid-base58btc>:<isco-08-code>`
87
+ *
88
+ * The UUID is encoded from its 16 raw bytes. It is neither hashed nor encoded
89
+ * from its textual representation. The organization URN is never rebuilt or
90
+ * lowercased, so the authority-issued legal identifier remains unchanged.
91
+ */
92
+ export function buildOrganizationEmployeeAuthorizationUrnCds(input) {
93
+ const organizationUrn = String(input.organizationUrn || '').trim();
94
+ const employeeUuid = String(input.employeeUuid || '').trim().replace(/^urn:uuid:/i, '');
95
+ const roleCode = String(input.roleCode || '').trim();
96
+ if (!CDS_ORGANIZATION_URN_PATTERN.test(organizationUrn)) {
97
+ throw new Error('CDS employee authorization URN requires a canonical CDS organization URN.');
98
+ }
99
+ if (!/^[0-9a-f]{8}-?[0-9a-f]{4}-?[0-9a-f]{4}-?[0-9a-f]{4}-?[0-9a-f]{12}$/i.test(employeeUuid)) {
100
+ throw new Error('CDS employee authorization URN requires an employee UUID.');
101
+ }
102
+ if (!/^[0-9]+$/.test(roleCode)) {
103
+ throw new Error('CDS employee authorization URN requires a bare ISCO-08 role code.');
104
+ }
105
+ return buildOrganizationMemberAuthorizationUrnCds({
106
+ organizationUrn,
107
+ memberId: encodeHexToMultibase58btc(employeeUuid),
108
+ roleType: 'ISCO-08',
109
+ roleValue: roleCode,
110
+ });
111
+ }
81
112
  /**
82
113
  * Accepts either the legacy `TYPE|VALUE` input or an already-canonical
83
114
  * `urn:org:...` identifier and always returns the canonical URN form.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gdc-common-utils-ts",
3
- "version": "2.9.26",
3
+ "version": "2.9.28",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },