gdc-sdk-node-ts 2.3.0 → 2.3.1

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.
@@ -1,3 +1,4 @@
1
+ import type { FamilyRegistrationStatus } from 'gdc-common-utils-ts/utils/family-organization-summary';
1
2
  import type { PollOptions, SubmitAndPollResult } from './orchestration/client-port.js';
2
3
  import type { RouteContext } from './individual-onboarding.js';
3
4
  import type { OfferPreview } from './order-offer-summary.js';
@@ -59,6 +60,29 @@ export type IndividualOrganizationStartResult = {
59
60
  registration: SubmitAndPollResult;
60
61
  offerId: string;
61
62
  offerPreview: OfferPreview;
63
+ /** Lifecycle state returned by GW for this registration receipt. */
64
+ registrationStatus?: FamilyRegistrationStatus;
65
+ /** False when the same family registration is already active. */
66
+ orderConfirmationRequired: boolean;
67
+ /**
68
+ * Canonical subject identity projected from the GW registration receipt.
69
+ *
70
+ * It is optional only for compatibility with older/non-conforming GW
71
+ * responses. Current GW responses expose both `resource.id` and
72
+ * `Offer.offeredBy`, allowing every BFF/channel to consume the same derived
73
+ * identity without rebuilding a provider DID from route fragments or VAT.
74
+ */
75
+ identity?: IndividualOrganizationBootstrapIdentity;
76
+ };
77
+ export type IndividualOrganizationBootstrapIdentity = {
78
+ /** Technical UUID returned as `Bundle.data[0].resource.id`. */
79
+ resourceId: string;
80
+ /** Stable UUID-byte identifier serialized as multibase base58btc. */
81
+ individualId: string;
82
+ /** Authoritative provider DID returned by GW in `Offer.offeredBy`. */
83
+ providerDidWeb: string;
84
+ /** Canonical child DID built beneath the exact provider DID returned by GW. */
85
+ subjectDid: string;
62
86
  };
