gdc-sdk-node-ts 2.4.23 → 2.4.24

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 CHANGED
@@ -288,9 +288,11 @@ npm run test:e2e:live-gw:all
288
288
 
289
289
  Profile note:
290
290
 
291
- - `didcomm-plain` is the current live baseline implemented by the Node runtime client
291
+ - `didcomm-plain` is the explicit demo-only live profile
292
292
  - `legacy-fhir` exercises raw `application/fhir+json` async batch submission for `org.hl7.fhir.*`
293
293
  - `all` runs every implemented profile from the same suite file
294
+ - each `NodeHttpClient` selects one profile at construction; every facade
295
+ operation and poll uses it and cannot override or downgrade it
294
296
 
295
297
  Run the IPS ingestion/search branch as well:
296
298
 
@@ -127,7 +127,9 @@ export declare class HttpRuntimeClient implements NodeRuntimeClient {
127
127
  */
128
128
  v1Path(ctx: RouteContext | undefined, section: string, format: string, resourceType: string, action: string): string;
129
129
  /**
130
- * Submits a batch payload to a gateway batch endpoint.
130
+ * Submits a batch payload using the transport profile selected once when the
131
+ * runtime client was constructed. Operations cannot downgrade or replace
132
+ * that profile locally.
131
133
  */
132
134
  submitBatch(path: string, payload: SubmitPayload): Promise<SubmitResponse>;
133
135
  /**
@@ -145,6 +147,13 @@ export declare class HttpRuntimeClient implements NodeRuntimeClient {
145
147
  /** Registers one tenant or exact-subject FHIR R5 rest-hook Subscription. */
146
148
  submitFhirR5SubscriptionBatch(ctx: RouteContext, input: FhirR5SubscriptionBatchInput, pollOptions?: PollOptions): Promise<SubmitAndPollResult>;
147
149
  private submitAndPollWithBearerToken;
150
+ /**
151
+ * Enforces the client-owned transport policy. Operation inputs retained for
152
+ * source compatibility may repeat the configured profile, but can never
153
+ * replace it or silently downgrade the wire protection selected at runtime
154
+ * construction.
155
+ */
156
+ private requireConfiguredTransportProfile;
148
157
  /**
149
158
  * Starts the host-side legal-organization verification transaction that GW
150
159
  * CORE forwards to ICA `_verify`.
@@ -547,8 +556,6 @@ export declare class HttpRuntimeClient implements NodeRuntimeClient {
547
556
  pollOptions?: PollOptions;
548
557
  }): Promise<SubmitAndPollResult>;
549
558
  private buildConsentClaimsWithCid;
550
- private pollBatchResponse;
551
- private postJson;
552
559
  private buildHeaders;
553
560
  private fetchWithTimeout;
554
561
  private parseResponseBody;
@@ -1,6 +1,3 @@
1
- // Copyright 2026 Antifraud Services Inc. under the Apache License, Version 2.0.
2
- // Always create JSDoc, do not use strings inline in keys nor values, use types instead, and reuse the data test examples.
3
- import { DIDCOMM_PLAINTEXT_JSON_MEDIA_TYPE, } from 'gdc-common-utils-ts/utils/didcomm-submit';
4
1
  import { buildAppHeaders, createBootstrapFacade, decodeTransportResponse, renderCommunicationOutboxRequest, renderGatewayMessageRequest, renderTransportPollRequest, resolveAppInfo, TransportProfiles, } from 'gdc-sdk-core-ts';
5
2
  import { pollUntilCompleteWithMethod } from './async-polling.js';
6
3
  import { confirmLegalOrganizationOrderWithDeps, HostLifecycleRequestType, HostedTenantLifecycleRequestType, submitHostedTenantLifecycleWithDeps, } from './host-onboarding.js';
@@ -14,8 +11,7 @@ import { confirmOrganizationLicenseOrderWithDeps } from './organization-license-
14
11
  import { startIndividualOrganizationWithDeps } from './individual-start.js';
15
12
  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, addFreeOrganizationEmployeeLicensesWithDeps, requestOrganizationEmployeeLicenseOfferWithDeps, } from './resource-operations.js';
16
13
  import { listOrganizationEmployeeLifecycleWithDeps, provisionOrganizationEmployeeWithDeps, } from './organization-employee-lifecycle.js';
17
- import { submitAndPollWithMethods } from './orchestration/client-port.js';
18
- import { buildRuntimeHeaders, fetchWithTimeout, parseResponseBody, pollBatchResponseWithRuntimeConfig, postJsonWithRuntimeConfig, postRenderedWithRuntimeConfig, } from './runtime-transport.js';
14
+ import { buildRuntimeHeaders, fetchWithTimeout, parseResponseBody, postRenderedWithRuntimeConfig, } from './runtime-transport.js';
19
15
  import { activateOrganizationInGatewayFromIcaProofWithDeps, submitLegalOrganizationCredentialReissuanceWithDeps, submitLegalOrganizationVerificationTransactionWithDeps, submitOrganizationDidBindingWithDeps, } from './runtime-host-submission.js';
20
16
  import { buildGrantProfessionalAccessClaimsWithCid } from './runtime-consent.js';
21
17
  import { RuntimeClientPaths } from './runtime-client-paths.js';
@@ -102,22 +98,38 @@ export class HttpRuntimeClient {
102
98
  return this.paths.v1Path(ctx, section, format, resourceType, action);
103
99
  }
104
100
  /**
105
- * Submits a batch payload to a gateway batch endpoint.
101
+ * Submits a batch payload using the transport profile selected once when the
102
+ * runtime client was constructed. Operations cannot downgrade or replace
103
+ * that profile locally.
106
104
  */
107
105
  async submitBatch(path, payload) {
108
- return this.postJson(path, payload, DIDCOMM_PLAINTEXT_JSON_MEDIA_TYPE);
106
+ const rendered = await renderGatewayMessageRequest(payload, this.transportProfile, this.secureTransportAdapter);
107
+ const response = await postRenderedWithRuntimeConfig(this.transportConfig, path, rendered);
108
+ return { status: response.status, location: response.location, body: response.body };
109
109
  }
110
110
  /**
111
111
  * Polls a batch-response endpoint until the GW reports a terminal state.
112
112
  */
113
113
  async pollUntilComplete(pollPath, request, pollOptions) {
114
- return pollUntilCompleteWithMethod(this.pollBatchResponse.bind(this), pollPath, request, pollOptions);
114
+ return pollUntilCompleteWithMethod(async (path, currentRequest) => {
115
+ const rendered = await renderTransportPollRequest(currentRequest.thid, this.transportProfile, this.secureTransportAdapter);
116
+ const response = await postRenderedWithRuntimeConfig(this.transportConfig, path, rendered);
117
+ return {
118
+ status: response.status,
119
+ body: response.status === 202
120
+ ? response.body
121
+ : response.status >= 200 && response.status < 300
122
+ ? await decodeTransportResponse(response.body, this.transportProfile, this.secureTransportAdapter)
123
+ : response.body,
124
+ retryAfterMs: response.retryAfterMs,
125
+ };
126
+ }, pollPath, request, pollOptions);
115
127
  }
116
128
  /**
117
129
  * Convenience wrapper that performs submit and poll in sequence.
118
130
  */
119
131
  async submitAndPoll(submitPath, pollPath, payload, pollOptions) {
120
- return submitAndPollWithMethods(this, submitPath, pollPath, payload, pollOptions);
132
+ return this.submitClinicalMessageAndPoll(submitPath, pollPath, payload, this.transportProfile, pollOptions);
121
133
  }
122
134
  /** Registers one neutral FHIR R5 topic in the tenant-owned CORE catalog. */
123
135
  submitFhirR5SubscriptionTopicBatch(ctx, topic, pollOptions) {
@@ -138,13 +150,19 @@ export class HttpRuntimeClient {
138
150
  });
139
151
  }
