gdc-sdk-node-ts 2.9.6 → 2.9.8

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
@@ -750,9 +750,13 @@ A document Bundle keeps `Composition.author` (the organization, EHR/patient
750
750
  portal or individual that supplies the document) separate from
751
751
  `Composition.attester` (the registered personal or professional assignment
752
752
  that attested its content). A `RelatedPerson` or `PractitionerRole` is an
753
- attester, never a shortcut for replacing the source author. The protected BFF
754
- profile resolves both from its registered binding. DIDComm sender and signing
755
- keys remain audit/transport identities.
753
+ attester, never a shortcut for replacing the source author. For personal
754
+ content, the BFF selects `Owner` when the individual originated/dictated it or
755
+ `Creator` when the registered member originated it. Use
756
+ `assignmentIdentifier` for that RelatedPerson/PractitionerRole UUID; the old
757
+ wire name `authorIdentifier` is deprecated and does not choose the author. The
758
+ protected BFF profile resolves both from its registered binding. DIDComm sender
759
+ and signing keys remain audit/transport identities.
756
760
  The BFF never configures ledger routing or supplies channel/smart-contract
757
761
  names. GW owns that decision and returns one transaction receipt with
758
762
  per-resource CID/version evidence for a successful clinical Bundle.
@@ -1,6 +1,7 @@
1
1
  import type { JWK } from 'gdc-common-utils-ts/models/jwk';
2
2
  import type { ActorKind } from 'gdc-common-utils-ts/models/actor-session';
3
3
  import type { LegalOrganizationVerificationTransactionInput } from 'gdc-common-utils-ts/utils/legal-organization-verification-transaction';
4
+ import { type ClinicalCreatorBindingInput } from 'gdc-common-utils-ts/utils/fhir-ips-creator-identity';
4
5
  import { type AppInfo, type ConfidentialStorageProfile, type PollOptions, type SubmitAndPollResult, type ClinicalCreatorBinding, type ClinicalCreatorIpsExport, type ClinicalSourceAuthorSelection } from 'gdc-sdk-core-ts';
5
6
  import { OrganizationControllerSdk } from './orchestration/organization-controller-sdk.js';
6
7
  import { IndividualControllerSdk } from './orchestration/individual-controller-sdk.js';
@@ -130,7 +131,7 @@ export type ServerProfileEnrollmentInput = Readonly<{
130
131
  * locally. Enrollment adds the operational actor DID and registered DCR
131
132
  * client/key aliases; it never derives UUIDs from those aliases.
132
133
  */
133
- clinicalCreatorBinding?: ClinicalCreatorBinding;
134
+ clinicalCreatorBinding?: ClinicalCreatorBindingInput;
134
135
  /**
135
136
  * Signed actor/controller VP protected for later SMART operations. Required
136
137
  * for organization/professional/member actors. Individual-controller
@@ -344,9 +345,10 @@ export declare class ServerProfileSessionManager {
344
345
  ownerId: string;
345
346
  profileId: string;
346
347
  /**
347
- * Deprecated compatibility choice. The high-level clone/section helpers
348
- * derive the final professional or individual-member author boundary
349
- * from the returned protected binding.
348
+ * Closed personal-content origin. `Owner` means the individual originated
349
+ * or dictated it; `Creator` means the registered member/controller did.
350
+ * This never changes the authenticated sender or permits a free-form
351
+ * author reference. Professional content remains organization-authored.
350
352
  */
351
353
  sourceAuthor?: ClinicalSourceAuthorSelection;
352
354
  }>): Promise<ClinicalCreatorIpsExport>;
