gdc-common-utils-ts 2.5.16 → 2.5.19
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/dist/examples/inter-tenant-access-contract.d.ts +2 -2
- package/dist/examples/inter-tenant-access-contract.js +16 -2
- package/dist/examples/legal-organization-verification-transaction.d.ts +1 -0
- package/dist/examples/legal-organization-verification-transaction.js +10 -4
- package/dist/examples/lifecycle.d.ts +6 -0
- package/dist/examples/lifecycle.js +3 -0
- package/dist/models/inter-tenant-access-contract.d.ts +14 -6
- package/dist/models/inter-tenant-access-contract.js +6 -6
- package/dist/utils/activation-policy.d.ts +25 -0
- package/dist/utils/activation-policy.js +42 -8
- package/dist/utils/consent-blockchain-rules.js +1 -0
- package/dist/utils/consent-duplicate-rules.d.ts +4 -1
- package/dist/utils/consent-duplicate-rules.js +5 -1
- package/dist/utils/inter-tenant-access-contract.d.ts +11 -0
- package/dist/utils/inter-tenant-access-contract.js +48 -12
- package/dist/utils/legal-organization-onboarding-editor.d.ts +6 -0
- package/dist/utils/legal-organization-onboarding-editor.js +19 -0
- package/dist/utils/organization-lifecycle.d.ts +4 -0
- package/dist/utils/organization-lifecycle.js +14 -0
- package/package.json +1 -1
|
@@ -37,8 +37,8 @@ export declare const EXAMPLE_INTER_TENANT_ACCESS_CONTRACT_CLAIMS: Readonly<{
|
|
|
37
37
|
readonly "Contract.applies-end": "2027-06-29T00:00:00.000Z";
|
|
38
38
|
readonly "Contract.provider-organization": "did:web:api.acme.org";
|
|
39
39
|
readonly "Contract.consumer-organization": "did:web:api.lab.org";
|
|
40
|
-
readonly "Contract.provider-
|
|
41
|
-
readonly "Contract.consumer-
|
|
40
|
+
readonly "Contract.provider-authorized-signatory": "did:web:people.acme.org:controllers:primary";
|
|
41
|
+
readonly "Contract.consumer-authorized-signatory": "did:web:people.lab.org:controllers:primary";
|
|
42
42
|
readonly "Contract.security-label": "organization/Composition.rs";
|
|
43
43
|
readonly "Contract.term-type": "HRESCH";
|
|
44
44
|
readonly "Contract.instantiates-uri": "https://portal.example.org/files/contracts/inter-tenant-contract-acme-lab-001.pdf";
|
|
@@ -47,8 +47,8 @@ export const EXAMPLE_INTER_TENANT_ACCESS_CONTRACT_CLAIMS = Object.freeze({
|
|
|
47
47
|
[ClaimInterTenantAccessContract.appliesEnd]: EXAMPLE_INTER_TENANT_ACCESS_CONTRACT_VALID_UNTIL,
|
|
48
48
|
[ClaimInterTenantAccessContract.providerOrganization]: EXAMPLE_API_ORGANIZATION_DID,
|
|
49
49
|
[ClaimInterTenantAccessContract.consumerOrganization]: EXAMPLE_RESEARCH_API_ORGANIZATION_DID,
|
|
50
|
-
[ClaimInterTenantAccessContract.
|
|
51
|
-
[ClaimInterTenantAccessContract.
|
|
50
|
+
[ClaimInterTenantAccessContract.providerAuthorizedSignatory]: EXAMPLE_CONTROLLER_DID,
|
|
51
|
+
[ClaimInterTenantAccessContract.consumerAuthorizedSignatory]: EXAMPLE_RESEARCH_CONTROLLER_DID,
|
|
52
52
|
[ClaimInterTenantAccessContract.capability]: EXAMPLE_INTER_TENANT_ACCESS_CONTRACT_SCOPE,
|
|
53
53
|
[ClaimInterTenantAccessContract.purpose]: EXAMPLE_INTER_TENANT_ACCESS_CONTRACT_PURPOSE,
|
|
54
54
|
[ClaimInterTenantAccessContract.instantiatesUri]: EXAMPLE_INTER_TENANT_ACCESS_CONTRACT_AGREEMENT_PDF_URL,
|
|
@@ -61,6 +61,20 @@ export const EXAMPLE_INTER_TENANT_ACCESS_CONTRACT_CREDENTIAL = Object.freeze(bui
|
|
|
61
61
|
validUntil: EXAMPLE_INTER_TENANT_ACCESS_CONTRACT_VALID_UNTIL,
|
|
62
62
|
additionalCredential: {
|
|
63
63
|
id: EXAMPLE_INTER_TENANT_ACCESS_CONTRACT_ID,
|
|
64
|
+
proof: [
|
|
65
|
+
{
|
|
66
|
+
type: 'JsonWebSignature2020',
|
|
67
|
+
proofPurpose: 'contractAgreement',
|
|
68
|
+
verificationMethod: `${EXAMPLE_CONTROLLER_DID}#contract-agreement`,
|
|
69
|
+
jws: 'provider-authorized-signatory-proof',
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
type: 'JsonWebSignature2020',
|
|
73
|
+
proofPurpose: 'contractAgreement',
|
|
74
|
+
verificationMethod: `${EXAMPLE_RESEARCH_CONTROLLER_DID}#contract-agreement`,
|
|
75
|
+
jws: 'consumer-authorized-signatory-proof',
|
|
76
|
+
},
|
|
77
|
+
],
|
|
64
78
|
},
|
|
65
79
|
}));
|
|
66
80
|
export const EXAMPLE_INTER_TENANT_ACCESS_CONTRACT_CONTEXT = Object.freeze({
|
|
@@ -30,6 +30,15 @@ const exampleControllerBinding = {
|
|
|
30
30
|
}
|
|
31
31
|
: {}),
|
|
32
32
|
};
|
|
33
|
+
/** Canonical capabilities reused by organization-onboarding editor tests. */
|
|
34
|
+
const exampleLegalOrganizationServiceType = serializeServiceCapabilityTokens([
|
|
35
|
+
ServiceCapability.IndexProvider,
|
|
36
|
+
ServiceCapability.DigitalTwinReader,
|
|
37
|
+
]);
|
|
38
|
+
if (!exampleLegalOrganizationServiceType) {
|
|
39
|
+
throw new Error('Canonical legal-organization example capabilities must not be empty.');
|
|
40
|
+
}
|
|
41
|
+
export const EXAMPLE_LEGAL_ORGANIZATION_SERVICE_TYPE = exampleLegalOrganizationServiceType;
|
|
33
42
|
export const EXAMPLE_LEGAL_ORGANIZATION_VERIFICATION_TRANSACTION_BUNDLE = buildLegalOrganizationVerificationTransactionBundle({
|
|
34
43
|
claims: {
|
|
35
44
|
'@context': 'org.schema',
|
|
@@ -42,10 +51,7 @@ export const EXAMPLE_LEGAL_ORGANIZATION_VERIFICATION_TRANSACTION_BUNDLE = buildL
|
|
|
42
51
|
[ClaimsServiceSchemaorg.category]: EXAMPLE_SECTOR,
|
|
43
52
|
[ClaimsServiceSchemaorg.identifier]: EXAMPLE_TENANT_SERVICE_DID,
|
|
44
53
|
[ClaimsServiceSchemaorg.url]: `https://operator.example.net/acme/cds-${String(EXAMPLE_JURISDICTION).toLowerCase()}/v1/${EXAMPLE_SECTOR}`,
|
|
45
|
-
[ClaimsServiceSchemaorg.serviceType]:
|
|
46
|
-
ServiceCapability.IndexProvider,
|
|
47
|
-
ServiceCapability.DigitalTwinReader,
|
|
48
|
-
]),
|
|
54
|
+
[ClaimsServiceSchemaorg.serviceType]: EXAMPLE_LEGAL_ORGANIZATION_SERVICE_TYPE,
|
|
49
55
|
},
|
|
50
56
|
controller: exampleControllerBinding,
|
|
51
57
|
organization: {
|
|
@@ -109,6 +109,7 @@ export declare const EXAMPLE_TENANT_ENABLE_MESSAGE: {
|
|
|
109
109
|
};
|
|
110
110
|
readonly claims: {
|
|
111
111
|
readonly '@context': "org.schema";
|
|
112
|
+
readonly "org.schema.Organization.identifier.additionalType": "taxID";
|
|
112
113
|
readonly "org.schema.Organization.identifier.value": "{{tenantTaxId}}";
|
|
113
114
|
readonly "org.schema.Organization.taxID": "{{tenantTaxId}}";
|
|
114
115
|
readonly "org.schema.Organization.identifier": "{{tenantDid}}";
|
|
@@ -124,6 +125,7 @@ export declare const EXAMPLE_TENANT_DISABLE_MESSAGE: {
|
|
|
124
125
|
};
|
|
125
126
|
readonly claims: {
|
|
126
127
|
readonly '@context': "org.schema";
|
|
128
|
+
readonly "org.schema.Organization.identifier.additionalType": "taxID";
|
|
127
129
|
readonly "org.schema.Organization.identifier.value": "{{tenantTaxId}}";
|
|
128
130
|
readonly "org.schema.Organization.taxID": "{{tenantTaxId}}";
|
|
129
131
|
readonly "org.schema.Organization.identifier": "{{tenantDid}}";
|
|
@@ -144,6 +146,7 @@ export declare const EXAMPLE_TENANT_DELETE_MESSAGE: {
|
|
|
144
146
|
};
|
|
145
147
|
readonly claims: {
|
|
146
148
|
readonly '@context': "org.schema";
|
|
149
|
+
readonly "org.schema.Organization.identifier.additionalType": "taxID";
|
|
147
150
|
readonly "org.schema.Organization.identifier.value": "{{tenantTaxId}}";
|
|
148
151
|
readonly "org.schema.Organization.taxID": "{{tenantTaxId}}";
|
|
149
152
|
readonly "org.schema.Organization.identifier": "{{tenantDid}}";
|
|
@@ -391,6 +394,7 @@ export declare const EXAMPLE_LIFECYCLE_REFERENCE: {
|
|
|
391
394
|
};
|
|
392
395
|
readonly claims: {
|
|
393
396
|
readonly '@context': "org.schema";
|
|
397
|
+
readonly "org.schema.Organization.identifier.additionalType": "taxID";
|
|
394
398
|
readonly "org.schema.Organization.identifier.value": "{{tenantTaxId}}";
|
|
395
399
|
readonly "org.schema.Organization.taxID": "{{tenantTaxId}}";
|
|
396
400
|
readonly "org.schema.Organization.identifier": "{{tenantDid}}";
|
|
@@ -406,6 +410,7 @@ export declare const EXAMPLE_LIFECYCLE_REFERENCE: {
|
|
|
406
410
|
};
|
|
407
411
|
readonly claims: {
|
|
408
412
|
readonly '@context': "org.schema";
|
|
413
|
+
readonly "org.schema.Organization.identifier.additionalType": "taxID";
|
|
409
414
|
readonly "org.schema.Organization.identifier.value": "{{tenantTaxId}}";
|
|
410
415
|
readonly "org.schema.Organization.taxID": "{{tenantTaxId}}";
|
|
411
416
|
readonly "org.schema.Organization.identifier": "{{tenantDid}}";
|
|
@@ -426,6 +431,7 @@ export declare const EXAMPLE_LIFECYCLE_REFERENCE: {
|
|
|
426
431
|
};
|
|
427
432
|
readonly claims: {
|
|
428
433
|
readonly '@context': "org.schema";
|
|
434
|
+
readonly "org.schema.Organization.identifier.additionalType": "taxID";
|
|
429
435
|
readonly "org.schema.Organization.identifier.value": "{{tenantTaxId}}";
|
|
430
436
|
readonly "org.schema.Organization.taxID": "{{tenantTaxId}}";
|
|
431
437
|
readonly "org.schema.Organization.identifier": "{{tenantDid}}";
|
|
@@ -117,6 +117,7 @@ export const EXAMPLE_TENANT_ENABLE_MESSAGE = {
|
|
|
117
117
|
},
|
|
118
118
|
claims: {
|
|
119
119
|
'@context': 'org.schema',
|
|
120
|
+
[ClaimsOrganizationSchemaorg.identifierType]: 'taxID',
|
|
120
121
|
[ClaimsOrganizationSchemaorg.identifierValue]: EXAMPLE_LIFECYCLE_PLACEHOLDERS.tenantTaxId,
|
|
121
122
|
[ClaimsOrganizationSchemaorg.taxId]: EXAMPLE_LIFECYCLE_PLACEHOLDERS.tenantTaxId,
|
|
122
123
|
[ClaimsOrganizationSchemaorg.identifier]: EXAMPLE_LIFECYCLE_PLACEHOLDERS.tenantDid,
|
|
@@ -132,6 +133,7 @@ export const EXAMPLE_TENANT_DISABLE_MESSAGE = {
|
|
|
132
133
|
},
|
|
133
134
|
claims: {
|
|
134
135
|
'@context': 'org.schema',
|
|
136
|
+
[ClaimsOrganizationSchemaorg.identifierType]: 'taxID',
|
|
135
137
|
[ClaimsOrganizationSchemaorg.identifierValue]: EXAMPLE_LIFECYCLE_PLACEHOLDERS.tenantTaxId,
|
|
136
138
|
[ClaimsOrganizationSchemaorg.taxId]: EXAMPLE_LIFECYCLE_PLACEHOLDERS.tenantTaxId,
|
|
137
139
|
[ClaimsOrganizationSchemaorg.identifier]: EXAMPLE_LIFECYCLE_PLACEHOLDERS.tenantDid,
|
|
@@ -152,6 +154,7 @@ export const EXAMPLE_TENANT_DELETE_MESSAGE = {
|
|
|
152
154
|
},
|
|
153
155
|
claims: {
|
|
154
156
|
'@context': 'org.schema',
|
|
157
|
+
[ClaimsOrganizationSchemaorg.identifierType]: 'taxID',
|
|
155
158
|
[ClaimsOrganizationSchemaorg.identifierValue]: EXAMPLE_LIFECYCLE_PLACEHOLDERS.tenantTaxId,
|
|
156
159
|
[ClaimsOrganizationSchemaorg.taxId]: EXAMPLE_LIFECYCLE_PLACEHOLDERS.tenantTaxId,
|
|
157
160
|
[ClaimsOrganizationSchemaorg.identifier]: EXAMPLE_LIFECYCLE_PLACEHOLDERS.tenantDid,
|
|
@@ -44,13 +44,13 @@ export declare enum ClaimInterTenantAccessContract {
|
|
|
44
44
|
* - in the current example this is `did:web:api.lab.org`
|
|
45
45
|
*/
|
|
46
46
|
consumerOrganization = "Contract.consumer-organization",
|
|
47
|
-
/**
|
|
48
|
-
|
|
49
|
-
|
|
47
|
+
/** DID of the person legally authorized to sign for the provider. */
|
|
48
|
+
providerAuthorizedSignatory = "Contract.provider-authorized-signatory",
|
|
49
|
+
/** DID of the person legally authorized to sign for the consumer. */
|
|
50
|
+
consumerAuthorizedSignatory = "Contract.consumer-authorized-signatory",
|
|
51
|
+
/** @deprecated Read-only compatibility alias. Technical control is not legal signing authority. */
|
|
50
52
|
providerController = "Contract.provider-controller",
|
|
51
|
-
/**
|
|
52
|
-
* DID of the controller who signed on behalf of the consumer organization.
|
|
53
|
-
*/
|
|
53
|
+
/** @deprecated Read-only compatibility alias. Technical control is not legal signing authority. */
|
|
54
54
|
consumerController = "Contract.consumer-controller",
|
|
55
55
|
/**
|
|
56
56
|
* Allowed operational capability, expressed with the same vocabulary used by
|
|
@@ -89,8 +89,14 @@ export type InterTenantAccessContractSummary = Readonly<{
|
|
|
89
89
|
appliesEnd?: string;
|
|
90
90
|
providerOrganizationDid?: string;
|
|
91
91
|
consumerOrganizationDid?: string;
|
|
92
|
+
providerAuthorizedSignatoryDid?: string;
|
|
93
|
+
consumerAuthorizedSignatoryDid?: string;
|
|
94
|
+
/** @deprecated Use providerAuthorizedSignatoryDid. */
|
|
92
95
|
providerControllerDid?: string;
|
|
96
|
+
/** @deprecated Use consumerAuthorizedSignatoryDid. */
|
|
93
97
|
consumerControllerDid?: string;
|
|
98
|
+
hasProviderContractAgreementProof: boolean;
|
|
99
|
+
hasConsumerContractAgreementProof: boolean;
|
|
94
100
|
capabilities: readonly string[];
|
|
95
101
|
purposes: readonly string[];
|
|
96
102
|
}>;
|
|
@@ -100,6 +106,8 @@ export type InterTenantAccessContractMatchCriteria = Readonly<{
|
|
|
100
106
|
requiredCapabilities?: readonly string[];
|
|
101
107
|
purpose?: string;
|
|
102
108
|
now?: string | Date;
|
|
109
|
+
/** Defaults to true for access-token authorization. */
|
|
110
|
+
requireBilateralContractAgreementProofs?: boolean;
|
|
103
111
|
}>;
|
|
104
112
|
export type InterTenantContractAuthorizationConsentCriteria = Readonly<{
|
|
105
113
|
consumerOrganizationDid: string;
|
|
@@ -46,13 +46,13 @@ export var ClaimInterTenantAccessContract;
|
|
|
46
46
|
* - in the current example this is `did:web:api.lab.org`
|
|
47
47
|
*/
|
|
48
48
|
ClaimInterTenantAccessContract["consumerOrganization"] = "Contract.consumer-organization";
|
|
49
|
-
/**
|
|
50
|
-
|
|
51
|
-
|
|
49
|
+
/** DID of the person legally authorized to sign for the provider. */
|
|
50
|
+
ClaimInterTenantAccessContract["providerAuthorizedSignatory"] = "Contract.provider-authorized-signatory";
|
|
51
|
+
/** DID of the person legally authorized to sign for the consumer. */
|
|
52
|
+
ClaimInterTenantAccessContract["consumerAuthorizedSignatory"] = "Contract.consumer-authorized-signatory";
|
|
53
|
+
/** @deprecated Read-only compatibility alias. Technical control is not legal signing authority. */
|
|
52
54
|
ClaimInterTenantAccessContract["providerController"] = "Contract.provider-controller";
|
|
53
|
-
/**
|
|
54
|
-
* DID of the controller who signed on behalf of the consumer organization.
|
|
55
|
-
*/
|
|
55
|
+
/** @deprecated Read-only compatibility alias. Technical control is not legal signing authority. */
|
|
56
56
|
ClaimInterTenantAccessContract["consumerController"] = "Contract.consumer-controller";
|
|
57
57
|
/**
|
|
58
58
|
* Allowed operational capability, expressed with the same vocabulary used by
|
|
@@ -8,6 +8,11 @@ export type ActivationServiceAuthorizationPolicyError = {
|
|
|
8
8
|
code: ActivationServiceAuthorizationPolicyErrorCode;
|
|
9
9
|
message: string;
|
|
10
10
|
};
|
|
11
|
+
/** Typed legal identifier used to bind one organization across credentials and lifecycle commands. */
|
|
12
|
+
export type LegalOrganizationIdentifier = Readonly<{
|
|
13
|
+
type: string;
|
|
14
|
+
value: string;
|
|
15
|
+
}>;
|
|
11
16
|
/**
|
|
12
17
|
* Extracts `credentialSubject` from a VC-like object.
|
|
13
18
|
*
|
|
@@ -20,6 +25,26 @@ export declare function extractCredentialSubject(credential: unknown): Record<st
|
|
|
20
25
|
* @param value Raw tax identifier value.
|
|
21
26
|
*/
|
|
22
27
|
export declare function normalizeTaxIdentifier(value: unknown): string | undefined;
|
|
28
|
+
/**
|
|
29
|
+
* Normalizes a typed organization identifier for equality checks without
|
|
30
|
+
* changing the canonical value stored in credentials or tenant records.
|
|
31
|
+
*/
|
|
32
|
+
export declare function normalizeLegalOrganizationIdentifier(identifier: Readonly<{
|
|
33
|
+
type?: unknown;
|
|
34
|
+
value?: unknown;
|
|
35
|
+
}> | undefined): LegalOrganizationIdentifier | undefined;
|
|
36
|
+
/** Extracts the typed legal identifier from an organization credential subject. */
|
|
37
|
+
export declare function extractOrganizationLegalIdentifier(organizationCredential: unknown): LegalOrganizationIdentifier | undefined;
|
|
38
|
+
/** Extracts the typed organization identifier from a representative `memberOf` binding. */
|
|
39
|
+
export declare function extractRepresentativeMemberOfLegalIdentifier(representativeCredential: unknown): LegalOrganizationIdentifier | undefined;
|
|
40
|
+
/** Compares typed legal identifiers without discarding punctuation from their values. */
|
|
41
|
+
export declare function legalOrganizationIdentifiersMatch(left: Readonly<{
|
|
42
|
+
type?: unknown;
|
|
43
|
+
value?: unknown;
|
|
44
|
+
}> | undefined, right: Readonly<{
|
|
45
|
+
type?: unknown;
|
|
46
|
+
value?: unknown;
|
|
47
|
+
}> | undefined): boolean;
|
|
23
48
|
/**
|
|
24
49
|
* Extracts an organization tax id from a VC-like organization credential.
|
|
25
50
|
*
|
|
@@ -31,6 +31,44 @@ export function normalizeTaxIdentifier(value) {
|
|
|
31
31
|
const normalized = String(value || '').trim().toUpperCase();
|
|
32
32
|
return normalized || undefined;
|
|
33
33
|
}
|
|
34
|
+
/**
|
|
35
|
+
* Normalizes a typed organization identifier for equality checks without
|
|
36
|
+
* changing the canonical value stored in credentials or tenant records.
|
|
37
|
+
*/
|
|
38
|
+
export function normalizeLegalOrganizationIdentifier(identifier) {
|
|
39
|
+
const rawType = String(identifier?.type || '').trim().toUpperCase();
|
|
40
|
+
const type = rawType === 'TAXID' || rawType === 'TAX_ID' ? 'TAX' : rawType;
|
|
41
|
+
const value = String(identifier?.value || '').trim().toUpperCase();
|
|
42
|
+
return type && value ? { type, value } : undefined;
|
|
43
|
+
}
|
|
44
|
+
function extractLegalOrganizationIdentifier(value) {
|
|
45
|
+
const source = asObject(value) || {};
|
|
46
|
+
const identifier = asObject(source.identifier) || {};
|
|
47
|
+
const taxId = source.taxID ?? source.taxId;
|
|
48
|
+
return normalizeLegalOrganizationIdentifier(taxId !== undefined
|
|
49
|
+
? { type: 'taxID', value: taxId }
|
|
50
|
+
: {
|
|
51
|
+
type: identifier.additionalType ?? identifier.type ?? source.identifierType,
|
|
52
|
+
value: identifier.value ?? source.identifierValue,
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
/** Extracts the typed legal identifier from an organization credential subject. */
|
|
56
|
+
export function extractOrganizationLegalIdentifier(organizationCredential) {
|
|
57
|
+
return extractLegalOrganizationIdentifier(extractCredentialSubject(organizationCredential));
|
|
58
|
+
}
|
|
59
|
+
/** Extracts the typed organization identifier from a representative `memberOf` binding. */
|
|
60
|
+
export function extractRepresentativeMemberOfLegalIdentifier(representativeCredential) {
|
|
61
|
+
const subject = extractCredentialSubject(representativeCredential) || {};
|
|
62
|
+
return extractLegalOrganizationIdentifier(subject.memberOf);
|
|
63
|
+
}
|
|
64
|
+
/** Compares typed legal identifiers without discarding punctuation from their values. */
|
|
65
|
+
export function legalOrganizationIdentifiersMatch(left, right) {
|
|
66
|
+
const normalizedLeft = normalizeLegalOrganizationIdentifier(left);
|
|
67
|
+
const normalizedRight = normalizeLegalOrganizationIdentifier(right);
|
|
68
|
+
return Boolean(normalizedLeft && normalizedRight
|
|
69
|
+
&& normalizedLeft.type === normalizedRight.type
|
|
70
|
+
&& normalizedLeft.value === normalizedRight.value);
|
|
71
|
+
}
|
|
34
72
|
/**
|
|
35
73
|
* Extracts an organization tax id from a VC-like organization credential.
|
|
36
74
|
*
|
|
@@ -39,10 +77,8 @@ export function normalizeTaxIdentifier(value) {
|
|
|
39
77
|
export function extractOrganizationTaxId(organizationCredential) {
|
|
40
78
|
const subject = extractCredentialSubject(organizationCredential) || {};
|
|
41
79
|
const identifier = asObject(subject.identifier);
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|| normalizeTaxIdentifier(identifier?.value)
|
|
45
|
-
|| normalizeTaxIdentifier(subject.identifierValue));
|
|
80
|
+
const value = String(subject.taxID ?? subject.taxId ?? identifier?.value ?? '').trim();
|
|
81
|
+
return normalizeTaxIdentifier(value) || undefined;
|
|
46
82
|
}
|
|
47
83
|
/**
|
|
48
84
|
* Extracts the `memberOf` tax id from a representative credential.
|
|
@@ -53,10 +89,8 @@ export function extractRepresentativeMemberOfTaxId(representativeCredential) {
|
|
|
53
89
|
const subject = extractCredentialSubject(representativeCredential) || {};
|
|
54
90
|
const memberOf = asObject(subject.memberOf) || {};
|
|
55
91
|
const identifier = asObject(memberOf.identifier);
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|| normalizeTaxIdentifier(identifier?.value)
|
|
59
|
-
|| normalizeTaxIdentifier(memberOf.identifierValue));
|
|
92
|
+
const value = String(memberOf.taxID ?? memberOf.taxId ?? identifier?.value ?? '').trim();
|
|
93
|
+
return normalizeTaxIdentifier(value) || undefined;
|
|
60
94
|
}
|
|
61
95
|
/**
|
|
62
96
|
* Extracts the representative role code from `credentialSubject.hasOccupation`.
|
|
@@ -86,6 +86,7 @@ function deriveRuleEntriesFromConsentEntry(entry, options, bundleEvidenceReferen
|
|
|
86
86
|
for (const purpose of purposes) {
|
|
87
87
|
for (const role of normalizedRoles) {
|
|
88
88
|
const ruleId = buildConsentAtomicRuleId({
|
|
89
|
+
sourceConsentIdentifier,
|
|
89
90
|
subject,
|
|
90
91
|
decision,
|
|
91
92
|
actorIdentifier,
|
|
@@ -32,9 +32,12 @@ export type ConsentDuplicateRuleConflict = Readonly<{
|
|
|
32
32
|
*
|
|
33
33
|
* The identifier intentionally excludes section/resource targets so that two
|
|
34
34
|
* entries that authorize different target sets for the same subject, decision,
|
|
35
|
-
* actor, purpose, and role collide into the same duplicate group.
|
|
35
|
+
* actor, purpose, and role collide into the same duplicate group. It includes
|
|
36
|
+
* the stable source Consent identifier so independent portal or study
|
|
37
|
+
* consents never collapse into the same rule.
|
|
36
38
|
*/
|
|
37
39
|
export declare function buildConsentAtomicRuleId(input: Readonly<{
|
|
40
|
+
sourceConsentIdentifier?: string;
|
|
38
41
|
subject?: string;
|
|
39
42
|
decision?: string;
|
|
40
43
|
actorIdentifier: string;
|
|
@@ -9,10 +9,13 @@ const RESOURCE_TYPE_PREFIX = 'resourceType:';
|
|
|
9
9
|
*
|
|
10
10
|
* The identifier intentionally excludes section/resource targets so that two
|
|
11
11
|
* entries that authorize different target sets for the same subject, decision,
|
|
12
|
-
* actor, purpose, and role collide into the same duplicate group.
|
|
12
|
+
* actor, purpose, and role collide into the same duplicate group. It includes
|
|
13
|
+
* the stable source Consent identifier so independent portal or study
|
|
14
|
+
* consents never collapse into the same rule.
|
|
13
15
|
*/
|
|
14
16
|
export function buildConsentAtomicRuleId(input) {
|
|
15
17
|
return [
|
|
18
|
+
normalizeRuleKeyPart(input.sourceConsentIdentifier),
|
|
16
19
|
normalizeRuleKeyPart(input.subject),
|
|
17
20
|
normalizeDecision(input.decision).toLowerCase(),
|
|
18
21
|
normalizeRuleKeyPart(input.actorIdentifier),
|
|
@@ -102,6 +105,7 @@ function deriveAtomicConsentRules(entry, entryIndex) {
|
|
|
102
105
|
for (const role of normalizedRoles) {
|
|
103
106
|
derived.push({
|
|
104
107
|
ruleId: buildConsentAtomicRuleId({
|
|
108
|
+
sourceConsentIdentifier: identifier,
|
|
105
109
|
subject,
|
|
106
110
|
decision,
|
|
107
111
|
actorIdentifier,
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import type { InterTenantAccessContractClaims, InterTenantContractAuthorizationConsentCriteria, InterTenantAccessContractMatchCriteria, InterTenantAccessContractSummary } from '../models/inter-tenant-access-contract';
|
|
2
2
|
import type { VerifiableCredentialV2 } from '../models/verifiable-credential';
|
|
3
3
|
type ContractLike = Record<string, any>;
|
|
4
|
+
/**
|
|
5
|
+
* Builds the canonical FHIR Contract. Signer entries identify legally
|
|
6
|
+
* authorized signatories; technical tenant controllers are not inferred as
|
|
7
|
+
* signatories. Historical controller role labels are accepted only on read.
|
|
8
|
+
*/
|
|
4
9
|
export declare function buildInterTenantAccessContractResource(claims: InterTenantAccessContractClaims): ContractLike;
|
|
5
10
|
export declare function buildInterTenantAccessContractCredential(input: Readonly<{
|
|
6
11
|
claims: InterTenantAccessContractClaims;
|
|
@@ -9,10 +14,16 @@ export declare function buildInterTenantAccessContractCredential(input: Readonly
|
|
|
9
14
|
validUntil?: string;
|
|
10
15
|
additionalCredential?: Record<string, unknown>;
|
|
11
16
|
}>): VerifiableCredentialV2;
|
|
17
|
+
/** Summarizes tenant, authority and bilateral proof evidence from one Contract VC. */
|
|
12
18
|
export declare function summarizeInterTenantAccessContract(credential: unknown): InterTenantAccessContractSummary | undefined;
|
|
13
19
|
export declare function isInterTenantAccessContractActive(summary: InterTenantAccessContractSummary | undefined, options?: Readonly<{
|
|
14
20
|
now?: string | Date;
|
|
15
21
|
}>): boolean;
|
|
22
|
+
/**
|
|
23
|
+
* Matches an active contract and, by default, requires contractAgreement
|
|
24
|
+
* proofs whose verification methods belong to both named signatories.
|
|
25
|
+
* Cryptographic proof verification must occur before this structural match.
|
|
26
|
+
*/
|
|
16
27
|
export declare function matchesInterTenantAccessContract(summary: InterTenantAccessContractSummary | undefined, criteria: InterTenantAccessContractMatchCriteria): boolean;
|
|
17
28
|
export declare function getMatchingInterTenantAccessContractFromVpToken(vpToken: string, criteria: InterTenantAccessContractMatchCriteria): Record<string, unknown> | undefined;
|
|
18
29
|
/**
|
|
@@ -7,8 +7,10 @@ import { getVpCredentials } from './vp-token.js';
|
|
|
7
7
|
const ACTIVE_CONTRACT_STATUSES = new Set(['executed', 'amended', 'appended']);
|
|
8
8
|
const PROVIDER_ROLE = 'provider';
|
|
9
9
|
const CONSUMER_ROLE = 'consumer';
|
|
10
|
-
const
|
|
11
|
-
const
|
|
10
|
+
const PROVIDER_AUTHORIZED_SIGNATORY_ROLE = 'provider-authorized-signatory';
|
|
11
|
+
const CONSUMER_AUTHORIZED_SIGNATORY_ROLE = 'consumer-authorized-signatory';
|
|
12
|
+
const LEGACY_PROVIDER_CONTROLLER_ROLE = 'provider-controller';
|
|
13
|
+
const LEGACY_CONSUMER_CONTROLLER_ROLE = 'consumer-controller';
|
|
12
14
|
function splitCsv(value) {
|
|
13
15
|
return Array.from(new Set(String(value || '')
|
|
14
16
|
.split(',')
|
|
@@ -108,6 +110,20 @@ function extractSignerReference(contract, expectedRole) {
|
|
|
108
110
|
}
|
|
109
111
|
return undefined;
|
|
110
112
|
}
|
|
113
|
+
function extractSignerReferenceWithAliases(contract, canonicalRole, legacyRole) {
|
|
114
|
+
return extractSignerReference(contract, canonicalRole) || extractSignerReference(contract, legacyRole);
|
|
115
|
+
}
|
|
116
|
+
function hasContractAgreementProof(credential, signatoryDid) {
|
|
117
|
+
if (!signatoryDid)
|
|
118
|
+
return false;
|
|
119
|
+
const proofs = Array.isArray(credential.proof) ? credential.proof : credential.proof ? [credential.proof] : [];
|
|
120
|
+
return proofs.some((proof) => {
|
|
121
|
+
if (String(proof?.proofPurpose || '').trim() !== 'contractAgreement')
|
|
122
|
+
return false;
|
|
123
|
+
const verificationMethod = String(proof?.verificationMethod || '').trim();
|
|
124
|
+
return verificationMethod === signatoryDid || verificationMethod.startsWith(`${signatoryDid}#`);
|
|
125
|
+
});
|
|
126
|
+
}
|
|
111
127
|
function extractPurposes(contract) {
|
|
112
128
|
const terms = Array.isArray(contract.term) ? contract.term : contract.term ? [contract.term] : [];
|
|
113
129
|
return Array.from(new Set(terms.flatMap((term) => {
|
|
@@ -135,6 +151,11 @@ function normalizeNow(input) {
|
|
|
135
151
|
return new Date(input).getTime();
|
|
136
152
|
return Date.now();
|
|
137
153
|
}
|
|
154
|
+
/**
|
|
155
|
+
* Builds the canonical FHIR Contract. Signer entries identify legally
|
|
156
|
+
* authorized signatories; technical tenant controllers are not inferred as
|
|
157
|
+
* signatories. Historical controller role labels are accepted only on read.
|
|
158
|
+
*/
|
|
138
159
|
export function buildInterTenantAccessContractResource(claims) {
|
|
139
160
|
const identifier = readClaimWithAliases(claims, ClaimInterTenantAccessContract.identifier) || '';
|
|
140
161
|
const status = readClaimWithAliases(claims, ClaimInterTenantAccessContract.status) || 'executed';
|
|
@@ -144,8 +165,8 @@ export function buildInterTenantAccessContractResource(claims) {
|
|
|
144
165
|
const appliesEnd = readClaimWithAliases(claims, ClaimInterTenantAccessContract.appliesEnd, ['Contract.applies.end']) || '';
|
|
145
166
|
const providerOrganization = readClaimWithAliases(claims, ClaimInterTenantAccessContract.providerOrganization, ['Contract.term.offer.party.provider']) || '';
|
|
146
167
|
const consumerOrganization = readClaimWithAliases(claims, ClaimInterTenantAccessContract.consumerOrganization, ['Contract.term.offer.party.consumer']) || '';
|
|
147
|
-
const
|
|
148
|
-
const
|
|
168
|
+
const providerAuthorizedSignatory = readClaimWithAliases(claims, ClaimInterTenantAccessContract.providerAuthorizedSignatory, [ClaimInterTenantAccessContract.providerController, 'Contract.signer.provider']) || '';
|
|
169
|
+
const consumerAuthorizedSignatory = readClaimWithAliases(claims, ClaimInterTenantAccessContract.consumerAuthorizedSignatory, [ClaimInterTenantAccessContract.consumerController, 'Contract.signer.consumer']) || '';
|
|
149
170
|
const instantiatesUri = readClaimWithAliases(claims, ClaimInterTenantAccessContract.instantiatesUri, ['Contract.instantiatesUri']) || '';
|
|
150
171
|
const capabilities = splitCsv(readClaimWithAliases(claims, ClaimInterTenantAccessContract.capability, ['Contract.term.offer.securityLabel']));
|
|
151
172
|
const purposes = splitCsv(readClaimWithAliases(claims, ClaimInterTenantAccessContract.purpose, ['Contract.term.type']));
|
|
@@ -162,16 +183,16 @@ export function buildInterTenantAccessContractResource(claims) {
|
|
|
162
183
|
...(appliesEnd ? { end: appliesEnd } : {}),
|
|
163
184
|
},
|
|
164
185
|
signer: [
|
|
165
|
-
|
|
186
|
+
providerAuthorizedSignatory
|
|
166
187
|
? {
|
|
167
|
-
type: [{ text:
|
|
168
|
-
party: { reference:
|
|
188
|
+
type: [{ text: PROVIDER_AUTHORIZED_SIGNATORY_ROLE }],
|
|
189
|
+
party: { reference: providerAuthorizedSignatory },
|
|
169
190
|
}
|
|
170
191
|
: undefined,
|
|
171
|
-
|
|
192
|
+
consumerAuthorizedSignatory
|
|
172
193
|
? {
|
|
173
|
-
type: [{ text:
|
|
174
|
-
party: { reference:
|
|
194
|
+
type: [{ text: CONSUMER_AUTHORIZED_SIGNATORY_ROLE }],
|
|
195
|
+
party: { reference: consumerAuthorizedSignatory },
|
|
175
196
|
}
|
|
176
197
|
: undefined,
|
|
177
198
|
].filter(Boolean),
|
|
@@ -211,6 +232,7 @@ export function buildInterTenantAccessContractCredential(input) {
|
|
|
211
232
|
...(input.additionalCredential || {}),
|
|
212
233
|
};
|
|
213
234
|
}
|
|
235
|
+
/** Summarizes tenant, authority and bilateral proof evidence from one Contract VC. */
|
|
214
236
|
export function summarizeInterTenantAccessContract(credential) {
|
|
215
237
|
if (!credential || typeof credential !== 'object')
|
|
216
238
|
return undefined;
|
|
@@ -220,6 +242,8 @@ export function summarizeInterTenantAccessContract(credential) {
|
|
|
220
242
|
const subject = (credential.credentialSubject || {});
|
|
221
243
|
if (String(subject.resourceType || '').trim() !== 'Contract')
|
|
222
244
|
return undefined;
|
|
245
|
+
const providerAuthorizedSignatoryDid = extractSignerReferenceWithAliases(subject, PROVIDER_AUTHORIZED_SIGNATORY_ROLE, LEGACY_PROVIDER_CONTROLLER_ROLE);
|
|
246
|
+
const consumerAuthorizedSignatoryDid = extractSignerReferenceWithAliases(subject, CONSUMER_AUTHORIZED_SIGNATORY_ROLE, LEGACY_CONSUMER_CONTROLLER_ROLE);
|
|
223
247
|
return {
|
|
224
248
|
identifier: firstIdentifierValue(subject.identifier) || String(subject.id || '').trim() || undefined,
|
|
225
249
|
status: String(subject.status || '').trim() || undefined,
|
|
@@ -228,8 +252,12 @@ export function summarizeInterTenantAccessContract(credential) {
|
|
|
228
252
|
appliesEnd: String(subject.applies?.end || '').trim() || undefined,
|
|
229
253
|
providerOrganizationDid: extractOfferPartyReference(subject, PROVIDER_ROLE),
|
|
230
254
|
consumerOrganizationDid: extractOfferPartyReference(subject, CONSUMER_ROLE),
|
|
231
|
-
|
|
232
|
-
|
|
255
|
+
providerAuthorizedSignatoryDid,
|
|
256
|
+
consumerAuthorizedSignatoryDid,
|
|
257
|
+
providerControllerDid: providerAuthorizedSignatoryDid,
|
|
258
|
+
consumerControllerDid: consumerAuthorizedSignatoryDid,
|
|
259
|
+
hasProviderContractAgreementProof: hasContractAgreementProof(credential, providerAuthorizedSignatoryDid),
|
|
260
|
+
hasConsumerContractAgreementProof: hasContractAgreementProof(credential, consumerAuthorizedSignatoryDid),
|
|
233
261
|
capabilities: extractCapabilities(subject),
|
|
234
262
|
purposes: extractPurposes(subject),
|
|
235
263
|
};
|
|
@@ -249,6 +277,11 @@ export function isInterTenantAccessContractActive(summary, options = {}) {
|
|
|
249
277
|
return false;
|
|
250
278
|
return true;
|
|
251
279
|
}
|
|
280
|
+
/**
|
|
281
|
+
* Matches an active contract and, by default, requires contractAgreement
|
|
282
|
+
* proofs whose verification methods belong to both named signatories.
|
|
283
|
+
* Cryptographic proof verification must occur before this structural match.
|
|
284
|
+
*/
|
|
252
285
|
export function matchesInterTenantAccessContract(summary, criteria) {
|
|
253
286
|
if (!isInterTenantAccessContractActive(summary, { now: criteria.now }))
|
|
254
287
|
return false;
|
|
@@ -256,6 +289,9 @@ export function matchesInterTenantAccessContract(summary, criteria) {
|
|
|
256
289
|
return false;
|
|
257
290
|
if (String(summary?.consumerOrganizationDid || '').trim() !== String(criteria.consumerOrganizationDid || '').trim())
|
|
258
291
|
return false;
|
|
292
|
+
if ((criteria.requireBilateralContractAgreementProofs ?? true)
|
|
293
|
+
&& (!summary?.hasProviderContractAgreementProof || !summary?.hasConsumerContractAgreementProof))
|
|
294
|
+
return false;
|
|
259
295
|
const requiredCapabilities = Array.from(new Set((criteria.requiredCapabilities || []).map((value) => String(value || '').trim()).filter(Boolean)));
|
|
260
296
|
if (requiredCapabilities.length > 0) {
|
|
261
297
|
const contractCapabilities = new Set((summary?.capabilities || []).map((value) => String(value || '').trim()));
|
|
@@ -10,6 +10,8 @@ export type LegalOrganizationFormTemplateFields = Readonly<{
|
|
|
10
10
|
controllerRole?: string;
|
|
11
11
|
serviceCategory?: string;
|
|
12
12
|
serviceIdentifier?: string;
|
|
13
|
+
/** Canonical CSV of capabilities stored in `org.schema.Service.serviceType`. */
|
|
14
|
+
serviceType?: string;
|
|
13
15
|
serviceUrl?: string;
|
|
14
16
|
tenantAlias?: string;
|
|
15
17
|
}>;
|
|
@@ -90,6 +92,8 @@ export interface LegalOrganizationOnboardingFacade {
|
|
|
90
92
|
getServiceCategory(fields: LegalOrganizationFormTemplateFields): string | undefined;
|
|
91
93
|
setServiceIdentifier(fields: LegalOrganizationFormTemplateFields, value: string): LegalOrganizationFormTemplateFields;
|
|
92
94
|
getServiceIdentifier(fields: LegalOrganizationFormTemplateFields): string | undefined;
|
|
95
|
+
setServiceType(fields: LegalOrganizationFormTemplateFields, value: string): LegalOrganizationFormTemplateFields;
|
|
96
|
+
getServiceType(fields: LegalOrganizationFormTemplateFields): string | undefined;
|
|
93
97
|
setServiceUrl(fields: LegalOrganizationFormTemplateFields, value: string): LegalOrganizationFormTemplateFields;
|
|
94
98
|
getServiceUrl(fields: LegalOrganizationFormTemplateFields): string | undefined;
|
|
95
99
|
/**
|
|
@@ -136,6 +140,8 @@ export interface LegalOrganizationOnboardingEditor {
|
|
|
136
140
|
getServiceCategory(): string | undefined;
|
|
137
141
|
setServiceIdentifier(value: string): LegalOrganizationOnboardingEditor;
|
|
138
142
|
getServiceIdentifier(): string | undefined;
|
|
143
|
+
setServiceType(value: string): LegalOrganizationOnboardingEditor;
|
|
144
|
+
getServiceType(): string | undefined;
|
|
139
145
|
setServiceUrl(value: string): LegalOrganizationOnboardingEditor;
|
|
140
146
|
getServiceUrl(): string | undefined;
|
|
141
147
|
setTenantAlias(value: string): LegalOrganizationOnboardingEditor;
|
|
@@ -51,6 +51,8 @@ function createEditorFromFacade(facade, initial) {
|
|
|
51
51
|
getServiceCategory() { return facade.getServiceCategory(formFields); },
|
|
52
52
|
setServiceIdentifier(value) { formFields = facade.setServiceIdentifier(formFields, value); return editor; },
|
|
53
53
|
getServiceIdentifier() { return facade.getServiceIdentifier(formFields); },
|
|
54
|
+
setServiceType(value) { formFields = facade.setServiceType(formFields, value); return editor; },
|
|
55
|
+
getServiceType() { return facade.getServiceType(formFields); },
|
|
54
56
|
setServiceUrl(value) { formFields = facade.setServiceUrl(formFields, value); return editor; },
|
|
55
57
|
getServiceUrl() { return facade.getServiceUrl(formFields); },
|
|
56
58
|
setTenantAlias(value) { formFields = facade.setTenantAlias(formFields, value); return editor; },
|
|
@@ -133,6 +135,12 @@ export function createLegalOrganizationOnboardingFacade() {
|
|
|
133
135
|
getServiceIdentifier(fields) {
|
|
134
136
|
return normalizeOptionalText(fields.serviceIdentifier);
|
|
135
137
|
},
|
|
138
|
+
setServiceType(fields, value) {
|
|
139
|
+
return patchFields(fields, { serviceType: normalizeText(value) });
|
|
140
|
+
},
|
|
141
|
+
getServiceType(fields) {
|
|
142
|
+
return normalizeOptionalText(fields.serviceType);
|
|
143
|
+
},
|
|
136
144
|
setServiceUrl(fields, value) {
|
|
137
145
|
return patchFields(fields, { serviceUrl: normalizeText(value) });
|
|
138
146
|
},
|
|
@@ -176,6 +184,9 @@ export function createLegalOrganizationOnboardingFacade() {
|
|
|
176
184
|
if (normalizeOptionalText(fields.serviceIdentifier)) {
|
|
177
185
|
claims[ClaimsServiceSchemaorg.identifier] = normalizeText(fields.serviceIdentifier);
|
|
178
186
|
}
|
|
187
|
+
if (normalizeOptionalText(fields.serviceType)) {
|
|
188
|
+
claims[ClaimsServiceSchemaorg.serviceType] = normalizeText(fields.serviceType);
|
|
189
|
+
}
|
|
179
190
|
if (normalizeOptionalText(fields.serviceUrl)) {
|
|
180
191
|
claims[ClaimsServiceSchemaorg.url] = normalizeText(fields.serviceUrl);
|
|
181
192
|
}
|
|
@@ -236,6 +247,14 @@ export function createLegalOrganizationOnboardingFacade() {
|
|
|
236
247
|
field: 'serviceCategory',
|
|
237
248
|
});
|
|
238
249
|
}
|
|
250
|
+
if (!normalizeOptionalText(fields.serviceType)) {
|
|
251
|
+
issues.push({
|
|
252
|
+
severity: 'error',
|
|
253
|
+
code: 'missing-service-type',
|
|
254
|
+
message: 'serviceType is required because GW authorizes activation capabilities from it.',
|
|
255
|
+
field: 'serviceType',
|
|
256
|
+
});
|
|
257
|
+
}
|
|
239
258
|
if (!normalizeOptionalText(fields.controllerRole)) {
|
|
240
259
|
issues.push({
|
|
241
260
|
severity: 'warning',
|
|
@@ -40,6 +40,8 @@ export declare class OrganizationLifecycleEditor {
|
|
|
40
40
|
setContext(context: string): this;
|
|
41
41
|
setIdentifier(identifier: string): this;
|
|
42
42
|
setIdentifierValue(identifierValue: string): this;
|
|
43
|
+
/** Sets the jurisdiction-defined identifier type independently from its complete value. */
|
|
44
|
+
setIdentifierType(identifierType: string): this;
|
|
43
45
|
setTaxId(taxId: string): this;
|
|
44
46
|
setOperation(operation: OrganizationLifecycleOperation): this;
|
|
45
47
|
setRequestType(requestType: string): this;
|
|
@@ -47,6 +49,8 @@ export declare class OrganizationLifecycleEditor {
|
|
|
47
49
|
getContext(): string | undefined;
|
|
48
50
|
getIdentifier(): string | undefined;
|
|
49
51
|
getIdentifierValue(): string | undefined;
|
|
52
|
+
/** Returns the jurisdiction-defined identifier type used by lifecycle authorization. */
|
|
53
|
+
getIdentifierType(): string | undefined;
|
|
50
54
|
getTaxId(): string | undefined;
|
|
51
55
|
getOperation(): OrganizationLifecycleOperation;
|
|
52
56
|
getRequestType(): string | undefined;
|
|
@@ -73,6 +73,16 @@ export class OrganizationLifecycleEditor {
|
|
|
73
73
|
});
|
|
74
74
|
return this;
|
|
75
75
|
}
|
|
76
|
+
/** Sets the jurisdiction-defined identifier type independently from its complete value. */
|
|
77
|
+
setIdentifierType(identifierType) {
|
|
78
|
+
this.draft = patchDraft(this.draft, {
|
|
79
|
+
claims: {
|
|
80
|
+
...this.draft.claims,
|
|
81
|
+
[ClaimsOrganizationSchemaorg.identifierType]: String(identifierType).trim(),
|
|
82
|
+
},
|
|
83
|
+
});
|
|
84
|
+
return this;
|
|
85
|
+
}
|
|
76
86
|
setTaxId(taxId) {
|
|
77
87
|
this.draft = patchDraft(this.draft, {
|
|
78
88
|
claims: {
|
|
@@ -103,6 +113,10 @@ export class OrganizationLifecycleEditor {
|
|
|
103
113
|
getIdentifierValue() {
|
|
104
114
|
return normalizeText(this.draft.claims[ClaimsOrganizationSchemaorg.identifierValue]) || undefined;
|
|
105
115
|
}
|
|
116
|
+
/** Returns the jurisdiction-defined identifier type used by lifecycle authorization. */
|
|
117
|
+
getIdentifierType() {
|
|
118
|
+
return normalizeText(this.draft.claims[ClaimsOrganizationSchemaorg.identifierType]) || undefined;
|
|
119
|
+
}
|
|
106
120
|
getTaxId() {
|
|
107
121
|
return normalizeText(this.draft.claims[ClaimsOrganizationSchemaorg.taxId]) || undefined;
|
|
108
122
|
}
|