gdc-sdk-node-ts 2.6.1 → 2.6.3
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 +8 -2
- package/dist/node-runtime-client.d.ts +11 -2
- package/dist/node-runtime-client.js +11 -2
- package/dist/orchestration/professional-sdk.d.ts +2 -1
- package/dist/orchestration/professional-sdk.js +2 -1
- package/dist/resource-operations.d.ts +6 -3
- package/dist/resource-operations.js +51 -3
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -427,13 +427,16 @@ data ingestion/search.
|
|
|
427
427
|
|
|
428
428
|
`ProfessionalSdk.requestProfessionalAccess(...)` is the bootstrap operation
|
|
429
429
|
for the inverse flow: it persists a subject-scoped permission-request
|
|
430
|
-
`Communication`
|
|
431
|
-
|
|
430
|
+
`Communication` with an attached batch Bundle of normal
|
|
431
|
+
`Consent.status = draft` resources, using the configured HTTP bearer and
|
|
432
|
+
transport profile without requiring SMART. A draft is inbox evidence and
|
|
433
|
+
cannot authorize access. The subject later answers through
|
|
432
434
|
`respondToProfessionalAccessRequest(...)`; that facade uses the normal Consent
|
|
433
435
|
grant/deny operation and retains the original Communication identifier/thread.
|
|
434
436
|
`listProfessionalAccessRequests(...)` provides the subject/requester inbox view,
|
|
435
437
|
and `GatewayActiveConsentProvider` supplies `evaluateRequestedAccess(...)` from
|
|
436
438
|
the GW Consent source of truth rather than a parallel application table.
|
|
439
|
+
There is no `AccessRequest` FHIR resource or `AccessRequest.*` claim family.
|
|
437
440
|
|
|
438
441
|
## Main Flows
|
|
439
442
|
|
|
@@ -813,6 +816,9 @@ Recovery-specific live rule:
|
|
|
813
816
|
and cannot select another tenant
|
|
814
817
|
- a failed poll `OperationOutcome` is surfaced before the helper checks for
|
|
815
818
|
`initial_access_token`, preserving the real GW diagnostic
|
|
819
|
+
- every asynchronous success test uses `BundleReader.getResponseAnalysis()`;
|
|
820
|
+
HTTP 200/201 alone is transport completion, not proof that the inner Bundle
|
|
821
|
+
entries succeeded
|
|
816
822
|
- the bundled recovery runner generates a syntactically valid demo JWT if
|
|
817
823
|
`CONTROLLER_ID_TOKEN` is not provided, but production/staging should use a
|
|
818
824
|
real IdP-issued token
|
|
@@ -143,6 +143,13 @@ export declare class HttpRuntimeClient implements NodeRuntimeClient {
|
|
|
143
143
|
}, pollOptions?: PollOptions): Promise<PollResult>;
|
|
144
144
|
/**
|
|
145
145
|
* Convenience wrapper that performs submit and poll in sequence.
|
|
146
|
+
*
|
|
147
|
+
* A terminal HTTP 200/201 means polling completed; it does not guarantee the
|
|
148
|
+
* business operation succeeded. Consumers and E2E tests must inspect
|
|
149
|
+
* `result.poll.body` with `BundleReader.getResponseAnalysis()` and reject
|
|
150
|
+
* error OperationOutcomes. High-level product code must not manually traverse
|
|
151
|
+
* DIDComm `body`, JSON-API `data[]`, FHIR `entry[]` or `issue[]` to decide
|
|
152
|
+
* success.
|
|
146
153
|
*/
|
|
147
154
|
submitAndPoll(submitPath: string, pollPath: string, payload: SubmitPayload, pollOptions?: PollOptions): Promise<SubmitAndPollResult>;
|
|
148
155
|
/** Registers one neutral FHIR R5 topic in the tenant-owned CORE catalog. */
|
|
@@ -496,8 +503,10 @@ export declare class HttpRuntimeClient implements NodeRuntimeClient {
|
|
|
496
503
|
ingestCommunicationAndUpdateIndex(ctx: RouteContext, input: CommunicationIngestionInput): Promise<SubmitAndPollResult>;
|
|
497
504
|
/**
|
|
498
505
|
* Records a subject-scoped permission-request Communication before SMART
|
|
499
|
-
* authorization exists. The
|
|
500
|
-
*
|
|
506
|
+
* authorization exists. The Communication carries a batch Bundle of
|
|
507
|
+
* `Consent.status = draft`; that draft grants nothing. The configured bearer
|
|
508
|
+
* authenticates HTTP and the configured secure transport adapter
|
|
509
|
+
* signs/encrypts DIDComm when enabled.
|
|
501
510
|
*/
|
|
502
511
|
requestProfessionalAccess(ctx: RouteContext, input: ProfessionalAccessRequestInput): Promise<ProfessionalAccessRequestResult>;
|
|
503
512
|
/**
|
|
@@ -129,6 +129,13 @@ export class HttpRuntimeClient {
|
|
|
129
129
|
}
|
|
130
130
|
/**
|
|
131
131
|
* Convenience wrapper that performs submit and poll in sequence.
|
|
132
|
+
*
|
|
133
|
+
* A terminal HTTP 200/201 means polling completed; it does not guarantee the
|
|
134
|
+
* business operation succeeded. Consumers and E2E tests must inspect
|
|
135
|
+
* `result.poll.body` with `BundleReader.getResponseAnalysis()` and reject
|
|
136
|
+
* error OperationOutcomes. High-level product code must not manually traverse
|
|
137
|
+
* DIDComm `body`, JSON-API `data[]`, FHIR `entry[]` or `issue[]` to decide
|
|
138
|
+
* success.
|
|
132
139
|
*/
|
|
133
140
|
async submitAndPoll(submitPath, pollPath, payload, pollOptions) {
|
|
134
141
|
return this.submitClinicalMessageAndPoll(submitPath, pollPath, payload, this.transportProfile, pollOptions);
|
|
@@ -984,8 +991,10 @@ export class HttpRuntimeClient {
|
|
|
984
991
|
}
|
|
985
992
|
/**
|
|
986
993
|
* Records a subject-scoped permission-request Communication before SMART
|
|
987
|
-
* authorization exists. The
|
|
988
|
-
*
|
|
994
|
+
* authorization exists. The Communication carries a batch Bundle of
|
|
995
|
+
* `Consent.status = draft`; that draft grants nothing. The configured bearer
|
|
996
|
+
* authenticates HTTP and the configured secure transport adapter
|
|
997
|
+
* signs/encrypts DIDComm when enabled.
|
|
989
998
|
*/
|
|
990
999
|
async requestProfessionalAccess(ctx, input) {
|
|
991
1000
|
this.requireConfiguredTransportProfile(input.transportProfile);
|
|
@@ -77,7 +77,8 @@ export declare class ProfessionalSdk {
|
|
|
77
77
|
ingestCommunicationAndUpdateIndex(ctx: RouteContext, input: CommunicationIngestionInput): Promise<SubmitAndPollResult>;
|
|
78
78
|
/**
|
|
79
79
|
* Requests subject-controlled access without requiring a SMART token. The
|
|
80
|
-
* runtime persists one canonical permission-request Communication
|
|
80
|
+
* runtime persists one canonical permission-request Communication carrying
|
|
81
|
+
* a draft Consent Bundle. The draft is auditable but never authorizes access.
|
|
81
82
|
*/
|
|
82
83
|
requestProfessionalAccess(ctx: RouteContext, input: ProfessionalAccessRequestInput): Promise<ProfessionalAccessRequestResult>;
|
|
83
84
|
/** Lists permission requests sent by or involving this professional. */
|
|
@@ -92,7 +92,8 @@ export class ProfessionalSdk {
|
|
|
92
92
|
}
|
|
93
93
|
/**
|
|
94
94
|
* Requests subject-controlled access without requiring a SMART token. The
|
|
95
|
-
* runtime persists one canonical permission-request Communication
|
|
95
|
+
* runtime persists one canonical permission-request Communication carrying
|
|
96
|
+
* a draft Consent Bundle. The draft is auditable but never authorizes access.
|
|
96
97
|
*/
|
|
97
98
|
requestProfessionalAccess(ctx, input) {
|
|
98
99
|
return requireClientMethod(this.client, 'requestProfessionalAccess')(ctx, input);
|
|
@@ -268,8 +268,9 @@ export type CommunicationIngestionInput = {
|
|
|
268
268
|
/**
|
|
269
269
|
* Canonical professional-to-subject permission request.
|
|
270
270
|
*
|
|
271
|
-
* This operation records
|
|
272
|
-
*
|
|
271
|
+
* This operation records one `Communication` carrying a normal
|
|
272
|
+
* `Consent.status = draft`; it never creates an active grant and does not
|
|
273
|
+
* require a SMART token. HTTP authentication and optional secure DIDComm
|
|
273
274
|
* transport remain concerns of the configured runtime client.
|
|
274
275
|
*/
|
|
275
276
|
export type ProfessionalAccessRequestInput = Omit<PermissionRequestCommunicationInput, 'missing'> & Readonly<{
|
|
@@ -288,6 +289,7 @@ export type ProfessionalAccessRequestInput = Omit<PermissionRequestCommunication
|
|
|
288
289
|
export type ProfessionalAccessRequestResult = Readonly<{
|
|
289
290
|
thid: string;
|
|
290
291
|
communicationIdentifier: string;
|
|
292
|
+
consentIdentifier: string;
|
|
291
293
|
communication: CommunicationInput;
|
|
292
294
|
delivery: SubmitAndPollResult;
|
|
293
295
|
}>;
|
|
@@ -846,7 +848,8 @@ export declare function ingestCommunicationAndUpdateIndexWithDeps(routeCtx: Rout
|
|
|
846
848
|
/**
|
|
847
849
|
* Builds and persists one professional access request against the subject's
|
|
848
850
|
* provider route. The request is deliberately independent from SMART because
|
|
849
|
-
* no subject consent exists yet.
|
|
851
|
+
* no active subject consent exists yet. The auditable Communication carries a
|
|
852
|
+
* draft Consent Bundle; the draft itself never authorizes data access.
|
|
850
853
|
*/
|
|
851
854
|
export declare function requestProfessionalAccessWithDeps(routeCtx: RouteContext, input: ProfessionalAccessRequestInput, deps: {
|
|
852
855
|
individualCommunicationBatchPath: (ctx: RouteContext, pathFormatSegment: string) => string;
|
|
@@ -476,7 +476,8 @@ export async function ingestCommunicationAndUpdateIndexWithDeps(routeCtx, input,
|
|
|
476
476
|
/**
|
|
477
477
|
* Builds and persists one professional access request against the subject's
|
|
478
478
|
* provider route. The request is deliberately independent from SMART because
|
|
479
|
-
* no subject consent exists yet.
|
|
479
|
+
* no active subject consent exists yet. The auditable Communication carries a
|
|
480
|
+
* draft Consent Bundle; the draft itself never authorizes data access.
|
|
480
481
|
*/
|
|
481
482
|
export async function requestProfessionalAccessWithDeps(routeCtx, input, deps) {
|
|
482
483
|
const subject = String(input.subject || '').trim();
|
|
@@ -498,11 +499,14 @@ export async function requestProfessionalAccessWithDeps(routeCtx, input, deps) {
|
|
|
498
499
|
const thid = String(input.thid || '').trim() || `permission-request-${createRuntimeUuid()}`;
|
|
499
500
|
const communicationIdentifier = String(input.communicationIdentifier || '').trim()
|
|
500
501
|
|| `urn:uuid:${createRuntimeUuid()}`;
|
|
502
|
+
const consentIdentifier = String(input.consentIdentifier || '').trim()
|
|
503
|
+
|| `urn:uuid:${createRuntimeUuid()}`;
|
|
501
504
|
const communication = buildPermissionRequestCommunication({
|
|
502
505
|
...input,
|
|
503
506
|
subject,
|
|
504
507
|
thid,
|
|
505
508
|
communicationIdentifier,
|
|
509
|
+
consentIdentifier,
|
|
506
510
|
missing: {
|
|
507
511
|
sections: missingSections,
|
|
508
512
|
resourceTypes: missingResourceTypes,
|
|
@@ -512,12 +516,56 @@ export async function requestProfessionalAccessWithDeps(routeCtx, input, deps) {
|
|
|
512
516
|
],
|
|
513
517
|
},
|
|
514
518
|
});
|
|
519
|
+
const communicationClaims = {
|
|
520
|
+
...communication.claims,
|
|
521
|
+
[CommunicationClaim.Category]: 'permission-request',
|
|
522
|
+
[CommunicationClaim.NoteText]: communication.text,
|
|
523
|
+
};
|
|
524
|
+
const persistedCommunication = { ...communication, claims: communicationClaims };
|
|
525
|
+
if (!communication.payload) {
|
|
526
|
+
throw new Error('Permission request requires one draft Consent Bundle.');
|
|
527
|
+
}
|
|
528
|
+
const communicationResource = addFhirResourceToCommunication(createCommunicationResource({
|
|
529
|
+
subject,
|
|
530
|
+
sender: communication.sender,
|
|
531
|
+
recipient: communication.recipient,
|
|
532
|
+
category: Array.isArray(communication.category)
|
|
533
|
+
? communication.category
|
|
534
|
+
: communication.category ? [communication.category] : undefined,
|
|
535
|
+
noteText: communication.text,
|
|
536
|
+
claims: communicationClaims,
|
|
537
|
+
}), communication.payload, {
|
|
538
|
+
attachmentTitle: 'draft-consent-request.json',
|
|
539
|
+
attachmentContentType: 'application/fhir+json',
|
|
540
|
+
});
|
|
541
|
+
communicationResource.id = communicationIdentifier;
|
|
542
|
+
const communicationPayload = {
|
|
543
|
+
thid,
|
|
544
|
+
body: {
|
|
545
|
+
resourceType: ResourceTypesFhirR4.Bundle,
|
|
546
|
+
type: 'batch',
|
|
547
|
+
data: [{
|
|
548
|
+
type: 'CommMsgExtended',
|
|
549
|
+
meta: { claims: communicationClaims },
|
|
550
|
+
resource: communicationResource,
|
|
551
|
+
}],
|
|
552
|
+
},
|
|
553
|
+
};
|
|
515
554
|
const delivery = await ingestCommunicationAndUpdateIndexWithDeps(routeCtx, {
|
|
516
|
-
|
|
555
|
+
// The compatibility ingestion facade still declares the historical flat
|
|
556
|
+
// CommunicationInput even though its runtime contract accepts the GW
|
|
557
|
+
// Bundle envelope. Keep this high-level builder as the only cast boundary.
|
|
558
|
+
communicationPayload: communicationPayload,
|
|
517
559
|
pathFormatSegment: 'r4',
|
|
518
560
|
pollOptions: input.pollOptions,
|
|
519
561
|
}, deps);
|
|
520
|
-
return {
|
|
562
|
+
return {
|
|
563
|
+
thid,
|
|
564
|
+
communicationIdentifier,
|
|
565
|
+
consentIdentifier,
|
|
566
|
+
communication: persistedCommunication,
|
|
567
|
+
delivery,
|
|
568
|
+
};
|
|
521
569
|
}
|
|
522
570
|
export async function searchCommunicationParticipantsWithDeps(routeCtx, input, deps) {
|
|
523
571
|
const payload = {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gdc-sdk-node-ts",
|
|
3
|
-
"version": "2.6.
|
|
3
|
+
"version": "2.6.3",
|
|
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.",
|
|
@@ -38,8 +38,8 @@
|
|
|
38
38
|
"test:e2e:live-gw:clean": "bash ./scripts/run-live-gw-clean.sh"
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {
|
|
41
|
-
"gdc-common-utils-ts": "2.7.
|
|
42
|
-
"gdc-sdk-core-ts": "2.4.
|
|
41
|
+
"gdc-common-utils-ts": "2.7.2",
|
|
42
|
+
"gdc-sdk-core-ts": "2.4.3"
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
45
45
|
"@types/node": "^20.14.10",
|