63
87
  type StartIndividualOrganizationDeps = {
64
88
  input: IndividualOrganizationBootstrapInput;
@@ -75,4 +99,13 @@ type StartIndividualOrganizationDeps = {
75
99
  getOfferPreviewFromResponse: (result: SubmitAndPollResult) => OfferPreview;
76
100
  };
77
101
  export declare function startIndividualOrganizationWithDeps(deps: StartIndividualOrganizationDeps): Promise<IndividualOrganizationStartResult>;
102
+ /**
103
+ * Projects the reusable subject identity from an individual bootstrap receipt.
104
+ *
105
+ * `providerDidWeb` is deliberately read from `Offer.offeredBy` and preserved
106
+ * byte-for-byte. The provider root uses the colon-delimited
107
+ * `:organization:taxid:` DID path. `buildIndividualDidWeb(...)` only adds the
108
+ * individual suffix and never rewrites that provider lineage.
109
+ */
110
+ export declare function readIndividualOrganizationBootstrapIdentity(responseBody: unknown): IndividualOrganizationBootstrapIdentity | undefined;
78
111
  export {};
@@ -1,5 +1,6 @@
1
1
  // Copyright 2026 Antifraud Services Inc. under the Apache License, Version 2.0.
2
- import { ClaimsOrganizationSchemaorg, ClaimsPersonSchemaorg, ClaimsServiceSchemaorg, } from 'gdc-common-utils-ts/constants';
2
+ import { ClaimsOfferSchemaorg, ClaimsOrganizationSchemaorg, ClaimsPersonSchemaorg, ClaimsServiceSchemaorg, } from 'gdc-common-utils-ts/constants';
3
+ import { buildIndividualDidWeb, encodeHexToMultibase58btc, extractPrimaryClaims, readFamilyOrganizationSummaryFromResponseBody, } from 'gdc-common-utils-ts';
3
4
  import { GwCoreLifecycleRequestType } from './constants/lifecycle.js';
4
5
  import { resolvePollOptionsFromSeconds } from './poll-options.js';
5
6
  export async function startIndividualOrganizationWithDeps(deps) {
@@ -27,6 +28,7 @@ export async function startIndividualOrganizationWithDeps(deps) {
27
28
  const controllerRole = String(deps.input.controllerRole || 'RESPRSN').trim();
28
29
  const claims = {
29
30
  '@context': 'org.schema',
31
+ ...(deps.input.additionalClaims || {}),
30
32
  [ClaimsOrganizationSchemaorg.alternateName]: alternateName,
31
33
  [ClaimsServiceSchemaorg.category]: deps.routeCtx.sector,
32
34
  [ClaimsPersonSchemaorg.hasOccupationalRoleValue]: controllerRole,
@@ -42,7 +44,6 @@ export async function startIndividualOrganizationWithDeps(deps) {
42
44
  [ClaimsPersonSchemaorg.telephone]: controllerTelephone,
43
45
  }
44
46
  : {}),
45
- ...(deps.input.additionalClaims || {}),
46
47
  };
47
48
  const registrationPayload = {
48
49
  jti: `jti-${createRuntimeUuid()}`,
@@ -77,12 +78,54 @@ export async function startIndividualOrganizationWithDeps(deps) {
77
78
  if (!offerId) {
78
79
  throw new Error('startIndividualOrganization failed: missing offerId in registration response.');
79
80
  }
81
+ const registrationSummary = readFamilyOrganizationSummaryFromResponseBody(registration.poll.body);
80
82
  return {
81
83
  registration,
82
84
  offerId,
83
85
  offerPreview: deps.getOfferPreviewFromResponse(registration),
86
+ registrationStatus: registrationSummary?.status,
87
+ orderConfirmationRequired: registrationSummary?.status !== 'already_exists',
88
+ identity: readIndividualOrganizationBootstrapIdentity(registration.poll.body),
89
+ };
90
+ }
91
+ /**
92
+ * Projects the reusable subject identity from an individual bootstrap receipt.
93
+ *
94
+ * `providerDidWeb` is deliberately read from `Offer.offeredBy` and preserved
95
+ * byte-for-byte. The provider root uses the colon-delimited
96
+ * `:organization:taxid:` DID path. `buildIndividualDidWeb(...)` only adds the
97
+ * individual suffix and never rewrites that provider lineage.
98
+ */
99
+ export function readIndividualOrganizationBootstrapIdentity(responseBody) {
100
+ const root = asRecord(responseBody);
101
+ const body = asRecord(root?.body) || root;
102
+ const entries = Array.isArray(body?.data) ? body.data : [];
103
+ const first = asRecord(entries[0]);
104
+ const resource = asRecord(first?.resource);
105
+ const resourceId = String(resource?.id || '').trim();
106
+ const claims = extractPrimaryClaims(responseBody);
107
+ const providerDidWeb = String(claims[ClaimsOfferSchemaorg.offeredBy] || '').trim();
108
+ if (!resourceId || !providerDidWeb)
109
+ return undefined;
110
+ let individualId;
111
+ try {
112
+ individualId = encodeHexToMultibase58btc(resourceId);
113
+ }
114
+ catch {
115
+ return undefined;
116
+ }
117
+ return {
118
+ resourceId,
119
+ individualId,
120
+ providerDidWeb,
121
+ subjectDid: buildIndividualDidWeb({ providerDidWeb, individualId }),
84
122
  };
85
123
  }
124
+ function asRecord(value) {
125
+ return value && typeof value === 'object' && !Array.isArray(value)
126
+ ? value
127
+ : undefined;
128
+ }
86
129
  function createRuntimeUuid() {
87
130
  const fromCrypto = globalThis.crypto?.randomUUID?.();
88
131
  if (fromCrypto) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gdc-sdk-node-ts",
3
- "version": "2.3.0",
3
+ "version": "2.3.1",
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.",
@@ -35,8 +35,8 @@
35
35
  "test:e2e:live-gw:clean": "bash ./scripts/run-live-gw-clean.sh"
36
36
  },
37
37
  "dependencies": {
38
- "gdc-common-utils-ts": "^2.3.0",
39
- "gdc-sdk-core-ts": "~2.3.0"
38
+ "gdc-common-utils-ts": "^2.3.1",
39
+ "gdc-sdk-core-ts": "~2.3.1"
40
40
  },
41
41
  "devDependencies": {
42
42
  "@types/node": "^20.14.10",