23.0.1Consent Module: Overview
Experimental

 

23.0.1.1Summary

Please contact us if you would like to try out this experimental new feature.

The Consent Module contributes a Consent Service to FHIR Endpoints or Persistence modules.

A Consent Service can remove or alter the resource(s) in a response to enforce privacy rules, or to remove proprietary data during a data transfer between organizations.

The Consent Service created by a Consent Module is configured dynamically for each request. This can be done in 2 ways:

  1. Using Consent resources (from a FHIR repository, internal service, or hardcoded Consent resource). In this method, each relevant Consent resource is matched to a list of ordered rules, and translated into a partial Consent Service.
  2. Using fixed logic that does not require Consent resources. In this method some logic which does not require a Consent resource is translated into a partial Consent Service.

These partial Consent Services are then combined using the ordered rules to determine the verdict from the startOperation, canSeeResource, and willSeeResource consent hooks.

23.0.2Introduction

 

A Consent Service can use the startOperation hook to block requests, and thecanSeeResource, and willSeeResource hooks remove or alter the resource(s) in a response.

For background on the Consent Service, and the capabilities of startOperation, canSeeResource, and willSeeResource, see the introduction and API documentation below:

Each method in this interface represents a consent method. Consent logic can be applied to resources in a clinical repository however, there is no integration with Consent resources in a consent repository.

The Consent Module has the same consent methods, but instead of code, implementers use JSON configuration to define rules. These rules are:

  1. Primarily driven by Consent resources 2. Evaluated in the order they are defined 3. Flexible and can allow fixed logic to be executed if required (i.e. Bypass for Superusers, handling fallback scenarios where a Consent verdict was not reached)

23.0.3Consent Module JSON Configuration

 

The sample JSON below will be used to show how the Consent Module is configured:

{
	"willSeeResource": {
		"consentRules": [
			{ "name": "ALLOW_USER_NAMES_RULE", "fixedPolicy": "myAllowUserNamesConsentService"},
			{ "name": "BREAK_THE_GLASS_RULE", "matching": [  { "matchUrl": "Consent?purpose=BTG"} ], "consentResourcePolicy":  "myConsentService"},
			{ "name": "PATIENT_GRANT_RULE", "matching": [  { "matchUrl": "Consent?category=patient-grant-code" } ], "consentResourcePolicy":  "myConsentService" },
			{ "name": "ALLOW_NON_PATIENT_COMPARTMENT_RULE", "fixedPolicy":  "ALLOW_NON_PATIENT_COMPARTMENT_RESOURCES" },
			{ "name": "FALLBACK_RULE", "fixedPolicy":  "REJECT" }
		]
	}
}

23.0.3.1Step 1: Determine the Applicable Consent Method(s)

The first thing implementers must decide is which consent method the consent rules should apply to.

The Consent Module supports the startOperation, canSeeResource, and willSeeResource consent methods.

The sample JSON configuration above uses the willSeeResource consent method.

23.0.3.2Step 2: Determine Applicable Consent Resources For Incoming Request

Implementers are required to create and register an interceptor that has at least one of the pointcuts below (both pointcuts may also be implemented):

23.0.3.2.11. CONSENT_FETCH_QUERIES

JavaDoc: CONSENT_FETCH_QUERIES

A fetch query will typically define a Consent patient and a Consent actor. The fetch query callback for the resource-specific methods (i.e. canSeeResource and willSeeResource) will include the Patient id for resources in a Patient Compartment.

Implementors should extract the Consent Actor from the request. This can be done using custom headers, custom OIDC/SMART claims, or user information, however other methods may be used.

For example, if a request was being made by Organization/organization-1 to view Observation/observation-1 with Observation.subject=Patient/patient-1, a sensible fetch query might be:

Consent?status=active&actor=Organization/organization-1&patient=Patient/patient-1

Other common queries are:

  • Patient blanket Consent resources not related to a specific actor:
Consent?status=active&actor:missing=true&patient=Patient/patient-1
  • Blanket Consent scoped to an Organization for any Patient:
