gdc-common-utils-ts 2.9.15 → 2.9.17

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
@@ -80,6 +80,12 @@ by its attached `Composition.section` graph.
80
80
 
81
81
  ## Identity Continuity
82
82
 
83
+ For every Individual Organization, the initial `Organization.member` is the
84
+ indexed subject itself and uses the HL7 relationship `ONESELF`. The creating
85
+ `Organization.owner` is the controller by default. `ONESELF` describes who the
86
+ subject is; controller authority such as `RESPRSN` describes who may act for
87
+ that subject. Never copy the owner/controller role into the SELF member.
88
+
83
89
  For ICA-backed organization activation, the representative/controller proof is
84
90
  intentionally split into two complementary dimensions:
85
91
 
@@ -72,7 +72,18 @@ export declare const HL7_V3_ROLE_CODE_LEGAL_REPRESENTATIVE: Hl7RoleEntry[];
72
72
  * is required.
73
73
  */
74
74
  export declare const HL7_RELATED_PERSON_FUNCTIONAL_ROLES: readonly Hl7RelatedPersonFunctionalRoleEntry[];
75
- /** Default role code for animal-care and non-human subjects. */
75
+ /** Default SELF-subject role for the initial Individual Organization member. */
76
+ export declare const HL7_DEFAULT_INDIVIDUAL_MEMBER_ROLE = "ONESELF";
77
+ /**
78
+ * @deprecated This is the human controller relationship, not the animal
79
+ * Individual Organization member role. Use
80
+ * `HL7_DEFAULT_CONTROLLER_RELATIONSHIP_ANIMAL_CARE`.
81
+ */
76
82
  export declare const HL7_DEFAULT_ROLE_ANIMAL_CARE = "RESPRSN";
83
+ /**
84
+ * Default human controller-to-animal authorization relationship.
85
+ * This never replaces the animal subject's `ONESELF` member role.
86
+ */
87
+ export declare const HL7_DEFAULT_CONTROLLER_RELATIONSHIP_ANIMAL_CARE = "RESPRSN";
77
88
  /** Default role code for health sector (patient self-represents). */
78
89
  export declare const HL7_DEFAULT_ROLE_HEALTH = "ONESELF";
@@ -290,7 +290,18 @@ export const HL7_RELATED_PERSON_FUNCTIONAL_ROLES = [
290
290
  codingSystem: HL7_CODING_SYSTEM_V3_ROLE_CODE,
291
291
  },
292
292
  ];
293
- /** Default role code for animal-care and non-human subjects. */
293
+ /** Default SELF-subject role for the initial Individual Organization member. */
294
+ export const HL7_DEFAULT_INDIVIDUAL_MEMBER_ROLE = 'ONESELF';
295
+ /**
296
+ * @deprecated This is the human controller relationship, not the animal
297
+ * Individual Organization member role. Use
298
+ * `HL7_DEFAULT_CONTROLLER_RELATIONSHIP_ANIMAL_CARE`.
299
+ */
294
300
  export const HL7_DEFAULT_ROLE_ANIMAL_CARE = 'RESPRSN';
301
+ /**
302
+ * Default human controller-to-animal authorization relationship.
303
+ * This never replaces the animal subject's `ONESELF` member role.
304
+ */
305
+ export const HL7_DEFAULT_CONTROLLER_RELATIONSHIP_ANIMAL_CARE = 'RESPRSN';
295
306
  /** Default role code for health sector (patient self-represents). */
296
307
  export const HL7_DEFAULT_ROLE_HEALTH = 'ONESELF';
@@ -49,8 +49,11 @@ export declare function buildNcbiTaxonomyUri(id: NcbiTaxonomyId): string;
49
49
  * Projects one controller-authorized animal card request to the existing
50
50
  * schema.org individual-organization claim envelope.
51
51
  *
52
- * The indexed subject is always an animal and its human actor is always a
53
- * responsible controller. Login identity proves only the application session;
52
+ * The indexed subject is always the first `Organization.member`, with the
53
+ * HL7 relationship `ONESELF`. The human that creates the envelope remains the
54
+ * separate `Organization.owner` controller; `RESPRSN` belongs to that
55
+ * controller authority and must never replace the subject's ONESELF role.
56
+ * Login identity proves only the application session;
54
57
  * GW must still verify the enrollment grant before accepting the request. A
55
58
  * card must not be shown as active until the authoritative GW transaction
56
59
  * returns success.
