This skill provides comprehensive guidance for implementing and reviewing GDPR-compliant features in Empathy Ledger.
This skill provides comprehensive guidance for implementing and reviewing GDPR-compliant features in Empathy Ledger.
Requirement: Users can request a copy of their personal data
Implementation:
// GET /api/user/export
const data = await gdprService.exportUserData(userId)
// Returns: stories, media, profile, consent records, activity logs
Requirement: Users can correct inaccurate personal data
Implementation:
Requirement: Users can request deletion of their data
Implementation:
// POST /api/user/deletion-request
// Initiates 30-day deletion workflow
// POST /api/stories/[id]/anonymize
// Immediate anonymization of specific story
Anonymization Process:
Requirement: Users can export data in machine-readable format
Implementation:
interface ConsentRecord {
has_consent: boolean // Initial consent given
consent_verified: boolean // Consent verification completed
consent_method?: string // 'written' | 'verbal' | 'digital'
consent_date?: Date
consent_witness_id?: string // For verbal consent
}
// POST /api/stories/[id]/consent/withdraw
// Triggers:
// 1. Set consent_withdrawn_at timestamp
// 2. Revoke all embed tokens
// 3. Mark all distributions as revoked
// 4. Send webhook notifications
// 5. Queue external takedown requests
// 6. Create audit log entries
For Empathy Ledger, we rely on:
□ Export includes all user stories
□ Export includes media files
□ Export includes profile data
□ Export includes consent records
□ Export includes activity log
□ Format is JSON (machine-readable)
□ Download is secure (authenticated)
□ Deletion request creates ticket
□ User receives confirmation email
□ 30-day processing window
□ All stories anonymized or deleted
□ All media files removed
□ Profile data erased
□ Audit trail anonymized
□ Third-party distributions notified
□ Consent captured before distribution
□ Consent method recorded
□ Consent can be withdrawn
□ Withdrawal cascades automatically
□ Audit trail for consent changes
□ Re-consent required for new purposes
GET /api/user/export - Export all user dataPOST /api/user/deletion-request - Request account deletionGET /api/user/deletion-request - Check deletion statusPOST /api/stories/[id]/anonymize - Anonymize specific storyPOST /api/stories/[id]/consent/withdraw - Withdraw consentGET /api/stories/[id]/audit - View story audit trailPOST /api/stories/[id]/audit/export - Export audit reportCREATE TABLE deletion_requests (
id UUID PRIMARY KEY,
user_id UUID NOT NULL,
tenant_id UUID NOT NULL,
request_type TEXT NOT NULL, -- 'anonymize_story', 'delete_account'
status TEXT DEFAULT 'pending', -- 'pending', 'processing', 'completed'
requested_at TIMESTAMPTZ,
processed_at TIMESTAMPTZ,
completed_at TIMESTAMPTZ
);
-- On stories table
anonymization_status TEXT, -- null, 'partial', 'full'
anonymized_fields JSONB, -- Track what was anonymized
consent_withdrawn_at TIMESTAMPTZ -- When consent was withdrawn
class GDPRService {
exportUserData(userId: string): Promise<DataExport>
anonymizeStory(storyId: string): Promise<AnonymizeResult>
anonymizeUserData(userId: string): Promise<AnonymizeResult>
createDeletionRequest(userId: string, type: string): Promise<Request>
processDeletionRequest(requestId: string): Promise<void>
scrubPII(content: string): string
}
When reviewing code, verify: