DEV Community

myougaTheAxo
myougaTheAxo

Posted on

Designing GDPR/Data Privacy with Claude Code: Anonymization, Right to Erasure, Consent Management

Introduction

Under GDPR and data protection laws, users can request "delete my data." However, order history must be retained for accounting purposes. Generate designs with Claude Code for masking data while maintaining business continuity.


CLAUDE.md Data Privacy Rules

## GDPR Data Privacy Design Rules

### Data Classification
- Category A (identifiable): name, email, phone, address → delete/mask
- Category B (business required): order ID, amounts, timestamps → retain (anonymize)
- Category C (analytics): activity logs, access history → delete

### Right to Erasure
- "Anonymize" user data, don't "delete" it (business continuity)
- After anonymization, link to original person must be impossible
- Complete within 30 days

### Consent Management
- Separate consent by purpose (marketing, analytics, essential)
- Consent withdrawal possible at any time
- Retain consent history (audit trail)
Enter fullscreen mode Exit fullscreen mode

Generated GDPR Implementation

// src/privacy/dataAnonymizer.ts
export async function anonymizeUser(userId: string, requestedBy: string): Promise<AnonymizationResult> {
  const anonymousId = `deleted_${crypto.randomBytes(8).toString('hex')}`;

  await prisma.$transaction(async (tx) => {
    await tx.user.update({
      where: { id: userId },
      data: { name: '[Deleted User]', email: `${anonymousId}@anonymized.local`, phone: null, address: null, deletedAt: new Date(), anonymizedAt: new Date(), anonymizedId: anonymousId },
    });

    // Mask shipping info in orders (keep order for accounting)
    await tx.order.updateMany({
      where: { userId },
      data: { shippingName: '[Deleted User]', shippingAddress: null, shippingPhone: null },
    });

    // Delete activity logs (not needed for business)
    await tx.userActivityLog.deleteMany({ where: { userId } });

    // Remove all sessions and tokens
    await tx.refreshToken.deleteMany({ where: { userId } });
    await tx.session.deleteMany({ where: { userId } });

    // Remove marketing emails from queue
    await tx.emailQueue.deleteMany({ where: { recipientId: userId, type: { in: ['marketing', 'newsletter'] } } });

    // Record anonymization history (legal evidence)
    await tx.gdprDeletionAudit.create({
      data: { userId, anonymousId, requestedBy, completedAt: new Date() },
    });
  });

  return { recordsAnonymized: 1, completedAt: new Date() };
}
Enter fullscreen mode Exit fullscreen mode

Consent Management

// src/privacy/consentManager.ts
export async function recordConsent(userId: string, purpose: ConsentPurpose, granted: boolean, ipAddress: string): Promise<void> {
  await prisma.consentRecord.create({
    data: { userId, purpose, granted, grantedAt: new Date(), ipAddress, version: process.env.PRIVACY_POLICY_VERSION ?? '1.0' },
  });

  if (purpose === 'marketing' && !granted) {
    await prisma.emailQueue.deleteMany({ where: { recipientId: userId, type: 'marketing' } });
  }
}

export function requireConsent(purpose: ConsentPurpose) {
  return async (req: Request, res: Response, next: NextFunction) => {
    const hasConsent = await getConsent(req.user.id, purpose);
    if (!hasConsent) return res.status(403).json({ error: `Consent required for ${purpose}`, consentUrl: `/privacy/consent?purpose=${purpose}` });
    next();
  };
}
Enter fullscreen mode Exit fullscreen mode

Summary

Design GDPR Data Privacy with Claude Code:

  1. CLAUDE.md — data classification, anonymize not delete, 30-day timeline
  2. Anonymize instead of delete — maintain business continuity (keep order history)
  3. Separate consent by purpose — allow "withdraw only marketing consent"
  4. Retain anonymization history — legal audit trail (what was anonymized, when)

Review GDPR data privacy designs with **Security Pack (¥1,480)* using /security-check at prompt-works.jp*

myouga (@myougatheaxo) — Axolotl VTuber.

Top comments (0)