Consent?status=active&actor=Organization/organization-1&patient:missing=true

23.0.3.2.22. CONSENT_ACTIVE_CONSENT_RESOURCES_RESOLVE

JavaDoc: CONSENT_ACTIVE_CONSENT_RESOURCES_RESOLVE

This pointcut is similar to the CONSENT_FETCH_QUERIES pointcut, however instead of providing String-based Consent fetch queries, implementers can provide Consent resource objects (IDomainResource) that will be applied to an incoming request.

This pointcut offers a large range of flexibility and allows implementers to:

  • Obtain Consent resources from a remote FHIR repository (i.e. using IGenenericClient)
  • @Autowire in a resource DAO that can be used to perform more complex queries (or multiple queries)
  • Reach out to a third party service if more information is needed to determine applicable consents
  • Hardcode a Consent resource that may apply to a specific Role or Permission (i.e. SUPERUSER)

The code snippet below shows a sample interceptor that implements the CONSENT_FETCH_QUERIES and the CONSENT_ACTIVE_CONSENT_RESOURCES_RESOLVE pointcuts.

/*-
 * #%L
 * Smile CDR - CDR
 * %%
 * Copyright (C) 2016 - 2025 Smile CDR, Inc.
 * %%
 * All rights reserved.
 * #L%
 */
package com.smilecdr.demo.consentmodule;

import ca.cdr.api.consent.CompartmentUtil;
import ca.cdr.api.consent.ConsentActiveResourceResolutionRequest;
import ca.cdr.api.consent.ConsentFetchQueries;
import ca.cdr.api.consent.ConsentLookupContext;
import ca.cdr.api.fhir.interceptor.CdrHook;
import ca.cdr.api.fhir.interceptor.CdrPointcut;
import ca.cdr.api.model.json.UserSessionDetailsJson;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.rest.api.server.RequestDetails;
import ca.uhn.fhir.rest.client.api.IGenericClient;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IDomainResource;
import org.hl7.fhir.instance.model.api.IIdType;
import org.hl7.fhir.r4.model.Bundle;
import org.hl7.fhir.r4.model.Consent;
import org.springframework.web.util.UriComponentsBuilder;

import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * A sample interceptor that demonstrates how to provide a list of Consent fetch queries by
 * implementing the CONSENT_FETCH_QUERIES and CONSENT_ACTIVE_CONSENT_RESOURCES_RESOLVE pointcut.
 */
@SuppressWarnings({"unused"})
public class DetermineApplicableConsentInterceptor {

	private static final String SERVER_BASE = "http://some-server-base";

	private final FhirContext myFhirContext;
	private final IGenericClient myFhirClient;

	public DetermineApplicableConsentInterceptor() {
		myFhirContext = FhirContext.forR4Cached();
		myFhirClient = myFhirContext.newRestfulGenericClient(SERVER_BASE);
	}

	/**
	 * Uses the CONSENT_FETCH_QUERIES pointcut to provide a list of fetch queries.
	 * @param theConsentFetchQueries - the object that consent queries should be added to
	 * @param theRequestDetails - the details of the request
	 * @param theConsentLookupContext - the consent lookup context
	 * @param theResource - the resource that consent rules should apply to
	 * @param theUserSessionDetails - the user session details
	 */
	@CdrHook(CdrPointcut.CONSENT_FETCH_QUERIES)
	public void getConsentFetchQueries(
			ConsentFetchQueries theConsentFetchQueries,
			RequestDetails theRequestDetails,
			ConsentLookupContext theConsentLookupContext,
			IBaseResource theResource,
			UserSessionDetailsJson theUserSessionDetails) {

		Optional<IIdType> consentPatient = getConsentPatient(theResource);
		if (consentPatient.isEmpty()) {
			// This will happen if the resource is not in the patient compartment (i.e. Organization, Location, etc.)
			// In this case, there will be no applicable Consent resource
			return;
		}

		UriComponentsBuilder query = UriComponentsBuilder.fromPath("Consent")
				.queryParam("status", "active")
				.queryParam("patient.identifier", consentPatient.get().getValue())
				.queryParam("actor:missing", "true");

		theConsentFetchQueries.addQuery(query.toUriString());
	}

