AWS Security ChangesHomeSearch

AWS healthlake high security documentation change

Service: healthlake · 2026-07-04 · Security-related high

File: healthlake/latest/devguide/reference-fhir-operations-bulk-member-match.md

Summary

Updated documentation for FHIR bulk member match operation: Added Quick Start guide, modified consent validation rules (removed performer validation, added status enforcement), added consent decision table, clarified output group persistence, updated validation rules table, and adjusted coverage disambiguation logic.

Security assessment

The change enforces strict validation of Consent.status (must be 'active') and adds validation for provision.actor/action, which are security controls preventing processing of invalid consents. Removal of performer validation against patient references could allow consent delegation (e.g., parent/child scenarios) but reduces authorization checks. The 400 error for non-active status replaces previous soft handling, directly addressing improper consent processing.

Diff

diff --git a/healthlake/latest/devguide/reference-fhir-operations-bulk-member-match.md b/healthlake/latest/devguide/reference-fhir-operations-bulk-member-match.md
index 78b96cb00..28f091583 100644
--- a//healthlake/latest/devguide/reference-fhir-operations-bulk-member-match.md
+++ b//healthlake/latest/devguide/reference-fhir-operations-bulk-member-match.md
@@ -7 +7 @@
-UsageSupported parametersPOST request to submit bulk member match jobCompleted job response with outputHow HealthLake classifies members into output GroupsCoverage matching behaviorConsent performer reference handlingOutput Group resourcesConsent-Patient linkageWhat gets stored vs. what is transientIntegration with $davinci-data-exportPerformance characteristicsAuthorizationValidation rulesMatching behaviorError handlingRelated operations
+UsageQuick startSupported parametersPOST request to submit bulk member match jobCompleted job response with outputHow HealthLake classifies members into output GroupsCoverage matching behaviorConsent performer reference handlingOutput Group resourcesConsent-Patient linkageWhat gets stored vs. what is transientIntegration with $davinci-data-exportPerformance characteristicsAuthorizationValidation rulesMatching behaviorError handlingRelated operations
@@ -43,0 +44,15 @@ After submitting a bulk match request, you can poll the job status using:
+Each request supports up to 500 members (5 MB maximum payload).
+
+## Quick start
+
+  1. Submit: `POST [base]/Group/$bulk-member-match` with MemberBundles → receive jobId
+
+  2. Poll: `GET [base]/$bulk-member-match-status/{jobId}` until status = COMPLETED
+
+  3. Extract the MatchedMembers Group ID from the completed job response
+
+  4. Export: `POST [base]/Group/{matched-group-id}/$davinci-data-export` to retrieve clinical data
+
+
+
+
@@ -461 +476 @@ Every member submitted in a `$bulk-member-match` request is evaluated through a
-  4. **Consent evaluation** — Is the submitted Consent honorable right now? (status = active, period covers current date, performer can be validated). On failure: ConsentConstrainedMembers.
+  4. **Consent evaluation** — Does `provision.period` cover the current date? On failure: ConsentConstrainedMembers.
@@ -472 +487,3 @@ Every member submitted in a `$bulk-member-match` request is evaluated through a
-  * **Check 1 — Consent status:** Is `Consent.status` equal to "active"? If not → ConsentConstrainedMembers.
+  * **Provision period:** Does `provision.period` cover the current date? If current date is before `period.start` or after `period.end` → ConsentConstrainedMembers.
+
+
@@ -474 +490,0 @@ Every member submitted in a `$bulk-member-match` request is evaluated through a
-  * **Check 2 — Provision period:** Does `provision.period` cover the current date? If current date is before `period.start` or after `period.end` → ConsentConstrainedMembers.
@@ -476 +492 @@ Every member submitted in a `$bulk-member-match` request is evaluated through a
-  * **Check 3 — Performer validation:** Can the `Consent.performer` reference be validated? If the referenced resource is not found in the datastore or is not associated with the matched patient → ConsentConstrainedMembers.
+All checks must pass for the member to be placed in MatchedMembers and for the Consent to be stored.
@@ -477,0 +494,17 @@ Every member submitted in a `$bulk-member-match` request is evaluated through a
+###### Note
+
+The `performer` reference is not cross-validated against `patient`. A parent/guardian consenting on behalf of a dependent is valid.
+
+**Consent classification decision table:**
+
+  * `permit` \+ `#regular` \+ `active` \+ period covers now → **MatchedMembers (Consent stored)**
+
+  * `permit` \+ `#sensitive` \+ `active` \+ period covers now → **MatchedMembers (Consent stored)**
+
+  * `permit` \+ #regular or #sensitive + `active` \+ period expired/not started → **ConsentConstrainedMembers**
+
+  * `deny` \+ any + any + any → **400 Bad Request (Step 1)**
+
+  * `permit` \+ URI not ending in #regular or #sensitive + any + any → **400 Bad Request (Step 1)**
+
+  * any + any + not active + any → **400 Bad Request (Step 1)**
@@ -481 +513,0 @@ Every member submitted in a `$bulk-member-match` request is evaluated through a
-All checks must pass for the member to be placed in MatchedMembers and for the Consent to be stored.
@@ -497 +529 @@ The new payer may send a temporary or local patient reference in `Consent.perfor
-  * If performer validation fails (resource not found or not associated with the matched patient), the member is placed in ConsentConstrainedMembers rather than returning an error.
+  * The `performer` reference is not cross-validated against `patient`. A parent/guardian consenting on behalf of a dependent is valid and will not route the member to ConsentConstrainedMembers.
@@ -514 +546 @@ Contains Patient references for all successfully matched members whose consent i
-Contains references to members where no unique match was found. A member is placed here when no patient in the datastore matches the provided demographics, no valid coverage exists for any matched patient candidate, or multiple patients match demographics and multiple have valid coverage (ambiguous).
+Contains references to members where no unique match was found. A member is placed here when no patient in the datastore matches the provided demographics, no valid coverage exists for any matched patient candidate, or multiple patients match demographics and multiple have valid coverage (ambiguous). This Group is **not instantiated** in the datastore. It exists only in the completed job response.
@@ -519 +551 @@ Contains references to members where no unique match was found. A member is plac
-Contains Patient references for members who were successfully matched (demographics and coverage confirmed) but whose consent cannot be honored at the time of the request. The Consent resource is _not_ stored for consent-constrained members. The matched member identity (MemberIdentifier and MemberId) is still included so the requesting payer knows who was constrained.
+Contains Patient references for members who were successfully matched (demographics and coverage confirmed) but whose consent cannot be honored at the time of the request. The Consent resource is _not_ stored for consent-constrained members. The matched member identity (MemberIdentifier and MemberId) is still included so the requesting payer knows who was constrained. This Group is **not instantiated** in the datastore. It exists only in the completed job response.
@@ -640 +671,0 @@ Field| How HealthLake uses it| Validation failure if...
-`payor`| Disambiguation when multiple candidates exist| Missing, or more than one payor  
@@ -656 +687,3 @@ Field| How HealthLake uses it| Validation failure if...
-`status`| Evaluated at Step 4 (NOT Step 1)| Never causes Step 1 failure — HealthLake accepts any valid status and evaluates at Step 4  
+`provision.actor`| Identifies source and recipient payers| Missing or does not include required source + recipient actors per HRex profile  
+`provision.action`| Confirms disclosure action| Missing or no "disclose" code  
+`status`| Must be "active" per HRex IG| Not "active" — returns 400 validation error  
@@ -660 +693 @@ Field| How HealthLake uses it| Validation failure if...
-The HRex Consent profile defines status with a fixed value of "active". HealthLake intentionally relaxes this constraint so that a non-active Consent receives a meaningful classification (ConsentConstrainedMembers) rather than a blanket validation rejection.
+Per the HRex IG, `Consent.status` is fixed to "active". HealthLake enforces this at Step 1 (structural validation) and returns a 400 validation error if any other status is provided. Non-active consent will not be processed nor classified into ConsentConstrainedMembers — it is rejected upfront.
@@ -666 +699 @@ The HRex Consent profile defines status with a fixed value of "active". HealthLa
-  * **Coverage disambiguation (Step 3)** — When multiple patient candidates are found, `CoverageToMatch` is used to narrow to one. A coverage is "valid" when an active Coverage resource exists in the datastore matching on `subscriberId` or `identifier` (MB type) AND `payor`.
+  * **Coverage disambiguation (Step 3)** — When multiple patient candidates are found, `CoverageToMatch` is used to narrow to one. A coverage is "valid" when an active Coverage resource exists in the datastore matching on `subscriberId` or `identifier` (MB type).
@@ -681 +714 @@ The operation handles the following error conditions:
-  * **Individual member errors** : When a specific member fails to process, the operation continues with remaining members and includes error details in the NonMatchedMembers Group with appropriate reason codes. For example, a `MemberBundle` with a Patient missing the `birthDate` parameter will return the following error:
+  * **Individual member errors** : When a specific member fails to process, the operation continues with remaining members and includes error details with appropriate reason codes. For example, a `MemberBundle` with a Patient missing the `birthDate` parameter will return the following error: