gdc-sdk-node-ts 2.4.24 → 2.4.31
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 +15 -6
- package/dist/constants/lifecycle.d.ts +8 -0
- package/dist/constants/lifecycle.js +8 -0
- package/dist/device-activation.d.ts +48 -1
- package/dist/device-activation.js +157 -1
- package/dist/digital-twin.d.ts +12 -0
- package/dist/digital-twin.js +26 -4
- package/dist/host-onboarding.d.ts +7 -0
- package/dist/node-managed-wallet.d.ts +41 -1
- package/dist/node-managed-wallet.js +52 -0
- package/dist/node-runtime-client.d.ts +29 -1
- package/dist/node-runtime-client.js +92 -1
- package/dist/orchestration/client-port.d.ts +11 -1
- package/dist/orchestration/digital-twin-sdk.js +3 -1
- package/dist/orchestration/host-onboarding-sdk.d.ts +9 -3
- package/dist/orchestration/host-onboarding-sdk.js +10 -1
- package/dist/orchestration/individual-controller-sdk.d.ts +29 -3
- package/dist/orchestration/individual-controller-sdk.js +48 -2
- package/dist/orchestration/organization-controller-sdk.d.ts +19 -6
- package/dist/orchestration/organization-controller-sdk.js +27 -6
- package/dist/organization-controller-recovery.d.ts +4 -2
- package/dist/organization-controller-recovery.js +14 -8
- package/dist/organization-employee-lifecycle.d.ts +4 -0
- package/dist/organization-employee-lifecycle.js +17 -1
- package/dist/organization-license-order.d.ts +8 -3
- package/dist/resource-operations.d.ts +67 -0
- package/dist/resource-operations.js +62 -1
- package/dist/runtime-client-paths.d.ts +10 -0
- package/dist/runtime-client-paths.js +10 -0
- package/dist/server-profile-session.d.ts +32 -3
- package/dist/server-profile-session.js +21 -17
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -238,6 +238,11 @@ Current runtime boundary:
|
|
|
238
238
|
- `OrganizationControllerSdk.confirmOrganizationLicenseOrder(...)` now uses the
|
|
239
239
|
public host `Order/_batch` route used by GW CORE for portal-managed
|
|
240
240
|
post-payment seat activation
|
|
241
|
+
- that route is commercial routing only: `iss` remains the exact controller DID
|
|
242
|
+
registered by tenant DCR, `aud` remains the tenant id, and GW resolves its
|
|
243
|
+
JWS/JWE key identifiers from the tenant rather than the host
|
|
244
|
+
- applications use the high-level SDK method and configured transport profile;
|
|
245
|
+
they do not populate `meta.jws`, move public keys, or construct DIDComm by hand
|
|
241
246
|
- the long root lifecycle is still not fully closed because the suite does not
|
|
242
247
|
yet orchestrate the whole `license list -> pay -> confirm -> relist -> two
|
|
243
248
|
employees -> selective purge -> cleanup` dialogue as one single test
|
|
@@ -640,8 +645,8 @@ modules below.
|
|
|
640
645
|
- types: `SmartTokenRequestInput`, `SmartTokenExchangeResult`
|
|
641
646
|
- function: `requestSmartTokenWithDeps(...)`
|
|
642
647
|
- [`src/resource-operations.ts`](src/resource-operations.ts)
|
|
643
|
-
- types: `OrganizationEmployeeCreationInput`, `IpsOrFhirImportInput`, `RelatedPersonUpsertInput`, `CommunicationIngestionInput`, `ClinicalDateRange`, `ClinicalBundleSearchInput`, `ConsentActorTargetInput`, `GrantProfessionalAccessInput`, `GrantProfessionalAccessResult`, `
|
|
644
|
-
- functions: `createOrganizationEmployeeWithDeps(...)`, `importIpsOrFhirAndUpdateIndexWithDeps(...)`, `upsertRelatedPersonAndPollWithDeps(...)`, `ingestCommunicationAndUpdateIndexWithDeps(...)`, `searchClinicalBundleWithDeps(...)`, `searchLatestIpsWithDeps(...)`, `grantProfessionalAccessWithDeps(...)`, `
|
|
648
|
+
- types: `OrganizationEmployeeCreationInput`, `IpsOrFhirImportInput`, `RelatedPersonUpsertInput`, `CommunicationIngestionInput`, `ClinicalDateRange`, `ClinicalBundleSearchInput`, `ConsentActorTargetInput`, `GrantProfessionalAccessInput`, `GrantProfessionalAccessResult`, `DigitalTwinSecondaryUseConsentInput`, `DigitalTwinSubjectLinkPurgeInput`
|
|
649
|
+
- functions: `createOrganizationEmployeeWithDeps(...)`, `importIpsOrFhirAndUpdateIndexWithDeps(...)`, `upsertRelatedPersonAndPollWithDeps(...)`, `ingestCommunicationAndUpdateIndexWithDeps(...)`, `searchClinicalBundleWithDeps(...)`, `searchLatestIpsWithDeps(...)`, `grantProfessionalAccessWithDeps(...)`, `setDigitalTwinSecondaryUseConsentWithDeps(...)`, `purgeDigitalTwinSubjectLinkWithDeps(...)`
|
|
645
650
|
- [`src/digital-twin.ts`](src/digital-twin.ts)
|
|
646
651
|
- types: `DigitalTwinSearchInput`, `DigitalTwinSelectionInput`, `DigitalTwinResearchTag`, `DigitalTwinMaterializationInput`
|
|
647
652
|
- functions: `searchDigitalTwinsWithDeps(...)`, `saveDigitalTwinSelectionWithDeps(...)`, `materializeDigitalTwinWithDeps(...)`
|
|
@@ -791,10 +796,14 @@ Live E2E legal PDF source:
|
|
|
791
796
|
Recovery-specific live rule:
|
|
792
797
|
|
|
793
798
|
- `Organization/_issue` can succeed and still be followed by `_exchange` failure
|
|
794
|
-
if the controller `id_token` is not
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
799
|
+
if the controller `id_token` is invalid, expired or does not prove the
|
|
800
|
+
expected actor/contact
|
|
801
|
+
- the current GW `_exchange` path expects a valid IdP token but takes tenant
|
|
802
|
+
authority from the already validated request route
|
|
803
|
+
- a custom `tenant_id` claim is optional; when present it must match the route
|
|
804
|
+
and cannot select another tenant
|
|
805
|
+
- a failed poll `OperationOutcome` is surfaced before the helper checks for
|
|
806
|
+
`initial_access_token`, preserving the real GW diagnostic
|
|
798
807
|
- the bundled recovery runner generates a syntactically valid demo JWT if
|
|
799
808
|
`CONTROLLER_ID_TOKEN` is not provided, but production/staging should use a
|
|
800
809
|
real IdP-issued token
|
|
@@ -16,7 +16,11 @@ export declare const GwCoreLifecycleAction: Readonly<{
|
|
|
16
16
|
readonly Transaction: "_transaction";
|
|
17
17
|
readonly TransactionResponse: "_transaction-response";
|
|
18
18
|
readonly Disable: "_disable";
|
|
19
|
+
readonly Enable: "_enable";
|
|
19
20
|
readonly Purge: "_purge";
|
|
21
|
+
readonly Status: "_status";
|
|
22
|
+
readonly DisableDescendants: "_disable-descendants";
|
|
23
|
+
readonly PurgeDescendants: "_purge-descendants";
|
|
20
24
|
}>;
|
|
21
25
|
/**
|
|
22
26
|
* Entry request methods currently used by GW CORE lifecycle handlers.
|
|
@@ -36,6 +40,10 @@ export declare const GwCoreLifecycleRequestType: Readonly<{
|
|
|
36
40
|
readonly IndividualOrganizationDisable: "Family-disable-request-v1.0";
|
|
37
41
|
readonly IndividualOrganizationPurge: "Family-purge-request-v1.0";
|
|
38
42
|
readonly IndividualMemberPurge: "RelatedPerson-purge-request-v1.0";
|
|
43
|
+
readonly TenantStatus: "Organization-lifecycle-status-request-v1.0";
|
|
44
|
+
readonly TenantEnable: "Organization-enable-request-v1.0";
|
|
45
|
+
readonly TenantDisableDescendants: "Organization-disable-descendants-request-v1.0";
|
|
46
|
+
readonly TenantPurgeDescendants: "Organization-purge-descendants-request-v1.0";
|
|
39
47
|
}>;
|
|
40
48
|
/**
|
|
41
49
|
* Named TODO ids kept close to the current lifecycle implementation so the
|
|
@@ -18,7 +18,11 @@ export const GwCoreLifecycleAction = Object.freeze({
|
|
|
18
18
|
Transaction: '_transaction',
|
|
19
19
|
TransactionResponse: '_transaction-response',
|
|
20
20
|
Disable: '_disable',
|
|
21
|
+
Enable: '_enable',
|
|
21
22
|
Purge: '_purge',
|
|
23
|
+
Status: '_status',
|
|
24
|
+
DisableDescendants: '_disable-descendants',
|
|
25
|
+
PurgeDescendants: '_purge-descendants',
|
|
22
26
|
});
|
|
23
27
|
/**
|
|
24
28
|
* Entry request methods currently used by GW CORE lifecycle handlers.
|
|
@@ -38,6 +42,10 @@ export const GwCoreLifecycleRequestType = Object.freeze({
|
|
|
38
42
|
IndividualOrganizationDisable: 'Family-disable-request-v1.0',
|
|
39
43
|
IndividualOrganizationPurge: 'Family-purge-request-v1.0',
|
|
40
44
|
IndividualMemberPurge: LifecycleRequestType.RelatedPersonPurge,
|
|
45
|
+
TenantStatus: 'Organization-lifecycle-status-request-v1.0',
|
|
46
|
+
TenantEnable: 'Organization-enable-request-v1.0',
|
|
47
|
+
TenantDisableDescendants: 'Organization-disable-descendants-request-v1.0',
|
|
48
|
+
TenantPurgeDescendants: 'Organization-purge-descendants-request-v1.0',
|
|
41
49
|
});
|
|
42
50
|
/**
|
|
43
51
|
* Named TODO ids kept close to the current lifecycle implementation so the
|
|
@@ -12,10 +12,57 @@ export type EmployeeDeviceActivationRequestInput = {
|
|
|
12
12
|
sector?: string;
|
|
13
13
|
activationCode: string;
|
|
14
14
|
idToken: string;
|
|
15
|
-
|
|
15
|
+
/** Canonical high-level description converted to OpenID DCR metadata by the SDK. */
|
|
16
|
+
deviceRegistration?: ProfileDeviceRegistrationInput;
|
|
17
|
+
/**
|
|
18
|
+
* @deprecated Low-level OpenID escape hatch. Use
|
|
19
|
+
* `createProfileDeviceActivationRequest(...).set...build()` instead.
|
|
20
|
+
*/
|
|
21
|
+
dcrPayload?: Record<string, unknown>;
|
|
16
22
|
timeoutSeconds?: number;
|
|
17
23
|
intervalSeconds?: number;
|
|
18
24
|
};
|
|
25
|
+
/** Application concepts required to bind one portal/app installation. */
|
|
26
|
+
export type ProfileDeviceRegistrationInput = Readonly<{
|
|
27
|
+
clientInstanceId: string;
|
|
28
|
+
clientName: string;
|
|
29
|
+
applicationType: 'native' | 'web';
|
|
30
|
+
redirectUris: readonly string[];
|
|
31
|
+
publicJwks: readonly Record<string, unknown>[];
|
|
32
|
+
deviceName?: string;
|
|
33
|
+
actorDid?: string;
|
|
34
|
+
profileDid?: string;
|
|
35
|
+
}>;
|
|
36
|
+
/** Advanced typed editor used by SDK runtimes that already own profile keys. */
|
|
37
|
+
export interface ProfileDeviceActivationDraft {
|
|
38
|
+
setClientInstanceId(value: string): ProfileDeviceActivationDraft;
|
|
39
|
+
setClientName(value: string): ProfileDeviceActivationDraft;
|
|
40
|
+
setApplicationType(value: 'native' | 'web'): ProfileDeviceActivationDraft;
|
|
41
|
+
setRedirectUris(values: readonly string[]): ProfileDeviceActivationDraft;
|
|
42
|
+
setPublicJwks(values: readonly Record<string, unknown>[]): ProfileDeviceActivationDraft;
|
|
43
|
+
setDeviceName(value: string): ProfileDeviceActivationDraft;
|
|
44
|
+
setActorDid(value: string): ProfileDeviceActivationDraft;
|
|
45
|
+
setProfileDid(value: string): ProfileDeviceActivationDraft;
|
|
46
|
+
setTimeoutSeconds(value: number): ProfileDeviceActivationDraft;
|
|
47
|
+
setIntervalSeconds(value: number): ProfileDeviceActivationDraft;
|
|
48
|
+
build(): EmployeeDeviceActivationRequestInput & {
|
|
49
|
+
deviceRegistration: ProfileDeviceRegistrationInput;
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Starts an advanced profile-device activation request.
|
|
54
|
+
*
|
|
55
|
+
* Product portals should normally use `ServerProfileSessionManager.enroll`,
|
|
56
|
+
* which provisions the wallet and calls this editor internally. This surface
|
|
57
|
+
* exists for runtimes that already own and select the profile public keys.
|
|
58
|
+
*/
|
|
59
|
+
export declare function createProfileDeviceActivationRequest(input: Readonly<{
|
|
60
|
+
activationCode: string;
|
|
61
|
+
idToken: string;
|
|
62
|
+
tenantId?: string;
|
|
63
|
+
jurisdiction?: string;
|
|
64
|
+
sector?: string;
|
|
65
|
+
}>): ProfileDeviceActivationDraft;
|
|
19
66
|
export type EmployeeDeviceActivationResult = {
|
|
20
67
|
initialAccessToken: string;
|
|
21
68
|
exchange: SubmitAndPollResult;
|
|
@@ -2,6 +2,60 @@
|
|
|
2
2
|
import { resolvePollOptionsFromSeconds } from './poll-options.js';
|
|
3
3
|
import { IdentityAuthRequestFields, IdentityAuthResponseFields, IdentityDcrMetadataFields, IdentityDeviceInfoFields, } from 'gdc-common-utils-ts/constants/identity-auth';
|
|
4
4
|
import { buildEmployeeDeviceRevocationBody } from 'gdc-common-utils-ts/utils/organization-employee-lifecycle';
|
|
5
|
+
/**
|
|
6
|
+
* Starts an advanced profile-device activation request.
|
|
7
|
+
*
|
|
8
|
+
* Product portals should normally use `ServerProfileSessionManager.enroll`,
|
|
9
|
+
* which provisions the wallet and calls this editor internally. This surface
|
|
10
|
+
* exists for runtimes that already own and select the profile public keys.
|
|
11
|
+
*/
|
|
12
|
+
export function createProfileDeviceActivationRequest(input) {
|
|
13
|
+
const activationCode = requiredText(input.activationCode, 'activation code');
|
|
14
|
+
const idToken = requiredText(input.idToken, 'signed identity token');
|
|
15
|
+
let clientInstanceId = '';
|
|
16
|
+
let clientName = '';
|
|
17
|
+
let applicationType;
|
|
18
|
+
let redirectUris = [];
|
|
19
|
+
let publicJwks = [];
|
|
20
|
+
let deviceName = '';
|
|
21
|
+
let actorDid = '';
|
|
22
|
+
let profileDid = '';
|
|
23
|
+
let timeoutSeconds;
|
|
24
|
+
let intervalSeconds;
|
|
25
|
+
const draft = {
|
|
26
|
+
setClientInstanceId(value) { clientInstanceId = normalizedText(value); return draft; },
|
|
27
|
+
setClientName(value) { clientName = normalizedText(value); return draft; },
|
|
28
|
+
setApplicationType(value) { applicationType = value; return draft; },
|
|
29
|
+
setRedirectUris(values) { redirectUris = uniqueText(values); return draft; },
|
|
30
|
+
setPublicJwks(values) { publicJwks = values.map((value) => ({ ...value })); return draft; },
|
|
31
|
+
setDeviceName(value) { deviceName = normalizedText(value); return draft; },
|
|
32
|
+
setActorDid(value) { actorDid = normalizedText(value); return draft; },
|
|
33
|
+
setProfileDid(value) { profileDid = normalizedText(value); return draft; },
|
|
34
|
+
setTimeoutSeconds(value) { timeoutSeconds = positiveNumber(value, 'timeout seconds'); return draft; },
|
|
35
|
+
setIntervalSeconds(value) { intervalSeconds = positiveNumber(value, 'interval seconds'); return draft; },
|
|
36
|
+
build() {
|
|
37
|
+
const registration = {
|
|
38
|
+
clientInstanceId: requiredText(clientInstanceId, 'client instance id'),
|
|
39
|
+
clientName: requiredText(clientName, 'client name'),
|
|
40
|
+
applicationType: applicationType || failRequired('application type'),
|
|
41
|
+
redirectUris: requiredList(redirectUris, 'redirect URI'),
|
|
42
|
+
publicJwks: requiredList(publicJwks, 'public JWK'),
|
|
43
|
+
...(deviceName ? { deviceName } : {}),
|
|
44
|
+
...(actorDid ? { actorDid } : {}),
|
|
45
|
+
...(profileDid ? { profileDid } : {}),
|
|
46
|
+
};
|
|
47
|
+
return {
|
|
48
|
+
...input,
|
|
49
|
+
activationCode,
|
|
50
|
+
idToken,
|
|
51
|
+
deviceRegistration: registration,
|
|
52
|
+
...(timeoutSeconds !== undefined ? { timeoutSeconds } : {}),
|
|
53
|
+
...(intervalSeconds !== undefined ? { intervalSeconds } : {}),
|
|
54
|
+
};
|
|
55
|
+
},
|
|
56
|
+
};
|
|
57
|
+
return draft;
|
|
58
|
+
}
|
|
5
59
|
export async function revokeEmployeeDeviceWithDeps(deps) {
|
|
6
60
|
const licenseId = String(deps.input.licenseId || '').trim();
|
|
7
61
|
const clientId = String(deps.input.clientId || '').trim();
|
|
@@ -28,6 +82,16 @@ export async function activateEmployeeDeviceWithActivationCodeWithDeps(deps) {
|
|
|
28
82
|
[IdentityAuthRequestFields.ClientInstanceId]: clientInstanceId,
|
|
29
83
|
};
|
|
30
84
|
const exchange = await deps.submitAndPollWithBearerToken(deps.input.idToken, deps.identityTokenExchangePath(deps.routeCtx), deps.identityTokenExchangePollPath(deps.routeCtx), exchangePayload, deps.input.pollOptions);
|
|
85
|
+
const exchangeDiagnostics = firstFailedOperationOutcomeDiagnostic(exchange.poll.body)
|
|
86
|
+
|| firstFailedOperationOutcomeDiagnostic(exchange.submit.body);
|
|
87
|
+
if (exchangeDiagnostics) {
|
|
88
|
+
throw new Error(`activateEmployeeDeviceWithActivationCode: exchange failed: ${exchangeDiagnostics}`);
|
|
89
|
+
}
|
|
90
|
+
const failedExchangeStatus = [exchange.submit.status, exchange.poll.status]
|
|
91
|
+
.find((status) => status < 200 || status >= 300);
|
|
92
|
+
if (failedExchangeStatus !== undefined) {
|
|
93
|
+
throw new Error(`activateEmployeeDeviceWithActivationCode: exchange failed (HTTP ${failedExchangeStatus}).`);
|
|
94
|
+
}
|
|
31
95
|
const pollBody = exchange.poll.body || {};
|
|
32
96
|
const exchangeBody = (pollBody.body || pollBody);
|
|
33
97
|
const initialAccessToken = String(exchangeBody[IdentityAuthResponseFields.InitialAccessToken]
|
|
@@ -56,10 +120,58 @@ export async function activateEmployeeDeviceWithActivationRequestWithDeps(deps)
|
|
|
56
120
|
return deps.activateEmployeeDeviceWithActivationCode(deps.routeCtx, {
|
|
57
121
|
activationCode: deps.input.activationCode,
|
|
58
122
|
idToken: deps.input.idToken,
|
|
59
|
-
dcrPayload: deps.input
|
|
123
|
+
dcrPayload: resolveDcrPayload(deps.input),
|
|
60
124
|
pollOptions,
|
|
61
125
|
});
|
|
62
126
|
}
|
|
127
|
+
function resolveDcrPayload(input) {
|
|
128
|
+
if (input.deviceRegistration && input.dcrPayload) {
|
|
129
|
+
throw new Error('Device activation accepts either deviceRegistration or the deprecated dcrPayload, not both.');
|
|
130
|
+
}
|
|
131
|
+
if (input.deviceRegistration) {
|
|
132
|
+
const registration = input.deviceRegistration;
|
|
133
|
+
return {
|
|
134
|
+
[IdentityDcrMetadataFields.ApplicationType]: registration.applicationType,
|
|
135
|
+
[IdentityDcrMetadataFields.ClientName]: registration.clientName,
|
|
136
|
+
[IdentityDcrMetadataFields.RedirectUris]: [...registration.redirectUris],
|
|
137
|
+
[IdentityDcrMetadataFields.Jwks]: { keys: registration.publicJwks.map((value) => ({ ...value })) },
|
|
138
|
+
[IdentityDcrMetadataFields.ExtendedDeviceInfo]: {
|
|
139
|
+
[IdentityDeviceInfoFields.DeviceId]: registration.clientInstanceId,
|
|
140
|
+
device_name: registration.deviceName || registration.clientName,
|
|
141
|
+
},
|
|
142
|
+
...(registration.actorDid ? { [IdentityDcrMetadataFields.ActorDid]: registration.actorDid } : {}),
|
|
143
|
+
...(registration.profileDid ? { [IdentityDcrMetadataFields.ProfileDid]: registration.profileDid } : {}),
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
if (input.dcrPayload)
|
|
147
|
+
return { ...input.dcrPayload };
|
|
148
|
+
throw new Error('Device activation requires a device registration built by createProfileDeviceActivationRequest.');
|
|
149
|
+
}
|
|
150
|
+
function normalizedText(value) {
|
|
151
|
+
return typeof value === 'string' ? value.trim() : '';
|
|
152
|
+
}
|
|
153
|
+
function requiredText(value, label) {
|
|
154
|
+
const normalized = normalizedText(value);
|
|
155
|
+
if (!normalized)
|
|
156
|
+
throw new Error(`Profile device activation requires ${label}.`);
|
|
157
|
+
return normalized;
|
|
158
|
+
}
|
|
159
|
+
function uniqueText(values) {
|
|
160
|
+
return [...new Set((values || []).map((value) => normalizedText(value)).filter(Boolean))];
|
|
161
|
+
}
|
|
162
|
+
function requiredList(values, label) {
|
|
163
|
+
if (!values.length)
|
|
164
|
+
throw new Error(`Profile device activation requires at least one ${label}.`);
|
|
165
|
+
return [...values];
|
|
166
|
+
}
|
|
167
|
+
function positiveNumber(value, label) {
|
|
168
|
+
if (!Number.isFinite(value) || value <= 0)
|
|
169
|
+
throw new Error(`Profile device activation ${label} must be positive.`);
|
|
170
|
+
return value;
|
|
171
|
+
}
|
|
172
|
+
function failRequired(label) {
|
|
173
|
+
throw new Error(`Profile device activation requires ${label}.`);
|
|
174
|
+
}
|
|
63
175
|
function createRuntimeUuid() {
|
|
64
176
|
const fromCrypto = globalThis.crypto?.randomUUID?.();
|
|
65
177
|
if (fromCrypto) {
|
|
@@ -67,3 +179,47 @@ function createRuntimeUuid() {
|
|
|
67
179
|
}
|
|
68
180
|
return `fallback-${Date.now()}-${Math.random().toString(16).slice(2)}`;
|
|
69
181
|
}
|
|
182
|
+
/** Preserves a terminal async GW diagnostic before checking success fields. */
|
|
183
|
+
function firstFailedOperationOutcomeDiagnostic(value) {
|
|
184
|
+
if (typeof value === 'string') {
|
|
185
|
+
const candidate = value.trim();
|
|
186
|
+
if (!candidate || (candidate[0] !== '{' && candidate[0] !== '['))
|
|
187
|
+
return undefined;
|
|
188
|
+
try {
|
|
189
|
+
return firstFailedOperationOutcomeDiagnostic(JSON.parse(candidate));
|
|
190
|
+
}
|
|
191
|
+
catch {
|
|
192
|
+
return undefined;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
if (!value || typeof value !== 'object')
|
|
196
|
+
return undefined;
|
|
197
|
+
if (Array.isArray(value)) {
|
|
198
|
+
for (const child of value) {
|
|
199
|
+
const diagnostic = firstFailedOperationOutcomeDiagnostic(child);
|
|
200
|
+
if (diagnostic)
|
|
201
|
+
return diagnostic;
|
|
202
|
+
}
|
|
203
|
+
return undefined;
|
|
204
|
+
}
|
|
205
|
+
const record = value;
|
|
206
|
+
if (record.resourceType === 'OperationOutcome' && Array.isArray(record.issue)) {
|
|
207
|
+
for (const rawIssue of record.issue) {
|
|
208
|
+
if (!rawIssue || typeof rawIssue !== 'object')
|
|
209
|
+
continue;
|
|
210
|
+
const issue = rawIssue;
|
|
211
|
+
const severity = String(issue.severity || '').trim().toLowerCase();
|
|
212
|
+
if (severity !== 'error' && severity !== 'fatal')
|
|
213
|
+
continue;
|
|
214
|
+
const diagnostic = String(issue.diagnostics || '').trim();
|
|
215
|
+
if (diagnostic)
|
|
216
|
+
return diagnostic;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
for (const child of Object.values(record)) {
|
|
220
|
+
const diagnostic = firstFailedOperationOutcomeDiagnostic(child);
|
|
221
|
+
if (diagnostic)
|
|
222
|
+
return diagnostic;
|
|
223
|
+
}
|
|
224
|
+
return undefined;
|
|
225
|
+
}
|
package/dist/digital-twin.d.ts
CHANGED
|
@@ -3,6 +3,18 @@ import type { MetaTagCoding } from 'gdc-common-utils-ts/models/confidential-stor
|
|
|
3
3
|
import type { RouteContext } from './individual-onboarding.js';
|
|
4
4
|
import type { PollOptions, SubmitAndPollResult } from './orchestration/client-port.js';
|
|
5
5
|
export type DigitalTwinFhirFormat = 'org.hl7.fhir.r4' | 'org.hl7.fhir.api';
|
|
6
|
+
/**
|
|
7
|
+
* Creates the opaque FHIR identifier for the provider-level secondary-use
|
|
8
|
+
* Consent. Call this exactly once when the server creates the subject's index
|
|
9
|
+
* enrollment, persist the result there, and reuse it for every permit/deny.
|
|
10
|
+
* It is intentionally random and must not be derived from a subject or tenant
|
|
11
|
+
* identifier.
|
|
12
|
+
*/
|
|
13
|
+
export declare function createDigitalTwinSecondaryUseConsentIdentifier(): string;
|
|
14
|
+
/** Returns whether a value can be used as a pseudonymous digital-twin subject. */
|
|
15
|
+
export declare function isDigitalTwinSubjectId(value: unknown): value is string;
|
|
16
|
+
/** Rejects operational DIDs and malformed or caller-invented subject shapes. */
|
|
17
|
+
export declare function assertDigitalTwinSubjectId(value: unknown): asserts value is string;
|
|
6
18
|
/** Search parameters added by the digital-twin Composition profile. */
|
|
7
19
|
export declare const DigitalTwinSearchParameter: Readonly<{
|
|
8
20
|
Section: "section";
|
package/dist/digital-twin.js
CHANGED
|
@@ -2,6 +2,27 @@
|
|
|
2
2
|
import { randomUUID } from 'node:crypto';
|
|
3
3
|
import { HealthcareDocumentTypes } from 'gdc-common-utils-ts/constants';
|
|
4
4
|
import { CompositionClaim } from 'gdc-common-utils-ts/models';
|
|
5
|
+
const DIGITAL_TWIN_SUBJECT_URN_UUID = /^urn:uuid:[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
6
|
+
/**
|
|
7
|
+
* Creates the opaque FHIR identifier for the provider-level secondary-use
|
|
8
|
+
* Consent. Call this exactly once when the server creates the subject's index
|
|
9
|
+
* enrollment, persist the result there, and reuse it for every permit/deny.
|
|
10
|
+
* It is intentionally random and must not be derived from a subject or tenant
|
|
11
|
+
* identifier.
|
|
12
|
+
*/
|
|
13
|
+
export function createDigitalTwinSecondaryUseConsentIdentifier() {
|
|
14
|
+
return `urn:uuid:${randomUUID()}`;
|
|
15
|
+
}
|
|
16
|
+
/** Returns whether a value can be used as a pseudonymous digital-twin subject. */
|
|
17
|
+
export function isDigitalTwinSubjectId(value) {
|
|
18
|
+
return DIGITAL_TWIN_SUBJECT_URN_UUID.test(String(value || '').trim());
|
|
19
|
+
}
|
|
20
|
+
/** Rejects operational DIDs and malformed or caller-invented subject shapes. */
|
|
21
|
+
export function assertDigitalTwinSubjectId(value) {
|
|
22
|
+
if (!isDigitalTwinSubjectId(value)) {
|
|
23
|
+
throw new Error('Digital twin subject must be a valid urn:uuid identifier.');
|
|
24
|
+
}
|
|
25
|
+
}
|
|
5
26
|
/** Search parameters added by the digital-twin Composition profile. */
|
|
6
27
|
export const DigitalTwinSearchParameter = Object.freeze({
|
|
7
28
|
Section: 'section',
|
|
@@ -61,6 +82,9 @@ export function readDigitalTwinSearchResult(operation) {
|
|
|
61
82
|
throw new Error('Digital twin search did not return a Composition result set.');
|
|
62
83
|
}
|
|
63
84
|
const matches = responseEntry.resource.data;
|
|
85
|
+
for (const match of matches) {
|
|
86
|
+
assertDigitalTwinSubjectId(match?.[CompositionClaim.Subject]);
|
|
87
|
+
}
|
|
64
88
|
const parsedTotal = Number(responseEntry.resource.total);
|
|
65
89
|
return {
|
|
66
90
|
total: Number.isFinite(parsedTotal) ? parsedTotal : matches.length,
|
|
@@ -73,8 +97,7 @@ export async function saveDigitalTwinSelectionWithDeps(ctx, input, deps) {
|
|
|
73
97
|
const twinSubjectId = String(input.twinSubjectId || '').trim();
|
|
74
98
|
const section = String(input.section || '').trim();
|
|
75
99
|
const authorDid = String(input.authorDid || '').trim();
|
|
76
|
-
|
|
77
|
-
throw new Error('twinSubjectId is required.');
|
|
100
|
+
assertDigitalTwinSubjectId(twinSubjectId);
|
|
78
101
|
if (!section)
|
|
79
102
|
throw new Error('Digital twin selection section is required.');
|
|
80
103
|
if (!authorDid)
|
|
@@ -146,8 +169,7 @@ export async function searchDigitalTwinsWithDeps(ctx, input, deps) {
|
|
|
146
169
|
/** Materializes one selected pseudonymous twin as a research summary Bundle. */
|
|
147
170
|
export async function materializeDigitalTwinWithDeps(ctx, input, deps) {
|
|
148
171
|
const twinSubjectId = String(input.twinSubjectId || '').trim();
|
|
149
|
-
|
|
150
|
-
throw new Error('twinSubjectId is required.');
|
|
172
|
+
assertDigitalTwinSubjectId(twinSubjectId);
|
|
151
173
|
const format = input.format || 'org.hl7.fhir.r4';
|
|
152
174
|
const thid = String(input.thid || randomUUID());
|
|
153
175
|
const parameters = [
|
|
@@ -7,3 +7,10 @@
|
|
|
7
7
|
*/
|
|
8
8
|
export { confirmLegalOrganizationOrderWithDeps, HostLifecycleRequestType, HostedTenantLifecycleRequestType, submitHostedTenantLifecycleWithDeps, } from 'gdc-sdk-core-ts';
|
|
9
9
|
export type { HostingControllerFacade, HostLifecycleInput, HostRouteContext, HostedTenantLifecycleInput, LegalOrganizationOrderInput, } from 'gdc-sdk-core-ts';
|
|
10
|
+
/** Descendant groups that a controller can clean explicitly before tenant shutdown. */
|
|
11
|
+
/**
|
|
12
|
+
* Tenant-owned subject group supported by the generic cleanup endpoint.
|
|
13
|
+
* Employees use their dedicated encrypted lifecycle so license release and
|
|
14
|
+
* audit metadata cannot be bypassed.
|
|
15
|
+
*/
|
|
16
|
+
export type HostedTenantDescendantKind = 'individuals';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { CryptographyService } from 'gdc-common-utils-ts/CryptographyService';
|
|
2
2
|
import type { ICryptoHelper } from 'gdc-common-utils-ts/interfaces/ICryptoHelper';
|
|
3
|
-
import type { IWallet, WalletAlgorithm, WalletCompactJweRequest, WalletCompactJwsRequest, WalletDetachedJwsRequest, WalletExecutionContext, WalletKeyDescriptor, WalletKeyPurpose, WalletKeySelection, WalletPackOptions, WalletProvisionRequest, WalletUnpackOptions } from 'gdc-sdk-core-ts';
|
|
3
|
+
import type { IWallet, WalletAlgorithm, WalletCompactJweRequest, WalletCompactJwsRequest, WalletDetachedJwsRequest, WalletExecutionContext, WalletKeyDescriptor, WalletKeyPurpose, WalletKeySelection, WalletPackOptions, WalletProvisionMode, WalletProvisionRequest, WalletUnpackOptions } from 'gdc-sdk-core-ts';
|
|
4
4
|
import type { JWK, JwkSet } from 'gdc-common-utils-ts/models/jwk';
|
|
5
5
|
export type NodeManagedWalletPolicy = {
|
|
6
6
|
defaults: Partial<Record<WalletKeyPurpose, WalletAlgorithm>>;
|
|
@@ -11,6 +11,20 @@ export type NodeManagedWalletOptions = {
|
|
|
11
11
|
resolveRecipientJwk?: (recipientDid: string) => Promise<JWK>;
|
|
12
12
|
policy?: Partial<NodeManagedWalletPolicy>;
|
|
13
13
|
};
|
|
14
|
+
export type NodeCommunicationWalletInitialization = {
|
|
15
|
+
/**
|
|
16
|
+
* Stable secret used to reconstruct the same communication keys after a
|
|
17
|
+
* process restart. Persist it only through the portal's protected wallet
|
|
18
|
+
* store; never send it to ICA or GW.
|
|
19
|
+
*/
|
|
20
|
+
seedMaterial?: string | Uint8Array;
|
|
21
|
+
/**
|
|
22
|
+
* Defaults to deterministic when seedMaterial is present, otherwise random.
|
|
23
|
+
* Random keys are suitable only when the wallet implementation itself is
|
|
24
|
+
* durably persisted.
|
|
25
|
+
*/
|
|
26
|
+
mode?: WalletProvisionMode;
|
|
27
|
+
};
|
|
14
28
|
/**
|
|
15
29
|
* Node-focused managed wallet implementation for BFF, portal, and backend flows.
|
|
16
30
|
*
|
|
@@ -20,6 +34,11 @@ export type NodeManagedWalletOptions = {
|
|
|
20
34
|
* - OpenID/JWT signing
|
|
21
35
|
* - DIDComm-style transport wrapping
|
|
22
36
|
* - confidential document protection
|
|
37
|
+
*
|
|
38
|
+
* OpenID boundary: managing an `openid-id-token-signing` key and producing a
|
|
39
|
+
* compact JWT does not turn this wallet into an OpenID Provider. The hosting
|
|
40
|
+
* portal/BFF must authenticate the account, verify any asserted email, publish
|
|
41
|
+
* provider metadata and JWKS, and be explicitly trusted by the receiving GW.
|
|
23
42
|
*/
|
|
24
43
|
export declare class NodeManagedWallet implements IWallet {
|
|
25
44
|
private readonly cryptoHelper;
|
|
@@ -47,6 +66,27 @@ export declare class NodeManagedWallet implements IWallet {
|
|
|
47
66
|
* Returns the currently available public JWKs for the selected context and filter.
|
|
48
67
|
*/
|
|
49
68
|
getPublicJwks(context?: WalletExecutionContext, filter?: WalletKeySelection): Promise<WalletKeyDescriptor[]>;
|
|
69
|
+
/**
|
|
70
|
+
* Initializes the runtime communication wallet and returns exactly the
|
|
71
|
+
* public signing/encryption JWKS accepted as `controller.publicKeys` by the
|
|
72
|
+
* legacy organization activation builder.
|
|
73
|
+
*
|
|
74
|
+
* This does not replace the professional-role signing key supplied as
|
|
75
|
+
* `controller.publicSignKey`. The role key identifies the historical legal
|
|
76
|
+
* representative; these runtime keys protect DIDComm communications.
|
|
77
|
+
*
|
|
78
|
+
* The caller owns durable wallet custody. When deterministic provisioning is
|
|
79
|
+
* used, protect `seedMaterial` in the portal wallet store (for example behind
|
|
80
|
+
* the user's PIN and a server-held KEK) so the same private keys can be
|
|
81
|
+
* reconstructed after restart. ICA and GW receive only this returned public
|
|
82
|
+
* JWKS.
|
|
83
|
+
*/
|
|
84
|
+
initializeCommunicationJsonWebKeySet(context: WalletExecutionContext, options?: NodeCommunicationWalletInitialization): Promise<JwkSet>;
|
|
85
|
+
/**
|
|
86
|
+
* Returns only the public DIDComm signing/encryption keys for a previously
|
|
87
|
+
* initialized runtime wallet. Private material never leaves the wallet.
|
|
88
|
+
*/
|
|
89
|
+
getCommunicationJsonWebKeySet(context: WalletExecutionContext): Promise<JwkSet>;
|
|
50
90
|
/**
|
|
51
91
|
* Computes a digest of a string using the configured runtime helper.
|
|
52
92
|
*/
|
|
@@ -25,6 +25,11 @@ const DEFAULT_POLICY = {
|
|
|
25
25
|
* - OpenID/JWT signing
|
|
26
26
|
* - DIDComm-style transport wrapping
|
|
27
27
|
* - confidential document protection
|
|
28
|
+
*
|
|
29
|
+
* OpenID boundary: managing an `openid-id-token-signing` key and producing a
|
|
30
|
+
* compact JWT does not turn this wallet into an OpenID Provider. The hosting
|
|
31
|
+
* portal/BFF must authenticate the account, verify any asserted email, publish
|
|
32
|
+
* provider metadata and JWKS, and be explicitly trusted by the receiving GW.
|
|
28
33
|
*/
|
|
29
34
|
export class NodeManagedWallet {
|
|
30
35
|
/**
|
|
@@ -128,6 +133,53 @@ export class NodeManagedWallet {
|
|
|
128
133
|
}
|
|
129
134
|
return descriptors;
|
|
130
135
|
}
|
|
136
|
+
/**
|
|
137
|
+
* Initializes the runtime communication wallet and returns exactly the
|
|
138
|
+
* public signing/encryption JWKS accepted as `controller.publicKeys` by the
|
|
139
|
+
* legacy organization activation builder.
|
|
140
|
+
*
|
|
141
|
+
* This does not replace the professional-role signing key supplied as
|
|
142
|
+
* `controller.publicSignKey`. The role key identifies the historical legal
|
|
143
|
+
* representative; these runtime keys protect DIDComm communications.
|
|
144
|
+
*
|
|
145
|
+
* The caller owns durable wallet custody. When deterministic provisioning is
|
|
146
|
+
* used, protect `seedMaterial` in the portal wallet store (for example behind
|
|
147
|
+
* the user's PIN and a server-held KEK) so the same private keys can be
|
|
148
|
+
* reconstructed after restart. ICA and GW receive only this returned public
|
|
149
|
+
* JWKS.
|
|
150
|
+
*/
|
|
151
|
+
async initializeCommunicationJsonWebKeySet(context, options = {}) {
|
|
152
|
+
if (!context.runtime?.runtimeId) {
|
|
153
|
+
throw new Error('Communication wallet initialization requires context.runtime.runtimeId.');
|
|
154
|
+
}
|
|
155
|
+
await this.provisionManagedKeys(context, {
|
|
156
|
+
ownerScope: 'runtime',
|
|
157
|
+
purposes: ['comm-signing', 'comm-encryption'],
|
|
158
|
+
...(options.seedMaterial !== undefined ? { seedMaterial: options.seedMaterial } : {}),
|
|
159
|
+
mode: options.mode ?? (options.seedMaterial !== undefined ? 'deterministic' : 'random'),
|
|
160
|
+
});
|
|
161
|
+
return this.getCommunicationJsonWebKeySet(context);
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Returns only the public DIDComm signing/encryption keys for a previously
|
|
165
|
+
* initialized runtime wallet. Private material never leaves the wallet.
|
|
166
|
+
*/
|
|
167
|
+
async getCommunicationJsonWebKeySet(context) {
|
|
168
|
+
if (!context.runtime?.runtimeId) {
|
|
169
|
+
throw new Error('Communication JWKS lookup requires context.runtime.runtimeId.');
|
|
170
|
+
}
|
|
171
|
+
const descriptors = await this.getPublicJwks(context, { ownerScope: 'runtime' });
|
|
172
|
+
return {
|
|
173
|
+
keys: descriptors
|
|
174
|
+
.filter((entry) => entry.purpose === 'comm-signing' || entry.purpose === 'comm-encryption')
|
|
175
|
+
.map((entry) => ({
|
|
176
|
+
...entry.publicJwk,
|
|
177
|
+
kid: entry.publicJwk.kid ?? entry.kid,
|
|
178
|
+
use: entry.use,
|
|
179
|
+
alg: entry.publicJwk.alg ?? entry.alg,
|
|
180
|
+
})),
|
|
181
|
+
};
|
|
182
|
+
}
|
|
131
183
|
/**
|
|
132
184
|
* Computes a digest of a string using the configured runtime helper.
|
|
133
185
|
*/
|
|
@@ -3,6 +3,7 @@ import type { AppInfo } from 'gdc-sdk-core-ts';
|
|
|
3
3
|
import type { IndividualOrganizationLifecycleInput } from 'gdc-sdk-core-ts';
|
|
4
4
|
import { type ResolvedAppInfo, type CommunicationClinicalFormatRenderers, type SecureDidcommTransportAdapter, type TransportProfile } from 'gdc-sdk-core-ts';
|
|
5
5
|
import { type HostRouteContext, type HostedTenantLifecycleInput } from './host-onboarding.js';
|
|
6
|
+
import type { HostedTenantDescendantKind } from './host-onboarding.js';
|
|
6
7
|
import type { NodeLegalOrganizationVerificationTransactionInput, NodeOrganizationDidBindingInput, NodeOrganizationActivationInput } from './orchestration/client-port.js';
|
|
7
8
|
import { type IndividualOrganizationConfirmOrderInput, type RouteContext } from './individual-onboarding.js';
|
|
8
9
|
import { type EnsureFamilyOrganizationRegistrationInput } from './family-organization-registration.js';
|
|
@@ -11,7 +12,7 @@ import { type SmartTokenRequestInput } from './smart-token.js';
|
|
|
11
12
|
import { type EmployeeDeviceActivationRequestInput, type EmployeeDeviceActivationResult, type EmployeeDeviceRevocationInput } from './device-activation.js';
|
|
12
13
|
import { type OrganizationLicenseOrderConfirmInput } from './organization-license-order.js';
|
|
13
14
|
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 OrganizationEmployeeLicenseAddInput, type OrganizationEmployeeLicenseOfferInput, type OrganizationEmployeeLicenseInvitationInput, type OrganizationEmployeeLifecycleInput, type OrganizationEmployeeSearchInput, type ProfessionalAccessRequestInput, type ProfessionalAccessRequestResult, type RevokeProfessionalAccessInput, type RevokeProfessionalAccessResult, type RelatedPersonUpsertInput } from './resource-operations.js';
|
|
15
|
+
import { type CommunicationIngestionInput, type BlockchainArtifactRegistrationInput, type VitalSignBatchCommunicationFromSearchResponseInput, type CommunicationParticipantRuntimeSearchInput, type ClinicalBundleSearchInput, type ClinicalSectionUpdateInput, type ClinicalSummaryReadResult, type ClinicalSummaryRequestInput, type ClinicalSummaryUpdateInput, type GrantProfessionalAccessInput, type GrantProfessionalAccessResult, type DigitalTwinSecondaryUseConsentInput, type DigitalTwinSecondaryUseConsentResult, type DigitalTwinSubjectLinkPurgeInput, type DigitalTwinSubjectLinkPurgeResult, type IndividualMemberLifecycleInput, type IndividualMemberLicenseAddInput, type IndividualMemberLicenseInvitationInput, type IndividualMemberLicenseTransitionInput, type LicenseListRuntimeSearchInput, type LicenseOfferRuntimeSearchInput, type LicenseOrderRuntimeSearchInput, type OrganizationEmployeeCreationInput, type OrganizationEmployeeLicenseAddInput, type OrganizationEmployeeLicenseOfferInput, type OrganizationEmployeeLicenseInvitationInput, type OrganizationEmployeeLifecycleInput, type OrganizationEmployeeSearchInput, type ProfessionalAccessRequestInput, type ProfessionalAccessRequestResult, type RevokeProfessionalAccessInput, type RevokeProfessionalAccessResult, type RelatedPersonUpsertInput } from './resource-operations.js';
|
|
15
16
|
import type { LegalOrganizationOrderInput } from './host-onboarding.js';
|
|
16
17
|
import type { SmartTokenExchangeResult } from './smart-token.js';
|
|
17
18
|
import { type OrganizationEmployeeProvisioningInput, type OrganizationEmployeeProvisioningResult } from './organization-employee-lifecycle.js';
|
|
@@ -254,10 +255,23 @@ export declare class HttpRuntimeClient implements NodeRuntimeClient {
|
|
|
254
255
|
* have already been disabled/purged.
|
|
255
256
|
*/
|
|
256
257
|
disableTenant(hostCtx: HostRouteContext, input: HostedTenantLifecycleInput, pollOptions?: PollOptions): Promise<SubmitAndPollResult>;
|
|
258
|
+
/** Re-enables one suspended hosted tenant without changing its legal identity. */
|
|
259
|
+
enableTenant(hostCtx: HostRouteContext, input: HostedTenantLifecycleInput, pollOptions?: PollOptions): Promise<SubmitAndPollResult>;
|
|
257
260
|
/**
|
|
258
261
|
* Purges one already-disabled hosted tenant through the host registry.
|
|
259
262
|
*/
|
|
260
263
|
purgeTenant(hostCtx: HostRouteContext, input: HostedTenantLifecycleInput, pollOptions?: PollOptions): Promise<SubmitAndPollResult>;
|
|
264
|
+
/** Reads authoritative tenant and descendant lifecycle state from the host registry. */
|
|
265
|
+
getTenantLifecycleStatus(hostCtx: HostRouteContext, input: HostedTenantLifecycleInput, pollOptions?: PollOptions): Promise<SubmitAndPollResult>;
|
|
266
|
+
/** Explicitly disables one descendant group; tenant disable itself never cascades. */
|
|
267
|
+
disableTenantDescendants(hostCtx: HostRouteContext, input: HostedTenantLifecycleInput & {
|
|
268
|
+
descendantKind: HostedTenantDescendantKind;
|
|
269
|
+
}, pollOptions?: PollOptions): Promise<SubmitAndPollResult>;
|
|
270
|
+
/** Explicitly purges one descendant group; tenant purge itself never cascades. */
|
|
271
|
+
purgeTenantDescendants(hostCtx: HostRouteContext, input: HostedTenantLifecycleInput & {
|
|
272
|
+
descendantKind: HostedTenantDescendantKind;
|
|
273
|
+
}, pollOptions?: PollOptions): Promise<SubmitAndPollResult>;
|
|
274
|
+
private submitTenantDescendantLifecycle;
|
|
261
275
|
/**
|
|
262
276
|
* Creates an employee or professional entry under an existing organization tenant.
|
|
263
277
|
*/
|
|
@@ -419,6 +433,13 @@ export declare class HttpRuntimeClient implements NodeRuntimeClient {
|
|
|
419
433
|
* Creates and submits a consent-oriented access grant for a professional actor.
|
|
420
434
|
*/
|
|
421
435
|
grantProfessionalAccess(ctx: RouteContext, input: GrantProfessionalAccessInput): Promise<GrantProfessionalAccessResult>;
|
|
436
|
+
/**
|
|
437
|
+
* Applies the subject's reversible secondary-use decision and lets GW
|
|
438
|
+
* rebuild or pause the tenant-private digital-twin projection.
|
|
439
|
+
*/
|
|
440
|
+
setDigitalTwinSecondaryUseConsent(ctx: RouteContext, input: DigitalTwinSecondaryUseConsentInput): Promise<DigitalTwinSecondaryUseConsentResult>;
|
|
441
|
+
/** Offboards the subject from this index provider without deleting the anonymous twin. */
|
|
442
|
+
purgeDigitalTwinSubjectLink(ctx: RouteContext, input: DigitalTwinSubjectLinkPurgeInput): Promise<DigitalTwinSubjectLinkPurgeResult>;
|
|
422
443
|
/**
|
|
423
444
|
* Closes an existing professional consent by setting its period end and
|
|
424
445
|
* resubmitting the updated consent resource.
|
|
@@ -439,6 +460,11 @@ export declare class HttpRuntimeClient implements NodeRuntimeClient {
|
|
|
439
460
|
* actor-neutral and is used by portal and telephone profile runtimes.
|
|
440
461
|
*/
|
|
441
462
|
activateProfileDeviceWithActivationRequest(input: EmployeeDeviceActivationRequestInput): Promise<EmployeeDeviceActivationResult>;
|
|
463
|
+
/**
|
|
464
|
+
* Actor-facade name retained for organization controllers and employees.
|
|
465
|
+
* The implementation is actor-neutral and shares the profile-device flow.
|
|
466
|
+
*/
|
|
467
|
+
activateEmployeeDeviceWithActivationRequest(input: EmployeeDeviceActivationRequestInput): Promise<EmployeeDeviceActivationResult>;
|
|
442
468
|
/**
|
|
443
469
|
* Creates or updates a `RelatedPerson` for non-employee family/caregiver
|
|
444
470
|
* roles such as a grandfather, guardian, or external caregiver.
|
|
@@ -616,6 +642,8 @@ export declare class HttpRuntimeClient implements NodeRuntimeClient {
|
|
|
616
642
|
individualRelatedPersonPurgePollPath(ctx?: RouteContext): string;
|
|
617
643
|
individualConsentR4BatchPath(ctx: RouteContext): string;
|
|
618
644
|
individualConsentR4PollPath(ctx: RouteContext): string;
|
|
645
|
+
individualResearchSubjectPurgePath(ctx: RouteContext): string;
|
|
646
|
+
individualResearchSubjectPurgePollPath(ctx: RouteContext): string;
|
|
619
647
|
individualCommunicationBatchPath(ctx: RouteContext, format: string): string;
|
|
620
648
|
individualCommunicationPollPath(ctx: RouteContext, format: string): string;
|
|
621
649
|
individualCommunicationSearchPath(ctx: RouteContext): string;
|