@@ -443,11 +445,11 @@ export declare class ServerProfileSessionManager {
443
445
  /**
444
446
  * Exports the stable FHIR IPS source author and attester attached to a server
445
447
  * profile. The returned protected binding lets high-level helpers use the
446
- * stable legal organization URN plus PractitionerRole for professionals, or
447
- * one RelatedPerson urn:uuid as both author and attester for individual
448
- * members/controllers. The optional selection remains only for backwards
449
- * compatibility. DIDComm sender and signing keys remain transport/audit
450
- * evidence and never become FHIR provenance.
448
+ * stable legal organization URN plus PractitionerRole for professionals. For
449
+ * individual members/controllers, `Owner` selects the individual as author and
450
+ * `Creator` selects the registered RelatedPerson; that RelatedPerson remains
451
+ * the attester. DIDComm sender and signing keys remain transport/audit evidence
452
+ * and never become FHIR provenance.
451
453
  */
452
454
  export declare function exportServerProfileClinicalCreatorIps(profile: ServerProfileRecord, options?: Readonly<{
453
455
  sourceAuthor?: ClinicalSourceAuthorSelection;
@@ -1,6 +1,8 @@
1
1
  // Copyright 2026 Antifraud Services Inc. under the Apache License, Version 2.0.
2
2
  import { randomBytes } from 'node:crypto';
3
3
  import { ActorKinds } from 'gdc-common-utils-ts/constants/actor-session';
4
+ import { normalizeClinicalCreatorBinding, } from 'gdc-common-utils-ts/utils/fhir-ips-creator-identity';
5
+ import { getHealthcareRoleByClaim } from 'gdc-common-utils-ts/constants/healthcare';
4
6
  import { readLegalOrganizationVerificationCredentialPairFromResponseBody, readServiceControllerCredentialFromResponseBody, } from 'gdc-common-utils-ts/utils/legal-organization-verification-result';
5
7
  import { addLegalRepresentativeCredential, addOrganizationCredential, addServiceControllerCredential, createVP, } from 'gdc-common-utils-ts/utils/vp-token';
6
8
  import { TransportProfiles, resolveClinicalCreatorIpsExport, } from 'gdc-sdk-core-ts';
@@ -33,7 +35,15 @@ export class ServerProfileSessionManager {
33
35
  return exportServerProfileClinicalCreatorIps(await this.requireOwnedProfile(input.ownerId, input.profileId), { sourceAuthor: input.sourceAuthor });
34
36
  }
35
37
  async enroll(input) {
36
- requireEnrollment(input);
38
+ const normalizedClinicalCreatorBinding = input.clinicalCreatorBinding
39
+ ? normalizeClinicalCreatorBinding(input.clinicalCreatorBinding)
40
+ : undefined;
41
+ requireEnrollment({
42
+ ...input,
43
+ ...(normalizedClinicalCreatorBinding
44
+ ? { clinicalCreatorBinding: normalizedClinicalCreatorBinding }
45
+ : {}),
46
+ });
37
47
  const seed = input.walletSeed || randomBytes(32).toString('base64url');
38
48
  if (input.walletSeed)
39
49
  requireBase64UrlSeed32(input.walletSeed);
@@ -78,8 +88,8 @@ export class ServerProfileSessionManager {
78
88
  .setPublicJwks(publicKeys.filter((entry) => entry.purpose !== 'document-at-rest').map((entry) => entry.publicJwk))
79
89
  .setActorDid(input.actorDid)
80
90
  .setProfileDid(input.profileDid);
81
- if (input.clinicalCreatorBinding) {
82
- activationDraft.setClinicalCreatorBinding(input.clinicalCreatorBinding);
91
+ if (normalizedClinicalCreatorBinding) {
92
+ activationDraft.setClinicalCreatorBinding(normalizedClinicalCreatorBinding);
83
93
  }
84
94
  const activationRequest = activationDraft.build();
85
95
  const activation = await client.activateProfileDeviceWithActivationRequest(activationRequest);
@@ -97,8 +107,8 @@ export class ServerProfileSessionManager {
97
107
  ...input.professionalProof,
98
108
  })
99
109
  : undefined);
100
- const clinicalCreatorBinding = input.clinicalCreatorBinding
101
- ? bindClinicalCreatorChannels(input.clinicalCreatorBinding, {
110
+ const clinicalCreatorBinding = normalizedClinicalCreatorBinding
111
+ ? bindClinicalCreatorChannels(normalizedClinicalCreatorBinding, {
102
112
  actorDid: input.actorDid,
103
113
  clientId,
104
114
  clientInstanceId,
@@ -831,11 +841,11 @@ function requireBase64UrlSeed32(seed) {
831
841
  /**
832
842
  * Exports the stable FHIR IPS source author and attester attached to a server
833
843
  * profile. The returned protected binding lets high-level helpers use the
834
- * stable legal organization URN plus PractitionerRole for professionals, or
835
- * one RelatedPerson urn:uuid as both author and attester for individual
836
- * members/controllers. The optional selection remains only for backwards
837
- * compatibility. DIDComm sender and signing keys remain transport/audit
838
- * evidence and never become FHIR provenance.
844
+ * stable legal organization URN plus PractitionerRole for professionals. For
845
+ * individual members/controllers, `Owner` selects the individual as author and
846
+ * `Creator` selects the registered RelatedPerson; that RelatedPerson remains
847
+ * the attester. DIDComm sender and signing keys remain transport/audit evidence
848
+ * and never become FHIR provenance.
839
849
  */
840
850
  export function exportServerProfileClinicalCreatorIps(profile, options = {}) {
841
851
  if (!profile.clinicalCreatorBinding) {
@@ -882,12 +892,25 @@ function requireEnrollment(input) {
882
892
  throw new Error('Profile enrollment professionalProof requires role.');
883
893
  }
884
894
  if (input.professionalProof && input.clinicalCreatorBinding
885
- && String(input.professionalProof.role).trim() !== String(input.clinicalCreatorBinding.role).trim()) {
895
+ && !sameGovernedRole(input.professionalProof.role, input.clinicalCreatorBinding.role)) {
886
896
  throw new Error('Clinical creator binding role must equal professionalProof.role.');
887
897
  }
888
898
  if (!input.allowedSubjectDids.length)
889
899
  throw new Error('Profile enrollment requires an allowed subject.');
890
900
  }
901
+ function sameGovernedRole(left, right) {
902
+ const resolveRole = (value) => {
903
+ const normalized = String(value || '').trim();
904
+ return getHealthcareRoleByClaim(normalized)
905
+ || getHealthcareRoleByClaim(normalized.split('|').pop() || '');
906
+ };
907
+ const leftRole = resolveRole(left);
908
+ const rightRole = resolveRole(right);
909
+ return Boolean(leftRole
910
+ && rightRole
911
+ && leftRole.codingSystem === rightRole.codingSystem
912
+ && leftRole.code === rightRole.code);
913
+ }
891
914
  function unique(values) {
892
915
  return [...new Set(values.map((value) => String(value).trim()).filter(Boolean))].sort();
893
916
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gdc-sdk-node-ts",
3
- "version": "2.9.6",
3
+ "version": "2.9.8",
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.9.7",
42
- "gdc-sdk-core-ts": "2.9.5"
41
+ "gdc-common-utils-ts": "2.9.10",
42
+ "gdc-sdk-core-ts": "2.9.7"
43
43
  },
44
44
  "devDependencies": {
45
45
  "@types/node": "^20.14.10",