gdc-common-utils-ts 2.1.0 → 2.3.0

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.
Files changed (175) hide show
  1. package/README.md +22 -2
  2. package/dist/claims/claims-helpers-allergy-intolerance.d.ts +8 -0
  3. package/dist/claims/claims-helpers-allergy-intolerance.js +30 -12
  4. package/dist/claims/claims-helpers-condition.d.ts +8 -0
  5. package/dist/claims/claims-helpers-condition.js +30 -12
  6. package/dist/claims/claims-helpers-consent.d.ts +4 -0
  7. package/dist/claims/claims-helpers-consent.js +15 -1
  8. package/dist/claims/claims-helpers-diagnostic-report.d.ts +4 -0
  9. package/dist/claims/claims-helpers-diagnostic-report.js +17 -2
  10. package/dist/claims/claims-helpers-medication-statement.d.ts +10 -2
  11. package/dist/claims/claims-helpers-medication-statement.js +32 -14
  12. package/dist/constants/data-collections.js +0 -1
  13. package/dist/constants/didcomm.d.ts +22 -0
  14. package/dist/constants/didcomm.js +22 -0
  15. package/dist/constants/fhir-resource-types.d.ts +16 -0
  16. package/dist/constants/fhir-resource-types.js +7 -0
  17. package/dist/constants/healthcare.d.ts +348 -193
  18. package/dist/constants/healthcare.js +99 -37
  19. package/dist/constants/hl7-roles.d.ts +38 -4
  20. package/dist/constants/hl7-roles.js +92 -4
  21. package/dist/constants/index.d.ts +1 -0
  22. package/dist/constants/index.js +1 -0
  23. package/dist/constants/lifecycle.d.ts +2 -0
  24. package/dist/constants/lifecycle.js +2 -0
  25. package/dist/constants/verifiable-credentials.d.ts +9 -0
  26. package/dist/constants/verifiable-credentials.js +9 -0
  27. package/dist/examples/bundle-didcomm-payload.js +4 -2
  28. package/dist/examples/communication-attached-bundle-session.js +27 -27
  29. package/dist/examples/communication-didcomm-payload.d.ts +8 -4
  30. package/dist/examples/communication-didcomm-payload.js +17 -11
  31. package/dist/examples/consent-access.js +2 -1
  32. package/dist/examples/employee.d.ts +21 -0
  33. package/dist/examples/employee.js +21 -0
  34. package/dist/examples/individual-controller.d.ts +27 -0
  35. package/dist/examples/individual-controller.js +28 -1
  36. package/dist/examples/inter-tenant-access-contract.js +3 -2
  37. package/dist/examples/ips-bundle.js +17 -16
  38. package/dist/examples/lifecycle.js +13 -11
  39. package/dist/examples/profile-manager-mem.js +2 -1
  40. package/dist/examples/related-person.d.ts +14 -0
  41. package/dist/examples/related-person.js +18 -4
  42. package/dist/examples/shared.d.ts +12 -3
  43. package/dist/examples/shared.js +13 -4
  44. package/dist/examples/vital-signs.js +1 -1
  45. package/dist/examples/wallet-mem.js +4 -2
  46. package/dist/i18n/role-codes.i18n.d.ts +9 -1
  47. package/dist/i18n/role-codes.i18n.js +12 -1
  48. package/dist/models/authority-resolution.d.ts +56 -0
  49. package/dist/models/authority-resolution.js +2 -0
  50. package/dist/models/bundle-editor-types.d.ts +89 -0
  51. package/dist/models/bundle-editor-types.js +45 -0
  52. package/dist/models/bundle.d.ts +5 -0
  53. package/dist/models/communication-attached-bundle-session.d.ts +6 -4
  54. package/dist/models/communication-attached-bundle-session.js +6 -4
  55. package/dist/models/confidential-storage.d.ts +2 -1
  56. package/dist/models/consent-rule.d.ts +11 -1
  57. package/dist/models/consent-rule.js +9 -1
  58. package/dist/models/device-license.d.ts +20 -0
  59. package/dist/models/index.d.ts +2 -0
  60. package/dist/models/index.js +2 -0
  61. package/dist/models/individual-onboarding.d.ts +18 -0
  62. package/dist/models/interoperable-claims/allergy-intolerance-claims.d.ts +12 -1
  63. package/dist/models/interoperable-claims/allergy-intolerance-claims.js +12 -1
  64. package/dist/models/interoperable-claims/condition-claims.d.ts +12 -1
  65. package/dist/models/interoperable-claims/condition-claims.js +12 -1
  66. package/dist/models/interoperable-claims/diagnostic-report-claims.d.ts +13 -2
  67. package/dist/models/interoperable-claims/diagnostic-report-claims.js +12 -1
  68. package/dist/models/interoperable-claims/document-reference-claims.d.ts +1 -0
  69. package/dist/models/interoperable-claims/document-reference-claims.js +3 -0
  70. package/dist/models/interoperable-claims/medication-statement-claims.d.ts +17 -0
  71. package/dist/models/interoperable-claims/medication-statement-claims.js +17 -0
  72. package/dist/models/interoperable-claims/related-person-claims.d.ts +13 -0
  73. package/dist/models/interoperable-claims/related-person-claims.js +16 -0
  74. package/dist/utils/allergy-intolerance-entry-editor.d.ts +51 -0
  75. package/dist/utils/allergy-intolerance-entry-editor.js +55 -0
  76. package/dist/utils/authority-resolution.d.ts +37 -0
  77. package/dist/utils/authority-resolution.js +112 -0
  78. package/dist/utils/backend-message-manager-mem.d.ts +11 -0
  79. package/dist/utils/backend-message-manager-mem.js +11 -0
  80. package/dist/utils/bundle-didcomm-payload.js +3 -2
  81. package/dist/utils/bundle-document-builder.d.ts +36 -0
  82. package/dist/utils/bundle-document-builder.js +310 -14
  83. package/dist/utils/bundle-editor-core.d.ts +181 -0
  84. package/dist/utils/bundle-editor-core.js +467 -0
  85. package/dist/utils/bundle-editor-helpers.d.ts +53 -0
  86. package/dist/utils/bundle-editor-helpers.js +146 -0
  87. package/dist/utils/bundle-editor-registry.d.ts +6 -0
  88. package/dist/utils/bundle-editor-registry.js +14 -0
  89. package/dist/utils/bundle-editor.d.ts +21 -722
  90. package/dist/utils/bundle-editor.js +21 -1601
  91. package/dist/utils/bundle-entry-editor.d.ts +96 -0
  92. package/dist/utils/bundle-entry-editor.js +305 -0
  93. package/dist/utils/bundle-query.d.ts +1 -0
  94. package/dist/utils/bundle-query.js +12 -3
  95. package/dist/utils/bundle-reader.d.ts +48 -0
  96. package/dist/utils/bundle-reader.js +175 -1
  97. package/dist/utils/care-plan-entry-editor.d.ts +43 -0
  98. package/dist/utils/care-plan-entry-editor.js +47 -0
  99. package/dist/utils/client-assertion.d.ts +38 -0
  100. package/dist/utils/client-assertion.js +113 -0
  101. package/dist/utils/clinical-impression-entry-editor.d.ts +43 -0
  102. package/dist/utils/clinical-impression-entry-editor.js +47 -0
  103. package/dist/utils/clinical-resource-entry-editor.d.ts +123 -0
  104. package/dist/utils/clinical-resource-entry-editor.js +296 -0
  105. package/dist/utils/clinical-resource-view.d.ts +16 -0
  106. package/dist/utils/clinical-resource-view.js +267 -33
  107. package/dist/utils/communication-attached-bundle-session-helpers.js +8 -6
  108. package/dist/utils/communication-attached-bundle-session.d.ts +29 -3
  109. package/dist/utils/communication-attached-bundle-session.js +62 -3
  110. package/dist/utils/communication-consent-access-editor.d.ts +8 -4
  111. package/dist/utils/communication-consent-access-editor.js +8 -4
  112. package/dist/utils/communication-didcomm-payload.d.ts +5 -0
  113. package/dist/utils/communication-didcomm-payload.js +28 -18
  114. package/dist/utils/communication-document-reference.d.ts +23 -0
  115. package/dist/utils/communication-document-reference.js +89 -0
  116. package/dist/utils/communication-editor.d.ts +53 -0
  117. package/dist/utils/communication-editor.js +97 -0
  118. package/dist/utils/condition-entry-editor.d.ts +30 -0
  119. package/dist/utils/condition-entry-editor.js +34 -0
  120. package/dist/utils/consent-claim-helpers.d.ts +4 -0
  121. package/dist/utils/consent-claim-helpers.js +15 -1
  122. package/dist/utils/consent-duplicate-rules.js +1 -1
  123. package/dist/utils/coverage-entry-editor.d.ts +51 -0
  124. package/dist/utils/coverage-entry-editor.js +55 -0
  125. package/dist/utils/device-entry-editor.d.ts +59 -0
  126. package/dist/utils/device-entry-editor.js +63 -0
  127. package/dist/utils/device-use-statement-entry-editor.d.ts +43 -0
  128. package/dist/utils/device-use-statement-entry-editor.js +47 -0
  129. package/dist/utils/diagnostic-report-entry-editor.d.ts +74 -0
  130. package/dist/utils/diagnostic-report-entry-editor.js +136 -0
  131. package/dist/utils/did.d.ts +8 -0
  132. package/dist/utils/did.js +22 -0
  133. package/dist/utils/document-reference-entry-editor.d.ts +62 -0
  134. package/dist/utils/document-reference-entry-editor.js +66 -0
  135. package/dist/utils/employee-entry-editor.d.ts +36 -0
  136. package/dist/utils/employee-entry-editor.js +88 -0
  137. package/dist/utils/employee.d.ts +1 -0
  138. package/dist/utils/employee.js +2 -1
  139. package/dist/utils/encounter-entry-editor.d.ts +51 -0
  140. package/dist/utils/encounter-entry-editor.js +55 -0
  141. package/dist/utils/flag-entry-editor.d.ts +47 -0
  142. package/dist/utils/flag-entry-editor.js +51 -0
  143. package/dist/utils/immunization-entry-editor.d.ts +87 -0
  144. package/dist/utils/immunization-entry-editor.js +169 -0
  145. package/dist/utils/index.d.ts +7 -0
  146. package/dist/utils/index.js +7 -0
  147. package/dist/utils/individual-onboarding-acceptance-credential.d.ts +35 -0
  148. package/dist/utils/individual-onboarding-acceptance-credential.js +55 -0
  149. package/dist/utils/individual-smart.d.ts +59 -0
  150. package/dist/utils/individual-smart.js +135 -0
  151. package/dist/utils/license-list-search.d.ts +5 -0
  152. package/dist/utils/license-list-search.js +9 -0
  153. package/dist/utils/license.d.ts +45 -1
  154. package/dist/utils/license.js +86 -2
  155. package/dist/utils/medication-statement-entry-editor.d.ts +90 -0
  156. package/dist/utils/medication-statement-entry-editor.js +94 -0
  157. package/dist/utils/observation-component-entry-editor.d.ts +57 -0
  158. package/dist/utils/observation-component-entry-editor.js +105 -0
  159. package/dist/utils/observation-entry-editor.d.ts +29 -0
  160. package/dist/utils/observation-entry-editor.js +68 -0
  161. package/dist/utils/procedure-entry-editor.d.ts +71 -0
  162. package/dist/utils/procedure-entry-editor.js +75 -0
  163. package/dist/utils/professional-smart.d.ts +87 -0
  164. package/dist/utils/professional-smart.js +118 -4
  165. package/dist/utils/related-person-list.d.ts +4 -0
  166. package/dist/utils/related-person-list.js +26 -6
  167. package/dist/utils/same-as.d.ts +40 -0
  168. package/dist/utils/same-as.js +72 -0
  169. package/dist/utils/unified-health-id.d.ts +51 -0
  170. package/dist/utils/unified-health-id.js +92 -0
  171. package/dist/utils/vital-sign-day-batch.d.ts +25 -0
  172. package/dist/utils/vital-sign-day-batch.js +115 -0
  173. package/dist/utils/vital-sign-entry-editor.d.ts +61 -0
  174. package/dist/utils/vital-sign-entry-editor.js +152 -0
  175. package/package.json +2 -1