	/**
	 * Uses the CONSENT_ACTIVE_CONSENT_RESOURCES_RESOLVE pointcut to provide consent resources.
	 * @param theResolutionRequest - the object that consent resources should be added to
	 * @param theRequestDetails - the details of the request
	 * @param theConsentLookupContext - the consent lookup context
	 * @param theResource - the resource that consent rules should apply to
	 * @param theUserSessionDetails - the user session details
	 */
	@CdrHook(CdrPointcut.CONSENT_ACTIVE_CONSENT_RESOURCES_RESOLVE)
	public void getConsentResolutionRequest(
			ConsentActiveResourceResolutionRequest theResolutionRequest,
			RequestDetails theRequestDetails,
			ConsentLookupContext theConsentLookupContext,
			IBaseResource theResource,
			UserSessionDetailsJson theUserSessionDetails) {

		Optional<IIdType> consentPatient = getConsentPatient(theResource);
		if (consentPatient.isEmpty()) {
			// This will happen if the resource is not in the patient compartment (i.e. Organization, Location, etc.)
			// In this case, there will be no applicable Consent resource
			return;
		}

		IIdType consentActor = getConsentActor(theUserSessionDetails);

		UriComponentsBuilder query = UriComponentsBuilder.fromPath("Consent")
				.queryParam("status", "active")
				.queryParam("patient.identifier", consentPatient.get().getValue())
				.queryParam("actor.identifier", consentActor.getValue());

		Bundle bundle = myFhirClient
				.search()
				.byUrl(query.toUriString())
				.returnBundle(Bundle.class)
				.execute();
		List<IDomainResource> consents = bundle.getEntry().stream()
				.map(entry -> (Consent) entry.getResource())
				.collect(Collectors.toList());
		theResolutionRequest.addActiveConsents(consents);
	}

	/**
	 * Determines the Organization of the requester that will be used as <code>Consent.actor</code>
	 * @param theUserSessionDetails - the user session details
	 * @return IdDt of the Organization that will be used as the <code>Consent.actor</code>
	 */
	private IIdType getConsentActor(UserSessionDetailsJson theUserSessionDetails) {
		// UserSessionDetailsJson contains all the user session and OIDC information for the incoming request
		// so implementers can determine the consent actor.
		String username = theUserSessionDetails.getUsername();
		if ("ADMIN".equals(theUserSessionDetails.getUsername())) {
			return myFhirContext.getVersion().newIdType("Organization", "1");
		} else {
			throw new IllegalArgumentException("Could not determine actor from UserSessionDetailsJson");
		}
	}

	/**
	 * Finds the Patient compartment of the provided resource which is used to determine the <code>Consent.patient</code>
	 * @param theResource - the resource that consent rules should apply to
	 * @return Optional IIdType of the Patient that will be used as the <code>Consent.patient</code> if the resource is in the Patient compartment
	 */
	private Optional<IIdType> getConsentPatient(IBaseResource theResource) {
		return CompartmentUtil.getPatientCompartmentForResource(myFhirContext, theResource);
	}
}

23.0.3.3Step 3: Define the `consentRules`

The consentRules are used create a list of policies which will be evaluated in the order that they are defined. Each consent rule must have a name and a single policy type.

There are two kinds of policies:

23.0.3.3.11) Consent Resource Policy

Note: Implementers may define Consent Resource policies for different Consent actors (i.e. Patient vs Organization).

A rule with a Consent Resource Policy must have the following properties:

  1. A matching property with one or more matchUrl elements 2. A consentResourcePolicy property

A Consent Resource Policy creates a list of Consent buckets that Consent resources will be put into. These are defined by a name and matchUrl. After Consent resources are obtained from Step 2 they will be placed into the "bucket" with the specified name if they meet the matchUrl criteria.

A new instance of an IConsentService will be created for each Consent resource. The actual implementation of the IConsentService will be mapped using the Consent Resource Policy (consentResourcePolicy property).

