gdc-sdk-node-ts 2.4.43 → 2.4.45

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
@@ -650,13 +650,13 @@ modules below.
650
650
  - types: `SmartTokenRequestInput`, `SmartTokenExchangeResult`
651
651
  - function: `requestSmartTokenWithDeps(...)`
652
652
  - [`src/resource-operations.ts`](src/resource-operations.ts)
653
- - types: `OrganizationEmployeeCreationInput`, `IpsOrFhirImportInput`, `RelatedPersonUpsertInput`, `CommunicationIngestionInput`, `ClinicalDateRange`, `ClinicalBundleSearchInput`, `ConsentActorTargetInput`, `GrantProfessionalAccessInput`, `GrantProfessionalAccessResult`, `DigitalTwinSecondaryUseConsentInput`, `DigitalTwinSubjectLinkPurgeInput`
654
- - functions: `createOrganizationEmployeeWithDeps(...)`, `importIpsOrFhirAndUpdateIndexWithDeps(...)`, `upsertRelatedPersonAndPollWithDeps(...)`, `ingestCommunicationAndUpdateIndexWithDeps(...)`, `searchClinicalBundleWithDeps(...)`, `searchLatestIpsWithDeps(...)`, `grantProfessionalAccessWithDeps(...)`, `setDigitalTwinSecondaryUseConsentWithDeps(...)`, `purgeDigitalTwinSubjectLinkWithDeps(...)`
653
+ - types: `OrganizationEmployeeCreationInput`, `IpsOrFhirImportInput`, `RelatedPersonUpsertInput`, `CommunicationIngestionInput`, `ClinicalDateRange`, `ClinicalBundleSearchInput`, `ConsentActorTargetInput`, `GrantProfessionalAccessInput`, `GrantProfessionalAccessResult`, `DigitalTwinSecondaryUseConsentInput`, `DigitalTwinSubjectLinkPurgeInput`, `SubjectConsentSearchInput`
654
+ - functions: `createOrganizationEmployeeWithDeps(...)`, `importIpsOrFhirAndUpdateIndexWithDeps(...)`, `upsertRelatedPersonAndPollWithDeps(...)`, `ingestCommunicationAndUpdateIndexWithDeps(...)`, `searchClinicalBundleWithDeps(...)`, `searchSubjectConsentsWithDeps(...)`, `searchLatestIpsWithDeps(...)`, `grantProfessionalAccessWithDeps(...)`, `setDigitalTwinSecondaryUseConsentWithDeps(...)`, `purgeDigitalTwinSubjectLinkWithDeps(...)`
655
655
  - [`src/digital-twin.ts`](src/digital-twin.ts)
656
656
  - types: `DigitalTwinSearchInput`, `DigitalTwinSelectionInput`, `DigitalTwinResearchTag`, `DigitalTwinMaterializationInput`
657
657
  - functions: `searchDigitalTwinsWithDeps(...)`, `saveDigitalTwinSelectionWithDeps(...)`, `materializeDigitalTwinWithDeps(...)`
658
658
  - [`src/orchestration/digital-twin-sdk.ts`](src/orchestration/digital-twin-sdk.ts)
659
- - class: `DigitalTwinSdk` (`requestSmartToken`, `search`, `saveSelection`, `materialize`)
659
+ - class: `DigitalTwinSdk` (`requestSmartToken`, `search`, `saveSelection`, `searchSelections`, `materialize`); both searches expose `ResearchSubject` through FHIR Parameters, with its canonical internal Composition available as `composition`
660
660
  - [`src/session.ts`](src/session.ts)
661
661
  - types: `NodeCapability`, `NodeActorSessionContext`, `ActorSessionContext`
662
662
  - classes: `ActorSession`, `NodeActorSession`
@@ -7,7 +7,7 @@ export type DigitalTwinFhirFormat = 'org.hl7.fhir.r4' | 'org.hl7.fhir.api';
7
7
  export declare function isDigitalTwinSubjectId(value: unknown): value is string;
8
8
  /** Rejects operational DIDs and malformed or caller-invented subject shapes. */
9
9
  export declare function assertDigitalTwinSubjectId(value: unknown): asserts value is string;