@@ -1,4 +1,5 @@
1
1
  export * from './actor.js';
2
+ export * from './authority-resolution.js';
2
3
  export * from './activation-policy.js';
3
4
  export * from './base-convert.js';
4
5
  export * from './baseN.js';
@@ -34,6 +35,7 @@ export * from './gw-core-path.js';
34
35
  export * from './gw-core-commercial-contract.js';
35
36
  export * from './legal-organization-verification-result.js';
36
37
  export * from './communication-fhir-r4.js';
38
+ export * from './communication-editor.js';
37
39
  export * from './communication-document-reference.js';
38
40
  export * from './communication-bundle-document-request.js';
39
41
  export * from './communication-identity.js';
@@ -48,6 +50,7 @@ export * from './communication-didcomm-payload.js';
48
50
  export * from './confidential-storage-persistence.js';
49
51
  export * from './confidential-storage-test-data.js';
50
52
  export * from './permission-templates.js';
53
+ export * from './client-assertion.js';
51
54
  export * from './professional-smart.js';
52
55
  export * from './related-person-list.js';
53
56
  export * from './clinical-resource-converters.js';
@@ -56,6 +59,7 @@ export * from './clinical-resource-view.js';
56
59
  export * from './fhir-validator.js';
57
60
  export * from './family-registration-test-data.js';