If any of the IConsentService instances in a bucket produce a REJECT verdict, the verdict for the entire rule will be REJECT. If the bucket does not produce any REJECT verdicts and an AUTHORIZED verdict, the verdict for the entire rule will be AUTHORIZED. If the bucket only produces PROCEED verdicts, the verdict for the entire rule will be PROCEED.

23.0.3.3.22) Fixed Policy

A rule with a Fixed Policy must have a fixedPolicy property.

Unlike a Consent Resource Policy, a Fixed Policy is not dependent on a Consent resource.

Fixed Policies can help implementers create rules to:

A Fixed Policy will create a new instance of an IConsentService for each resource in the incoming request. The actual implementation of the IConsentService will be mapped using the Fixed Policy (fixedPolicy property).

23.0.3.3.3Evaluation Across Consent Rules

As soon as there is a decisive verdict (i.e. AUTHORIZED or REJECT) from a consent rule, it will be used and none of the remaining consent rules will be evaluated. However, if the verdict from a rule is indecisive (i.e. PROCEED) the subsequent rules(s) will be evaluated.

23.0.3.3.4Consent Rules In The Sample Configuration

  1. ALLOW_USER_NAMES_RULE - Creates an IConsentService using the myAllowUserNamesConsentService key that will be used to render a Consent Verdict for the incoming resource.

    		{ "name": "ALLOW_USER_NAMES_RULE", "fixedPolicy":  "myAllowUserNamesConsentService" }
    
  2. BREAK_THE_GLASS_RULE - Contains a bucket for all Consent resources from Step 2 that have a purpose of BTG. These Consent resources, along with the IConsentService created using the myConsentService key, will be used to render a Consent Verdict for the incoming resource.

    	{ "name": "BREAK_THE_GLASS_RULE", "matching": [  { "matchUrl": "Consent?purpose=BTG"} ], "consentResourcePolicy":  "myConsentService"}
    
  3. PATIENT_GRANT_RULE - Contains a bucket for all Consent resources from Step 2 that have category of patient-grant-code. These Consent resources, along with the IConsentService created using the myConsentService key, will be used to render a Consent Verdict for the incoming resource.

    	{ "name": "PATIENT_GRANT_RULE", "matching": [  { "matchUrl": "Consent?category=patient-grant-code" } ], "consentResourcePolicy":  "myConsentService" }
    
  4. ALLOW_NON_PATIENT_COMPARTMENT_RULE - Creates an IConsentService using the ALLOW_NON_PATIENT_COMPARTMENT_RESOURCES key. This is a Smile provided IConsentService that will be produce a verdict of AUTHORIZED for any non-Patient compartment resource. If a resource is in the Patient compartment, it will produce a verdict of PROCEED.

       { "name": "ALLOW_NON_PATIENT_COMPARTMENT_RULE", "fixedPolicy":  "ALLOW_NON_PATIENT_COMPARTMENT_RESOURCES" }
    
  5. FALLBACK_RULE - Creates an IConsentService using the REJECT key. This is a Smile provided IConsentService that will always render a REJECT verdict. If an incoming resource does not reach a decisive verdict by the time it reaches the FALLBACK_RULE, it will be rejected.

    		{ "name": "FALLBACK_RULE", "fixedPolicy":  "REJECT" }
    

23.0.3.4Step 4: Map and Implement A Custom Consent Policy (If Applicable)

A Consent Policy is a name that maps to a Smile provided IConsentService or a custom IConsentService.

23.0.3.4.1Creating a custom `consentResourcePolicy`

To create a custom consentResourcePolicy, an IConsentService should be implemented that takes Consent resource as a constructor argument. An interceptor should also be created and registered with a CONSENT_BUILD_CONSENT_RESOURCE_POLICY_CONSENT_SERVICE pointcut that maps a String name to a new instance of the implemented IConsentService.

The code snippet below shows a sample Interceptor that implements that CONSENT_BUILD_CONSENT_RESOURCE_POLICY_CONSENT_SERVICE pointcut to create a custom consentResourcePolicy:

/*-
 * #%L
 * Smile CDR - CDR
 * %%
 * Copyright (C) 2016 - 2025 Smile CDR, Inc.
 * %%
 * All rights reserved.
 * #L%
 */
package com.smilecdr.demo.consentmodule;

import ca.cdr.api.fhir.interceptor.CdrHook;
import ca.cdr.api.fhir.interceptor.CdrPointcut;
import ca.uhn.fhir.rest.api.server.RequestDetails;
import ca.uhn.fhir.rest.server.interceptor.consent.ConsentOutcome;
import ca.uhn.fhir.rest.server.interceptor.consent.IConsentContextServices;
import ca.uhn.fhir.rest.server.interceptor.consent.IConsentService;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.r4.model.Consent;

/**
 * A sample interceptor that demonstrates how to use the CONSENT_BUILD_CONSENT_RESOURCE_POLICY_CONSENT_SERVICE pointcut
 */
@SuppressWarnings({"unused"})
public class BuildConsentResourcePolicyConsentServiceInterceptor {

	public static final String MY_CONSENT_SERVICE_NAME = "myConsentService";

	/**
	 * Uses the CONSENT_BUILD_CONSENT_RESOURCE_POLICY_CONSENT_SERVICE pointcut to map the <code>consentResourcePolicy</code> property
	 * to a custom <code>IConsentService</code> implementations.
	 * @param theConsentServiceName - the name of the consent service that should be mapped (from <code>consentResourcePolicy</code>)
	 * @param theConsent - the Consent resource.
	 * @return an IConsentService that will be used to supply a <code>consentResourcePolicy</code>
	 */
	@CdrHook(CdrPointcut.CONSENT_BUILD_CONSENT_RESOURCE_POLICY_CONSENT_SERVICE)
	public IConsentService buildConsentService(String theConsentServiceName, IBaseResource theConsent) {
		if (MY_CONSENT_SERVICE_NAME.equals(theConsentServiceName)) {
			return new MyConsentService(theConsent);
		}
		return null;
	}

	/**
	 * The implementation of IConsentService that will be used for the <code>consentResourcePolicy</code>
	 */
	static class MyConsentService implements IConsentService {
		private final Consent myConsent;

		public MyConsentService(IBaseResource theConsent) {
			if (!(theConsent instanceof Consent)) {
				throw new IllegalArgumentException(
						"Invalid Consent resource: " + theConsent.getIdElement().getIdPart());
			}
			myConsent = (Consent) theConsent;
		}

		@Override
		public ConsentOutcome canSeeResource(
				RequestDetails theRequestDetails,
				IBaseResource theResource,
				IConsentContextServices theContextServices) {
			if (isSpecialConsent(myConsent) && isSpecialResource(theResource)) {
				return ConsentOutcome.AUTHORIZED;
			}
			return ConsentOutcome.PROCEED;
		}

		private boolean isSpecialConsent(Consent theConsent) {
			return "some-special-consent".equals(theConsent.getId());
		}

		private boolean isSpecialResource(IBaseResource theResource) {
			return "some-special-resource".equals(theResource.getIdElement().getIdPart());
		}
	}
}

23.0.3.4.2Creating a custom `fixedPolicy`

To create a custom fixedPolicy, an IConsentService should be implemented. An interceptor should then be created and registered with a CONSENT_BUILD_FIXED_POLICY_CONSENT_SERVICE pointcut that maps a String name to a new instance of the implemented IConsentService.

The code snippet below shows a sample Interceptor that implements that CONSENT_BUILD_FIXED_POLICY_CONSENT_SERVICE pointcut to create a custom fixedPolicy:

/*-
 * #%L
 * Smile CDR - CDR
 * %%
 * Copyright (C) 2016 - 2025 Smile CDR, Inc.
 * %%
 * All rights reserved.
 * #L%
 */
package com.smilecdr.demo.consentmodule;

