gdc-common-utils-ts 1.24.0 → 1.24.3

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.
@@ -24,6 +24,13 @@ export declare const EXAMPLE_ORG_CONTROLLER_SIGNING_KEY_ID: "urn:ietf:params:oau
24
24
  export declare const EXAMPLE_PRESENTATION_AUDIENCE_HOST_ID: "host:node-operator-es";
25
25
  export declare const EXAMPLE_ORGANIZATION_TAX_ID: "ESB00112233";
26
26
  export declare const EXAMPLE_REPRESENTATIVE_ROLE_CODE: "RESPRSN";
27
+ export declare const EXAMPLE_REPRESENTATIVE_ISCO08_ROLE_CODE: "1120";
28
+ export declare const EXAMPLE_REPRESENTATIVE_ISCO08_ROLE_IDENTIFIER: "urn:ilo:ilostat:isco-08:1120";
29
+ export declare const EXAMPLE_REPRESENTATIVE_IDENTIFIER: "IDCES-99999999R";
30
+ export declare const EXAMPLE_REPRESENTATIVE_EMAIL: "legal.rep@example.org";
31
+ export declare const EXAMPLE_REPRESENTATIVE_SUBJECT_URN: "urn:person:identifier:IDCES-99999999R";
32
+ export declare const EXAMPLE_REPRESENTATIVE_SAME_AS: "urn:multibase:zControllerHash";
33
+ export declare const EXAMPLE_ORG_ACTIVATION_ORGANIZATION_DID: "did:web:provider.example:health-care:organization:taxid:VATES-ESB00112233";
27
34
  export declare const EXAMPLE_ORGANIZATION_ID: "ESB00112233";
28
35
  export declare const EXAMPLE_ACTIVATION_AUTHORIZED_CATEGORY: "health-care";
29
36
  export declare const EXAMPLE_ACTIVATION_AUTHORIZED_SERVICE_TYPE: "organization/Composition.cruds";
@@ -45,18 +52,18 @@ export declare const EXAMPLE_ORG_ACTIVATION_LEGAL_REPRESENTATIVE_CREDENTIAL: Rea
45
52
  '@context': string[];
46
53
  type: ("VerifiableCredential" | "LegalRepresentativeCredential")[];
47
54
  credentialSubject: {
48
- id: "urn:ietf:params:oauth:jwk-thumbprint:sha-256:Q0ZfM0V4YW1wbGVUaHVtYnByaW50X2Jhc2U2NHVybA";
55
+ id: "urn:person:identifier:IDCES-99999999R";
49
56
  memberOf: {
50
57
  taxID: "ESB00112233";
51
58
  };
52
59
  hasOccupation: {
53
- identifier: {
54
- value: "RESPRSN";
55
- };
60
+ identifier: "urn:ilo:ilostat:isco-08:1120";
56
61
  };
57
62
  hasCredential: {
58
63
  material: "urn:ietf:params:oauth:jwk-thumbprint:sha-256:Q0ZfM0V4YW1wbGVUaHVtYnByaW50X2Jhc2U2NHVybA";
59
64
  };
65
+ identifier: "IDCES-99999999R";
66
+ sameAs: "urn:multibase:zControllerHash";
60
67
  };
61
68
  }>;
