gdc-sdk-node-ts 0.12.0 → 2.0.2

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.
@@ -2,8 +2,9 @@
2
2
  // Always create JSDoc, do not use strings inline in keys nor values, use types instead, and reuse the data test examples.
3
3
  import fs from 'node:fs';
4
4
  import path from 'node:path';
5
- import { buildAppHeaders, createBootstrapFacade, resolveAppInfo, } from 'gdc-sdk-core-ts';
5
+ import { buildLegalOrganizationVerificationGatewayRequestBundle, buildOrganizationDidBindingBundle, buildAppHeaders, createBootstrapFacade, resolveAppInfo, } from 'gdc-sdk-core-ts';
6
6
  import { buildConsentClaimsSimpleWithCid } from 'gdc-common-utils-ts/utils/consent';
7
+ import { buildDidcommPlaintextTransportMetadata } from 'gdc-common-utils-ts/utils/activation-request';
7
8
  import { pollUntilCompleteWithMethod } from './async-polling.js';
8
9
  import { confirmLegalOrganizationOrderWithDeps, HostLifecycleRequestType, HostedTenantLifecycleRequestType, submitHostedTenantLifecycleWithDeps, } from './host-onboarding.js';
9
10
  import { confirmIndividualOrganizationOrderWithDeps, } from './individual-onboarding.js';
@@ -11,7 +12,7 @@ import { requestSmartTokenWithDeps } from './smart-token.js';
11
12
  import { extractOfferIdFromResponseBody, extractOfferPreviewFromResponseBody, } from './order-offer-summary.js';
12
13
  import { confirmOrganizationLicenseOrderWithDeps } from './organization-license-order.js';
13
14
  import { startIndividualOrganizationWithDeps } from './individual-start.js';
14
- import { createOrganizationEmployeeWithDeps, disableIndividualMemberWithDeps, disableIndividualOrganizationWithDeps, disableOrganizationEmployeeWithDeps, listIndividualLicenseOffersWithDeps, listIndividualLicenseOrdersWithDeps, listIndividualLicensesWithDeps, listOrganizationLicenseOffersWithDeps, listOrganizationLicenseOrdersWithDeps, listOrganizationLicensesWithDeps, grantProfessionalAccessWithDeps, ingestCommunicationAndUpdateIndexWithDeps, purgeIndividualMemberWithDeps, purgeIndividualOrganizationWithDeps, purgeOrganizationEmployeeWithDeps, searchIndividualLicensesWithDeps, searchIndividualLicenseOffersWithDeps, searchIndividualLicenseOrdersWithDeps, searchOrganizationLicensesWithDeps, searchOrganizationLicenseOffersWithDeps, searchOrganizationLicenseOrdersWithDeps, searchOrganizationEmployeesWithDeps, searchClinicalBundleWithDeps, searchLatestIpsWithDeps, upsertRelatedPersonAndPollWithDeps, } from './resource-operations.js';
15
+ import { createOrganizationEmployeeWithDeps, disableIndividualMemberWithDeps, disableIndividualOrganizationWithDeps, disableOrganizationEmployeeWithDeps, listIndividualLicenseOffersWithDeps, listIndividualLicenseOrdersWithDeps, listIndividualLicensesWithDeps, listOrganizationLicenseOffersWithDeps, listOrganizationLicenseOrdersWithDeps, listOrganizationLicensesWithDeps, grantProfessionalAccessWithDeps, ingestCommunicationAndUpdateIndexWithDeps, searchCommunicationParticipantsWithDeps, purgeIndividualMemberWithDeps, purgeIndividualOrganizationWithDeps, purgeOrganizationEmployeeWithDeps, searchIndividualLicensesWithDeps, searchIndividualLicenseOffersWithDeps, searchIndividualLicenseOrdersWithDeps, searchOrganizationLicensesWithDeps, searchOrganizationLicenseOffersWithDeps, searchOrganizationLicenseOrdersWithDeps, searchOrganizationEmployeesWithDeps, searchClinicalBundleWithDeps, searchLatestIpsWithDeps, upsertRelatedPersonAndPollWithDeps, } from './resource-operations.js';
15
16
  import { submitAndPollWithMethods } from './orchestration/client-port.js';
16
17
  import { GwCoreLifecycleAction } from './constants/lifecycle.js';
17
18
  const bootstrapFacade = createBootstrapFacade();
