gdc-sdk-node-ts 2.6.6 → 2.6.7

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.
@@ -34,11 +34,11 @@ export async function listAuthorizedIndividualSubjectsWithDeps(routeContext, inp
34
34
  data: [{
35
35
  type: 'Family-search-v1.0',
36
36
  request: { method: 'POST' },
37
- meta: { claims: {
38
- '@context': SCHEMA_CONTEXT,
39
- ...(email ? { [CLAIM_ORGANIZATION_OWNER_EMAIL]: email } : {}),
40
- ...(telephone ? { [CLAIM_ORGANIZATION_OWNER_TELEPHONE]: telephone } : {}),
41
- } },
37
+ resource: { meta: { claims: {
38
+ '@context': SCHEMA_CONTEXT,
39
+ ...(email ? { [CLAIM_ORGANIZATION_OWNER_EMAIL]: email } : {}),
40
+ ...(telephone ? { [CLAIM_ORGANIZATION_OWNER_TELEPHONE]: telephone } : {}),
41
+ } } },
42
42
  }],
43
43
  },
44
44
  }, input.pollOptions);
@@ -58,7 +58,7 @@ export async function listAuthorizedIndividualSubjectsWithDeps(routeContext, inp
58
58
  type: 'batch',
59
59
  data: [{
60
60
  request: { method: 'POST' },
61
- meta: { status: 'active', claims: licenseClaims },
61
+ resource: { meta: { status: 'active', claims: licenseClaims } },
62
62
  }],
63
63
  },
64
64
  }, input.pollOptions);
@@ -76,7 +76,7 @@ export async function listAuthorizedIndividualSubjectsWithDeps(routeContext, inp
76
76
  data: [{
77
77
  type: 'Family-search-v1.0',
78
78
  request: { method: 'POST' },
79
- meta: { claims: organizationClaims },
79
+ resource: { meta: { claims: organizationClaims } },
80
80
  }],
81
81
  },
82
82
  }, input.pollOptions);
@@ -155,7 +155,7 @@ function readAcceptedLicenses(result) {
155
155
  }
156
156
  function readFirstClaims(result) {
157
157
  const entry = readData(result)[0];
158
- const claims = entry?.meta?.claims || entry?.resource?.meta?.claims;
158
+ const claims = entry?.resource?.meta?.claims || entry?.meta?.claims;
159
159
  return claims && typeof claims === 'object' ? claims : {};
160
160
  }