62
69
  export declare const EXAMPLE_ORG_ACTIVATION_PROOF_VP_PAYLOAD: Readonly<{
@@ -30,6 +30,13 @@ export const EXAMPLE_ORG_CONTROLLER_SIGNING_KEY_ID = `${UrnPrefixes.JwkThumbprin
30
30
  export const EXAMPLE_PRESENTATION_AUDIENCE_HOST_ID = 'host:node-operator-es';
31
31
  export const EXAMPLE_ORGANIZATION_TAX_ID = 'ESB00112233';
32
32
  export const EXAMPLE_REPRESENTATIVE_ROLE_CODE = 'RESPRSN';
33
+ export const EXAMPLE_REPRESENTATIVE_ISCO08_ROLE_CODE = '1120';
34
+ export const EXAMPLE_REPRESENTATIVE_ISCO08_ROLE_IDENTIFIER = 'urn:ilo:ilostat:isco-08:1120';
35
+ export const EXAMPLE_REPRESENTATIVE_IDENTIFIER = 'IDCES-99999999R';
36
+ export const EXAMPLE_REPRESENTATIVE_EMAIL = 'legal.rep@example.org';
37
+ export const EXAMPLE_REPRESENTATIVE_SUBJECT_URN = `urn:person:identifier:${EXAMPLE_REPRESENTATIVE_IDENTIFIER}`;
38
+ export const EXAMPLE_REPRESENTATIVE_SAME_AS = 'urn:multibase:zControllerHash';
39
+ export const EXAMPLE_ORG_ACTIVATION_ORGANIZATION_DID = 'did:web:provider.example:health-care:organization:taxid:VATES-ESB00112233';
33
40
  export const EXAMPLE_ORGANIZATION_ID = EXAMPLE_ORGANIZATION_TAX_ID;
34
41
  export const EXAMPLE_ACTIVATION_AUTHORIZED_CATEGORY = DataspaceSectors.HealthCare;
35
42
  export const EXAMPLE_ACTIVATION_AUTHORIZED_SERVICE_TYPE = ServiceCapability.IndexProvider;
@@ -57,18 +64,18 @@ export const EXAMPLE_ORG_ACTIVATION_LEGAL_REPRESENTATIVE_CREDENTIAL = Object.fre
57
64
  ActivationCredentialTypes.LegalRepresentativeCredential,
58
65
  ],
59
66
  credentialSubject: {
60
- id: EXAMPLE_ORG_CONTROLLER_SIGNING_KEY_ID,
67
+ id: EXAMPLE_REPRESENTATIVE_SUBJECT_URN,
61
68
  memberOf: {
62
69
  taxID: EXAMPLE_ORGANIZATION_TAX_ID,
63
70
  },
64
71
  hasOccupation: {
65
- identifier: {
66
- value: EXAMPLE_REPRESENTATIVE_ROLE_CODE,
67
- },
72
+ identifier: EXAMPLE_REPRESENTATIVE_ISCO08_ROLE_IDENTIFIER,
68
73
  },
69
74
  hasCredential: {
70
75
  material: EXAMPLE_ORG_CONTROLLER_SIGNING_KEY_ID,
71
76
  },
77
+ identifier: EXAMPLE_REPRESENTATIVE_IDENTIFIER,
78
+ sameAs: EXAMPLE_REPRESENTATIVE_SAME_AS,
72
79
  },
73
80
  });
74
81
  export const EXAMPLE_ORG_ACTIVATION_PROOF_VP_PAYLOAD = Object.freeze({
@@ -187,6 +187,15 @@ export declare const EXAMPLE_CONSENT_OPERATION_THREAD_ID: "thread-consent-exampl
187
187
  export declare const EXAMPLE_CONSENT_PERIOD_START: "2026-05-20T00:00:00Z";
188
188
  export declare const EXAMPLE_COMMUNICATION_UUID: "urn:uuid:communication-example-001";
189
189
  export declare const EXAMPLE_COMMUNICATION_IDENTIFIER: "urn:uuid:communication-example-001";
190
+ export declare const EXAMPLE_COMMUNICATION_THREAD_ID: "thread-communication-example-001";
191
+ export declare const EXAMPLE_COMMUNICATION_PARTICIPANT_SEARCH_SUBJECT_DID: string;
192
+ export declare const EXAMPLE_COMMUNICATION_PARTICIPANT_SENDER_DID: "did:web:provider.example.org";
193
+ export declare const EXAMPLE_COMMUNICATION_PARTICIPANT_USER_DID: string;
194
+ export declare const EXAMPLE_COMMUNICATION_PARTICIPANT_EMAIL_USER: "family.owner@example.org";
195
+ export declare const EXAMPLE_COMMUNICATION_PARTICIPANT_EMAIL_RECIPIENT: "nurse.oncall@example.org";
196
+ export declare const EXAMPLE_COMMUNICATION_PARTICIPANT_TEL_RECIPIENT: "+34600111222";
197
+ export declare const EXAMPLE_COMMUNICATION_SEARCH_CATEGORY: string;
198
+ export declare const EXAMPLE_COMMUNICATION_SEARCH_TOPIC: "care-plan-follow-up";
190
199
  export declare const EXAMPLE_IPS_BUNDLE_NOTE_TEXT: "IPS ingestion request";
191
200
  export declare const EXAMPLE_CONTENT_TYPE_APPLICATION_JSON: "application/json";
192
201
  export declare const EXAMPLE_CONTENT_TYPE_FHIR_JSON: "application/fhir+json";
@@ -226,6 +226,15 @@ export const EXAMPLE_CONSENT_OPERATION_THREAD_ID = 'thread-consent-example-001';
226
226
  export const EXAMPLE_CONSENT_PERIOD_START = '2026-05-20T00:00:00Z';
227
227
  export const EXAMPLE_COMMUNICATION_UUID = 'urn:uuid:communication-example-001';
228
228
  export const EXAMPLE_COMMUNICATION_IDENTIFIER = EXAMPLE_COMMUNICATION_UUID;
229
+ export const EXAMPLE_COMMUNICATION_THREAD_ID = 'thread-communication-example-001';
230
+ export const EXAMPLE_COMMUNICATION_PARTICIPANT_SEARCH_SUBJECT_DID = EXAMPLE_SUBJECT_DID;
231
+ export const EXAMPLE_COMMUNICATION_PARTICIPANT_SENDER_DID = EXAMPLE_TENANT_SERVICE_DID;
232
+ export const EXAMPLE_COMMUNICATION_PARTICIPANT_USER_DID = EXAMPLE_RELATED_PERSON_MEMBER_DID;
233
+ export const EXAMPLE_COMMUNICATION_PARTICIPANT_EMAIL_USER = 'family.owner@example.org';
234
+ export const EXAMPLE_COMMUNICATION_PARTICIPANT_EMAIL_RECIPIENT = 'nurse.oncall@example.org';
235
+ export const EXAMPLE_COMMUNICATION_PARTICIPANT_TEL_RECIPIENT = '+34600111222';
236
+ export const EXAMPLE_COMMUNICATION_SEARCH_CATEGORY = CommunicationCategoryCodes.Notification.attributeValue;
237
+ export const EXAMPLE_COMMUNICATION_SEARCH_TOPIC = 'care-plan-follow-up';
229
238
  export const EXAMPLE_IPS_BUNDLE_NOTE_TEXT = 'IPS ingestion request';
230
239
  export const EXAMPLE_CONTENT_TYPE_APPLICATION_JSON = 'application/json';
231
240
  export const EXAMPLE_CONTENT_TYPE_FHIR_JSON = 'application/fhir+json';
@@ -39,6 +39,11 @@ export interface AuditInfo {
39
39
  updated?: string;
40
40
  /** True if removed/deactivated (deactivation time is typically `updated`). */
41
41
  deactivated?: boolean;
42
+ /**
43
+ * Optional lightweight lifecycle disposition copied outside encrypted
44
+ * content, for example `purged`.
45
+ */
46
+ disposition?: string;
42
47
  /** Name of the channel/network where the data is audited/anchored. */
43
48
  channel?: string;
44
49
  /** Base58/Base64Url transaction identifier, depending on the attestation layer. */
@@ -46,6 +51,34 @@ export interface AuditInfo {
46
51
  /** Transaction timestamp (ISO 8601). */
47
52
  txTime?: string;
48
53
  }
54
+ /**
55
+ * Public runtime projection kept outside encrypted `content`.
56
+ *
57
+ * These values are not the canonical business payload. They are copied or
58
+ * generated from the protected content so runtime flows can answer lightweight
59
+ * queries without hydrating the confidential JWE blob.
60
+ *
61
+ * Rules:
62
+ * - Keep this object strictly minimal.
63
+ * - Only place data here when it is intentionally public or deployment-safe.
64
+ * - Never treat these fields as the source of truth if the encrypted content
65
+ * carries the canonical value.
66
+ */
67
+ export interface PublicInfo {
68
+ /**
69
+ * Optional lightweight role or technical marker copied outside encrypted
70
+ * content for routing, gating, or lifecycle inspection.
71
+ *
72
+ * This is a convenience projection for lookup. The canonical role still
73
+ * belongs to the protected business payload and/or indexed attributes.
74
+ *
75
+ * Example:
76
+ * - hosting may copy a synthetic bootstrap-controller marker here so tenant
77
+ * lifecycle scans can ignore that technical employee without hydrating the
78
+ * confidential JWE payload.
79
+ */
80
+ role?: string;
81
+ }
49
82
  /**
50
83
  * Defines the structure of an attribute to be indexed for blind, searchable queries.
51
84
  * @see https://identity.foundation/confidential-storage/#indexed-attributes
@@ -157,6 +190,19 @@ export interface ConfidentialStorageDoc {
157
190
  tag?: MetaTagCoding[];
158
191
  /** Policy-dependent research/analytics metadata, kept outside encrypted `content`. */
159
192
  research?: ResearchInfo;
193
+ /**
194
+ * Optional public runtime projection copied or generated for lightweight
195
+ * reads outside encrypted `content`.
196
+ *
197
+ * This object is intended for lookup, routing, and operational gating.
198
+ * It must not become a second canonical payload.
199
+ *
200
+ * Typical usage:
201
+ * - copy a small public or deployment-safe value out of protected content
202
+ * - or generate a technical marker needed for lightweight runtime scans
203
+ * - never treat this object as the source of truth for business semantics
204
+ */
205
+ public?: PublicInfo;
160
206
  }
161
207
  /**
162
208
  * Represents a document whose sensitive content has been decrypted and is held
@@ -1,4 +1,4 @@
1
- export type ActivationRepresentativePolicyErrorCode = 'MISSING_REPRESENTATIVE_DID_WEB' | 'MISSING_REPRESENTATIVE_ROLE_RESPRSN' | 'MISSING_REPRESENTATIVE_CREDENTIAL_BINDING' | 'REPRESENTATIVE_TAXID_MISMATCH';
1
+ export type ActivationRepresentativePolicyErrorCode = 'MISSING_REPRESENTATIVE_SUBJECT_ID' | 'MISSING_REPRESENTATIVE_ROLE_RESPRSN' | 'MISSING_REPRESENTATIVE_CREDENTIAL_BINDING' | 'REPRESENTATIVE_TAXID_MISMATCH';
2
2
  export type ActivationServiceAuthorizationPolicyErrorCode = 'MISSING_ORGANIZATION_SERVICE_CATEGORY' | 'MISSING_ORGANIZATION_SERVICE_TYPE' | 'UNAUTHORIZED_ORGANIZATION_SERVICE_CATEGORY' | 'UNAUTHORIZED_ORGANIZATION_SERVICE_TYPE';
3
3
  export type ActivationRepresentativePolicyError = {
4
4
  code: ActivationRepresentativePolicyErrorCode;
@@ -56,12 +56,37 @@ export declare function hasRoleCode(roleCode: string | undefined, requiredCode?:
56
56
  * @param representativeCredential Candidate representative credential.
57
57
  */
58
58
  export declare function extractRepresentativeCredentialBinding(representativeCredential: unknown): string | undefined;
59
+ /**
60
+ * Extracts the representative subject identifier from `credentialSubject.id`.
61
+ *
62
+ * ICA currently models the natural person with a stable person URN while the
63
+ * controller/bootstrap continuity is carried in sibling claims such as
64
+ * `sameAs` and `hasCredential`. Activation policy must therefore accept the
65
+ * canonical person URN form and must not require a representative `did:web`.
66
+ *
67
+ * @param representativeCredential Candidate representative credential.
68
+ */
69
+ export declare function extractRepresentativeSubjectId(representativeCredential: unknown): string | undefined;
59
70
  /**
60
71
  * Extracts a `did:web:` identifier from a VC-like credential.
61
72
  *
62
73
  * @param credential Candidate credential.
63
74
  */
64
75
  export declare function extractDidWebFromCredential(credential: unknown): string | undefined;
76
+ /**
77
+ * Checks whether the representative role expresses the activation-controller
78
+ * semantics accepted by GW.
79
+ *
80
+ * Compatibility rules:
81
+ * - historical GW payloads may still use HL7/FHIR `RESPRSN`
82
+ * - current ICA person credentials may encode the legal representative role as
83
+ * ISCO-08 `1120`, either tokenized (`ISCO-08|1120`) or as the canonical
84
+ * ILO URN (`urn:ilo:ilostat:isco-08:1120`)
85
+ *
86
+ * @param roleCode Candidate role token extracted from the credential.
87
+ * @param requiredCode Required GW compatibility code, defaults to `RESPRSN`.
88
+ */
89
+ export declare function hasActivationRepresentativeRole(roleCode: string | undefined, requiredCode?: string): boolean;
65
90
  /**
66
91
  * Extracts the categories authorized by an ICA-issued organization credential.
67
92
  *
@@ -141,6 +141,24 @@ function extractCredentialBindingValue(value) {
141
141
  || '').trim();
142
142
  return candidate || undefined;
143
143
  }
144
+ /**
145
+ * Extracts the representative subject identifier from `credentialSubject.id`.
146
+ *
147
+ * ICA currently models the natural person with a stable person URN while the
148
+ * controller/bootstrap continuity is carried in sibling claims such as
149
+ * `sameAs` and `hasCredential`. Activation policy must therefore accept the
150
+ * canonical person URN form and must not require a representative `did:web`.
151
+ *
152
+ * @param representativeCredential Candidate representative credential.
153
+ */
154
+ export function extractRepresentativeSubjectId(representativeCredential) {
155
+ const obj = asObject(representativeCredential);
156
+ if (!obj)
157
+ return undefined;
158
+ const subject = extractCredentialSubject(obj);
159
+ const subjectId = String(subject?.id || '').trim();
160
+ return subjectId || undefined;
161
+ }
144
162
  /**
145
163
  * Extracts a `did:web:` identifier from a VC-like credential.
146
164
  *
@@ -154,6 +172,27 @@ export function extractDidWebFromCredential(credential) {
154
172
  const didCandidate = String(subject?.id || obj.id || '').trim();
155
173
  return didCandidate.startsWith('did:web:') ? didCandidate : undefined;
156
174
  }
175
+ /**
176
+ * Checks whether the representative role expresses the activation-controller
177
+ * semantics accepted by GW.
178
+ *
179
+ * Compatibility rules:
180
+ * - historical GW payloads may still use HL7/FHIR `RESPRSN`
181
+ * - current ICA person credentials may encode the legal representative role as
182
+ * ISCO-08 `1120`, either tokenized (`ISCO-08|1120`) or as the canonical
183
+ * ILO URN (`urn:ilo:ilostat:isco-08:1120`)
184
+ *
185
+ * @param roleCode Candidate role token extracted from the credential.
186
+ * @param requiredCode Required GW compatibility code, defaults to `RESPRSN`.
187
+ */
188
+ export function hasActivationRepresentativeRole(roleCode, requiredCode = 'RESPRSN') {
189
+ if (hasRoleCode(roleCode, requiredCode))
190
+ return true;
191
+ const normalized = String(roleCode || '').trim().toUpperCase();
192
+ if (!normalized)
193
+ return false;
194
+ return /(?:^|[|:])1120$/.test(normalized);
195
+ }
157
196
  /**
158
197
  * Extracts the categories authorized by an ICA-issued organization credential.
159
198
  *
@@ -273,13 +312,13 @@ export function isMemberDidWebUnderOwner(memberDidWeb, ownerDidWeb) {
273
312
  */
274
313
  export function validateActivationRepresentativePolicy(input) {
275
314
  const errors = [];
276
- const representativeDid = input.representativeCredential
277
- ? extractDidWebFromCredential(input.representativeCredential)
315
+ const representativeSubjectId = input.representativeCredential
316
+ ? extractRepresentativeSubjectId(input.representativeCredential)
278
317
  : undefined;
279
- if (input.representativeCredential && !representativeDid) {
318
+ if (input.representativeCredential && !representativeSubjectId) {
280
319
  errors.push({
281
- code: 'MISSING_REPRESENTATIVE_DID_WEB',
282
- message: 'ICA-issued representative credential is missing credentialSubject.id did:web.',
320
+ code: 'MISSING_REPRESENTATIVE_SUBJECT_ID',
321
+ message: 'ICA-issued representative credential is missing credentialSubject.id.',
283
322
  });
284
323
  }
285
324
  if (!input.representativeCredential)
@@ -293,10 +332,10 @@ export function validateActivationRepresentativePolicy(input) {
293
332
  });
294
333
  }
295
334
  const roleCode = extractRepresentativeRoleCode(input.representativeCredential);
296
- if (!hasRoleCode(roleCode, input.requiredRoleCode || 'RESPRSN')) {
335
+ if (!hasActivationRepresentativeRole(roleCode, input.requiredRoleCode || 'RESPRSN')) {
297
336
  errors.push({
298
337
  code: 'MISSING_REPRESENTATIVE_ROLE_RESPRSN',
299
- message: 'ICA-issued representative credential must include Responsible Party role (RESPRSN) in credentialSubject.hasOccupation.',
338
+ message: 'ICA-issued representative credential must include legal representative role semantics (RESPRSN or ISCO-08 1120) in credentialSubject.hasOccupation.',
300
339
  });
301
340
  }
302
341
  const binding = extractRepresentativeCredentialBinding(input.representativeCredential);
@@ -22,7 +22,18 @@ export interface BuildOrganizationActivationRequestInput {
22
22
  export interface BuildControllerBindingInputInput {
23
23
  /** Public DID to publish or bind for the controller/person. */
24
24
  did?: string;
25
- /** Additional public alias such as `mailto:`. */
25
+ /**
26
+ * Additional public alias for the controller/person.
27
+ *
28
+ * Canonical examples:
29
+ * - `urn:multibase:z...` for an email-derived ICA/GW binding
30
+ * - `tel:+34600111222` for a phone identifier
31
+ * - `did:web:...` or another stable public identifier
32
+ *
33
+ * Do not use `mailto:` when the source value is an email for ICA/GW
34
+ * interoperability. Start from the plain email and normalize it first with
35
+ * `normalizeSameAsHash(...)`.
36
+ */
26
37
  sameAs?: string;
27
38
  /** Primary controller signing key. */
28
39
  publicSignKey?: Record<string, unknown>;
@@ -54,6 +65,14 @@ export interface BuildOrganizationBindingInputInput {
54
65
  *
55
66
  * so the caller does not have to manually shape `controller.publicKeyJwk` and
56
67
  * `controller.jwks`.
68
+ *
69
+ * ICA/GW interoperability note:
70
+ * - callers that start from a raw email should first normalize it with
71
+ * `normalizeSameAsHash(...)` before assigning `sameAs`
72
+ * - keep the raw email separately in activation claims when GW still needs it
73
+ * for internal admin/bootstrap records
74
+ * - do not send `mailto:` as the canonical controller alias when the binding
75
+ * source is an email address
57
76
  */
58
77
  export declare function buildControllerBindingInput(input: BuildControllerBindingInputInput): ControllerBindingInput;
59
78
  /**
@@ -23,6 +23,14 @@ function normalizeJwkSet(publicKeys) {
23
23
  *
24
24
  * so the caller does not have to manually shape `controller.publicKeyJwk` and
25
25
  * `controller.jwks`.
26
+ *
27
+ * ICA/GW interoperability note:
28
+ * - callers that start from a raw email should first normalize it with
29
+ * `normalizeSameAsHash(...)` before assigning `sameAs`
30
+ * - keep the raw email separately in activation claims when GW still needs it
31
+ * for internal admin/bootstrap records
32
+ * - do not send `mailto:` as the canonical controller alias when the binding
33
+ * source is an email address
26
34
  */
27
35
  export function buildControllerBindingInput(input) {
28
36
  const jwks = normalizeJwkSet(input.publicKeys);
@@ -0,0 +1,17 @@
1
+ import type { CommunicationParticipantProjection, CommunicationParticipantSearchInput } from './communication-participant-search';
2
+ /**
3
+ * Shared communication-participant search input fixture reused across GW/SDK
4
+ * tests.
5
+ */
6
+ export declare function buildExampleCommunicationParticipantSearchInput(overrides?: Partial<CommunicationParticipantSearchInput>): CommunicationParticipantSearchInput;
7
+ /**
8
+ * Shared stored projection fixture that mirrors the shape persisted by GW
9
+ * communication-channel projections.
10
+ */
11
+ export declare function buildExampleCommunicationParticipantProjection(overrides?: Partial<CommunicationParticipantProjection & {
12
+ id?: string;
13
+ thid?: string;
14
+ }>): CommunicationParticipantProjection & {
15
+ id: string;
16
+ thid: string;
17
+ };
@@ -0,0 +1,39 @@
1
+ import { EXAMPLE_COMMUNICATION_PARTICIPANT_EMAIL_RECIPIENT, EXAMPLE_COMMUNICATION_PARTICIPANT_EMAIL_USER, EXAMPLE_COMMUNICATION_SEARCH_CATEGORY, EXAMPLE_COMMUNICATION_SEARCH_TOPIC, EXAMPLE_COMMUNICATION_PARTICIPANT_SEARCH_SUBJECT_DID, EXAMPLE_COMMUNICATION_PARTICIPANT_SENDER_DID, EXAMPLE_COMMUNICATION_PARTICIPANT_TEL_RECIPIENT, EXAMPLE_COMMUNICATION_PARTICIPANT_USER_DID, EXAMPLE_COMMUNICATION_THREAD_ID, } from '../examples/shared.js';
2
+ import { CommunicationClaim } from '../models/interoperable-claims/communication-claims.js';
3
+ /**
4
+ * Shared communication-participant search input fixture reused across GW/SDK
5
+ * tests.
6
+ */
7
+ export function buildExampleCommunicationParticipantSearchInput(overrides = {}) {
8
+ return {
9
+ subject: EXAMPLE_COMMUNICATION_PARTICIPANT_SEARCH_SUBJECT_DID,
10
+ userActorId: [EXAMPLE_COMMUNICATION_PARTICIPANT_USER_DID, EXAMPLE_COMMUNICATION_PARTICIPANT_EMAIL_USER],
11
+ targetActorId: [EXAMPLE_COMMUNICATION_PARTICIPANT_EMAIL_RECIPIENT, EXAMPLE_COMMUNICATION_PARTICIPANT_TEL_RECIPIENT],
12
+ searchParams: {
13
+ [CommunicationClaim.Category]: EXAMPLE_COMMUNICATION_SEARCH_CATEGORY,
14
+ [CommunicationClaim.Topic]: EXAMPLE_COMMUNICATION_SEARCH_TOPIC,
15
+ },
16
+ ...overrides,
17
+ };
18
+ }
19
+ /**
20
+ * Shared stored projection fixture that mirrors the shape persisted by GW
21
+ * communication-channel projections.
22
+ */
23
+ export function buildExampleCommunicationParticipantProjection(overrides = {}) {
24
+ return {
25
+ id: 'communication-participant-record-001',
26
+ thid: EXAMPLE_COMMUNICATION_THREAD_ID,
27
+ subject: EXAMPLE_COMMUNICATION_PARTICIPANT_SEARCH_SUBJECT_DID,
28
+ sender: EXAMPLE_COMMUNICATION_PARTICIPANT_SENDER_DID,
29
+ sent: '2026-06-15T10:00:00Z',
30
+ category: EXAMPLE_COMMUNICATION_SEARCH_CATEGORY,
31
+ topic: EXAMPLE_COMMUNICATION_SEARCH_TOPIC,
32
+ recipients: [
33
+ EXAMPLE_COMMUNICATION_PARTICIPANT_USER_DID,
34
+ EXAMPLE_COMMUNICATION_PARTICIPANT_EMAIL_RECIPIENT,
35
+ EXAMPLE_COMMUNICATION_PARTICIPANT_TEL_RECIPIENT,
36
+ ],
37
+ ...overrides,
38
+ };
39
+ }
@@ -0,0 +1,108 @@
1
+ import { buildSearchBundle, type FhirParametersResource, type SearchParameterPrimitive } from './fhir-search.js';
2
+ /**
3
+ * Canonical participant-token prefixes used by communication search helpers.
4
+ */
5
+ export declare const CommunicationParticipantPrefixes: Readonly<{
6
+ readonly Did: "did:";
7
+ readonly Email: "email:";
8
+ readonly Mailto: "mailto:";
9
+ readonly Tel: "tel:";
10
+ readonly Phone: "phone:";
11
+ readonly Wildcard: "*";
12
+ }>;
13
+ /**
14
+ * Canonical parameter names supported by `Communication/_search`.
15
+ */
16
+ export declare const CommunicationParticipantSearchParameterNames: Readonly<{
17
+ readonly Subject: "subject";
18
+ readonly Actor: "actor";
19
+ readonly Sender: "sender";
20
+ readonly Recipient: "recipient";
21
+ readonly User: "user";
22
+ readonly Target: "target";
23
+ readonly PeriodStart: "period-start";
24
+ readonly PeriodEnd: "period-end";
25
+ readonly Page: "page";
26
+ readonly Count: "count";
27
+ }>;
28
+ /**
29
+ * Backward-compatible aliases still accepted while callers migrate to the
30
+ * canonical control names.
31
+ */
32
+ export declare const CommunicationParticipantSearchParameterAliases: Readonly<{
33
+ readonly SentFrom: "sent-from";
34
+ readonly SentTo: "sent-to";
35
+ }>;
36
+ /**
37
+ * Indexed-attribute names used by communication projections.
38
+ */
39
+ export declare const CommunicationParticipantIndexNames: Readonly<{
40
+ readonly Subject: "Communication.subject";
41
+ readonly Participant: "Communication.participant-token";
42
+ readonly Sender: "Communication.sender-token";
43
+ readonly Recipient: "Communication.recipient-token";
44
+ }>;
45
+ export type CommunicationParticipantTokenInput = string | readonly string[] | undefined | null;
46
+ export type CommunicationParticipantSearchInput = {
47
+ /**
48
+ * Canonical claims-like search parameters keyed by reusable claim constants
49
+ * such as `CommunicationClaim.Sender`, `CommunicationClaim.Recipient`,
50
+ * `CommunicationClaim.Category`, or `CommunicationClaim.Topic`.
51
+ */
52
+ searchParams?: Readonly<Record<string, SearchParameterPrimitive | undefined>>;
53
+ subject?: CommunicationParticipantTokenInput;
54
+ actorId?: CommunicationParticipantTokenInput;
55
+ senderActorId?: CommunicationParticipantTokenInput;
56
+ recipientActorId?: CommunicationParticipantTokenInput;
57
+ userActorId?: CommunicationParticipantTokenInput;
58
+ targetActorId?: CommunicationParticipantTokenInput;
59
+ periodStart?: string;
60
+ periodEnd?: string;
61
+ sentFrom?: string;
62
+ sentTo?: string;
63
+ page?: number;
64
+ count?: number;
65
+ };
66
+ export type CommunicationParticipantSearchCriteria = {
67
+ subjectActorIds: string[];
68
+ anySubject: boolean;
69
+ actorIds: string[];
70
+ anyActor: boolean;
71
+ senderActorIds: string[];
72
+ anySender: boolean;
73
+ recipientActorIds: string[];
74
+ anyRecipient: boolean;
75
+ userActorIds: string[];
76
+ anyUser: boolean;
77
+ targetActorIds: string[];
78
+ anyTarget: boolean;
79
+ claimSearchParams: Readonly<Record<string, string[]>>;
80
+ periodStart?: string;
81
+ periodEnd?: string;
82
+ page: number;
83
+ count?: number;
84
+ };
85
+ export type CommunicationParticipantProjection = {
86
+ subject?: unknown;
87
+ sender?: unknown;
88
+ recipients?: unknown;
89
+ from?: unknown;
90
+ to?: unknown;
91
+ sent?: unknown;
92
+ category?: unknown;
93
+ topic?: unknown;
94
+ };
95
+ export type CommunicationParticipantIndexedAttribute = {
96
+ name: string;
97
+ value: string;
98
+ unique?: boolean;
99
+ };
100
+ export declare function normalizeCommunicationParticipantToken(value: unknown): string;
101
+ export declare function normalizeCommunicationParticipantTokenList(value: unknown): string[];
102
+ export declare function isCommunicationParticipantWildcardToken(value: unknown): boolean;
103
+ export declare function buildCommunicationParticipantSearchParameters(input: CommunicationParticipantSearchInput): FhirParametersResource;
104
+ export declare function buildCommunicationParticipantSearchBundle(input: CommunicationParticipantSearchInput): ReturnType<typeof buildSearchBundle>;
105
+ export declare function parseCommunicationParticipantSearchCriteria(input: Record<string, unknown> | FhirParametersResource | undefined): CommunicationParticipantSearchCriteria;
106
+ export declare function buildCommunicationParticipantIndexAttributes(projection: CommunicationParticipantProjection): CommunicationParticipantIndexedAttribute[];
107
+ export declare function matchesCommunicationParticipantSearch(projection: CommunicationParticipantProjection, criteria: CommunicationParticipantSearchCriteria): boolean;
108
+ export declare function paginateCommunicationParticipantMatches<T>(records: readonly T[], criteria: Pick<CommunicationParticipantSearchCriteria, 'page' | 'count'>): T[];