gdc-common-utils-ts 2.0.17 → 2.1.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.
- package/README.md +0 -1
- package/dist/constants/verifiable-credentials.d.ts +7 -0
- package/dist/constants/verifiable-credentials.js +7 -0
- package/dist/examples/bundle-didcomm-payload.d.ts +11 -0
- package/dist/examples/bundle-didcomm-payload.js +13 -0
- package/dist/examples/communication-attached-bundle-session.js +2 -1
- package/dist/examples/communication-didcomm-payload.d.ts +35 -0
- package/dist/examples/communication-didcomm-payload.js +38 -0
- package/dist/examples/contract-examples.d.ts +1 -0
- package/dist/examples/contract-examples.js +1 -0
- package/dist/examples/index.d.ts +5 -0
- package/dist/examples/index.js +5 -0
- package/dist/examples/inter-tenant-access-contract.d.ts +124 -0
- package/dist/examples/inter-tenant-access-contract.js +134 -0
- package/dist/examples/profile-manager-mem.d.ts +45 -0
- package/dist/examples/profile-manager-mem.js +29 -0
- package/dist/examples/shared.d.ts +6 -0
- package/dist/examples/shared.js +6 -0
- package/dist/examples/wallet-mem.d.ts +38 -0
- package/dist/examples/wallet-mem.js +40 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/interfaces/IProfileOutboxRepository.d.ts +36 -0
- package/dist/interfaces/IProfileOutboxRepository.js +2 -0
- package/dist/interfaces/IWallet.d.ts +74 -0
- package/dist/interfaces/IWallet.js +2 -0
- package/dist/interfaces/IWalletQueue.d.ts +30 -0
- package/dist/interfaces/IWalletQueue.js +2 -0
- package/dist/interfaces/index.d.ts +8 -0
- package/dist/interfaces/index.js +8 -0
- package/dist/models/communication-attached-bundle-session.d.ts +193 -0
- package/dist/models/communication-attached-bundle-session.js +34 -0
- package/dist/models/index.d.ts +4 -0
- package/dist/models/index.js +4 -0
- package/dist/models/inter-tenant-access-contract.d.ts +105 -0
- package/dist/models/inter-tenant-access-contract.js +78 -0
- package/dist/models/interoperable-claims/diagnostic-report-claims.d.ts +1 -2
- package/dist/models/interoperable-claims/diagnostic-report-claims.js +1 -2
- package/dist/models/profile-manager.d.ts +85 -0
- package/dist/models/profile-manager.js +2 -0
- package/dist/models/wallet.d.ts +59 -0
- package/dist/models/wallet.js +22 -0
- package/dist/utils/backend-message-manager-mem.d.ts +67 -0
- package/dist/utils/backend-message-manager-mem.js +227 -0
- package/dist/utils/bundle-didcomm-payload.d.ts +29 -0
- package/dist/utils/bundle-didcomm-payload.js +48 -0
- package/dist/utils/communication-attached-bundle-session-helpers.d.ts +54 -0
- package/dist/utils/communication-attached-bundle-session-helpers.js +517 -0
- package/dist/utils/communication-attached-bundle-session.d.ts +59 -302
- package/dist/utils/communication-attached-bundle-session.js +114 -839
- package/dist/utils/communication-consent-access-editor.d.ts +85 -0
- package/dist/utils/communication-consent-access-editor.js +244 -0
- package/dist/utils/communication-didcomm-payload.d.ts +33 -0
- package/dist/utils/communication-didcomm-payload.js +75 -0
- package/dist/utils/evidence-blockchain-references.d.ts +2 -0
- package/dist/utils/evidence-blockchain-references.js +4 -0
- package/dist/utils/index.d.ts +10 -0
- package/dist/utils/index.js +10 -0
- package/dist/utils/inter-tenant-access-contract.d.ts +44 -0
- package/dist/utils/inter-tenant-access-contract.js +358 -0
- package/dist/utils/organization-authorization-urn.d.ts +43 -0
- package/dist/utils/organization-authorization-urn.js +87 -0
- package/dist/utils/profile-manager-mem.d.ts +69 -0
- package/dist/utils/profile-manager-mem.js +79 -0
- package/dist/utils/profile-outbox-memory-repository.d.ts +34 -0
- package/dist/utils/profile-outbox-memory-repository.js +57 -0
- package/dist/utils/wallet-mem.d.ts +93 -0
- package/dist/utils/wallet-mem.js +277 -0
- package/dist/utils/wallet-memory-queue.d.ts +32 -0
- package/dist/utils/wallet-memory-queue.js +82 -0
- package/package.json +1 -1
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { type HealthcareActorRoleDescriptor, type HealthcareSectionDescriptor } from '../constants/healthcare';
|
|
2
|
+
import type { DataspaceSector } from '../constants/sectors';
|
|
3
|
+
import type { CommunicationAttachedBundleSessionOptions, ConsentEditorClassifiedActors, ConsentEditorClassifiedPurpose, ConsentEditorClassifiedRoles, ConsentEditorClassifiedTarget, ConsentViewModel } from '../models/communication-attached-bundle-session';
|
|
4
|
+
import type { ConsentDuplicateRuleConflict } from './consent-duplicate-rules';
|
|
5
|
+
import { CommunicationAttachedBundleSession } from './communication-attached-bundle-session';
|
|
6
|
+
/**
|
|
7
|
+
* High-level consent-access editor alias for onboarding and app-facing code.
|
|
8
|
+
*
|
|
9
|
+
* This keeps the business intent explicit for developers who are editing
|
|
10
|
+
* Consent access rules inside a Communication-carried bundle and should not
|
|
11
|
+
* need to start from the lower-level generic session name.
|
|
12
|
+
*/
|
|
13
|
+
export declare class ConsentAccessEditor extends CommunicationAttachedBundleSession {
|
|
14
|
+
/** Returns duplicate atomic consent-rule conflicts across the current bundle. */
|
|
15
|
+
getConsentRuleDuplicateConflicts(): ConsentDuplicateRuleConflict[];
|
|
16
|
+
/** Returns duplicate atomic consent-rule conflicts affecting the active Consent entry. */
|
|
17
|
+
getActiveConsentRuleDuplicateConflicts(): ConsentDuplicateRuleConflict[];
|
|
18
|
+
/** Returns one frontend-facing editable view model for the active Consent entry. */
|
|
19
|
+
getConsentViewModel(): ConsentViewModel;
|
|
20
|
+
/** Applies one frontend-facing editable view model back into the active Consent entry. */
|
|
21
|
+
applyConsentViewModel(viewModel: ConsentViewModel): this;
|
|
22
|
+
/** Returns the canonical permit/deny decision from the active Consent entry. */
|
|
23
|
+
getDecision(): string;
|
|
24
|
+
/** @deprecated Use `getDecision()`. */
|
|
25
|
+
getPermit(): string;
|
|
26
|
+
/** Returns target classification derived from the current consent claim contract. */
|
|
27
|
+
getTargetsClassified(): ConsentEditorClassifiedTarget[];
|
|
28
|
+
getCoreSectionOptions(): readonly ConsentEditorClassifiedTarget[];
|
|
29
|
+
getCoreSectionCatalog(): Readonly<Record<string, HealthcareSectionDescriptor>>;
|
|
30
|
+
getKindOfDocumentOptions(): readonly ConsentEditorClassifiedTarget[];
|
|
31
|
+
getKindOfDocumentCatalog(): Readonly<Record<string, HealthcareSectionDescriptor>>;
|
|
32
|
+
getTypeOfServiceOptions(): readonly ConsentEditorClassifiedTarget[];
|
|
33
|
+
getTypeOfServiceCatalog(): Readonly<Record<string, HealthcareSectionDescriptor>>;
|
|
34
|
+
getSubjectMatterDomainOptions(): readonly ConsentEditorClassifiedTarget[];
|
|
35
|
+
getSubjectMatterDomainCatalog(): Readonly<Record<string, HealthcareSectionDescriptor>>;
|
|
36
|
+
getResourceTypeOptions(): readonly ConsentEditorClassifiedTarget[];
|
|
37
|
+
getResourceTypeCatalog(): readonly string[];
|
|
38
|
+
getAvailableProfessionalRolesBySector(sector: DataspaceSector): Readonly<Record<string, HealthcareActorRoleDescriptor>>;
|
|
39
|
+
getAvailableRelationshipRoles(): Readonly<Record<string, HealthcareActorRoleDescriptor>>;
|
|
40
|
+
getSelectedCoreSections(): string[];
|
|
41
|
+
getSelectedKindOfDocuments(): string[];
|
|
42
|
+
getSelectedTypeOfServices(): string[];
|
|
43
|
+
getSelectedSubjectMatterDomains(): string[];
|
|
44
|
+
getSelectedResourceTypes(): string[];
|
|
45
|
+
setSelectedCoreSections(codes: readonly string[]): this;
|
|
46
|
+
setSelectedKindOfDocuments(codes: readonly string[]): this;
|
|
47
|
+
setSelectedTypeOfServices(codes: readonly string[]): this;
|
|
48
|
+
setSelectedSubjectMatterDomains(codes: readonly string[]): this;
|
|
49
|
+
setSelectedResourceTypes(codes: readonly string[]): this;
|
|
50
|
+
addCoreSections(codes: readonly string[]): this;
|
|
51
|
+
removeCoreSections(codes: readonly string[]): this;
|
|
52
|
+
addKindOfDocuments(codes: readonly string[]): this;
|
|
53
|
+
removeKindOfDocuments(codes: readonly string[]): this;
|
|
54
|
+
addTypeOfServices(codes: readonly string[]): this;
|
|
55
|
+
removeTypeOfServices(codes: readonly string[]): this;
|
|
56
|
+
addSubjectMatterDomains(codes: readonly string[]): this;
|
|
57
|
+
removeSubjectMatterDomains(codes: readonly string[]): this;
|
|
58
|
+
addResourceTypes(codes: readonly string[]): this;
|
|
59
|
+
removeResourceTypes(codes: readonly string[]): this;
|
|
60
|
+
getPurposesClassified(): ConsentEditorClassifiedPurpose[];
|
|
61
|
+
getSelectedPurposes(): string[];
|
|
62
|
+
setSelectedPurposes(codes: readonly string[]): this;
|
|
63
|
+
addPurposes(codes: readonly string[]): this;
|
|
64
|
+
removePurposes(codes: readonly string[]): this;
|
|
65
|
+
getRolesClassified(): ConsentEditorClassifiedRoles;
|
|
66
|
+
getSelectedRoles(): string[];
|
|
67
|
+
setSelectedRoles(codes: readonly string[]): this;
|
|
68
|
+
addRoles(codes: readonly string[]): this;
|
|
69
|
+
removeRoles(codes: readonly string[]): this;
|
|
70
|
+
getActorsClassified(): ConsentEditorClassifiedActors;
|
|
71
|
+
private getSelectedSectionCodesByFamily;
|
|
72
|
+
private setSelectedSectionCodesByFamily;
|
|
73
|
+
private addSectionCodesByFamily;
|
|
74
|
+
private removeSectionCodesByFamily;
|
|
75
|
+
private setActiveEntryClaimList;
|
|
76
|
+
private addActiveEntryClaimList;
|
|
77
|
+
private removeActiveEntryClaimList;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* High-level factory for consent-access editing.
|
|
81
|
+
*
|
|
82
|
+
* Prefer this name in onboarding docs when the developer intent is:
|
|
83
|
+
* "edit a Consent access bundle carried by a Communication".
|
|
84
|
+
*/
|
|
85
|
+
export declare function createConsentAccessEditor(options?: CommunicationAttachedBundleSessionOptions): ConsentAccessEditor;
|
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
// Copyright 2026 Conectate Soluciones y Aplicaciones SL under the Apache License, Version 2.0.
|
|
2
|
+
import { ResourceTypesFhirR4 } from '../constants/fhir-resource-types.js';
|
|
3
|
+
import { getHealthcareProfessionalRolesBySector, getHealthcareRolesByFamily, getHealthcareSectionsByFamily, getHealthcareSectionFamilyByCode, HealthcareRoleFamilies, HealthcareCanonicalSectionFamilies, } from '../constants/healthcare.js';
|
|
4
|
+
import { ClaimConsent } from '../models/consent-rule.js';
|
|
5
|
+
import { ConsentEditorScopeCodes, ConsentEditorTargetKinds, } from '../models/communication-attached-bundle-session.js';
|
|
6
|
+
import { detectDuplicateConsentRuleConflicts } from './consent-duplicate-rules.js';
|
|
7
|
+
import { CommunicationAttachedBundleSession } from './communication-attached-bundle-session.js';
|
|
8
|
+
import { asTrimmedString, buildClassifiedConsentTarget, buildConsentViewModel, buildSectionCatalogOptions, classifyConsentActors, classifyConsentPurposes, classifyConsentRoles, classifyConsentTargetsFromClaims, CSV_SEPARATOR, flattenClassifiedActors, flattenClassifiedRoles, flattenClassifiedTargets, normalizeCsvValues, splitCsv, } from './communication-attached-bundle-session-helpers.js';
|
|
9
|
+
/**
|
|
10
|
+
* High-level consent-access editor alias for onboarding and app-facing code.
|
|
11
|
+
*
|
|
12
|
+
* This keeps the business intent explicit for developers who are editing
|
|
13
|
+
* Consent access rules inside a Communication-carried bundle and should not
|
|
14
|
+
* need to start from the lower-level generic session name.
|
|
15
|
+
*/
|
|
16
|
+
export class ConsentAccessEditor extends CommunicationAttachedBundleSession {
|
|
17
|
+
/** Returns duplicate atomic consent-rule conflicts across the current bundle. */
|
|
18
|
+
getConsentRuleDuplicateConflicts() {
|
|
19
|
+
return detectDuplicateConsentRuleConflicts(this.getBundleInMemory().data);
|
|
20
|
+
}
|
|
21
|
+
/** Returns duplicate atomic consent-rule conflicts affecting the active Consent entry. */
|
|
22
|
+
getActiveConsentRuleDuplicateConflicts() {
|
|
23
|
+
const activeEntryIndex = this.getActiveEntryIndex();
|
|
24
|
+
if (activeEntryIndex === null) {
|
|
25
|
+
return [];
|
|
26
|
+
}
|
|
27
|
+
return this.getConsentRuleDuplicateConflicts()
|
|
28
|
+
.filter((conflict) => conflict.affectedEntries.some((entry) => entry.entryIndex === activeEntryIndex));
|
|
29
|
+
}
|
|
30
|
+
/** Returns one frontend-facing editable view model for the active Consent entry. */
|
|
31
|
+
getConsentViewModel() {
|
|
32
|
+
return buildConsentViewModel(this.getActiveEntry(), this.getDecision(), this.getActorsClassified(), this.getRolesClassified(), this.getPurposesClassified(), this.getTargetsClassified());
|
|
33
|
+
}
|
|
34
|
+
/** Applies one frontend-facing editable view model back into the active Consent entry. */
|
|
35
|
+
applyConsentViewModel(viewModel) {
|
|
36
|
+
this.setActiveEntryClaim(ClaimConsent.identifier, viewModel.identifier);
|
|
37
|
+
this.setActiveEntryClaim(ClaimConsent.subject, viewModel.subject);
|
|
38
|
+
this.setActiveEntryClaim(ClaimConsent.decision, viewModel.decision);
|
|
39
|
+
this.setActiveEntryClaimList(ClaimConsent.actorIdentifier, flattenClassifiedActors(viewModel.classifiedActors));
|
|
40
|
+
this.setSelectedRoles(flattenClassifiedRoles(viewModel.classifiedRoles));
|
|
41
|
+
this.setSelectedPurposes(viewModel.classifiedPurposes.map((purpose) => purpose.code));
|
|
42
|
+
const flattenedTargets = flattenClassifiedTargets(viewModel.classifiedTargets);
|
|
43
|
+
this.setSelectedCoreSections(flattenedTargets.coreSections);
|
|
44
|
+
this.setSelectedKindOfDocuments(flattenedTargets.kindOfDocuments);
|
|
45
|
+
this.setSelectedTypeOfServices(flattenedTargets.typeOfServices);
|
|
46
|
+
this.setSelectedSubjectMatterDomains(flattenedTargets.subjectMatterDomains);
|
|
47
|
+
this.setSelectedResourceTypes(flattenedTargets.resourceTypes);
|
|
48
|
+
return this;
|
|
49
|
+
}
|
|
50
|
+
/** Returns the canonical permit/deny decision from the active Consent entry. */
|
|
51
|
+
getDecision() {
|
|
52
|
+
return asTrimmedString(this.getActiveEntryClaim(ClaimConsent.decision));
|
|
53
|
+
}
|
|
54
|
+
/** @deprecated Use `getDecision()`. */
|
|
55
|
+
getPermit() {
|
|
56
|
+
return this.getDecision();
|
|
57
|
+
}
|
|
58
|
+
/** Returns target classification derived from the current consent claim contract. */
|
|
59
|
+
getTargetsClassified() {
|
|
60
|
+
return classifyConsentTargetsFromClaims({
|
|
61
|
+
...(this.getActiveEntry()?.resource?.meta?.claims || {}),
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
getCoreSectionOptions() {
|
|
65
|
+
return buildSectionCatalogOptions(HealthcareCanonicalSectionFamilies.CoreSection);
|
|
66
|
+
}
|
|
67
|
+
getCoreSectionCatalog() {
|
|
68
|
+
return getHealthcareSectionsByFamily(HealthcareCanonicalSectionFamilies.CoreSection);
|
|
69
|
+
}
|
|
70
|
+
getKindOfDocumentOptions() {
|
|
71
|
+
return buildSectionCatalogOptions(HealthcareCanonicalSectionFamilies.KindOfDocument);
|
|
72
|
+
}
|
|
73
|
+
getKindOfDocumentCatalog() {
|
|
74
|
+
return getHealthcareSectionsByFamily(HealthcareCanonicalSectionFamilies.KindOfDocument);
|
|
75
|
+
}
|
|
76
|
+
getTypeOfServiceOptions() {
|
|
77
|
+
return buildSectionCatalogOptions(HealthcareCanonicalSectionFamilies.TypeOfService);
|
|
78
|
+
}
|
|
79
|
+
getTypeOfServiceCatalog() {
|
|
80
|
+
return getHealthcareSectionsByFamily(HealthcareCanonicalSectionFamilies.TypeOfService);
|
|
81
|
+
}
|
|
82
|
+
getSubjectMatterDomainOptions() {
|
|
83
|
+
return buildSectionCatalogOptions(HealthcareCanonicalSectionFamilies.SubjectMatterDomain);
|
|
84
|
+
}
|
|
85
|
+
getSubjectMatterDomainCatalog() {
|
|
86
|
+
return getHealthcareSectionsByFamily(HealthcareCanonicalSectionFamilies.SubjectMatterDomain);
|
|
87
|
+
}
|
|
88
|
+
getResourceTypeOptions() {
|
|
89
|
+
return this.getSelectedResourceTypes().map((code) => buildClassifiedConsentTarget(ConsentEditorTargetKinds.ResourceType, code, [ConsentEditorScopeCodes.Read]));
|
|
90
|
+
}
|
|
91
|
+
getResourceTypeCatalog() {
|
|
92
|
+
return Object.values(ResourceTypesFhirR4).filter((resourceType) => resourceType !== ResourceTypesFhirR4.Bundle);
|
|
93
|
+
}
|
|
94
|
+
getAvailableProfessionalRolesBySector(sector) {
|
|
95
|
+
return getHealthcareProfessionalRolesBySector(sector);
|
|
96
|
+
}
|
|
97
|
+
getAvailableRelationshipRoles() {
|
|
98
|
+
return getHealthcareRolesByFamily(HealthcareRoleFamilies.PersonalRelationshipHl7);
|
|
99
|
+
}
|
|
100
|
+
getSelectedCoreSections() {
|
|
101
|
+
return this.getSelectedSectionCodesByFamily(ClaimConsent.action, HealthcareCanonicalSectionFamilies.CoreSection);
|
|
102
|
+
}
|
|
103
|
+
getSelectedKindOfDocuments() {
|
|
104
|
+
return splitCsv(this.getActiveEntryClaim(ClaimConsent.category));
|
|
105
|
+
}
|
|
106
|
+
getSelectedTypeOfServices() {
|
|
107
|
+
return this.getSelectedSectionCodesByFamily(ClaimConsent.action, HealthcareCanonicalSectionFamilies.TypeOfService);
|
|
108
|
+
}
|
|
109
|
+
getSelectedSubjectMatterDomains() {
|
|
110
|
+
return this.getSelectedSectionCodesByFamily(ClaimConsent.action, HealthcareCanonicalSectionFamilies.SubjectMatterDomain);
|
|
111
|
+
}
|
|
112
|
+
getSelectedResourceTypes() {
|
|
113
|
+
return splitCsv(this.getActiveEntryClaim(ClaimConsent.resourceType));
|
|
114
|
+
}
|
|
115
|
+
setSelectedCoreSections(codes) {
|
|
116
|
+
return this.setSelectedSectionCodesByFamily(ClaimConsent.action, HealthcareCanonicalSectionFamilies.CoreSection, codes);
|
|
117
|
+
}
|
|
118
|
+
setSelectedKindOfDocuments(codes) {
|
|
119
|
+
return this.setActiveEntryClaimList(ClaimConsent.category, codes);
|
|
120
|
+
}
|
|
121
|
+
setSelectedTypeOfServices(codes) {
|
|
122
|
+
return this.setSelectedSectionCodesByFamily(ClaimConsent.action, HealthcareCanonicalSectionFamilies.TypeOfService, codes);
|
|
123
|
+
}
|
|
124
|
+
setSelectedSubjectMatterDomains(codes) {
|
|
125
|
+
return this.setSelectedSectionCodesByFamily(ClaimConsent.action, HealthcareCanonicalSectionFamilies.SubjectMatterDomain, codes);
|
|
126
|
+
}
|
|
127
|
+
setSelectedResourceTypes(codes) {
|
|
128
|
+
return this.setActiveEntryClaimList(ClaimConsent.resourceType, codes);
|
|
129
|
+
}
|
|
130
|
+
addCoreSections(codes) {
|
|
131
|
+
return this.addSectionCodesByFamily(ClaimConsent.action, HealthcareCanonicalSectionFamilies.CoreSection, codes);
|
|
132
|
+
}
|
|
133
|
+
removeCoreSections(codes) {
|
|
134
|
+
return this.removeSectionCodesByFamily(ClaimConsent.action, HealthcareCanonicalSectionFamilies.CoreSection, codes);
|
|
135
|
+
}
|
|
136
|
+
addKindOfDocuments(codes) {
|
|
137
|
+
return this.addActiveEntryClaimList(ClaimConsent.category, codes);
|
|
138
|
+
}
|
|
139
|
+
removeKindOfDocuments(codes) {
|
|
140
|
+
return this.removeActiveEntryClaimList(ClaimConsent.category, codes);
|
|
141
|
+
}
|
|
142
|
+
addTypeOfServices(codes) {
|
|
143
|
+
return this.addSectionCodesByFamily(ClaimConsent.action, HealthcareCanonicalSectionFamilies.TypeOfService, codes);
|
|
144
|
+
}
|
|
145
|
+
removeTypeOfServices(codes) {
|
|
146
|
+
return this.removeSectionCodesByFamily(ClaimConsent.action, HealthcareCanonicalSectionFamilies.TypeOfService, codes);
|
|
147
|
+
}
|
|
148
|
+
addSubjectMatterDomains(codes) {
|
|
149
|
+
return this.addSectionCodesByFamily(ClaimConsent.action, HealthcareCanonicalSectionFamilies.SubjectMatterDomain, codes);
|
|
150
|
+
}
|
|
151
|
+
removeSubjectMatterDomains(codes) {
|
|
152
|
+
return this.removeSectionCodesByFamily(ClaimConsent.action, HealthcareCanonicalSectionFamilies.SubjectMatterDomain, codes);
|
|
153
|
+
}
|
|
154
|
+
addResourceTypes(codes) {
|
|
155
|
+
return this.addActiveEntryClaimList(ClaimConsent.resourceType, codes);
|
|
156
|
+
}
|
|
157
|
+
removeResourceTypes(codes) {
|
|
158
|
+
return this.removeActiveEntryClaimList(ClaimConsent.resourceType, codes);
|
|
159
|
+
}
|
|
160
|
+
getPurposesClassified() {
|
|
161
|
+
return classifyConsentPurposes(this.getSelectedPurposes());
|
|
162
|
+
}
|
|
163
|
+
getSelectedPurposes() {
|
|
164
|
+
return splitCsv(this.getActiveEntryClaim(ClaimConsent.purpose));
|
|
165
|
+
}
|
|
166
|
+
setSelectedPurposes(codes) {
|
|
167
|
+
return this.setActiveEntryClaimList(ClaimConsent.purpose, codes);
|
|
168
|
+
}
|
|
169
|
+
addPurposes(codes) {
|
|
170
|
+
return this.addActiveEntryClaimList(ClaimConsent.purpose, codes);
|
|
171
|
+
}
|
|
172
|
+
removePurposes(codes) {
|
|
173
|
+
return this.removeActiveEntryClaimList(ClaimConsent.purpose, codes);
|
|
174
|
+
}
|
|
175
|
+
getRolesClassified() {
|
|
176
|
+
return classifyConsentRoles(this.getSelectedRoles());
|
|
177
|
+
}
|
|
178
|
+
getSelectedRoles() {
|
|
179
|
+
return splitCsv(this.getActiveEntryClaim(ClaimConsent.actorRole));
|
|
180
|
+
}
|
|
181
|
+
setSelectedRoles(codes) {
|
|
182
|
+
return this.setActiveEntryClaimList(ClaimConsent.actorRole, codes);
|
|
183
|
+
}
|
|
184
|
+
addRoles(codes) {
|
|
185
|
+
return this.addActiveEntryClaimList(ClaimConsent.actorRole, codes);
|
|
186
|
+
}
|
|
187
|
+
removeRoles(codes) {
|
|
188
|
+
return this.removeActiveEntryClaimList(ClaimConsent.actorRole, codes);
|
|
189
|
+
}
|
|
190
|
+
getActorsClassified() {
|
|
191
|
+
const claims = {
|
|
192
|
+
...(this.getActiveEntry()?.resource?.meta?.claims || {}),
|
|
193
|
+
};
|
|
194
|
+
return classifyConsentActors(splitCsv(claims[ClaimConsent.actorIdentifier]), splitCsv(claims[ClaimConsent.actorRole])[0] || '');
|
|
195
|
+
}
|
|
196
|
+
getSelectedSectionCodesByFamily(claimKey, family) {
|
|
197
|
+
return splitCsv(this.getActiveEntryClaim(claimKey))
|
|
198
|
+
.filter((code) => getHealthcareSectionFamilyByCode(code) === family);
|
|
199
|
+
}
|
|
200
|
+
setSelectedSectionCodesByFamily(claimKey, family, codes) {
|
|
201
|
+
const preserved = splitCsv(this.getActiveEntryClaim(claimKey))
|
|
202
|
+
.filter((code) => getHealthcareSectionFamilyByCode(code) !== family);
|
|
203
|
+
return this.setActiveEntryClaimList(claimKey, [...preserved, ...codes]);
|
|
204
|
+
}
|
|
205
|
+
addSectionCodesByFamily(claimKey, family, codes) {
|
|
206
|
+
const next = [...this.getSelectedSectionCodesByFamily(claimKey, family), ...codes];
|
|
207
|
+
return this.setSelectedSectionCodesByFamily(claimKey, family, next);
|
|
208
|
+
}
|
|
209
|
+
removeSectionCodesByFamily(claimKey, family, codes) {
|
|
210
|
+
const codesToRemove = new Set(normalizeCsvValues(codes));
|
|
211
|
+
const next = this.getSelectedSectionCodesByFamily(claimKey, family)
|
|
212
|
+
.filter((code) => !codesToRemove.has(code));
|
|
213
|
+
return this.setSelectedSectionCodesByFamily(claimKey, family, next);
|
|
214
|
+
}
|
|
215
|
+
setActiveEntryClaimList(key, values) {
|
|
216
|
+
const normalized = normalizeCsvValues(values);
|
|
217
|
+
if (normalized.length === 0) {
|
|
218
|
+
return this.removeActiveEntryClaim(key);
|
|
219
|
+
}
|
|
220
|
+
return this.setActiveEntryClaim(key, normalized.join(CSV_SEPARATOR));
|
|
221
|
+
}
|
|
222
|
+
addActiveEntryClaimList(key, values) {
|
|
223
|
+
const next = normalizeCsvValues([
|
|
224
|
+
...splitCsv(this.getActiveEntryClaim(key)),
|
|
225
|
+
...values,
|
|
226
|
+
]);
|
|
227
|
+
return this.setActiveEntryClaimList(key, next);
|
|
228
|
+
}
|
|
229
|
+
removeActiveEntryClaimList(key, values) {
|
|
230
|
+
const valuesToRemove = new Set(normalizeCsvValues(values));
|
|
231
|
+
const next = splitCsv(this.getActiveEntryClaim(key))
|
|
232
|
+
.filter((value) => !valuesToRemove.has(value));
|
|
233
|
+
return this.setActiveEntryClaimList(key, next);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* High-level factory for consent-access editing.
|
|
238
|
+
*
|
|
239
|
+
* Prefer this name in onboarding docs when the developer intent is:
|
|
240
|
+
* "edit a Consent access bundle carried by a Communication".
|
|
241
|
+
*/
|
|
242
|
+
export function createConsentAccessEditor(options = {}) {
|
|
243
|
+
return new ConsentAccessEditor(options);
|
|
244
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { IDecodedDidcommPayload } from '../models/confidential-message';
|
|
2
|
+
export declare const CommunicationDidcommEntryTypes: Readonly<{
|
|
3
|
+
readonly AttachedBundle: "Communication-attached-bundle-v1.0";
|
|
4
|
+
}>;
|
|
5
|
+
/**
|
|
6
|
+
* Input contract for wrapping canonical Communication claims as one low-level
|
|
7
|
+
* DIDComm-style batch payload.
|
|
8
|
+
*/
|
|
9
|
+
export type BuildDidcommPayloadFromCommunicationClaimsInput = Readonly<{
|
|
10
|
+
communicationClaims: Record<string, unknown>;
|
|
11
|
+
iss: string;
|
|
12
|
+
aud: string;
|
|
13
|
+
jti: string;
|
|
14
|
+
thid: string;
|
|
15
|
+
entryType?: string;
|
|
16
|
+
}>;
|
|
17
|
+
/**
|
|
18
|
+
* Builds the low-level DIDComm-style batch payload that carries one FHIR-like
|
|
19
|
+
* `Communication` resource authored from canonical communication claims.
|
|
20
|
+
*
|
|
21
|
+
* This helper intentionally stays below actor-specific SDK facades so frontend,
|
|
22
|
+
* BFF, and GW-like tests can reuse the same wrapping contract.
|
|
23
|
+
*/
|
|
24
|
+
export declare function buildDidcommPayloadFromCommunicationClaims(input: BuildDidcommPayloadFromCommunicationClaimsInput): IDecodedDidcommPayload;
|
|
25
|
+
/**
|
|
26
|
+
* Reads canonical communication claims from the first `body.data[]` entry of
|
|
27
|
+
* one DIDComm-style payload.
|
|
28
|
+
*/
|
|
29
|
+
export declare function getFirstCommunicationClaimsFromDidcommPayload(payload: IDecodedDidcommPayload): Record<string, unknown>;
|
|
30
|
+
/**
|
|
31
|
+
* Decodes the attached bundle carried in `Communication.content-attachment-data`.
|
|
32
|
+
*/
|
|
33
|
+
export declare function decodeAttachedBundleFromCommunicationClaims(communicationClaims: Record<string, unknown>): Record<string, unknown>;
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
// Copyright 2026 Conectate Soluciones y Aplicaciones SL under the Apache License, Version 2.0.
|
|
2
|
+
import { CommunicationClaim } from '../models/interoperable-claims/communication-claims.js';
|
|
3
|
+
import { transformCommunicationClaimsToResourceFhirR4 } from './communication-fhir-r4.js';
|
|
4
|
+
export const CommunicationDidcommEntryTypes = Object.freeze({
|
|
5
|
+
AttachedBundle: 'Communication-attached-bundle-v1.0',
|
|
6
|
+
});
|
|
7
|
+
function clone(value) {
|
|
8
|
+
return JSON.parse(JSON.stringify(value));
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Builds the low-level DIDComm-style batch payload that carries one FHIR-like
|
|
12
|
+
* `Communication` resource authored from canonical communication claims.
|
|
13
|
+
*
|
|
14
|
+
* This helper intentionally stays below actor-specific SDK facades so frontend,
|
|
15
|
+
* BFF, and GW-like tests can reuse the same wrapping contract.
|
|
16
|
+
*/
|
|
17
|
+
export function buildDidcommPayloadFromCommunicationClaims(input) {
|
|
18
|
+
const claims = clone(input.communicationClaims);
|
|
19
|
+
const transformed = transformCommunicationClaimsToResourceFhirR4([claims], {
|
|
20
|
+
mode: 'strict',
|
|
21
|
+
});
|
|
22
|
+
const communicationResource = transformed.resources[0] || {};
|
|
23
|
+
return {
|
|
24
|
+
iss: String(input.iss || '').trim(),
|
|
25
|
+
aud: String(input.aud || '').trim(),
|
|
26
|
+
jti: String(input.jti || '').trim(),
|
|
27
|
+
thid: String(input.thid || '').trim(),
|
|
28
|
+
type: CommunicationDidcommEntryTypes.AttachedBundle,
|
|
29
|
+
body: {
|
|
30
|
+
data: [
|
|
31
|
+
{
|
|
32
|
+
id: String(claims[CommunicationClaim.Identifier] || input.jti || '').trim(),
|
|
33
|
+
type: String(input.entryType || CommunicationDidcommEntryTypes.AttachedBundle).trim(),
|
|
34
|
+
meta: {
|
|
35
|
+
claims,
|
|
36
|
+
},
|
|
37
|
+
resource: communicationResource,
|
|
38
|
+
},
|
|
39
|
+
],
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Reads canonical communication claims from the first `body.data[]` entry of
|
|
45
|
+
* one DIDComm-style payload.
|
|
46
|
+
*/
|
|
47
|
+
export function getFirstCommunicationClaimsFromDidcommPayload(payload) {
|
|
48
|
+
const first = Array.isArray(payload?.body?.data) ? payload.body.data[0] : undefined;
|
|
49
|
+
const metaClaims = first?.meta && typeof first.meta === 'object'
|
|
50
|
+
? first.meta['claims']
|
|
51
|
+
: undefined;
|
|
52
|
+
if (metaClaims && typeof metaClaims === 'object') {
|
|
53
|
+
return clone(metaClaims);
|
|
54
|
+
}
|
|
55
|
+
const resource = first?.resource && typeof first.resource === 'object'
|
|
56
|
+
? first.resource
|
|
57
|
+
: {};
|
|
58
|
+
const meta = resource.meta && typeof resource.meta === 'object'
|
|
59
|
+
? resource.meta
|
|
60
|
+
: {};
|
|
61
|
+
const claims = meta.claims && typeof meta.claims === 'object'
|
|
62
|
+
? meta.claims
|
|
63
|
+
: {};
|
|
64
|
+
return clone(claims);
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Decodes the attached bundle carried in `Communication.content-attachment-data`.
|
|
68
|
+
*/
|
|
69
|
+
export function decodeAttachedBundleFromCommunicationClaims(communicationClaims) {
|
|
70
|
+
const encoded = String(communicationClaims[CommunicationClaim.ContentAttachmentData] || '').trim();
|
|
71
|
+
if (!encoded) {
|
|
72
|
+
throw new Error(`decodeAttachedBundleFromCommunicationClaims requires ${CommunicationClaim.ContentAttachmentData}.`);
|
|
73
|
+
}
|
|
74
|
+
return JSON.parse(Buffer.from(encoded, 'base64').toString('utf8'));
|
|
75
|
+
}
|
|
@@ -4,6 +4,8 @@ import type { EvidenceObjectDLT } from '../models/oidc4ida.evidence.model.js';
|
|
|
4
4
|
*
|
|
5
5
|
* Current shared rule:
|
|
6
6
|
* - `z...` multibase base58 references are already public and stable
|
|
7
|
+
* - `sha3-384:...` references are already blockchain-safe and must pass
|
|
8
|
+
* through unchanged
|
|
7
9
|
* - any other identifier-like value is SHA3-384 hashed before persistence
|
|
8
10
|
*/
|
|
9
11
|
export declare function sanitizeBlockchainReference(value: unknown): string | undefined;
|
|
@@ -5,6 +5,8 @@ const SHA3_384_PREFIX = 'sha3-384:';
|
|
|
5
5
|
*
|
|
6
6
|
* Current shared rule:
|
|
7
7
|
* - `z...` multibase base58 references are already public and stable
|
|
8
|
+
* - `sha3-384:...` references are already blockchain-safe and must pass
|
|
9
|
+
* through unchanged
|
|
8
10
|
* - any other identifier-like value is SHA3-384 hashed before persistence
|
|
9
11
|
*/
|
|
10
12
|
export function sanitizeBlockchainReference(value) {
|
|
@@ -13,6 +15,8 @@ export function sanitizeBlockchainReference(value) {
|
|
|
13
15
|
return undefined;
|
|
14
16
|
if (/^z[1-9A-HJ-NP-Za-km-z]+$/.test(normalized))
|
|
15
17
|
return normalized;
|
|
18
|
+
if (/^sha3-384:[a-f0-9]{96}$/i.test(normalized))
|
|
19
|
+
return normalized;
|
|
16
20
|
return `${SHA3_384_PREFIX}${createHash('sha3-384').update(normalized, 'utf8').digest('hex')}`;
|
|
17
21
|
}
|
|
18
22
|
/**
|
package/dist/utils/index.d.ts
CHANGED
|
@@ -42,6 +42,9 @@ export * from './communication-participant-search';
|
|
|
42
42
|
export * from './communication-participant-search-test-data';
|
|
43
43
|
export * from './communication-retention-policy';
|
|
44
44
|
export * from './communication-attached-bundle-session';
|
|
45
|
+
export * from './communication-consent-access-editor';
|
|
46
|
+
export * from './bundle-didcomm-payload';
|
|
47
|
+
export * from './communication-didcomm-payload';
|
|
45
48
|
export * from './confidential-storage-persistence';
|
|
46
49
|
export * from './confidential-storage-test-data';
|
|
47
50
|
export * from './permission-templates';
|
|
@@ -54,9 +57,11 @@ export * from './fhir-validator';
|
|
|
54
57
|
export * from './family-registration-test-data';
|
|
55
58
|
export * from './individual-form-pdf';
|
|
56
59
|
export * from './individual-organization-claims';
|
|
60
|
+
export * from './inter-tenant-access-contract';
|
|
57
61
|
export * from './legal-organization-onboarding-editor';
|
|
58
62
|
export * from './organization-lifecycle';
|
|
59
63
|
export * from './organization-did-binding';
|
|
64
|
+
export * from './organization-authorization-urn';
|
|
60
65
|
export * from './individual-organization-lifecycle';
|
|
61
66
|
export * from './individual-onboarding-editor';
|
|
62
67
|
export * from './individual-onboarding-document-reference';
|
|
@@ -89,3 +94,8 @@ export * from './service-act-reasons';
|
|
|
89
94
|
export * from './same-as';
|
|
90
95
|
export * from './activation-request';
|
|
91
96
|
export * from './vp-token';
|
|
97
|
+
export * from './wallet-mem';
|
|
98
|
+
export * from './wallet-memory-queue';
|
|
99
|
+
export * from './profile-outbox-memory-repository';
|
|
100
|
+
export * from './backend-message-manager-mem';
|
|
101
|
+
export * from './profile-manager-mem';
|
package/dist/utils/index.js
CHANGED
|
@@ -42,6 +42,9 @@ export * from './communication-participant-search.js';
|
|
|
42
42
|
export * from './communication-participant-search-test-data.js';
|
|
43
43
|
export * from './communication-retention-policy.js';
|
|
44
44
|
export * from './communication-attached-bundle-session.js';
|
|
45
|
+
export * from './communication-consent-access-editor.js';
|
|
46
|
+
export * from './bundle-didcomm-payload.js';
|
|
47
|
+
export * from './communication-didcomm-payload.js';
|
|
45
48
|
export * from './confidential-storage-persistence.js';
|
|
46
49
|
export * from './confidential-storage-test-data.js';
|
|
47
50
|
export * from './permission-templates.js';
|
|
@@ -54,9 +57,11 @@ export * from './fhir-validator.js';
|
|
|
54
57
|
export * from './family-registration-test-data.js';
|
|
55
58
|
export * from './individual-form-pdf.js';
|
|
56
59
|
export * from './individual-organization-claims.js';
|
|
60
|
+
export * from './inter-tenant-access-contract.js';
|
|
57
61
|
export * from './legal-organization-onboarding-editor.js';
|
|
58
62
|
export * from './organization-lifecycle.js';
|
|
59
63
|
export * from './organization-did-binding.js';
|
|
64
|
+
export * from './organization-authorization-urn.js';
|
|
60
65
|
export * from './individual-organization-lifecycle.js';
|
|
61
66
|
export * from './individual-onboarding-editor.js';
|
|
62
67
|
export * from './individual-onboarding-document-reference.js';
|
|
@@ -89,3 +94,8 @@ export * from './service-act-reasons.js';
|
|
|
89
94
|
export * from './same-as.js';
|
|
90
95
|
export * from './activation-request.js';
|
|
91
96
|
export * from './vp-token.js';
|
|
97
|
+
export * from './wallet-mem.js';
|
|
98
|
+
export * from './wallet-memory-queue.js';
|
|
99
|
+
export * from './profile-outbox-memory-repository.js';
|
|
100
|
+
export * from './backend-message-manager-mem.js';
|
|
101
|
+
export * from './profile-manager-mem.js';
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { InterTenantAccessContractClaims, InterTenantContractAuthorizationConsentCriteria, InterTenantAccessContractMatchCriteria, InterTenantAccessContractSummary } from '../models/inter-tenant-access-contract';
|
|
2
|
+
import type { VerifiableCredentialV2 } from '../models/verifiable-credential';
|
|
3
|
+
type ContractLike = Record<string, any>;
|
|
4
|
+
export declare function buildInterTenantAccessContractResource(claims: InterTenantAccessContractClaims): ContractLike;
|
|
5
|
+
export declare function buildInterTenantAccessContractCredential(input: Readonly<{
|
|
6
|
+
claims: InterTenantAccessContractClaims;
|
|
7
|
+
issuer: string;
|
|
8
|
+
validFrom: string;
|
|
9
|
+
validUntil?: string;
|
|
10
|
+
additionalCredential?: Record<string, unknown>;
|
|
11
|
+
}>): VerifiableCredentialV2;
|
|
12
|
+
export declare function summarizeInterTenantAccessContract(credential: unknown): InterTenantAccessContractSummary | undefined;
|
|
13
|
+
export declare function isInterTenantAccessContractActive(summary: InterTenantAccessContractSummary | undefined, options?: Readonly<{
|
|
14
|
+
now?: string | Date;
|
|
15
|
+
}>): boolean;
|
|
16
|
+
export declare function matchesInterTenantAccessContract(summary: InterTenantAccessContractSummary | undefined, criteria: InterTenantAccessContractMatchCriteria): boolean;
|
|
17
|
+
export declare function getMatchingInterTenantAccessContractFromVpToken(vpToken: string, criteria: InterTenantAccessContractMatchCriteria): Record<string, unknown> | undefined;
|
|
18
|
+
/**
|
|
19
|
+
* Returns the public blockchain-safe reference that a reused consent-style
|
|
20
|
+
* authorization rule should store under `Consent.source-reference` when it
|
|
21
|
+
* delegates use of one inter-tenant contract VC to an employee/researcher.
|
|
22
|
+
*
|
|
23
|
+
* Source-of-truth order:
|
|
24
|
+
* - VC `id`
|
|
25
|
+
* - FHIR `Contract.identifier`
|
|
26
|
+
*
|
|
27
|
+
* In both cases the reference is normalized through the same blockchain-safe
|
|
28
|
+
* sanitization rule already used by consent-access assets.
|
|
29
|
+
*/
|
|
30
|
+
export declare function getInterTenantAccessContractBlockchainReference(credential: unknown): string | undefined;
|
|
31
|
+
/**
|
|
32
|
+
* Evaluates one consent-style rule reused as an organization-to-employee
|
|
33
|
+
* delegation for inter-tenant contract usage.
|
|
34
|
+
*
|
|
35
|
+
* Shared semantic contract:
|
|
36
|
+
* - `Consent.subject` = consumer organization DID
|
|
37
|
+
* - `Consent.actor-identifier` = delegated employee/researcher identifier
|
|
38
|
+
* - `Consent.action` = allowed capabilities/scopes
|
|
39
|
+
* - `Consent.purpose` = allowed purpose
|
|
40
|
+
* - `Consent.source-reference` = blockchain-safe hash/reference of the
|
|
41
|
+
* underlying contract VC
|
|
42
|
+
*/
|
|
43
|
+
export declare function matchesInterTenantContractAuthorizationConsentRule(rule: Record<string, unknown>, contractCredential: unknown, criteria: InterTenantContractAuthorizationConsentCriteria): boolean;
|
|
44
|
+
export {};
|