10
- /** Search parameters added by the digital-twin Composition profile. */
10
+ /** Search parameters evaluated against a ResearchSubject's canonical Composition index. */
11
11
  export declare const DigitalTwinSearchParameter: Readonly<{
12
12
  Section: "section";
13
13
  DateFrom: "date-from";
@@ -20,7 +20,8 @@ export type DigitalTwinSearchInput = {
20
20
  accessToken?: string;
21
21
  thid?: string;
22
22
  format?: DigitalTwinFhirFormat;
23
- resourceType?: string;
23
+ /** Public twin search resource; exposed for low-level request inspection only. */
24
+ resourceType?: 'ResearchSubject';
24
25
  /** One or more IPS section tokens. Basic search uses OR across sections. */
25
26
  sections?: readonly string[];
26
27
  /** Inclusive clinical-event lower bound as ISO date or dateTime. */
@@ -33,11 +34,19 @@ export type DigitalTwinSearchInput = {
33
34
  filters?: Readonly<Record<string, string | readonly string[] | undefined>>;
34
35
  pollOptions?: PollOptions;
35
36
  };
36
- /** One pseudonymous Composition returned by a digital-twin search. */
37
+ /**
38
+ * One public ResearchSubject digital twin returned by search.
39
+ *
40
+ * `composition` is the canonical Composition GW uses as the aggregate's
41
+ * internal index document. It joins the ResearchSubject to the projected
42
+ * clinical resources later returned by `ResearchSubject/$summary`.
43
+ */
37
44
  export type DigitalTwinSearchMatch = Record<string, unknown> & {
45
+ resourceType?: 'ResearchSubject';
38
46
  id?: string;
39
47
  [CompositionClaim.Subject]: string;
40
48
  [CompositionClaim.Section]?: string;
49
+ composition?: Record<string, unknown>;
41
50
  meta?: {
42
51
  tag?: DigitalTwinResearchTag[];
43
52
  };
@@ -120,11 +129,15 @@ export type DigitalTwinRuntimeDeps = {
120
129
  body: Record<string, unknown>;
121
130
  }, pollOptions?: PollOptions) => Promise<SubmitAndPollResult>;
122
131
  };
123
- /** Opens the GW async response and exposes the matched Compositions directly. */
132
+ /** Opens the GW async response and exposes the matched ResearchSubjects directly. */
124
133
  export declare function readDigitalTwinSearchResult(operation: SubmitAndPollResult): DigitalTwinSearchResult;
125
134
  /** Persists one tagged researcher working copy through `digitaltwin/Composition/_batch`. */
126
135
  export declare function saveDigitalTwinSelectionWithDeps(ctx: RouteContext, input: DigitalTwinSelectionInput, deps: DigitalTwinRuntimeDeps): Promise<SubmitAndPollResult>;
127
- /** Searches the tenant digital-twin index through its public asynchronous route. */
136
+ /**
137
+ * Searches ResearchSubject digital twins through the public asynchronous route.
138
+ * GW filters their canonical Composition index documents internally; callers
139
+ * never switch to a separate public Composition search surface.
140
+ */
128
141
  export declare function searchDigitalTwinsWithDeps(ctx: RouteContext, input: DigitalTwinSearchInput, deps: DigitalTwinRuntimeDeps): Promise<SubmitAndPollResult>;
129
142
  /** Materializes one selected pseudonymous twin as a research summary Bundle. */
130
143
  export declare function materializeDigitalTwinWithDeps(ctx: RouteContext, input: DigitalTwinMaterializationInput, deps: DigitalTwinRuntimeDeps): Promise<SubmitAndPollResult>;
@@ -13,7 +13,7 @@ export function assertDigitalTwinSubjectId(value) {
13
13
  throw new Error('Digital twin subject must be a valid urn:uuid identifier.');
14
14
  }
15
15
  }
16
- /** Search parameters added by the digital-twin Composition profile. */
16
+ /** Search parameters evaluated against a ResearchSubject's canonical Composition index. */
17
17
  export const DigitalTwinSearchParameter = Object.freeze({
18
18
  Section: 'section',
19
19
  DateFrom: 'date-from',
@@ -59,7 +59,7 @@ function normalizeResearchTags(tags) {
59
59
  }
60
60
  return normalized;
61
61
  }
62
- /** Opens the GW async response and exposes the matched Compositions directly. */
62
+ /** Opens the GW async response and exposes the matched ResearchSubjects directly. */
63
63
  export function readDigitalTwinSearchResult(operation) {
64
64
  const body = operation?.poll?.body;
65
65
  const responseEntries = Array.isArray(body?.data)
@@ -129,10 +129,14 @@ export async function saveDigitalTwinSelectionWithDeps(ctx, input, deps) {
129
129
  : { resourceType: 'Bundle', type: 'batch', entry: [entry] },
130
130
  }, input.pollOptions);
131
131
  }
