Skip to content
Development
Skill

/kvkk-compliance

KVKK and GDPR compliance patterns - consent management, right to erasure, breach notification, audit logging, cookie consent, and data classification.

From plugin
vibecosystem
532200 skills138 agents7 hooks
Install
$ npx -y skills add vibeeval/vibecosystem --skill kvkk-compliance --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/kvkk-compliance

Context preview

The summary Claude sees to decide when to auto-load this skill.

KVKK and GDPR compliance patterns - consent management, right to erasure, breach notification, audit logging, cookie consent, and data classification.

SKILL.md

kvkk-compliance.SKILL.md
name: kvkk-compliance
description: KVKK and GDPR compliance patterns - consent management, right to erasure, breach notification, audit logging, cookie consent, and data classification.

KVKK & GDPR Compliance Patterns

Practical patterns for Turkish KVKK (Law No. 6698) and EU GDPR data protection compliance.

KVKK vs GDPR Comparison

| Aspect | KVKK (Turkey) | GDPR (EU) | |--------|---------------|-----------| | Authority | KVKK Board (Kisisel Verileri Koruma Kurumu) | National DPAs + EDPB | | Consent | Explicit, no pre-ticked boxes | Freely given, specific, informed | | Breach notification | "As soon as possible" to Board | 72 hours to DPA | | DPO requirement | VERBiS registration | Mandatory for public bodies + large-scale | | Right to erasure | Article 7 - withdrawal + deletion | Article 17 - "Right to be forgotten" | | Data transfer abroad | Board approval or adequate country | Adequacy decision, SCCs, or BCRs | | Fines | Up to ~2M TL per violation | Up to 20M EUR or 4% global turnover | | Legal bases | 5 in Article 5 + explicit consent | 6 in Article 6 + explicit consent |

Data Classification

enum DataCategory {
  PERSONAL = 'personal',           // name, email, phone
  SPECIAL = 'special_category',    // health, biometrics, religion
  ANONYMOUS = 'anonymous',         // cannot identify anyone
  PSEUDONYMOUS = 'pseudonymous',   // identifiable only with additional data
}

interface DataField {
  name: string
  category: DataCategory
  retentionDays: number
  requiresExplicitConsent: boolean
  encryptAtRest: boolean
}

const USER_DATA_FIELDS: DataField[] = [
  { name: 'email', category: DataCategory.PERSONAL, retentionDays: 730, requiresExplicitConsent: false, encryptAtRest: false },
  { name: 'healthRecords', category: DataCategory.SPECIAL, retentionDays: 365, requiresExplicitConsent: true, encryptAtRest: true },
  { name: 'analyticsId', category: DataCategory.PSEUDONYMOUS, retentionDays: 365, requiresExplicitConsent: false, encryptAtRest: false },
]

Consent Management

// BAD: single "accept all" checkbox - violates both KVKK and GDPR
// <input type="checkbox" /> I accept everything

// GOOD: granular, purpose-specific consent
interface ConsentRecord {
  userId: string; purpose: string; granted: boolean
  timestamp: Date; ipAddress: string; version: string
}

const CONSENT_PURPOSES = [
  { id: 'essential', label: 'Service operation', required: true },
  { id: 'analytics', label: 'Usage analytics', required: false },
  { id: 'marketing', label: 'Marketing emails', required: false },
  { id: 'third_party', label: 'Third-party sharing', required: false },
] as const

async function recordConsent(userId: string, purposeId: string, granted: boolean, meta: { ip: string; userAgent: string }): Promise<ConsentRecord> {
  // Always INSERT, never UPDATE - full audit trail
  return db.consentRecords.create({
    data: { userId, purpose: purposeId, granted, timestamp: new Date(), ipAddress: meta.ip, version: CURRENT_CONSENT_VERSION },
  })
}

async function hasActiveConsent(userId: string, purposeId: string): Promise<boolean> {
  const latest = await db.consentRecords.findFirst({
    where: { userId, purpose: purposeId },
    orderBy: { timestamp: 'desc' },
  })
  return latest?.granted === true
}

Right to Erasure (Soft Delete + Anonymization)

const GRACE_PERIOD_DAYS = 30

async function requestAccountDeletion(userId: string): Promise<void> {
  await db.users.update({ where: { id: userId }, data: { status: 'deletion_pending', deactivatedAt: new Date() } })
  await db.deletionRequests.create({
    data: { userId, requestedAt: new Date(), gracePeriodEndsAt: new Date(Date.now() + GRACE_PERIOD_DAYS * 86400000), status: 'pending' },
  })
}

// Scheduled job: purge after grace period
async function purgeExpiredAccounts(): Promise<void> {
  const expired = await db.deletionRequests.findMany({
    where: { status: 'pending', gracePeriodEndsAt: { lte: new Date() } },
  })
  for (const req of expired) {
    await db.$transaction(async (tx) => {
      await tx.users.update({
        where: { id: req.userId },
        data: { email: `deleted-${req.userId}@anon.local`, fullName: 'Deleted User', phone: null, address: null, status: 'deleted' },
      })
      // Anonymize consent records (retain for legal proof, not delete)
      await tx.consentRecords.updateMany({
        where: { userId: req.userId },
        data: { userId: `deleted-${req.userId}`, ipAddress: 'REDACTED' }
      })
      await tx.orders.updateMany({ where: { userId: req.userId }, data: { userEmail: null, userName: 'Deleted User' } })
      await tx.deletionRequests.update({ where: { id: req.id }, data: { status: 'completed', completedAt: new Date() } })
    })
  }
}

Cookie Consent Flow

const COOKIE_CATEGORIES = {
  necessary: { name: 'Strictly Necessary', required: true },
  functional: { name: 'Functional', required: false },
  analytics: { name: 'Analytics', required: false },
  marketing: { name: 'Marketing', required: false },
} as const

type CookiePrefs = Record<keyof typeof COOKIE_CATEGORIES, boolean>

// BAD: set tracking cookies before consent
// document.cookie = '_ga=GA1.2.123; max-age=63072000'

// GOOD: only after explicit consent per category
function applyCookiePreferences(prefs: CookiePrefs): void {
  initSessionCookies() // always allowed
  prefs.analytics ? initGoogleAnalytics() : removeAnalyticsCookies()
  prefs.marketing ? initMarketingPixels() : removeMarketingCookies()
  document.cookie = `cookie_consent=${JSON.stringify(prefs)}; path=/; max-age=${365 * 86400}; SameSite=Lax; Secure`
}

Data Breach Notification (72-Hour Rule)

const NOTIFICATION_DEADLINE_HOURS = 72

async function reportBreach(breach: { detectedAt: Date; severity: string; affectedCount: number; dataTypes: string[]; description: string }): Promise<void> {
  const record = await db.dataBreaches.create({ data: { ...breach, notifiedAuth
Read more
Ships withvibecosystem

Your AI software team. Built on Claude Code. vibecosystem turns Claude Code into a full AI software team — 138 specialized agents that plan, build, review, test, and learn from every mistake. No configuration needed — just install and code.

Get the whole plugin

Other skills on vibecosystem.