gdc-common-utils-ts 2.0.4 → 2.0.5

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.
Files changed (30) hide show
  1. package/dist/constants/verifiable-credentials.d.ts +6 -0
  2. package/dist/constants/verifiable-credentials.js +6 -0
  3. package/dist/examples/employee.d.ts +15 -0
  4. package/dist/examples/employee.js +15 -0
  5. package/dist/examples/individual-controller.d.ts +25 -0
  6. package/dist/examples/individual-controller.js +23 -0
  7. package/dist/examples/legal-organization-verification-transaction.js +10 -0
  8. package/dist/examples/shared.d.ts +7 -0
  9. package/dist/examples/shared.js +8 -1
  10. package/dist/utils/bundle-reader.d.ts +2 -0
  11. package/dist/utils/bundle-reader.js +14 -0
  12. package/dist/utils/clinical-bundle-summary.d.ts +20 -0
  13. package/dist/utils/clinical-bundle-summary.js +34 -0
  14. package/dist/utils/didcomm-submit-policy.d.ts +20 -3
  15. package/dist/utils/didcomm-submit-policy.js +37 -6
  16. package/dist/utils/didcomm-submit.d.ts +10 -3
  17. package/dist/utils/didcomm-submit.js +12 -5
  18. package/dist/utils/family-organization-summary.d.ts +24 -0
  19. package/dist/utils/family-organization-summary.js +59 -0
  20. package/dist/utils/index.d.ts +4 -0
  21. package/dist/utils/index.js +4 -0
  22. package/dist/utils/legal-organization-onboarding-editor.d.ts +156 -0
  23. package/dist/utils/legal-organization-onboarding-editor.js +350 -0
  24. package/dist/utils/legal-organization-verification-transaction.d.ts +40 -0
  25. package/dist/utils/legal-organization-verification-transaction.js +53 -0
  26. package/dist/utils/professional-smart.d.ts +21 -0
  27. package/dist/utils/professional-smart.js +37 -0
  28. package/dist/utils/related-person-list.d.ts +14 -0
  29. package/dist/utils/related-person-list.js +31 -0
  30. package/package.json +1 -1
@@ -30,5 +30,11 @@ export declare const ActivationCredentialTypes: Readonly<{
30
30
  LegalRepresentativeCredential: "LegalRepresentativeCredential";
31
31
  PersonCredential: "PersonCredential";
32
32
  }>;
33
+ /**
34
+ * Canonical credential subtype names used by professional/member access flows.
35
+ */
36
+ export declare const ProfessionalCredentialTypes: Readonly<{
37
+ EmployeeCredential: "EmployeeCredential";
38
+ }>;
33
39
  export declare const ORGANIZATION_ACTIVATION_VC_TYPES: readonly ("OrganizationCredential" | "LegalOrganizationCredential")[];
34
40
  export declare const REPRESENTATIVE_ACTIVATION_VC_TYPES: readonly ("LegalRepresentativeCredential" | "PersonCredential")[];
@@ -32,6 +32,12 @@ export const ActivationCredentialTypes = Object.freeze({
32
32
  LegalRepresentativeCredential: 'LegalRepresentativeCredential',
33
33
  PersonCredential: 'PersonCredential',
34
34
  });
35
+ /**
36
+ * Canonical credential subtype names used by professional/member access flows.
37
+ */
38
+ export const ProfessionalCredentialTypes = Object.freeze({
39
+ EmployeeCredential: 'EmployeeCredential',
40
+ });
35
41
  export const ORGANIZATION_ACTIVATION_VC_TYPES = Object.freeze([
36
42
  ActivationCredentialTypes.OrganizationCredential,
37
43
  ActivationCredentialTypes.LegalOrganizationCredential,
@@ -39,3 +39,18 @@ export declare const EXAMPLE_EMPLOYEE_DIRECTORY_RECORDS: readonly [Readonly<{
39
39
  status: "active" | "inactive" | "purged";
40
40
  }>];
41
41
  export declare function buildExampleEmployeeClaims(record: ExampleEmployeeRecord): Readonly<Record<string, string>>;
42
+ /**
43
+ * Canonical employee search/list response body reused by runtime and doc tests.
44
+ *
45
+ * This keeps one stable GW-style envelope for high-level tutorials that want
46
+ * to show employee directory flows without reauthoring `meta.claims` by hand.
47
+ */
48
+ export declare const EXAMPLE_EMPLOYEE_SEARCH_RESPONSE_BODY: Readonly<{
49
+ readonly data: {
50
+ id: string;
51
+ meta: {
52
+ status: "active" | "inactive" | "purged";
53
+ claims: Readonly<Record<string, string>>;
54
+ };
55
+ }[];
56
+ }>;
@@ -37,3 +37,18 @@ export function buildExampleEmployeeClaims(record) {
37
37
  [ClaimsPersonSchemaorg.hasOccupationalRoleValue]: record.role,
38
38
  });
39
39
  }
