gdc-sdk-node-ts 2.4.2 → 2.4.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/device-activation.d.ts +15 -0
- package/dist/device-activation.js +23 -9
- package/dist/index.d.ts +2 -1
- package/dist/index.js +2 -1
- package/dist/node-runtime-client.d.ts +12 -2
- package/dist/node-runtime-client.js +39 -2
- package/dist/orchestration/client-port.d.ts +8 -2
- package/dist/orchestration/organization-controller-sdk.d.ts +12 -2
- package/dist/orchestration/organization-controller-sdk.js +17 -0
- package/dist/organization-employee-lifecycle.d.ts +64 -0
- package/dist/organization-employee-lifecycle.js +76 -0
- package/dist/{organization-registration-authorization.d.ts → organization-test-network-credential.d.ts} +7 -2
- package/dist/organization-test-network-credential.js +62 -0
- package/dist/resource-operations.d.ts +28 -1
- package/dist/resource-operations.js +32 -0
- package/dist/runtime-client-paths.d.ts +4 -0
- package/dist/runtime-client-paths.js +5 -1
- package/dist/runtime-paths.d.ts +6 -0
- package/dist/runtime-paths.js +22 -4
- package/dist/server-profile-session.d.ts +4 -0
- package/dist/server-profile-session.js +10 -0
- package/package.json +2 -2
- package/dist/organization-registration-authorization.js +0 -34
|
@@ -21,6 +21,21 @@ export type EmployeeDeviceActivationResult = {
|
|
|
21
21
|
exchange: SubmitAndPollResult;
|
|
22
22
|
dcr: SubmitAndPollResult;
|
|
23
23
|
};
|
|
24
|
+
export type EmployeeDeviceRevocationInput = {
|
|
25
|
+
licenseId: string;
|
|
26
|
+
clientId: string;
|
|
27
|
+
requestThid?: string;
|
|
28
|
+
pollOptions?: PollOptions;
|
|
29
|
+
};
|
|
30
|
+
export declare function revokeEmployeeDeviceWithDeps(deps: {
|
|
31
|
+
routeCtx: RouteContext;
|
|
32
|
+
input: EmployeeDeviceRevocationInput;
|
|
33
|
+
identityDeviceRevokePath: (ctx: RouteContext) => string;
|
|
34
|
+
identityDeviceRevokePollPath: (ctx: RouteContext) => string;
|
|
35
|
+
submitAndPoll: (submitPath: string, pollPath: string, payload: {
|
|
36
|
+
thid?: string;
|
|
37
|
+
} & Record<string, unknown>, pollOptions?: PollOptions) => Promise<SubmitAndPollResult>;
|
|
38
|
+
}): Promise<SubmitAndPollResult>;
|
|
24
39
|
type ActivateEmployeeDeviceDeps = {
|
|
25
40
|
routeCtx: RouteContext;
|
|
26
41
|
input: EmployeeDeviceActivationInput;
|
|
@@ -1,30 +1,44 @@
|
|
|
1
1
|
// Copyright 2026 Antifraud Services Inc. under the Apache License, Version 2.0.
|
|
2
2
|
import { resolvePollOptionsFromSeconds } from './poll-options.js';
|
|
3
|
+
import { IdentityAuthRequestFields, IdentityAuthResponseFields, IdentityDcrMetadataFields, IdentityDeviceInfoFields, } from 'gdc-common-utils-ts/constants/identity-auth';
|
|
4
|
+
import { buildEmployeeDeviceRevocationBody } from 'gdc-common-utils-ts/utils/organization-employee-lifecycle';
|
|
5
|
+
export async function revokeEmployeeDeviceWithDeps(deps) {
|
|
6
|
+
const licenseId = String(deps.input.licenseId || '').trim();
|
|
7
|
+
const clientId = String(deps.input.clientId || '').trim();
|
|
8
|
+
if (!licenseId || !clientId)
|
|
9
|
+
throw new Error('revokeEmployeeDevice: licenseId and clientId are required.');
|
|
10
|
+
return deps.submitAndPoll(deps.identityDeviceRevokePath(deps.routeCtx), deps.identityDeviceRevokePollPath(deps.routeCtx), {
|
|
11
|
+
thid: deps.input.requestThid || `device-revoke-${createRuntimeUuid()}`,
|
|
12
|
+
body: buildEmployeeDeviceRevocationBody({ licenseId, clientId }),
|
|
13
|
+
}, deps.input.pollOptions);
|
|
14
|
+
}
|
|
3
15
|
export async function activateEmployeeDeviceWithActivationCodeWithDeps(deps) {
|
|
4
|
-
const deviceInfo = deps.input.dcrPayload.
|
|
5
|
-
const redirectUris = deps.input.dcrPayload.
|
|
6
|
-
const jwks = deps.input.dcrPayload.
|
|
7
|
-
const clientInstanceId = String(deviceInfo?.
|
|
8
|
-
|| (deps.input.dcrPayload.
|
|
16
|
+
const deviceInfo = deps.input.dcrPayload[IdentityDcrMetadataFields.ExtendedDeviceInfo];
|
|
17
|
+
const redirectUris = deps.input.dcrPayload[IdentityDcrMetadataFields.RedirectUris];
|
|
18
|
+
const jwks = deps.input.dcrPayload[IdentityDcrMetadataFields.Jwks];
|
|
19
|
+
const clientInstanceId = String(deviceInfo?.[IdentityDeviceInfoFields.DeviceId]
|
|
20
|
+
|| (deps.input.dcrPayload[IdentityDcrMetadataFields.SoftwareId] ? `software:${deps.input.dcrPayload[IdentityDcrMetadataFields.SoftwareId]}` : '')
|
|
9
21
|
|| (redirectUris?.[0] ? `redirect:${redirectUris[0]}` : '')
|
|
10
22
|
|| (jwks?.keys?.[0]?.kid ? `key:${jwks.keys[0].kid}` : '')).trim();
|
|
11
23
|
if (!clientInstanceId)
|
|
12
24
|
throw new Error('Device activation requires a stable device, software, redirect, or key identifier.');
|
|
13
25
|
const exchangePayload = {
|
|
14
26
|
thid: `exchange-${createRuntimeUuid()}`,
|
|
15
|
-
|
|
16
|
-
|
|
27
|
+
[IdentityAuthRequestFields.SubjectToken]: deps.input.activationCode,
|
|
28
|
+
[IdentityAuthRequestFields.ClientInstanceId]: clientInstanceId,
|
|
17
29
|
};
|
|
18
30
|
const exchange = await deps.submitAndPollWithBearerToken(deps.input.idToken, deps.identityTokenExchangePath(deps.routeCtx), deps.identityTokenExchangePollPath(deps.routeCtx), exchangePayload, deps.input.pollOptions);
|
|
19
31
|
const pollBody = exchange.poll.body || {};
|
|
20
32
|
const exchangeBody = (pollBody.body || pollBody);
|
|
21
|
-
const initialAccessToken = String(exchangeBody.
|
|
33
|
+
const initialAccessToken = String(exchangeBody[IdentityAuthResponseFields.InitialAccessToken]
|
|
34
|
+
|| exchangeBody[IdentityAuthResponseFields.AccessToken]
|
|
35
|
+
|| '').trim();
|
|
22
36
|
if (!initialAccessToken) {
|
|
23
37
|
throw new Error('activateEmployeeDeviceWithActivationCode: missing initial_access_token in exchange response.');
|
|
24
38
|
}
|
|
25
39
|
const dcrPayload = {
|
|
26
40
|
thid: `dcr-${createRuntimeUuid()}`,
|
|
27
|
-
|
|
41
|
+
[IdentityAuthRequestFields.Code]: deps.input.activationCode,
|
|
28
42
|
...deps.input.dcrPayload,
|
|
29
43
|
};
|
|
30
44
|
const dcr = await deps.submitAndPollWithBearerToken(initialAccessToken, deps.identityDeviceDcrPath(deps.routeCtx), deps.identityDeviceDcrPollPath(deps.routeCtx), dcrPayload, deps.input.pollOptions);
|
package/dist/index.d.ts
CHANGED
|
@@ -17,7 +17,8 @@ export * from './family-organization-registration.js';
|
|
|
17
17
|
export * from './individual-onboarding.js';
|
|
18
18
|
export * from './device-activation.js';
|
|
19
19
|
export * from './organization-controller-recovery.js';
|
|
20
|
-
export * from './organization-
|
|
20
|
+
export * from './organization-test-network-credential.js';
|
|
21
|
+
export * from './organization-employee-lifecycle.js';
|
|
21
22
|
export * from './smart-token.js';
|
|
22
23
|
export * from './fhir-r5-subscription-runtime.js';
|
|
23
24
|
export * from './order-offer-summary.js';
|
package/dist/index.js
CHANGED
|
@@ -18,7 +18,8 @@ export * from './family-organization-registration.js';
|
|
|
18
18
|
export * from './individual-onboarding.js';
|
|
19
19
|
export * from './device-activation.js';
|
|
20
20
|
export * from './organization-controller-recovery.js';
|
|
21
|
-
export * from './organization-
|
|
21
|
+
export * from './organization-test-network-credential.js';
|
|
22
|
+
export * from './organization-employee-lifecycle.js';
|
|
22
23
|
export * from './smart-token.js';
|
|
23
24
|
export * from './fhir-r5-subscription-runtime.js';
|
|
24
25
|
export * from './order-offer-summary.js';
|
|
@@ -8,12 +8,14 @@ import { type IndividualOrganizationConfirmOrderInput, type RouteContext } from
|
|
|
8
8
|
import { type EnsureFamilyOrganizationRegistrationInput } from './family-organization-registration.js';
|
|
9
9
|
import { type FamilyOrganizationSearchInput } from './family-organization-search.js';
|
|
10
10
|
import { type SmartTokenRequestInput } from './smart-token.js';
|
|
11
|
-
import { type EmployeeDeviceActivationRequestInput, type EmployeeDeviceActivationResult } from './device-activation.js';
|
|
11
|
+
import { type EmployeeDeviceActivationRequestInput, type EmployeeDeviceActivationResult, type EmployeeDeviceRevocationInput } from './device-activation.js';
|
|
12
12
|
import { type OrganizationLicenseOrderConfirmInput } from './organization-license-order.js';
|
|
13
13
|
import { type IndividualOrganizationBootstrapInput, type IndividualOrganizationStartResult } from './individual-start.js';
|
|
14
|
-
import { type CommunicationIngestionInput, type BlockchainArtifactRegistrationInput, type VitalSignBatchCommunicationFromSearchResponseInput, type CommunicationParticipantRuntimeSearchInput, type ClinicalBundleSearchInput, type ClinicalSectionUpdateInput, type ClinicalSummaryReadResult, type ClinicalSummaryRequestInput, type ClinicalSummaryUpdateInput, type GrantProfessionalAccessInput, type GrantProfessionalAccessResult, type IndividualMemberLifecycleInput, type IndividualMemberLicenseAddInput, type IndividualMemberLicenseInvitationInput, type IndividualMemberLicenseTransitionInput, type LicenseListRuntimeSearchInput, type LicenseOfferRuntimeSearchInput, type LicenseOrderRuntimeSearchInput, type OrganizationEmployeeCreationInput, type OrganizationEmployeeLifecycleInput, type OrganizationEmployeeSearchInput, type ProfessionalAccessRequestInput, type ProfessionalAccessRequestResult, type RevokeProfessionalAccessInput, type RevokeProfessionalAccessResult, type RelatedPersonUpsertInput } from './resource-operations.js';
|
|
14
|
+
import { type CommunicationIngestionInput, type BlockchainArtifactRegistrationInput, type VitalSignBatchCommunicationFromSearchResponseInput, type CommunicationParticipantRuntimeSearchInput, type ClinicalBundleSearchInput, type ClinicalSectionUpdateInput, type ClinicalSummaryReadResult, type ClinicalSummaryRequestInput, type ClinicalSummaryUpdateInput, type GrantProfessionalAccessInput, type GrantProfessionalAccessResult, type IndividualMemberLifecycleInput, type IndividualMemberLicenseAddInput, type IndividualMemberLicenseInvitationInput, type IndividualMemberLicenseTransitionInput, type LicenseListRuntimeSearchInput, type LicenseOfferRuntimeSearchInput, type LicenseOrderRuntimeSearchInput, type OrganizationEmployeeCreationInput, type OrganizationEmployeeLicenseInvitationInput, type OrganizationEmployeeLifecycleInput, type OrganizationEmployeeSearchInput, type ProfessionalAccessRequestInput, type ProfessionalAccessRequestResult, type RevokeProfessionalAccessInput, type RevokeProfessionalAccessResult, type RelatedPersonUpsertInput } from './resource-operations.js';
|
|
15
15
|
import type { LegalOrganizationOrderInput } from './host-onboarding.js';
|
|
16
16
|
import type { SmartTokenExchangeResult } from './smart-token.js';
|
|
17
|
+
import { type OrganizationEmployeeProvisioningInput, type OrganizationEmployeeProvisioningResult } from './organization-employee-lifecycle.js';
|
|
18
|
+
import type { OrganizationEmployeeLifecycleRecord } from 'gdc-common-utils-ts/models/organization-employee-lifecycle';
|
|
17
19
|
import type { NodeRuntimeClient, PollOptions, PollResult, SubmitAndPollResult, SubmitPayload, SubmitResponse } from './orchestration/client-port.js';
|
|
18
20
|
import { type FhirR5SubscriptionBatchInput } from './fhir-r5-subscription-runtime.js';
|
|
19
21
|
import type { FhirR5SubscriptionTopic } from 'gdc-common-utils-ts/models/fhir-r5-subscription';
|
|
@@ -250,6 +252,12 @@ export declare class HttpRuntimeClient implements NodeRuntimeClient {
|
|
|
250
252
|
* Creates an employee or professional entry under an existing organization tenant.
|
|
251
253
|
*/
|
|
252
254
|
createOrganizationEmployee(ctx: RouteContext, input: OrganizationEmployeeCreationInput, pollOptions?: PollOptions): Promise<SubmitAndPollResult>;
|
|
255
|
+
/** Creates an employee and reserves its activation credential as one SDK workflow. */
|
|
256
|
+
provisionOrganizationEmployee(ctx: RouteContext, input: OrganizationEmployeeProvisioningInput): Promise<OrganizationEmployeeProvisioningResult>;
|
|
257
|
+
/** Revokes one selected employee installation without releasing its seat. */
|
|
258
|
+
revokeEmployeeDevice(ctx: RouteContext, input: EmployeeDeviceRevocationInput): Promise<SubmitAndPollResult>;
|
|
259
|
+
/** Reserves an employee seat and issues its bounded multi-device activation credential. */
|
|
260
|
+
issueOrganizationEmployeeLicense(ctx: RouteContext, input: OrganizationEmployeeLicenseInvitationInput): Promise<SubmitAndPollResult>;
|
|
253
261
|
/**
|
|
254
262
|
* Disables an employee using the current GW CORE contract.
|
|
255
263
|
*
|
|
@@ -276,6 +284,8 @@ export declare class HttpRuntimeClient implements NodeRuntimeClient {
|
|
|
276
284
|
* Searches employees/professionals under the selected organization tenant.
|
|
277
285
|
*/
|
|
278
286
|
searchOrganizationEmployees(ctx: RouteContext, input: OrganizationEmployeeSearchInput): Promise<SubmitAndPollResult>;
|
|
287
|
+
/** Lists employees with their license and installation state. */
|
|
288
|
+
listOrganizationEmployeeLifecycle(ctx: RouteContext): Promise<OrganizationEmployeeLifecycleRecord[]>;
|
|
279
289
|
/**
|
|
280
290
|
* Searches organization-owned license seats through the canonical
|
|
281
291
|
* `License/_search` route.
|
|
@@ -8,11 +8,12 @@ import { confirmIndividualOrganizationOrderWithDeps, } from './individual-onboar
|
|
|
8
8
|
import { ensureFamilyOrganizationRegistrationWithDeps, } from './family-organization-registration.js';
|
|
9
9
|
import { searchFamilyOrganizationWithDeps } from './family-organization-search.js';
|
|
10
10
|
import { requestSmartTokenWithDeps } from './smart-token.js';
|
|
11
|
-
import { activateEmployeeDeviceWithActivationCodeWithDeps, activateEmployeeDeviceWithActivationRequestWithDeps, } from './device-activation.js';
|
|
11
|
+
import { activateEmployeeDeviceWithActivationCodeWithDeps, activateEmployeeDeviceWithActivationRequestWithDeps, revokeEmployeeDeviceWithDeps, } from './device-activation.js';
|
|
12
12
|
import { extractOfferIdFromResponseBody, extractOfferPreviewFromResponseBody, } from './order-offer-summary.js';
|
|
13
13
|
import { confirmOrganizationLicenseOrderWithDeps } from './organization-license-order.js';
|
|
14
14
|
import { startIndividualOrganizationWithDeps } from './individual-start.js';
|
|
15
|
-
import { createOrganizationEmployeeWithDeps, disableIndividualMemberWithDeps, disableIndividualOrganizationWithDeps, disableOrganizationEmployeeWithDeps, listIndividualLicenseOffersWithDeps, listIndividualLicenseOrdersWithDeps, listIndividualLicensesWithDeps, addFreeIndividualMemberLicensesWithDeps, issueIndividualMemberLicenseWithDeps, transitionIndividualMemberLicenseWithDeps, listOrganizationLicenseOffersWithDeps, listOrganizationLicenseOrdersWithDeps, listOrganizationLicensesWithDeps, grantProfessionalAccessWithDeps, buildClinicalSectionUpdateIngestion, buildClinicalSummaryUpdateIngestion, ingestCommunicationAndUpdateIndexWithDeps, requestProfessionalAccessWithDeps, buildVitalSignBatchCommunicationFromSearchResponse, registerBlockchainArtifactAndUpdateIndexWithDeps, requestClinicalSummaryWithDeps, revokeProfessionalAccessWithDeps, searchCommunicationParticipantsWithDeps, purgeIndividualMemberWithDeps, purgeIndividualOrganizationWithDeps, purgeOrganizationEmployeeWithDeps, prepareEmployeeLifecycleMessageForTransport, searchIndividualLicensesWithDeps, searchIndividualLicenseOffersWithDeps, searchIndividualLicenseOrdersWithDeps, searchOrganizationLicensesWithDeps, searchOrganizationLicenseOffersWithDeps, searchOrganizationLicenseOrdersWithDeps, searchOrganizationEmployeesWithDeps, searchClinicalBundleWithDeps, searchLatestIpsWithDeps, upsertRelatedPersonAndPollWithDeps, normalizeCommunicationPathFormatSegment, } from './resource-operations.js';
|
|
15
|
+
import { createOrganizationEmployeeWithDeps, issueOrganizationEmployeeLicenseWithDeps, disableIndividualMemberWithDeps, disableIndividualOrganizationWithDeps, disableOrganizationEmployeeWithDeps, listIndividualLicenseOffersWithDeps, listIndividualLicenseOrdersWithDeps, listIndividualLicensesWithDeps, addFreeIndividualMemberLicensesWithDeps, issueIndividualMemberLicenseWithDeps, transitionIndividualMemberLicenseWithDeps, listOrganizationLicenseOffersWithDeps, listOrganizationLicenseOrdersWithDeps, listOrganizationLicensesWithDeps, grantProfessionalAccessWithDeps, buildClinicalSectionUpdateIngestion, buildClinicalSummaryUpdateIngestion, ingestCommunicationAndUpdateIndexWithDeps, requestProfessionalAccessWithDeps, buildVitalSignBatchCommunicationFromSearchResponse, registerBlockchainArtifactAndUpdateIndexWithDeps, requestClinicalSummaryWithDeps, revokeProfessionalAccessWithDeps, searchCommunicationParticipantsWithDeps, purgeIndividualMemberWithDeps, purgeIndividualOrganizationWithDeps, purgeOrganizationEmployeeWithDeps, prepareEmployeeLifecycleMessageForTransport, searchIndividualLicensesWithDeps, searchIndividualLicenseOffersWithDeps, searchIndividualLicenseOrdersWithDeps, searchOrganizationLicensesWithDeps, searchOrganizationLicenseOffersWithDeps, searchOrganizationLicenseOrdersWithDeps, searchOrganizationEmployeesWithDeps, searchClinicalBundleWithDeps, searchLatestIpsWithDeps, upsertRelatedPersonAndPollWithDeps, normalizeCommunicationPathFormatSegment, } from './resource-operations.js';
|
|
16
|
+
import { listOrganizationEmployeeLifecycleWithDeps, provisionOrganizationEmployeeWithDeps, } from './organization-employee-lifecycle.js';
|
|
16
17
|
import { submitAndPollWithMethods } from './orchestration/client-port.js';
|
|
17
18
|
import { buildRuntimeHeaders, fetchWithTimeout, parseResponseBody, pollBatchResponseWithRuntimeConfig, postJsonWithRuntimeConfig, postRenderedWithRuntimeConfig, } from './runtime-transport.js';
|
|
18
19
|
import { activateOrganizationInGatewayFromIcaProofWithDeps, submitLegalOrganizationCredentialReissuanceWithDeps, submitLegalOrganizationVerificationTransactionWithDeps, submitOrganizationDidBindingWithDeps, } from './runtime-host-submission.js';
|
|
@@ -365,6 +366,35 @@ export class HttpRuntimeClient {
|
|
|
365
366
|
submitAndPoll: (submitPath, pollPath, payload, options) => this.submitClinicalMessageAndPoll(submitPath, pollPath, prepareEmployeeLifecycleMessageForTransport(payload, this.transportProfile), this.transportProfile, options),
|
|
366
367
|
});
|
|
367
368
|
}
|
|
369
|
+
/** Creates an employee and reserves its activation credential as one SDK workflow. */
|
|
370
|
+
async provisionOrganizationEmployee(ctx, input) {
|
|
371
|
+
return provisionOrganizationEmployeeWithDeps(ctx, input, {
|
|
372
|
+
createEmployee: (routeContext, creation) => this.createOrganizationEmployee(routeContext, creation),
|
|
373
|
+
issueLicense: (routeContext, invitation) => this.issueOrganizationEmployeeLicense(routeContext, invitation),
|
|
374
|
+
});
|
|
375
|
+
}
|
|
376
|
+
/** Revokes one selected employee installation without releasing its seat. */
|
|
377
|
+
async revokeEmployeeDevice(ctx, input) {
|
|
378
|
+
return revokeEmployeeDeviceWithDeps({
|
|
379
|
+
routeCtx: ctx,
|
|
380
|
+
input,
|
|
381
|
+
identityDeviceRevokePath: this.paths.identityDeviceRevokePath.bind(this.paths),
|
|
382
|
+
identityDeviceRevokePollPath: this.paths.identityDeviceRevokePollPath.bind(this.paths),
|
|
383
|
+
submitAndPoll: this.transportProfile === TransportProfiles.DidcommEncryptedForm
|
|
384
|
+
? (submitPath, pollPath, payload, pollOptions) => this.submitClinicalMessageAndPoll(submitPath, pollPath, payload, this.transportProfile, pollOptions)
|
|
385
|
+
: this.submitAndPoll.bind(this),
|
|
386
|
+
});
|
|
387
|
+
}
|
|
388
|
+
/** Reserves an employee seat and issues its bounded multi-device activation credential. */
|
|
389
|
+
async issueOrganizationEmployeeLicense(ctx, input) {
|
|
390
|
+
return issueOrganizationEmployeeLicenseWithDeps(ctx, input, {
|
|
391
|
+
identityLicenseIssuePath: this.paths.identityLicenseIssuePath.bind(this.paths),
|
|
392
|
+
identityLicenseIssuePollPath: this.paths.identityLicenseIssuePollPath.bind(this.paths),
|
|
393
|
+
submitAndPoll: this.transportProfile === TransportProfiles.DidcommEncryptedForm
|
|
394
|
+
? (submitPath, pollPath, payload, pollOptions) => this.submitClinicalMessageAndPoll(submitPath, pollPath, payload, this.transportProfile, pollOptions)
|
|
395
|
+
: this.submitAndPoll.bind(this),
|
|
396
|
+
});
|
|
397
|
+
}
|
|
368
398
|
/**
|
|
369
399
|
* Disables an employee using the current GW CORE contract.
|
|
370
400
|
*
|
|
@@ -413,6 +443,13 @@ export class HttpRuntimeClient {
|
|
|
413
443
|
submitAndPoll: this.submitAndPoll.bind(this),
|
|
414
444
|
});
|
|
415
445
|
}
|
|
446
|
+
/** Lists employees with their license and installation state. */
|
|
447
|
+
async listOrganizationEmployeeLifecycle(ctx) {
|
|
448
|
+
return listOrganizationEmployeeLifecycleWithDeps(ctx, {
|
|
449
|
+
searchEmployees: (routeContext, input) => this.searchOrganizationEmployees(routeContext, input),
|
|
450
|
+
listLicenses: (routeContext, input) => this.listOrganizationLicenses(routeContext, input),
|
|
451
|
+
});
|
|
452
|
+
}
|
|
416
453
|
/**
|
|
417
454
|
* Searches organization-owned license seats through the canonical
|
|
418
455
|
* `License/_search` route.
|
|
@@ -5,7 +5,9 @@ import type { IndividualOrganizationLifecycleInput, OrganizationDidBindingInput
|
|
|
5
5
|
import type { LicenseListRuntimeSearchInput, LicenseOfferRuntimeSearchInput, LicenseOrderRuntimeSearchInput } from '../resource-operations.js';
|
|
6
6
|
import type { AsyncPollRequest, OrganizationActivationServiceOptions, PollOptions, PollResult, SubmitAndPollResult, SubmitPayload, SubmitResponse } from 'gdc-sdk-core-ts';
|
|
7
7
|
export type { AsyncPollRequest, PollOptions, PollResult, SubmitAndPollResult, SubmitPayload, SubmitResponse, } from 'gdc-sdk-core-ts';
|
|
8
|
-
import type { EmployeeDeviceActivationResult, EmployeeDeviceActivationRequestInput } from '../device-activation.js';
|
|
8
|
+
import type { EmployeeDeviceActivationResult, EmployeeDeviceActivationRequestInput, EmployeeDeviceRevocationInput } from '../device-activation.js';
|
|
9
|
+
import type { OrganizationEmployeeProvisioningInput, OrganizationEmployeeProvisioningResult } from '../organization-employee-lifecycle.js';
|
|
10
|
+
import type { OrganizationEmployeeLifecycleRecord } from 'gdc-common-utils-ts/models/organization-employee-lifecycle';
|
|
9
11
|
import type { HostRouteContext, HostedTenantLifecycleInput, LegalOrganizationOrderInput } from '../host-onboarding.js';
|
|
10
12
|
import type { IndividualOrganizationConfirmOrderInput, RouteContext } from '../individual-onboarding.js';
|
|
11
13
|
import type { IndividualOrganizationBootstrapInput, IndividualOrganizationStartResult } from '../individual-start.js';
|
|
@@ -15,7 +17,7 @@ import type { FhirR5SubscriptionBatchInput } from '../fhir-r5-subscription-runti
|
|
|
15
17
|
import type { EnsureFamilyOrganizationRegistrationInput, EnsureFamilyOrganizationRegistrationResult } from '../family-organization-registration.js';
|
|
16
18
|
import type { OrganizationLicenseOrderConfirmInput } from '../organization-license-order.js';
|
|
17
19
|
import type { SmartTokenExchangeResult, SmartTokenRequestInput } from '../smart-token.js';
|
|
18
|
-
import type { CommunicationIngestionInput, BlockchainArtifactRegistrationInput, CommunicationParticipantRuntimeSearchInput, ClinicalBundleSearchInput, ClinicalSectionUpdateInput, ClinicalSummaryReadResult, ClinicalSummaryRequestInput, ClinicalSummaryUpdateInput, VitalSignBatchCommunicationFromSearchResponseInput, DigitalTwinGenerationInput, GrantProfessionalAccessInput, GrantProfessionalAccessResult, IndividualMemberLifecycleInput, IndividualMemberLicenseAddInput, IndividualMemberLicenseInvitationInput, IndividualMemberLicenseTransitionInput, IpsOrFhirImportInput, OrganizationEmployeeCreationInput, OrganizationEmployeeLifecycleInput, OrganizationEmployeeSearchInput, ProfessionalAccessRequestInput, ProfessionalAccessRequestResult, RevokeProfessionalAccessInput, RevokeProfessionalAccessResult, RelatedPersonUpsertInput } from '../resource-operations.js';
|
|
20
|
+
import type { CommunicationIngestionInput, BlockchainArtifactRegistrationInput, CommunicationParticipantRuntimeSearchInput, ClinicalBundleSearchInput, ClinicalSectionUpdateInput, ClinicalSummaryReadResult, ClinicalSummaryRequestInput, ClinicalSummaryUpdateInput, VitalSignBatchCommunicationFromSearchResponseInput, DigitalTwinGenerationInput, GrantProfessionalAccessInput, GrantProfessionalAccessResult, IndividualMemberLifecycleInput, IndividualMemberLicenseAddInput, IndividualMemberLicenseInvitationInput, IndividualMemberLicenseTransitionInput, IpsOrFhirImportInput, OrganizationEmployeeCreationInput, OrganizationEmployeeLicenseInvitationInput, OrganizationEmployeeLifecycleInput, OrganizationEmployeeSearchInput, ProfessionalAccessRequestInput, ProfessionalAccessRequestResult, RevokeProfessionalAccessInput, RevokeProfessionalAccessResult, RelatedPersonUpsertInput } from '../resource-operations.js';
|
|
19
21
|
/**
|
|
20
22
|
* Shared node-runtime activation input.
|
|
21
23
|
*
|
|
@@ -72,7 +74,10 @@ export type RuntimeClient = {
|
|
|
72
74
|
disableTenant?: (hostCtx: HostRouteContext, input: HostedTenantLifecycleInput, pollOptions?: PollOptions) => Promise<SubmitAndPollResult>;
|
|
73
75
|
purgeTenant?: (hostCtx: HostRouteContext, input: HostedTenantLifecycleInput, pollOptions?: PollOptions) => Promise<SubmitAndPollResult>;
|
|
74
76
|
createOrganizationEmployee?: (ctx: RouteContext, input: OrganizationEmployeeCreationInput, pollOptions?: PollOptions) => Promise<SubmitAndPollResult>;
|
|
77
|
+
provisionOrganizationEmployee?: (ctx: RouteContext, input: OrganizationEmployeeProvisioningInput) => Promise<OrganizationEmployeeProvisioningResult>;
|
|
78
|
+
issueOrganizationEmployeeLicense?: (ctx: RouteContext, input: OrganizationEmployeeLicenseInvitationInput) => Promise<SubmitAndPollResult>;
|
|
75
79
|
searchOrganizationEmployees?: (ctx: RouteContext, input: OrganizationEmployeeSearchInput) => Promise<SubmitAndPollResult>;
|
|
80
|
+
listOrganizationEmployeeLifecycle?: (ctx: RouteContext) => Promise<OrganizationEmployeeLifecycleRecord[]>;
|
|
76
81
|
searchOrganizationLicenses?: (ctx: RouteContext, input: LicenseListRuntimeSearchInput) => Promise<SubmitAndPollResult>;
|
|
77
82
|
listOrganizationLicenses?: (ctx: RouteContext, input?: LicenseListRuntimeSearchInput) => Promise<SubmitAndPollResult>;
|
|
78
83
|
searchOrganizationLicenseOffers?: (ctx: RouteContext, input: LicenseOfferRuntimeSearchInput) => Promise<SubmitAndPollResult>;
|
|
@@ -85,6 +90,7 @@ export type RuntimeClient = {
|
|
|
85
90
|
disableOrganizationEmployee?: (ctx: RouteContext, input: OrganizationEmployeeLifecycleInput, pollOptions?: PollOptions) => Promise<SubmitAndPollResult>;
|
|
86
91
|
purgeOrganizationEmployee?: (ctx: RouteContext, input: OrganizationEmployeeLifecycleInput, pollOptions?: PollOptions) => Promise<SubmitAndPollResult>;
|
|
87
92
|
activateEmployeeDeviceWithActivationRequest?: (input: EmployeeDeviceActivationRequestInput) => Promise<EmployeeDeviceActivationResult>;
|
|
93
|
+
revokeEmployeeDevice?: (ctx: RouteContext, input: EmployeeDeviceRevocationInput) => Promise<SubmitAndPollResult>;
|
|
88
94
|
requestSmartToken?: (input: SmartTokenRequestInput) => Promise<SmartTokenExchangeResult>;
|
|
89
95
|
startIndividualOrganization?: (input: IndividualOrganizationBootstrapInput) => Promise<IndividualOrganizationStartResult>;
|
|
90
96
|
searchFamilyOrganization?: (ctx: RouteContext, input: FamilyOrganizationSearchInput) => Promise<FamilyOrganizationSummary | null>;
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import { type NodeOrganizationDidBindingInput, type NodeLegalOrganizationVerificationTransactionInput, type NodeRuntimeClient, type PollOptions, type SubmitAndPollResult, type SubmitPayload } from './client-port.js';
|
|
2
2
|
import type { RouteContext } from '../individual-onboarding.js';
|
|
3
3
|
import type { HostRouteContext, HostedTenantLifecycleInput } from '../host-onboarding.js';
|
|
4
|
-
import type { EmployeeDeviceActivationResult, EmployeeDeviceActivationRequestInput } from '../device-activation.js';
|
|
4
|
+
import type { EmployeeDeviceActivationResult, EmployeeDeviceActivationRequestInput, EmployeeDeviceRevocationInput } from '../device-activation.js';
|
|
5
5
|
import type { SmartTokenExchangeResult, SmartTokenRequestInput } from '../smart-token.js';
|
|
6
6
|
import type { OrganizationLicenseOrderConfirmInput } from '../organization-license-order.js';
|
|
7
7
|
import type { NodeCapability } from '../session.js';
|
|
8
|
-
import type { LicenseListRuntimeSearchInput, LicenseOfferRuntimeSearchInput, LicenseOrderRuntimeSearchInput, OrganizationEmployeeCreationInput, OrganizationEmployeeLifecycleInput, OrganizationEmployeeSearchInput } from '../resource-operations.js';
|
|
8
|
+
import type { LicenseListRuntimeSearchInput, LicenseOfferRuntimeSearchInput, LicenseOrderRuntimeSearchInput, OrganizationEmployeeCreationInput, OrganizationEmployeeLicenseInvitationInput, OrganizationEmployeeLifecycleInput, OrganizationEmployeeSearchInput } from '../resource-operations.js';
|
|
9
|
+
import type { OrganizationEmployeeProvisioningInput, OrganizationEmployeeProvisioningResult } from '../organization-employee-lifecycle.js';
|
|
10
|
+
import type { OrganizationEmployeeLifecycleRecord } from 'gdc-common-utils-ts/models/organization-employee-lifecycle';
|
|
9
11
|
/**
|
|
10
12
|
* Organization-controller oriented facade over a `NodeRuntimeClient`.
|
|
11
13
|
*
|
|
@@ -55,6 +57,10 @@ export declare class OrganizationControllerSdk {
|
|
|
55
57
|
* Creates an employee/professional under the current organization tenant.
|
|
56
58
|
*/
|
|
57
59
|
createOrganizationEmployee(ctx: RouteContext, input: OrganizationEmployeeCreationInput, pollOptions?: PollOptions): Promise<SubmitAndPollResult>;
|
|
60
|
+
/** Creates the employee and issues its reusable multi-installation credential. */
|
|
61
|
+
provisionOrganizationEmployee(ctx: RouteContext, input: OrganizationEmployeeProvisioningInput): Promise<OrganizationEmployeeProvisioningResult>;
|
|
62
|
+
/** Reserves the employee seat and returns its bounded multi-device activation credential. */
|
|
63
|
+
issueOrganizationEmployeeLicense(ctx: RouteContext, input: OrganizationEmployeeLicenseInvitationInput): Promise<SubmitAndPollResult>;
|
|
58
64
|
/**
|
|
59
65
|
* Disables an employee using the current GW CORE lifecycle contract.
|
|
60
66
|
*/
|
|
@@ -67,6 +73,8 @@ export declare class OrganizationControllerSdk {
|
|
|
67
73
|
* Searches employees/professionals under the current organization tenant.
|
|
68
74
|
*/
|
|
69
75
|
searchOrganizationEmployees(ctx: RouteContext, input: OrganizationEmployeeSearchInput): Promise<SubmitAndPollResult>;
|
|
76
|
+
/** Lists employees with typed license and device lifecycle state. */
|
|
77
|
+
listOrganizationEmployeeLifecycle(ctx: RouteContext): Promise<OrganizationEmployeeLifecycleRecord[]>;
|
|
70
78
|
/**
|
|
71
79
|
* Searches organization-owned license seats using semantic license filters.
|
|
72
80
|
*/
|
|
@@ -130,6 +138,8 @@ export declare class OrganizationControllerSdk {
|
|
|
130
138
|
* Activates the employee device from a previously issued activation request.
|
|
131
139
|
*/
|
|
132
140
|
activateEmployeeDeviceWithActivationRequest(input: EmployeeDeviceActivationRequestInput): Promise<EmployeeDeviceActivationResult>;
|
|
141
|
+
/** Revokes one selected installation while preserving the employee and seat. */
|
|
142
|
+
revokeEmployeeDevice(ctx: RouteContext, input: EmployeeDeviceRevocationInput): Promise<SubmitAndPollResult>;
|
|
133
143
|
/**
|
|
134
144
|
* Requests a SMART token for the current organization-scoped actor.
|
|
135
145
|
*
|
|
@@ -66,6 +66,15 @@ export class OrganizationControllerSdk {
|
|
|
66
66
|
assertFacadeCapability(this.capabilities, ActorCapabilities.OrganizationCreateEmployee, ActorKinds.OrganizationController, 'createOrganizationEmployee');
|
|
67
67
|
return requireClientMethod(this.client, 'createOrganizationEmployee')(ctx, input, pollOptions);
|
|
68
68
|
}
|
|
69
|
+
/** Creates the employee and issues its reusable multi-installation credential. */
|
|
70
|
+
provisionOrganizationEmployee(ctx, input) {
|
|
71
|
+
assertFacadeCapability(this.capabilities, ActorCapabilities.OrganizationCreateEmployee, ActorKinds.OrganizationController, 'provisionOrganizationEmployee');
|
|
72
|
+
return requireClientMethod(this.client, 'provisionOrganizationEmployee')(ctx, input);
|
|
73
|
+
}
|
|
74
|
+
/** Reserves the employee seat and returns its bounded multi-device activation credential. */
|
|
75
|
+
issueOrganizationEmployeeLicense(ctx, input) {
|
|
76
|
+
return requireClientMethod(this.client, 'issueOrganizationEmployeeLicense')(ctx, input);
|
|
77
|
+
}
|
|
69
78
|
/**
|
|
70
79
|
* Disables an employee using the current GW CORE lifecycle contract.
|
|
71
80
|
*/
|
|
@@ -86,6 +95,10 @@ export class OrganizationControllerSdk {
|
|
|
86
95
|
searchOrganizationEmployees(ctx, input) {
|
|
87
96
|
return requireClientMethod(this.client, 'searchOrganizationEmployees')(ctx, input);
|
|
88
97
|
}
|
|
98
|
+
/** Lists employees with typed license and device lifecycle state. */
|
|
99
|
+
listOrganizationEmployeeLifecycle(ctx) {
|
|
100
|
+
return requireClientMethod(this.client, 'listOrganizationEmployeeLifecycle')(ctx);
|
|
101
|
+
}
|
|
89
102
|
/**
|
|
90
103
|
* Searches organization-owned license seats using semantic license filters.
|
|
91
104
|
*/
|
|
@@ -177,6 +190,10 @@ export class OrganizationControllerSdk {
|
|
|
177
190
|
activateEmployeeDeviceWithActivationRequest(input) {
|
|
178
191
|
return requireClientMethod(this.client, 'activateEmployeeDeviceWithActivationRequest')(input);
|
|
179
192
|
}
|
|
193
|
+
/** Revokes one selected installation while preserving the employee and seat. */
|
|
194
|
+
revokeEmployeeDevice(ctx, input) {
|
|
195
|
+
return requireClientMethod(this.client, 'revokeEmployeeDevice')(ctx, input);
|
|
196
|
+
}
|
|
180
197
|
/**
|
|
181
198
|
* Requests a SMART token for the current organization-scoped actor.
|
|
182
199
|
*
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { type EmployeeActivationGrant, type OrganizationEmployeeLifecycleRecord } from 'gdc-common-utils-ts';
|
|
2
|
+
import type { RouteContext } from './individual-onboarding.js';
|
|
3
|
+
import type { SubmitAndPollResult } from './orchestration/client-port.js';
|
|
4
|
+
import type { ServerProfileEnrollmentInput, ServerProfileRecord } from './server-profile-session.js';
|
|
5
|
+
import type { LicenseListRuntimeSearchInput, OrganizationEmployeeCreationInput, OrganizationEmployeeLicenseInvitationInput, OrganizationEmployeeSearchInput } from './resource-operations.js';
|
|
6
|
+
/** Input for the atomic controller-facing create plus seat issuance workflow. */
|
|
7
|
+
export type OrganizationEmployeeProvisioningInput = Readonly<{
|
|
8
|
+
creation: OrganizationEmployeeCreationInput;
|
|
9
|
+
invitation: OrganizationEmployeeLicenseInvitationInput;
|
|
10
|
+
}>;
|
|
11
|
+
/** Results required by a portal to persist routing and display the credential once. */
|
|
12
|
+
export type OrganizationEmployeeProvisioningResult = Readonly<{
|
|
13
|
+
employee: SubmitAndPollResult;
|
|
14
|
+
license: SubmitAndPollResult;
|
|
15
|
+
activationCode: string;
|
|
16
|
+
}>;
|
|
17
|
+
/** Shared dependencies for the create plus seat issuance workflow. */
|
|
18
|
+
export type OrganizationEmployeeProvisioningDeps = Readonly<{
|
|
19
|
+
createEmployee(routeContext: RouteContext, input: OrganizationEmployeeCreationInput): Promise<SubmitAndPollResult>;
|
|
20
|
+
issueLicense(routeContext: RouteContext, input: OrganizationEmployeeLicenseInvitationInput): Promise<SubmitAndPollResult>;
|
|
21
|
+
}>;
|
|
22
|
+
/** Creates the employee, reserves its seat and returns the exact GW credential. */
|
|
23
|
+
export declare function provisionOrganizationEmployeeWithDeps(routeContext: RouteContext, input: OrganizationEmployeeProvisioningInput, deps: OrganizationEmployeeProvisioningDeps): Promise<OrganizationEmployeeProvisioningResult>;
|
|
24
|
+
/** Shared dependencies for combining employee and license directory searches. */
|
|
25
|
+
export type OrganizationEmployeeLifecycleQueryDeps = Readonly<{
|
|
26
|
+
searchEmployees(routeContext: RouteContext, input: OrganizationEmployeeSearchInput): Promise<SubmitAndPollResult>;
|
|
27
|
+
listLicenses(routeContext: RouteContext, input?: LicenseListRuntimeSearchInput): Promise<SubmitAndPollResult>;
|
|
28
|
+
}>;
|
|
29
|
+
/** Lists employees and their installation allowance through one typed projection. */
|
|
30
|
+
export declare function listOrganizationEmployeeLifecycleWithDeps(routeContext: RouteContext, deps: OrganizationEmployeeLifecycleQueryDeps): Promise<OrganizationEmployeeLifecycleRecord[]>;
|
|
31
|
+
/** Input used to persist routing metadata for one issued employee credential. */
|
|
32
|
+
export type EmployeeActivationGrantInput = Readonly<{
|
|
33
|
+
email: string;
|
|
34
|
+
employeeDid: string;
|
|
35
|
+
employeeRoleCode: string;
|
|
36
|
+
providerDid: string;
|
|
37
|
+
routeContext: RouteContext;
|
|
38
|
+
createdAt: Date;
|
|
39
|
+
expiresAt: Date;
|
|
40
|
+
}>;
|
|
41
|
+
/** Builds the product-neutral routing grant stored under a credential digest. */
|
|
42
|
+
export declare function createEmployeeActivationGrant(input: EmployeeActivationGrantInput): EmployeeActivationGrant;
|
|
43
|
+
/** Verifies that a stored routing grant belongs to the authenticated email. */
|
|
44
|
+
export declare function employeeActivationGrantMatchesEmail(grant: EmployeeActivationGrant, email: string): boolean;
|
|
45
|
+
/** Stable profile id derived from account, employee and provider identities. */
|
|
46
|
+
export declare function buildOrganizationEmployeeProfileId(input: Readonly<{
|
|
47
|
+
ownerId: string;
|
|
48
|
+
employeeDid: string;
|
|
49
|
+
providerDid: string;
|
|
50
|
+
clientInstanceId: string;
|
|
51
|
+
}>): string;
|
|
52
|
+
/** Enrolls a previously invited employee without organization discovery. */
|
|
53
|
+
export declare function enrollInvitedOrganizationEmployeeWithDeps(input: Readonly<{
|
|
54
|
+
ownerId: string;
|
|
55
|
+
idToken: string;
|
|
56
|
+
activationCode: string;
|
|
57
|
+
pin: string;
|
|
58
|
+
grant: EmployeeActivationGrant;
|
|
59
|
+
dcrRedirectUris: string[];
|
|
60
|
+
dcrClientName: string;
|
|
61
|
+
clientInstanceId: string;
|
|
62
|
+
}>, deps: Readonly<{
|
|
63
|
+
enroll(enrollment: ServerProfileEnrollmentInput): Promise<ServerProfileRecord>;
|
|
64
|
+
}>): Promise<ServerProfileRecord>;
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
// Copyright 2026 Antifraud Services Inc. under the Apache License, Version 2.0.
|
|
2
|
+
import { createHash } from 'node:crypto';
|
|
3
|
+
import { ActorKinds, EmployeeActivationGrantVersions, projectOrganizationEmployeeLifecycle, readEmployeeActivationCode, } from 'gdc-common-utils-ts';
|
|
4
|
+
import { buildStableActorIdentifier } from 'gdc-common-utils-ts/utils/actor-identifier';
|
|
5
|
+
/** Creates the employee, reserves its seat and returns the exact GW credential. */
|
|
6
|
+
export async function provisionOrganizationEmployeeWithDeps(routeContext, input, deps) {
|
|
7
|
+
const employee = await deps.createEmployee(routeContext, input.creation);
|
|
8
|
+
const license = await deps.issueLicense(routeContext, input.invitation);
|
|
9
|
+
const activationCode = readEmployeeActivationCode(license.poll.body);
|
|
10
|
+
if (!activationCode) {
|
|
11
|
+
throw new Error('provisionOrganizationEmployee: GW response did not contain an employee activation credential.');
|
|
12
|
+
}
|
|
13
|
+
return { employee, license, activationCode };
|
|
14
|
+
}
|
|
15
|
+
/** Lists employees and their installation allowance through one typed projection. */
|
|
16
|
+
export async function listOrganizationEmployeeLifecycleWithDeps(routeContext, deps) {
|
|
17
|
+
const [employees, licenses] = await Promise.all([
|
|
18
|
+
deps.searchEmployees(routeContext, {}),
|
|
19
|
+
deps.listLicenses(routeContext),
|
|
20
|
+
]);
|
|
21
|
+
return projectOrganizationEmployeeLifecycle({
|
|
22
|
+
employeeResponse: employees.poll.body,
|
|
23
|
+
licenseResponse: licenses.poll.body,
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
/** Builds the product-neutral routing grant stored under a credential digest. */
|
|
27
|
+
export function createEmployeeActivationGrant(input) {
|
|
28
|
+
return {
|
|
29
|
+
version: EmployeeActivationGrantVersions.V1,
|
|
30
|
+
employeeDid: input.employeeDid,
|
|
31
|
+
employeeRoleCode: input.employeeRoleCode,
|
|
32
|
+
employeeActorIdentifier: buildStableActorIdentifier({ contactKind: 'email', contact: input.email }),
|
|
33
|
+
providerDid: input.providerDid,
|
|
34
|
+
routeContext: input.routeContext,
|
|
35
|
+
createdAt: input.createdAt.toISOString(),
|
|
36
|
+
expiresAt: input.expiresAt.toISOString(),
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
/** Verifies that a stored routing grant belongs to the authenticated email. */
|
|
40
|
+
export function employeeActivationGrantMatchesEmail(grant, email) {
|
|
41
|
+
return grant.employeeActorIdentifier === buildStableActorIdentifier({ contactKind: 'email', contact: email });
|
|
42
|
+
}
|
|
43
|
+
/** Stable profile id derived from account, employee and provider identities. */
|
|
44
|
+
export function buildOrganizationEmployeeProfileId(input) {
|
|
45
|
+
const digest = createHash('sha256')
|
|
46
|
+
.update([input.ownerId, input.employeeDid, input.providerDid, input.clientInstanceId].join('\u0000'))
|
|
47
|
+
.digest('base64url');
|
|
48
|
+
return `organization-employee:${digest}`;
|
|
49
|
+
}
|
|
50
|
+
/** Enrolls a previously invited employee without organization discovery. */
|
|
51
|
+
export async function enrollInvitedOrganizationEmployeeWithDeps(input, deps) {
|
|
52
|
+
const profileId = buildOrganizationEmployeeProfileId({
|
|
53
|
+
ownerId: input.ownerId,
|
|
54
|
+
employeeDid: input.grant.employeeDid,
|
|
55
|
+
providerDid: input.grant.providerDid,
|
|
56
|
+
clientInstanceId: input.clientInstanceId,
|
|
57
|
+
});
|
|
58
|
+
return deps.enroll({
|
|
59
|
+
ownerId: input.ownerId,
|
|
60
|
+
profileId,
|
|
61
|
+
actorKind: ActorKinds.OrganizationEmployee,
|
|
62
|
+
actorMode: 'member',
|
|
63
|
+
actorDid: input.grant.employeeDid,
|
|
64
|
+
profileDid: input.grant.employeeDid,
|
|
65
|
+
providerDid: input.grant.providerDid,
|
|
66
|
+
routeContext: input.grant.routeContext,
|
|
67
|
+
allowedSubjectDids: [input.grant.employeeDid],
|
|
68
|
+
pin: input.pin,
|
|
69
|
+
idToken: input.idToken,
|
|
70
|
+
activationCode: input.activationCode,
|
|
71
|
+
clientInstanceId: input.clientInstanceId,
|
|
72
|
+
dcrRedirectUris: input.dcrRedirectUris,
|
|
73
|
+
dcrClientName: input.dcrClientName,
|
|
74
|
+
vpToken: input.idToken,
|
|
75
|
+
});
|
|
76
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { VerifiableCredentialV2 } from 'gdc-common-utils-ts/models/verifiable-credential';
|
|
2
2
|
import type { IWallet, WalletExecutionContext, WalletKeySelection } from 'gdc-sdk-core-ts';
|
|
3
3
|
/** Input required to add one human-authorizer proof to the out-of-band VC. */
|
|
4
|
-
export type
|
|
4
|
+
export type SignOrganizationTestNetworkCredentialInput = Readonly<{
|
|
5
5
|
credential: VerifiableCredentialV2;
|
|
6
6
|
wallet: IWallet;
|
|
7
7
|
context: WalletExecutionContext;
|
|
@@ -13,4 +13,9 @@ export type SignOrganizationRegistrationAuthorizationInput = Readonly<{
|
|
|
13
13
|
* Adds one detached JWS proof made by the already-unlocked professional
|
|
14
14
|
* profile. The browser never receives the private key or clear wallet seed.
|
|
15
15
|
*/
|
|
16
|
-
export declare function
|
|
16
|
+
export declare function signOrganizationTestNetworkCredential(input: SignOrganizationTestNetworkCredentialInput): Promise<VerifiableCredentialV2>;
|
|
17
|
+
/**
|
|
18
|
+
* Adds the unlocked reviewer's ML-DSA-65 assertion proof to one of the three
|
|
19
|
+
* normal domain credentials restricted to Test Network.
|
|
20
|
+
*/
|
|
21
|
+
export declare function signTestNetworkOrganizationCredential(input: SignOrganizationTestNetworkCredentialInput): Promise<VerifiableCredentialV2>;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { canonicalizeOrganizationTestNetworkCredential, } from 'gdc-common-utils-ts/utils/organization-test-network-credential';
|
|
2
|
+
import { canonicalizeTestNetworkOrganizationCredential, } from 'gdc-common-utils-ts/utils/test-network-organization-credentials';
|
|
3
|
+
/**
|
|
4
|
+
* Adds one detached JWS proof made by the already-unlocked professional
|
|
5
|
+
* profile. The browser never receives the private key or clear wallet seed.
|
|
6
|
+
*/
|
|
7
|
+
export async function signOrganizationTestNetworkCredential(input) {
|
|
8
|
+
if (!input.wallet.signDetachedJws) {
|
|
9
|
+
throw new Error('Wallet does not support detached organization authorization proofs.');
|
|
10
|
+
}
|
|
11
|
+
const verificationMethod = String(input.verificationMethod || '').trim();
|
|
12
|
+
if (!verificationMethod)
|
|
13
|
+
throw new Error('Organization authorization proof requires verificationMethod.');
|
|
14
|
+
const payload = canonicalizeOrganizationTestNetworkCredential(input.credential);
|
|
15
|
+
const jws = await input.wallet.signDetachedJws(input.context, {
|
|
16
|
+
payload,
|
|
17
|
+
header: { typ: 'application/vc+ld+json' },
|
|
18
|
+
key: input.key,
|
|
19
|
+
});
|
|
20
|
+
const existingProofs = Array.isArray(input.credential.proof)
|
|
21
|
+
? input.credential.proof
|
|
22
|
+
: input.credential.proof
|
|
23
|
+
? [input.credential.proof]
|
|
24
|
+
: [];
|
|
25
|
+
return {
|
|
26
|
+
...input.credential,
|
|
27
|
+
proof: [...existingProofs, {
|
|
28
|
+
type: 'JsonWebSignature2020',
|
|
29
|
+
created: input.createdAt || new Date().toISOString(),
|
|
30
|
+
proofPurpose: 'contractAgreement',
|
|
31
|
+
verificationMethod,
|
|
32
|
+
jws,
|
|
33
|
+
}],
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Adds the unlocked reviewer's ML-DSA-65 assertion proof to one of the three
|
|
38
|
+
* normal domain credentials restricted to Test Network.
|
|
39
|
+
*/
|
|
40
|
+
export async function signTestNetworkOrganizationCredential(input) {
|
|
41
|
+
if (!input.wallet.signDetachedJws) {
|
|
42
|
+
throw new Error('Wallet does not support detached Test Network credential proofs.');
|
|
43
|
+
}
|
|
44
|
+
const verificationMethod = String(input.verificationMethod || '').trim();
|
|
45
|
+
if (!verificationMethod)
|
|
46
|
+
throw new Error('Test Network credential proof requires verificationMethod.');
|
|
47
|
+
const jws = await input.wallet.signDetachedJws(input.context, {
|
|
48
|
+
payload: canonicalizeTestNetworkOrganizationCredential(input.credential),
|
|
49
|
+
header: { typ: 'application/vc+ld+json' },
|
|
50
|
+
key: input.key,
|
|
51
|
+
});
|
|
52
|
+
return {
|
|
53
|
+
...input.credential,
|
|
54
|
+
proof: [{
|
|
55
|
+
type: 'JsonWebSignature2020',
|
|
56
|
+
created: input.createdAt || new Date().toISOString(),
|
|
57
|
+
proofPurpose: 'assertionMethod',
|
|
58
|
+
verificationMethod,
|
|
59
|
+
jws,
|
|
60
|
+
}],
|
|
61
|
+
};
|
|
62
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type DeviceAppType } from 'gdc-common-utils-ts/constants/device';
|
|
2
2
|
import { type ClinicalSectionUpdateCommunicationInput, type ClinicalUpdateCommunicationInput, type ClinicalSummaryReadResult, type ClinicalSummaryRequestInput, type PermissionRequestCommunicationInput } from 'gdc-sdk-core-ts';
|
|
3
3
|
import type { LicenseOfferSearchState, LicenseOrderSearchState } from 'gdc-common-utils-ts/utils/license-commercial-search';
|
|
4
4
|
import type { LicenseListSearchState } from 'gdc-common-utils-ts/utils/license-list-search';
|
|
@@ -28,6 +28,18 @@ export type OrganizationEmployeeCreationInput = {
|
|
|
28
28
|
employeeClaims: Record<string, unknown>;
|
|
29
29
|
dataType?: string;
|
|
30
30
|
};
|
|
31
|
+
/** Input for reserving an existing employee seat and issuing its activation credential. */
|
|
32
|
+
export type OrganizationEmployeeLicenseInvitationInput = {
|
|
33
|
+
email: string;
|
|
34
|
+
role: string;
|
|
35
|
+
subjectDid: string;
|
|
36
|
+
type?: DeviceAppType;
|
|
37
|
+
requestThid?: string;
|
|
38
|
+
pollOptions?: {
|
|
39
|
+
timeoutMs?: number;
|
|
40
|
+
intervalMs?: number;
|
|
41
|
+
};
|
|
42
|
+
};
|
|
31
43
|
/**
|
|
32
44
|
* Current GW CORE employee lifecycle locator payload.
|
|
33
45
|
*
|
|
@@ -489,6 +501,21 @@ export declare function createOrganizationEmployeeWithDeps(routeCtx: RouteContex
|
|
|
489
501
|
intervalMs?: number;
|
|
490
502
|
}) => Promise<SubmitAndPollResult>;
|
|
491
503
|
}): Promise<SubmitAndPollResult>;
|
|
504
|
+
/**
|
|
505
|
+
* Issues the activation credential for an employee already created under the
|
|
506
|
+
* tenant. The credential belongs to that employee seat and can authorize its
|
|
507
|
+
* configured number of concurrent installations (two by default in GW CORE).
|
|
508
|
+
*/
|
|
509
|
+
export declare function issueOrganizationEmployeeLicenseWithDeps(routeCtx: RouteContext, input: OrganizationEmployeeLicenseInvitationInput, deps: {
|
|
510
|
+
identityLicenseIssuePath: (ctx: RouteContext) => string;
|
|
511
|
+
identityLicenseIssuePollPath: (ctx: RouteContext) => string;
|
|
512
|
+
submitAndPoll: (submitPath: string, pollPath: string, payload: {
|
|
513
|
+
thid?: string;
|
|
514
|
+
} & Record<string, unknown>, pollOptions?: {
|
|
515
|
+
timeoutMs?: number;
|
|
516
|
+
intervalMs?: number;
|
|
517
|
+
}) => Promise<SubmitAndPollResult>;
|
|
518
|
+
}): Promise<SubmitAndPollResult>;
|
|
492
519
|
export declare function disableOrganizationEmployeeWithDeps(routeCtx: RouteContext, input: OrganizationEmployeeLifecycleInput, options: {
|
|
493
520
|
timeoutMs?: number;
|
|
494
521
|
intervalMs?: number;
|
|
@@ -5,6 +5,7 @@ import { RelatedPersonClaim } from 'gdc-common-utils-ts/models/interoperable-cla
|
|
|
5
5
|
import { CommunicationClaim } from 'gdc-common-utils-ts/models/interoperable-claims/communication-claims';
|
|
6
6
|
import { BundleEditor, buildCommunicationParticipantSearchBundle, buildBlockchainArtifactDocumentReference, BundleQuery, createInteroperableResourceOperationEditor, IndividualOrganizationLifecycleEditor, LicenseOfferSearchEditor, LicenseOrderSearchEditor, InteroperableLifecycleStatuses, LicenseListSearchEditor, buildLicenseIssueEntry, buildLicensePurchaseEntry, } from 'gdc-common-utils-ts';
|
|
7
7
|
import { EmployeeBundleOperations, EmployeeResourceTypes, } from 'gdc-common-utils-ts/utils/employee';
|
|
8
|
+
import { DeviceAppTypes, DeviceUserClasses } from 'gdc-common-utils-ts/constants/device';
|
|
8
9
|
import { addFhirResourceToCommunication, createCommunicationResource, buildClinicalSummaryCommunicationJob, buildPermissionRequestCommunication, createClinicalSectionUpdateOutboxJob, createClinicalSummaryUpdateOutboxJob, readClinicalSummaryOperationResult, TransportProfiles, } from 'gdc-sdk-core-ts';
|
|
9
10
|
import { GwCoreLifecycleRequestMethod, GwCoreLifecycleRequestType, GwCoreLifecycleTodo, } from './constants/lifecycle.js';
|
|
10
11
|
import { buildEmployeeSearchBundle, ConsentClaims, } from 'gdc-sdk-core-ts';
|
|
@@ -58,6 +59,37 @@ export async function createOrganizationEmployeeWithDeps(routeCtx, input, option
|
|
|
58
59
|
});
|
|
59
60
|
return deps.submitAndPoll(deps.employeeBatchPath(routeCtx), deps.employeePollPath(routeCtx), payload, options);
|
|
60
61
|
}
|
|
62
|
+
/**
|
|
63
|
+
* Issues the activation credential for an employee already created under the
|
|
64
|
+
* tenant. The credential belongs to that employee seat and can authorize its
|
|
65
|
+
* configured number of concurrent installations (two by default in GW CORE).
|
|
66
|
+
*/
|
|
67
|
+
export async function issueOrganizationEmployeeLicenseWithDeps(routeCtx, input, deps) {
|
|
68
|
+
const email = String(input.email || '').trim().toLowerCase();
|
|
69
|
+
const role = String(input.role || '').trim();
|
|
70
|
+
const subjectDid = String(input.subjectDid || '').trim();
|
|
71
|
+
if (!email)
|
|
72
|
+
throw new Error('issueOrganizationEmployeeLicense: email is required.');
|
|
73
|
+
if (!role)
|
|
74
|
+
throw new Error('issueOrganizationEmployeeLicense: role is required.');
|
|
75
|
+
if (!subjectDid)
|
|
76
|
+
throw new Error('issueOrganizationEmployeeLicense: subjectDid is required.');
|
|
77
|
+
const entry = buildLicenseIssueEntry({
|
|
78
|
+
email,
|
|
79
|
+
role,
|
|
80
|
+
userClass: DeviceUserClasses.Employee,
|
|
81
|
+
type: input.type || DeviceAppTypes.Web,
|
|
82
|
+
});
|
|
83
|
+
entry.meta.subjectDid = subjectDid;
|
|
84
|
+
return deps.submitAndPoll(deps.identityLicenseIssuePath(routeCtx), deps.identityLicenseIssuePollPath(routeCtx), {
|
|
85
|
+
thid: input.requestThid || `employee-license-issue-${createRuntimeUuid()}`,
|
|
86
|
+
body: {
|
|
87
|
+
resourceType: EmployeeResourceTypes.bundle,
|
|
88
|
+
type: EmployeeResourceTypes.batch,
|
|
89
|
+
data: [entry],
|
|
90
|
+
},
|
|
91
|
+
}, input.pollOptions);
|
|
92
|
+
}
|
|
61
93
|
export async function disableOrganizationEmployeeWithDeps(routeCtx, input, options, deps) {
|
|
62
94
|
// TODO(gw-core-lifecycle-target-patch-employee-disable): switch this
|
|
63
95
|
// legacy DELETE-in-_batch flow to `_batch + PATCH` when GW CORE deploys it.
|
|
@@ -88,6 +88,10 @@ export declare class RuntimeClientPaths {
|
|
|
88
88
|
identityTokenExchangePollPath(ctx: RouteContext): string;
|
|
89
89
|
identityDeviceDcrPath(ctx: RouteContext): string;
|
|
90
90
|
identityDeviceDcrPollPath(ctx: RouteContext): string;
|
|
91
|
+
identityDeviceRevokePath(ctx: RouteContext): string;
|
|
92
|
+
identityDeviceRevokePollPath(ctx: RouteContext): string;
|
|
93
|
+
identityLicenseIssuePath(ctx: RouteContext): string;
|
|
94
|
+
identityLicenseIssuePollPath(ctx: RouteContext): string;
|
|
91
95
|
identityOpenIdSmartTokenPath(ctx: RouteContext): string;
|
|
92
96
|
identityOpenIdSmartTokenPollPath(ctx: RouteContext): string;
|
|
93
97
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Copyright 2026 Antifraud Services Inc. under the Apache License, Version 2.0.
|
|
2
2
|
import { GwCoreLifecycleAction } from './constants/lifecycle.js';
|
|
3
|
-
import { buildHostRegistryPath, buildIdentityDeviceDcrPath, buildIdentityDeviceDcrPollPath, buildIdentityOpenIdSmartTokenPath, buildIdentityOpenIdSmartTokenPollPath, buildIdentityTokenExchangePath, buildIdentityTokenExchangePollPath, buildOrganizationDidBindingPath, buildOrganizationDidBindingPollPath, buildV1Path, } from './runtime-paths.js';
|
|
3
|
+
import { buildHostRegistryPath, buildIdentityDeviceDcrPath, buildIdentityDeviceDcrPollPath, buildIdentityDeviceRevokePath, buildIdentityDeviceRevokePollPath, buildIdentityLicenseIssuePath, buildIdentityLicenseIssuePollPath, buildIdentityOpenIdSmartTokenPath, buildIdentityOpenIdSmartTokenPollPath, buildIdentityTokenExchangePath, buildIdentityTokenExchangePollPath, buildOrganizationDidBindingPath, buildOrganizationDidBindingPollPath, buildV1Path, } from './runtime-paths.js';
|
|
4
4
|
import { requireHostRouteContext, requireRouteContext, routeCtxFromInput, } from './runtime-route-context.js';
|
|
5
5
|
export class RuntimeClientPaths {
|
|
6
6
|
constructor(defaultCtx) {
|
|
@@ -102,6 +102,10 @@ export class RuntimeClientPaths {
|
|
|
102
102
|
identityTokenExchangePollPath(ctx) { return buildIdentityTokenExchangePollPath(ctx); }
|
|
103
103
|
identityDeviceDcrPath(ctx) { return buildIdentityDeviceDcrPath(ctx); }
|
|
104
104
|
identityDeviceDcrPollPath(ctx) { return buildIdentityDeviceDcrPollPath(ctx); }
|
|
105
|
+
identityDeviceRevokePath(ctx) { return buildIdentityDeviceRevokePath(ctx); }
|
|
106
|
+
identityDeviceRevokePollPath(ctx) { return buildIdentityDeviceRevokePollPath(ctx); }
|
|
107
|
+
identityLicenseIssuePath(ctx) { return buildIdentityLicenseIssuePath(ctx); }
|
|
108
|
+
identityLicenseIssuePollPath(ctx) { return buildIdentityLicenseIssuePollPath(ctx); }
|
|
105
109
|
identityOpenIdSmartTokenPath(ctx) { return buildIdentityOpenIdSmartTokenPath(ctx); }
|
|
106
110
|
identityOpenIdSmartTokenPollPath(ctx) { return buildIdentityOpenIdSmartTokenPollPath(ctx); }
|
|
107
111
|
}
|
package/dist/runtime-paths.d.ts
CHANGED
|
@@ -8,5 +8,11 @@ export declare function buildIdentityTokenExchangePath(ctx: RouteContext): strin
|
|
|
8
8
|
export declare function buildIdentityTokenExchangePollPath(ctx: RouteContext): string;
|
|
9
9
|
export declare function buildIdentityDeviceDcrPath(ctx: RouteContext): string;
|
|
10
10
|
export declare function buildIdentityDeviceDcrPollPath(ctx: RouteContext): string;
|
|
11
|
+
/** Canonical controller operation that reserves an employee seat activation credential. */
|
|
12
|
+
export declare function buildIdentityLicenseIssuePath(ctx: RouteContext): string;
|
|
13
|
+
/** Poll endpoint paired with {@link buildIdentityLicenseIssuePath}. */
|
|
14
|
+
export declare function buildIdentityLicenseIssuePollPath(ctx: RouteContext): string;
|
|
15
|
+
export declare function buildIdentityDeviceRevokePath(ctx: RouteContext): string;
|
|
16
|
+
export declare function buildIdentityDeviceRevokePollPath(ctx: RouteContext): string;
|
|
11
17
|
export declare function buildIdentityOpenIdSmartTokenPath(ctx: RouteContext): string;
|
|
12
18
|
export declare function buildIdentityOpenIdSmartTokenPollPath(ctx: RouteContext): string;
|
package/dist/runtime-paths.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// Copyright 2026 Antifraud Services Inc. under the Apache License, Version 2.0.
|
|
2
2
|
import { buildGwCoreTenantResourceActionPath } from 'gdc-common-utils-ts/utils/gw-core-path';
|
|
3
|
+
import { IdentityAuthActions, IdentityAuthRouteSegments } from 'gdc-common-utils-ts/constants/identity-auth';
|
|
3
4
|
export function buildV1Path(routeCtx, section, format, resourceType, action) {
|
|
4
5
|
return buildGwCoreTenantResourceActionPath({
|
|
5
6
|
tenantId: routeCtx.tenantId,
|
|
@@ -22,16 +23,33 @@ export function buildOrganizationDidBindingPollPath(routeCtx) {
|
|
|
22
23
|
return `/${encodeURIComponent(routeCtx.tenantId)}/cds-${encodeURIComponent(routeCtx.jurisdiction)}/v1/${encodeURIComponent(routeCtx.sector)}/did/document/_binding-response`;
|
|
23
24
|
}
|
|
24
25
|
export function buildIdentityTokenExchangePath(ctx) {
|
|
25
|
-
return
|
|
26
|
+
return buildIdentityAuthPath(ctx, IdentityAuthActions.Exchange);
|
|
26
27
|
}
|
|
27
28
|
export function buildIdentityTokenExchangePollPath(ctx) {
|
|
28
|
-
return
|
|
29
|
+
return buildIdentityAuthPath(ctx, IdentityAuthActions.ExchangeResponse);
|
|
29
30
|
}
|
|
30
31
|
export function buildIdentityDeviceDcrPath(ctx) {
|
|
31
|
-
return
|
|
32
|
+
return buildIdentityAuthPath(ctx, IdentityAuthActions.Dcr);
|
|
32
33
|
}
|
|
33
34
|
export function buildIdentityDeviceDcrPollPath(ctx) {
|
|
34
|
-
return
|
|
35
|
+
return buildIdentityAuthPath(ctx, IdentityAuthActions.DcrResponse);
|
|
36
|
+
}
|
|
37
|
+
/** Canonical controller operation that reserves an employee seat activation credential. */
|
|
38
|
+
export function buildIdentityLicenseIssuePath(ctx) {
|
|
39
|
+
return buildIdentityAuthPath(ctx, IdentityAuthActions.Issue);
|
|
40
|
+
}
|
|
41
|
+
/** Poll endpoint paired with {@link buildIdentityLicenseIssuePath}. */
|
|
42
|
+
export function buildIdentityLicenseIssuePollPath(ctx) {
|
|
43
|
+
return buildIdentityAuthPath(ctx, IdentityAuthActions.IssueResponse);
|
|
44
|
+
}
|
|
45
|
+
export function buildIdentityDeviceRevokePath(ctx) {
|
|
46
|
+
return buildIdentityAuthPath(ctx, IdentityAuthActions.Revoke);
|
|
47
|
+
}
|
|
48
|
+
export function buildIdentityDeviceRevokePollPath(ctx) {
|
|
49
|
+
return buildIdentityAuthPath(ctx, IdentityAuthActions.RevokeResponse);
|
|
50
|
+
}
|
|
51
|
+
function buildIdentityAuthPath(ctx, action) {
|
|
52
|
+
return `/${encodeURIComponent(IdentityAuthRouteSegments.Host)}/cds-${encodeURIComponent(ctx.jurisdiction)}/${IdentityAuthRouteSegments.Version}/${encodeURIComponent(ctx.sector)}/${encodeURIComponent(ctx.tenantId)}/${IdentityAuthRouteSegments.Section}/${IdentityAuthRouteSegments.Format}/${encodeURIComponent(action)}`;
|
|
35
53
|
}
|
|
36
54
|
export function buildIdentityOpenIdSmartTokenPath(ctx) {
|
|
37
55
|
return `/${encodeURIComponent(ctx.tenantId)}/cds-${encodeURIComponent(ctx.jurisdiction)}/v1/${encodeURIComponent(ctx.sector)}/identity/openid/smart/token`;
|
|
@@ -22,6 +22,8 @@ export type ServerProfileRecord = Readonly<{
|
|
|
22
22
|
routeContext: RouteContext;
|
|
23
23
|
allowedSubjectDids: string[];
|
|
24
24
|
clientId: string;
|
|
25
|
+
/** Stable non-secret id of the browser/app installation registered by DCR. */
|
|
26
|
+
clientInstanceId?: string;
|
|
25
27
|
deviceDid: string;
|
|
26
28
|
publicJwks: Record<string, unknown>[];
|
|
27
29
|
/** Public recipient key for local confidential storage; not a DCR communication key. */
|
|
@@ -67,6 +69,8 @@ export type ServerProfileEnrollmentInput = Readonly<{
|
|
|
67
69
|
pin: string;
|
|
68
70
|
idToken: string;
|
|
69
71
|
activationCode: string;
|
|
72
|
+
/** Explicit per-installation id. Older callers fall back to the first DCR key id. */
|
|
73
|
+
clientInstanceId?: string;
|
|
70
74
|
vpToken: string;
|
|
71
75
|
/** Registered web redirect URIs included in the OpenID DCR metadata. */
|
|
72
76
|
dcrRedirectUris?: string[];
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// Copyright 2026 Antifraud Services Inc. under the Apache License, Version 2.0.
|
|
2
2
|
import { randomBytes } from 'node:crypto';
|
|
3
|
+
import { IdentityDcrMetadataFields, IdentityDeviceInfoFields } from 'gdc-common-utils-ts/constants/identity-auth';
|
|
3
4
|
import { TransportProfiles, } from 'gdc-sdk-core-ts';
|
|
4
5
|
import { NodeManagedWallet } from './node-managed-wallet.js';
|
|
5
6
|
import { NodeHttpClient } from './node-runtime-client.js';
|
|
@@ -26,6 +27,11 @@ export class ServerProfileSessionManager {
|
|
|
26
27
|
const wallet = await this.createWallet(walletKeyDerivationId, seed);
|
|
27
28
|
const context = walletContext(walletKeyDerivationId);
|
|
28
29
|
const publicKeys = await wallet.getPublicJwks(context, {});
|
|
30
|
+
const clientInstanceId = String(input.clientInstanceId
|
|
31
|
+
|| publicKeys.find((entry) => entry.purpose !== 'document-at-rest')?.kid
|
|
32
|
+
|| '').trim();
|
|
33
|
+
if (!clientInstanceId)
|
|
34
|
+
throw new Error('Server profile enrollment requires clientInstanceId or a DCR public key id.');
|
|
29
35
|
const storagePublicJwk = publicKeys.find((entry) => entry.purpose === 'document-at-rest')?.publicJwk;
|
|
30
36
|
if (!storagePublicJwk)
|
|
31
37
|
throw new Error('Server profile enrollment requires a document-at-rest ML-KEM key.');
|
|
@@ -35,6 +41,9 @@ export class ServerProfileSessionManager {
|
|
|
35
41
|
activationCode: input.activationCode,
|
|
36
42
|
idToken: input.idToken,
|
|
37
43
|
dcrPayload: {
|
|
44
|
+
[IdentityDcrMetadataFields.ExtendedDeviceInfo]: {
|
|
45
|
+
[IdentityDeviceInfoFields.DeviceId]: clientInstanceId,
|
|
46
|
+
},
|
|
38
47
|
application_type: 'web',
|
|
39
48
|
...(input.dcrRedirectUris?.length ? { redirect_uris: unique(input.dcrRedirectUris) } : {}),
|
|
40
49
|
...(input.dcrClientName ? { client_name: input.dcrClientName } : {}),
|
|
@@ -61,6 +70,7 @@ export class ServerProfileSessionManager {
|
|
|
61
70
|
routeContext: input.routeContext,
|
|
62
71
|
allowedSubjectDids: unique(input.allowedSubjectDids),
|
|
63
72
|
clientId,
|
|
73
|
+
clientInstanceId,
|
|
64
74
|
deviceDid,
|
|
65
75
|
publicJwks: publicKeys.filter((entry) => entry.purpose !== 'document-at-rest').map((entry) => entry.publicJwk),
|
|
66
76
|
storagePublicJwk: storagePublicJwk,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gdc-sdk-node-ts",
|
|
3
|
-
"version": "2.4.
|
|
3
|
+
"version": "2.4.4",
|
|
4
4
|
"description": "Next-generation Node runtime package for the GDC SDK family",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "Antifraud Services Inc.",
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
"test:e2e:live-gw:clean": "bash ./scripts/run-live-gw-clean.sh"
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
|
-
"gdc-common-utils-ts": "2.5.
|
|
40
|
+
"gdc-common-utils-ts": "2.5.6",
|
|
41
41
|
"gdc-sdk-core-ts": "~2.3.18"
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import { canonicalizeOrganizationRegistrationAuthorizationCredential, } from 'gdc-common-utils-ts/utils/organization-registration-authorization';
|
|
2
|
-
/**
|
|
3
|
-
* Adds one detached JWS proof made by the already-unlocked professional
|
|
4
|
-
* profile. The browser never receives the private key or clear wallet seed.
|
|
5
|
-
*/
|
|
6
|
-
export async function signOrganizationRegistrationAuthorizationCredential(input) {
|
|
7
|
-
if (!input.wallet.signDetachedJws) {
|
|
8
|
-
throw new Error('Wallet does not support detached organization authorization proofs.');
|
|
9
|
-
}
|
|
10
|
-
const verificationMethod = String(input.verificationMethod || '').trim();
|
|
11
|
-
if (!verificationMethod)
|
|
12
|
-
throw new Error('Organization authorization proof requires verificationMethod.');
|
|
13
|
-
const payload = canonicalizeOrganizationRegistrationAuthorizationCredential(input.credential);
|
|
14
|
-
const jws = await input.wallet.signDetachedJws(input.context, {
|
|
15
|
-
payload,
|
|
16
|
-
header: { typ: 'application/vc+ld+json' },
|
|
17
|
-
key: input.key,
|
|
18
|
-
});
|
|
19
|
-
const existingProofs = Array.isArray(input.credential.proof)
|
|
20
|
-
? input.credential.proof
|
|
21
|
-
: input.credential.proof
|
|
22
|
-
? [input.credential.proof]
|
|
23
|
-
: [];
|
|
24
|
-
return {
|
|
25
|
-
...input.credential,
|
|
26
|
-
proof: [...existingProofs, {
|
|
27
|
-
type: 'JsonWebSignature2020',
|
|
28
|
-
created: input.createdAt || new Date().toISOString(),
|
|
29
|
-
proofPurpose: 'contractAgreement',
|
|
30
|
-
verificationMethod,
|
|
31
|
-
jws,
|
|
32
|
-
}],
|
|
33
|
-
};
|
|
34
|
-
}
|