Data Rights Management
Overview
ASCEND's Data Rights Management system provides enterprise-grade automation for data subject rights processing, supporting both GDPR and CCPA requirements. The system implements fail-closed tenant isolation (ONBOARD-019) ensuring complete data segregation between organizations.
Key Features:
- Automated data discovery and inventory
- Right to access (GDPR Art. 15, CCPA 1798.110)
- Right to erasure (GDPR Art. 17, CCPA 1798.105)
- Right to portability (GDPR Art. 20)
- Consent management (GDPR Art. 6-7)
- Data lineage tracking
- Immutable audit trail
Supported Regulations
| Regulation | Region | Features Supported |
|---|---|---|
| GDPR | EU/EEA | Full compliance |
| UK GDPR | United Kingdom | Full compliance |
| CCPA | California, USA | Full compliance |
| CPRA | California, USA | Full compliance |
| VCDPA | Virginia, USA | Partial |
| CPA | Colorado, USA | Partial |
Architecture
Tenant Isolation (ONBOARD-019)
All data rights operations are strictly scoped to a single organization:
class DataSubjectRightsService:
"""
ONBOARD-019: Enterprise Tenant Isolation
- organization_id required in constructor (fail-closed)
- All queries filter by organization_id
- Immutable audit logging on all operations
"""
def __init__(self, db: Session, organization_id: int):
if organization_id is None:
raise ValueError(
"organization_id is required for tenant isolation."
)
self.db = db
self.organization_id = organization_id
Security Properties:
| Property | Implementation |
|---|---|
| Fail-closed design | Missing org_id raises exception |
| Query scoping | All queries include organization_id filter |
| No cross-tenant access | Architecture prevents data leakage |
| Audit trail | All operations logged with org context |
Database Schema
-- Data Subject Requests
CREATE TABLE data_subject_requests (
id SERIAL PRIMARY KEY,
request_id VARCHAR(50) UNIQUE NOT NULL,
organization_id INTEGER NOT NULL REFERENCES organizations(id),
subject_email VARCHAR(255) NOT NULL,
subject_id INTEGER REFERENCES users(id),
request_type VARCHAR(50) NOT NULL, -- ACCESS, ERASURE, PORTABILITY
legal_basis VARCHAR(100),
compliance_framework VARCHAR(20), -- GDPR, CCPA
status VARCHAR(50) DEFAULT 'RECEIVED',
priority VARCHAR(20) DEFAULT 'NORMAL',
verification_status VARCHAR(50) DEFAULT 'PENDING',
request_details JSONB,
result_data JSONB,
due_date TIMESTAMPTZ,
completed_at TIMESTAMPTZ,
created_at TIMESTAMPTZ DEFAULT NOW()
);
-- Consent Records
CREATE TABLE consent_records (
id SERIAL PRIMARY KEY,
organization_id INTEGER NOT NULL REFERENCES organizations(id),
subject_email VARCHAR(255) NOT NULL,
subject_id INTEGER REFERENCES users(id),
consent_type VARCHAR(100) NOT NULL,
purpose TEXT,
legal_basis VARCHAR(100),
granted BOOLEAN DEFAULT FALSE,
granted_at TIMESTAMPTZ,
withdrawn_at TIMESTAMPTZ,
consent_method VARCHAR(50),
ip_address INET,
user_agent TEXT,
created_at TIMESTAMPTZ DEFAULT NOW()
);
-- Data Lineage
CREATE TABLE data_lineage (
id SERIAL PRIMARY KEY,
organization_id INTEGER NOT NULL REFERENCES organizations(id),
subject_email VARCHAR(255) NOT NULL,
data_category VARCHAR(100) NOT NULL,
data_source VARCHAR(255),
sensitivity_level VARCHAR(20),
legal_basis_processing VARCHAR(100),
processing_purpose TEXT,
retention_period VARCHAR(100),
created_at TIMESTAMPTZ DEFAULT NOW()
);
-- Erasure Audit Log
CREATE TABLE data_erasure_log (
id SERIAL PRIMARY KEY,
organization_id INTEGER NOT NULL REFERENCES organizations(id),
request_id VARCHAR(50),
subject_email VARCHAR(255) NOT NULL,
erasure_type VARCHAR(50), -- FULL, PARTIAL, ANONYMIZATION
tables_affected TEXT[],
records_affected INTEGER,
records_deleted INTEGER,
executed_by_email VARCHAR(255),
execution_method VARCHAR(50),
legal_basis VARCHAR(100),
verification_hash VARCHAR(64),
executed_at TIMESTAMPTZ DEFAULT NOW()
);
Data Subject Request API
Create Request
POST /api/v1/data-rights/requests
Authorization: Bearer {token}
Content-Type: application/json
{
"subject_email": "user@example.com",
"request_type": "ACCESS",
"legal_basis": "GDPR Article 15",
"priority": "NORMAL"
}
Response:
{
"request_id": "DSR-20260120-ABC123",
"organization_id": 1,
"subject_email": "user@example.com",
"request_type": "ACCESS",
"legal_basis": "GDPR Article 15",
"compliance_framework": "GDPR",
"status": "RECEIVED",
"priority": "NORMAL",
"verification_status": "PENDING",
"due_date": "2026-02-19T00:00:00Z",
"created_at": "2026-01-20T10:00:00Z"
}
Request Types
| Type | GDPR Article | CCPA Section | Description |
|---|---|---|---|
| ACCESS | Article 15 | 1798.110 | Provide copy of personal data |
| ERASURE | Article 17 | 1798.105 | Delete personal data |
| PORTABILITY | Article 20 | 1798.100 | Export in machine-readable format |
| RECTIFICATION | Article 16 | - | Correct inaccurate data |
| RESTRICTION | Article 18 | - | Limit processing |
| OBJECTION | Article 21 | 1798.120 | Object to processing |
Response Timelines
| Framework | Standard | Complex Cases |
|---|---|---|
| GDPR | 30 days | +60 days (with notice) |
| CCPA | 45 days | +45 days (with notice) |
Data Discovery
Start Discovery
POST /api/v1/data-rights/discover
Authorization: Bearer {token}
Content-Type: application/json
{
"request_id": "DSR-20260120-ABC123",
"subject_email": "user@example.com"
}
Response:
{
"subject_email": "user@example.com",
"discovery_completed_at": "2026-01-20T10:05:00Z",
"locations_found": 4,
"data_locations": [
{
"table": "users",
"category": "PROFILE",
"record_count": 1,
"sensitivity": "HIGH"
},
{
"table": "agent_actions",
"category": "AGENT_INTERACTION",
"record_count": 156,
"sensitivity": "MEDIUM"
},
{
"table": "consent_records",
"category": "CONSENT",
"record_count": 3,
"sensitivity": "HIGH"
},
{
"table": "data_lineage",
"category": "DATA_LINEAGE",
"record_count": 5,
"sensitivity": "MEDIUM"
}
]
}
Get Data Sources
GET /api/v1/data-rights/sources?subject_email=user@example.com
Authorization: Bearer {token}
Response:
{
"sources": [
{
"source": "users",
"category": "Profile Data",
"retention": "Account lifetime"
},
{
"source": "agent_actions",
"category": "Interaction Data",
"retention": "7 years"
},
{
"source": "consent_records",
"category": "Consent Data",
"retention": "3 years after withdrawal"
}
]
}
Export Request API
Generate Access Package
POST /api/v1/data-rights/access-package
Authorization: Bearer {token}
Content-Type: application/json
{
"subject_email": "user@example.com",
"format": "json",
"include_metadata": true
}
Response:
{
"profile": {
"user_id": 123,
"email": "user@example.com",
"role": "standard_user",
"created_at": "2025-06-15T08:30:00Z",
"is_active": true
},
"agent_interactions": [
{
"id": 456,
"agent_id": "support-agent",
"tool": "query_database",
"timestamp": "2026-01-19T14:30:00Z",
"risk_level": "low",
"status": "completed"
}
],
"consent_history": [
{
"consent_type": "marketing_emails",
"purpose": "Marketing communications",
"legal_basis": "consent",
"granted": true,
"granted_at": "2025-06-15T08:35:00Z"
}
],
"data_lineage": [
{
"data_category": "profile_data",
"data_source": "registration_form",
"sensitivity_level": "HIGH",
"legal_basis_processing": "contract",
"processing_purpose": "Account management"
}
]
}
Export Formats
| Format | Content-Type | Use Case |
|---|---|---|
| JSON | application/json | API integration |
| CSV | text/csv | Spreadsheet import |
| XML | application/xml | Enterprise systems |
Deletion Request API
Assess Erasure Eligibility
POST /api/v1/data-rights/erasure/assess
Authorization: Bearer {token}
Content-Type: application/json
{
"request_id": "DSR-20260120-ABC123",
"subject_email": "user@example.com"
}
Response:
{
"eligible_for_erasure": [
{
"category": "profile_data",
"table": "users",
"reason": "No retention requirement"
},
{
"category": "consent_records",
"table": "consent_records",
"record_count": 3,
"reason": "No active retention requirement"
}
],
"retention_required": [
{
"category": "agent_interactions",
"table": "agent_actions",
"record_count": 156,
"reason": "SOX/PCI-DSS 7-year retention requirement",
"alternative": "Anonymization available"
}
],
"assessment_notes": [
"Audit logs will be anonymized, not deleted",
"Financial records retained per legal requirement"
]
}
Execute Erasure
POST /api/v1/data-rights/erasure/execute
Authorization: Bearer {token}
Content-Type: application/json
{
"request_id": "DSR-20260120-ABC123",
"subject_email": "user@example.com",
"erasure_scope": "FULL",
"data_categories": ["profile", "consent", "lineage"],
"retention_exceptions": ["agent_actions"],
"performed_by": "compliance@example.com"
}
Response:
{
"scope": "FULL",
"systems_affected": ["users", "consent_records", "data_lineage"],
"records_erased": 9,
"records_anonymized": 156,
"retention_exceptions": ["agent_actions"],
"completed_at": "2026-01-20T10:30:00Z",
"audit_trail_id": "erasure-log-789",
"verification_hash": "sha256:abc123def456..."
}
Erasure Scopes
| Scope | Description |
|---|---|
| FULL | Delete all eligible data, anonymize retained |
| PARTIAL | Delete specified categories only |
| ANONYMIZATION | Replace PII with anonymous identifiers |
Retention Policies
Default Retention Schedule
GET /api/v1/data-rights/retention-schedule?subject_email=user@example.com
Authorization: Bearer {token}
Response:
{
"profile_data": "Retained while account is active",
"interaction_data": "7 years for compliance purposes (SOX, PCI-DSS)",
"audit_data": "7 years as required by financial regulations",
"consent_data": "3 years after consent withdrawal",
"erasure_logs": "Permanent (legal compliance evidence)"
}
Retention by Data Category
| Category | Retention Period | Legal Basis |
|---|---|---|
| Profile data | Account lifetime + 30 days | Contract |
| Agent interactions | 7 years | SOX, PCI-DSS |
| Audit logs | 7 years | Financial regulations |
| Consent records | 3 years after withdrawal | GDPR evidence |
| Erasure logs | Permanent | Legal compliance |
| Security events | 7 years | SOC 2 |
Audit Trail
Audit Log Structure
Every data rights operation is logged with:
{
"organization_id": 1,
"event_type": "DATA_ERASURE_EXECUTED",
"action": "EXECUTE_ERASURE",
"resource_type": "DATA_SUBJECT",
"resource_id": "user@example.com",
"actor_id": "compliance@example.com",
"risk_level": "CRITICAL",
"details": {
"request_id": "DSR-20260120-ABC123",
"erasure_scope": "FULL",
"records_erased": 9,
"records_anonymized": 156,
"systems_affected": ["users", "consent_records", "data_lineage"]
},
"timestamp": "2026-01-20T10:30:00Z"
}
Audit Event Types
| Event Type | Risk Level | Description |
|---|---|---|
| DATA_SUBJECT_REQUEST_CREATED | MEDIUM | New request received |
| DATA_SUBJECT_REQUEST_UPDATED | LOW | Status change |
| DATA_ACCESS_PACKAGE_GENERATED | HIGH | Data exported |
| DATA_ERASURE_EXECUTED | CRITICAL | Data deleted/anonymized |
| CONSENT_RECORDED | MEDIUM | Consent given/withdrawn |
| DATA_LINEAGE_RECORDED | LOW | Lineage tracking update |
Compliance Reporting
Generate Compliance Report
POST /api/v1/data-rights/reports
Authorization: Bearer {token}
Content-Type: application/json
{
"report_type": "SUMMARY",
"date_range": {
"start": "2026-01-01",
"end": "2026-01-20"
}
}
Response:
{
"report_period": {
"start": "2026-01-01T00:00:00Z",
"end": "2026-01-20T23:59:59Z"
},
"request_summary": {
"total_requests": 45,
"completed_requests": 42,
"completion_rate": 93.33,
"overdue_requests": 0
},
"request_breakdown": {
"access_requests": 25,
"erasure_requests": 15,
"portability_requests": 5
},
"erasure_summary": {
"total_erasures_executed": 15,
"records_deleted": 1250,
"records_anonymized": 3400
},
"compliance_status": {
"gdpr_compliant": true,
"response_deadline_met": true,
"audit_trail_complete": true
},
"organization_id": 1
}
Metrics Dashboard
| Metric | Target | Current |
|---|---|---|
| Request completion rate | > 95% | 93.33% |
| Average response time | < 15 days | 12 days |
| Overdue requests | 0 | 0 |
| Audit coverage | 100% | 100% |
Data Lineage
Create Lineage Record
POST /api/v1/data-lineage
Authorization: Bearer {token}
Content-Type: application/json
{
"subject_identifier": "user@example.com",
"data_type": "profile_data",
"source_system": "registration_form",
"destination_system": "user_database",
"processing_purpose": "Account management",
"legal_basis": "contract",
"retention_period": "Account lifetime",
"data_classification": "HIGH"
}
Get Subject Lineage
GET /api/v1/data-lineage?subject_email=user@example.com
Authorization: Bearer {token}
Response:
{
"data_types": ["profile_data", "interaction_data", "consent_data"],
"source_systems": ["registration_form", "api", "agent_service"],
"processing_purposes": ["Account management", "AI governance", "Compliance"],
"retention_summary": {
"profile_data": "Account lifetime",
"interaction_data": "7 years",
"consent_data": "3 years after withdrawal"
},
"lineage_records": [
{
"id": "uuid-123",
"data_category": "profile_data",
"data_source": "registration_form",
"processing_purpose": "Account management",
"legal_basis": "contract",
"sensitivity": "HIGH",
"retention": "Account lifetime"
}
]
}
API Reference Summary
Data Subject Requests
| Method | Endpoint | Description |
|---|---|---|
| POST | /api/v1/data-rights/requests | Create request |
| GET | /api/v1/data-rights/requests | List requests |
| GET | /api/v1/data-rights/requests/{id} | Get request |
| PATCH | /api/v1/data-rights/requests/{id} | Update status |
Discovery and Export
| Method | Endpoint | Description |
|---|---|---|
| POST | /api/v1/data-rights/discover | Discover data |
| GET | /api/v1/data-rights/sources | Get data sources |
| POST | /api/v1/data-rights/access-package | Generate access package |
| POST | /api/v1/data-rights/export | Export data |
Erasure
| Method | Endpoint | Description |
|---|---|---|
| POST | /api/v1/data-rights/erasure/assess | Assess eligibility |
| POST | /api/v1/data-rights/erasure/execute | Execute erasure |
Consent
| Method | Endpoint | Description |
|---|---|---|
| POST | /api/v1/consent/record | Record consent |
| POST | /api/v1/consent/withdraw | Withdraw consent |
| GET | /api/v1/consent/history | Get history |
Lineage and Reporting
| Method | Endpoint | Description |
|---|---|---|
| POST | /api/v1/data-lineage | Create lineage |
| GET | /api/v1/data-lineage | Get lineage |
| POST | /api/v1/data-rights/reports | Generate report |
| GET | /api/v1/data-rights/retention-schedule | Get retention |