Privacy and GDPR alignment

Help draft ROPA tables, DPA annex bullets, and DPIA structure; map cross-border transfer mechanisms. Stress collaboration boundaries with DPO / legal—do not invent legal bases.

List purpose, categories, retention, recipients, and subprocessors in tables; the SKILL must forbid inventing legal bases—reference adopted internal policy clause IDs or leave <TBD>.

For access, erasure, portability, etc., map outputs to existing APIs or ticketing flows with SLAs and identity checks; minimize personal data in logs by default.

Compliance flow (ROPA →DPA →DPIA)

  [ Inventory: processing activities / systems / data flows ]
        │
        ▼
  ┌─────────────→    Table: purpose, legal basis (placeholder), categories, retention, recipients
  →ROPA draft  │──── Gaps tagged “needs legal/DPO”—do not auto-print “compliant—
  └─────────────┘
        │
        ▼
  ┌─────────────→    Processor: written DPA + annex (subject matter, duration, subprocessor changes)
  →DPA align   │──── Controller: instructions boundary, subcontracting, audit clauses (placeholders)
  └─────────────┘
        │
        ▼
  ┌─────────────→    High-risk processing →DPIA; supervisory consultation if needed (placeholder)
  →DPIA        │──── Necessity, risks, mitigations; version and reviewers on file
  └─────────────┘
        │
        ▼
  ┌─────────────→    Subject requests →ticket/API mapping; cross-border →SCC/BCR/local options
  →Rights / xfer →
  └─────────────┘
        │
        ▼
        —Major uncertainty →escalate DPO / legal (attach evidence and drafts)

Agent output is draft and checklist only; binding legal effect and clause choice remain with DPO, legal, or external counsel.

PII field annotation, encrypted storage, and consent implementation

PII field annotation (data model level)

// Prisma schema — annotate PII fields with comments
model User {
  id        String   @id @default(cuid())
  /// @pii:direct email address, retention 3 years
  email     String   @unique
  /// @pii:direct phone number, encrypted storage
  phone     String?  // AES-256-GCM encrypted before storage
  /// @pii:quasi date of birth, re-identifiable in combination
  birthDate DateTime?
  createdAt DateTime @default(now())
}

// PII encrypted storage (Node.js — AES-256-GCM)
import { createCipheriv, createDecipheriv, randomBytes } from 'crypto';

const KEY = Buffer.from(process.env.PII_ENCRYPTION_KEY!, 'base64'); // 32 bytes

export function encryptPII(plaintext: string): string {
  const iv = randomBytes(12);
  const cipher = createCipheriv('aes-256-gcm', KEY, iv);
  const encrypted = Buffer.concat([cipher.update(plaintext, 'utf8'), cipher.final()]);
  const tag = cipher.getAuthTag();
  return Buffer.concat([iv, tag, encrypted]).toString('base64');
}

export function decryptPII(ciphertext: string): string {
  const buf = Buffer.from(ciphertext, 'base64');
  const iv = buf.subarray(0, 12);
  const tag = buf.subarray(12, 28);
  const encrypted = buf.subarray(28);
  const decipher = createDecipheriv('aes-256-gcm', KEY, iv);
  decipher.setAuthTag(tag);
  return decipher.update(encrypted) + decipher.final('utf8');
}

// Access log: record who accessed which user's PII and when
await prisma.piiAccessLog.create({
  data: {
    accessorId: currentUser.id,
    targetUserId: targetUser.id,
    fields: ['email', 'phone'],
    purpose: 'customer_support_ticket_#12345',
    timestamp: new Date(),
  }
});

User consent record data structure and queries

// Consent record table structure (SQL)
CREATE TABLE consent_records (
  id            UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  user_id       UUID NOT NULL REFERENCES users(id),
  purpose       VARCHAR(100) NOT NULL,  -- 'marketing_email', 'analytics', 'third_party_sharing'
  version       VARCHAR(20) NOT NULL,   -- privacy policy version '2025-01-01'
  granted       BOOLEAN NOT NULL,
  granted_at    TIMESTAMPTZ,
  withdrawn_at  TIMESTAMPTZ,
  ip_address    INET,                   -- record operation source (itself PII, handle accordingly)
  user_agent    TEXT,
  created_at    TIMESTAMPTZ DEFAULT NOW()
);

-- Query current valid consent (latest version, not withdrawn)
SELECT purpose, granted, version, granted_at
FROM consent_records
WHERE user_id = $1
  AND withdrawn_at IS NULL
ORDER BY granted_at DESC;
  • Use pseudonyms or hashes in examples—no real user data.
  • Legal-basis column: only org-adopted references or <TBD>—no fabricated applicability.

DPA (processor agreement) essentials

Standard modules typically cover: subject matter and duration, nature and purpose, personal data and data-subject categories, controller duties, processing only on documented instructions, confidentiality, security measures, subprocessors, assistance with data-subject and supervisory requests, breach assistance, deletion or return, audit and demonstration, and liability. Exact clauses depend on your jurisdiction’s templates.

Controller-side checks

  • Scope matches product features; changes go through change management.
  • Subprocessor list + objection mechanism (if applicable) has placeholder links.
  • Transfer annex (e.g. SCC) version and signature status placeholders.

Processor-side checks

  • Process only on documented instructions; no scope creep.
  • Security implementation and audit cooperation as required (placeholders).
  • Deletion/return timelines and proof at termination.

DPIA triggers and document structure

When systematic large-scale monitoring, automated decision-making/profiling, large-scale sensitive processing, or systematic monitoring of publicly accessible areas applies, assess whether a DPIA is mandatory (per regulator guidance and internal policy). Document processing description, necessity/proportionality, stakeholder consultation placeholders, risks, existing and planned mitigations, residual risk, and whether supervisory consultation is needed.

  • Cross-link ROPA: same activity row links to the DPIA section.
  • Major gaps flagged for DPO review—do not output “DPIA passed—conclusions.

Data Subject Rights API design

// Express.js — Data Subject Rights API endpoints

// 1. Data Access/Export (Right to Access & Portability)
// GET /api/gdpr/data-export
router.get('/data-export', authenticateUser, async (req, res) => {
  const userId = req.user.id;
  const userData = await collectUserData(userId); // aggregate all PII fields
  const exportData = {
    exported_at: new Date().toISOString(),
    format_version: '1.0',
    user_id: userId,
    personal_data: {
      profile: userData.profile,
      orders: userData.orders,
      consents: userData.consents,
    }
  };
  await auditLog('DATA_EXPORT', userId, req.ip);
  res.json(exportData);
  // SLA: respond within 30 days (GDPR requirement)
});

// 2. Data Erasure (Right to Erasure)
// DELETE /api/gdpr/erasure
router.delete('/erasure', authenticateUser, async (req, res) => {
  const userId = req.user.id;
  // Check for legal hold obligations (e.g. tax records 7 years)
  const legalHold = await checkLegalHold(userId);
  if (legalHold.hasHold) {
    return res.status(409).json({
      error: 'LEGAL_HOLD',
      reason: legalHold.reason,
      retain_until: legalHold.until,
    });
  }
  // Soft delete + redact (not immediate physical deletion)
  await prisma.user.update({
    where: { id: userId },
    data: {
      email: `deleted-${userId}@erased.invalid`,
      phone: null,
      deletedAt: new Date(),
      erasureRequestedAt: new Date(),
    }
  });
  await auditLog('ERASURE_COMPLETED', userId, req.ip);
  res.json({ status: 'erasure_scheduled', completed_within: '30_days' });
});

// 3. Data Rectification (Right to Rectification)
// PATCH /api/gdpr/rectification
router.patch('/rectification', authenticateUser, validateBody, async (req, res) => {
  const { field, new_value, reason } = req.body;
  const ALLOWED_FIELDS = ['phone', 'address', 'name'];
  if (!ALLOWED_FIELDS.includes(field)) {
    return res.status(400).json({ error: 'FIELD_NOT_RECTIFIABLE' });
  }
  await prisma.user.update({
    where: { id: req.user.id },
    data: { [field]: field === 'phone' ? encryptPII(new_value) : new_value }
  });
  await auditLog('RECTIFICATION', req.user.id, req.ip, { field, reason });
  res.json({ status: 'updated' });
});

Cross-border transfers and localization placeholders

List destinations, mechanisms (SCCs, BCRs, adequacy, local deployment, other lawful paths), effective status, and owner placeholders. For multiple regions, use separate columns—do not conflate frameworks.

  • Subprocessor chain: one row per hop with recipient and legal basis each.
  • Do not fabricate signed SCC IDs or regulator approvals.

Multi-jurisdiction terminology

When several frameworks apply, separate terms: e.g. “consent—under one statute vs GDPR consent; “legitimate interests—vs other lawful bases—cite the correct framework per document and note applicable jurisdiction.

  • Do not mix concepts from different laws in one paragraph without explanation.
  • Public privacy notices vs internal ROPA may link to a terminology crosswalk (placeholder).

DPA / DPIA checklist lab

Check common items to generate pasteable Markdown for tickets or Confluence; unchecked items stay [ ] for on-site completion.

Typical DPA annex items
DPIA document structure

For internal review only; clause choice, execution, and filings need legal / DPO sign-off. Use <TBD> for placeholders.

---
name: gdpr-privacy
description: Implement GDPR-aligned privacy controls: PII annotation, encryption, consent records, and data subject rights APIs
---
# Steps
1. Annotate PII fields in data models: @pii:direct / @pii:indirect / @pii:quasi
2. Encrypt PII at rest: AES-256-GCM, key stored in Secrets Manager (not in code)
3. PII access logging: record accessor, target user, fields accessed, purpose, timestamp
4. Consent records: SQL table with purpose/version/granted/withdrawn_at; query current valid consent
5. Data Subject Rights: implement GET /data-export, DELETE /erasure, PATCH /rectification
6. Legal hold check: before erasure, verify whether retention obligations apply
7. ROPA: table with purpose, legal basis (placeholder), categories, retention, recipients
8. DPA: align with processor agreement; note subprocessor list and audit clause placeholders
9. DPIA: trigger for high-risk processing; document necessity, risks, and mitigations
10. Cross-border transfers: list destinations, mechanisms (SCC/BCR/adequacy), and status
11. Minimize PII in logs: redact or hash PII fields by default
12. Escalate uncertainties: flag legal basis gaps as needing DPO/legal review

# Anti-patterns
- Do NOT fabricate legal bases or regulator approval IDs
- Do NOT output "DPIA passed" conclusions without evidence
- Do NOT store PII in application logs in plaintext

Back to skills More skills