gdc-common-utils-ts 1.24.1 → 2.0.1
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 +39 -0
- package/dist/constants/index.d.ts +1 -0
- package/dist/constants/index.js +1 -0
- package/dist/constants/profile-runtime.d.ts +33 -0
- package/dist/constants/profile-runtime.js +30 -0
- package/dist/examples/frontend-session.js +2 -1
- package/dist/examples/ica-activation-proof.d.ts +11 -4
- package/dist/examples/ica-activation-proof.js +11 -4
- package/dist/examples/index.d.ts +1 -0
- package/dist/examples/index.js +1 -0
- package/dist/examples/lifecycle.js +5 -5
- package/dist/examples/organization-controller.d.ts +0 -1
- package/dist/examples/organization-controller.js +0 -1
- package/dist/examples/profile-runtime.d.ts +16 -0
- package/dist/examples/profile-runtime.js +18 -0
- package/dist/examples/shared.d.ts +9 -0
- package/dist/examples/shared.js +9 -0
- package/dist/interfaces/Cryptography.types.d.ts +15 -0
- package/dist/models/identity-bootstrap.d.ts +9 -0
- package/dist/utils/activation-policy.d.ts +45 -1
- package/dist/utils/activation-policy.js +65 -7
- package/dist/utils/activation-request.d.ts +63 -2
- package/dist/utils/activation-request.js +82 -0
- package/dist/utils/communication-participant-search-test-data.d.ts +17 -0
- package/dist/utils/communication-participant-search-test-data.js +39 -0
- package/dist/utils/communication-participant-search.d.ts +108 -0
- package/dist/utils/communication-participant-search.js +425 -0
- package/dist/utils/communication-retention-policy.d.ts +32 -0
- package/dist/utils/communication-retention-policy.js +41 -0
- package/dist/utils/communication-search-editor.d.ts +54 -0
- package/dist/utils/communication-search-editor.js +156 -0
- package/dist/utils/fhir-search.d.ts +32 -0
- package/dist/utils/fhir-search.js +45 -0
- package/dist/utils/index.d.ts +8 -0
- package/dist/utils/index.js +8 -0
- package/dist/utils/individual-organization-lifecycle.d.ts +15 -5
- package/dist/utils/individual-organization-lifecycle.js +53 -6
- package/dist/utils/interoperable-resource-operation.d.ts +4 -4
- package/dist/utils/interoperable-resource-operation.js +22 -22
- package/dist/utils/jwk-thumbprint.d.ts +40 -0
- package/dist/utils/jwk-thumbprint.js +57 -0
- package/dist/utils/legal-organization-onboarding.d.ts +97 -0
- package/dist/utils/legal-organization-onboarding.js +128 -0
- package/dist/utils/license-commercial-search.d.ts +6 -6
- package/dist/utils/license-commercial-search.js +2 -2
- package/dist/utils/license-list-search.d.ts +7 -7
- package/dist/utils/license-list-search.js +23 -23
- package/dist/utils/license-offer-order.d.ts +19 -19
- package/dist/utils/license-offer-order.js +68 -68
- package/dist/utils/organization-lifecycle.d.ts +59 -0
- package/dist/utils/organization-lifecycle.js +155 -0
- package/dist/utils/same-as.d.ts +41 -0
- package/dist/utils/same-as.js +83 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
# gdc-common-utils-ts
|
|
2
2
|
|
|
3
|
+
See [ARCHITECTURE.md](./ARCHITECTURE.md) and
|
|
4
|
+
[CONTRIBUTING.md](./CONTRIBUTING.md) before adding new shared helpers,
|
|
5
|
+
fixtures, or high-level tests.
|
|
6
|
+
|
|
7
|
+
Short rule:
|
|
8
|
+
|
|
9
|
+
- if a test/example can reuse a shared type or fixture, it must do so
|
|
10
|
+
- do not add ad hoc literals in `101` tests when `gdc-common-utils-ts` can own
|
|
11
|
+
the reusable value instead
|
|
12
|
+
|
|
3
13
|
Employee shared examples live in `src/examples/employee.ts`.
|
|
4
14
|
Employee pure helper functions live in `src/utils/employee.ts`.
|
|
5
15
|
|
|
@@ -30,6 +40,35 @@ boundaries used in `gdc-common-utils-ts`.
|
|
|
30
40
|
- `resource.meta.claims` is the canonical project-specific claims container and must be preserved across conversions/transports.
|
|
31
41
|
- `resource.meta.claims` is not part of base FHIR; it is a claims-first extension carried by FHIR-like resources in GDC contracts.
|
|
32
42
|
|
|
43
|
+
## Identity Continuity
|
|
44
|
+
|
|
45
|
+
For ICA-backed organization activation, the representative/controller proof is
|
|
46
|
+
intentionally split into two complementary dimensions:
|
|
47
|
+
|
|
48
|
+
- `credentialSubject.sameAs`
|
|
49
|
+
public identity continuity, typically an email-derived
|
|
50
|
+
`urn:multibase:z...`
|
|
51
|
+
- `credentialSubject.hasCredential.material`
|
|
52
|
+
signing-key continuity, ideally an RFC 9278 JWK-thumbprint URN bound to the
|
|
53
|
+
controller key that signs the VP or was captured during ICA verification
|
|
54
|
+
|
|
55
|
+
They are not interchangeable:
|
|
56
|
+
|
|
57
|
+
- `sameAs` does not prove possession of the signing key
|
|
58
|
+
- `hasCredential.material` does not by itself prove the expected public alias
|
|
59
|
+
or email continuity
|
|
60
|
+
|
|
61
|
+
Production-grade flows should prefer ICA-issued representative VCs that carry
|
|
62
|
+
both dimensions.
|
|
63
|
+
|
|
64
|
+
Step by step:
|
|
65
|
+
|
|
66
|
+
1. ICA verifies the signed PDF and emits the representative VC.
|
|
67
|
+
2. ICA projects `credentialSubject.sameAs` from signed email evidence when available.
|
|
68
|
+
3. ICA projects `credentialSubject.hasCredential.material` from the captured controller binding key.
|
|
69
|
+
4. GW/common-utils enforce key-binding continuity as the hard activation requirement.
|
|
70
|
+
5. Higher layers may additionally compare `sameAs` for stronger identity/audit continuity.
|
|
71
|
+
|
|
33
72
|
## 101 Test Convention
|
|
34
73
|
|
|
35
74
|
Every `101` test in this repo is expected to be a didactic executable tutorial,
|
|
@@ -14,6 +14,7 @@ export * from './schemaorg';
|
|
|
14
14
|
export * from './hl7-roles';
|
|
15
15
|
export * from './healthcare';
|
|
16
16
|
export * from './permission-templates';
|
|
17
|
+
export * from './profile-runtime';
|
|
17
18
|
export * from './vital-signs';
|
|
18
19
|
export * from './network';
|
|
19
20
|
export * from './observation-category';
|
package/dist/constants/index.js
CHANGED
|
@@ -14,6 +14,7 @@ export * from './schemaorg.js';
|
|
|
14
14
|
export * from './hl7-roles.js';
|
|
15
15
|
export * from './healthcare.js';
|
|
16
16
|
export * from './permission-templates.js';
|
|
17
|
+
export * from './profile-runtime.js';
|
|
17
18
|
export * from './vital-signs.js';
|
|
18
19
|
export * from './network.js';
|
|
19
20
|
export * from './observation-category.js';
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Canonical logical application families used by shared SDK profile/session
|
|
3
|
+
* contracts.
|
|
4
|
+
*/
|
|
5
|
+
export declare const ProfileAppTypes: Readonly<{
|
|
6
|
+
readonly Organization: "Organization";
|
|
7
|
+
readonly Family: "Family";
|
|
8
|
+
}>;
|
|
9
|
+
export type ProfileAppType = typeof ProfileAppTypes[keyof typeof ProfileAppTypes];
|
|
10
|
+
/**
|
|
11
|
+
* Canonical runtime classes for actor-aware profile loading.
|
|
12
|
+
*/
|
|
13
|
+
export declare const ActorRuntimeClasses: Readonly<{
|
|
14
|
+
readonly Frontend: "frontend";
|
|
15
|
+
readonly Server: "server";
|
|
16
|
+
}>;
|
|
17
|
+
export type ActorRuntimeClass = typeof ActorRuntimeClasses[keyof typeof ActorRuntimeClasses];
|
|
18
|
+
/**
|
|
19
|
+
* Canonical key access strategies for profile loading/unlocking.
|
|
20
|
+
*/
|
|
21
|
+
export declare const KeyAccessModes: Readonly<{
|
|
22
|
+
readonly DeriveFromSeed: "derive-from-seed";
|
|
23
|
+
readonly UnlockEncryptedKeys: "unlock-encrypted-keys";
|
|
24
|
+
}>;
|
|
25
|
+
export type KeyAccessMode = typeof KeyAccessModes[keyof typeof KeyAccessModes];
|
|
26
|
+
/**
|
|
27
|
+
* Canonical secret kinds for subject/index relationship connection.
|
|
28
|
+
*/
|
|
29
|
+
export declare const ConnectionSecretKinds: Readonly<{
|
|
30
|
+
readonly PinPassword: "pin-password";
|
|
31
|
+
readonly OtpCode: "otp-code";
|
|
32
|
+
}>;
|
|
33
|
+
export type ConnectionSecretKind = typeof ConnectionSecretKinds[keyof typeof ConnectionSecretKinds];
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
// Copyright 2026 Antifraud Services Inc. under the Apache License, Version 2.0.
|
|
2
|
+
/**
|
|
3
|
+
* Canonical logical application families used by shared SDK profile/session
|
|
4
|
+
* contracts.
|
|
5
|
+
*/
|
|
6
|
+
export const ProfileAppTypes = Object.freeze({
|
|
7
|
+
Organization: 'Organization',
|
|
8
|
+
Family: 'Family',
|
|
9
|
+
});
|
|
10
|
+
/**
|
|
11
|
+
* Canonical runtime classes for actor-aware profile loading.
|
|
12
|
+
*/
|
|
13
|
+
export const ActorRuntimeClasses = Object.freeze({
|
|
14
|
+
Frontend: 'frontend',
|
|
15
|
+
Server: 'server',
|
|
16
|
+
});
|
|
17
|
+
/**
|
|
18
|
+
* Canonical key access strategies for profile loading/unlocking.
|
|
19
|
+
*/
|
|
20
|
+
export const KeyAccessModes = Object.freeze({
|
|
21
|
+
DeriveFromSeed: 'derive-from-seed',
|
|
22
|
+
UnlockEncryptedKeys: 'unlock-encrypted-keys',
|
|
23
|
+
});
|
|
24
|
+
/**
|
|
25
|
+
* Canonical secret kinds for subject/index relationship connection.
|
|
26
|
+
*/
|
|
27
|
+
export const ConnectionSecretKinds = Object.freeze({
|
|
28
|
+
PinPassword: 'pin-password',
|
|
29
|
+
OtpCode: 'otp-code',
|
|
30
|
+
});
|
|
@@ -9,12 +9,13 @@
|
|
|
9
9
|
* - do not inline DID/email/profile literals directly in frontend examples
|
|
10
10
|
*/
|
|
11
11
|
import { EXAMPLE_PROFILE_EMAIL, EXAMPLE_PROFILE_ID, EXAMPLE_PROFILE_ORGANIZATION_DID, } from './shared.js';
|
|
12
|
+
import { EXAMPLE_PROFILE_APP_TYPE_FAMILY } from './profile-runtime.js';
|
|
12
13
|
export const EXAMPLE_PROFILE_SESSION_INPUT = {
|
|
13
14
|
profileId: ` ${EXAMPLE_PROFILE_ID} `,
|
|
14
15
|
email: ` ${EXAMPLE_PROFILE_EMAIL} `,
|
|
15
16
|
role: ' controller ',
|
|
16
17
|
providerDid: ` ${EXAMPLE_PROFILE_ORGANIZATION_DID} `,
|
|
17
|
-
appType:
|
|
18
|
+
appType: EXAMPLE_PROFILE_APP_TYPE_FAMILY,
|
|
18
19
|
};
|
|
19
20
|
export const EXAMPLE_PROFILE_REGISTRY_ENTRY = {
|
|
20
21
|
id: EXAMPLE_PROFILE_ID,
|
|
@@ -24,6 +24,13 @@ export declare const EXAMPLE_ORG_CONTROLLER_SIGNING_KEY_ID: "urn:ietf:params:oau
|
|
|
24
24
|
export declare const EXAMPLE_PRESENTATION_AUDIENCE_HOST_ID: "host:node-operator-es";
|
|
25
25
|
export declare const EXAMPLE_ORGANIZATION_TAX_ID: "ESB00112233";
|
|
26
26
|
export declare const EXAMPLE_REPRESENTATIVE_ROLE_CODE: "RESPRSN";
|
|
27
|
+
export declare const EXAMPLE_REPRESENTATIVE_ISCO08_ROLE_CODE: "1120";
|
|
28
|
+
export declare const EXAMPLE_REPRESENTATIVE_ISCO08_ROLE_IDENTIFIER: "urn:ilo:ilostat:isco-08:1120";
|
|
29
|
+
export declare const EXAMPLE_REPRESENTATIVE_IDENTIFIER: "IDCES-99999999R";
|
|
30
|
+
export declare const EXAMPLE_REPRESENTATIVE_EMAIL: "legal.rep@example.org";
|
|
31
|
+
export declare const EXAMPLE_REPRESENTATIVE_SUBJECT_URN: "urn:person:identifier:IDCES-99999999R";
|
|
32
|
+
export declare const EXAMPLE_REPRESENTATIVE_SAME_AS: "urn:multibase:zControllerHash";
|
|
33
|
+
export declare const EXAMPLE_ORG_ACTIVATION_ORGANIZATION_DID: "did:web:provider.example:health-care:organization:taxid:VATES-ESB00112233";
|
|
27
34
|
export declare const EXAMPLE_ORGANIZATION_ID: "ESB00112233";
|
|
28
35
|
export declare const EXAMPLE_ACTIVATION_AUTHORIZED_CATEGORY: "health-care";
|
|
29
36
|
export declare const EXAMPLE_ACTIVATION_AUTHORIZED_SERVICE_TYPE: "organization/Composition.cruds";
|
|
@@ -45,18 +52,18 @@ export declare const EXAMPLE_ORG_ACTIVATION_LEGAL_REPRESENTATIVE_CREDENTIAL: Rea
|
|
|
45
52
|
'@context': string[];
|
|
46
53
|
type: ("VerifiableCredential" | "LegalRepresentativeCredential")[];
|
|
47
54
|
credentialSubject: {
|
|
48
|
-
id: "urn:
|
|
55
|
+
id: "urn:person:identifier:IDCES-99999999R";
|
|
49
56
|
memberOf: {
|
|
50
57
|
taxID: "ESB00112233";
|
|
51
58
|
};
|
|
52
59
|
hasOccupation: {
|
|
53
|
-
identifier:
|
|
54
|
-
value: "RESPRSN";
|
|
55
|
-
};
|
|
60
|
+
identifier: "urn:ilo:ilostat:isco-08:1120";
|
|
56
61
|
};
|
|
57
62
|
hasCredential: {
|
|
58
63
|
material: "urn:ietf:params:oauth:jwk-thumbprint:sha-256:Q0ZfM0V4YW1wbGVUaHVtYnByaW50X2Jhc2U2NHVybA";
|
|
59
64
|
};
|
|
65
|
+
identifier: "IDCES-99999999R";
|
|
66
|
+
sameAs: "urn:multibase:zControllerHash";
|
|
60
67
|
};
|
|
61
68
|
}>;
|
|
62
69
|
export declare const EXAMPLE_ORG_ACTIVATION_PROOF_VP_PAYLOAD: Readonly<{
|
|
@@ -30,6 +30,13 @@ export const EXAMPLE_ORG_CONTROLLER_SIGNING_KEY_ID = `${UrnPrefixes.JwkThumbprin
|
|
|
30
30
|
export const EXAMPLE_PRESENTATION_AUDIENCE_HOST_ID = 'host:node-operator-es';
|
|
31
31
|
export const EXAMPLE_ORGANIZATION_TAX_ID = 'ESB00112233';
|
|
32
32
|
export const EXAMPLE_REPRESENTATIVE_ROLE_CODE = 'RESPRSN';
|
|
33
|
+
export const EXAMPLE_REPRESENTATIVE_ISCO08_ROLE_CODE = '1120';
|
|
34
|
+
export const EXAMPLE_REPRESENTATIVE_ISCO08_ROLE_IDENTIFIER = 'urn:ilo:ilostat:isco-08:1120';
|
|
35
|
+
export const EXAMPLE_REPRESENTATIVE_IDENTIFIER = 'IDCES-99999999R';
|
|
36
|
+
export const EXAMPLE_REPRESENTATIVE_EMAIL = 'legal.rep@example.org';
|
|
37
|
+
export const EXAMPLE_REPRESENTATIVE_SUBJECT_URN = `urn:person:identifier:${EXAMPLE_REPRESENTATIVE_IDENTIFIER}`;
|
|
38
|
+
export const EXAMPLE_REPRESENTATIVE_SAME_AS = 'urn:multibase:zControllerHash';
|
|
39
|
+
export const EXAMPLE_ORG_ACTIVATION_ORGANIZATION_DID = 'did:web:provider.example:health-care:organization:taxid:VATES-ESB00112233';
|
|
33
40
|
export const EXAMPLE_ORGANIZATION_ID = EXAMPLE_ORGANIZATION_TAX_ID;
|
|
34
41
|
export const EXAMPLE_ACTIVATION_AUTHORIZED_CATEGORY = DataspaceSectors.HealthCare;
|
|
35
42
|
export const EXAMPLE_ACTIVATION_AUTHORIZED_SERVICE_TYPE = ServiceCapability.IndexProvider;
|
|
@@ -57,18 +64,18 @@ export const EXAMPLE_ORG_ACTIVATION_LEGAL_REPRESENTATIVE_CREDENTIAL = Object.fre
|
|
|
57
64
|
ActivationCredentialTypes.LegalRepresentativeCredential,
|
|
58
65
|
],
|
|
59
66
|
credentialSubject: {
|
|
60
|
-
id:
|
|
67
|
+
id: EXAMPLE_REPRESENTATIVE_SUBJECT_URN,
|
|
61
68
|
memberOf: {
|
|
62
69
|
taxID: EXAMPLE_ORGANIZATION_TAX_ID,
|
|
63
70
|
},
|
|
64
71
|
hasOccupation: {
|
|
65
|
-
identifier:
|
|
66
|
-
value: EXAMPLE_REPRESENTATIVE_ROLE_CODE,
|
|
67
|
-
},
|
|
72
|
+
identifier: EXAMPLE_REPRESENTATIVE_ISCO08_ROLE_IDENTIFIER,
|
|
68
73
|
},
|
|
69
74
|
hasCredential: {
|
|
70
75
|
material: EXAMPLE_ORG_CONTROLLER_SIGNING_KEY_ID,
|
|
71
76
|
},
|
|
77
|
+
identifier: EXAMPLE_REPRESENTATIVE_IDENTIFIER,
|
|
78
|
+
sameAs: EXAMPLE_REPRESENTATIVE_SAME_AS,
|
|
72
79
|
},
|
|
73
80
|
});
|
|
74
81
|
export const EXAMPLE_ORG_ACTIVATION_PROOF_VP_PAYLOAD = Object.freeze({
|
package/dist/examples/index.d.ts
CHANGED
|
@@ -11,6 +11,7 @@ export * from './related-person';
|
|
|
11
11
|
export * from './consent-access';
|
|
12
12
|
export * from './relationship-access';
|
|
13
13
|
export * from './frontend-session';
|
|
14
|
+
export * from './profile-runtime';
|
|
14
15
|
export * from './lifecycle';
|
|
15
16
|
export * from './api-flow-examples';
|
|
16
17
|
export * from './contract-examples';
|
package/dist/examples/index.js
CHANGED
|
@@ -11,6 +11,7 @@ export * from './related-person.js';
|
|
|
11
11
|
export * from './consent-access.js';
|
|
12
12
|
export * from './relationship-access.js';
|
|
13
13
|
export * from './frontend-session.js';
|
|
14
|
+
export * from './profile-runtime.js';
|
|
14
15
|
export * from './lifecycle.js';
|
|
15
16
|
export * from './api-flow-examples.js';
|
|
16
17
|
export * from './contract-examples.js';
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { ClaimsOrganizationSchemaorg, ClaimsPersonSchemaorg, } from '../constants/schemaorg.js';
|
|
3
3
|
import { LifecycleRequestType } from '../constants/lifecycle.js';
|
|
4
4
|
import { ClaimConsent } from '../models/consent-rule.js';
|
|
5
|
-
import {
|
|
5
|
+
import { IndividualOrganizationLifecycleEditor, IndividualOrganizationLifecycleOperations, } from '../utils/individual-organization-lifecycle.js';
|
|
6
6
|
import { EXAMPLE_EMAIL_CONTROLLER_INDIVIDUAL, EXAMPLE_EMAIL_CONTROLLER_ORG, EXAMPLE_CLINICAL_SECTION_ALLERGIES, EXAMPLE_CONSENT_PURPOSE_TREATMENT, EXAMPLE_HEALTHCARE_ACTOR_ROLE_PHYSICIAN, EXAMPLE_JURISDICTION, EXAMPLE_SECTOR, EXAMPLE_TENANT_IDENTIFIER, } from './shared.js';
|
|
7
7
|
/**
|
|
8
8
|
* Canonical lifecycle naming for `v1`.
|
|
@@ -190,12 +190,12 @@ export const EXAMPLE_INDIVIDUAL_DISABLE_MESSAGE = {
|
|
|
190
190
|
erasesPersonalDataImmediately: false,
|
|
191
191
|
},
|
|
192
192
|
};
|
|
193
|
-
export const EXAMPLE_INDIVIDUAL_ORGANIZATION_DISABLE_ENTRY = new
|
|
193
|
+
export const EXAMPLE_INDIVIDUAL_ORGANIZATION_DISABLE_ENTRY = new IndividualOrganizationLifecycleEditor()
|
|
194
194
|
.setClaims(EXAMPLE_INDIVIDUAL_DISABLE_MESSAGE.claims)
|
|
195
195
|
.setOperation(IndividualOrganizationLifecycleOperations.Disable)
|
|
196
196
|
.setRequestType(EXAMPLE_INDIVIDUAL_ORGANIZATION_DISABLE_REQUEST_TYPE)
|
|
197
197
|
.buildCurrentGwDataEntry();
|
|
198
|
-
export const EXAMPLE_INDIVIDUAL_ORGANIZATION_DISABLE_PAYLOAD = new
|
|
198
|
+
export const EXAMPLE_INDIVIDUAL_ORGANIZATION_DISABLE_PAYLOAD = new IndividualOrganizationLifecycleEditor()
|
|
199
199
|
.setClaims(EXAMPLE_INDIVIDUAL_DISABLE_MESSAGE.claims)
|
|
200
200
|
.setOperation(IndividualOrganizationLifecycleOperations.Disable)
|
|
201
201
|
.setRequestType(EXAMPLE_INDIVIDUAL_ORGANIZATION_DISABLE_REQUEST_TYPE)
|
|
@@ -221,12 +221,12 @@ export const EXAMPLE_INDIVIDUAL_DELETE_MESSAGE = {
|
|
|
221
221
|
keepsMinimumAuditTrailRequiredByLaw: true,
|
|
222
222
|
},
|
|
223
223
|
};
|
|
224
|
-
export const EXAMPLE_INDIVIDUAL_ORGANIZATION_PURGE_ENTRY = new
|
|
224
|
+
export const EXAMPLE_INDIVIDUAL_ORGANIZATION_PURGE_ENTRY = new IndividualOrganizationLifecycleEditor()
|
|
225
225
|
.setClaims(EXAMPLE_INDIVIDUAL_DISABLE_MESSAGE.claims)
|
|
226
226
|
.setOperation(IndividualOrganizationLifecycleOperations.Purge)
|
|
227
227
|
.setRequestType(EXAMPLE_INDIVIDUAL_ORGANIZATION_PURGE_REQUEST_TYPE)
|
|
228
228
|
.buildCurrentGwDataEntry();
|
|
229
|
-
export const EXAMPLE_INDIVIDUAL_ORGANIZATION_PURGE_PAYLOAD = new
|
|
229
|
+
export const EXAMPLE_INDIVIDUAL_ORGANIZATION_PURGE_PAYLOAD = new IndividualOrganizationLifecycleEditor()
|
|
230
230
|
.setClaims(EXAMPLE_INDIVIDUAL_DISABLE_MESSAGE.claims)
|
|
231
231
|
.setOperation(IndividualOrganizationLifecycleOperations.Purge)
|
|
232
232
|
.setRequestType(EXAMPLE_INDIVIDUAL_ORGANIZATION_PURGE_REQUEST_TYPE)
|
|
@@ -32,7 +32,6 @@ export declare const EXAMPLE_ACTIVATE_ORGANIZATION_FROM_ICA_PROOF_INPUT: {
|
|
|
32
32
|
};
|
|
33
33
|
};
|
|
34
34
|
readonly additionalClaims: {
|
|
35
|
-
readonly "org.schema.Organization.alternateName": "acme";
|
|
36
35
|
readonly "org.schema.Organization.legalName": "ACME HEALTH SL";
|
|
37
36
|
readonly "org.schema.Organization.identifier.additionalType": "taxID";
|
|
38
37
|
readonly "org.schema.Organization.identifier.value": "VATES-B00112233";
|
|
@@ -14,7 +14,6 @@ export const EXAMPLE_ACTIVATE_ORGANIZATION_FROM_ICA_PROOF_INPUT = {
|
|
|
14
14
|
vpToken: '<ica-proof-token>',
|
|
15
15
|
controller: EXAMPLE_CONTROLLER_BINDING,
|
|
16
16
|
additionalClaims: {
|
|
17
|
-
[ClaimsOrganizationSchemaorg.alternateName]: 'acme',
|
|
18
17
|
[ClaimsOrganizationSchemaorg.legalName]: 'ACME HEALTH SL',
|
|
19
18
|
[ClaimsOrganizationSchemaorg.identifierType]: 'taxID',
|
|
20
19
|
[ClaimsOrganizationSchemaorg.identifierValue]: 'VATES-B00112233',
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared fixtures for profile-runtime tests and 101 examples.
|
|
3
|
+
*
|
|
4
|
+
* Keep runtime-class, key-access, secret-kind, app-type, and local secret
|
|
5
|
+
* placeholders here so SDK packages do not re-inline them in their own tests.
|
|
6
|
+
*/
|
|
7
|
+
export declare const EXAMPLE_PROFILE_APP_TYPE_FAMILY: "Family";
|
|
8
|
+
export declare const EXAMPLE_PROFILE_RUNTIME_CLASS_SERVER: "server";
|
|
9
|
+
export declare const EXAMPLE_PROFILE_RUNTIME_CLASS_FRONTEND: "frontend";
|
|
10
|
+
export declare const EXAMPLE_PROFILE_KEY_ACCESS_MODE_SERVER: "unlock-encrypted-keys";
|
|
11
|
+
export declare const EXAMPLE_PROFILE_KEY_ACCESS_MODE_FRONTEND: "derive-from-seed";
|
|
12
|
+
export declare const EXAMPLE_PROFILE_CONNECTION_SECRET_KIND_PIN_PASSWORD: "pin-password";
|
|
13
|
+
export declare const EXAMPLE_PROFILE_LOCAL_PIN_PASSWORD_BACKEND: "local-backend-pin";
|
|
14
|
+
export declare const EXAMPLE_PROFILE_LOCAL_PIN_PASSWORD_FRONTEND: "local-frontend-pin";
|
|
15
|
+
export declare const EXAMPLE_PROFILE_CONNECTION_PIN_PASSWORD: "subject-channel-pin";
|
|
16
|
+
export declare const EXAMPLE_PROFILE_RUNTIME_JOB_ID: "job-id";
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// Copyright 2026 Antifraud Services Inc. under the Apache License, Version 2.0.
|
|
2
|
+
import { ActorRuntimeClasses, ConnectionSecretKinds, KeyAccessModes, ProfileAppTypes, } from '../constants/profile-runtime.js';
|
|
3
|
+
/**
|
|
4
|
+
* Shared fixtures for profile-runtime tests and 101 examples.
|
|
5
|
+
*
|
|
6
|
+
* Keep runtime-class, key-access, secret-kind, app-type, and local secret
|
|
7
|
+
* placeholders here so SDK packages do not re-inline them in their own tests.
|
|
8
|
+
*/
|
|
9
|
+
export const EXAMPLE_PROFILE_APP_TYPE_FAMILY = ProfileAppTypes.Family;
|
|
10
|
+
export const EXAMPLE_PROFILE_RUNTIME_CLASS_SERVER = ActorRuntimeClasses.Server;
|
|
11
|
+
export const EXAMPLE_PROFILE_RUNTIME_CLASS_FRONTEND = ActorRuntimeClasses.Frontend;
|
|
12
|
+
export const EXAMPLE_PROFILE_KEY_ACCESS_MODE_SERVER = KeyAccessModes.UnlockEncryptedKeys;
|
|
13
|
+
export const EXAMPLE_PROFILE_KEY_ACCESS_MODE_FRONTEND = KeyAccessModes.DeriveFromSeed;
|
|
14
|
+
export const EXAMPLE_PROFILE_CONNECTION_SECRET_KIND_PIN_PASSWORD = ConnectionSecretKinds.PinPassword;
|
|
15
|
+
export const EXAMPLE_PROFILE_LOCAL_PIN_PASSWORD_BACKEND = 'local-backend-pin';
|
|
16
|
+
export const EXAMPLE_PROFILE_LOCAL_PIN_PASSWORD_FRONTEND = 'local-frontend-pin';
|
|
17
|
+
export const EXAMPLE_PROFILE_CONNECTION_PIN_PASSWORD = 'subject-channel-pin';
|
|
18
|
+
export const EXAMPLE_PROFILE_RUNTIME_JOB_ID = 'job-id';
|
|
@@ -187,6 +187,15 @@ export declare const EXAMPLE_CONSENT_OPERATION_THREAD_ID: "thread-consent-exampl
|
|
|
187
187
|
export declare const EXAMPLE_CONSENT_PERIOD_START: "2026-05-20T00:00:00Z";
|
|
188
188
|
export declare const EXAMPLE_COMMUNICATION_UUID: "urn:uuid:communication-example-001";
|
|
189
189
|
export declare const EXAMPLE_COMMUNICATION_IDENTIFIER: "urn:uuid:communication-example-001";
|
|
190
|
+
export declare const EXAMPLE_COMMUNICATION_THREAD_ID: "thread-communication-example-001";
|
|
191
|
+
export declare const EXAMPLE_COMMUNICATION_PARTICIPANT_SEARCH_SUBJECT_DID: string;
|
|
192
|
+
export declare const EXAMPLE_COMMUNICATION_PARTICIPANT_SENDER_DID: "did:web:provider.example.org";
|
|
193
|
+
export declare const EXAMPLE_COMMUNICATION_PARTICIPANT_USER_DID: string;
|
|
194
|
+
export declare const EXAMPLE_COMMUNICATION_PARTICIPANT_EMAIL_USER: "family.owner@example.org";
|
|
195
|
+
export declare const EXAMPLE_COMMUNICATION_PARTICIPANT_EMAIL_RECIPIENT: "nurse.oncall@example.org";
|
|
196
|
+
export declare const EXAMPLE_COMMUNICATION_PARTICIPANT_TEL_RECIPIENT: "+34600111222";
|
|
197
|
+
export declare const EXAMPLE_COMMUNICATION_SEARCH_CATEGORY: string;
|
|
198
|
+
export declare const EXAMPLE_COMMUNICATION_SEARCH_TOPIC: "care-plan-follow-up";
|
|
190
199
|
export declare const EXAMPLE_IPS_BUNDLE_NOTE_TEXT: "IPS ingestion request";
|
|
191
200
|
export declare const EXAMPLE_CONTENT_TYPE_APPLICATION_JSON: "application/json";
|
|
192
201
|
export declare const EXAMPLE_CONTENT_TYPE_FHIR_JSON: "application/fhir+json";
|
package/dist/examples/shared.js
CHANGED
|
@@ -226,6 +226,15 @@ export const EXAMPLE_CONSENT_OPERATION_THREAD_ID = 'thread-consent-example-001';
|
|
|
226
226
|
export const EXAMPLE_CONSENT_PERIOD_START = '2026-05-20T00:00:00Z';
|
|
227
227
|
export const EXAMPLE_COMMUNICATION_UUID = 'urn:uuid:communication-example-001';
|
|
228
228
|
export const EXAMPLE_COMMUNICATION_IDENTIFIER = EXAMPLE_COMMUNICATION_UUID;
|
|
229
|
+
export const EXAMPLE_COMMUNICATION_THREAD_ID = 'thread-communication-example-001';
|
|
230
|
+
export const EXAMPLE_COMMUNICATION_PARTICIPANT_SEARCH_SUBJECT_DID = EXAMPLE_SUBJECT_DID;
|
|
231
|
+
export const EXAMPLE_COMMUNICATION_PARTICIPANT_SENDER_DID = EXAMPLE_TENANT_SERVICE_DID;
|
|
232
|
+
export const EXAMPLE_COMMUNICATION_PARTICIPANT_USER_DID = EXAMPLE_RELATED_PERSON_MEMBER_DID;
|
|
233
|
+
export const EXAMPLE_COMMUNICATION_PARTICIPANT_EMAIL_USER = 'family.owner@example.org';
|
|
234
|
+
export const EXAMPLE_COMMUNICATION_PARTICIPANT_EMAIL_RECIPIENT = 'nurse.oncall@example.org';
|
|
235
|
+
export const EXAMPLE_COMMUNICATION_PARTICIPANT_TEL_RECIPIENT = '+34600111222';
|
|
236
|
+
export const EXAMPLE_COMMUNICATION_SEARCH_CATEGORY = CommunicationCategoryCodes.Notification.attributeValue;
|
|
237
|
+
export const EXAMPLE_COMMUNICATION_SEARCH_TOPIC = 'care-plan-follow-up';
|
|
229
238
|
export const EXAMPLE_IPS_BUNDLE_NOTE_TEXT = 'IPS ingestion request';
|
|
230
239
|
export const EXAMPLE_CONTENT_TYPE_APPLICATION_JSON = 'application/json';
|
|
231
240
|
export const EXAMPLE_CONTENT_TYPE_FHIR_JSON = 'application/fhir+json';
|
|
@@ -27,6 +27,17 @@ export type AlgMlDsa2 = "ML-DSA-44";
|
|
|
27
27
|
export type AlgMlDsa3 = "ML-DSA-65";
|
|
28
28
|
export type AlgMlDsa5 = "ML-DSA-87";
|
|
29
29
|
export type MldsaAlg = AlgMlDsa2 | AlgMlDsa3 | AlgMlDsa5;
|
|
30
|
+
/**
|
|
31
|
+
* Base JWKs used for RFC 7638 thumbprint calculation.
|
|
32
|
+
*
|
|
33
|
+
* Mapping used by this codebase:
|
|
34
|
+
* - ML-KEM uses `OKP` with `crv`
|
|
35
|
+
* - ML-DSA uses `AKP` with `alg` and `pub`
|
|
36
|
+
* - classical EC uses `EC` with `crv`, `x`, `y`
|
|
37
|
+
*
|
|
38
|
+
* Note that ML-DSA does not use `crv` here. The algorithm family/strength is
|
|
39
|
+
* captured by `alg` instead, for example `ML-DSA-44`.
|
|
40
|
+
*/
|
|
30
41
|
export type MlkemBaseJwk = {
|
|
31
42
|
kty: "OKP";
|
|
32
43
|
crv: MlkemCurve;
|
|
@@ -52,6 +63,10 @@ export interface MldsaPublicJwk extends MldsaBaseJwk {
|
|
|
52
63
|
}
|
|
53
64
|
/**
|
|
54
65
|
* Represents a public key for classic cryptography algorithms like Elliptic Curve.
|
|
66
|
+
*
|
|
67
|
+
* The RFC 7638 thumbprint for these keys is derived from `kty`, `crv`, `x`,
|
|
68
|
+
* and `y`. This means curves such as `P-256`, `P-384`, and `secp256k1` are
|
|
69
|
+
* covered through the `crv` field.
|
|
55
70
|
*/
|
|
56
71
|
export interface ClassicPublicJwk {
|
|
57
72
|
kty: "EC";
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { PublicJwk } from '../interfaces/Cryptography.types';
|
|
2
2
|
import { type IssueSeverityAttentionCode } from './issue';
|
|
3
3
|
import { JwkSet } from './jwk';
|
|
4
|
+
import { DidCommDecodedMetadata } from './confidential-message';
|
|
4
5
|
/**
|
|
5
6
|
* Public key binding for a human actor/controller identity.
|
|
6
7
|
*
|
|
@@ -79,6 +80,14 @@ export interface OrganizationActivationRequest extends ActivationProofInput {
|
|
|
79
80
|
*/
|
|
80
81
|
representativeCredential?: unknown;
|
|
81
82
|
}
|
|
83
|
+
/**
|
|
84
|
+
* Technical metadata mirrored into plaintext DIDComm payloads when no real
|
|
85
|
+
* outer JWS/JWE envelope is present on the wire.
|
|
86
|
+
*
|
|
87
|
+
* This must be treated as transport compatibility metadata only. It does not
|
|
88
|
+
* replace canonical activation fields such as `vp_token` or `controller.*`.
|
|
89
|
+
*/
|
|
90
|
+
export type DidcommPlaintextTransportMetadata = DidCommDecodedMetadata;
|
|
82
91
|
/**
|
|
83
92
|
* Structured validation issue emitted by bootstrap validators.
|
|
84
93
|
*/
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type ActivationRepresentativePolicyErrorCode = '
|
|
1
|
+
export type ActivationRepresentativePolicyErrorCode = 'MISSING_REPRESENTATIVE_SUBJECT_ID' | 'MISSING_REPRESENTATIVE_ROLE_RESPRSN' | 'MISSING_REPRESENTATIVE_CREDENTIAL_BINDING' | 'REPRESENTATIVE_TAXID_MISMATCH';
|
|
2
2
|
export type ActivationServiceAuthorizationPolicyErrorCode = 'MISSING_ORGANIZATION_SERVICE_CATEGORY' | 'MISSING_ORGANIZATION_SERVICE_TYPE' | 'UNAUTHORIZED_ORGANIZATION_SERVICE_CATEGORY' | 'UNAUTHORIZED_ORGANIZATION_SERVICE_TYPE';
|
|
3
3
|
export type ActivationRepresentativePolicyError = {
|
|
4
4
|
code: ActivationRepresentativePolicyErrorCode;
|
|
@@ -48,6 +48,14 @@ export declare function hasRoleCode(roleCode: string | undefined, requiredCode?:
|
|
|
48
48
|
/**
|
|
49
49
|
* Extracts representative signing/binding continuity data from `credentialSubject.hasCredential`.
|
|
50
50
|
*
|
|
51
|
+
* Security note:
|
|
52
|
+
* - this field proves continuity of the controller signing/binding key
|
|
53
|
+
* - it is intentionally different from `credentialSubject.sameAs`, which
|
|
54
|
+
* proves continuity of the representative public identity alias (for example
|
|
55
|
+
* email-derived `urn:multibase:z...`)
|
|
56
|
+
* - production-grade activation flows are strongest when both dimensions are
|
|
57
|
+
* present in the ICA-issued representative VC
|
|
58
|
+
*
|
|
51
59
|
* Compatibility rules:
|
|
52
60
|
* - legacy VC payloads may still carry `hasCredential.material`
|
|
53
61
|
* - newer payloads may carry the same semantic value in `hasCredential.value`
|
|
@@ -56,12 +64,40 @@ export declare function hasRoleCode(roleCode: string | undefined, requiredCode?:
|
|
|
56
64
|
* @param representativeCredential Candidate representative credential.
|
|
57
65
|
*/
|
|
58
66
|
export declare function extractRepresentativeCredentialBinding(representativeCredential: unknown): string | undefined;
|
|
67
|
+
/**
|
|
68
|
+
* Extracts the representative subject identifier from `credentialSubject.id`.
|
|
69
|
+
*
|
|
70
|
+
* ICA currently models the natural person with a stable person URN while the
|
|
71
|
+
* controller/bootstrap continuity is carried in sibling claims:
|
|
72
|
+
* - `sameAs` for public identity continuity
|
|
73
|
+
* - `hasCredential` for key-binding continuity
|
|
74
|
+
*
|
|
75
|
+
* Activation policy must therefore accept the canonical person URN form and
|
|
76
|
+
* must not require a representative `did:web`.
|
|
77
|
+
*
|
|
78
|
+
* @param representativeCredential Candidate representative credential.
|
|
79
|
+
*/
|
|
80
|
+
export declare function extractRepresentativeSubjectId(representativeCredential: unknown): string | undefined;
|
|
59
81
|
/**
|
|
60
82
|
* Extracts a `did:web:` identifier from a VC-like credential.
|
|
61
83
|
*
|
|
62
84
|
* @param credential Candidate credential.
|
|
63
85
|
*/
|
|
64
86
|
export declare function extractDidWebFromCredential(credential: unknown): string | undefined;
|
|
87
|
+
/**
|
|
88
|
+
* Checks whether the representative role expresses the activation-controller
|
|
89
|
+
* semantics accepted by GW.
|
|
90
|
+
*
|
|
91
|
+
* Compatibility rules:
|
|
92
|
+
* - historical GW payloads may still use HL7/FHIR `RESPRSN`
|
|
93
|
+
* - current ICA person credentials may encode the legal representative role as
|
|
94
|
+
* ISCO-08 `1120`, either tokenized (`ISCO-08|1120`) or as the canonical
|
|
95
|
+
* ILO URN (`urn:ilo:ilostat:isco-08:1120`)
|
|
96
|
+
*
|
|
97
|
+
* @param roleCode Candidate role token extracted from the credential.
|
|
98
|
+
* @param requiredCode Required GW compatibility code, defaults to `RESPRSN`.
|
|
99
|
+
*/
|
|
100
|
+
export declare function hasActivationRepresentativeRole(roleCode: string | undefined, requiredCode?: string): boolean;
|
|
65
101
|
/**
|
|
66
102
|
* Extracts the categories authorized by an ICA-issued organization credential.
|
|
67
103
|
*
|
|
@@ -123,6 +159,14 @@ export declare function isMemberDidWebUnderOwner(memberDidWeb: string, ownerDidW
|
|
|
123
159
|
/**
|
|
124
160
|
* Validates the activation representative policy against organization and representative credentials.
|
|
125
161
|
*
|
|
162
|
+
* The representative proof model is intentionally two-dimensional:
|
|
163
|
+
* - `credentialSubject.sameAs` expresses public identity continuity
|
|
164
|
+
* - `credentialSubject.hasCredential.material` expresses signing-key continuity
|
|
165
|
+
*
|
|
166
|
+
* For GW activation, the key-binding dimension is the hard requirement
|
|
167
|
+
* enforced here. The public-identity dimension may still be used by higher
|
|
168
|
+
* layers for stronger demo/production matching and auditability.
|
|
169
|
+
*
|
|
126
170
|
* @param input.organizationCredential Candidate organization credential.
|
|
127
171
|
* @param input.representativeCredential Candidate representative credential.
|
|
128
172
|
* @param input.requiredRoleCode Required representative role, defaults to `RESPRSN`.
|
|
@@ -106,6 +106,14 @@ export function hasRoleCode(roleCode, requiredCode = 'RESPRSN') {
|
|
|
106
106
|
/**
|
|
107
107
|
* Extracts representative signing/binding continuity data from `credentialSubject.hasCredential`.
|
|
108
108
|
*
|
|
109
|
+
* Security note:
|
|
110
|
+
* - this field proves continuity of the controller signing/binding key
|
|
111
|
+
* - it is intentionally different from `credentialSubject.sameAs`, which
|
|
112
|
+
* proves continuity of the representative public identity alias (for example
|
|
113
|
+
* email-derived `urn:multibase:z...`)
|
|
114
|
+
* - production-grade activation flows are strongest when both dimensions are
|
|
115
|
+
* present in the ICA-issued representative VC
|
|
116
|
+
*
|
|
109
117
|
* Compatibility rules:
|
|
110
118
|
* - legacy VC payloads may still carry `hasCredential.material`
|
|
111
119
|
* - newer payloads may carry the same semantic value in `hasCredential.value`
|
|
@@ -141,6 +149,27 @@ function extractCredentialBindingValue(value) {
|
|
|
141
149
|
|| '').trim();
|
|
142
150
|
return candidate || undefined;
|
|
143
151
|
}
|
|
152
|
+
/**
|
|
153
|
+
* Extracts the representative subject identifier from `credentialSubject.id`.
|
|
154
|
+
*
|
|
155
|
+
* ICA currently models the natural person with a stable person URN while the
|
|
156
|
+
* controller/bootstrap continuity is carried in sibling claims:
|
|
157
|
+
* - `sameAs` for public identity continuity
|
|
158
|
+
* - `hasCredential` for key-binding continuity
|
|
159
|
+
*
|
|
160
|
+
* Activation policy must therefore accept the canonical person URN form and
|
|
161
|
+
* must not require a representative `did:web`.
|
|
162
|
+
*
|
|
163
|
+
* @param representativeCredential Candidate representative credential.
|
|
164
|
+
*/
|
|
165
|
+
export function extractRepresentativeSubjectId(representativeCredential) {
|
|
166
|
+
const obj = asObject(representativeCredential);
|
|
167
|
+
if (!obj)
|
|
168
|
+
return undefined;
|
|
169
|
+
const subject = extractCredentialSubject(obj);
|
|
170
|
+
const subjectId = String(subject?.id || '').trim();
|
|
171
|
+
return subjectId || undefined;
|
|
172
|
+
}
|
|
144
173
|
/**
|
|
145
174
|
* Extracts a `did:web:` identifier from a VC-like credential.
|
|
146
175
|
*
|
|
@@ -154,6 +183,27 @@ export function extractDidWebFromCredential(credential) {
|
|
|
154
183
|
const didCandidate = String(subject?.id || obj.id || '').trim();
|
|
155
184
|
return didCandidate.startsWith('did:web:') ? didCandidate : undefined;
|
|
156
185
|
}
|
|
186
|
+
/**
|
|
187
|
+
* Checks whether the representative role expresses the activation-controller
|
|
188
|
+
* semantics accepted by GW.
|
|
189
|
+
*
|
|
190
|
+
* Compatibility rules:
|
|
191
|
+
* - historical GW payloads may still use HL7/FHIR `RESPRSN`
|
|
192
|
+
* - current ICA person credentials may encode the legal representative role as
|
|
193
|
+
* ISCO-08 `1120`, either tokenized (`ISCO-08|1120`) or as the canonical
|
|
194
|
+
* ILO URN (`urn:ilo:ilostat:isco-08:1120`)
|
|
195
|
+
*
|
|
196
|
+
* @param roleCode Candidate role token extracted from the credential.
|
|
197
|
+
* @param requiredCode Required GW compatibility code, defaults to `RESPRSN`.
|
|
198
|
+
*/
|
|
199
|
+
export function hasActivationRepresentativeRole(roleCode, requiredCode = 'RESPRSN') {
|
|
200
|
+
if (hasRoleCode(roleCode, requiredCode))
|
|
201
|
+
return true;
|
|
202
|
+
const normalized = String(roleCode || '').trim().toUpperCase();
|
|
203
|
+
if (!normalized)
|
|
204
|
+
return false;
|
|
205
|
+
return /(?:^|[|:])1120$/.test(normalized);
|
|
206
|
+
}
|
|
157
207
|
/**
|
|
158
208
|
* Extracts the categories authorized by an ICA-issued organization credential.
|
|
159
209
|
*
|
|
@@ -267,19 +317,27 @@ export function isMemberDidWebUnderOwner(memberDidWeb, ownerDidWeb) {
|
|
|
267
317
|
/**
|
|
268
318
|
* Validates the activation representative policy against organization and representative credentials.
|
|
269
319
|
*
|
|
320
|
+
* The representative proof model is intentionally two-dimensional:
|
|
321
|
+
* - `credentialSubject.sameAs` expresses public identity continuity
|
|
322
|
+
* - `credentialSubject.hasCredential.material` expresses signing-key continuity
|
|
323
|
+
*
|
|
324
|
+
* For GW activation, the key-binding dimension is the hard requirement
|
|
325
|
+
* enforced here. The public-identity dimension may still be used by higher
|
|
326
|
+
* layers for stronger demo/production matching and auditability.
|
|
327
|
+
*
|
|
270
328
|
* @param input.organizationCredential Candidate organization credential.
|
|
271
329
|
* @param input.representativeCredential Candidate representative credential.
|
|
272
330
|
* @param input.requiredRoleCode Required representative role, defaults to `RESPRSN`.
|
|
273
331
|
*/
|
|
274
332
|
export function validateActivationRepresentativePolicy(input) {
|
|
275
333
|
const errors = [];
|
|
276
|
-
const
|
|
277
|
-
?
|
|
334
|
+
const representativeSubjectId = input.representativeCredential
|
|
335
|
+
? extractRepresentativeSubjectId(input.representativeCredential)
|
|
278
336
|
: undefined;
|
|
279
|
-
if (input.representativeCredential && !
|
|
337
|
+
if (input.representativeCredential && !representativeSubjectId) {
|
|
280
338
|
errors.push({
|
|
281
|
-
code: '
|
|
282
|
-
message: 'ICA-issued representative credential is missing credentialSubject.id
|
|
339
|
+
code: 'MISSING_REPRESENTATIVE_SUBJECT_ID',
|
|
340
|
+
message: 'ICA-issued representative credential is missing credentialSubject.id.',
|
|
283
341
|
});
|
|
284
342
|
}
|
|
285
343
|
if (!input.representativeCredential)
|
|
@@ -293,10 +351,10 @@ export function validateActivationRepresentativePolicy(input) {
|
|
|
293
351
|
});
|
|
294
352
|
}
|
|
295
353
|
const roleCode = extractRepresentativeRoleCode(input.representativeCredential);
|
|
296
|
-
if (!
|
|
354
|
+
if (!hasActivationRepresentativeRole(roleCode, input.requiredRoleCode || 'RESPRSN')) {
|
|
297
355
|
errors.push({
|
|
298
356
|
code: 'MISSING_REPRESENTATIVE_ROLE_RESPRSN',
|
|
299
|
-
message: 'ICA-issued representative credential must include
|
|
357
|
+
message: 'ICA-issued representative credential must include legal representative role semantics (RESPRSN or ISCO-08 1120) in credentialSubject.hasOccupation.',
|
|
300
358
|
});
|
|
301
359
|
}
|
|
302
360
|
const binding = extractRepresentativeCredentialBinding(input.representativeCredential);
|