# Consent Management {#consent-management}



## Overview {#overview}


MQUAD provides a consent management system for tracking participant consent in surveys, supporting GDPR and other regulatory compliance requirements.


## Data Model {#data-model}


Consent records are stored in the `audit_db` database:

| Field | Type | Description |
|-------|------|-------------|
| `id` | UUID | Unique consent record ID |
| `participant_id` | String | Participant identifier |
| `survey_id` | UUID | Associated survey |
| `consent_type` | String | Type of consent |
| `status` | Enum | `granted`, `withdrawn`, `expired` |
| `granted_at` | DateTime | When consent was given |
| `withdrawn_at` | DateTime | When consent was withdrawn |
| `expires_at` | DateTime | Consent expiry |
| `metadata` | JSON | Additional data |


## Consent Types {#consent-types}


| Type | Description |
|------|-------------|
| `survey_participation` | Consent to participate in survey |
| `data_processing` | Consent to process response data |
| `data_sharing` | Consent to share with third parties |
| `follow_up` | Consent for future follow-up contact |


## Consent Flow {#consent-flow}


```
Survey presented ──► Consent form shown
                         │
                    [Agree] [Disagree]
                         │
                    Consent recorded
                    (audit_db.consent_records)
                         │
                    Survey proceeds
                         │
              ┌──────────┴──────────┐
              │                     │
        Withdrawal             Expiry
              │                     │
        Data anonymized       Consent re-requested
```


## Consent Withdrawal {#consent-withdrawal}


When a participant withdraws consent:

```python
async def withdraw_consent(participant_id: str, consent_type: str):
    # 1. Update consent record status
    consent = await consent_repo.find_active(participant_id, consent_type)
    consent.status = "withdrawn"
    consent.withdrawn_at = datetime.utcnow()

    # 2. Anonymize or delete associated data
    await anonymize_participant_data(participant_id)

    # 3. Log audit event
    await log_audit(event_type="consent.withdrawn", ...)
```


## Audit Trail {#audit-trail}


All consent actions create audit events:

```python
events = [
    "consent.granted",
    "consent.withdrawn",
    "consent.expired",
    "consent.renewed",
]
```


## API {#api}


```bash
# Record consent
POST /consent
{
  "participant_id": "part-001",
  "survey_id": "survey-uuid",
  "consent_type": "survey_participation",
  "status": "granted"
}

# Withdraw consent
POST /consent/{id}/withdraw
{
  "reason": "Participant requested data removal"
}

# Check consent status
GET /consent?participant_id=part-001&consent_type=survey_participation
```


## Retention {#retention}


Consent records are retained for **10 years** (or as required by local regulations) before archival. Even withdrawn consents are retained to prove compliance.
