Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Table of Contents

Migration

The biggest change in the system will be that participant-facing APIs will no longer throw a 412 if the user is enrolled in any study in the app. This is different than the Subpopulation model where some subpopulations require consent, and some do not.

In the first version of consent, we matched subpopulations based on criteria, and then returned 412 if any of the required consents were not signed. To disable consent, you created a new, optional subpopulation, the only purpose of which was to turn off the 412 responses without having to sign consent.

In the new consent system, you would model this as two studies that shared the same protocols, and enrollment state, where one had a consent assigned to it and one did not. (There’s no use of criteria to select which one a user should enroll in…creating an external ID for an account is one way to enroll someone in a study.)

  1. Refactor subpopulations to use a single String guid, so an account’s consent signatures can continue to work to persist consents under the new consent system;

  2. For every required subpopulation, create a study, and change the subpopulation to enroll the user in that study when the subpopulation consent is signed. (Possibly require this going forward.)

  3. Migrate all existing accounts with consents by adding enrollment records for these.

  4. Going forward, consents will merge with the presence of an enrollment record, in many cases (if a study enrolled people but didn’t require them to consent or use an external ID, the reality is, we don’t know that they are enrolled).

The App object should include a consent version number, and existing studies should be marked as v1. Subpopulations, consents, and study consents should continue to work for v1 applications. The v2 consent system is described below.We intend to revise our consent system for a few purposes:

  1. To provide a server model that can drive re-usable or dynamically-rendered user interfaces to design and to present informed consent;

  2. To better track where people fail to enroll (eligibility requirements, the informed consent process);

  3. Internally we are going to insert a layer between apps and consents in the form of a study. Consents will be reusable elements that are explicitly associated to studies.

In an alternative universe where we don’t intend to provide #1 (in particular), we could refactor Subpopulation to be this new top-level Consent object, and reuse almost all of our existing consent infrastructure with a new association between Study (originally Substudy) and Consent (originally Subpopulation). So it’s worth checking again that we really want to perform this refactor.

Consent v2

Each study has one (and only one) required consent that must be signed to enroll in the study (with the caveat that the required consent may be in multiple languages). The consent can also be flagged if the client should force the user to reconsent (the user enrolled with a prior consent). There can be any number of optional, supplemental consents that can be presented to the user.

...

And in place of many of these, I would add one field: enrollments. This would be an array of enrollment records without withdrawn records (see above). A user is considered “consented” to access participant-facing APIs without receiving a 412 from the API if they have at least one enrollment record.

...

Migration

The new consent objects will be created in SQL and will replace StudyConsent, Subpopulation. ConsentSignature will continue to be stored in SQL as it is now, repurposing the AccountConsents table (the content of a signature is not changing).The consent signatures table may be able to store signatures for the v2 version of consent, if the consent GUID can be stored in the subpopulation GUID column (the values are in fact globally unique)biggest change in the system will be that participant-facing APIs will no longer throw a 412 if the user is enrolled in any study in the app. This is different than the Subpopulation model where some subpopulations require consent, and some do not.

In the first version of consent, we matched subpopulations based on criteria, and then returned 412 if any of the required consents were not signed. To disable consent, you created a new, optional subpopulation, the only purpose of which was to turn off the 412 responses without having to sign consent.

In the new consent system, you would model this as two studies that shared the same protocols, and enrollment state, where one had a consent assigned to it and one did not. (There’s no use of criteria to select which one a user should enroll in…creating an external ID for an account is one way to enroll someone in a study.)

  1. Refactor subpopulations to use a single String guid, so an account’s consent signatures can continue to work to persist consents under the new consent system;

  2. For every required subpopulation, create a study, and change the subpopulation to enroll the user in that study when the subpopulation consent is signed. (Possibly require this going forward.)

  3. Migrate all existing accounts with consents by adding enrollment records for these.

  4. Going forward, consents will merge with the presence of an enrollment record, in many cases (if a study enrolled people but didn’t require them to consent or use an external ID, the reality is, we don’t know that they are enrolled).

The App object should include a consent version number, and existing studies should be marked as v1. Subpopulations, consents, and study consents should continue to work for v1 applications. The v2 consent system is described below.

Candidates API

Code Block
Candidate {
    String anonymousId;
    DateTime firstContactOn;
    DateTime mostRecentContactOn;
    String anonSessionToken;
    // should map 1:1 with a consent, but we can include consentGuid
    String studyId; 
    String userId;
    String stepCompleted; // eligibility, comprehension, consented, demographics
    Enum eligibility; // eligible, ineligible
    List<RejectedAnswer> eligibilityRejections;
    JsonNode clientState;
}

...