140
152
  async submitAndPollWithBearerToken(bearerToken, submitPath, pollPath, payload, pollOptions) {
141
- const config = { ...this.transportConfig, bearerToken };
142
- const submitted = await postJsonWithRuntimeConfig(config, submitPath, payload, DIDCOMM_PLAINTEXT_JSON_MEDIA_TYPE);
143
- const poll = await pollUntilCompleteWithMethod((path, request) => pollBatchResponseWithRuntimeConfig(config, path, request), pollPath, { thid: String(payload.thid) }, pollOptions);
144
- return {
145
- submit: { status: submitted.status, location: submitted.location, body: submitted.body },
146
- poll,
147
- };
153
+ return this.submitClinicalMessageAndPoll(submitPath, pollPath, payload, this.transportProfile, pollOptions, bearerToken);
154
+ }
155
+ /**
156
+ * Enforces the client-owned transport policy. Operation inputs retained for
157
+ * source compatibility may repeat the configured profile, but can never
158
+ * replace it or silently downgrade the wire protection selected at runtime
159
+ * construction.
160
+ */
161
+ requireConfiguredTransportProfile(requested) {
162
+ if (requested && requested !== this.transportProfile) {
163
+ throw new Error(`Operation transport profile '${requested}' conflicts with configured runtime profile '${this.transportProfile}'.`);
164
+ }
165
+ return this.transportProfile;
148
166
  }