@@ -1,5 +1,6 @@
1
1
  import { ClaimsOrganizationSchemaorg, ClaimsServiceSchemaorg } from '../constants/schemaorg.js';
2
2
  import { DataspaceSectors } from '../constants/sectors.js';
3
+ import { HL7_DEFAULT_INDIVIDUAL_MEMBER_ROLE } from '../constants/hl7-roles.js';
3
4
  /**
4
5
  * @deprecated Animal-card vocabulary is owned by the consuming product SDK.
5
6
  * Retained only so consumers of 2.3.x can migrate without a breaking removal.
@@ -42,8 +43,11 @@ export function buildNcbiTaxonomyUri(id) {
42
43
  * Projects one controller-authorized animal card request to the existing
43
44
  * schema.org individual-organization claim envelope.
44
45
  *
45
- * The indexed subject is always an animal and its human actor is always a
46
- * responsible controller. Login identity proves only the application session;
46
+ * The indexed subject is always the first `Organization.member`, with the
47
+ * HL7 relationship `ONESELF`. The human that creates the envelope remains the
48
+ * separate `Organization.owner` controller; `RESPRSN` belongs to that
49
+ * controller authority and must never replace the subject's ONESELF role.
50
+ * Login identity proves only the application session;
47
51
  * GW must still verify the enrollment grant before accepting the request. A
48
52
  * card must not be shown as active until the authoritative GW transaction
49
53
  * returns success.
@@ -68,7 +72,7 @@ export function buildAnimalOnboardingClaims(input) {
68
72
  [ClaimsOrganizationSchemaorg.sameAs]: cardDidWeb,
69
73
  [ClaimsOrganizationSchemaorg.memberName]: alternateName,
70
74
  [ClaimsOrganizationSchemaorg.memberAdditionalType]: buildNcbiTaxonomyUri(input.ncbiTaxonomyId),
71
- [ClaimsOrganizationSchemaorg.memberRole]: 'RESPRSN',
75
+ [ClaimsOrganizationSchemaorg.memberRole]: HL7_DEFAULT_INDIVIDUAL_MEMBER_ROLE,
72
76
  ...(birthDate ? { [ClaimsOrganizationSchemaorg.memberBirthDate]: birthDate } : {}),
73
77
  ...(gender ? { [ClaimsOrganizationSchemaorg.memberGender]: gender } : {}),
74
78
  [ClaimsOrganizationSchemaorg.ownerEmail]: input.controllerEmail?.trim() || '',
@@ -162,7 +162,10 @@ export declare function toClinicalResourceCardView(entry: ClinicalResourceEntryL
162
162
  * Short claims take precedence over their expanded
163
163
  * `org.hl7.fhir.api.<ResourceType>.<search-param>` equivalent. Versioned
164
164
  * `org.hl7.fhir.<version>.*` namespaces are rejected because they are native
165
- * FHIR representation namespaces, never claims vocabularies.
165
+ * FHIR representation namespaces, never claims vocabularies. Native
166
+ * structural projections such as `<ResourceType>.meta.versionId` or array
167
+ * paths are ignored: they remain part of the FHIR resource, but are not API
168
+ * SearchParameters and must never become editable clinical fields.
166
169
  */
167
170
  export declare function toClinicalResourceClaimFieldViews(claims: ClinicalViewClaims): ClinicalResourceClaimFieldView[];
168
171
  /**
@@ -113,7 +113,10 @@ export function toClinicalResourceCardView(entry, options = {}) {
113
113
  * Short claims take precedence over their expanded
114
114
  * `org.hl7.fhir.api.<ResourceType>.<search-param>` equivalent. Versioned
115
115
  * `org.hl7.fhir.<version>.*` namespaces are rejected because they are native
116
- * FHIR representation namespaces, never claims vocabularies.
116
+ * FHIR representation namespaces, never claims vocabularies. Native
117
+ * structural projections such as `<ResourceType>.meta.versionId` or array
118
+ * paths are ignored: they remain part of the FHIR resource, but are not API
119
+ * SearchParameters and must never become editable clinical fields.
117
120
  */