import ca.cdr.api.consent.ConsentFixedPolicyRequest;
import ca.cdr.api.fhir.interceptor.CdrHook;
import ca.cdr.api.fhir.interceptor.CdrPointcut;
import ca.cdr.api.model.json.UserSessionDetailsJson;
import ca.uhn.fhir.rest.api.server.RequestDetails;
import ca.uhn.fhir.rest.server.interceptor.consent.ConsentOutcome;
import ca.uhn.fhir.rest.server.interceptor.consent.IConsentContextServices;
import ca.uhn.fhir.rest.server.interceptor.consent.IConsentService;
import org.hl7.fhir.instance.model.api.IBaseResource;

import java.util.List;

/**
 * A sample interceptor that demonstrates how to use the CONSENT_BUILD_FIXED_POLICY_CONSENT_SERVICE pointcut
 */
@SuppressWarnings({"unused"})
public class BuildFixedPolicyConsentServiceInterceptor {

	public static final String MY_ALLOW_USER_NAME_CONSENT_SERVICE_NAME = "myAllowUserNamesConsentService";

	/**
	 * Uses the CONSENT_BUILD_FIXED_POLICY_CONSENT_SERVICE pointcut to map the <code>fixedPolicy</code> property
	 * to a custom <code>IConsentService</code> implementations.
	 * @param theFixedPolicyRequest {@link ConsentFixedPolicyRequest#getPolicyName()} contains the name of the consent
	 *                                  service that should be mapped (<code>myDefaultAllowConsentService</code>)
	 * @param theUserSessionDetails - the user session details.
	 * @return an IConsentService that will be used to supply a <code>fixedPolicy</code>
	 */
	@CdrHook(CdrPointcut.CONSENT_BUILD_FIXED_POLICY_CONSENT_SERVICE)
	public IConsentService buildConsentService(
			ConsentFixedPolicyRequest theFixedPolicyRequest, UserSessionDetailsJson theUserSessionDetails) {
		if (MY_ALLOW_USER_NAME_CONSENT_SERVICE_NAME.equals(theFixedPolicyRequest.getPolicyName())) {
			return new MyAllowUserNamesConsentService(theUserSessionDetails);
		}
		return null;
	}

	/**
	 * The implementation of IConsentService that will be used for the <code>fixedPolicy</code>
	 */
	static class MyAllowUserNamesConsentService implements IConsentService {

		private static final List<String> SPECIAL_ADMINS = List.of("ADMIN_1", "ADMIN_2", "ADMIN_3");

		private final UserSessionDetailsJson myUserSessionDetailsJson;

		public MyAllowUserNamesConsentService(UserSessionDetailsJson theUserSessionDetailsJson) {
			myUserSessionDetailsJson = theUserSessionDetailsJson;
		}

		@Override
		public ConsentOutcome canSeeResource(
				RequestDetails theRequestDetails,
				IBaseResource theResource,
				IConsentContextServices theContextServices) {
			if (isSpecialAdmin()) {
				return ConsentOutcome.AUTHORIZED;
			}
			return ConsentOutcome.PROCEED;
		}

		private boolean isSpecialAdmin() {
			return SPECIAL_ADMINS.contains(myUserSessionDetailsJson.getUsername());
		}
	}
}

23.0.4Consent Module Configuration (Diagram)

  Consent Module Configuration

23.0.5Consent Module Request Flow

 

The diagram below shows what a request could look like using the sample JSON configuration:

Consent Module Request Flow

23.0.6Bulk Export Support

 

In order to apply the rules configured in the Consent Module to bulk export requests (/$export) the register_with_persistence property must be enabled, and a persistence dependency must be selected.

NOTE: When the register_with_persistence property is enabled, the rules configured in the Consent Module configuration will apply to all FHIR Endpoints that use the specified persistence dependency.

23.0.7Glossary

 

23.0.7.1Active Consent Resources

The resources used to configure the Consent Service for a single request. These are the search results for the Consent Fetch Queries.

23.0.7.2Clinical Repository

A FHIR repository that contains clinical data (e.g. Observation, Condition, etc.) to be protected by Consent resources.

23.0.7.3Clinical Patient Compartment(s)

The Patient compartment(s) implicated by the query or Resource. For example, the query Observation?patient=Patient/1 would implicate the Patient/1 compartment.