149
167
  /**
150
168
  * Starts the host-side legal-organization verification transaction that GW
@@ -175,9 +193,7 @@ export class HttpRuntimeClient {
175
193
  wrapBundleAsGatewayTransactionMessage: this.wrapBundleAsGatewayTransactionMessage.bind(this),
176
194
  submitPath: this.hostRegistryOrganizationTransactionPath.bind(this),
177
195
  pollPath: this.hostRegistryOrganizationTransactionPollPath.bind(this),
178
- submitAndPoll: this.transportProfile === TransportProfiles.DidcommEncryptedForm
179
- ? (submitPath, pollPath, payload, pollOptions) => this.submitClinicalMessageAndPoll(submitPath, pollPath, payload, this.transportProfile, pollOptions)
180
- : this.submitAndPoll.bind(this),
196
+ submitAndPoll: this.submitAndPoll.bind(this),
181
197
  });
182
198
  }
183
199
  /**
@@ -199,9 +215,7 @@ export class HttpRuntimeClient {
199
215
  wrapBundleAsGatewayTransactionMessage: this.wrapBundleAsGatewayTransactionMessage.bind(this),
200
216
  submitPath: this.hostRegistryOrganizationIssuePath.bind(this),
201
217
  pollPath: this.hostRegistryOrganizationIssuePollPath.bind(this),
202
- submitAndPoll: this.transportProfile === TransportProfiles.DidcommEncryptedForm
203
- ? (submitPath, pollPath, payload, pollOptions) => this.submitClinicalMessageAndPoll(submitPath, pollPath, payload, this.transportProfile, pollOptions)
204
- : this.submitAndPoll.bind(this),
218
+ submitAndPoll: this.submitAndPoll.bind(this),
205
219
  });
206
220
  }
207
221
  /**
@@ -364,7 +378,7 @@ export class HttpRuntimeClient {
364
378
  return createOrganizationEmployeeWithDeps(ctx, input, pollOptions, {
365
379
  employeeBatchPath: this.paths.employeeBatchPath.bind(this.paths),
366
380
  employeePollPath: this.paths.employeePollPath.bind(this.paths),
367
- submitAndPoll: (submitPath, pollPath, payload, options) => this.submitClinicalMessageAndPoll(submitPath, pollPath, prepareEmployeeLifecycleMessageForTransport(payload, this.transportProfile), this.transportProfile, options),
381
+ submitAndPoll: (submitPath, pollPath, payload, options) => this.submitAndPoll(submitPath, pollPath, prepareEmployeeLifecycleMessageForTransport(payload, this.transportProfile), options),
368
382
  });
369
383
  }
370
384
  /** Creates an employee and reserves its activation credential as one SDK workflow. */
@@ -382,9 +396,7 @@ export class HttpRuntimeClient {
382
396
  input,
383
397
  identityDeviceRevokePath: this.paths.identityDeviceRevokePath.bind(this.paths),
384
398
  identityDeviceRevokePollPath: this.paths.identityDeviceRevokePollPath.bind(this.paths),
385
- submitAndPoll: this.transportProfile === TransportProfiles.DidcommEncryptedForm
386
- ? (submitPath, pollPath, payload, pollOptions) => this.submitClinicalMessageAndPoll(submitPath, pollPath, payload, this.transportProfile, pollOptions)
387
- : this.submitAndPoll.bind(this),
399
+ submitAndPoll: this.submitAndPoll.bind(this),
388
400
  });
389
401
  }
390
402
  /** Reserves an employee seat and issues its bounded multi-device activation credential. */
@@ -392,9 +404,7 @@ export class HttpRuntimeClient {
392
404
  return issueOrganizationEmployeeLicenseWithDeps(ctx, input, {
393
405
  identityLicenseIssuePath: this.paths.identityLicenseIssuePath.bind(this.paths),
394
406
  identityLicenseIssuePollPath: this.paths.identityLicenseIssuePollPath.bind(this.paths),
395
- submitAndPoll: this.transportProfile === TransportProfiles.DidcommEncryptedForm
396
- ? (submitPath, pollPath, payload, pollOptions) => this.submitClinicalMessageAndPoll(submitPath, pollPath, payload, this.transportProfile, pollOptions)
397
- : this.submitAndPoll.bind(this),
407
+ submitAndPoll: this.submitAndPoll.bind(this),
398
408
  });
399
409
  }