40
+ /**
41
+ * Canonical employee search/list response body reused by runtime and doc tests.
42
+ *
43
+ * This keeps one stable GW-style envelope for high-level tutorials that want
44
+ * to show employee directory flows without reauthoring `meta.claims` by hand.
45
+ */
46
+ export const EXAMPLE_EMPLOYEE_SEARCH_RESPONSE_BODY = Object.freeze({
47
+ data: EXAMPLE_EMPLOYEE_DIRECTORY_RECORDS.map((record) => ({
48
+ id: record.identifier,
49
+ meta: {
50
+ status: record.status,
51
+ claims: buildExampleEmployeeClaims(record),
52
+ },
53
+ })),
54
+ });
@@ -98,3 +98,28 @@ export declare const EXAMPLE_DIGITAL_TWIN_COMPOSITION_INPUT: {
98
98
  };
99
99
  export declare const EXAMPLE_CLINICAL_BUNDLE_SEARCH_INPUT: ExampleClinicalBundleSearchInput;
100
100
  export declare const EXAMPLE_LATEST_IPS_SEARCH_INPUT: ExampleLatestIpsSearchInput;
101
+ export declare const EXAMPLE_FAMILY_ORGANIZATION_SEARCH_INPUT: {
102
+ readonly controllerPhone: "+34600000001";
103
+ readonly usualname: "Ana";
104
+ readonly birthDate: "2010-05-20";
105
+ };
106
+ export declare const EXAMPLE_FAMILY_ORGANIZATION_SEARCH_RESPONSE_BODY: {
107
+ readonly body: {
108
+ readonly data: readonly [{
109
+ readonly type: "Family-search-result-v1.0";
110
+ readonly meta: {
111
+ readonly claims: {
112
+ readonly 'org.schema.FamilyRegistration.status': "already_exists";
113
+ readonly 'org.schema.Offer.identifier': "offer-uuid-001";
114
+ readonly 'org.schema.Organization.identifier.value': "org-uuid-001";
115
+ readonly 'org.schema.Organization.alternateName': "Ana";
116
+ readonly 'org.schema.Organization.owner.telephone': "+34600000001";
117
+ readonly 'org.schema.Organization.foundingDate': "2010-05-20";
118
+ };
119
+ };
120
+ readonly resource: {
121
+ readonly id: "org-uuid-001";
122
+ };
123
+ }];
124
+ };
125
+ };
@@ -69,3 +69,26 @@ export const EXAMPLE_CLINICAL_BUNDLE_SEARCH_INPUT = {
69
69
  export const EXAMPLE_LATEST_IPS_SEARCH_INPUT = {
70
70
  subject: EXAMPLE_SUBJECT_DID,
71
71
  };
72
+ export const EXAMPLE_FAMILY_ORGANIZATION_SEARCH_INPUT = {
73
+ controllerPhone: '+34600000001',
74
+ usualname: 'Ana',
75
+ birthDate: '2010-05-20',
76
+ };
77
+ export const EXAMPLE_FAMILY_ORGANIZATION_SEARCH_RESPONSE_BODY = {
78
+ body: {
79
+ data: [{
80
+ type: 'Family-search-result-v1.0',
81
+ meta: {
82
+ claims: {
83
+ 'org.schema.FamilyRegistration.status': 'already_exists',
84
+ 'org.schema.Offer.identifier': 'offer-uuid-001',
85
+ 'org.schema.Organization.identifier.value': 'org-uuid-001',
86
+ 'org.schema.Organization.alternateName': EXAMPLE_FAMILY_ORGANIZATION_SEARCH_INPUT.usualname,
87
+ 'org.schema.Organization.owner.telephone': EXAMPLE_FAMILY_ORGANIZATION_SEARCH_INPUT.controllerPhone,
88
+ 'org.schema.Organization.foundingDate': EXAMPLE_FAMILY_ORGANIZATION_SEARCH_INPUT.birthDate,
89
+ },
90
+ },
91
+ resource: { id: 'org-uuid-001' },
92
+ }],
93
+ },
94
+ };
@@ -1,5 +1,6 @@
1
1
  // Copyright 2026 Antifraud Services Inc. under the Apache License, Version 2.0.
2
2
  import { ClaimsOrganizationSchemaorg, ClaimsPersonSchemaorg, ClaimsServiceSchemaorg, } from '../constants/schemaorg.js';
3
+ import { serializeServiceCapabilityTokens, ServiceCapability, } from '../constants/service-capabilities.js';
3
4
  import { buildLegalOrganizationVerificationTransactionBundle, } from '../utils/legal-organization-verification-transaction.js';
4
5
  import { EXAMPLE_CONTROLLER_BINDING, EXAMPLE_EMAIL_CONTROLLER_ORG, EXAMPLE_JURISDICTION, EXAMPLE_ORGANIZATION_LEGAL_NAME, EXAMPLE_LEGAL_ORGANIZATION_TAX_ID, EXAMPLE_SECTOR, EXAMPLE_SIGNED_TERMS_PDF_URL, EXAMPLE_TENANT_SERVICE_DID, } from './shared.js';
5
6
  /**
@@ -11,6 +12,11 @@ import { EXAMPLE_CONTROLLER_BINDING, EXAMPLE_EMAIL_CONTROLLER_ORG, EXAMPLE_JURIS
11
12
  * that wraps an ICA `_verify`
12
13
  * - the example keeps the controller business binding separate from any
13
14
  * technical DIDComm communication key
15
+ *
16
+ * Contract note:
17
+ * - the same request must already declare the requested tenant service
18
+ * capabilities because GW uses them to prepare the pending Offer that the
19
+ * client will later confirm via `Order/_batch`
14
20
  */
15
21
  const exampleControllerBinding = {
16
22
  did: EXAMPLE_CONTROLLER_BINDING.did,
@@ -36,6 +42,10 @@ export const EXAMPLE_LEGAL_ORGANIZATION_VERIFICATION_TRANSACTION_BUNDLE = buildL
36
42
  [ClaimsServiceSchemaorg.category]: EXAMPLE_SECTOR,
37
43
  [ClaimsServiceSchemaorg.identifier]: EXAMPLE_TENANT_SERVICE_DID,
38
44
  [ClaimsServiceSchemaorg.url]: `https://operator.example.net/acme/cds-${String(EXAMPLE_JURISDICTION).toLowerCase()}/v1/${EXAMPLE_SECTOR}`,
45
+ [ClaimsServiceSchemaorg.serviceType]: serializeServiceCapabilityTokens([
46
+ ServiceCapability.IndexProvider,
47
+ ServiceCapability.DigitalTwinReader,
48
+ ]),
39
49
  },
40
50
  controller: exampleControllerBinding,
41
51
  organization: {
@@ -91,6 +91,13 @@ export declare const EXAMPLE_TENANT_ROUTE_CONTEXT: {
91
91
  export declare const EXAMPLE_HOST_ROUTE_CONTEXT: {
92
92
  readonly hostCoverageScope: "EU";
93
93
  readonly jurisdiction: "ES";
94
+ /**
95
+ * Host route segment used in `/host/cds-{hostCoverageScope}/v1/{hostNetwork}/...`.
96
+ *
97
+ * This is intentionally not the tenant business sector.
98
+ */
99
+ readonly hostNetwork: "test";
100
+ /** @deprecated Use `hostNetwork`. */
94
101
  readonly sector: "test";
95
102
  };
96
103
  export declare const EXAMPLE_CONTROLLER_DID: "did:web:people.acme.org:controllers:primary";
@@ -106,7 +106,14 @@ export const EXAMPLE_TENANT_ROUTE_CONTEXT = {
106
106
  export const EXAMPLE_HOST_ROUTE_CONTEXT = {
107
107
  hostCoverageScope: EXAMPLE_HOST_COVERAGE_SCOPE,
108
108
  jurisdiction: EXAMPLE_JURISDICTION,
109
- sector: HostNetworkTypes.Test,
109
+ /**
110
+ * Host route segment used in `/host/cds-{hostCoverageScope}/v1/{hostNetwork}/...`.
111
+ *
112
+ * This is intentionally not the tenant business sector.
113
+ */
114
+ hostNetwork: EXAMPLE_NETWORK_TYPE,
115
+ /** @deprecated Use `hostNetwork`. */
116
+ sector: EXAMPLE_NETWORK_TYPE,
110
117
  };
111
118
  export const EXAMPLE_CONTROLLER_DID = 'did:web:people.acme.org:controllers:primary';
112
119
  export const EXAMPLE_CONTROLLER_EMAIL = EXAMPLE_EMAIL_CONTROLLER_ORG;
@@ -84,3 +84,5 @@ export declare class BundleReader {
84
84
  private buildSeverityBucket;
85
85
  private resolveEntryIdentifier;
86
86
  }
87
+ export declare function unwrapBundleLikeResponseBody(input: unknown): Record<string, unknown>;
88
+ export declare function readFirstBundleResourceFromResponseBody(input: unknown): Record<string, unknown> | undefined;
@@ -221,3 +221,17 @@ export class BundleReader {
221
221
  function normalizeOptionalString(value) {
222
222
  return typeof value === 'string' && value.trim() ? value.trim() : undefined;
223
223
  }
224
+ export function unwrapBundleLikeResponseBody(input) {
225
+ const body = input && typeof input === 'object' ? input : {};
226
+ const nested = body.body && typeof body.body === 'object' ? body.body : undefined;
227
+ const candidate = nested && (Array.isArray(nested.data) || Array.isArray(nested.entry))
228
+ ? nested
229
+ : body;
230
+ return candidate && typeof candidate === 'object' ? candidate : {};
231
+ }
232
+ export function readFirstBundleResourceFromResponseBody(input) {
233
+ const reader = new BundleReader(unwrapBundleLikeResponseBody(input));
234
+ const first = reader.getEntries()[0];
235
+ const resource = first?.resource;
236
+ return resource && typeof resource === 'object' ? resource : undefined;
237
+ }
@@ -0,0 +1,20 @@
1
+ import type { ClinicalResourceBundleLike } from './clinical-resource-view.js';
2
+ export type ClinicalBundleTypeSummary = Readonly<{
3
+ resourceType: string;
4
+ count: number;
5
+ }>;
6
+ export type ClinicalBundleSummary = Readonly<{
7
+ totalEntries: number;
8
+ resourceTypes: ClinicalBundleTypeSummary[];
9
+ xhtmlEntries: number;
10
+ notedEntries: number;
11
+ }>;
12
+ /**
13
+ * Builds one high-level summary from a FHIR/IPS bundle already normalized to
14
+ * the common clinical-resource view contract.
15
+ *
16
+ * Intended for BFF/frontend/call-center code that needs to announce simple
17
+ * menu facts such as "how many medications are present" without hand-reading
18
+ * bundle entries.
19
+ */
20
+ export declare function summarizeClinicalBundle(bundle: ClinicalResourceBundleLike): ClinicalBundleSummary;
@@ -0,0 +1,34 @@
1
+ // Copyright 2026 Antifraud Services Inc. under the Apache License, Version 2.0.
2
+ import { toClinicalResourceExpandedViews } from './clinical-resource-view.js';
3
+ /**
4
+ * Builds one high-level summary from a FHIR/IPS bundle already normalized to
5
+ * the common clinical-resource view contract.
6
+ *
7
+ * Intended for BFF/frontend/call-center code that needs to announce simple
8
+ * menu facts such as "how many medications are present" without hand-reading
9
+ * bundle entries.
10
+ */
11
+ export function summarizeClinicalBundle(bundle) {
12
+ const views = toClinicalResourceExpandedViews(bundle);
13
+ const counts = new Map();
14
+ let xhtmlEntries = 0;
15
+ let notedEntries = 0;
16
+ views.forEach((view) => {
17
+ const resourceType = String(view.common.resourceType || 'Unknown').trim() || 'Unknown';
18
+ counts.set(resourceType, (counts.get(resourceType) || 0) + 1);
19
+ if (String(view.xhtml || '').trim()) {
20
+ xhtmlEntries += 1;
21
+ }
22
+ if (Array.isArray(view.notes) && view.notes.length > 0) {
23
+ notedEntries += 1;
24
+ }
25
+ });
26
+ return {
27
+ totalEntries: views.length,
28
+ resourceTypes: [...counts.entries()]
29
+ .map(([resourceType, count]) => ({ resourceType, count }))
30
+ .sort((left, right) => left.resourceType.localeCompare(right.resourceType)),
31
+ xhtmlEntries,
32
+ notedEntries,
33
+ };
34
+ }
@@ -1,10 +1,27 @@
1
- export type CommunicationMode = 'plain' | 'strict' | 'auto-detect';
1
+ export declare const DIDCOMM_COMMUNICATION_MODES: Readonly<{
2
+ readonly Plain: "plain";
3
+ readonly Strict: "strict";
4
+ readonly AutoDetect: "auto-detect";
5
+ }>;
6
+ export type CommunicationMode = typeof DIDCOMM_COMMUNICATION_MODES[keyof typeof DIDCOMM_COMMUNICATION_MODES];
7
+ export declare const DIDCOMM_SUBMIT_KINDS: Readonly<{
8
+ readonly Plain: "plain";
9
+ readonly Encrypted: "encrypted";
10
+ }>;
11
+ export type DidcommSubmitKind = typeof DIDCOMM_SUBMIT_KINDS[keyof typeof DIDCOMM_SUBMIT_KINDS];
2
12
  export type DidcommSubmissionCapabilities = {
3
13
  hasRecipientEncryptionJwk: boolean;
4
14
  };
15
+ export declare const DIDCOMM_SUBMISSION_REASONS: Readonly<{
16
+ readonly PlainMode: "plain-mode";
17
+ readonly StrictMode: "strict-mode";
18
+ readonly AutoDetectEncrypted: "auto-detect-encrypted";
19
+ readonly AutoDetectPlain: "auto-detect-plain";
20
+ }>;
21
+ export type DidcommSubmissionReason = typeof DIDCOMM_SUBMISSION_REASONS[keyof typeof DIDCOMM_SUBMISSION_REASONS];
5
22
  export type DidcommSubmissionPlan = {
6
23
  mode: CommunicationMode;
7
- submitKind: 'plain' | 'encrypted';
8
- reason: 'plain-mode' | 'strict-mode' | 'auto-detect-encrypted' | 'auto-detect-plain';
24
+ submitKind: DidcommSubmitKind;
25
+ reason: DidcommSubmissionReason;
9
26
  };
10
27
  export declare function resolveDidcommSubmissionPlan(mode: CommunicationMode, capabilities: DidcommSubmissionCapabilities): DidcommSubmissionPlan;
@@ -1,15 +1,46 @@
1
+ export const DIDCOMM_COMMUNICATION_MODES = Object.freeze({
2
+ Plain: 'plain',
3
+ Strict: 'strict',
4
+ AutoDetect: 'auto-detect',
5
+ });
6
+ export const DIDCOMM_SUBMIT_KINDS = Object.freeze({
7
+ Plain: 'plain',
8
+ Encrypted: 'encrypted',
9
+ });
10
+ export const DIDCOMM_SUBMISSION_REASONS = Object.freeze({
11
+ PlainMode: 'plain-mode',
12
+ StrictMode: 'strict-mode',
13
+ AutoDetectEncrypted: 'auto-detect-encrypted',
14
+ AutoDetectPlain: 'auto-detect-plain',
15
+ });
1
16
  export function resolveDidcommSubmissionPlan(mode, capabilities) {
2
- if (mode === 'plain') {
3
- return { mode, submitKind: 'plain', reason: 'plain-mode' };
17
+ if (mode === DIDCOMM_COMMUNICATION_MODES.Plain) {
18
+ return {
19
+ mode,
20
+ submitKind: DIDCOMM_SUBMIT_KINDS.Plain,
21
+ reason: DIDCOMM_SUBMISSION_REASONS.PlainMode,
22
+ };
4
23
  }
5
- if (mode === 'strict') {
24
+ if (mode === DIDCOMM_COMMUNICATION_MODES.Strict) {
6
25
  if (!capabilities.hasRecipientEncryptionJwk) {
7
26
  throw new Error('strict mode requires recipient encryption JWK.');
8
27
  }
9
- return { mode, submitKind: 'encrypted', reason: 'strict-mode' };
28
+ return {
29
+ mode,
30
+ submitKind: DIDCOMM_SUBMIT_KINDS.Encrypted,
31
+ reason: DIDCOMM_SUBMISSION_REASONS.StrictMode,
32
+ };
10
33
  }
11
34
  if (capabilities.hasRecipientEncryptionJwk) {
12
- return { mode, submitKind: 'encrypted', reason: 'auto-detect-encrypted' };
35
+ return {
36
+ mode,
37
+ submitKind: DIDCOMM_SUBMIT_KINDS.Encrypted,
38
+ reason: DIDCOMM_SUBMISSION_REASONS.AutoDetectEncrypted,
39
+ };
13
40
  }
14
- return { mode, submitKind: 'plain', reason: 'auto-detect-plain' };
41
+ return {
42
+ mode,
43
+ submitKind: DIDCOMM_SUBMIT_KINDS.Plain,
44
+ reason: DIDCOMM_SUBMISSION_REASONS.AutoDetectPlain,
45
+ };
15
46
  }
@@ -1,4 +1,11 @@
1
- import { CommunicationMode } from './didcomm-submit-policy';
1
+ import { CommunicationMode, type DidcommSubmitKind } from './didcomm-submit-policy';
2
+ export declare const DIDCOMM_PLAINTEXT_JSON_MEDIA_TYPE: "application/didcomm-plaintext+json";
3
+ export declare const DIDCOMM_ENCRYPTED_JSON_MEDIA_TYPE: "application/didcomm-encrypted+json";
4
+ export declare const DIDCOMM_DEFAULT_ACCEPT_HEADER: "application/json, application/didcomm-plaintext+json, */*";
5
+ export declare const DIDCOMM_CONTENT_TYPE_BY_SUBMIT_KIND: Readonly<{
6
+ readonly plain: "application/didcomm-plaintext+json";
7
+ readonly encrypted: "application/didcomm-encrypted+json";
8
+ }>;
2
9
  export type DidcommFetchInit = {
3
10
  method: 'POST';
4
11
  headers: Record<string, string>;
@@ -28,8 +35,8 @@ export type DidcommSubmitResult = {
28
35
  status: number;
29
36
  location?: string;
30
37
  body: unknown;
31
- submitKind: 'plain' | 'encrypted';
32
- contentType: 'application/didcomm-plaintext+json' | 'application/didcomm-encrypted+json';
38
+ submitKind: DidcommSubmitKind;
39
+ contentType: typeof DIDCOMM_PLAINTEXT_JSON_MEDIA_TYPE | typeof DIDCOMM_ENCRYPTED_JSON_MEDIA_TYPE;
33
40
  };
34
41
  /**
35
42
  * Submits a DIDComm payload using either plaintext or encrypted transport,
@@ -1,4 +1,11 @@
1
- import { resolveDidcommSubmissionPlan } from './didcomm-submit-policy.js';
1
+ import { DIDCOMM_SUBMIT_KINDS, resolveDidcommSubmissionPlan, } from './didcomm-submit-policy.js';
2
+ export const DIDCOMM_PLAINTEXT_JSON_MEDIA_TYPE = 'application/didcomm-plaintext+json';
3
+ export const DIDCOMM_ENCRYPTED_JSON_MEDIA_TYPE = 'application/didcomm-encrypted+json';
4
+ export const DIDCOMM_DEFAULT_ACCEPT_HEADER = `application/json, ${DIDCOMM_PLAINTEXT_JSON_MEDIA_TYPE}, */*`;
5
+ export const DIDCOMM_CONTENT_TYPE_BY_SUBMIT_KIND = Object.freeze({
6
+ [DIDCOMM_SUBMIT_KINDS.Plain]: DIDCOMM_PLAINTEXT_JSON_MEDIA_TYPE,
7
+ [DIDCOMM_SUBMIT_KINDS.Encrypted]: DIDCOMM_ENCRYPTED_JSON_MEDIA_TYPE,
8
+ });
2
9
  function getHeaderValue(headers, name) {
3
10
  if (!headers || typeof headers.get !== 'function') {
4
11
  return undefined;
@@ -40,12 +47,12 @@ export async function submitDidcomm(input) {
40
47
  });
41
48
  const headers = {
42
49
  ...(input.defaultHeaders ?? {}),
43
- Accept: 'application/json, application/didcomm-plaintext+json, */*',
50
+ Accept: DIDCOMM_DEFAULT_ACCEPT_HEADER,
44
51
  };
45
52
  let body;
46
53
  let contentType;
47
- if (plan.submitKind === 'plain') {
48
- contentType = 'application/didcomm-plaintext+json';
54
+ if (plan.submitKind === DIDCOMM_SUBMIT_KINDS.Plain) {
55
+ contentType = DIDCOMM_CONTENT_TYPE_BY_SUBMIT_KIND[DIDCOMM_SUBMIT_KINDS.Plain];
49
56
  body = JSON.stringify(input.payload);
50
57
  }
51
58
  else {
@@ -60,7 +67,7 @@ export async function submitDidcomm(input) {
60
67
  }
61
68
  const compactJws = await input.signCompactJws(input.payload);
62
69
  body = await input.encryptCompactJwe(compactJws, input.recipientEncryptionJwk);
63
- contentType = 'application/didcomm-encrypted+json';
70
+ contentType = DIDCOMM_CONTENT_TYPE_BY_SUBMIT_KIND[DIDCOMM_SUBMIT_KINDS.Encrypted];
64
71
  }
65
72
  headers['Content-Type'] = contentType;
66
73
  if (input.bearerToken) {
@@ -0,0 +1,24 @@
1
+ export type FamilyRegistrationStatus = 'new_created' | 'resume_required' | 'already_exists' | 'not_found';
2
+ export type FamilyOrganizationSubjectInfo = Readonly<{
3
+ identifierType?: string;
4
+ identifierValue?: string;
5
+ alternateName?: string;
6
+ birthDate?: string;
7
+ ownerTelephone?: string;
8
+ }>;
9
+ export type FamilyOrganizationSummary = Readonly<{
10
+ status: FamilyRegistrationStatus;
11
+ offerId?: string;
12
+ organizationId?: string;
13
+ subjectInfo?: FamilyOrganizationSubjectInfo;
14
+ missingFields?: string[];
15
+ updatedAt?: string;
16
+ }>;
17
+ /**
18
+ * Reads the first family-organization summary returned by current GW-style
19
+ * search or batch responses.
20
+ *
21
+ * Returns `null` when the response does not contain one usable summary or when
22
+ * the registration status is explicitly `not_found`.
23
+ */
24
+ export declare function readFamilyOrganizationSummaryFromResponseBody(body: unknown): FamilyOrganizationSummary | null;
@@ -0,0 +1,59 @@
1
+ // Copyright 2026 Antifraud Services Inc. under the Apache License, Version 2.0.
2
+ function asRecord(value) {
3
+ return value && typeof value === 'object' ? value : {};
4
+ }
5
+ function normalizeText(value) {
6
+ const normalized = String(value ?? '').trim();
7
+ return normalized || undefined;
8
+ }
9
+ function normalizeStringList(value) {
10
+ if (!Array.isArray(value)) {
11
+ return undefined;
12
+ }
13
+ const items = value.map((item) => normalizeText(item)).filter(Boolean);
14
+ return items.length ? items : undefined;
15
+ }
16
+ /**
17
+ * Reads the first family-organization summary returned by current GW-style
18
+ * search or batch responses.
19
+ *
20
+ * Returns `null` when the response does not contain one usable summary or when
21
+ * the registration status is explicitly `not_found`.
22
+ */
23
+ export function readFamilyOrganizationSummaryFromResponseBody(body) {
24
+ const root = asRecord(body);
25
+ const bodyNode = asRecord(root.body);
26
+ const rawEntries = Array.isArray(bodyNode.data)
27
+ ? bodyNode.data
28
+ : (Array.isArray(root.data) ? root.data : []);
29
+ const firstEntry = rawEntries[0];
30
+ if (!firstEntry || typeof firstEntry !== 'object') {
31
+ return null;
32
+ }
33
+ const entry = asRecord(firstEntry);
34
+ const entryMeta = asRecord(entry.meta);
35
+ const entryResource = asRecord(entry.resource);
36
+ const entryResourceMeta = asRecord(entryResource.meta);
37
+ const claims = {
38
+ ...asRecord(entryMeta.claims),
39
+ ...asRecord(entryResourceMeta.claims),
40
+ };
41
+ const status = normalizeText(claims['org.schema.FamilyRegistration.status'] ?? claims.status);
42
+ if (!status || status === 'not_found') {
43
+ return null;
44
+ }
45
+ return {
46
+ status,
47
+ offerId: normalizeText(claims['org.schema.Offer.identifier']),
48
+ organizationId: normalizeText(claims['org.schema.Organization.identifier.value'] ?? entryResource.id),
49
+ subjectInfo: {
50
+ identifierType: normalizeText(claims['org.schema.Organization.identifier.additionalType']),
51
+ identifierValue: normalizeText(claims['org.schema.Organization.identifier.value']),
52
+ alternateName: normalizeText(claims['org.schema.Organization.alternateName']),
53
+ birthDate: normalizeText(claims['org.schema.Organization.foundingDate']),
54
+ ownerTelephone: normalizeText(claims['org.schema.Organization.owner.telephone']),
55
+ },
56
+ missingFields: normalizeStringList(claims['org.schema.FamilyRegistration.missingFields'] ?? claims.missingFields),
57
+ updatedAt: normalizeText(claims['org.schema.FamilyRegistration.updatedAt'] ?? claims.updatedAt),
58
+ };
59
+ }
@@ -28,6 +28,7 @@ export * from './discovery-normalization';
28
28
  export * from './format-converter';
29
29
  export * from './fhir-cid';
30
30
  export * from './fhir-search';
31
+ export * from './family-organization-summary';
31
32
  export * from './gw-core-path';
32
33
  export * from './communication-fhir-r4';
33
34
  export * from './communication-document-reference';
@@ -41,13 +42,16 @@ export * from './communication-attached-bundle-session';
41
42
  export * from './confidential-storage-persistence';
42
43
  export * from './confidential-storage-test-data';
43
44
  export * from './permission-templates';
45
+ export * from './professional-smart';
44
46
  export * from './related-person-list';
45
47
  export * from './clinical-resource-converters';
48
+ export * from './clinical-bundle-summary';
46
49
  export * from './clinical-resource-view';
47
50
  export * from './fhir-validator';
48
51
  export * from './family-registration-test-data';
49
52
  export * from './individual-form-pdf';
50
53
  export * from './individual-organization-claims';
54
+ export * from './legal-organization-onboarding-editor';
51
55
  export * from './organization-lifecycle';
52
56
  export * from './organization-did-binding';
53
57
  export * from './individual-organization-lifecycle';
@@ -28,6 +28,7 @@ export * from './discovery-normalization.js';
28
28
  export * from './format-converter.js';
29
29
  export * from './fhir-cid.js';
30
30
  export * from './fhir-search.js';
31
+ export * from './family-organization-summary.js';
31
32
  export * from './gw-core-path.js';
32
33
  export * from './communication-fhir-r4.js';
33
34
  export * from './communication-document-reference.js';
@@ -41,13 +42,16 @@ export * from './communication-attached-bundle-session.js';
41
42
  export * from './confidential-storage-persistence.js';
42
43
  export * from './confidential-storage-test-data.js';
43
44
  export * from './permission-templates.js';
45
+ export * from './professional-smart.js';
44
46
  export * from './related-person-list.js';
45
47
  export * from './clinical-resource-converters.js';
48
+ export * from './clinical-bundle-summary.js';
46
49
  export * from './clinical-resource-view.js';
47
50
  export * from './fhir-validator.js';
48
51
  export * from './family-registration-test-data.js';
49
52
  export * from './individual-form-pdf.js';
50
53
  export * from './individual-organization-claims.js';
54
+ export * from './legal-organization-onboarding-editor.js';
51
55
  export * from './organization-lifecycle.js';
52
56
  export * from './organization-did-binding.js';
53
57
  export * from './individual-organization-lifecycle.js';