Note: Chained queries may implicate many compartments. For example, if patient-1-mdm-id is a golden resource, then the query Observation?patient.identifier:mdm=patient-1-mdm-id may match several patients. In this case, each matched Patient resource will have its' own compartment.

23.0.7.4Consent Actor

The id of a resource in the Clinical Repository that will identify the actor of a request for purposes of Consent resolution. Each request should be mapped to an effective Consent.actor (i.e. Organization, Patient, Practitioner, etc.).

Implementers can use the UserSessionDetailsJson object provided by the CONSENT_FETCH_QUERIES pointcut to determine the Consent Actor. For example, a custom claim could be added to an OIDC client Access Token (i.e. Organization/1) which is mapped to the Consent Actor. Alternatively, the username of the Local Inbound Security User could be used to determine an effective Consent Actor.

23.0.7.5Consent Buckets

Consent buckets are defined by consentRules that have a consentResourcePolicy. They consist of a name and matchUrl. After Consent resources are obtained from the Consent fetch query they will be placed into the "bucket" with the specified name if they meet the matchUrl criteria.

23.0.7.6Consent Custodian

The individual responsible for creating and managing Consent resources.

23.0.7.7Consent Fetch Queries

The queries used to search for active Consent resources in the Consent Repository for a single request.

For example, this query would find Consent resources for a request on behalf of actor Organization/org-1 that apply to Patient/patient-1 (i.e. Consent?status=active&actor=Organization/org-1&patient=Patient/patient-1). Depending on your use of Consent resources, you may need to combine queries:

  • The query Consent?status=active&actor:missing=true&patient=Patient/patient-1 will find Consent resources for patient-1 that are not specific to a single actor. E.g. a blanket withdrawal of Consent.
  • The query Consent?status=active&actor=Organization/org-1&patient:missing=true will find Consent resources that apply to that actor regardless of the subject Patient.

23.0.7.8Consent Methods

The methods subject to Consent evaluation. The following Consent methods are supported by the Consent Module:

Consent Module JavaScript API Equivalent Java API Equivalent
startOperation consentStartOperation startOperation
canSeeResource consentCanSeeResource canSeeResource
willSeeResource consentWillSeeResource willSeeResource

23.0.7.9Consent Patient

The patient id (e.g. Patient/patient-1) used to search for Consent resources in the Consent Repository (i.e. Consent.patient). This may be the Clinical Patient compartment of the resource which Consent rules should apply, or might come from a header, or via some MDM Service. Actual Patient compartments may have a many-to-one relationship to a Consent Patient compartment.

For example, in the query Observation?category=imaging&patient=Patient/patient-1 if Patient/patient-1 is a golden resource, then there may be multiple Consent Patient compartments (i.e. for each matching Patient).

23.0.7.10Consent Repository

The FHIR repository that contains Consent resources which mediate access to the Clinical Repository. This may be the same as the Clinical Repository.

23.0.7.11Consent Resource Policy

Specified by the consentResourcePolicy property of a Consent Rule. It is the name of the IConsentService instance that will be created for each of the Consent resources in a Consent Bucket which will be used to determine a Consent Verdict of a request.

23.0.7.12Consent Verdict

Consent adjudications which may be one of three results: AUTHORIZED (i.e. allow), PROCEED (i.e. abstain), and REJECT (i.e. deny). These verdicts are defined by the ConsentOperationStatusEnum.

Of the three verdicts, AUTHORIZED and REJECT are considered decisive. A PROCEED verdict is considered indecisive.

23.0.7.13Fixed Policy

Specified by the fixedPolicy property of a Consent Rule. It is the name of the IConsentService instance that will be created for each resource in an incoming request which will be used to determine a Consent Verdict.

23.0.7.14Resolving Active Consent Resources

This is done inside the CONSENT_ACTIVE_CONSENT_RESOURCES_RESOLVE pointcut, and gives implementers the flexibility to provide Consent resource objects (IDomainResource) instead of a String-based Consent Fetch Query that will be applied to an incoming request.