400
410
  /**
@@ -479,9 +489,7 @@ export class HttpRuntimeClient {
479
489
  return addFreeOrganizationEmployeeLicensesWithDeps(ctx, input, {
480
490
  organizationLicenseOfferCreatePath: this.paths.organizationLicenseOfferCreatePath.bind(this.paths),
481
491
  organizationLicenseOfferCreatePollPath: this.paths.organizationLicenseOfferCreatePollPath.bind(this.paths),
482
- submitAndPoll: this.transportProfile === TransportProfiles.DidcommEncryptedForm
483
- ? (submitPath, pollPath, payload, pollOptions) => this.submitClinicalMessageAndPoll(submitPath, pollPath, payload, this.transportProfile, pollOptions)
484
- : this.submitAndPoll.bind(this),
492
+ submitAndPoll: this.submitAndPoll.bind(this),
485
493
  });
486
494
  }
487
495
  /** Starts the commercial Offer flow for additional professional seats. */
@@ -489,9 +497,7 @@ export class HttpRuntimeClient {
489
497
  return requestOrganizationEmployeeLicenseOfferWithDeps(ctx, input, {
490
498
  organizationLicenseOfferCreatePath: this.paths.organizationLicenseOfferCreatePath.bind(this.paths),
491
499
  organizationLicenseOfferCreatePollPath: this.paths.organizationLicenseOfferCreatePollPath.bind(this.paths),
492
- submitAndPoll: this.transportProfile === TransportProfiles.DidcommEncryptedForm
493
- ? (submitPath, pollPath, payload, pollOptions) => this.submitClinicalMessageAndPoll(submitPath, pollPath, payload, this.transportProfile, pollOptions)
494
- : this.submitAndPoll.bind(this),
500
+ submitAndPoll: this.submitAndPoll.bind(this),
495
501
  });
496
502
  }
497
503
  async searchOrganizationLicenseOffers(ctx, input) {
@@ -540,9 +546,7 @@ export class HttpRuntimeClient {
540
546
  defaultIntervalMs: pollOptions?.intervalMs,
541
547
  hostRegistryOrderBatchPath: this.paths.hostRegistryOrderBatchPath.bind(this.paths),
542
548
  hostRegistryOrderPollPath: this.paths.hostRegistryOrderPollPath.bind(this.paths),
543
- submitAndPoll: this.transportProfile === TransportProfiles.DidcommEncryptedForm
544
- ? (submitPath, pollPath, payload, options) => this.submitClinicalMessageAndPoll(submitPath, pollPath, payload, this.transportProfile, options)
545
- : this.submitAndPoll.bind(this),
549
+ submitAndPoll: this.submitAndPoll.bind(this),
546
550
  });
547
551
  }
548
552
  /**
@@ -850,10 +854,11 @@ export class HttpRuntimeClient {
850
854
  * configured secure transport adapter signs/encrypts DIDComm when enabled.
851
855
  */
852
856
  async requestProfessionalAccess(ctx, input) {
857
+ this.requireConfiguredTransportProfile(input.transportProfile);
853
858
  return requestProfessionalAccessWithDeps(ctx, input, {
854
859
  individualCommunicationBatchPath: this.paths.individualCommunicationBatchPath.bind(this.paths),
855
860
  individualCommunicationPollPath: this.paths.individualCommunicationPollPath.bind(this.paths),
856
- submitAndPoll: (submitPath, pollPath, payload, pollOptions) => this.submitClinicalMessageAndPoll(submitPath, pollPath, payload, input.transportProfile || this.transportProfile, pollOptions),
861
+ submitAndPoll: this.submitAndPoll.bind(this),
857
862
  });
858
863
  }
859
864
  /**
@@ -897,7 +902,7 @@ export class HttpRuntimeClient {
897
902
  */