@@ -96,9 +97,66 @@ export class HttpRuntimeClient {
96
97
  async submitAndPoll(submitPath, pollPath, payload, pollOptions) {
97
98
  return submitAndPollWithMethods(this, submitPath, pollPath, payload, pollOptions);
98
99
  }
100
+ /**
101
+ * Starts the host-side legal-organization verification transaction that GW
102
+ * CORE forwards to ICA `_verify`.
103
+ *
104
+ * Runtime ownership:
105
+ * - builds the canonical shared business bundle from `sdk-core/common-utils`
106
+ * - keeps communication/runtime transport concerns at the outer message layer
107
+ * - keeps the controller business key inside the submitted bundle payload
108
+ *
109
+ * Flow separation:
110
+ * - `_transaction` is the first host onboarding step
111
+ * - `_activate` remains a later step that consumes the ICA proof
112
+ */
113
+ async submitLegalOrganizationVerificationTransaction(hostCtx, input, pollOptions) {
114
+ const thid = `organization-verification-transaction-${runtimeUuid()}`;
115
+ const jti = `organization-verification-transaction-jti-${runtimeUuid()}`;
116
+ const verificationBundle = buildLegalOrganizationVerificationGatewayRequestBundle(input);
117
+ const payload = this.wrapBundleAsGatewayTransactionMessage({
118
+ thid,
119
+ jti,
120
+ hostCtx,
121
+ bundle: verificationBundle,
122
+ });
123
+ return this.submitAndPoll(this.hostRegistryOrganizationTransactionPath(hostCtx), this.hostRegistryOrganizationTransactionPollPath(hostCtx), payload, pollOptions);
124
+ }
125
+ /**
126
+ * Submits one tenant-scoped DID document binding request.
127
+ *
128
+ * Binding semantics:
129
+ * - the tenant path identifies the existing organization
130
+ * - `organization.url` carries the public alias/domain list
131
+ * - `controller.sameAs` is optional corroborating identity material
132
+ * - the flow does not rotate or replace organization public keys
133
+ */
134
+ async submitOrganizationDidBinding(ctx, input, pollOptions) {
135
+ const thid = `organization-did-binding-${runtimeUuid()}`;
136
+ const jti = `organization-did-binding-jti-${runtimeUuid()}`;
137
+ const payload = {
138
+ jti,
139
+ thid,
140
+ type: 'application/api+json',
141
+ body: buildOrganizationDidBindingBundle(input),
142
+ };
143
+ return this.submitAndPoll(this.organizationDidBindingPath(ctx), this.organizationDidBindingPollPath(ctx), payload, pollOptions);
144
+ }
99
145
  /**
100
146
  * Activates a legal organization in the gateway host registry using an ICA
101
147
  * proof token already obtained by the caller.
148
+ *
149
+ * Plaintext transport note:
150
+ * - this Node runtime currently submits `_activate` as
151
+ * `application/didcomm-plaintext+json`
152
+ * - because there is no real outer JWS/JWE envelope in that mode, the
153
+ * runtime mirrors the technical communication metadata derived from
154
+ * `controller.publicKeyJwk` / `controller.jwks` into `meta.jws.protected`
155
+ * and `meta.jwe.header`
156
+ * - secure JOSE transports should carry those values in the real protected
157
+ * headers instead of plaintext `meta`
158
+ * - this mirrored metadata is transport fallback only; the canonical
159
+ * activation contract remains `body.vp_token` plus `body.controller.*`
102
160
  */
103
161
  async activateOrganizationInGatewayFromIcaProof(hostCtx, input, pollOptions) {
104
162
  const thid = `activate-org-${runtimeUuid()}`;
@@ -109,11 +167,16 @@ export class HttpRuntimeClient {
109
167
  additionalClaims: input.additionalClaims,
110
168
  });
111
169
  const serviceClaims = activationDraft.buildServiceClaims();
170
+ const transportMeta = buildDidcommPlaintextTransportMetadata({
171
+ controller: input.controller,
172
+ contentType: 'application/didcomm-plaintext+json',
173
+ });
112
174
  const payload = {
113
175
  thid,
114
176
  iss: String(hostCtx.controllerDid || '').trim() || undefined,
115
177
  aud: String(hostCtx.hostDid || '').trim() || undefined,
116
178
  type: 'application/api+json',
179
+ ...(transportMeta ? { meta: transportMeta } : {}),
117
180
  body: {
118
181
  vp_token: input.vpToken,
119
182
  ...(input.controller ? { controller: input.controller } : {}),
@@ -550,6 +613,17 @@ export class HttpRuntimeClient {
550
613
  submitAndPoll: this.submitAndPoll.bind(this),
551
614
  });
552
615
  }
616
+ /**
617
+ * Searches communication channel records by subject and participant
618
+ * identifiers through `Communication/_search`.
619
+ */
620
+ async searchCommunicationParticipants(ctx, input) {
621
+ return searchCommunicationParticipantsWithDeps(ctx, input, {
622
+ communicationSearchPath: this.individualCommunicationSearchPath.bind(this),
623
+ communicationSearchPollPath: this.individualCommunicationSearchPollPath.bind(this),
624
+ submitAndPoll: this.submitAndPoll.bind(this),
625
+ });
626
+ }
553
627
  /**
554
628
  * Alias for `ingestCommunicationAndUpdateIndex(...)`.
555
629
  *
@@ -723,6 +797,24 @@ export class HttpRuntimeClient {
723
797
  ? { tenantId, jurisdiction: input.jurisdiction, sector: input.sector }
724
798
  : undefined);
725
799
  }
800
+ /**
801
+ * Reuses the shared bundle business contract while keeping attachment
802
+ * transport fields at the DIDComm/plaintext message layer expected by GW.
803
+ */
804
+ wrapBundleAsGatewayTransactionMessage(input) {
805
+ const rawBundle = (input.bundle || {});
806
+ const attachments = Array.isArray(rawBundle.attachments) ? rawBundle.attachments : undefined;
807
+ const { attachments: _ignoredAttachments, ...body } = rawBundle;
808
+ return {
809
+ jti: input.jti,
810
+ thid: input.thid,
811
+ iss: String(input.hostCtx.controllerDid || '').trim() || undefined,
812
+ aud: String(input.hostCtx.hostDid || '').trim() || undefined,
813
+ type: 'application/api+json',
814
+ body,
815
+ ...(attachments && attachments.length > 0 ? { attachments } : {}),
816
+ };
817
+ }
726
818
  hostRegistryPath(ctx, resourceType, action) {
727
819
  const hostCtx = this.requireHostRouteContext(ctx);
728
820
  return `/host/cds-${encodeURIComponent(hostCtx.jurisdiction)}/v1/${encodeURIComponent(hostCtx.hostNetwork || '')}/registry/org.schema/${encodeURIComponent(resourceType)}/${encodeURIComponent(action)}`;
@@ -735,6 +827,8 @@ export class HttpRuntimeClient {
735
827
  throw new Error('Host route context is required.');
736
828
  return { jurisdiction, hostNetwork };
737
829
  }
830
+ hostRegistryOrganizationTransactionPath(ctx) { return this.hostRegistryPath(ctx, 'Organization', GwCoreLifecycleAction.Transaction); }
831
+ hostRegistryOrganizationTransactionPollPath(ctx) { return this.hostRegistryPath(ctx, 'Organization', GwCoreLifecycleAction.TransactionResponse); }
738
832
  hostRegistryOrganizationActivatePath(ctx) { return this.hostRegistryPath(ctx, 'Organization', '_activate'); }
739
833
  hostRegistryOrganizationActivatePollPath(ctx) { return this.hostRegistryPath(ctx, 'Organization', '_activate-response'); }
740
834
  hostRegistryOrganizationDisablePath(ctx) { return this.hostRegistryPath(ctx, 'Organization', GwCoreLifecycleAction.Disable); }
@@ -749,6 +843,14 @@ export class HttpRuntimeClient {
749
843
  employeeSearchPollPath(ctx) { return this.v1Path(ctx, 'entity', 'org.schema', 'Employee', '_search-response'); }
750
844
  organizationLicenseSearchPath(ctx) { return this.v1Path(ctx, 'entity', 'org.schema', 'License', '_search'); }
751
845
  organizationLicenseSearchPollPath(ctx) { return this.v1Path(ctx, 'entity', 'org.schema', 'License', '_search-response'); }
846
+ organizationDidBindingPath(ctx) {
847
+ const resolved = this.requireRouteContext(ctx);
848
+ return `/${encodeURIComponent(resolved.tenantId)}/cds-${encodeURIComponent(resolved.jurisdiction)}/v1/${encodeURIComponent(resolved.sector)}/did/document/_binding`;
849
+ }
850
+ organizationDidBindingPollPath(ctx) {
851
+ const resolved = this.requireRouteContext(ctx);
852
+ return `/${encodeURIComponent(resolved.tenantId)}/cds-${encodeURIComponent(resolved.jurisdiction)}/v1/${encodeURIComponent(resolved.sector)}/did/document/_binding-response`;
853
+ }
752
854
  organizationLicenseOfferSearchPath(ctx) { return this.v1Path(ctx, 'entity', 'org.schema', 'Offer', '_search'); }
753
855
  organizationLicenseOfferSearchPollPath(ctx) { return this.v1Path(ctx, 'entity', 'org.schema', 'Offer', '_search-response'); }
754
856
  organizationLicenseOrderSearchPath(ctx) { return this.v1Path(ctx, 'entity', 'org.schema', 'Order', '_search'); }
@@ -779,6 +881,8 @@ export class HttpRuntimeClient {
779
881
  individualConsentR4PollPath(ctx) { return this.v1Path(ctx, 'individual', 'org.hl7.fhir.r4', 'Consent', '_batch-response'); }
780
882
  individualCommunicationBatchPath(ctx, format) { return this.v1Path(ctx, 'individual', format, 'Communication', '_batch'); }
781
883
  individualCommunicationPollPath(ctx, format) { return this.v1Path(ctx, 'individual', format, 'Communication', '_batch-response'); }
884
+ individualCommunicationSearchPath(ctx) { return this.v1Path(ctx, 'individual', 'org.hl7.fhir.r4', 'Communication', '_search'); }
885
+ individualCommunicationSearchPollPath(ctx) { return this.v1Path(ctx, 'individual', 'org.hl7.fhir.r4', 'Communication', '_search-response'); }
782
886
  individualBundleSearchPath(ctx) { return this.v1Path(ctx, 'individual', 'org.hl7.fhir.r4', 'Bundle', '_search'); }
783
887
  individualBundleSearchPollPath(ctx) { return this.v1Path(ctx, 'individual', 'org.hl7.fhir.r4', 'Bundle', '_search-response'); }
784
888
  identityTokenExchangePath(ctx) {
@@ -1,4 +1,6 @@
1
1
  import type { ControllerBindingInput } from 'gdc-common-utils-ts/models';
2
+ import type { LegalOrganizationVerificationTransactionInput } from 'gdc-common-utils-ts/utils/legal-organization-verification-transaction';
3
+ import type { OrganizationDidBindingInput } from 'gdc-sdk-core-ts';
2
4
  import type { LicenseListRuntimeSearchInput, LicenseOfferRuntimeSearchInput, LicenseOrderRuntimeSearchInput } from '../resource-operations.js';
3
5
  import type { AsyncPollRequest, OrganizationActivationServiceOptions, PollOptions, PollResult, SubmitAndPollResult, SubmitPayload, SubmitResponse } from 'gdc-sdk-core-ts';
4
6
  export type { AsyncPollRequest, PollOptions, PollResult, SubmitAndPollResult, SubmitPayload, SubmitResponse, } from 'gdc-sdk-core-ts';
@@ -8,7 +10,7 @@ import type { IndividualOrganizationConfirmOrderInput, RouteContext } from '../i
8
10
  import type { IndividualOrganizationBootstrapInput, IndividualOrganizationStartResult } from '../individual-start.js';
9
11
  import type { OrganizationLicenseOrderConfirmInput } from '../organization-license-order.js';
10
12
  import type { SmartTokenExchangeResult, SmartTokenRequestInput } from '../smart-token.js';
11
- import type { CommunicationIngestionInput, ClinicalBundleSearchInput, DigitalTwinGenerationInput, GrantProfessionalAccessInput, GrantProfessionalAccessResult, IndividualMemberLifecycleInput, IndividualOrganizationLifecycleInput, IpsOrFhirImportInput, OrganizationEmployeeCreationInput, OrganizationEmployeeLifecycleInput, OrganizationEmployeeSearchInput, RelatedPersonUpsertInput } from '../resource-operations.js';
13
+ import type { CommunicationIngestionInput, CommunicationParticipantRuntimeSearchInput, ClinicalBundleSearchInput, DigitalTwinGenerationInput, GrantProfessionalAccessInput, GrantProfessionalAccessResult, IndividualMemberLifecycleInput, IndividualOrganizationLifecycleInput, IpsOrFhirImportInput, OrganizationEmployeeCreationInput, OrganizationEmployeeLifecycleInput, OrganizationEmployeeSearchInput, RelatedPersonUpsertInput } from '../resource-operations.js';
12
14
  /**
13
15
  * Shared node-runtime activation input.
14
16
  *
@@ -21,6 +23,25 @@ export type NodeOrganizationActivationInput = {
21
23
  service?: OrganizationActivationServiceOptions;
22
24
  additionalClaims?: Record<string, unknown>;
23
25
  };
26
+ /**
27
+ * Shared node-runtime input for the first host-side legal-organization
28
+ * verification step.
29
+ *
30
+ * The business payload is owned by shared SDK/common packages:
31
+ * - transport/runtime communication keys stay outside this contract
32
+ * - controller business key binding remains in `controller.*`
33
+ * - GW CORE host routing/polling stays in the runtime adapter
34
+ */
35
+ export type NodeLegalOrganizationVerificationTransactionInput = LegalOrganizationVerificationTransactionInput;
36
+ /**
37
+ * Shared node-runtime input for the organization DID binding operation.
38
+ *
39
+ * Binding contract:
40
+ * - tenant identity is resolved from the route path
41
+ * - `organization.url` carries one or more public aliases/domains
42
+ * - `controller.sameAs` is optional corroborating identity evidence
43
+ */
44
+ export type NodeOrganizationDidBindingInput = OrganizationDidBindingInput;
24
45
  /**
25
46
  * Runtime-neutral actor/application client contract as exposed by the Node SDK.
26
47
  *
@@ -29,6 +50,8 @@ export type NodeOrganizationActivationInput = {
29
50
  * converge across runtimes.
30
51
  */
31
52
  export type RuntimeClient = {
53
+ submitLegalOrganizationVerificationTransaction?: (hostCtx: HostRouteContext, input: NodeLegalOrganizationVerificationTransactionInput, pollOptions?: PollOptions) => Promise<SubmitAndPollResult>;
54
+ submitOrganizationDidBinding?: (ctx: RouteContext, input: NodeOrganizationDidBindingInput, pollOptions?: PollOptions) => Promise<SubmitAndPollResult>;
32
55
  activateOrganizationInGatewayFromIcaProof?: (hostCtx: HostRouteContext, input: NodeOrganizationActivationInput, pollOptions?: PollOptions) => Promise<SubmitAndPollResult>;
33
56
  confirmLegalOrganizationOrder?: (hostCtx: HostRouteContext, input: LegalOrganizationOrderInput, pollOptions?: PollOptions) => Promise<SubmitAndPollResult>;
34
57
  disableHost?: (hostCtx: HostRouteContext, input: HostedTenantLifecycleInput, pollOptions?: PollOptions) => Promise<SubmitAndPollResult>;
@@ -59,6 +82,7 @@ export type RuntimeClient = {
59
82
  disableIndividualOrganization?: (ctx: RouteContext, input: IndividualOrganizationLifecycleInput, pollOptions?: PollOptions) => Promise<SubmitAndPollResult>;
60
83
  purgeIndividualOrganization?: (ctx: RouteContext, input: IndividualOrganizationLifecycleInput, pollOptions?: PollOptions) => Promise<SubmitAndPollResult>;
61
84
  ingestCommunicationAndUpdateIndex?: (ctx: RouteContext, input: CommunicationIngestionInput) => Promise<SubmitAndPollResult>;
85
+ searchCommunicationParticipants?: (ctx: RouteContext, input: CommunicationParticipantRuntimeSearchInput) => Promise<SubmitAndPollResult>;
62
86
  grantProfessionalAccess?: (ctx: RouteContext, input: GrantProfessionalAccessInput) => Promise<GrantProfessionalAccessResult>;
63
87
  searchIndividualLicenses?: (ctx: RouteContext, input: LicenseListRuntimeSearchInput) => Promise<SubmitAndPollResult>;
64
88
  listIndividualLicenses?: (ctx: RouteContext, input?: LicenseListRuntimeSearchInput) => Promise<SubmitAndPollResult>;
@@ -2,7 +2,7 @@ import { type NodeRuntimeClient, type PollOptions, type SubmitAndPollResult, typ
2
2
  import type { IndividualOrganizationConfirmOrderInput, RouteContext } from '../individual-onboarding.js';
3
3
  import type { IndividualOrganizationBootstrapInput, IndividualOrganizationStartResult } from '../individual-start.js';
4
4
  import type { NodeCapability } from '../session.js';
5
- import type { ClinicalBundleSearchInput, CommunicationIngestionInput, DigitalTwinGenerationInput, GrantProfessionalAccessInput, GrantProfessionalAccessResult, IndividualMemberLifecycleInput, IndividualOrganizationLifecycleInput, IpsOrFhirImportInput, LicenseListRuntimeSearchInput, LicenseOfferRuntimeSearchInput, LicenseOrderRuntimeSearchInput, RelatedPersonUpsertInput } from '../resource-operations.js';
5
+ import type { ClinicalBundleSearchInput, CommunicationIngestionInput, CommunicationParticipantRuntimeSearchInput, DigitalTwinGenerationInput, GrantProfessionalAccessInput, GrantProfessionalAccessResult, IndividualMemberLifecycleInput, IndividualOrganizationLifecycleInput, IpsOrFhirImportInput, LicenseListRuntimeSearchInput, LicenseOfferRuntimeSearchInput, LicenseOrderRuntimeSearchInput, RelatedPersonUpsertInput } from '../resource-operations.js';
6
6
  import type { SmartTokenExchangeResult, SmartTokenRequestInput } from '../smart-token.js';
7
7
  /**
8
8
  * Individual-controller oriented facade over a `NodeRuntimeClient`.
@@ -71,6 +71,11 @@ export declare class IndividualControllerSdk {
71
71
  * Ingests a FHIR `Communication` and waits for indexing.
72
72
  */
73
73
  ingestCommunicationAndUpdateIndex(ctx: RouteContext, input: CommunicationIngestionInput): Promise<SubmitAndPollResult>;
74
+ /**
75
+ * Searches indexed communication channel records by subject and participant
76
+ * identifiers.
77
+ */
78
+ searchCommunicationParticipants(ctx: RouteContext, input: CommunicationParticipantRuntimeSearchInput): Promise<SubmitAndPollResult>;
74
79
  /**
75
80
  * Generates a digital twin projection from subject data.
76
81
  */
@@ -106,6 +106,13 @@ export class IndividualControllerSdk {
106
106
  assertFacadeCapability(this.capabilities, ActorCapabilities.IndividualIngestCommunication, ActorKinds.IndividualController, 'ingestCommunicationAndUpdateIndex');
107
107
  return requireClientMethod(this.client, 'ingestCommunicationAndUpdateIndex')(ctx, input);
108
108
  }
109
+ /**
110
+ * Searches indexed communication channel records by subject and participant
111
+ * identifiers.
112
+ */
113
+ searchCommunicationParticipants(ctx, input) {
114
+ return requireClientMethod(this.client, 'searchCommunicationParticipants')(ctx, input);
115
+ }
109
116
  /**
110
117
  * Generates a digital twin projection from subject data.
111
118
  */
@@ -1,4 +1,4 @@
1
- import { type NodeRuntimeClient, type PollOptions, type SubmitAndPollResult, type SubmitPayload } from './client-port.js';
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
4
  import type { EmployeeDeviceActivationResult, EmployeeDeviceActivationRequestInput } from '../device-activation.js';
@@ -19,6 +19,26 @@ export declare class OrganizationControllerSdk {
19
19
  * @param client Runtime client implementation used to submit and poll GW flows.
20
20
  */
21
21
  constructor(client: NodeRuntimeClient, capabilities?: readonly NodeCapability[] | undefined);
22
+ /**
23
+ * Starts the host-side legal-organization verification transaction that GW
24
+ * CORE forwards to ICA `_verify`.
25
+ *
26
+ * This is intentionally distinct from the later host `_activate` step:
27
+ * - `_transaction` carries signed evidence and controller business binding
28
+ * - `_activate` later consumes the ICA proof returned after verification
29
+ */
30
+ submitLegalOrganizationVerificationTransaction(hostCtx: HostRouteContext, input: NodeLegalOrganizationVerificationTransactionInput, pollOptions?: PollOptions): Promise<SubmitAndPollResult>;
31
+ /**
32
+ * Binds the current tenant organization DID document to one public alias
33
+ * view.
34
+ *
35
+ * Contract:
36
+ * - the tenant path identifies the organization
37
+ * - `organization.url`, when present, provides the public aliases/domains to
38
+ * bind
39
+ * - `controller.sameAs` is optional corroborating identity evidence
40
+ */
41
+ submitOrganizationDidBinding(ctx: RouteContext, input: NodeOrganizationDidBindingInput, pollOptions?: PollOptions): Promise<SubmitAndPollResult>;
22
42
  /**
23
43
  * Creates an employee/professional under the current organization tenant.
24
44
  */
@@ -16,6 +16,30 @@ export class OrganizationControllerSdk {
16
16
  this.client = client;
17
17
  this.capabilities = capabilities;
18
18
  }
19
+ /**
20
+ * Starts the host-side legal-organization verification transaction that GW
21
+ * CORE forwards to ICA `_verify`.
22
+ *
23
+ * This is intentionally distinct from the later host `_activate` step:
24
+ * - `_transaction` carries signed evidence and controller business binding
25
+ * - `_activate` later consumes the ICA proof returned after verification
26
+ */
27
+ submitLegalOrganizationVerificationTransaction(hostCtx, input, pollOptions) {
28
+ return requireClientMethod(this.client, 'submitLegalOrganizationVerificationTransaction')(hostCtx, input, pollOptions);
29
+ }
30
+ /**
31
+ * Binds the current tenant organization DID document to one public alias
32
+ * view.
33
+ *
34
+ * Contract:
35
+ * - the tenant path identifies the organization
36
+ * - `organization.url`, when present, provides the public aliases/domains to
37
+ * bind
38
+ * - `controller.sameAs` is optional corroborating identity evidence
39
+ */
40
+ submitOrganizationDidBinding(ctx, input, pollOptions) {
41
+ return requireClientMethod(this.client, 'submitOrganizationDidBinding')(ctx, input, pollOptions);
42
+ }
19
43
  /**
20
44
  * Creates an employee/professional under the current organization tenant.
21
45
  */
@@ -1,7 +1,7 @@
1
1
  import { type NodeRuntimeClient, type PollOptions, type SubmitAndPollResult, type SubmitPayload } from './client-port.js';
2
2
  import type { IndividualOrganizationBootstrapInput, IndividualOrganizationStartResult } from '../individual-start.js';
3
3
  import type { RouteContext } from '../individual-onboarding.js';
4
- import type { ClinicalBundleSearchInput, CommunicationIngestionInput, DigitalTwinGenerationInput, GrantProfessionalAccessInput, GrantProfessionalAccessResult, IpsOrFhirImportInput, LicenseListRuntimeSearchInput, LicenseOfferRuntimeSearchInput, LicenseOrderRuntimeSearchInput } from '../resource-operations.js';
4
+ import type { ClinicalBundleSearchInput, CommunicationIngestionInput, CommunicationParticipantRuntimeSearchInput, DigitalTwinGenerationInput, GrantProfessionalAccessInput, GrantProfessionalAccessResult, IpsOrFhirImportInput, LicenseListRuntimeSearchInput, LicenseOfferRuntimeSearchInput, LicenseOrderRuntimeSearchInput } from '../resource-operations.js';
5
5
  import type { SmartTokenExchangeResult, SmartTokenRequestInput } from '../smart-token.js';
6
6
  export declare class PersonalSdk {
7
7
  private readonly client;
@@ -14,6 +14,8 @@ export declare class PersonalSdk {
14
14
  importIpsOrFhirAndUpdateIndex(ctx: RouteContext, input: IpsOrFhirImportInput): Promise<SubmitAndPollResult>;
15
15
  /** Ingests canonical Communication and waits for projection completion. */
16
16
  ingestCommunicationAndUpdateIndex(ctx: RouteContext, input: CommunicationIngestionInput): Promise<SubmitAndPollResult>;
17
+ /** Searches indexed communication channel records by subject and participant identifiers. */
18
+ searchCommunicationParticipants(ctx: RouteContext, input: CommunicationParticipantRuntimeSearchInput): Promise<SubmitAndPollResult>;
17
19
  /** Triggers digital twin generation from subject data. */
18
20
  generateDigitalTwinFromSubjectData(ctx: RouteContext, input: DigitalTwinGenerationInput): Promise<SubmitAndPollResult>;
19
21
  /** Searches indexed clinical bundles for the current subject/controller context. */
@@ -20,6 +20,10 @@ export class PersonalSdk {
20
20
  ingestCommunicationAndUpdateIndex(ctx, input) {
21
21
  return requireClientMethod(this.client, 'ingestCommunicationAndUpdateIndex')(ctx, input);
22
22
  }
23
+ /** Searches indexed communication channel records by subject and participant identifiers. */
24
+ searchCommunicationParticipants(ctx, input) {
25
+ return requireClientMethod(this.client, 'searchCommunicationParticipants')(ctx, input);
26
+ }
23
27
  /** Triggers digital twin generation from subject data. */
24
28
  generateDigitalTwinFromSubjectData(ctx, input) {
25
29
  return requireClientMethod(this.client, 'generateDigitalTwinFromSubjectData')(ctx, input);
@@ -1,7 +1,7 @@
1
1
  import { 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 { SmartTokenExchangeResult, SmartTokenRequestInput } from '../smart-token.js';
4
- import type { CommunicationIngestionInput, GrantProfessionalAccessInput, GrantProfessionalAccessResult } from '../resource-operations.js';
4
+ import type { CommunicationIngestionInput, CommunicationParticipantRuntimeSearchInput, GrantProfessionalAccessInput, GrantProfessionalAccessResult } from '../resource-operations.js';
5
5
  /**
6
6
  * Professional-oriented facade for runtime actions that belong to the
7
7
  * professional actor itself after tenant and employee provisioning have already
@@ -33,6 +33,11 @@ export declare class ProfessionalSdk {
33
33
  * Ingests a FHIR `Communication` and waits for indexing.
34
34
  */
35
35
  ingestCommunicationAndUpdateIndex(ctx: RouteContext, input: CommunicationIngestionInput): Promise<SubmitAndPollResult>;
36
+ /**
37
+ * Searches indexed communication channel records by subject and participant
38
+ * identifiers.
39
+ */
40
+ searchCommunicationParticipants(ctx: RouteContext, input: CommunicationParticipantRuntimeSearchInput): Promise<SubmitAndPollResult>;
36
41
  /**
37
42
  * Grants access to a professional through a consent flow.
38
43
  */
@@ -37,6 +37,13 @@ export class ProfessionalSdk {
37
37
  ingestCommunicationAndUpdateIndex(ctx, input) {
38
38
  return requireClientMethod(this.client, 'ingestCommunicationAndUpdateIndex')(ctx, input);
39
39
  }
40
+ /**
41
+ * Searches indexed communication channel records by subject and participant
42
+ * identifiers.
43
+ */
44
+ searchCommunicationParticipants(ctx, input) {
45
+ return requireClientMethod(this.client, 'searchCommunicationParticipants')(ctx, input);
46
+ }
40
47
  /**
41
48
  * Grants access to a professional through a consent flow.
42
49
  */
@@ -1,4 +1,6 @@
1
- import { type LicenseOfferSearchDraft, type LicenseOrderSearchDraft, type LicenseListSearchDraft } from 'gdc-common-utils-ts';
1
+ import { IndividualOrganizationLifecycleEditor } from 'gdc-common-utils-ts';
2
+ import type { LicenseOfferSearchState, LicenseOrderSearchState } from 'gdc-common-utils-ts/utils/license-commercial-search';
3
+ import type { LicenseListSearchState } from 'gdc-common-utils-ts/utils/license-list-search';
2
4
  import type { BundleSearchQuery, CommunicationInput, DateRange, EmployeeSearchValue } from 'gdc-sdk-core-ts';
3
5
  import type { SubmitAndPollResult } from './orchestration/client-port.js';
4
6
  import type { RouteContext } from './individual-onboarding.js';
@@ -66,7 +68,7 @@ export type OrganizationEmployeeSearchInput = {
66
68
  * The semantic filter set comes from the shared license controller facade.
67
69
  */
68
70
  export type LicenseListRuntimeSearchInput = {
69
- licenseQuery?: Partial<LicenseListSearchDraft>;
71
+ licenseQuery?: Partial<LicenseListSearchState>;
70
72
  requestThid?: string;
71
73
  pollOptions?: {
72
74
  timeoutMs?: number;
@@ -78,7 +80,7 @@ export type LicenseListRuntimeSearchInput = {
78
80
  * actor facades.
79
81
  */
80
82
  export type LicenseOfferRuntimeSearchInput = {
81
- offerQuery?: Partial<LicenseOfferSearchDraft>;
83
+ offerQuery?: Partial<LicenseOfferSearchState>;
82
84
  requestThid?: string;
83
85
  pollOptions?: {
84
86
  timeoutMs?: number;
@@ -90,7 +92,7 @@ export type LicenseOfferRuntimeSearchInput = {
90
92
  * through actor facades.
91
93
  */
92
94
  export type LicenseOrderRuntimeSearchInput = {
93
- orderQuery?: Partial<LicenseOrderSearchDraft>;
95
+ orderQuery?: Partial<LicenseOrderSearchState>;
94
96
  requestThid?: string;
95
97
  pollOptions?: {
96
98
  timeoutMs?: number;
@@ -109,7 +111,12 @@ export type IndividualOrganizationLifecycleInput = {
109
111
  * Canonical claims used by GW CORE to locate the hosted individual/family
110
112
  * registration.
111
113
  */
112
- organizationClaims: Record<string, unknown>;
114
+ organizationClaims?: Record<string, unknown>;
115
+ /**
116
+ * Preferred high-level shared editor for lifecycle callers that want to
117
+ * avoid assembling raw claims inline.
118
+ */
119
+ organizationEditor?: IndividualOrganizationLifecycleEditor;
113
120
  /**
114
121
  * Optional canonical resource id when already known by the caller.
115
122
  */
@@ -160,6 +167,39 @@ export type CommunicationIngestionInput = {
160
167
  intervalMs?: number;
161
168
  };
162
169
  };
170
+ /**
171
+ * Runtime participant query for `Communication/_search`.
172
+ *
173
+ * Search semantics:
174
+ * - `subject` scopes which individual communication sections to inspect
175
+ * - `userActorId` and `targetActorId` both match sender OR any recipient
176
+ * - `senderActorId` and `recipientActorId` constrain one side explicitly
177
+ * - `actorId` is the generic sender-or-recipient filter
178
+ * - `*` means "all" for the corresponding operand
179
+ *
180
+ * Canonical prefixes are normalized by shared `gdc-common-utils-ts` helpers:
181
+ * - `did:`
182
+ * - `email:` / `mailto:`
183
+ * - `tel:` / `phone:`
184
+ */
185
+ export type CommunicationParticipantRuntimeSearchInput = {
186
+ searchParams?: Record<string, string | number | boolean | Array<string | number | boolean> | undefined>;
187
+ subject?: string | string[];
188
+ actorId?: string | string[];
189
+ senderActorId?: string | string[];
190
+ recipientActorId?: string | string[];
191
+ userActorId?: string | string[];
192
+ targetActorId?: string | string[];
193
+ periodStart?: string;
194
+ periodEnd?: string;
195
+ requestThid?: string;
196
+ pollOptions?: {
197
+ timeoutMs?: number;
198
+ intervalMs?: number;
199
+ };
200
+ page?: number;
201
+ count?: number;
202
+ };
163
203
  export type ClinicalDateRange = DateRange;
164
204
  export type ClinicalBundleSearchInput = Omit<BundleSearchQuery, 'section' | 'searchParams'> & {
165
205
  section?: string | string[];
@@ -465,6 +505,16 @@ export declare function ingestCommunicationAndUpdateIndexWithDeps(routeCtx: Rout
465
505
  intervalMs?: number;
466
506
  }) => Promise<SubmitAndPollResult>;
467
507
  }): Promise<SubmitAndPollResult>;
508
+ export declare function searchCommunicationParticipantsWithDeps(routeCtx: RouteContext, input: CommunicationParticipantRuntimeSearchInput, deps: {
509
+ communicationSearchPath: (ctx: RouteContext) => string;
510
+ communicationSearchPollPath: (ctx: RouteContext) => string;
511
+ submitAndPoll: (submitPath: string, pollPath: string, payload: {
512
+ thid?: string;
513
+ } & Record<string, unknown>, pollOptions?: {
514
+ timeoutMs?: number;
515
+ intervalMs?: number;
516
+ }) => Promise<SubmitAndPollResult>;
517
+ }): Promise<SubmitAndPollResult>;
468
518
  export declare function searchClinicalBundleWithDeps(routeCtx: RouteContext, input: ClinicalBundleSearchInput, deps: {
469
519
  bundleSearchPath: (ctx: RouteContext) => string;
470
520
  bundleSearchPollPath: (ctx: RouteContext) => string;
@@ -2,7 +2,7 @@
2
2
  import { HealthcareBasicSections, ResourceTypesFhirR4 } from 'gdc-common-utils-ts/constants';
3
3
  import { Format } from 'gdc-common-utils-ts/constants/Schemas';
4
4
  import { RelatedPersonClaim } from 'gdc-common-utils-ts/models/interoperable-claims/related-person-claims';
5
- import { createInteroperableResourceOperationEditor, IndividualOrganizationLifecycleDraft, LicenseOfferSearchEditor, LicenseOrderSearchEditor, InteroperableLifecycleStatuses, LicenseListSearchEditor, } from 'gdc-common-utils-ts';
5
+ import { buildCommunicationParticipantSearchBundle, createInteroperableResourceOperationEditor, IndividualOrganizationLifecycleEditor, LicenseOfferSearchEditor, LicenseOrderSearchEditor, InteroperableLifecycleStatuses, LicenseListSearchEditor, } from 'gdc-common-utils-ts';
6
6
  import { GwCoreLifecycleRequestMethod, GwCoreLifecycleRequestType, GwCoreLifecycleTodo, } from './constants/lifecycle.js';
7
7
  import { buildEmployeeBatchEntry, buildEmployeeSearchBundle, } from 'gdc-sdk-core-ts';
8
8
  export async function createOrganizationEmployeeWithDeps(routeCtx, input, options, deps) {
@@ -117,6 +117,7 @@ export async function disableIndividualOrganizationWithDeps(routeCtx, input, opt
117
117
  routeCtx,
118
118
  requestType: input.dataType || GwCoreLifecycleRequestType.IndividualOrganizationDisable,
119
119
  organizationClaims: input.organizationClaims,
120
+ organizationEditor: input.organizationEditor,
120
121
  resourceId: input.resourceId,
121
122
  thidPrefix: 'individual-organization-disable',
122
123
  });
@@ -127,6 +128,7 @@ export async function purgeIndividualOrganizationWithDeps(routeCtx, input, optio
127
128
  routeCtx,
128
129
  requestType: input.dataType || GwCoreLifecycleRequestType.IndividualOrganizationPurge,
129
130
  organizationClaims: input.organizationClaims,
131
+ organizationEditor: input.organizationEditor,
130
132
  resourceId: input.resourceId,
131
133
  thidPrefix: 'individual-organization-purge',
132
134
  });
@@ -280,6 +282,25 @@ export async function ingestCommunicationAndUpdateIndexWithDeps(routeCtx, input,
280
282
  : payload;
281
283
  return deps.submitAndPoll(deps.individualCommunicationBatchPath(routeCtx, pathFormatSegment), deps.individualCommunicationPollPath(routeCtx, pathFormatSegment), convertedPayload, input.pollOptions);
282
284
  }
285
+ export async function searchCommunicationParticipantsWithDeps(routeCtx, input, deps) {
286
+ const payload = {
287
+ thid: input.requestThid || `communication-search-${createRuntimeUuid()}`,
288
+ body: buildCommunicationParticipantSearchBundle({
289
+ searchParams: input.searchParams,
290
+ subject: input.subject,
291
+ actorId: input.actorId,
292
+ senderActorId: input.senderActorId,
293
+ recipientActorId: input.recipientActorId,
294
+ userActorId: input.userActorId,
295
+ targetActorId: input.targetActorId,
296
+ periodStart: input.periodStart,
297
+ periodEnd: input.periodEnd,
298
+ page: input.page,
299
+ count: input.count,
300
+ }),
301
+ };
302
+ return deps.submitAndPoll(deps.communicationSearchPath(routeCtx), deps.communicationSearchPollPath(routeCtx), payload, input.pollOptions);
303
+ }
283
304
  export async function searchClinicalBundleWithDeps(routeCtx, input, deps) {
284
305
  const query = buildBundleSearchQuery(input);
285
306
  const payload = {
@@ -384,9 +405,10 @@ function buildEmployeeLifecyclePayload(input) {
384
405
  };
385
406
  }
386
407
  function buildIndividualOrganizationLifecyclePayload(input) {
387
- const claims = input.organizationClaims || {};
388
- const payload = new IndividualOrganizationLifecycleDraft()
389
- .setClaims(claims)
408
+ const payload = input.organizationEditor
409
+ ? new IndividualOrganizationLifecycleEditor(input.organizationEditor.getState())
410
+ : new IndividualOrganizationLifecycleEditor().setClaims(input.organizationClaims || {});
411
+ payload
390
412
  .setRequestType(input.requestType)
391
413
  .setThreadId(`${input.thidPrefix}-${createRuntimeUuid()}`);
392
414
  if (input.resourceId) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gdc-sdk-node-ts",
3
- "version": "0.12.0",
3
+ "version": "2.0.2",
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.",
@@ -23,11 +23,15 @@
23
23
  "test:e2e:live-gw:didcomm-plain": "npm run build && RUN_LIVE_GW_E2E=1 LIVE_GW_E2E_TRANSPORT=didcomm-plain node --test tests/live-gw-node-runtime.e2e.test.mjs",
24
24
  "test:e2e:live-gw:legacy-fhir": "npm run build && RUN_LIVE_GW_E2E=1 LIVE_GW_E2E_TRANSPORT=legacy-fhir node --test tests/live-gw-node-runtime.e2e.test.mjs",
25
25
  "test:e2e:live-gw:all": "npm run build && RUN_LIVE_GW_E2E=1 LIVE_GW_E2E_TRANSPORT=all node --test tests/live-gw-node-runtime.e2e.test.mjs",
26
+ "test:e2e:live-gw:host-transaction:clean": "bash ./scripts/run-live-gw-host-transaction-clean.sh",
27
+ "test:e2e:live-profile-runtime:individual": "npm run build && RUN_LIVE_PROFILE_RUNTIME_E2E=1 node --test tests/live-profile-runtime-individual.e2e.test.mjs",
28
+ "test:e2e:live-profile-runtime:professional": "npm run build && RUN_LIVE_PROFILE_RUNTIME_PROFESSIONAL_E2E=1 node --test tests/live-profile-runtime-professional.e2e.test.mjs",
29
+ "test:e2e:live-dialogue:consent-professional": "npm run build && RUN_LIVE_DIALOGUE_CONSENT_PROFESSIONAL_E2E=1 node --test tests/live-dialogue-consent-professional-access.e2e.test.mjs",
26
30
  "test:e2e:live-gw:clean": "bash ./scripts/run-live-gw-clean.sh"
27
31
  },
28
32
  "dependencies": {
29
- "gdc-common-utils-ts": "^1.24.0",
30
- "gdc-sdk-core-ts": "^0.11.0"
33
+ "gdc-common-utils-ts": "^2.0.4",
34
+ "gdc-sdk-core-ts": "^2.0.3"
31
35
  },
32
36
  "devDependencies": {
33
37
  "@types/node": "^20.14.10",