132
- /** Searches the tenant digital-twin index through its public asynchronous route. */
132
+ /**
133
+ * Searches ResearchSubject digital twins through the public asynchronous route.
134
+ * GW filters their canonical Composition index documents internally; callers
135
+ * never switch to a separate public Composition search surface.
136
+ */
133
137
  export async function searchDigitalTwinsWithDeps(ctx, input, deps) {
134
138
  const format = input.format || 'org.hl7.fhir.r4';
135
- const resourceType = String(input.resourceType || 'Composition').trim();
139
+ const resourceType = String(input.resourceType || 'ResearchSubject').trim();
136
140
  if (!resourceType)
137
141
  throw new Error('Digital twin resourceType is required.');
138
142
  const usesBasicSearch = Boolean(input.sections || input.dateFrom || input.dateTo || input.text);
@@ -2,6 +2,7 @@ import { type ConsentRule } from 'gdc-common-utils-ts/models/consent-rule';
2
2
  import type { ActiveConsentProvider } from 'gdc-sdk-core-ts';
3
3
  import type { RouteContext } from './individual-onboarding.js';
4
4
  import { type NodeRuntimeClient } from './orchestration/client-port.js';
5
+ import type { SubjectConsentSearchInput } from './resource-operations.js';
5
6
  /**
6
7
  * GW-backed implementation of the runtime-neutral ActiveConsentProvider.
7
8
  *
@@ -13,7 +14,7 @@ export declare class GatewayActiveConsentProvider implements ActiveConsentProvid
13
14
  private readonly routeContext;
14
15
  constructor(client: NodeRuntimeClient, routeContext: RouteContext);
15
16
  /** Loads and normalizes the active Consent rules owned by one subject. */
16
- getActiveConsentsForSubject(subject: string): Promise<ConsentRule[]>;
17
+ getActiveConsentsForSubject(subject: string, filters?: Omit<SubjectConsentSearchInput, 'subject' | 'pollOptions'>): Promise<ConsentRule[]>;
17
18
  }
18
19
  /** Extracts canonical Consent claim maps from current GW Bundle wrappers. */
19
20
  export declare function extractConsentRules(value: unknown): ConsentRule[];
@@ -1,5 +1,4 @@
1
1
  // Copyright 2026 Antifraud Services Inc. under the Apache License, Version 2.0.
2
- import { ResourceTypesFhirR4 } from 'gdc-common-utils-ts/constants/fhir-resource-types';
3
2
  import { ClaimConsent } from 'gdc-common-utils-ts/models/consent-rule';
4
3
  import { isConsentRuleActive } from 'gdc-common-utils-ts/utils/consent';
5
4
  import { requireClientMethod } from './orchestration/client-port.js';
@@ -15,15 +14,12 @@ export class GatewayActiveConsentProvider {
15
14
  this.routeContext = routeContext;
16
15
  }
17
16
  /** Loads and normalizes the active Consent rules owned by one subject. */