898
903
  async submitCommunicationOutboxJobAndPoll(ctx, input) {
899
904
  const job = input.communicationJob;
900
- const profile = input.transportProfile || this.transportProfile;
905
+ const profile = this.requireConfiguredTransportProfile(input.transportProfile);
901
906
  const format = normalizeCommunicationPathFormatSegment(input.clinicalFormat || input.pathFormatSegment);
902
907
  const submitPath = this.paths.individualCommunicationBatchPath(ctx, format);
903
908
  const pollPath = this.paths.individualCommunicationPollPath(ctx, format);
@@ -1013,10 +1018,11 @@ export class HttpRuntimeClient {
1013
1018
  * @param input Search parameters such as subject, section, date and included resource types.
1014
1019
  */
1015
1020
  async searchClinicalBundle(ctx, input) {
1021
+ this.requireConfiguredTransportProfile(input.transportProfile);
1016
1022
  return searchClinicalBundleWithDeps(ctx, input, {
1017
1023
  bundleSearchPath: this.paths.individualBundleSearchPath.bind(this.paths),
1018
1024
  bundleSearchPollPath: this.paths.individualBundleSearchPollPath.bind(this.paths),
1019
- submitAndPoll: (submitPath, pollPath, payload, pollOptions) => this.submitClinicalMessageAndPoll(submitPath, pollPath, payload, input.transportProfile || this.transportProfile, pollOptions),
1025
+ submitAndPoll: this.submitAndPoll.bind(this),
1020
1026
  });
1021
1027
  }
1022
1028
  /** Searches tenant digital twins using coded, pseudonymous research claims. */
@@ -1028,7 +1034,7 @@ export class HttpRuntimeClient {
1028
1034
  digitalTwinCompositionPollPath: this.paths.digitalTwinCompositionPollPath.bind(this.paths),
1029
1035
  digitalTwinCommunicationBatchPath: this.paths.digitalTwinCommunicationBatchPath.bind(this.paths),
1030
1036
  digitalTwinCommunicationPollPath: this.paths.digitalTwinCommunicationPollPath.bind(this.paths),
1031
- submitAndPoll: (submitPath, pollPath, payload, pollOptions) => this.submitClinicalMessageAndPoll(submitPath, pollPath, payload, this.transportProfile, pollOptions, input.accessToken),
1037
+ submitAndPoll: (submitPath, pollPath, payload, pollOptions) => this.submitAndPollWithBearerToken(input.accessToken, submitPath, pollPath, payload, pollOptions),
1032
1038
  });
1033
1039
  }
1034
1040
  /** Saves one tagged researcher working copy without mutating the canonical twin. */
@@ -1040,7 +1046,7 @@ export class HttpRuntimeClient {
1040
1046
  digitalTwinCompositionPollPath: this.paths.digitalTwinCompositionPollPath.bind(this.paths),
1041
1047
  digitalTwinCommunicationBatchPath: this.paths.digitalTwinCommunicationBatchPath.bind(this.paths),
1042
1048
  digitalTwinCommunicationPollPath: this.paths.digitalTwinCommunicationPollPath.bind(this.paths),
1043
- submitAndPoll: (submitPath, pollPath, payload, pollOptions) => this.submitClinicalMessageAndPoll(submitPath, pollPath, payload, this.transportProfile, pollOptions, input.accessToken),
1049
+ submitAndPoll: (submitPath, pollPath, payload, pollOptions) => this.submitAndPollWithBearerToken(input.accessToken, submitPath, pollPath, payload, pollOptions),
1044
1050
  });
1045
1051
  }
1046
1052
  /** Materializes one selected pseudonymous research subject as a summary Bundle. */
@@ -1052,7 +1058,7 @@ export class HttpRuntimeClient {
1052
1058
  digitalTwinCompositionPollPath: this.paths.digitalTwinCompositionPollPath.bind(this.paths),
1053
1059
  digitalTwinCommunicationBatchPath: this.paths.digitalTwinCommunicationBatchPath.bind(this.paths),
1054
1060
  digitalTwinCommunicationPollPath: this.paths.digitalTwinCommunicationPollPath.bind(this.paths),
1055
- submitAndPoll: (submitPath, pollPath, payload, pollOptions) => this.submitClinicalMessageAndPoll(submitPath, pollPath, payload, this.transportProfile, pollOptions, input.accessToken),
1061
+ submitAndPoll: (submitPath, pollPath, payload, pollOptions) => this.submitAndPollWithBearerToken(input.accessToken, submitPath, pollPath, payload, pollOptions),
1056
1062
  });
1057
1063
  }
1058
1064
  /**
@@ -1090,12 +1096,6 @@ export class HttpRuntimeClient {
1090
1096
  buildConsentClaimsWithCid(input) {
1091
1097
  return buildGrantProfessionalAccessClaimsWithCid(input, runtimeUuid);
1092
1098
  }
1093
- async pollBatchResponse(path, request) {
1094
- return pollBatchResponseWithRuntimeConfig(this.transportConfig, path, request);
1095
- }
1096
- async postJson(path, payload, contentType) {
1097
- return postJsonWithRuntimeConfig(this.transportConfig, path, payload, contentType);
1098
- }
1099
1099
  buildHeaders(contentType) {
1100
1100
  return buildRuntimeHeaders(this.transportConfig, contentType);
1101
1101
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gdc-sdk-node-ts",
3
- "version": "2.4.23",
3
+ "version": "2.4.24",
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.",