58
61
  export * from './individual-form-pdf.js';
62
+ export * from './individual-smart.js';
59
63
  export * from './individual-organization-claims.js';
60
64
  export * from './inter-tenant-access-contract.js';
61
65
  export * from './legal-organization-onboarding-editor.js';
@@ -64,6 +68,7 @@ export * from './organization-did-binding.js';
64
68
  export * from './organization-authorization-urn.js';
65
69
  export * from './individual-organization-lifecycle.js';
66
70
  export * from './individual-onboarding-editor.js';
71
+ export * from './individual-onboarding-acceptance-credential.js';
67
72
  export * from './individual-onboarding-document-reference.js';
68
73
  export * from './individual-organization-kyc.js';
69
74
  export * from './individual-bundle-vault.js';
@@ -88,12 +93,14 @@ export * from './normalize.js';
88
93
  export * from './object-convert.js';
89
94
  export * from './normalize-uuid.js';
90
95
  export * from './object-sanitize.js';
96
+ export * from './unified-health-id.js';
91
97
  export * from './permission-templates.js';
92
98
  export * from './smart-scope.js';
93
99
  export * from './service-act-reasons.js';
94
100
  export * from './same-as.js';
95
101
  export * from './activation-request.js';
96
102
  export * from './vp-token.js';
103
+ export * from './vital-sign-day-batch.js';
97
104
  export * from './wallet-mem.js';
98
105
  export * from './wallet-memory-queue.js';
99
106
  export * from './profile-outbox-memory-repository.js';
