Implementing CCPA Consumer Rights
Implementing CCPA Consumer Rights
CCPA grants California consumers specific rights that require technical implementation. The right to know allows consumers to request disclosure of personal information collected, sources, purposes, and third parties with whom information is shared. The right to delete enables consumers to request deletion of their personal information, subject to certain exceptions. The right to opt-out requires businesses to provide mechanisms for consumers to direct businesses not to sell their personal information. The right to non-discrimination prohibits businesses from discriminating against consumers who exercise their privacy rights.
// CCPA consumer rights implementation
class CCPAConsumerRights {
constructor() {
this.requestTypes = {
KNOW: 'right-to-know',
DELETE: 'right-to-delete',
OPT_OUT: 'right-to-opt-out',
OPT_IN: 'right-to-opt-in'
};
this.verificationMethods = {
EMAIL: 'email-verification',
PHONE: 'phone-verification',
ACCOUNT: 'account-verification'
};
}
// Handle right to know requests
async processRightToKnow(requestData) {
// Verify consumer identity
const verified = await this.verifyConsumer(requestData);
if (!verified.success) {
return {
status: 'verification-failed',
reason: verified.reason,
requestId: requestData.requestId
};
}
// Gather personal information
const personalInfo = await this.gatherPersonalInformation(verified.consumerId);
// Generate disclosure report
const report = {
requestId: requestData.requestId,
timestamp: new Date().toISOString(),
consumer: {
id: verified.consumerId,
verificationMethod: verified.method
},
disclosure: {
categoriesCollected: this.categorizePersonalInfo(personalInfo),
specificPieces: this.formatPersonalInfo(personalInfo),
sourcesOfCollection: await this.getDataSources(verified.consumerId),
purposesOfCollection: this.getProcessingPurposes(),
thirdPartySharing: await this.getThirdPartySharing(verified.consumerId),
salesDisclosure: await this.getDataSales(verified.consumerId)
}
};
// Log request for compliance
await this.logConsumerRequest(report);
// Deliver report securely
await this.deliverReport(verified.consumerId, report);
return {
status: 'success',
requestId: requestData.requestId,
deliveryMethod: 'secure-portal'
};
}
// Verify consumer identity
async verifyConsumer(requestData) {
const verificationSteps = [];
// Email verification
if (requestData.email) {
const emailVerified = await this.sendVerificationEmail(requestData.email);
verificationSteps.push({
method: this.verificationMethods.EMAIL,
status: emailVerified
});
}
// Account verification
if (requestData.accountId) {
const accountVerified = await this.verifyAccountOwnership(
requestData.accountId,
requestData.credentials
);
verificationSteps.push({
method: this.verificationMethods.ACCOUNT,
status: accountVerified
});
}
// Assess verification strength
const verificationStrength = this.assessVerificationStrength(verificationSteps);
return {
success: verificationStrength >= 2,
consumerId: requestData.accountId || this.generateConsumerId(requestData),
method: verificationSteps.filter(s => s.status).map(s => s.method),
reason: verificationStrength < 2 ? 'Insufficient verification' : null
};
}
// Handle deletion requests
async processRightToDelete(requestData) {
const verified = await this.verifyConsumer(requestData);
if (!verified.success) {
return {
status: 'verification-failed',
reason: verified.reason
};
}
// Check for exceptions
const exceptions = await this.checkDeletionExceptions(verified.consumerId);
if (exceptions.length > 0) {
return {
status: 'partial-deletion',
retained: exceptions,
reason: 'Legal or business requirements'
};
}
// Process deletion
const deletionResult = await this.deletePersonalInformation(verified.consumerId);
// Notify third parties
await this.notifyThirdPartiesOfDeletion(verified.consumerId);
// Log deletion
await this.logDeletion({
consumerId: verified.consumerId,
timestamp: new Date().toISOString(),
categoriesDeleted: deletionResult.categories,
recordsDeleted: deletionResult.count
});
return {
status: 'success',
requestId: requestData.requestId,
deletionSummary: deletionResult
};
}
// Implement opt-out mechanism
async processOptOut(requestData) {
// CCPA doesn't require verification for opt-out
const consumerId = this.identifyConsumer(requestData);
// Update opt-out status
await this.updateOptOutStatus(consumerId, true);
// Stop any pending data sales
await this.haltDataSales(consumerId);
// Update cookie preferences
this.updateCookieConsent(consumerId, {
advertising: false,
analytics: false,
thirdParty: false
});
// Notify partners
await this.notifyPartnersOfOptOut(consumerId);
return {
status: 'success',
consumerId,
effectiveDate: new Date().toISOString()
};
}
// Delete personal information with exceptions
async deletePersonalInformation(consumerId) {
const deletionPlan = {
categories: [],
count: 0,
retained: []
};
// Define deletion exceptions
const exceptions = {
activeTransactions: await this.hasActiveTransactions(consumerId),
legalObligations: await this.hasLegalObligations(consumerId),
securityPurposes: await this.getSecurityRelatedData(consumerId),
internalUses: await this.getCompatibleInternalUses(consumerId)
};
// Delete data not covered by exceptions
const allData = await this.getAllConsumerData(consumerId);
for (const [category, data] of Object.entries(allData)) {
if (!this.isExemptFromDeletion(category, exceptions)) {
await this.deleteDataCategory(consumerId, category);
deletionPlan.categories.push(category);
deletionPlan.count += data.length;
} else {
deletionPlan.retained.push({
category,
reason: this.getExemptionReason(category, exceptions)
});
}
}
return deletionPlan;
}
}