18
- async getActiveConsentsForSubject(subject) {
17
+ async getActiveConsentsForSubject(subject, filters = {}) {
19
18
  const normalizedSubject = String(subject || '').trim();
20
19
  if (!normalizedSubject.startsWith('did:')) {
21
20
  throw new Error('Active Consent lookup requires a subject DID.');
22
21
  }
23
- const result = await requireClientMethod(this.client, 'searchClinicalBundle')(this.routeContext, {
24
- subject: normalizedSubject,
25
- includedTypes: [ResourceTypesFhirR4.Consent],
26
- });
22
+ const result = await requireClientMethod(this.client, 'searchSubjectConsents')(this.routeContext, { subject: normalizedSubject, ...filters });
27
23
  return extractConsentRules(result.poll.body)
28
24
  .filter((rule) => isConsentRuleActive(rule, { subject: normalizedSubject }));
29
25
  }
@@ -12,7 +12,7 @@ import { type SmartTokenRequestInput } from './smart-token.js';
12
12
  import { type EmployeeDeviceActivationRequestInput, type EmployeeDeviceActivationResult, type EmployeeDeviceOtpRecoveryInput, type EmployeeDeviceOtpRecoveryResult, type EmployeeDeviceRevocationInput } from './device-activation.js';
13
13
  import { type OrganizationLicenseOrderConfirmInput } from './organization-license-order.js';
14
14
  import { type IndividualOrganizationBootstrapInput, type IndividualOrganizationStartResult } from './individual-start.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
+ 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 SubjectConsentSearchInput, 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';
16
16
  import type { LegalOrganizationOrderInput } from './host-onboarding.js';
17
17
  import type { SmartTokenExchangeResult } from './smart-token.js';
18
18
  import { type OrganizationEmployeeProvisioningInput, type OrganizationEmployeeProvisioningResult } from './organization-employee-lifecycle.js';
@@ -447,6 +447,8 @@ export declare class HttpRuntimeClient implements NodeRuntimeClient {
447
447
  setDigitalTwinSecondaryUseConsent(ctx: RouteContext, input: DigitalTwinSecondaryUseConsentInput): Promise<DigitalTwinSecondaryUseConsentResult>;
448
448
  /** Offboards the subject from this index provider without deleting the anonymous twin. */
449
449
  purgeDigitalTwinSubjectLink(ctx: RouteContext, input: DigitalTwinSubjectLinkPurgeInput): Promise<DigitalTwinSubjectLinkPurgeResult>;
450
+ /** Reads the subject-owned Consent records through Communication -> Subject/_search. */
451
+ searchSubjectConsents(ctx: RouteContext, input: SubjectConsentSearchInput): Promise<SubmitAndPollResult>;
450
452
  /**
451
453
  * Closes an existing professional consent by setting its period end and
452
454
  * resubmitting the updated consent resource.
@@ -10,7 +10,7 @@ import { activateEmployeeDeviceWithActivationCodeWithDeps, activateEmployeeDevic
10
10
  import { extractOfferIdFromResponseBody, extractOfferPreviewFromResponseBody, } from './order-offer-summary.js';
11
11
  import { confirmOrganizationLicenseOrderWithDeps } from './organization-license-order.js';
12
12
  import { startIndividualOrganizationWithDeps } from './individual-start.js';
13
- import { createOrganizationEmployeeWithDeps, issueOrganizationEmployeeLicenseWithDeps, disableIndividualMemberWithDeps, disableIndividualOrganizationWithDeps, disableOrganizationEmployeeWithDeps, listIndividualLicenseOffersWithDeps, listIndividualLicenseOrdersWithDeps, listIndividualLicensesWithDeps, addFreeIndividualMemberLicensesWithDeps, issueIndividualMemberLicenseWithDeps, transitionIndividualMemberLicenseWithDeps, listOrganizationLicenseOffersWithDeps, listOrganizationLicenseOrdersWithDeps, listOrganizationLicensesWithDeps, grantProfessionalAccessWithDeps, setDigitalTwinSecondaryUseConsentWithDeps, purgeDigitalTwinSubjectLinkWithDeps, 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';
13
+ import { createOrganizationEmployeeWithDeps, issueOrganizationEmployeeLicenseWithDeps, disableIndividualMemberWithDeps, disableIndividualOrganizationWithDeps, disableOrganizationEmployeeWithDeps, listIndividualLicenseOffersWithDeps, listIndividualLicenseOrdersWithDeps, listIndividualLicensesWithDeps, addFreeIndividualMemberLicensesWithDeps, issueIndividualMemberLicenseWithDeps, transitionIndividualMemberLicenseWithDeps, listOrganizationLicenseOffersWithDeps, listOrganizationLicenseOrdersWithDeps, listOrganizationLicensesWithDeps, grantProfessionalAccessWithDeps, setDigitalTwinSecondaryUseConsentWithDeps, purgeDigitalTwinSubjectLinkWithDeps, searchSubjectConsentsWithDeps, 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';
14
14
  import { listOrganizationEmployeeLifecycleWithDeps, provisionOrganizationEmployeeWithDeps, } from './organization-employee-lifecycle.js';
15
15
  import { buildRuntimeHeaders, fetchWithTimeout, parseResponseBody, postRenderedWithRuntimeConfig, } from './runtime-transport.js';
16
16
  import { activateOrganizationInGatewayFromIcaProofWithDeps, submitLegalOrganizationCredentialReissuanceWithDeps, submitLegalOrganizationVerificationTransactionWithDeps, submitOrganizationDidBindingWithDeps, } from './runtime-host-submission.js';
@@ -860,6 +860,14 @@ export class HttpRuntimeClient {
860
860
  submitAndPoll: this.submitAndPoll.bind(this),
861
861
  });
862
862
  }
863
+ /** Reads the subject-owned Consent records through Communication -> Subject/_search. */
864
+ async searchSubjectConsents(ctx, input) {
865
+ return searchSubjectConsentsWithDeps(ctx, input, {
866
+ individualCommunicationBatchPath: this.paths.individualCommunicationBatchPath.bind(this.paths),
867
+ individualCommunicationPollPath: this.paths.individualCommunicationPollPath.bind(this.paths),
868
+ submitAndPoll: this.submitAndPoll.bind(this),
869
+ });
870
+ }
863
871
  /**
864
872
  * Closes an existing professional consent by setting its period end and
865
873
  * resubmitting the updated consent resource.
@@ -19,7 +19,7 @@ import type { OrganizationLicenseOrderConfirmInput } from '../organization-licen
19
19
  import type { SmartTokenExchangeResult, SmartTokenRequestInput } from '../smart-token.js';
20
20
  import type { DigitalTwinMaterializationInput, DigitalTwinSearchInput, DigitalTwinSelectionInput } from '../digital-twin.js';
21
21
  import type { AuthorizedIndividualSubject, AuthorizedIndividualSubjectDirectoryInput } from '../authorized-subject-directory.js';
22
- import type { CommunicationIngestionInput, BlockchainArtifactRegistrationInput, CommunicationParticipantRuntimeSearchInput, ClinicalBundleSearchInput, ClinicalSectionUpdateInput, ClinicalSummaryReadResult, ClinicalSummaryRequestInput, ClinicalSummaryUpdateInput, VitalSignBatchCommunicationFromSearchResponseInput, DigitalTwinGenerationInput, DigitalTwinSecondaryUseConsentInput, DigitalTwinSecondaryUseConsentResult, DigitalTwinSubjectLinkPurgeInput, DigitalTwinSubjectLinkPurgeResult, GrantProfessionalAccessInput, GrantProfessionalAccessResult, IndividualMemberLifecycleInput, IndividualMemberLicenseAddInput, IndividualMemberLicenseInvitationInput, IndividualMemberLicenseTransitionInput, IpsOrFhirImportInput, OrganizationEmployeeCreationInput, OrganizationEmployeeLicenseAddInput, OrganizationEmployeeLicenseOfferInput, OrganizationEmployeeLicenseInvitationInput, OrganizationEmployeeLifecycleInput, OrganizationEmployeeSearchInput, ProfessionalAccessRequestInput, ProfessionalAccessRequestResult, RevokeProfessionalAccessInput, RevokeProfessionalAccessResult, RelatedPersonUpsertInput } from '../resource-operations.js';
22
+ import type { CommunicationIngestionInput, BlockchainArtifactRegistrationInput, CommunicationParticipantRuntimeSearchInput, ClinicalBundleSearchInput, ClinicalSectionUpdateInput, ClinicalSummaryReadResult, ClinicalSummaryRequestInput, ClinicalSummaryUpdateInput, VitalSignBatchCommunicationFromSearchResponseInput, DigitalTwinGenerationInput, DigitalTwinSecondaryUseConsentInput, DigitalTwinSecondaryUseConsentResult, DigitalTwinSubjectLinkPurgeInput, DigitalTwinSubjectLinkPurgeResult, GrantProfessionalAccessInput, GrantProfessionalAccessResult, IndividualMemberLifecycleInput, IndividualMemberLicenseAddInput, IndividualMemberLicenseInvitationInput, IndividualMemberLicenseTransitionInput, IpsOrFhirImportInput, OrganizationEmployeeCreationInput, OrganizationEmployeeLicenseAddInput, OrganizationEmployeeLicenseOfferInput, OrganizationEmployeeLicenseInvitationInput, OrganizationEmployeeLifecycleInput, OrganizationEmployeeSearchInput, ProfessionalAccessRequestInput, ProfessionalAccessRequestResult, RevokeProfessionalAccessInput, RevokeProfessionalAccessResult, RelatedPersonUpsertInput, SubjectConsentSearchInput } from '../resource-operations.js';
23
23
  /**
24
24
  * Shared node-runtime activation input.
25
25
  *
@@ -140,6 +140,7 @@ export type RuntimeClient = {
140
140
  generateDigitalTwinFromSubjectData?: (ctx: RouteContext, input: DigitalTwinGenerationInput) => Promise<SubmitAndPollResult>;
141
141
  setDigitalTwinSecondaryUseConsent?: (ctx: RouteContext, input: DigitalTwinSecondaryUseConsentInput) => Promise<DigitalTwinSecondaryUseConsentResult>;
142
142
  purgeDigitalTwinSubjectLink?: (ctx: RouteContext, input: DigitalTwinSubjectLinkPurgeInput) => Promise<DigitalTwinSubjectLinkPurgeResult>;
143
+ searchSubjectConsents?: (ctx: RouteContext, input: SubjectConsentSearchInput) => Promise<SubmitAndPollResult>;
143
144
  searchClinicalBundle?: (ctx: RouteContext, input: ClinicalBundleSearchInput) => Promise<SubmitAndPollResult>;
144
145
  searchDigitalTwins?: (ctx: RouteContext, input: DigitalTwinSearchInput) => Promise<SubmitAndPollResult>;
145
146
  saveDigitalTwinSelection?: (ctx: RouteContext, input: DigitalTwinSelectionInput) => Promise<SubmitAndPollResult>;
@@ -11,7 +11,9 @@ export declare class DigitalTwinSdk {
11
11
  /** Requests the SMART token used by subsequent digital-twin operations. */
12
12
  requestSmartToken(input: SmartTokenRequestInput): Promise<SmartTokenExchangeResult>;
13
13
  /**
14
- * Searches pseudonymous records and exposes matched Compositions directly.
14
+ * Searches the public `ResearchSubject/_search` aggregate with FHIR
15
+ * Parameters. Each match includes the canonical Composition GW uses
16
+ * internally to index that ResearchSubject and connect its resources.
15
17
  *
16
18
  * MVP basic search supplies `sections`, `dateFrom`, optional `dateTo`, and
17
19
  * `text`. GW resolves an omitted `dateTo` to its current time, applies OR
@@ -24,7 +26,11 @@ export declare class DigitalTwinSdk {
24
26
  * The canonical clinical twin is never modified.
25
27
  */
26
28
  saveSelection(ctx: RouteContext, input: DigitalTwinSelectionInput): Promise<SubmitAndPollResult>;
27
- /** Reopens only this employee's saved selections for one exact custom tag. */
29
+ /**
30
+ * Reopens this employee's saved ResearchSubjects through the same public
31
+ * route. The tag is combined with an author filter bound to the actor DID;
32
+ * GW verifies that author against the authenticated SMART `sub`.
33
+ */
28
34
  searchSelections(ctx: RouteContext, input: Omit<DigitalTwinSearchInput, 'filters'> & {
29
35
  section: string;
30
36
  tag: Readonly<{
@@ -16,11 +16,18 @@ export class DigitalTwinSdk {
16
16
  throw new Error('DigitalTwinSdk actorDid must match the actor session.');
17
17
  }
18
18
  const actorDid = this.researcherDid || requestedActorDid;
19
+ const requestedScopes = input.scopes?.length
20
+ ? input.scopes
21
+ : [ServiceCapability.DigitalTwinReader];
19
22
  const result = await requireClientMethod(this.client, 'requestSmartToken')({
20
23
  ...input,
21
24
  actorDid,
22
25
  purpose: input.purpose || HealthcareConsentPurposes.Research,
23
- scopes: input.scopes?.length ? input.scopes : [ServiceCapability.DigitalTwinReader],
26
+ // GW root scopes are explicit queries. Complete the common bare SDK
27
+ // capability so callers do not have to know the SMART wire syntax.
28
+ scopes: requestedScopes.map((scope) => scope === ServiceCapability.DigitalTwinReader
29
+ ? `${scope}?subject=*`
30
+ : scope),
24
31
  });
25
32
  if (result.accessToken)
26
33
  this.smartAccessToken = result.accessToken;
@@ -29,7 +36,9 @@ export class DigitalTwinSdk {
29
36
  return result;
30
37
  }
31
38
  /**
32
- * Searches pseudonymous records and exposes matched Compositions directly.
39
+ * Searches the public `ResearchSubject/_search` aggregate with FHIR
40
+ * Parameters. Each match includes the canonical Composition GW uses
41
+ * internally to index that ResearchSubject and connect its resources.
33
42
  *
34
43
  * MVP basic search supplies `sections`, `dateFrom`, optional `dateTo`, and
35
44
  * `text`. GW resolves an omitted `dateTo` to its current time, applies OR
@@ -59,6 +68,7 @@ export class DigitalTwinSdk {
59
68
  }
60
69
  const operation = await requireClientMethod(this.client, 'searchDigitalTwins')(ctx, {
61
70
  ...input,
71
+ resourceType: 'ResearchSubject',
62
72
  filters,
63
73
  accessToken: input.accessToken || this.smartAccessToken,
64
74
  });
@@ -80,7 +90,11 @@ export class DigitalTwinSdk {
80
90
  accessToken: input.accessToken || this.smartAccessToken,
81
91
  });
82
92
  }
83
- /** Reopens only this employee's saved selections for one exact custom tag. */
93
+ /**
94
+ * Reopens this employee's saved ResearchSubjects through the same public
95
+ * route. The tag is combined with an author filter bound to the actor DID;
96
+ * GW verifies that author against the authenticated SMART `sub`.
97
+ */
84
98
  searchSelections(ctx, input) {
85
99
  const section = String(input.section || '').trim();
86
100
  const system = String(input.tag?.system || '').trim();
@@ -138,7 +138,11 @@ export declare class IndividualControllerSdk {
138
138
  * data already shared for research.
139
139
  */
140
140
  purgeDigitalTwinSubjectLink(ctx: RouteContext, input: DigitalTwinSubjectLinkPurgeInput): Promise<DigitalTwinSubjectLinkPurgeResult>;
141
- /** Returns the current decision for one portal, software or research study. */
141
+ /**
142
+ * Returns the current decision for one portal, software or research study.
143
+ * Consent is read through Communication -> individual `Subject/_search`;
144
+ * this does not query a clinical Bundle or the twin ResearchSubject index.
145
+ */
142
146
  getDigitalTwinSecondaryUseConsentStatus(ctx: RouteContext, input: Readonly<{
143
147
  subjectDid: string;
144
148
  indexProviderOrganizationDid: string;
@@ -208,11 +208,20 @@ export class IndividualControllerSdk {
208
208
  assertFacadeCapability(this.capabilities, ActorCapabilities.IndividualGenerateDigitalTwin, ActorKinds.IndividualController, 'purgeDigitalTwinSubjectLink');
209
209
  return requireClientMethod(this.client, 'purgeDigitalTwinSubjectLink')(ctx, input);
210
210
  }
211
- /** Returns the current decision for one portal, software or research study. */
211
+ /**
212
+ * Returns the current decision for one portal, software or research study.
213
+ * Consent is read through Communication -> individual `Subject/_search`;
214
+ * this does not query a clinical Bundle or the twin ResearchSubject index.
215
+ */
212
216
  async getDigitalTwinSecondaryUseConsentStatus(ctx, input) {
213
217
  assertFacadeCapability(this.capabilities, ActorCapabilities.IndividualGenerateDigitalTwin, ActorKinds.IndividualController, 'getDigitalTwinSecondaryUseConsentStatus');
214
218
  const consents = await new GatewayActiveConsentProvider(this.client, ctx)
215
- .getActiveConsentsForSubject(input.subjectDid);
219
+ .getActiveConsentsForSubject(input.subjectDid, {
220
+ actorIdentifier: input.indexProviderOrganizationDid,
221
+ purpose: HealthcareConsentPurposes.Research,
222
+ action: ServiceCapability.DigitalTwinReader,
223
+ sourceReference: input.researchUseReference,
224
+ });
216
225
  const researchUseReference = String(input.researchUseReference || '').trim();
217
226
  if (!researchUseReference)
218
227
  throw new Error('researchUseReference is required to identify the portal, software or study consent.');
@@ -0,0 +1,16 @@
1
+ import type { VerifiableCredentialV2 } from 'gdc-common-utils-ts/models/verifiable-credential';
2
+ import type { IWallet, WalletExecutionContext, WalletKeySelection } from 'gdc-sdk-core-ts';
3
+ /** Input required to add one human-authorizer proof to the out-of-band VC. */
4
+ export type SignOrganizationRegistrationAuthorizationInput = Readonly<{
5
+ credential: VerifiableCredentialV2;
6
+ wallet: IWallet;
7
+ context: WalletExecutionContext;
8
+ key: WalletKeySelection;
9
+ verificationMethod: string;
10
+ createdAt?: string;
11
+ }>;
12
+ /**
13
+ * Adds one detached JWS proof made by the already-unlocked professional
14
+ * profile. The browser never receives the private key or clear wallet seed.
15
+ */
16
+ export declare function signOrganizationRegistrationAuthorizationCredential(input: SignOrganizationRegistrationAuthorizationInput): Promise<VerifiableCredentialV2>;
@@ -0,0 +1,34 @@
1
+ import { canonicalizeOrganizationRegistrationAuthorizationCredential, } from 'gdc-common-utils-ts/utils/organization-registration-authorization';
2
+ /**
3
+ * Adds one detached JWS proof made by the already-unlocked professional
4
+ * profile. The browser never receives the private key or clear wallet seed.
5
+ */
6
+ export async function signOrganizationRegistrationAuthorizationCredential(input) {
7
+ if (!input.wallet.signDetachedJws) {
8
+ throw new Error('Wallet does not support detached organization authorization proofs.');
9
+ }
10
+ const verificationMethod = String(input.verificationMethod || '').trim();
11
+ if (!verificationMethod)
12
+ throw new Error('Organization authorization proof requires verificationMethod.');
13
+ const payload = canonicalizeOrganizationRegistrationAuthorizationCredential(input.credential);
14
+ const jws = await input.wallet.signDetachedJws(input.context, {
15
+ payload,
16
+ header: { typ: 'application/vc+ld+json' },
17
+ key: input.key,
18
+ });
19
+ const existingProofs = Array.isArray(input.credential.proof)
20
+ ? input.credential.proof
21
+ : input.credential.proof
22
+ ? [input.credential.proof]
23
+ : [];
24
+ return {
25
+ ...input.credential,
26
+ proof: [...existingProofs, {
27
+ type: 'JsonWebSignature2020',
28
+ created: input.createdAt || new Date().toISOString(),
29
+ proofPurpose: 'contractAgreement',
30
+ verificationMethod,
31
+ jws,
32
+ }],
33
+ };
34
+ }
@@ -532,6 +532,18 @@ export type DigitalTwinSubjectLinkPurgeInput = {
532
532
  };
533
533
  /** Async GW result for a subject/twin binding purge. */
534
534
  export type DigitalTwinSubjectLinkPurgeResult = SubmitAndPollResult;
535
+ /** Input for reading the subject-owned Consent records through its individual aggregate. */
536
+ export type SubjectConsentSearchInput = Readonly<{
537
+ subject: string;
538
+ actorIdentifier?: string;
539
+ purpose?: string;
540
+ action?: string;
541
+ sourceReference?: string;
542
+ pollOptions?: {
543
+ timeoutMs?: number;
544
+ intervalMs?: number;
545
+ };
546
+ }>;
535
547
  export declare function createOrganizationEmployeeWithDeps(routeCtx: RouteContext, input: OrganizationEmployeeCreationInput, options: {
536
548
  timeoutMs?: number;
537
549
  intervalMs?: number;
@@ -953,6 +965,22 @@ export declare function purgeDigitalTwinSubjectLinkWithDeps(routeCtx: RouteConte
953
965
  intervalMs?: number;
954
966
  }) => Promise<SubmitAndPollResult>;
955
967
  }): Promise<DigitalTwinSubjectLinkPurgeResult>;
968
+ /**
969
+ * Reads Consent through the individual `Subject/_search` aggregate carried by
970
+ * an auditable Communication. `Subject` is the individual aggregate; it is
971
+ * intentionally separate from the public digital-twin `ResearchSubject`
972
+ * aggregate, whose canonical index document is a Composition.
973
+ */
974
+ export declare function searchSubjectConsentsWithDeps(routeCtx: RouteContext, input: SubjectConsentSearchInput, deps: {
975
+ individualCommunicationBatchPath: (ctx: RouteContext, pathFormatSegment: string) => string;
976
+ individualCommunicationPollPath: (ctx: RouteContext, pathFormatSegment: string) => string;
977
+ submitAndPoll: (submitPath: string, pollPath: string, payload: {
978
+ thid?: string;
979
+ } & Record<string, unknown>, pollOptions?: {
980
+ timeoutMs?: number;
981
+ intervalMs?: number;
982
+ }) => Promise<SubmitAndPollResult>;
983
+ }): Promise<SubmitAndPollResult>;
956
984
  export declare function revokeProfessionalAccessWithDeps(routeCtx: RouteContext, input: RevokeProfessionalAccessInput, deps: {
957
985
  individualConsentR4BatchPath: (ctx: RouteContext) => string;
958
986
  individualConsentR4PollPath: (ctx: RouteContext) => string;
@@ -865,6 +865,61 @@ export async function purgeDigitalTwinSubjectLinkWithDeps(routeCtx, input, deps)
865
865
  },
866
866
  }, input.pollOptions);
867
867
  }
868
+ /**
869
+ * Reads Consent through the individual `Subject/_search` aggregate carried by
870
+ * an auditable Communication. `Subject` is the individual aggregate; it is
871
+ * intentionally separate from the public digital-twin `ResearchSubject`
872
+ * aggregate, whose canonical index document is a Composition.
873
+ */
874
+ export async function searchSubjectConsentsWithDeps(routeCtx, input, deps) {
875
+ const subject = String(input.subject || '').trim();
876
+ if (!subject.startsWith('did:')) {
877
+ throw new Error('Consent search requires a subject DID.');
878
+ }
879
+ const format = 'org.hl7.fhir.r4';
880
+ const optionalParameters = [
881
+ ['actor-identifier', input.actorIdentifier],
882
+ ['purpose', input.purpose],
883
+ ['action', input.action],
884
+ ['source-reference', input.sourceReference],
885
+ ];
886
+ const parameters = {
887
+ resourceType: 'Parameters',
888
+ parameter: [
889
+ { name: 'subject', valueString: subject },
890
+ ...optionalParameters
891
+ .map(([name, rawValue]) => ({ name, valueString: String(rawValue || '').trim() }))
892
+ .filter((parameter) => parameter.valueString),
893
+ ],
894
+ };
895
+ const thid = `subject-consent-search-${createRuntimeUuid()}`;
896
+ const communication = {
897
+ resourceType: 'Communication',
898
+ status: 'completed',
899
+ subject: { reference: subject },
900
+ payload: [{
901
+ contentReference: {
902
+ reference: 'individual/org.hl7.fhir.api/Subject/_search',
903
+ },
904
+ contentAttachment: {
905
+ contentType: 'application/fhir+json',
906
+ title: 'subject-consent-search-parameters.json',
907
+ data: Buffer.from(JSON.stringify(parameters), 'utf8').toString('base64'),
908
+ },
909
+ }],
910
+ };
911
+ return deps.submitAndPoll(deps.individualCommunicationBatchPath(routeCtx, format), deps.individualCommunicationPollPath(routeCtx, format), {
912
+ thid,
913
+ body: {
914
+ resourceType: 'Bundle',
915
+ type: 'batch',
916
+ entry: [{
917
+ request: { method: 'POST', url: 'Communication' },
918
+ resource: communication,
919
+ }],
920
+ },
921
+ }, input.pollOptions);
922
+ }
868
923
  export async function revokeProfessionalAccessWithDeps(routeCtx, input, deps) {
869
924
  const revokedClaims = ConsentClaims
870
925
  .fromClaims(input.consentClaims)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gdc-sdk-node-ts",
3
- "version": "2.4.43",
3
+ "version": "2.4.45",
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.",