@@ -0,0 +1,35 @@
1
+ import type { VerifiableCredentialV2 } from '../models/verifiable-credential';
2
+ /**
3
+ * Input for the canonical individual-onboarding acceptance credential.
4
+ *
5
+ * This helper builds the evidence object that a frontend/BFF can later sign
6
+ * with the user profile key pair before sending it as an attachment.
7
+ *
8
+ * Canonical semantics:
9
+ * - `credentialSubject.memberOf.taxID` is the organization tax identifier
10
+ * - `credentialSubject.hasOccupation.identifier.value` defaults to `RESPRSN`
11
+ * - `credentialSubject.hasCredential.material` binds the credential to the
12
+ * profile signing material
13
+ */
14
+ export type IndividualOnboardingAcceptanceCredentialInput = Readonly<{
15
+ issuerDid: string;
16
+ subjectDid: string;
17
+ organizationTaxId: string;
18
+ profileKeyMaterial: string;
19
+ validFrom: string;
20
+ credentialId?: string;
21
+ representativeIdentifier?: string;
22
+ representativeRoleCode?: string;
23
+ sameAs?: string;
24
+ validUntil?: string;
25
+ proof?: VerifiableCredentialV2['proof'];
26
+ }>;
27
+ /**
28
+ * Builds the canonical Verifiable Credential for individual onboarding
29
+ * acceptance.
30
+ *
31
+ * The result is unsigned by design. Callers sign it with the user profile key
32
+ * pair and then attach the signed VC to the `Organization/_transaction`
33
+ * request.
34
+ */
35
+ export declare function buildIndividualOnboardingAcceptanceCredential(input: IndividualOnboardingAcceptanceCredentialInput): VerifiableCredentialV2;
@@ -0,0 +1,55 @@
1
+ import { ActivationCredentialTypes, W3cCredentialContexts, W3cCredentialTypes } from '../constants/verifiable-credentials.js';
2
+ import { ClaimsPersonSchemaorg } from '../constants/schemaorg.js';
3
+ function normalizeText(value) {
4
+ return typeof value === 'string' ? value.trim() : '';
5
+ }
6
+ function requireText(value, fieldName) {
7
+ const normalized = normalizeText(value);
8
+ if (!normalized) {
9
+ throw new Error(`buildIndividualOnboardingAcceptanceCredential requires ${fieldName}.`);
10
+ }
11
+ return normalized;
12
+ }
13
+ /**
14
+ * Builds the canonical Verifiable Credential for individual onboarding
15
+ * acceptance.
16
+ *
17
+ * The result is unsigned by design. Callers sign it with the user profile key
18
+ * pair and then attach the signed VC to the `Organization/_transaction`
19
+ * request.
20
+ */
21
+ export function buildIndividualOnboardingAcceptanceCredential(input) {
22
+ const issuerDid = requireText(input.issuerDid, 'issuerDid');
23
+ const subjectDid = requireText(input.subjectDid, 'subjectDid');
24
+ const organizationTaxId = requireText(input.organizationTaxId, 'organizationTaxId');
25
+ const profileKeyMaterial = requireText(input.profileKeyMaterial, 'profileKeyMaterial');
26
+ const validFrom = requireText(input.validFrom, 'validFrom');
27
+ const roleCode = normalizeText(input.representativeRoleCode) || 'RESPRSN';
28
+ return {
29
+ '@context': [W3cCredentialContexts.V2, 'https://schema.org'],
30
+ ...(normalizeText(input.credentialId) ? { id: normalizeText(input.credentialId) } : {}),
31
+ type: [W3cCredentialTypes.VerifiableCredential, ActivationCredentialTypes.LegalRepresentativeCredential],
32
+ issuer: issuerDid,
33
+ credentialSubject: {
34
+ id: subjectDid,
35
+ memberOf: {
36
+ taxID: organizationTaxId,
37
+ },
38
+ hasOccupation: {
39
+ identifier: {
40
+ value: roleCode,
41
+ },
42
+ },
43
+ hasCredential: {
44
+ material: profileKeyMaterial,
45
+ },
46
+ ...(normalizeText(input.representativeIdentifier)
47
+ ? { [ClaimsPersonSchemaorg.identifierValue]: normalizeText(input.representativeIdentifier) }
48
+ : {}),
49
+ ...(normalizeText(input.sameAs) ? { sameAs: normalizeText(input.sameAs) } : {}),
50
+ },
51
+ validFrom,
52
+ ...(normalizeText(input.validUntil) ? { validUntil: normalizeText(input.validUntil) } : {}),
53
+ ...(input.proof ? { proof: input.proof } : {}),
54
+ };
55
+ }
@@ -0,0 +1,59 @@
1
+ export type IndividualActorIdentityCredentialInput = Readonly<{
2
+ actorDid: string;
3
+ subjectDid?: string;
4
+ relationship?: string;
5
+ authorityBasis?: string;
6
+ email?: string;
7
+ sameAs?: string | readonly string[];
8
+ telephone?: string;
9
+ credentialMaterial?: string;
10
+ evidence?: readonly Record<string, unknown>[];
11
+ additionalCredentialSubject?: Record<string, unknown>;
12
+ additionalCredential?: Record<string, unknown>;
13
+ }>;
14
+ export type IndividualActorIdentityVpPayloadInput = Readonly<{
15
+ clientId: string;
16
+ actorDid: string;
17
+ subjectDid?: string;
18
+ relationship?: string;
19
+ authorityBasis?: string;
20
+ email?: string;
21
+ sameAs?: string | readonly string[];
22
+ telephone?: string;
23
+ credentialMaterial?: string;
24
+ evidence?: readonly Record<string, unknown>[];
25
+ verifiableCredential?: string | Record<string, unknown> | ReadonlyArray<string | Record<string, unknown>>;
26
+ additionalVp?: Record<string, unknown>;
27
+ additionalPayload?: Record<string, unknown>;
28
+ }>;
29
+ export type IndividualSubjectCredentialInput = Readonly<{
30
+ subjectDid: string;
31
+ sameAs?: string | readonly string[];
32
+ telephone?: string;
33
+ evidence?: readonly Record<string, unknown>[];
34
+ additionalCredentialSubject?: Record<string, unknown>;
35
+ additionalCredential?: Record<string, unknown>;
36
+ }>;
37
+ export type IndividualControllerCredentialInput = IndividualActorIdentityCredentialInput;
38
+ export type IndividualControllerVpPayloadInput = IndividualActorIdentityVpPayloadInput;
39
+ export type IndividualMemberCredentialInput = IndividualActorIdentityCredentialInput;
40
+ export type IndividualMemberVpPayloadInput = IndividualActorIdentityVpPayloadInput;
41
+ export declare function getIndividualControllerIdentitySameAs(input: Readonly<Pick<IndividualControllerCredentialInput, 'sameAs' | 'email'>>): string[];
42
+ export declare function getIndividualControllerIdentityTelephone(input: Readonly<Pick<IndividualControllerCredentialInput, 'telephone'>>): string | undefined;
43
+ export declare function getIndividualControllerIdentityVC(input: IndividualControllerCredentialInput): Record<string, unknown>;
44
+ export declare function buildIndividualControllerIdentityVpPayload(input: IndividualControllerVpPayloadInput): Record<string, unknown>;
45
+ export declare function buildUnsignedIndividualControllerIdentityVpJwt(input: IndividualControllerVpPayloadInput, options?: Readonly<{
46
+ nowSeconds?: number;
47
+ ttlSeconds?: number;
48
+ nonce?: string;
49
+ }>): string;
50
+ export declare function getIndividualSubjectVC(input: IndividualSubjectCredentialInput): Record<string, unknown>;
51
+ export declare function getIndividualMemberIdentitySameAs(input: Readonly<Pick<IndividualMemberCredentialInput, 'sameAs' | 'email'>>): string[];
52
+ export declare function getIndividualMemberIdentityTelephone(input: Readonly<Pick<IndividualMemberCredentialInput, 'telephone'>>): string | undefined;
53
+ export declare function getIndividualMemberIdentityVC(input: IndividualMemberCredentialInput): Record<string, unknown>;
54
+ export declare function buildIndividualMemberIdentityVpPayload(input: IndividualMemberVpPayloadInput): Record<string, unknown>;
55
+ export declare function buildUnsignedIndividualMemberIdentityVpJwt(input: IndividualMemberVpPayloadInput, options?: Readonly<{
56
+ nowSeconds?: number;
57
+ ttlSeconds?: number;
58
+ nonce?: string;
59
+ }>): string;
@@ -0,0 +1,135 @@
1
+ import { ClaimsPersonSchemaorg } from '../constants/schemaorg.js';
2
+ import { IndividualCredentialTypes, W3cCredentialTypes, } from '../constants/verifiable-credentials.js';
3
+ import { normalizeSameAsHashCsv, normalizeSameAsHashList, normalizeTelephoneHash } from './same-as.js';
4
+ import { buildUnsignedVpJwt } from './jwt.js';
5
+ function getIndividualIdentitySameAs(input) {
6
+ const sameAsCandidates = [];
7
+ if (input.sameAs) {
8
+ sameAsCandidates.push(...normalizeSameAsHashList(input.sameAs));
9
+ }
10
+ if (input.email) {
11
+ sameAsCandidates.push(...normalizeSameAsHashList(input.email));
12
+ }
13
+ return [...new Set(sameAsCandidates)];
14
+ }
15
+ function getIndividualIdentityTelephone(input) {
16
+ const normalized = normalizeTelephoneHash(String(input.telephone || ''));
17
+ return normalized || undefined;
18
+ }
19
+ function buildIndividualIdentityVC(input, credentialType) {
20
+ const normalizedSameAs = getIndividualIdentitySameAs(input);
21
+ const normalizedTelephone = getIndividualIdentityTelephone(input);
22
+ const normalizedCredentialMaterial = String(input.credentialMaterial || '').trim();
23
+ const normalizedSubjectDid = String(input.subjectDid || '').trim();
24
+ const normalizedRelationship = String(input.relationship || '').trim();
25
+ const normalizedAuthorityBasis = String(input.authorityBasis || '').trim();
26
+ return {
27
+ type: [
28
+ W3cCredentialTypes.VerifiableCredential,
29
+ credentialType,
30
+ ],
31
+ credentialSubject: {
32
+ id: String(input.actorDid || '').trim(),
33
+ ...(normalizedSubjectDid ? { subject: normalizedSubjectDid } : {}),
34
+ ...(normalizedRelationship ? { relationship: normalizedRelationship } : {}),
35
+ ...(normalizedAuthorityBasis ? { authorityBasis: normalizedAuthorityBasis } : {}),
36
+ ...(normalizedSameAs.length
37
+ ? { sameAs: normalizeSameAsHashCsv(normalizedSameAs) }
38
+ : {}),
39
+ ...(normalizedTelephone
40
+ ? { [ClaimsPersonSchemaorg.telephone]: normalizedTelephone }
41
+ : {}),
42
+ ...(normalizedCredentialMaterial
43
+ ? { [ClaimsPersonSchemaorg.hasCredentialMaterial]: normalizedCredentialMaterial }
44
+ : {}),
45
+ ...(input.additionalCredentialSubject || {}),
46
+ },
47
+ ...(Array.isArray(input.evidence) && input.evidence.length
48
+ ? { evidence: [...input.evidence] }
49
+ : {}),
50
+ ...(input.additionalCredential || {}),
51
+ };
52
+ }
53
+ function buildIndividualIdentityVpPayload(input, credentialType) {
54
+ const credentials = Array.isArray(input.verifiableCredential)
55
+ ? [...input.verifiableCredential]
56
+ : input.verifiableCredential
57
+ ? [input.verifiableCredential]
58
+ : [buildIndividualIdentityVC({
59
+ actorDid: input.actorDid,
60
+ subjectDid: input.subjectDid,
61
+ relationship: input.relationship,
62
+ authorityBasis: input.authorityBasis,
63
+ email: input.email,
64
+ sameAs: input.sameAs,
65
+ telephone: input.telephone,
66
+ credentialMaterial: input.credentialMaterial,
67
+ evidence: input.evidence,
68
+ }, credentialType)];
69
+ return {
70
+ ...(input.additionalPayload || {}),
71
+ vp: {
72
+ holder: String(input.clientId || '').trim(),
73
+ verifiableCredential: credentials,
74
+ ...(input.additionalVp || {}),
75
+ },
76
+ };
77
+ }
78
+ export function getIndividualControllerIdentitySameAs(input) {
79
+ return getIndividualIdentitySameAs(input);
80
+ }
81
+ export function getIndividualControllerIdentityTelephone(input) {
82
+ return getIndividualIdentityTelephone(input);
83
+ }
84
+ export function getIndividualControllerIdentityVC(input) {
85
+ return buildIndividualIdentityVC(input, IndividualCredentialTypes.IndividualControllerCredential);
86
+ }
87
+ export function buildIndividualControllerIdentityVpPayload(input) {
88
+ return buildIndividualIdentityVpPayload(input, IndividualCredentialTypes.IndividualControllerCredential);
89
+ }
90
+ export function buildUnsignedIndividualControllerIdentityVpJwt(input, options = {}) {
91
+ return buildUnsignedVpJwt(buildIndividualControllerIdentityVpPayload(input), options);
92
+ }
93
+ export function getIndividualSubjectVC(input) {
94
+ const normalizedSameAs = getIndividualIdentitySameAs({
95
+ sameAs: input.sameAs,
96
+ });
97
+ const normalizedTelephone = getIndividualIdentityTelephone({
98
+ telephone: input.telephone,
99
+ });
100
+ return {
101
+ type: [
102
+ W3cCredentialTypes.VerifiableCredential,
103
+ IndividualCredentialTypes.IndividualSubjectCredential,
104
+ ],
105
+ credentialSubject: {
106
+ id: String(input.subjectDid || '').trim(),
107
+ ...(normalizedSameAs.length
108
+ ? { sameAs: normalizeSameAsHashCsv(normalizedSameAs) }
109
+ : {}),
110
+ ...(normalizedTelephone
111
+ ? { [ClaimsPersonSchemaorg.telephone]: normalizedTelephone }
112
+ : {}),
113
+ ...(input.additionalCredentialSubject || {}),
114
+ },
115
+ ...(Array.isArray(input.evidence) && input.evidence.length
116
+ ? { evidence: [...input.evidence] }
117
+ : {}),
118
+ ...(input.additionalCredential || {}),
119
+ };
120
+ }
121
+ export function getIndividualMemberIdentitySameAs(input) {
122
+ return getIndividualIdentitySameAs(input);
123
+ }
124
+ export function getIndividualMemberIdentityTelephone(input) {
125
+ return getIndividualIdentityTelephone(input);
126
+ }
127
+ export function getIndividualMemberIdentityVC(input) {
128
+ return buildIndividualIdentityVC(input, IndividualCredentialTypes.IndividualMemberCredential);
129
+ }
130
+ export function buildIndividualMemberIdentityVpPayload(input) {
131
+ return buildIndividualIdentityVpPayload(input, IndividualCredentialTypes.IndividualMemberCredential);
132
+ }
133
+ export function buildUnsignedIndividualMemberIdentityVpJwt(input, options = {}) {
134
+ return buildUnsignedVpJwt(buildIndividualMemberIdentityVpPayload(input), options);
135
+ }
@@ -8,9 +8,11 @@ import { buildLicenseSearchEntry, type LicenseClaims, type LicenseSearchInput, t
8
8
  export type LicenseListSearchState = Readonly<{
9
9
  serialNumbers?: readonly string[];
10
10
  email?: string;
11
+ telephone?: string;
11
12
  role?: string;
12
13
  status?: LicenseStatus;
13
14
  subjectId?: string;
15
+ ownerOrganizationId?: string;
14
16
  userClass?: string;
15
17
  type?: string;
16
18
  active?: boolean;
@@ -28,6 +30,7 @@ export type LicenseListRecord = Readonly<{
28
30
  id?: string;
29
31
  status?: string;
30
32
  subjectId?: string;
33
+ ownerOrganizationId?: string;
31
34
  email?: string;
32
35
  role?: string;
33
36
  category?: string;
@@ -66,6 +69,8 @@ export declare class LicenseListSearchEditor {
66
69
  setRole(value: string): this;
67
70
  setStatus(value: LicenseStatus): this;
68
71
  setSubjectId(value: string): this;
72
+ /** Limits results to the organization that owns the seat pool. */
73
+ setOwnerOrganizationId(value: string): this;
69
74
  setUserClass(value: string): this;
70
75
  setAppType(value: string): this;
71
76
  setActive(value: boolean): this;
@@ -15,6 +15,7 @@ function cloneDraft(state) {
15
15
  role: normalizeText(state?.role),
16
16
  status: state?.status,
17
17
  subjectId: normalizeText(state?.subjectId),
18
+ ownerOrganizationId: normalizeText(state?.ownerOrganizationId),
18
19
  userClass: normalizeText(state?.userClass),
19
20
  type: normalizeText(state?.type),
20
21
  active: typeof state?.active === 'boolean' ? state.active : undefined,
@@ -71,6 +72,11 @@ export class LicenseListSearchEditor {
71
72
  this.draft = cloneDraft({ ...this.draft, subjectId: value });
72
73
  return this;
73
74
  }
75
+ /** Limits results to the organization that owns the seat pool. */
76
+ setOwnerOrganizationId(value) {
77
+ this.draft = cloneDraft({ ...this.draft, ownerOrganizationId: value });
78
+ return this;
79
+ }
74
80
  setUserClass(value) {
75
81
  this.draft = cloneDraft({ ...this.draft, userClass: value });
76
82
  return this;
@@ -117,6 +123,7 @@ export class LicenseListSearchEditor {
117
123
  ...(this.draft.role ? { role: this.draft.role } : {}),
118
124
  ...(resolveStatus(this.draft) ? { status: resolveStatus(this.draft) } : {}),
119
125
  ...(this.draft.subjectId ? { subjectId: this.draft.subjectId } : {}),
126
+ ...(this.draft.ownerOrganizationId ? { ownerOrganizationId: this.draft.ownerOrganizationId } : {}),
120
127
  additionalClaims: cloneClaims(this.draft.additionalClaims),
121
128
  };
122
129
  }
@@ -151,7 +158,9 @@ export function readLicenseListRecords(body) {
151
158
  || entry.id),
152
159
  status: normalizeText(meta.status),
153
160
  subjectId: normalizeText(meta.subjectId),
161
+ ownerOrganizationId: normalizeText(meta.ownerOrganizationId || claims['License.ownerOrganizationId']),
154
162
  email: normalizeText(claims[ClaimsPersonSchemaorg.email]),
163
+ telephone: normalizeText(claims[ClaimsPersonSchemaorg.telephone]),
155
164
  role: normalizeText(claims[ClaimsPersonSchemaorg.hasOccupationalRoleValue]),
156
165
  category: normalizeText(claims[ClaimsIndividualProductSchemaorg.category]),
157
166
  appType: normalizeText(claims[ClaimsIndividualProductSchemaorg.additionalType]),
@@ -54,11 +54,44 @@ export declare const LicenseStatuses: Readonly<{
54
54
  readonly Inactive: "inactive";
55
55
  }>;
56
56
  export type LicenseStatus = typeof LicenseStatuses[keyof typeof LicenseStatuses];
57
+ /**
58
+ * Role families that decide which organization owns the actor's license.
59
+ *
60
+ * This classification is deliberately independent from Consent. A person may
61
+ * receive permissions in either case, but only a FHIR v3 relationship role is
62
+ * a member of the individual's organization and consumes its seat pool.
63
+ */
64
+ export declare const LicenseRoleKinds: Readonly<{
65
+ readonly IndividualMember: "individual-member";
66
+ readonly Professional: "professional";
67
+ readonly Unsupported: "unsupported";
68
+ }>;
69
+ export type LicenseRoleKind = typeof LicenseRoleKinds[keyof typeof LicenseRoleKinds];
70
+ /**
71
+ * Classifies one canonical or compatibility role token for license ownership.
72
+ *
73
+ * Rules:
74
+ * - FHIR/HL7 v3 `RoleCode` actors are non-employee members of the individual
75
+ * organization and consume one of its licenses.
76
+ * - ISCO/ISCO-08 actors are professionals. Their employer/organization owns
77
+ * their professional license, so a patient's individual pool is untouched.
78
+ * - Unknown role systems are not silently charged to either pool.
79
+ */
80
+ export declare function classifyLicenseRole(role: string): LicenseRoleKind;
57
81
  export type LicenseIssueInput = Readonly<{
58
- email: string;
82
+ email?: string;
83
+ telephone?: string;
59
84
  role: string;
60
85
  userClass?: DeviceUserClass;
61
86
  type?: DeviceAppType;
87
+ /** Individual/legal organization that owns the seat pool. */
88
+ ownerOrganizationId?: string;
89
+ /** Card/individual DID granted by the invitation after acceptance. */
90
+ subjectDid?: string;
91
+ /** Existing RelatedPerson/contact selected before the invitation. */
92
+ relatedPersonId?: string;
93
+ /** Stable invitation workflow identifier; not the license id or code. */
94
+ invitationId?: string;
62
95
  additionalClaims?: LicenseClaims;
63
96
  }>;
64
97
  export type LicensePurchaseInput = Readonly<{
@@ -66,6 +99,10 @@ export type LicensePurchaseInput = Readonly<{
66
99
  userClass?: DeviceUserClass;
67
100
  type?: DeviceAppType;
68
101
  serialNumbers?: readonly string[];
102
+ price?: number;
103
+ priceCurrency?: string;
104
+ /** Organization whose pool receives the newly materialized seats. */
105
+ ownerOrganizationId?: string;
69
106
  additionalClaims?: LicenseClaims;
70
107
  }>;
71
108
  export type LicenseSearchInput = Readonly<{
@@ -76,6 +113,7 @@ export type LicenseSearchInput = Readonly<{
76
113
  role?: string;
77
114
  status?: LicenseStatus;
78
115
  subjectId?: string;
116
+ ownerOrganizationId?: string;
79
117
  additionalClaims?: LicenseClaims;
80
118
  }>;
81
119
  /**
@@ -106,6 +144,10 @@ export declare function buildLicenseIssueEntry(input: LicenseIssueInput): {
106
144
  };
107
145
  meta: {
108
146
  claims: LicenseClaims;
147
+ ownerOrganizationId?: string;
148
+ subjectDid?: string;
149
+ relatedPersonId?: string;
150
+ invitationId?: string;
109
151
  };
110
152
  };
111
153
  /**
@@ -130,6 +172,7 @@ export declare function buildLicensePurchaseEntry(input: LicensePurchaseInput):
130
172
  };
131
173
  meta: {
132
174
  claims: LicenseClaims;
175
+ ownerOrganizationId?: string;
133
176
  };
134
177
  };
135
178
  /**
@@ -151,5 +194,6 @@ export declare function buildLicenseSearchEntry(input: LicenseSearchInput): {
151
194
  claims: LicenseClaims;
152
195
  status?: LicenseStatus;
153
196
  subjectId?: string;
197
+ ownerOrganizationId?: string;
154
198
  };
155
199
  };
@@ -52,6 +52,47 @@ export const LicenseStatuses = Object.freeze({
52
52
  Active: 'active',
53
53
  Inactive: 'inactive',
54
54
  });
55
+ /**
56
+ * Role families that decide which organization owns the actor's license.
57
+ *
58
+ * This classification is deliberately independent from Consent. A person may
59
+ * receive permissions in either case, but only a FHIR v3 relationship role is
60
+ * a member of the individual's organization and consumes its seat pool.
61
+ */
62
+ export const LicenseRoleKinds = Object.freeze({
63
+ IndividualMember: 'individual-member',
64
+ Professional: 'professional',
65
+ Unsupported: 'unsupported',
66
+ });
67
+ /**
68
+ * Classifies one canonical or compatibility role token for license ownership.
69
+ *
70
+ * Rules:
71
+ * - FHIR/HL7 v3 `RoleCode` actors are non-employee members of the individual
72
+ * organization and consume one of its licenses.
73
+ * - ISCO/ISCO-08 actors are professionals. Their employer/organization owns
74
+ * their professional license, so a patient's individual pool is untouched.
75
+ * - Unknown role systems are not silently charged to either pool.
76
+ */
77
+ export function classifyLicenseRole(role) {
78
+ const normalized = String(role || '').trim().toLowerCase();
79
+ if (!normalized)
80
+ return LicenseRoleKinds.Unsupported;
81
+ const system = normalized.includes('|') ? normalized.split('|', 1)[0] : normalized;
82
+ if (system === 'isco'
83
+ || system === 'isco-08'
84
+ || system === 'org.ilo.isco'
85
+ || system === 'org.ilo.isco-08'
86
+ || system.endsWith('/isco-08')) {
87
+ return LicenseRoleKinds.Professional;
88
+ }
89
+ if (system === 'v3-rolecode'
90
+ || system === 'org.hl7.v3.rolecode'
91
+ || system.endsWith('/v3-rolecode')) {
92
+ return LicenseRoleKinds.IndividualMember;
93
+ }
94
+ return LicenseRoleKinds.Unsupported;
95
+ }
55
96
  function cloneClaims(claims) {
56
97
  return { ...(claims || {}) };
57
98
  }
@@ -82,12 +123,31 @@ export function serializeLicenseSerialNumbers(serialNumbers) {
82
123
  * - seat/app semantics come from `IndividualProduct.*`
83
124
  */
84
125
  export function buildLicenseIssueClaims(input) {
126
+ const email = String(input.email || '').trim();
127
+ const telephone = String(input.telephone || '').trim();
128
+ if (!email && !telephone) {
129
+ throw new Error('License issue requires an email or telephone recipient.');
130
+ }
131
+ if (telephone && !/^\+[1-9]\d{6,14}$/.test(telephone)) {
132
+ throw new Error('License issue telephone must use an international ITU format beginning with +.');
133
+ }
134
+ const userClass = input.userClass || DeviceUserClasses.Employee;
135
+ if (userClass === DeviceUserClasses.Individual) {
136
+ const roleKind = classifyLicenseRole(input.role);
137
+ if (roleKind === LicenseRoleKinds.Professional) {
138
+ throw new Error('ISCO professional roles do not consume individual-member licenses.');
139
+ }
140
+ if (roleKind !== LicenseRoleKinds.IndividualMember) {
141
+ throw new Error('Individual-member licenses require a FHIR v3-RoleCode role.');
142
+ }
143
+ }
85
144
  const claims = {
86
145
  '@context': LicenseClaimContext.SchemaOrg,
87
146
  ...cloneClaims(input.additionalClaims),
88
- [ClaimsPersonSchemaorg.email]: input.email.trim(),
147
+ ...(email ? { [ClaimsPersonSchemaorg.email]: email } : {}),
148
+ ...(telephone ? { [ClaimsPersonSchemaorg.telephone]: telephone } : {}),
89
149
  [ClaimsPersonSchemaorg.hasOccupationalRoleValue]: input.role.trim(),
90
- [ClaimsIndividualProductSchemaorg.category]: mapLicenseCategoryFromUserClass(input.userClass || DeviceUserClasses.Employee),
150
+ [ClaimsIndividualProductSchemaorg.category]: mapLicenseCategoryFromUserClass(userClass),
91
151
  [ClaimsIndividualProductSchemaorg.additionalType]: input.type || DeviceAppTypes.Mobile,
92
152
  };
93
153
  return claims;
@@ -104,6 +164,18 @@ export function buildLicenseIssueEntry(input) {
104
164
  ...buildLicenseIssueClaims(input),
105
165
  '@type': LicenseEntryOperations.Issue,
106
166
  },
167
+ ...(String(input.ownerOrganizationId || '').trim()
168
+ ? { ownerOrganizationId: String(input.ownerOrganizationId).trim() }
169
+ : {}),
170
+ ...(String(input.subjectDid || '').trim()
171
+ ? { subjectDid: String(input.subjectDid).trim() }
172
+ : {}),
173
+ ...(String(input.relatedPersonId || '').trim()
174
+ ? { relatedPersonId: String(input.relatedPersonId).trim() }
175
+ : {}),
176
+ ...(String(input.invitationId || '').trim()
177
+ ? { invitationId: String(input.invitationId).trim() }
178
+ : {}),
107
179
  },
108
180
  };
109
181
  }
@@ -129,6 +201,12 @@ export function buildLicensePurchaseClaims(input) {
129
201
  if (serializedSerialNumbers) {
130
202
  claims[ClaimsOfferSchemaorg.serialNumber] = serializedSerialNumbers;
131
203
  }
204
+ if (typeof input.price === 'number' && Number.isFinite(input.price) && input.price >= 0) {
205
+ claims[ClaimsOfferSchemaorg.price] = input.price;
206
+ }
207
+ if (typeof input.priceCurrency === 'string' && input.priceCurrency.trim()) {
208
+ claims[ClaimsOfferSchemaorg.priceCurrency] = input.priceCurrency.trim().toUpperCase();
209
+ }
132
210
  return claims;
133
211
  }
134
212
  /**
@@ -144,6 +222,9 @@ export function buildLicensePurchaseEntry(input) {
144
222
  ...buildLicensePurchaseClaims(input),
145
223
  '@type': LicenseEntryOperations.Purchase,
146
224
  },
225
+ ...(String(input.ownerOrganizationId || '').trim()
226
+ ? { ownerOrganizationId: String(input.ownerOrganizationId).trim() }
227
+ : {}),
147
228
  },
148
229
  };
149
230
  }
@@ -189,6 +270,9 @@ export function buildLicenseSearchEntry(input) {
189
270
  ...(typeof input.subjectId === 'string' && input.subjectId.trim()
190
271
  ? { subjectId: input.subjectId.trim() }
191
272
  : {}),
273
+ ...(typeof input.ownerOrganizationId === 'string' && input.ownerOrganizationId.trim()
274
+ ? { ownerOrganizationId: input.ownerOrganizationId.trim() }
275
+ : {}),
192
276
  },
193
277
  };
194
278
  }