gdc-common-utils-ts 2.5.0 → 2.5.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 +3 -1
- package/dist/constants/healthcare.d.ts +13 -12
- package/dist/constants/healthcare.js +25 -25
- package/dist/constants/verifiable-credentials.d.ts +8 -0
- package/dist/constants/verifiable-credentials.js +10 -0
- package/dist/examples/employee.d.ts +1 -1
- package/dist/examples/employee.js +2 -2
- package/dist/examples/ica-activation-proof.d.ts +1 -3
- package/dist/examples/ica-activation-proof.js +1 -3
- package/dist/examples/ica-verify-response.d.ts +2 -2
- package/dist/examples/ica-verify-response.js +1 -1
- package/dist/models/device-license.d.ts +2 -2
- package/dist/models/did.d.ts +2 -0
- package/dist/utils/activation-policy.d.ts +2 -5
- package/dist/utils/activation-policy.js +4 -12
- package/dist/utils/actor-identifier.d.ts +9 -13
- package/dist/utils/actor-identifier.js +20 -21
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.js +1 -0
- package/dist/utils/jwk-thumbprint.d.ts +8 -0
- package/dist/utils/jwk-thumbprint.js +11 -0
- package/dist/utils/legal-organization-onboarding-editor.d.ts +2 -0
- package/dist/utils/legal-organization-onboarding-editor.js +1 -3
- package/dist/utils/legal-organization-verification-result.d.ts +45 -0
- package/dist/utils/legal-organization-verification-result.js +78 -0
- package/dist/utils/legal-organization-verification-transaction.d.ts +13 -0
- package/dist/utils/legal-organization-verification-transaction.js +6 -0
- package/dist/utils/organization-registration-authorization.d.ts +65 -0
- package/dist/utils/organization-registration-authorization.js +112 -0
- package/dist/utils/vp-token.d.ts +14 -0
- package/dist/utils/vp-token.js +19 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -450,8 +450,10 @@ The canonical API contract should live in JSDoc on exported code. The README act
|
|
|
450
450
|
- [`buildSmartCompositionReadScope(...)`](src/utils/smart-scope.ts)
|
|
451
451
|
- Builds the current CORE GW pinned SMART root scope for `organization/Composition...` token requests.
|
|
452
452
|
- This is the preferred first scope to teach when the backend only needs subject-scoped read access.
|
|
453
|
-
- [`getOrganizationCredentialFromVpToken(...)`, `getLegalRepresentativeCredentialFromVpToken(...)`](src/utils/vp-token.ts)
|
|
453
|
+
- [`getOrganizationCredentialFromVpToken(...)`, `getLegalRepresentativeCredentialFromVpToken(...)`, `getOrganizationControllerCredentialFromVpToken(...)`](src/utils/vp-token.ts)
|
|
454
454
|
- Extract typed VC objects from a VP token when GW/SDK flows carry canonical proof only in `vp_token`.
|
|
455
|
+
- [`readOrganizationControllerCredentialsFromResponseBody(...)`](src/utils/legal-organization-verification-result.ts)
|
|
456
|
+
- Reads every independently issued controller service VC from direct ICA or projected GW responses; companion helpers expose `owner.sameAs` and its JWK-thumbprint binding without falling back to the legal representative.
|
|
455
457
|
- [`docs/101-VP_TOKEN.md`](docs/101-VP_TOKEN.md)
|
|
456
458
|
- Step-by-step guide for building the canonical compact `vp_token` string from organization and representative VCs.
|
|
457
459
|
- [`validateCommunicationResourceFhirR4(...)`](src/utils/communication-fhir-r4.ts)
|
|
@@ -1711,7 +1711,8 @@ export declare const HealthcareConsentPurposes: Readonly<{
|
|
|
1711
1711
|
readonly RecordsManagement: "RECORDMGT";
|
|
1712
1712
|
}>;
|
|
1713
1713
|
export declare const HealthcareActorRoles: Readonly<{
|
|
1714
|
-
|
|
1714
|
+
/** Bare HL7 v3 RoleCode used for an organization controller. */
|
|
1715
|
+
readonly Controller: "RESPRSN";
|
|
1715
1716
|
readonly MedicalDoctors: "ISCO-08|221";
|
|
1716
1717
|
readonly GeneralistMedicalPractitioner: "ISCO-08|2211";
|
|
1717
1718
|
readonly SpecialistMedicalPractitioner: "ISCO-08|2212";
|
|
@@ -1728,7 +1729,7 @@ export declare const HealthcareActorRoles: Readonly<{
|
|
|
1728
1729
|
readonly MedicalSecretary: "ISCO-08|3344";
|
|
1729
1730
|
}>;
|
|
1730
1731
|
export declare const HealthcareActorRoleCodes: Readonly<{
|
|
1731
|
-
readonly Controller: "
|
|
1732
|
+
readonly Controller: "RESPRSN";
|
|
1732
1733
|
readonly MedicalDoctors: "221";
|
|
1733
1734
|
readonly GeneralistMedicalPractitioner: "2211";
|
|
1734
1735
|
readonly SpecialistMedicalPractitioner: "2212";
|
|
@@ -1779,16 +1780,16 @@ export declare const HealthcareRolesByFamily: Readonly<{
|
|
|
1779
1780
|
}>;
|
|
1780
1781
|
export declare const HealthcareAllRolesByClaim: Readonly<Record<string, HealthcareActorRoleDescriptor>>;
|
|
1781
1782
|
export declare const HealthcareProfessionalRoleCodesBySector: Readonly<{
|
|
1782
|
-
readonly "health-care": readonly ("
|
|
1783
|
-
readonly "health-research": readonly ("
|
|
1784
|
-
readonly "health-tech": readonly "
|
|
1785
|
-
readonly "health-insurance": readonly "
|
|
1786
|
-
readonly "animal-care": readonly ("
|
|
1787
|
-
readonly "animal-research": readonly ("
|
|
1788
|
-
readonly "animal-insurance": readonly "
|
|
1789
|
-
readonly "animal-tech": readonly "
|
|
1790
|
-
readonly "onehealth-research": readonly ("
|
|
1791
|
-
readonly "onehealth-tech": readonly "
|
|
1783
|
+
readonly "health-care": readonly ("RESPRSN" | "221" | "2211" | "2212" | "2221" | "2222" | "2240" | "3344")[];
|
|
1784
|
+
readonly "health-research": readonly ("RESPRSN" | "221" | "2211" | "2212" | "3344")[];
|
|
1785
|
+
readonly "health-tech": readonly "RESPRSN"[];
|
|
1786
|
+
readonly "health-insurance": readonly "RESPRSN"[];
|
|
1787
|
+
readonly "animal-care": readonly ("RESPRSN" | "2250")[];
|
|
1788
|
+
readonly "animal-research": readonly ("RESPRSN" | "2250")[];
|
|
1789
|
+
readonly "animal-insurance": readonly "RESPRSN"[];
|
|
1790
|
+
readonly "animal-tech": readonly "RESPRSN"[];
|
|
1791
|
+
readonly "onehealth-research": readonly ("RESPRSN" | "221" | "2211" | "2212" | "2250" | "3344")[];
|
|
1792
|
+
readonly "onehealth-tech": readonly "RESPRSN"[];
|
|
1792
1793
|
}>;
|
|
1793
1794
|
export declare const HealthcareProfessionalRolesBySector: Readonly<{
|
|
1794
1795
|
readonly "health-care": Readonly<Record<string, Readonly<{
|
|
@@ -343,7 +343,8 @@ export const HealthcareConsentPurposes = Object.freeze({
|
|
|
343
343
|
RecordsManagement: 'RECORDMGT',
|
|
344
344
|
});
|
|
345
345
|
export const HealthcareActorRoles = Object.freeze({
|
|
346
|
-
|
|
346
|
+
/** Bare HL7 v3 RoleCode used for an organization controller. */
|
|
347
|
+
Controller: 'RESPRSN',
|
|
347
348
|
MedicalDoctors: 'ISCO-08|221',
|
|
348
349
|
GeneralistMedicalPractitioner: 'ISCO-08|2211',
|
|
349
350
|
SpecialistMedicalPractitioner: 'ISCO-08|2212',
|
|
@@ -360,7 +361,7 @@ export const HealthcareActorRoles = Object.freeze({
|
|
|
360
361
|
MedicalSecretary: 'ISCO-08|3344',
|
|
361
362
|
});
|
|
362
363
|
export const HealthcareActorRoleCodes = Object.freeze({
|
|
363
|
-
Controller: '
|
|
364
|
+
Controller: 'RESPRSN',
|
|
364
365
|
MedicalDoctors: '221',
|
|
365
366
|
GeneralistMedicalPractitioner: '2211',
|
|
366
367
|
SpecialistMedicalPractitioner: '2212',
|
|
@@ -382,17 +383,6 @@ export const HealthcareActorRoleCodes = Object.freeze({
|
|
|
382
383
|
});
|
|
383
384
|
function buildProfessionalIscoRoles() {
|
|
384
385
|
const entries = [
|
|
385
|
-
[
|
|
386
|
-
HealthcareActorRoleCodes.Controller,
|
|
387
|
-
Object.freeze({
|
|
388
|
-
family: HealthcareRoleFamilies.ProfessionalOccupationIsco08,
|
|
389
|
-
codingSystem: ISCO08_CODING_SYSTEM,
|
|
390
|
-
code: HealthcareActorRoleCodes.Controller,
|
|
391
|
-
claim: HealthcareActorRoles.Controller,
|
|
392
|
-
i18nKey: `${ISCO08_I18N_NAMESPACE}.${HealthcareActorRoleCodes.Controller}`,
|
|
393
|
-
titleEn: 'Controller',
|
|
394
|
-
}),
|
|
395
|
-
],
|
|
396
386
|
[
|
|
397
387
|
HealthcareActorRoleCodes.MedicalDoctors,
|
|
398
388
|
Object.freeze({
|
|
@@ -519,15 +509,25 @@ export const HealthcareRolesByFamily = Object.freeze({
|
|
|
519
509
|
});
|
|
520
510
|
export const HealthcareAllRolesByClaim = Object.freeze(Object.fromEntries(Object.values(HealthcareRolesByFamily)
|
|
521
511
|
.flatMap((catalog) => Object.values(catalog))
|
|
522
|
-
.
|
|
512
|
+
.flatMap((descriptor) => [
|
|
513
|
+
[descriptor.claim, descriptor],
|
|
514
|
+
[descriptor.code, descriptor],
|
|
515
|
+
])));
|
|
523
516
|
function pickRoleCatalogByCodes(catalog, codes) {
|
|
524
517
|
return Object.freeze(Object.fromEntries(codes
|
|
525
518
|
.map((code) => [code, catalog[code]])
|
|
526
519
|
.filter((entry) => Boolean(entry[1]))));
|
|
527
520
|
}
|
|
528
521
|
function reindexRoleCatalogByClaim(catalog) {
|
|
529
|
-
return Object.freeze(Object.fromEntries(Object.values(catalog).
|
|
522
|
+
return Object.freeze(Object.fromEntries(Object.values(catalog).flatMap((descriptor) => [
|
|
523
|
+
[descriptor.claim, descriptor],
|
|
524
|
+
[descriptor.code, descriptor],
|
|
525
|
+
])));
|
|
530
526
|
}
|
|
527
|
+
const HealthcareProfessionalAndControllerRoles = Object.freeze({
|
|
528
|
+
...HealthcareRolesByFamily[HealthcareRoleFamilies.ProfessionalOccupationIsco08],
|
|
529
|
+
[HealthcareActorRoleCodes.Controller]: HealthcareRolesByFamily[HealthcareRoleFamilies.LegalRepresentativeHl7][HealthcareActorRoleCodes.Controller],
|
|
530
|
+
});
|
|
531
531
|
export const HealthcareProfessionalRoleCodesBySector = Object.freeze({
|
|
532
532
|
[DataspaceSectors.HealthCare]: Object.freeze([
|
|
533
533
|
HealthcareActorRoleCodes.Controller,
|
|
@@ -569,16 +569,16 @@ export const HealthcareProfessionalRoleCodesBySector = Object.freeze({
|
|
|
569
569
|
[DataspaceSectors.OneHealthTech]: Object.freeze([HealthcareActorRoleCodes.Controller]),
|
|
570
570
|
});
|
|
571
571
|
export const HealthcareProfessionalRolesBySector = Object.freeze({
|
|
572
|
-
[DataspaceSectors.HealthCare]: pickRoleCatalogByCodes(
|
|
573
|
-
[DataspaceSectors.HealthResearch]: pickRoleCatalogByCodes(
|
|
574
|
-
[DataspaceSectors.HealthTech]: pickRoleCatalogByCodes(
|
|
575
|
-
[DataspaceSectors.HealthInsurance]: pickRoleCatalogByCodes(
|
|
576
|
-
[DataspaceSectors.AnimalCare]: pickRoleCatalogByCodes(
|
|
577
|
-
[DataspaceSectors.AnimalResearch]: pickRoleCatalogByCodes(
|
|
578
|
-
[DataspaceSectors.AnimalInsurance]: pickRoleCatalogByCodes(
|
|
579
|
-
[DataspaceSectors.AnimalTech]: pickRoleCatalogByCodes(
|
|
580
|
-
[DataspaceSectors.OneHealthResearch]: pickRoleCatalogByCodes(
|
|
581
|
-
[DataspaceSectors.OneHealthTech]: pickRoleCatalogByCodes(
|
|
572
|
+
[DataspaceSectors.HealthCare]: pickRoleCatalogByCodes(HealthcareProfessionalAndControllerRoles, HealthcareProfessionalRoleCodesBySector[DataspaceSectors.HealthCare]),
|
|
573
|
+
[DataspaceSectors.HealthResearch]: pickRoleCatalogByCodes(HealthcareProfessionalAndControllerRoles, HealthcareProfessionalRoleCodesBySector[DataspaceSectors.HealthResearch]),
|
|
574
|
+
[DataspaceSectors.HealthTech]: pickRoleCatalogByCodes(HealthcareProfessionalAndControllerRoles, HealthcareProfessionalRoleCodesBySector[DataspaceSectors.HealthTech]),
|
|
575
|
+
[DataspaceSectors.HealthInsurance]: pickRoleCatalogByCodes(HealthcareProfessionalAndControllerRoles, HealthcareProfessionalRoleCodesBySector[DataspaceSectors.HealthInsurance]),
|
|
576
|
+
[DataspaceSectors.AnimalCare]: pickRoleCatalogByCodes(HealthcareProfessionalAndControllerRoles, HealthcareProfessionalRoleCodesBySector[DataspaceSectors.AnimalCare]),
|
|
577
|
+
[DataspaceSectors.AnimalResearch]: pickRoleCatalogByCodes(HealthcareProfessionalAndControllerRoles, HealthcareProfessionalRoleCodesBySector[DataspaceSectors.AnimalResearch]),
|
|
578
|
+
[DataspaceSectors.AnimalInsurance]: pickRoleCatalogByCodes(HealthcareProfessionalAndControllerRoles, HealthcareProfessionalRoleCodesBySector[DataspaceSectors.AnimalInsurance]),
|
|
579
|
+
[DataspaceSectors.AnimalTech]: pickRoleCatalogByCodes(HealthcareProfessionalAndControllerRoles, HealthcareProfessionalRoleCodesBySector[DataspaceSectors.AnimalTech]),
|
|
580
|
+
[DataspaceSectors.OneHealthResearch]: pickRoleCatalogByCodes(HealthcareProfessionalAndControllerRoles, HealthcareProfessionalRoleCodesBySector[DataspaceSectors.OneHealthResearch]),
|
|
581
|
+
[DataspaceSectors.OneHealthTech]: pickRoleCatalogByCodes(HealthcareProfessionalAndControllerRoles, HealthcareProfessionalRoleCodesBySector[DataspaceSectors.OneHealthTech]),
|
|
582
582
|
});
|
|
583
583
|
export const HealthcareProfessionalRolesBySectorAndClaim = Object.freeze(Object.fromEntries(Object.values(DataspaceSectors).map((sector) => [
|
|
584
584
|
sector,
|
|
@@ -28,6 +28,7 @@ export declare const ActivationCredentialTypes: Readonly<{
|
|
|
28
28
|
OrganizationCredential: "OrganizationCredential";
|
|
29
29
|
LegalOrganizationCredential: "LegalOrganizationCredential";
|
|
30
30
|
LegalRepresentativeCredential: "LegalRepresentativeCredential";
|
|
31
|
+
OrganizationControllerCredential: "OrganizationControllerCredential";
|
|
31
32
|
PersonCredential: "PersonCredential";
|
|
32
33
|
}>;
|
|
33
34
|
/**
|
|
@@ -59,6 +60,13 @@ export declare const IndividualCredentialTypes: Readonly<{
|
|
|
59
60
|
*/
|
|
60
61
|
export declare const ContractCredentialTypes: Readonly<{
|
|
61
62
|
InterTenantAccessContractCredential: "InterTenantAccessContractCredential";
|
|
63
|
+
/** Host/ICA-issued evidence that permits one controller to submit tenant registration. */
|
|
64
|
+
OrganizationRegistrationAuthorizationCredential: "OrganizationRegistrationAuthorizationCredential";
|
|
62
65
|
}>;
|
|
63
66
|
export declare const ORGANIZATION_ACTIVATION_VC_TYPES: readonly ("OrganizationCredential" | "LegalOrganizationCredential")[];
|
|
64
67
|
export declare const REPRESENTATIVE_ACTIVATION_VC_TYPES: readonly ("LegalRepresentativeCredential" | "PersonCredential")[];
|
|
68
|
+
/**
|
|
69
|
+
* Canonical credential subtype used to bind an organization tenant service to
|
|
70
|
+
* one independently authenticated controller actor and its signing key.
|
|
71
|
+
*/
|
|
72
|
+
export declare const ORGANIZATION_CONTROLLER_ACTIVATION_VC_TYPES: readonly "OrganizationControllerCredential"[];
|
|
@@ -30,6 +30,7 @@ export const ActivationCredentialTypes = Object.freeze({
|
|
|
30
30
|
OrganizationCredential: 'OrganizationCredential',
|
|
31
31
|
LegalOrganizationCredential: 'LegalOrganizationCredential',
|
|
32
32
|
LegalRepresentativeCredential: 'LegalRepresentativeCredential',
|
|
33
|
+
OrganizationControllerCredential: 'OrganizationControllerCredential',
|
|
33
34
|
PersonCredential: 'PersonCredential',
|
|
34
35
|
});
|
|
35
36
|
/**
|
|
@@ -61,6 +62,8 @@ export const IndividualCredentialTypes = Object.freeze({
|
|
|
61
62
|
*/
|
|
62
63
|
export const ContractCredentialTypes = Object.freeze({
|
|
63
64
|
InterTenantAccessContractCredential: 'InterTenantAccessContractCredential',
|
|
65
|
+
/** Host/ICA-issued evidence that permits one controller to submit tenant registration. */
|
|
66
|
+
OrganizationRegistrationAuthorizationCredential: 'OrganizationRegistrationAuthorizationCredential',
|
|
64
67
|
});
|
|
65
68
|
export const ORGANIZATION_ACTIVATION_VC_TYPES = Object.freeze([
|
|
66
69
|
ActivationCredentialTypes.OrganizationCredential,
|
|
@@ -70,3 +73,10 @@ export const REPRESENTATIVE_ACTIVATION_VC_TYPES = Object.freeze([
|
|
|
70
73
|
ActivationCredentialTypes.LegalRepresentativeCredential,
|
|
71
74
|
ActivationCredentialTypes.PersonCredential,
|
|
72
75
|
]);
|
|
76
|
+
/**
|
|
77
|
+
* Canonical credential subtype used to bind an organization tenant service to
|
|
78
|
+
* one independently authenticated controller actor and its signing key.
|
|
79
|
+
*/
|
|
80
|
+
export const ORGANIZATION_CONTROLLER_ACTIVATION_VC_TYPES = Object.freeze([
|
|
81
|
+
ActivationCredentialTypes.OrganizationControllerCredential,
|
|
82
|
+
]);
|
|
@@ -27,7 +27,7 @@ export declare const ExampleEmployeeCredentialMaterials: Readonly<{
|
|
|
27
27
|
readonly SharedProfessionalSigningKid: "did:key:z6Mkt2p7vKov6R6By7QjFv2F5x8f4H9g2m3c4n5p6q7r8s9t#z6Mkt2p7vKov6R6By7QjFv2F5x8f4H9g2m3c4n5p6q7r8s9t";
|
|
28
28
|
}>;
|
|
29
29
|
export declare const ExampleEmployeeRoles: Readonly<{
|
|
30
|
-
readonly Controller: "
|
|
30
|
+
readonly Controller: "RESPRSN";
|
|
31
31
|
readonly Doctor: "ISCO-08|2211";
|
|
32
32
|
}>;
|
|
33
33
|
export declare const EXAMPLE_EMPLOYEE_CONTROLLER_ACTIVE: ExampleEmployeeRecord;
|
|
@@ -9,12 +9,12 @@ export const ExampleEmployeeCredentialMaterials = Object.freeze({
|
|
|
9
9
|
SharedProfessionalSigningKid: 'did:key:z6Mkt2p7vKov6R6By7QjFv2F5x8f4H9g2m3c4n5p6q7r8s9t#z6Mkt2p7vKov6R6By7QjFv2F5x8f4H9g2m3c4n5p6q7r8s9t',
|
|
10
10
|
});
|
|
11
11
|
export const ExampleEmployeeRoles = Object.freeze({
|
|
12
|
-
Controller: '
|
|
12
|
+
Controller: 'RESPRSN',
|
|
13
13
|
Doctor: 'ISCO-08|2211',
|
|
14
14
|
});
|
|
15
15
|
export const EXAMPLE_EMPLOYEE_CONTROLLER_ACTIVE = Object.freeze({
|
|
16
16
|
resourceId: 'urn:uuid:11111111-1111-4111-8111-111111111111',
|
|
17
|
-
identifier: 'did:web:api.example.org:employee:shared.professional@example.org:
|
|
17
|
+
identifier: 'did:web:api.example.org:employee:shared.professional@example.org:RESPRSN',
|
|
18
18
|
email: ExampleEmployeeEmails.SharedProfessional,
|
|
19
19
|
role: ExampleEmployeeRoles.Controller,
|
|
20
20
|
status: 'active',
|
|
@@ -24,8 +24,6 @@ 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
27
|
export declare const EXAMPLE_REPRESENTATIVE_IDENTIFIER: "IDCES-99999999R";
|
|
30
28
|
export declare const EXAMPLE_REPRESENTATIVE_EMAIL: "legal.rep@example.org";
|
|
31
29
|
export declare const EXAMPLE_REPRESENTATIVE_SUBJECT_URN: "urn:person:identifier:IDCES-99999999R";
|
|
@@ -57,7 +55,7 @@ export declare const EXAMPLE_ORG_ACTIVATION_LEGAL_REPRESENTATIVE_CREDENTIAL: Rea
|
|
|
57
55
|
taxID: "ESB00112233";
|
|
58
56
|
};
|
|
59
57
|
hasOccupation: {
|
|
60
|
-
identifier: "
|
|
58
|
+
identifier: "RESPRSN";
|
|
61
59
|
};
|
|
62
60
|
hasCredential: {
|
|
63
61
|
material: "urn:ietf:params:oauth:jwk-thumbprint:sha-256:Q0ZfM0V4YW1wbGVUaHVtYnByaW50X2Jhc2U2NHVybA";
|
|
@@ -30,8 +30,6 @@ 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
33
|
export const EXAMPLE_REPRESENTATIVE_IDENTIFIER = 'IDCES-99999999R';
|
|
36
34
|
export const EXAMPLE_REPRESENTATIVE_EMAIL = 'legal.rep@example.org';
|
|
37
35
|
export const EXAMPLE_REPRESENTATIVE_SUBJECT_URN = `urn:person:identifier:${EXAMPLE_REPRESENTATIVE_IDENTIFIER}`;
|
|
@@ -69,7 +67,7 @@ export const EXAMPLE_ORG_ACTIVATION_LEGAL_REPRESENTATIVE_CREDENTIAL = Object.fre
|
|
|
69
67
|
taxID: EXAMPLE_ORGANIZATION_TAX_ID,
|
|
70
68
|
},
|
|
71
69
|
hasOccupation: {
|
|
72
|
-
identifier:
|
|
70
|
+
identifier: EXAMPLE_REPRESENTATIVE_ROLE_CODE,
|
|
73
71
|
},
|
|
74
72
|
hasCredential: {
|
|
75
73
|
material: EXAMPLE_ORG_CONTROLLER_SIGNING_KEY_ID,
|
|
@@ -99,7 +99,7 @@ export declare const EXAMPLE_VERIFY_RESPONSE_ADDRESS_TYPE: "PostalAddress";
|
|
|
99
99
|
export declare const EXAMPLE_VERIFY_RESPONSE_ADDRESS_COUNTRY: "ES";
|
|
100
100
|
export declare const EXAMPLE_VERIFY_RESPONSE_OCCUPATION_TYPE: "Occupation";
|
|
101
101
|
export declare const EXAMPLE_VERIFY_RESPONSE_OCCUPATION_NAME: "LegalRepresentative";
|
|
102
|
-
export declare const EXAMPLE_VERIFY_RESPONSE_OCCUPATION_IDENTIFIER: "
|
|
102
|
+
export declare const EXAMPLE_VERIFY_RESPONSE_OCCUPATION_IDENTIFIER: "RESPRSN";
|
|
103
103
|
export declare const EXAMPLE_VERIFY_RESPONSE_PROOF_TYPE: "JsonWebSignature2020";
|
|
104
104
|
export declare const EXAMPLE_VERIFY_RESPONSE_PROOF_PURPOSE: "assertionMethod";
|
|
105
105
|
export declare const EXAMPLE_VERIFY_RESPONSE_PROOF_VERIFICATION_METHOD: "did:web:localhost%3A3310#verification-key-001";
|
|
@@ -197,7 +197,7 @@ export declare const EXAMPLE_VERIFY_RESPONSE_PERSON_CREDENTIAL: Readonly<{
|
|
|
197
197
|
hasOccupation: {
|
|
198
198
|
'@type': "Occupation";
|
|
199
199
|
name: "LegalRepresentative";
|
|
200
|
-
identifier: "
|
|
200
|
+
identifier: "RESPRSN";
|
|
201
201
|
};
|
|
202
202
|
memberOf: {
|
|
203
203
|
'@type': "Organization";
|
|
@@ -44,7 +44,7 @@ export const EXAMPLE_VERIFY_RESPONSE_ADDRESS_TYPE = 'PostalAddress';
|
|
|
44
44
|
export const EXAMPLE_VERIFY_RESPONSE_ADDRESS_COUNTRY = 'ES';
|
|
45
45
|
export const EXAMPLE_VERIFY_RESPONSE_OCCUPATION_TYPE = 'Occupation';
|
|
46
46
|
export const EXAMPLE_VERIFY_RESPONSE_OCCUPATION_NAME = 'LegalRepresentative';
|
|
47
|
-
export const EXAMPLE_VERIFY_RESPONSE_OCCUPATION_IDENTIFIER = '
|
|
47
|
+
export const EXAMPLE_VERIFY_RESPONSE_OCCUPATION_IDENTIFIER = 'RESPRSN';
|
|
48
48
|
export const EXAMPLE_VERIFY_RESPONSE_PROOF_TYPE = 'JsonWebSignature2020';
|
|
49
49
|
export const EXAMPLE_VERIFY_RESPONSE_PROOF_PURPOSE = 'assertionMethod';
|
|
50
50
|
export const EXAMPLE_VERIFY_RESPONSE_PROOF_VERIFICATION_METHOD = 'did:web:localhost%3A3310#verification-key-001';
|
|
@@ -162,8 +162,8 @@ export interface DeviceLicense {
|
|
|
162
162
|
/** All DCR installations bound to this user/member seat. */
|
|
163
163
|
deviceBindings?: DeviceBinding[];
|
|
164
164
|
/**
|
|
165
|
-
* Stable private
|
|
166
|
-
*
|
|
165
|
+
* Stable private contact identifier: `urn:multibase:<hash(normalized email or phone)>`.
|
|
166
|
+
* The canonical ISCO-08/FHIR-v3 role is stored separately in `issuedToRole`.
|
|
167
167
|
* Portal DIDs, IdP subjects, wallets and DCR clients bind to this value but do not define it.
|
|
168
168
|
*/
|
|
169
169
|
activatedBy?: string;
|
package/dist/models/did.d.ts
CHANGED
|
@@ -45,6 +45,8 @@ export interface DidDocument {
|
|
|
45
45
|
'@context': string | string[];
|
|
46
46
|
/** The DID URI itself. */
|
|
47
47
|
id: string;
|
|
48
|
+
/** Independent DID subjects authorized to control this DID. */
|
|
49
|
+
controller?: string | string[];
|
|
48
50
|
/** Public keys used for verifying digital signatures */
|
|
49
51
|
verificationMethod?: VerificationMethod[];
|
|
50
52
|
/**
|
|
@@ -88,11 +88,8 @@ export declare function extractDidWebFromCredential(credential: unknown): string
|
|
|
88
88
|
* Checks whether the representative role expresses the activation-controller
|
|
89
89
|
* semantics accepted by GW.
|
|
90
90
|
*
|
|
91
|
-
*
|
|
92
|
-
*
|
|
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`)
|
|
91
|
+
* The controller/legal-representative authorization is the bare HL7 v3 code
|
|
92
|
+
* `RESPRSN`. ISCO occupation `1120` is not a controller authorization role.
|
|
96
93
|
*
|
|
97
94
|
* @param roleCode Candidate role token extracted from the credential.
|
|
98
95
|
* @param requiredCode Required GW compatibility code, defaults to `RESPRSN`.
|
|
@@ -187,22 +187,14 @@ export function extractDidWebFromCredential(credential) {
|
|
|
187
187
|
* Checks whether the representative role expresses the activation-controller
|
|
188
188
|
* semantics accepted by GW.
|
|
189
189
|
*
|
|
190
|
-
*
|
|
191
|
-
*
|
|
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`)
|
|
190
|
+
* The controller/legal-representative authorization is the bare HL7 v3 code
|
|
191
|
+
* `RESPRSN`. ISCO occupation `1120` is not a controller authorization role.
|
|
195
192
|
*
|
|
196
193
|
* @param roleCode Candidate role token extracted from the credential.
|
|
197
194
|
* @param requiredCode Required GW compatibility code, defaults to `RESPRSN`.
|
|
198
195
|
*/
|
|
199
196
|
export function hasActivationRepresentativeRole(roleCode, requiredCode = 'RESPRSN') {
|
|
200
|
-
|
|
201
|
-
return true;
|
|
202
|
-
const normalized = String(roleCode || '').trim().toUpperCase();
|
|
203
|
-
if (!normalized)
|
|
204
|
-
return false;
|
|
205
|
-
return /(?:^|[|:])1120$/.test(normalized);
|
|
197
|
+
return hasRoleCode(roleCode, requiredCode);
|
|
206
198
|
}
|
|
207
199
|
/**
|
|
208
200
|
* Extracts the categories authorized by an ICA-issued organization credential.
|
|
@@ -354,7 +346,7 @@ export function validateActivationRepresentativePolicy(input) {
|
|
|
354
346
|
if (!hasActivationRepresentativeRole(roleCode, input.requiredRoleCode || 'RESPRSN')) {
|
|
355
347
|
errors.push({
|
|
356
348
|
code: 'MISSING_REPRESENTATIVE_ROLE_RESPRSN',
|
|
357
|
-
message: 'ICA-issued representative credential must include
|
|
349
|
+
message: 'ICA-issued representative credential must include controller role RESPRSN in credentialSubject.hasOccupation.',
|
|
358
350
|
});
|
|
359
351
|
}
|
|
360
352
|
const binding = extractRepresentativeCredentialBinding(input.representativeCredential);
|
|
@@ -1,17 +1,11 @@
|
|
|
1
|
-
/** Cross-portal actor classes. These are intentionally broader than job roles. */
|
|
2
|
-
export declare const StableActorRoles: Readonly<{
|
|
3
|
-
readonly Professional: "professional";
|
|
4
|
-
readonly Personal: "personal";
|
|
5
|
-
}>;
|
|
6
|
-
export type StableActorRole = typeof StableActorRoles[keyof typeof StableActorRoles];
|
|
7
1
|
export type StableActorContactKind = 'email' | 'phone';
|
|
8
2
|
/**
|
|
9
3
|
* Builds the private, stable actor identifier shared by independent portals.
|
|
10
4
|
*
|
|
11
|
-
* Wire format: `urn:multibase:<multibase(multihash(SHA3-256, normalized-contact))
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
5
|
+
* Wire format: `urn:multibase:<multibase(multihash(SHA3-256, normalized-contact))>`.
|
|
6
|
+
* The clear email/phone and the actor role are never embedded. ISCO-08 or
|
|
7
|
+
* FHIR v3 roles are persisted separately in `Person.hasOccupation` and may be
|
|
8
|
+
* represented separately in an employee/member DID.
|
|
15
9
|
*
|
|
16
10
|
* Email is trimmed, stripped of `mailto:` and lower-cased. Phone is stripped
|
|
17
11
|
* of `tel:` and formatting while preserving an E.164 leading `+`.
|
|
@@ -19,15 +13,17 @@ export type StableActorContactKind = 'email' | 'phone';
|
|
|
19
13
|
export declare function buildStableActorIdentifier(input: {
|
|
20
14
|
contactKind: StableActorContactKind;
|
|
21
15
|
contact: string;
|
|
22
|
-
role: StableActorRole;
|
|
23
16
|
}): string;
|
|
24
17
|
/**
|
|
25
|
-
* Builds a portal-specific DID binding
|
|
26
|
-
*
|
|
18
|
+
* Builds a portal-specific employee DID binding. The stable actor payload and
|
|
19
|
+
* the canonical ISCO-08/FHIR-v3 role remain distinct path components.
|
|
20
|
+
*
|
|
21
|
+
* @deprecated Use `buildProfessionalDidWeb` for organization employees.
|
|
27
22
|
*/
|
|
28
23
|
export declare function buildPortalActorDidWeb(input: {
|
|
29
24
|
portalDidWeb: string;
|
|
30
25
|
actorIdentifier: string;
|
|
26
|
+
role: string;
|
|
31
27
|
}): string;
|
|
32
28
|
/**
|
|
33
29
|
* Extracts the stable actor URN from a canonical GDC portal actor DID.
|
|
@@ -1,26 +1,17 @@
|
|
|
1
1
|
import { normalizePhone } from './consent.js';
|
|
2
|
-
import {
|
|
3
|
-
/** Cross-portal actor classes. These are intentionally broader than job roles. */
|
|
4
|
-
export const StableActorRoles = Object.freeze({
|
|
5
|
-
Professional: 'professional',
|
|
6
|
-
Personal: 'personal',
|
|
7
|
-
});
|
|
2
|
+
import { normalizeSameAsHash, normalizeTelephoneHash } from './same-as.js';
|
|
8
3
|
/**
|
|
9
4
|
* Builds the private, stable actor identifier shared by independent portals.
|
|
10
5
|
*
|
|
11
|
-
* Wire format: `urn:multibase:<multibase(multihash(SHA3-256, normalized-contact))
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
6
|
+
* Wire format: `urn:multibase:<multibase(multihash(SHA3-256, normalized-contact))>`.
|
|
7
|
+
* The clear email/phone and the actor role are never embedded. ISCO-08 or
|
|
8
|
+
* FHIR v3 roles are persisted separately in `Person.hasOccupation` and may be
|
|
9
|
+
* represented separately in an employee/member DID.
|
|
15
10
|
*
|
|
16
11
|
* Email is trimmed, stripped of `mailto:` and lower-cased. Phone is stripped
|
|
17
12
|
* of `tel:` and formatting while preserving an E.164 leading `+`.
|
|
18
13
|
*/
|
|
19
14
|
export function buildStableActorIdentifier(input) {
|
|
20
|
-
const role = String(input.role || '').trim();
|
|
21
|
-
if (!Object.values(StableActorRoles).includes(role)) {
|
|
22
|
-
throw new Error('Stable actor role must be professional or personal.');
|
|
23
|
-
}
|
|
24
15
|
const rawContact = String(input.contact || '').trim();
|
|
25
16
|
const normalizedContact = input.contactKind === 'email'
|
|
26
17
|
? rawContact.replace(/^mailto:/i, '').replace(/\s+/g, '').toLowerCase()
|
|
@@ -28,31 +19,39 @@ export function buildStableActorIdentifier(input) {
|
|
|
28
19
|
if (!normalizedContact) {
|
|
29
20
|
throw new Error(`Stable actor ${input.contactKind} is required.`);
|
|
30
21
|
}
|
|
31
|
-
return
|
|
22
|
+
return input.contactKind === 'email'
|
|
23
|
+
? normalizeSameAsHash(normalizedContact)
|
|
24
|
+
: normalizeTelephoneHash(normalizedContact);
|
|
32
25
|
}
|
|
33
26
|
/**
|
|
34
|
-
* Builds a portal-specific DID binding
|
|
35
|
-
*
|
|
27
|
+
* Builds a portal-specific employee DID binding. The stable actor payload and
|
|
28
|
+
* the canonical ISCO-08/FHIR-v3 role remain distinct path components.
|
|
29
|
+
*
|
|
30
|
+
* @deprecated Use `buildProfessionalDidWeb` for organization employees.
|
|
36
31
|
*/
|
|
37
32
|
export function buildPortalActorDidWeb(input) {
|
|
38
33
|
const portalDidWeb = String(input.portalDidWeb || '').trim();
|
|
39
|
-
const match = /^urn:multibase:(z[^:]+)
|
|
34
|
+
const match = /^urn:multibase:(z[^:]+)$/.exec(String(input.actorIdentifier || '').trim());
|
|
35
|
+
const role = String(input.role || '').trim();
|
|
40
36
|
if (!portalDidWeb.startsWith('did:web:')) {
|
|
41
37
|
throw new Error('Portal actor binding requires a did:web root.');
|
|
42
38
|
}
|
|
43
39
|
if (!match) {
|
|
44
40
|
throw new Error('Portal actor binding requires a stable actor URN.');
|
|
45
41
|
}
|
|
46
|
-
|
|
42
|
+
if (!role) {
|
|
43
|
+
throw new Error('Portal actor binding requires a canonical role.');
|
|
44
|
+
}
|
|
45
|
+
return `${portalDidWeb}:employee:${match[1]}:${role}`;
|
|
47
46
|
}
|
|
48
47
|
/**
|
|
49
48
|
* Extracts the stable actor URN from a canonical GDC portal actor DID.
|
|
50
49
|
* This is extraction, not reversal of the contact hash.
|
|
51
50
|
*/
|
|
52
51
|
export function stableActorIdentifierFromDidWeb(didWeb) {
|
|
53
|
-
const match = /:
|
|
52
|
+
const match = /:employee:(z[^:]+):[^:]+(?:[:]|$)/.exec(String(didWeb || '').trim());
|
|
54
53
|
if (!match) {
|
|
55
54
|
throw new Error('DID does not contain a canonical GDC actor binding.');
|
|
56
55
|
}
|
|
57
|
-
return `urn:multibase:${match[1]}
|
|
56
|
+
return `urn:multibase:${match[1]}`;
|
|
58
57
|
}
|
package/dist/utils/index.d.ts
CHANGED
|
@@ -83,6 +83,7 @@ export * from './jwt-signer';
|
|
|
83
83
|
export * from './jwk-thumbprint';
|
|
84
84
|
export * from './legal-organization-onboarding';
|
|
85
85
|
export * from './legal-organization-verification-transaction';
|
|
86
|
+
export * from './organization-registration-authorization';
|
|
86
87
|
export * from './local-terminology-provider';
|
|
87
88
|
export * from './license';
|
|
88
89
|
export * from './license-commercial-search';
|
package/dist/utils/index.js
CHANGED
|
@@ -83,6 +83,7 @@ export * from './jwt-signer.js';
|
|
|
83
83
|
export * from './jwk-thumbprint.js';
|
|
84
84
|
export * from './legal-organization-onboarding.js';
|
|
85
85
|
export * from './legal-organization-verification-transaction.js';
|
|
86
|
+
export * from './organization-registration-authorization.js';
|
|
86
87
|
export * from './local-terminology-provider.js';
|
|
87
88
|
export * from './license.js';
|
|
88
89
|
export * from './license-commercial-search.js';
|
|
@@ -38,3 +38,11 @@ export declare function computeRfc7638JwkThumbprint(jwk: ThumbprintableJwk): str
|
|
|
38
38
|
* `urn:ietf:params:oauth:jwk-thumbprint:sha-256:<base64url>`
|
|
39
39
|
*/
|
|
40
40
|
export declare function toJwkThumbprintSha256Urn(jwk: ThumbprintableJwk): string;
|
|
41
|
+
/**
|
|
42
|
+
* Returns a public JWK whose `kid` is derived exclusively from its public key
|
|
43
|
+
* material. Caller-provided aliases are deliberately replaced so DID methods,
|
|
44
|
+
* credentials and confidential-storage indexes share one RFC 9278 identifier.
|
|
45
|
+
*/
|
|
46
|
+
export declare function withJwkThumbprintSha256Kid<T extends ThumbprintableJwk>(jwk: T): T & {
|
|
47
|
+
kid: string;
|
|
48
|
+
};
|
|
@@ -55,3 +55,14 @@ export function computeRfc7638JwkThumbprint(jwk) {
|
|
|
55
55
|
export function toJwkThumbprintSha256Urn(jwk) {
|
|
56
56
|
return `${UrnPrefixes.JwkThumbprintSha256KeyId}${computeRfc7638JwkThumbprint(jwk)}`;
|
|
57
57
|
}
|
|
58
|
+
/**
|
|
59
|
+
* Returns a public JWK whose `kid` is derived exclusively from its public key
|
|
60
|
+
* material. Caller-provided aliases are deliberately replaced so DID methods,
|
|
61
|
+
* credentials and confidential-storage indexes share one RFC 9278 identifier.
|
|
62
|
+
*/
|
|
63
|
+
export function withJwkThumbprintSha256Kid(jwk) {
|
|
64
|
+
return {
|
|
65
|
+
...jwk,
|
|
66
|
+
kid: toJwkThumbprintSha256Urn(jwk),
|
|
67
|
+
};
|
|
68
|
+
}
|
|
@@ -106,6 +106,7 @@ export interface LegalOrganizationOnboardingFacade {
|
|
|
106
106
|
buildVerificationTransactionInput(fields: LegalOrganizationFormTemplateFields, input: Readonly<{
|
|
107
107
|
controller: LegalOrganizationVerificationTransactionController;
|
|
108
108
|
organization?: LegalOrganizationVerificationTransactionOrganization;
|
|
109
|
+
/** @deprecated Legacy demo/OTP compatibility input. */
|
|
109
110
|
legalRepresentativePayload?: LegalOrganizationVerificationRepresentativePayload;
|
|
110
111
|
verification?: LegalOrganizationVerificationRouting;
|
|
111
112
|
attachments?: unknown[];
|
|
@@ -146,6 +147,7 @@ export interface LegalOrganizationOnboardingEditor {
|
|
|
146
147
|
buildVerificationTransactionInput(input: Readonly<{
|
|
147
148
|
controller: LegalOrganizationVerificationTransactionController;
|
|
148
149
|
organization?: LegalOrganizationVerificationTransactionOrganization;
|
|
150
|
+
/** @deprecated Legacy demo/OTP compatibility input. */
|
|
149
151
|
legalRepresentativePayload?: LegalOrganizationVerificationRepresentativePayload;
|
|
150
152
|
verification?: LegalOrganizationVerificationRouting;
|
|
151
153
|
attachments?: unknown[];
|
|
@@ -304,9 +304,7 @@ export function createLegalOrganizationOnboardingFacade() {
|
|
|
304
304
|
...(controllerEmail ? { email: controllerEmail } : {}),
|
|
305
305
|
...(representativeSameAs ? { sameAs: representativeSameAs } : {}),
|
|
306
306
|
}
|
|
307
|
-
:
|
|
308
|
-
? { email: controllerEmail }
|
|
309
|
-
: undefined,
|
|
307
|
+
: undefined,
|
|
310
308
|
verification: {
|
|
311
309
|
resourceType: normalizeOptionalText(input.verificationResourceType) || 'contract',
|
|
312
310
|
},
|
|
@@ -4,6 +4,27 @@ export type LegalOrganizationVerificationCredentialPair = Readonly<{
|
|
|
4
4
|
organizationCredential: LegalOrganizationVerificationCredential;
|
|
5
5
|
legalRepresentativeCredential: LegalOrganizationVerificationCredential;
|
|
6
6
|
}>;
|
|
7
|
+
/**
|
|
8
|
+
* Extracts the controller actor stored at
|
|
9
|
+
* `credentialSubject.owner` in an organization-controller service VC.
|
|
10
|
+
*
|
|
11
|
+
* @param credential Candidate organization-controller credential.
|
|
12
|
+
*/
|
|
13
|
+
export declare function extractOrganizationControllerOwner(credential: unknown): Record<string, unknown> | undefined;
|
|
14
|
+
/**
|
|
15
|
+
* Extracts the stable public actor identifier from an
|
|
16
|
+
* organization-controller service VC.
|
|
17
|
+
*
|
|
18
|
+
* @param credential Candidate organization-controller credential.
|
|
19
|
+
*/
|
|
20
|
+
export declare function extractOrganizationControllerSameAs(credential: unknown): string | undefined;
|
|
21
|
+
/**
|
|
22
|
+
* Extracts the RFC 9278 JWK-thumbprint binding from an
|
|
23
|
+
* organization-controller service VC.
|
|
24
|
+
*
|
|
25
|
+
* @param credential Candidate organization-controller credential.
|
|
26
|
+
*/
|
|
27
|
+
export declare function extractOrganizationControllerBinding(credential: unknown): string | undefined;
|
|
7
28
|
/**
|
|
8
29
|
* Returns the ICA verification entries currently projected by GW host
|
|
9
30
|
* legal-organization `_transaction`.
|
|
@@ -35,3 +56,27 @@ export declare function readLegalRepresentativeSameAsFromResponseBody(responseBo
|
|
|
35
56
|
* legal-representative credential when present.
|
|
36
57
|
*/
|
|
37
58
|
export declare function readLegalRepresentativeBindingFromResponseBody(responseBody: unknown): string | undefined;
|
|
59
|
+
/**
|
|
60
|
+
* Returns all independently issued organization-controller service
|
|
61
|
+
* credentials in an ICA or projected GW verification response.
|
|
62
|
+
*
|
|
63
|
+
* The result is empty when the response contains only the legacy organization
|
|
64
|
+
* and legal-representative credential pair.
|
|
65
|
+
*/
|
|
66
|
+
export declare function readOrganizationControllerCredentialsFromResponseBody(responseBody: unknown): LegalOrganizationVerificationCredential[];
|
|
67
|
+
/**
|
|
68
|
+
* Returns one organization-controller service credential in an ICA or
|
|
69
|
+
* projected GW verification response. Pass a stable actor `sameAs` to select
|
|
70
|
+
* one controller independently; otherwise the first controller is returned.
|
|
71
|
+
*/
|
|
72
|
+
export declare function readOrganizationControllerCredentialFromResponseBody(responseBody: unknown, controllerSameAs?: string): LegalOrganizationVerificationCredential | undefined;
|
|
73
|
+
/**
|
|
74
|
+
* Reads `credentialSubject.owner.sameAs` from the first
|
|
75
|
+
* organization-controller service credential when present.
|
|
76
|
+
*/
|
|
77
|
+
export declare function readOrganizationControllerSameAsFromResponseBody(responseBody: unknown): string | undefined;
|
|
78
|
+
/**
|
|
79
|
+
* Reads `credentialSubject.owner.hasCredential.material` from the first
|
|
80
|
+
* organization-controller service credential when present.
|
|
81
|
+
*/
|
|
82
|
+
export declare function readOrganizationControllerBindingFromResponseBody(responseBody: unknown): string | undefined;
|
|
@@ -23,6 +23,45 @@ function findCredentialResource(entries, expectedTypeFragment, fallbackIndex) {
|
|
|
23
23
|
}
|
|
24
24
|
return resource;
|
|
25
25
|
}
|
|
26
|
+
function hasCredentialType(value, expectedType) {
|
|
27
|
+
const candidate = asObject(value);
|
|
28
|
+
const resource = asObject(candidate?.resource);
|
|
29
|
+
const typeValues = [candidate?.type, resource?.type];
|
|
30
|
+
return typeValues.some((typeValue) => {
|
|
31
|
+
const tokens = Array.isArray(typeValue)
|
|
32
|
+
? typeValue.map((token) => String(token || ''))
|
|
33
|
+
: [String(typeValue || '')];
|
|
34
|
+
return tokens.some((token) => token.includes(expectedType));
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Extracts the controller actor stored at
|
|
39
|
+
* `credentialSubject.owner` in an organization-controller service VC.
|
|
40
|
+
*
|
|
41
|
+
* @param credential Candidate organization-controller credential.
|
|
42
|
+
*/
|
|
43
|
+
export function extractOrganizationControllerOwner(credential) {
|
|
44
|
+
return asObject(extractCredentialSubject(credential)?.owner);
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Extracts the stable public actor identifier from an
|
|
48
|
+
* organization-controller service VC.
|
|
49
|
+
*
|
|
50
|
+
* @param credential Candidate organization-controller credential.
|
|
51
|
+
*/
|
|
52
|
+
export function extractOrganizationControllerSameAs(credential) {
|
|
53
|
+
return String(extractOrganizationControllerOwner(credential)?.sameAs || '').trim() || undefined;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Extracts the RFC 9278 JWK-thumbprint binding from an
|
|
57
|
+
* organization-controller service VC.
|
|
58
|
+
*
|
|
59
|
+
* @param credential Candidate organization-controller credential.
|
|
60
|
+
*/
|
|
61
|
+
export function extractOrganizationControllerBinding(credential) {
|
|
62
|
+
const owner = extractOrganizationControllerOwner(credential);
|
|
63
|
+
return owner ? extractRepresentativeCredentialBinding({ credentialSubject: owner }) : undefined;
|
|
64
|
+
}
|
|
26
65
|
/**
|
|
27
66
|
* Returns the ICA verification entries currently projected by GW host
|
|
28
67
|
* legal-organization `_transaction`.
|
|
@@ -104,3 +143,42 @@ export function readLegalRepresentativeBindingFromResponseBody(responseBody) {
|
|
|
104
143
|
const pair = readLegalOrganizationVerificationCredentialPairFromResponseBody(responseBody);
|
|
105
144
|
return extractRepresentativeCredentialBinding(pair.legalRepresentativeCredential);
|
|
106
145
|
}
|
|
146
|
+
/**
|
|
147
|
+
* Returns all independently issued organization-controller service
|
|
148
|
+
* credentials in an ICA or projected GW verification response.
|
|
149
|
+
*
|
|
150
|
+
* The result is empty when the response contains only the legacy organization
|
|
151
|
+
* and legal-representative credential pair.
|
|
152
|
+
*/
|
|
153
|
+
export function readOrganizationControllerCredentialsFromResponseBody(responseBody) {
|
|
154
|
+
return getLegalOrganizationVerificationEntriesFromResponseBody(responseBody)
|
|
155
|
+
.filter((entry) => hasCredentialType(entry, 'OrganizationControllerCredential'))
|
|
156
|
+
.map((entry) => asObject(asObject(entry)?.resource) || asObject(entry))
|
|
157
|
+
.filter((entry) => Boolean(entry));
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Returns one organization-controller service credential in an ICA or
|
|
161
|
+
* projected GW verification response. Pass a stable actor `sameAs` to select
|
|
162
|
+
* one controller independently; otherwise the first controller is returned.
|
|
163
|
+
*/
|
|
164
|
+
export function readOrganizationControllerCredentialFromResponseBody(responseBody, controllerSameAs) {
|
|
165
|
+
const credentials = readOrganizationControllerCredentialsFromResponseBody(responseBody);
|
|
166
|
+
const expectedSameAs = String(controllerSameAs || '').trim();
|
|
167
|
+
return expectedSameAs
|
|
168
|
+
? credentials.find((credential) => extractOrganizationControllerSameAs(credential) === expectedSameAs)
|
|
169
|
+
: credentials[0];
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Reads `credentialSubject.owner.sameAs` from the first
|
|
173
|
+
* organization-controller service credential when present.
|
|
174
|
+
*/
|
|
175
|
+
export function readOrganizationControllerSameAsFromResponseBody(responseBody) {
|
|
176
|
+
return extractOrganizationControllerSameAs(readOrganizationControllerCredentialFromResponseBody(responseBody));
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Reads `credentialSubject.owner.hasCredential.material` from the first
|
|
180
|
+
* organization-controller service credential when present.
|
|
181
|
+
*/
|
|
182
|
+
export function readOrganizationControllerBindingFromResponseBody(responseBody) {
|
|
183
|
+
return extractOrganizationControllerBinding(readOrganizationControllerCredentialFromResponseBody(responseBody));
|
|
184
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { BundleJsonApi } from '../models/bundle';
|
|
2
2
|
import type { ClaimsRecord } from '../models/resource-document';
|
|
3
|
+
import type { VerifiableCredentialV2 } from '../models/verifiable-credential';
|
|
3
4
|
/**
|
|
4
5
|
* Canonical business entry type for the first host-side onboarding step that
|
|
5
6
|
* asks GW CORE to forward a legal-organization verification request to ICA.
|
|
@@ -71,8 +72,14 @@ export type LegalOrganizationVerificationTransactionInput = Readonly<{
|
|
|
71
72
|
claims: ClaimsRecord;
|
|
72
73
|
controller: LegalOrganizationVerificationTransactionController;
|
|
73
74
|
organization?: LegalOrganizationVerificationTransactionOrganization;
|
|
75
|
+
/**
|
|
76
|
+
* @deprecated Legacy demo/OTP compatibility only. Canonical signed-PDF and
|
|
77
|
+
* strict flows derive the representative from verified evidence.
|
|
78
|
+
*/
|
|
74
79
|
legalRepresentativePayload?: LegalOrganizationVerificationRepresentativePayload;
|
|
75
80
|
verification?: LegalOrganizationVerificationRouting;
|
|
81
|
+
/** Out-of-band host authorization used only by the Test Network path. */
|
|
82
|
+
authorizationCredential?: VerifiableCredentialV2;
|
|
76
83
|
attachments?: unknown[];
|
|
77
84
|
}>;
|
|
78
85
|
export type LegalOrganizationVerificationTransactionEntry = Readonly<{
|
|
@@ -84,9 +91,12 @@ export type LegalOrganizationVerificationTransactionEntry = Readonly<{
|
|
|
84
91
|
resource?: {
|
|
85
92
|
controller?: LegalOrganizationVerificationTransactionController;
|
|
86
93
|
organization?: LegalOrganizationVerificationTransactionOrganization;
|
|
94
|
+
/** @deprecated Legacy demo/OTP compatibility input. */
|
|
87
95
|
legalRepresentativePayload?: LegalOrganizationVerificationRepresentativePayload;
|
|
96
|
+
/** @deprecated Legacy ICA wire alias accepted only while migrating old callers. */
|
|
88
97
|
legalRepresentative?: LegalOrganizationVerificationRepresentativePayload;
|
|
89
98
|
verification?: LegalOrganizationVerificationRouting;
|
|
99
|
+
authorizationCredential?: VerifiableCredentialV2;
|
|
90
100
|
[key: string]: unknown;
|
|
91
101
|
};
|
|
92
102
|
[key: string]: unknown;
|
|
@@ -122,6 +132,9 @@ export declare function getLegalOrganizationVerificationController(value: unknow
|
|
|
122
132
|
* Returns the normalized legal representative contact payload from the first
|
|
123
133
|
* legal-organization verification transaction entry when present.
|
|
124
134
|
*
|
|
135
|
+
* @deprecated Read-only support for legacy demo/OTP payloads. Canonical
|
|
136
|
+
* signed-PDF and strict flows derive the representative from verified evidence.
|
|
137
|
+
*
|
|
125
138
|
* Compatibility note:
|
|
126
139
|
* - GW/SDK request builders use `resource.legalRepresentativePayload`
|
|
127
140
|
* - the ICA forwarding payload currently uses `resource.legalRepresentative`
|
|
@@ -61,6 +61,9 @@ export function buildLegalOrganizationVerificationTransactionBundle(input) {
|
|
|
61
61
|
verification: {
|
|
62
62
|
resourceType: normalizeText(input.verification?.resourceType) || 'contract',
|
|
63
63
|
},
|
|
64
|
+
...(input.authorizationCredential
|
|
65
|
+
? { authorizationCredential: input.authorizationCredential }
|
|
66
|
+
: {}),
|
|
64
67
|
},
|
|
65
68
|
}],
|
|
66
69
|
...(Array.isArray(input.attachments) && input.attachments.length > 0
|
|
@@ -98,6 +101,9 @@ export function getLegalOrganizationVerificationController(value) {
|
|
|
98
101
|
* Returns the normalized legal representative contact payload from the first
|
|
99
102
|
* legal-organization verification transaction entry when present.
|
|
100
103
|
*
|
|
104
|
+
* @deprecated Read-only support for legacy demo/OTP payloads. Canonical
|
|
105
|
+
* signed-PDF and strict flows derive the representative from verified evidence.
|
|
106
|
+
*
|
|
101
107
|
* Compatibility note:
|
|
102
108
|
* - GW/SDK request builders use `resource.legalRepresentativePayload`
|
|
103
109
|
* - the ICA forwarding payload currently uses `resource.legalRepresentative`
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import type { VerifiableCredentialV2 } from '../models/verifiable-credential';
|
|
2
|
+
/** Lifecycle of the one GW activation licence delivered to the legal postal address. */
|
|
3
|
+
export declare const PostalActivationLicenseStatuses: Readonly<{
|
|
4
|
+
readonly Issued: "issued";
|
|
5
|
+
readonly Delivered: "delivered";
|
|
6
|
+
readonly Redeemed: "redeemed";
|
|
7
|
+
readonly Revoked: "revoked";
|
|
8
|
+
readonly Expired: "expired";
|
|
9
|
+
}>;
|
|
10
|
+
export type PostalActivationLicenseStatus = typeof PostalActivationLicenseStatuses[keyof typeof PostalActivationLicenseStatuses];
|
|
11
|
+
/**
|
|
12
|
+
* Public binding recorded for the activation licence. The activation code is
|
|
13
|
+
* deliberately absent: storage implementations retain only its protected
|
|
14
|
+
* value/index and never place the secret inside a VC.
|
|
15
|
+
*/
|
|
16
|
+
export type PostalActivationLicenseBinding = Readonly<{
|
|
17
|
+
licenseId: string;
|
|
18
|
+
applicationId: string;
|
|
19
|
+
organizationIdentifier: string;
|
|
20
|
+
controllerEmail: string;
|
|
21
|
+
controllerKeyMaterial: string;
|
|
22
|
+
postalAddressHash: string;
|
|
23
|
+
hostDid: string;
|
|
24
|
+
network: 'test-network' | 'network';
|
|
25
|
+
status: PostalActivationLicenseStatus;
|
|
26
|
+
issuedAt: string;
|
|
27
|
+
expiresAt: string;
|
|
28
|
+
deliveredAt?: string;
|
|
29
|
+
redeemedAt?: string;
|
|
30
|
+
}>;
|
|
31
|
+
/** Input for the credential returned out-of-band to the applicant controller. */
|
|
32
|
+
export type OrganizationRegistrationAuthorizationCredentialInput = Readonly<{
|
|
33
|
+
issuerDid: string;
|
|
34
|
+
subjectDid: string;
|
|
35
|
+
credentialId: string;
|
|
36
|
+
validFrom: string;
|
|
37
|
+
validUntil: string;
|
|
38
|
+
legalName: string;
|
|
39
|
+
organizationIdentifier: string;
|
|
40
|
+
controllerEmail: string;
|
|
41
|
+
controllerKeyMaterial: string;
|
|
42
|
+
applicationId: string;
|
|
43
|
+
accessPath: 'partner' | 'test-network';
|
|
44
|
+
targetNetwork: 'test-network' | 'network';
|
|
45
|
+
postalLicense: PostalActivationLicenseBinding;
|
|
46
|
+
proof?: VerifiableCredentialV2['proof'];
|
|
47
|
+
}>;
|
|
48
|
+
/**
|
|
49
|
+
* Builds the immutable VC that a controller receives out-of-band and attaches
|
|
50
|
+
* to `Organization/_transaction`. The postal code itself never appears in the
|
|
51
|
+
* credential; its confirmed, purpose-bound licence record is referenced.
|
|
52
|
+
*/
|
|
53
|
+
export declare function buildOrganizationRegistrationAuthorizationCredential(input: OrganizationRegistrationAuthorizationCredentialInput): VerifiableCredentialV2;
|
|
54
|
+
/**
|
|
55
|
+
* Applies the only legal state transitions for the purpose-bound postal code.
|
|
56
|
+
* Confirmation proves delivery but deliberately does not consume the code;
|
|
57
|
+
* redemption occurs later during `_exchange`.
|
|
58
|
+
*/
|
|
59
|
+
export declare function transitionPostalActivationLicense(current: PostalActivationLicenseStatus, action: 'mark_delivered' | 'redeem' | 'revoke' | 'expire'): PostalActivationLicenseStatus;
|
|
60
|
+
/**
|
|
61
|
+
* Produces deterministic UTF-8 JSON for detached proofs. Every proof signs the
|
|
62
|
+
* same credential payload with the complete `proof` property removed, so a
|
|
63
|
+
* later counter-proof cannot invalidate an earlier one.
|
|
64
|
+
*/
|
|
65
|
+
export declare function canonicalizeOrganizationRegistrationAuthorizationCredential(credential: VerifiableCredentialV2): string;
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { ContractCredentialTypes, W3cCredentialContexts, W3cCredentialTypes, } from '../constants/verifiable-credentials.js';
|
|
2
|
+
/** Lifecycle of the one GW activation licence delivered to the legal postal address. */
|
|
3
|
+
export const PostalActivationLicenseStatuses = Object.freeze({
|
|
4
|
+
Issued: 'issued',
|
|
5
|
+
Delivered: 'delivered',
|
|
6
|
+
Redeemed: 'redeemed',
|
|
7
|
+
Revoked: 'revoked',
|
|
8
|
+
Expired: 'expired',
|
|
9
|
+
});
|
|
10
|
+
function required(value, name) {
|
|
11
|
+
const normalized = String(value || '').trim();
|
|
12
|
+
if (!normalized)
|
|
13
|
+
throw new Error(`Organization registration authorization requires ${name}.`);
|
|
14
|
+
return normalized;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Builds the immutable VC that a controller receives out-of-band and attaches
|
|
18
|
+
* to `Organization/_transaction`. The postal code itself never appears in the
|
|
19
|
+
* credential; its confirmed, purpose-bound licence record is referenced.
|
|
20
|
+
*/
|
|
21
|
+
export function buildOrganizationRegistrationAuthorizationCredential(input) {
|
|
22
|
+
const applicationId = required(input.applicationId, 'applicationId');
|
|
23
|
+
const organizationIdentifier = required(input.organizationIdentifier, 'organizationIdentifier');
|
|
24
|
+
const controllerEmail = required(input.controllerEmail, 'controllerEmail').toLowerCase();
|
|
25
|
+
if (input.postalLicense.status !== PostalActivationLicenseStatuses.Delivered) {
|
|
26
|
+
throw new Error('Organization registration authorization requires a delivered postal activation licence.');
|
|
27
|
+
}
|
|
28
|
+
if (input.postalLicense.applicationId !== applicationId
|
|
29
|
+
|| input.postalLicense.organizationIdentifier !== organizationIdentifier
|
|
30
|
+
|| input.postalLicense.controllerEmail.trim().toLowerCase() !== controllerEmail
|
|
31
|
+
|| input.postalLicense.controllerKeyMaterial !== input.controllerKeyMaterial
|
|
32
|
+
|| input.postalLicense.network !== input.targetNetwork) {
|
|
33
|
+
throw new Error('Postal activation licence does not match the organization registration application.');
|
|
34
|
+
}
|
|
35
|
+
return {
|
|
36
|
+
'@context': [W3cCredentialContexts.V2, 'https://schema.org'],
|
|
37
|
+
id: required(input.credentialId, 'credentialId'),
|
|
38
|
+
type: [
|
|
39
|
+
W3cCredentialTypes.VerifiableCredential,
|
|
40
|
+
ContractCredentialTypes.OrganizationRegistrationAuthorizationCredential,
|
|
41
|
+
],
|
|
42
|
+
issuer: required(input.issuerDid, 'issuerDid'),
|
|
43
|
+
credentialSubject: {
|
|
44
|
+
id: required(input.subjectDid, 'subjectDid'),
|
|
45
|
+
applicationId,
|
|
46
|
+
accessPath: input.accessPath,
|
|
47
|
+
targetNetwork: input.targetNetwork,
|
|
48
|
+
organization: {
|
|
49
|
+
legalName: required(input.legalName, 'legalName'),
|
|
50
|
+
identifier: organizationIdentifier,
|
|
51
|
+
},
|
|
52
|
+
controller: {
|
|
53
|
+
email: controllerEmail,
|
|
54
|
+
hasCredential: { material: required(input.controllerKeyMaterial, 'controllerKeyMaterial') },
|
|
55
|
+
},
|
|
56
|
+
postalActivationLicense: {
|
|
57
|
+
id: required(input.postalLicense.licenseId, 'postalLicense.licenseId'),
|
|
58
|
+
status: input.postalLicense.status,
|
|
59
|
+
postalAddressHash: required(input.postalLicense.postalAddressHash, 'postalLicense.postalAddressHash'),
|
|
60
|
+
deliveredAt: required(input.postalLicense.deliveredAt, 'postalLicense.deliveredAt'),
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
validFrom: required(input.validFrom, 'validFrom'),
|
|
64
|
+
validUntil: required(input.validUntil, 'validUntil'),
|
|
65
|
+
...(input.proof ? { proof: input.proof } : {}),
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Applies the only legal state transitions for the purpose-bound postal code.
|
|
70
|
+
* Confirmation proves delivery but deliberately does not consume the code;
|
|
71
|
+
* redemption occurs later during `_exchange`.
|
|
72
|
+
*/
|
|
73
|
+
export function transitionPostalActivationLicense(current, action) {
|
|
74
|
+
if (action === 'mark_delivered' && current === PostalActivationLicenseStatuses.Issued) {
|
|
75
|
+
return PostalActivationLicenseStatuses.Delivered;
|
|
76
|
+
}
|
|
77
|
+
if (action === 'redeem' && current === PostalActivationLicenseStatuses.Delivered) {
|
|
78
|
+
return PostalActivationLicenseStatuses.Redeemed;
|
|
79
|
+
}
|
|
80
|
+
if (action === 'revoke'
|
|
81
|
+
&& (current === PostalActivationLicenseStatuses.Issued
|
|
82
|
+
|| current === PostalActivationLicenseStatuses.Delivered)) {
|
|
83
|
+
return PostalActivationLicenseStatuses.Revoked;
|
|
84
|
+
}
|
|
85
|
+
if (action === 'expire'
|
|
86
|
+
&& (current === PostalActivationLicenseStatuses.Issued
|
|
87
|
+
|| current === PostalActivationLicenseStatuses.Delivered)) {
|
|
88
|
+
return PostalActivationLicenseStatuses.Expired;
|
|
89
|
+
}
|
|
90
|
+
throw new Error(`Invalid postal activation licence transition: ${current} -> ${action}.`);
|
|
91
|
+
}
|
|
92
|
+
function canonicalizeValue(value) {
|
|
93
|
+
if (Array.isArray(value))
|
|
94
|
+
return value.map(canonicalizeValue);
|
|
95
|
+
if (!value || typeof value !== 'object')
|
|
96
|
+
return value;
|
|
97
|
+
return Object.fromEntries(Object.entries(value)
|
|
98
|
+
.filter(([key]) => key !== 'proof')
|
|
99
|
+
.sort(([left], [right]) => left.localeCompare(right))
|
|
100
|
+
.map(([key, nested]) => [key, canonicalizeValue(nested)]));
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Produces deterministic UTF-8 JSON for detached proofs. Every proof signs the
|
|
104
|
+
* same credential payload with the complete `proof` property removed, so a
|
|
105
|
+
* later counter-proof cannot invalidate an earlier one.
|
|
106
|
+
*/
|
|
107
|
+
export function canonicalizeOrganizationRegistrationAuthorizationCredential(credential) {
|
|
108
|
+
if (!credential.type.includes(ContractCredentialTypes.OrganizationRegistrationAuthorizationCredential)) {
|
|
109
|
+
throw new Error('Credential is not an organization registration authorization.');
|
|
110
|
+
}
|
|
111
|
+
return JSON.stringify(canonicalizeValue(credential));
|
|
112
|
+
}
|
package/dist/utils/vp-token.d.ts
CHANGED
|
@@ -102,6 +102,13 @@ export declare function getOrganizationCredentialFromVpToken(vpToken: string): V
|
|
|
102
102
|
* @param vpToken Compact VP token or raw JSON string.
|
|
103
103
|
*/
|
|
104
104
|
export declare function getLegalRepresentativeCredentialFromVpToken(vpToken: string): VpCredential | undefined;
|
|
105
|
+
/**
|
|
106
|
+
* Extracts the organization-controller service credential from a VP token
|
|
107
|
+
* when present. It never substitutes a legal-representative credential.
|
|
108
|
+
*
|
|
109
|
+
* @param vpToken Compact VP token or raw JSON string.
|
|
110
|
+
*/
|
|
111
|
+
export declare function getOrganizationControllerCredentialFromVpToken(vpToken: string): VpCredential | undefined;
|
|
105
112
|
/**
|
|
106
113
|
* Appends an organization activation credential after validating its VC type.
|
|
107
114
|
*
|
|
@@ -115,6 +122,13 @@ export declare function addOrganizationCredential(vpPayload: VpTokenPayload, vc:
|
|
|
115
122
|
* Accepts compact VC strings, raw JSON VC strings, or VC JSON objects.
|
|
116
123
|
*/
|
|
117
124
|
export declare function addLegalRepresentativeCredential(vpPayload: VpTokenPayload, vc: VpCredentialInput): VpTokenPayload;
|
|
125
|
+
/**
|
|
126
|
+
* Appends an organization-controller service credential after validating its
|
|
127
|
+
* VC type independently from the legal-representative credential type.
|
|
128
|
+
*
|
|
129
|
+
* Accepts compact VC strings, raw JSON VC strings, or VC JSON objects.
|
|
130
|
+
*/
|
|
131
|
+
export declare function addOrganizationControllerCredential(vpPayload: VpTokenPayload, vc: VpCredentialInput): VpTokenPayload;
|
|
118
132
|
export declare function prepareForSignature(header: VpTokenHeader, payload: VpTokenPayload): {
|
|
119
133
|
encodedHeader: string;
|
|
120
134
|
encodedPayload: string;
|
package/dist/utils/vp-token.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { buildJwtCompact, prepareJwtBytesForSignature, prepareJwtForSignature } from './jwt.js';
|
|
2
|
-
import { ORGANIZATION_ACTIVATION_VC_TYPES, REPRESENTATIVE_ACTIVATION_VC_TYPES, W3cCredentialContexts, W3cCredentialTypes, } from '../constants/verifiable-credentials.js';
|
|
2
|
+
import { ORGANIZATION_ACTIVATION_VC_TYPES, ORGANIZATION_CONTROLLER_ACTIVATION_VC_TYPES, REPRESENTATIVE_ACTIVATION_VC_TYPES, W3cCredentialContexts, W3cCredentialTypes, } from '../constants/verifiable-credentials.js';
|
|
3
3
|
function fallbackId() {
|
|
4
4
|
const rand = Math.random().toString(36).slice(2, 10);
|
|
5
5
|
return `id-${Date.now()}-${rand}`;
|
|
@@ -189,6 +189,15 @@ export function getOrganizationCredentialFromVpToken(vpToken) {
|
|
|
189
189
|
export function getLegalRepresentativeCredentialFromVpToken(vpToken) {
|
|
190
190
|
return getVpCredentialByAnyType(vpToken, [...REPRESENTATIVE_ACTIVATION_VC_TYPES]);
|
|
191
191
|
}
|
|
192
|
+
/**
|
|
193
|
+
* Extracts the organization-controller service credential from a VP token
|
|
194
|
+
* when present. It never substitutes a legal-representative credential.
|
|
195
|
+
*
|
|
196
|
+
* @param vpToken Compact VP token or raw JSON string.
|
|
197
|
+
*/
|
|
198
|
+
export function getOrganizationControllerCredentialFromVpToken(vpToken) {
|
|
199
|
+
return getVpCredentialByAnyType(vpToken, [...ORGANIZATION_CONTROLLER_ACTIVATION_VC_TYPES]);
|
|
200
|
+
}
|
|
192
201
|
function vcHasAnyType(vcPayload, acceptedTypes) {
|
|
193
202
|
if (!vcPayload)
|
|
194
203
|
return false;
|
|
@@ -222,6 +231,15 @@ export function addOrganizationCredential(vpPayload, vc) {
|
|
|
222
231
|
export function addLegalRepresentativeCredential(vpPayload, vc) {
|
|
223
232
|
return addTypedVC(vpPayload, vc, [...REPRESENTATIVE_ACTIVATION_VC_TYPES], 'LegalRepresentative');
|
|
224
233
|
}
|
|
234
|
+
/**
|
|
235
|
+
* Appends an organization-controller service credential after validating its
|
|
236
|
+
* VC type independently from the legal-representative credential type.
|
|
237
|
+
*
|
|
238
|
+
* Accepts compact VC strings, raw JSON VC strings, or VC JSON objects.
|
|
239
|
+
*/
|
|
240
|
+
export function addOrganizationControllerCredential(vpPayload, vc) {
|
|
241
|
+
return addTypedVC(vpPayload, vc, [...ORGANIZATION_CONTROLLER_ACTIVATION_VC_TYPES], 'OrganizationController');
|
|
242
|
+
}
|
|
225
243
|
export function prepareForSignature(header, payload) {
|
|
226
244
|
return prepareJwtForSignature(header, payload);
|
|
227
245
|
}
|