161
161
  function readData(result) {
@@ -234,12 +234,13 @@ export async function searchDigitalTwinsWithDeps(ctx, input, deps) {
234
234
  ? {
235
235
  data: [{
236
236
  type: `${resourceType}-search-request-v1.0`,
237
- resource: { resourceType: 'Parameters', parameter: parameters },
238
- meta: {
239
- claims: Object.fromEntries([
240
- ['@context', format],
241
- ...parameters.map((parameter) => [parameter.name, parameter.valueString || parameter.valueDate || '']),
242
- ]),
237
+ resource: {
238
+ resourceType: 'Parameters',
239
+ parameter: parameters,
240
+ meta: { claims: Object.fromEntries([
241
+ ['@context', format],
242
+ ...parameters.map((parameter) => [parameter.name, parameter.valueString || parameter.valueDate || '']),
243
+ ]) },
243
244
  },
244
245
  }],
245
246
  }
@@ -35,7 +35,6 @@ export async function searchFamilyOrganizationWithDeps(deps) {
35
35
  body: {
36
36
  data: [{
37
37
  type: 'Family-search-v1.0',
38
- meta: { claims },
39
38
  resource: { meta: { claims } },
40
39
  }],
41
40
  },
@@ -27,7 +27,6 @@ export async function confirmIndividualOrganizationOrderWithDeps(deps) {
27
27
  body: {
28
28
  data: [{
29
29
  type: 'Family-order-request-v1.0',
30
- meta: { claims: orderClaims },
31
30
  resource: { meta: { claims: orderClaims } },
32
31
  }],
33
32
  },
@@ -54,7 +54,6 @@ export async function startIndividualOrganizationWithDeps(deps) {
54
54
  body: {
55
55
  data: [{
56
56
  type: GwCoreLifecycleRequestType.IndividualOrganizationRegistration,
57
- meta: { claims },
58
57
  resource: { meta: { claims } },
59
58
  }],
60
59
  },
@@ -68,7 +68,10 @@ export const recoverOrganizationControllerWithIssueWithDeps = recoverOrganizatio
68
68
  export function readLegalOrganizationCredentialReissuanceActivationCode(result) {
69
69
  const pollBody = (result?.poll?.body || {});
70
70
  for (const candidate of nestedObjects(pollBody)) {
71
- const claims = candidate.meta?.claims;
71
+ const resource = candidate.resource;
72
+ const resourceClaims = resource?.meta?.claims;
73
+ const legacyClaims = candidate.meta?.claims;
74
+ const claims = resourceClaims || legacyClaims;
72
75
  const activationCode = String(claims?.['org.schema.IndividualProduct.serialNumber'] || '').trim();
73
76
  if (activationCode)
74
77
  return activationCode;
@@ -84,8 +84,10 @@ export function readEmployeeLicenseOfferId(value) {
84
84
  for (const candidate of nestedRecords(value)) {
85
85
  if (candidate.type !== 'Employee-license-offer-v1.0')
86
86
  continue;
87
- const meta = record(candidate.meta);
88
- const claims = record(meta?.claims);
87
+ const resource = record(candidate.resource);
88
+ const resourceMeta = record(resource?.meta);
89
+ const legacyMeta = record(candidate.meta);
90
+ const claims = record(resourceMeta?.claims) || record(legacyMeta?.claims);
89
91
  const offerId = String(claims?.[ClaimsOfferSchemaorg.identifier] || '').trim();
90
92
  if (offerId)
91
93
  return offerId;
@@ -27,7 +27,6 @@ export async function confirmOrganizationLicenseOrderWithDeps(deps) {
27
27
  body: {
28
28
  data: [{
29
29
  type: deps.input.dataType || 'Organization-order-request-v1.0',
30
- meta: { claims },
31
30
  resource: { meta: { claims } },
32
31
  }],
33
32
  },
@@ -340,11 +340,11 @@ export async function transitionIndividualMemberLicenseWithDeps(routeCtx, action
340
340
  ...(input.ownerOrganizationId ? { ownerOrganizationId: input.ownerOrganizationId } : {}),
341
341
  ...(input.subjectId ? { subjectId: input.subjectId } : {}),
342
342
  ...(input.verifiedActorIdentifier ? { verifiedActorIdentifier: input.verifiedActorIdentifier } : {}),
343
- claims: {
344
- '@context': 'org.schema',
345
- 'org.schema.IndividualProduct.serialNumber': input.activationCode,
346
- },
347
343
  },
344
+ resource: { meta: { claims: {
345
+ '@context': 'org.schema',
346
+ 'org.schema.IndividualProduct.serialNumber': input.activationCode,
347
+ } } },
348
348
  request: { method: 'POST' },
349
349
  }],
350
350
  },
@@ -414,7 +414,6 @@ export async function disableIndividualMemberWithDeps(routeCtx, input, options,
414
414
  type: 'batch',
415
415
  entry: [{
416
416
  request: { method: GwCoreLifecycleRequestMethod.Post },
417
- meta: { claims },
418
417
  resource: {
419
418
  ...resource,
420
419
  ...(input.resourceId ? { id: input.resourceId } : {}),
@@ -444,7 +443,6 @@ export async function purgeIndividualMemberWithDeps(routeCtx, input, options, de
444
443
  entry: [{
445
444
  type: input.dataType || GwCoreLifecycleRequestType.IndividualMemberPurge,
446
445
  request: { method: GwCoreLifecycleRequestMethod.Post },
447
- meta: { claims },
448
446
  resource: {
449
447
  ...resource,
450
448
  ...(input.resourceId ? { id: input.resourceId } : {}),
@@ -550,7 +548,6 @@ export async function requestProfessionalAccessWithDeps(routeCtx, input, deps) {
550
548
  type: 'batch',
551
549
  data: [{
552
550
  type: 'CommMsgExtended',
553
- meta: { claims: communicationClaims },
554
551
  resource: communicationResource,
555
552
  }],
556
553
  },
@@ -701,7 +698,6 @@ export function buildBlockchainArtifactBundleFromSearchResponse(input) {
701
698
  });
702
699
  return {
703
700
  type: 'DocumentReference',
704
- meta: { claims: artifact.documentReference.meta?.claims || {} },
705
701
  resource: artifact.documentReference,
706
702
  request: {
707
703
  method: 'POST',
@@ -762,7 +758,6 @@ export async function registerBlockchainArtifactAndUpdateIndexWithDeps(routeCtx,
762
758
  type: 'batch',
763
759
  data: [{
764
760
  type: 'DocumentReference',
765
- meta: { claims: artifact.documentReference.meta?.claims || {} },
766
761
  resource: artifact.documentReference,
767
762
  request: {
768
763
  method: 'POST',
@@ -840,7 +835,6 @@ export async function grantProfessionalAccessWithDeps(routeCtx, input, deps) {
840
835
  body: {
841
836
  data: [{
842
837
  type: input.dataType || 'Consent-grant-request-v1.0',
843
- meta: { claims: built.consentClaims },
844
838
  resource: { resourceType: 'Consent', meta: { claims: built.consentClaims } },
845
839
  }],
846
840
  },
@@ -983,7 +977,6 @@ export async function revokeProfessionalAccessWithDeps(routeCtx, input, deps) {
983
977
  body: {
984
978
  data: [{
985
979
  type: input.dataType || 'Consent-grant-request-v1.0',
986
- meta: { claims: revokedClaims },
987
980
  resource: { resourceType: 'Consent', meta: { claims: revokedClaims } },
988
981
  }],
989
982
  },
@@ -65,13 +65,6 @@ export async function activateOrganizationInGatewayFromIcaProofWithDeps(input) {
65
65
  ...(input.activationInput.controller ? { controller: input.activationInput.controller } : {}),
66
66
  data: [{
67
67
  type: 'Organization-activation-request-v1.0',
68
- meta: {
69
- claims: {
70
- '@context': 'org.schema',
71
- ...serviceClaims,
72
- ...(input.activationInput.additionalClaims || {}),
73
- },
74
- },
75
68
  resource: {
76
69
  meta: {
77
70
  claims: {
@@ -1,6 +1,7 @@
1
1
  // Copyright 2026 Antifraud Services Inc. under the Apache License, Version 2.0.
2
2
  import { buildGwCoreTenantResourceActionPath } from 'gdc-common-utils-ts/utils/gw-core-path';
3
- import { IdentityAuthActions, IdentityAuthRouteSegments } from 'gdc-common-utils-ts/constants/identity-auth';
3
+ import { IdentityAuthActions, IdentityAuthResourceTypes, IdentityAuthRouteSegments, SmartPostDcrActions, } from 'gdc-common-utils-ts/constants/identity-auth';
4
+ import { GatewayRouteFormats, GatewayRouteSections, } from 'gdc-common-utils-ts/constants/gateway-response';
4
5
  export function buildV1Path(routeCtx, section, format, resourceType, action) {
5
6
  return buildGwCoreTenantResourceActionPath({
6
7
  tenantId: routeCtx.tenantId,
@@ -60,8 +61,8 @@ function buildIdentityAuthPath(ctx, action) {
60
61
  return `/${encodeURIComponent(IdentityAuthRouteSegments.Host)}/cds-${encodeURIComponent(ctx.jurisdiction)}/${IdentityAuthRouteSegments.Version}/${encodeURIComponent(ctx.sector)}/${encodeURIComponent(ctx.tenantId)}/${IdentityAuthRouteSegments.Section}/${IdentityAuthRouteSegments.Format}/${encodeURIComponent(action)}`;
61
62
  }
62
63
  export function buildIdentityOpenIdSmartTokenPath(ctx) {
63
- return `/${encodeURIComponent(ctx.tenantId)}/cds-${encodeURIComponent(ctx.jurisdiction)}/v1/${encodeURIComponent(ctx.sector)}/identity/openid/smart/token`;
64
+ return buildV1Path(ctx, GatewayRouteSections.Identity, GatewayRouteFormats.OpenId, IdentityAuthResourceTypes.Smart, SmartPostDcrActions.Token);
64
65
  }
65
66
  export function buildIdentityOpenIdSmartTokenPollPath(ctx) {
66
- return `/${encodeURIComponent(ctx.tenantId)}/cds-${encodeURIComponent(ctx.jurisdiction)}/v1/${encodeURIComponent(ctx.sector)}/identity/openid/smart/_batch-response`;
67
+ return buildV1Path(ctx, GatewayRouteSections.Identity, GatewayRouteFormats.OpenId, IdentityAuthResourceTypes.Smart, SmartPostDcrActions.TokenResponse);
67
68
  }
@@ -379,6 +379,7 @@ export declare class ServerProfileSessionManager {
379
379
  openProfessional(input: ServerProfessionalOpenInput): Promise<OpenedServerProfessional>;
380
380
  lock(ownerId: string, sessionId: string): Promise<void>;
381
381
  private createClient;
382
+ private createRegisteredProfileClient;
382
383
  private createWallet;
383
384
  /**
384
385
  * Upgrade legacy profiles deterministically after successful PIN unlock.
@@ -328,12 +328,13 @@ export class ServerProfileSessionManager {
328
328
  profile = await this.ensureRequiredStorageProfile(profile, seed);
329
329
  const walletKeyDerivationId = profile.walletKeyDerivationId || profile.profileId;
330
330
  const wallet = await this.createWallet(walletKeyDerivationId, seed);
331
+ const context = walletContext(walletKeyDerivationId);
331
332
  const smartTokenEndpoint = [
332
333
  this.options.gatewayBaseUrl.replace(/\/+$/, ''),
333
334
  buildIdentityOpenIdSmartTokenPath(profile.routeContext),
334
335
  ].join('');
335
336
  const assertion = await buildWalletClientAssertion(wallet, profile, smartTokenEndpoint, now);
336
- const token = await this.createClient(profile.routeContext, input.idToken).requestSmartToken({
337
+ const token = await this.createRegisteredProfileClient(profile, wallet, context, input.idToken).requestSmartToken({
337
338
  ...profile.routeContext,
338
339
  actorDid: profile.actorDid,
339
340
  subjectDid: input.subjectDid,
@@ -394,13 +395,14 @@ export class ServerProfileSessionManager {
394
395
  : undefined;
395
396
  const walletKeyDerivationId = profile.walletKeyDerivationId || profile.profileId;
396
397
  const wallet = await this.createWallet(walletKeyDerivationId, seed);
398
+ const context = walletContext(walletKeyDerivationId);
397
399
  const now = this.now();
398
400
  const smartTokenEndpoint = [
399
401
  this.options.gatewayBaseUrl.replace(/\/+$/, ''),
400
402
  buildIdentityOpenIdSmartTokenPath(profile.routeContext),
401
403
  ].join('');
402
404
  const assertion = await buildWalletClientAssertion(wallet, profile, smartTokenEndpoint, now);
403
- const token = await this.createClient(profile.routeContext, normalizedIdToken).requestSmartToken({
405
+ const token = await this.createRegisteredProfileClient(profile, wallet, context, normalizedIdToken).requestSmartToken({
404
406
  ...profile.routeContext,
405
407
  actorDid: profile.actorDid,
406
408
  subjectDid: session.subjectDid,
@@ -546,13 +548,11 @@ export class ServerProfileSessionManager {
546
548
  transportProfile: TransportProfiles.DidcommEncryptedForm,
547
549
  secureTransportAdapter,
548
550
  });
549
- // SMART/OpenID uses its own JSON/form protocol and must not be wrapped in
550
- // the encrypted resource transport selected for later business actions.
551
- // Professional business operations are authored by the registered employee
552
- // wallet and therefore use the encrypted DIDComm client. SMART/OpenID below
553
- // remains an independent JSON/form exchange through its dedicated method.
551
+ // Both SMART and later business operations are post-DCR profile actions.
552
+ // Strict GW therefore resolves the same registered employee wallet for the
553
+ // encrypted request and poll transport used by both facades.
554
554
  const sdk = new ProfessionalSdk(operationalClient);
555
- const smartSdk = new ProfessionalSdk(this.createClient(profile.routeContext, idToken));
555
+ const smartSdk = sdk;
556
556
  const digitalTwin = new DigitalTwinSdk(operationalClient, profile.actorDid);
557
557
  let digitalTwinAccessToken;
558
558
  const request = async (smart) => {
@@ -625,6 +625,20 @@ export class ServerProfileSessionManager {
625
625
  appInfo: this.options.appInfo,
626
626
  });
627
627
  }
628
+ createRegisteredProfileClient(profile, wallet, context, bearerToken) {
629
+ return new NodeHttpClient({
630
+ baseUrl: this.options.gatewayBaseUrl,
631
+ ctx: profile.routeContext,
632
+ bearerToken,
633
+ fetchImpl: this.options.fetchImpl,
634
+ appInfo: this.options.appInfo,
635
+ transportProfile: TransportProfiles.DidcommEncryptedForm,
636
+ secureTransportAdapter: {
637
+ pack: (message) => wallet.packForRecipientWithContext(bindOrganizationControllerTransport(message, profile), profile.providerDid, { context }),
638
+ unpack: async (jwe) => (await wallet.unpackWithContext(jwe, { context })).content,
639
+ },
640
+ });
641
+ }
628
642
  async createWallet(walletKeyDerivationId, seed) {
629
643
  const wallet = new NodeManagedWallet({ resolveRecipientJwk: this.options.resolveRecipientJwk });
630
644
  const context = walletContext(walletKeyDerivationId);
@@ -1,5 +1,7 @@
1
1
  // Copyright 2026 Antifraud Services Inc. under the Apache License, Version 2.0.
2
2
  import { HealthcareConsentPurposes } from 'gdc-common-utils-ts/constants';
3
+ import { IdentityAuthResourceTypes, SmartPostDcrActions, } from 'gdc-common-utils-ts/constants/identity-auth';
4
+ import { GatewayRouteFormats, GatewayRouteSections, } from 'gdc-common-utils-ts/constants/gateway-response';
3
5
  import { buildClientAssertionJwt } from 'gdc-common-utils-ts/utils/client-assertion';
4
6
  import { resolvePollOptionsFromSeconds } from './poll-options.js';
5
7
  /**
@@ -109,16 +111,19 @@ function normalizeResolvedSmartTokenEndpoint(value) {
109
111
  if (!['http:', 'https:'].includes(endpoint.protocol)) {
110
112
  throw new Error('Resolved SMART token endpoint must use HTTP(S).');
111
113
  }
112
- if (!endpoint.pathname.endsWith('/identity/openid/smart/token')) {
113
- throw new Error('Resolved SMART token endpoint must target /identity/openid/smart/token.');
114
+ if (!endpoint.pathname.endsWith(smartTokenRouteSuffix(SmartPostDcrActions.Token))) {
115
+ throw new Error(`Resolved SMART token endpoint must target ${smartTokenRouteSuffix(SmartPostDcrActions.Token)}.`);
114
116
  }
115
117
  return endpoint.toString();
116
118
  }
117
119
  function smartTokenPollEndpointFromTokenEndpoint(tokenEndpoint) {
118
120
  const endpoint = new URL(tokenEndpoint);
119
- endpoint.pathname = endpoint.pathname.replace(/\/identity\/openid\/smart\/token$/, '/identity/openid/smart/_batch-response');
121
+ endpoint.pathname = `${endpoint.pathname.slice(0, -smartTokenRouteSuffix(SmartPostDcrActions.Token).length)}${smartTokenRouteSuffix(SmartPostDcrActions.TokenResponse)}`;
120
122
  return endpoint.toString();
121
123
  }
124
+ function smartTokenRouteSuffix(action) {
125
+ return `/${GatewayRouteSections.Identity}/${GatewayRouteFormats.OpenId}/${IdentityAuthResourceTypes.Smart}/${action}`;
126
+ }
122
127
  async function resolveClientAssertion(input) {
123
128
  const explicit = String(input.clientAssertion || '').trim();
124
129
  if (explicit)
@@ -132,7 +137,10 @@ async function resolveClientAssertion(input) {
132
137
  });
133
138
  }
134
139
  function resolveTokenExchangeResult(exchange, normalizedScopes, tokenCacheKey, setTokenCache) {
135
- const exchangeBody = exchange.poll.body ?? {};
140
+ const pollBody = exchange.poll.body ?? {};
141
+ // Encrypted DIDComm returns the token in the authenticated message body;
142
+ // plain compatibility transports may still expose the token at the root.
143
+ const exchangeBody = pollBody.body || pollBody;
136
144
  const accessToken = String(exchangeBody.access_token || '').trim();
137
145
  if (exchange.poll.status >= 400 || !accessToken) {
138
146
  return {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gdc-sdk-node-ts",
3
- "version": "2.6.6",
3
+ "version": "2.6.7",
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.4",
42
- "gdc-sdk-core-ts": "2.4.6"
41
+ "gdc-common-utils-ts": "2.7.8",
42
+ "gdc-sdk-core-ts": "2.4.9"
43
43
  },
44
44
  "devDependencies": {
45
45
  "@types/node": "^20.14.10",