118
121
  export function toClinicalResourceClaimFieldViews(claims) {
119
122
  const fields = new Map();
@@ -126,7 +129,9 @@ export function toClinicalResourceClaimFieldViews(claims) {
126
129
  }
127
130
  if (!rawClaim.startsWith('org.hl7.fhir.api.') && !/^[A-Z][A-Za-z0-9]+\./.test(rawClaim))
128
131
  continue;
129
- const claim = normalizeFhirApiClaimKey(rawClaim);
132
+ const claim = normalizeViewClaim(rawClaim);
133
+ if (!claim)
134
+ continue;
130
135
  const separator = claim.indexOf('.');
131
136
  if (separator <= 0 || separator === claim.length - 1)
132
137
  continue;
@@ -145,17 +150,28 @@ export function toClinicalResourceClaimFieldViews(claims) {
145
150
  continue;
146
151
  if (!/^[A-Z][A-Za-z0-9]+\./.test(claim))
147
152
  continue;
148
- const separator = claim.indexOf('.');
149
- if (separator <= 0 || separator === claim.length - 1)
153
+ const normalizedClaim = normalizeViewClaim(claim);
154
+ if (!normalizedClaim)
155
+ continue;
156
+ const separator = normalizedClaim.indexOf('.');
157
+ if (separator <= 0 || separator === normalizedClaim.length - 1)
150
158
  continue;
151
- fields.set(claim, {
152
- claim,
153
- parameter: claim.slice(separator + 1),
159
+ fields.set(normalizedClaim, {
160
+ claim: normalizedClaim,
161
+ parameter: normalizedClaim.slice(separator + 1),
154
162
  value,
155
163
  });
156
164
  }
157
165
  return [...fields.values()].sort((left, right) => left.claim.localeCompare(right.claim));
158
166
  }
167
+ function normalizeViewClaim(rawClaim) {
168
+ try {
169
+ return normalizeFhirApiClaimKey(rawClaim);
170
+ }
171
+ catch {
172
+ return undefined;
173
+ }
174
+ }
159
175
  /**
160
176
  * Maps all entries from a Bundle into minimal card views.
161
177
  */
@@ -1,4 +1,4 @@
1
- export type FamilyRegistrationStatus = 'new_created' | 'resume_required' | 'already_exists' | 'not_found';
1
+ export type FamilyRegistrationStatus = 'new_created' | 'draft_saved' | 'resume_required' | 'already_exists' | 'not_found';
2
2
  export type FamilyOrganizationSubjectInfo = Readonly<{
3
3
  identifierType?: string;
4
4
  identifierValue?: string;
@@ -1,4 +1,11 @@
1
1
  // Copyright 2026 Antifraud Services Inc. under the Apache License, Version 2.0.
2
+ const FAMILY_REGISTRATION_STATUSES = new Set([
3
+ 'new_created',
4
+ 'draft_saved',
5
+ 'resume_required',
6
+ 'already_exists',
7
+ 'not_found',
8
+ ]);
2
9
  function asRecord(value) {
3
10
  return value && typeof value === 'object' ? value : {};
4
11
  }
@@ -38,8 +45,12 @@ export function readFamilyOrganizationSummaryFromResponseBody(body) {
38
45
  ...asRecord(entryMeta.claims),
39
46
  ...asRecord(entryResourceMeta.claims),
40
47
  };
41
- const status = normalizeText(claims['org.schema.FamilyRegistration.status'] ?? claims.status);
42
- if (!status || status === 'not_found') {
48
+ const rawStatus = normalizeText(claims['org.schema.FamilyRegistration.status'] ?? claims.status);
49
+ if (!rawStatus || !FAMILY_REGISTRATION_STATUSES.has(rawStatus)) {
50
+ return null;
51
+ }
52
+ const status = rawStatus;
53
+ if (status === 'not_found') {
43
54
  return null;
44
55
  }
45
56
  return {
@@ -50,7 +61,8 @@ export function readFamilyOrganizationSummaryFromResponseBody(body) {
50
61
  identifierType: normalizeText(claims['org.schema.Organization.identifier.additionalType']),
51
62
  identifierValue: normalizeText(claims['org.schema.Organization.identifier.value']),
52
63
  alternateName: normalizeText(claims['org.schema.Organization.alternateName']),
53
- birthDate: normalizeText(claims['org.schema.Organization.foundingDate']),
64
+ birthDate: normalizeText(claims['org.schema.Person.birthDate']
65
+ ?? claims['org.schema.Organization.foundingDate']),
54
66
  ownerTelephone: normalizeText(claims['org.schema.Organization.owner.telephone']),
55
67
  },
56
68
  missingFields: normalizeStringList(claims['org.schema.FamilyRegistration.missingFields'] ?? claims.missingFields),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gdc-common-utils-ts",
3
- "version": "2.9.15",
3
+ "version": "2.9.17",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },