GDPR Privacy Engineering skill for Codex

Know every copy of personal data, and delete it. Codex inventories personal data across databases, logs, analytics and processors into a data map kept in the repo, then builds one DSAR orchestrator that exports and erases across every store, retention jobs that actually run, and privacy by design checks for new features. Legal calls such as lawful basis and DPIA outcomes are flagged for the privacy lead and counsel.

  • Security
  • $gdpr-privacy-engineering
  • 143 lines
  • 2 files
  • ~1,800 tokens
  • MIT
  • Updated

Install

curl -fsSL codexskills.dev/install.sh \  | sh -s -- gdpr-privacy-engineering

Installs to ~/.agents/skills/gdpr-privacy-engineering/ for every project on this machine.

104-line POSIX script. No sudo, no telemetry. Read install.sh

Use it in Codex

Start a prompt with $gdpr-privacy-engineering, or pick it from /skills. You can also just describe the task: Codex reads the description below and loads the playbook when your request matches.

What Codex reads before loading it

Implements GDPR and UK GDPR requirements in code and infrastructure - personal data inventory from schemas and code, records of processing, retention and deletion jobs, data subject access and erasure (DSAR) pipelines, pseudonymisation, consent records, processor mapping and privacy by design reviews of new features. Use when asked to find where personal data lives, build a DSAR export or account deletion flow, enforce retention periods, prepare engineering input for a DPIA, or check a feature for privacy issues before launch.

Use it when

  • You need a map of where personal data lives in the system
  • Access, export or erasure requests are handled manually and slowly
  • Retention periods exist on paper but no job enforces them
  • A new feature collects personal or special category data

Use something else when

How to check the result

A seeded test subject is exported completely and then erased from every store in staging, leaving zero matching rows outside documented exceptions, and retention job counts drop to zero past the limit.

The mistake it prevents

Treating soft deletes, unsalted email hashes or pseudonymised analytics IDs as erasure or anonymisation when they are still personal data.

~/.agents/skills/gdpr-privacy-engineering/SKILL.md

--- name: gdpr-privacy-engineering description: Implements GDPR and UK GDPR requirements in code and infrastructure - personal data inventory from schemas and code, records of processing, retention… license: MIT ---

Done well means: every store of personal data is known, has a purpose and a retention period, and is reached by the export and deletion paths; nothing is collected that the feature does not need. Engineering builds the machinery; the lawful basis, retention periods and DPIA conclusions are decided by the privacy lead or DPO and reviewed by a lawyer. Say that plainly whenever a step depends on a legal judgement.

Inventory before building

  1. Read AGENTS.md, then map data stores: databases, caches, search indexes, object storage, queues, data warehouse, logs, analytics, backups, email/SMS providers, support tools, error trackers.
  2. Find personal data in schemas and code:
rg -n -i "email|phone|first_?name|last_?name|address|birth|dob|ssn|national_id|passport|ip_?address|lat(itude)?|lon(gitude)?|device_id|advertising_id" \
   --glob '*.{sql,prisma,py,ts,rb,go,java,kt,cs}' migrations/ schema/ src/ app/
rg -n -i "logger\.|console\.log|log\.(info|debug)" src | rg -i "email|user|token|address"
rg -n "posthog|segment|mixpanel|amplitude|ga4|gtag|sentry|datadog|intercom|hubspot" src package.json
  1. Classify each field: identifier, contact, special category (health, biometric, religion, union membership, sexual orientation, ethnicity: Art. 9, needs a separate condition), financial, location, behavioural, children’s data.
  2. Record it in a machine-readable data map kept in the repo.
# privacy/data-map.yaml (one entry per store and field group)
- store: postgres.users
  fields: [email, display_name, last_login_ip]
  category: contact, identifier
  purpose: account management, security
  lawful_basis: contract (Art. 6(1)(b)); security logging legitimate interest  # set by DPO
  retention: account lifetime + 30 days
  deletion: hard delete via AccountErasureJob
  processors: [AWS eu-west-1]
  transfers: none outside EEA

This feeds the Article 30 record of processing; the privacy lead owns the final record.

Rights requests (DSARs)

Deadline: one month from receipt, extendable by two further months for complex or numerous requests, with the extension explained to the person within the first month.

RightEngineering deliverable
Access (Art. 15)Export of all personal data across stores, plus purposes and recipients
Rectification (Art. 16)Self-service edits, propagated to downstream copies
Erasure (Art. 17)Deletion across stores and processors, with documented exceptions (legal hold, tax records)
Portability (Art. 20)Data the person provided, in JSON or CSV
Objection / restriction (Art. 18, 21)Flags that stop marketing or processing without deleting

Build one orchestrator that fans out to every store in the data map, so new stores are added in one place:

# Each store registers an exporter and an eraser; the orchestrator logs every outcome.
class StoreHandler(Protocol):
    name: str
    def export(self, subject_id: str) -> dict: ...
    def erase(self, subject_id: str) -> int: ...   # rows/objects affected

def erase_subject(subject_id: str, handlers: list[StoreHandler], request_id: str) -> dict:
    results = {}
    for h in handlers:
        try:
            results[h.name] = {"status": "ok", "affected": h.erase(subject_id)}
        except Exception as exc:          # one failing store must not hide the others
            results[h.name] = {"status": "failed", "error": type(exc).__name__}
    audit_log.info("dsar.erasure", request_id=request_id, results=results)  # no PII in the log
    return results
  • Verify identity before acting; an export sent to an impostor is a breach. Use the existing authenticated session or a verified channel, not just a matching email.
  • Erasure must reach processors: call deletion APIs (support desk, CRM, email provider, analytics user deletion endpoints) and record the confirmation.
  • Running erasure in production is destructive. Run it against staging fixtures first, and require the user’s explicit confirmation before the first production run of a new handler.

Retention

  • Each table or bucket with personal data gets a retention rule enforced by a scheduled job or native TTL (S3 lifecycle rules, DynamoDB TTL, Postgres partition drops, Elasticsearch ILM). A policy document without a job is not retention.
  • Logs: keep IPs and user IDs only as long as security needs them (often 30-180 days, set by the privacy lead); strip query strings and bodies that may carry personal data.
  • Backups: you usually cannot edit them. Document that deleted data persists until backup expiry, keep that window short, and re-apply deletions after any restore (keep a tombstone list of erased subject IDs).
  • Crypto-shredding (per-user data keys, deleting the key to erase) works for event stores and immutable logs where row deletion is impossible.

Privacy by design review for a new feature

  • Purpose stated; every new field justified by it (drop the rest)
  • Lawful basis confirmed by the privacy lead; consent only where it is the actual basis
  • Defaults are the most private option (Art. 25): opt-in for non-essential processing
  • Data added to the data map, export and erasure handlers in the same PR
  • Retention rule and job added
  • New processors or transfers outside the EEA/UK flagged (needs DPA and transfer mechanism)
  • High-risk processing (large-scale special category, systematic monitoring, profiling with significant effects) flagged for a DPIA before build, not after launch
  • Pseudonymise for analytics (keyed hash with a secret salt, stored separately); remember pseudonymised data is still personal data, only anonymised data is out of scope

When consent is the basis, store who consented, to what (versioned text ID), when, how (UI surface), and withdrawals, append-only. Cookie banners must block non-essential tags until consent; check in the browser network panel, not only in the code.

Gotchas

  • Personal data in URLs ends up in access logs, analytics and referrers. Use POST bodies or opaque IDs.
  • Soft-delete (deleted_at) is not erasure. Either hard delete or anonymise in place, and make sure search indexes and caches are purged too.
  • Error trackers capture request bodies and local variables; configure scrubbing (send_default_pii=False in Sentry SDKs, plus before_send filters).
  • Hashing an email without a secret is reversible by dictionary; it is not anonymisation.
  • Test and staging databases restored from production copy all of this risk. Use synthetic or masked data.

Verification

  • Seed a test subject with data in every store, run export and erasure in staging, then query each store for the subject ID and email: zero rows remain except documented exceptions.
  • Retention job dry-run lists the expected rows; after the run, counts older than the limit are zero.
  • rg the codebase for new loggers that include personal fields; grep log samples too.
  • Hand the data map and DSAR test evidence to the privacy lead; final compliance sign-off is theirs and their counsel’s, not the engineering team’s.

What the zip contains

SKILL.md plus the interface file below. Nothing runs on install.

agents/openai.yamlgenerated from this page

Gives the Codex app a display name, a one-line description and a starter prompt for this skill.

interface:
  display_name: "GDPR Privacy Engineering"
  short_description: "Know every copy of personal data, and delete it"
  default_prompt: "$gdpr-privacy-engineering Find every place we store user emails and IP addresses"

About this skill

Written and maintained by the Codex Skills editors to the same editorial standard as every skill here: a selective description, a real workflow, known pitfalls and a way to verify the work. First published , last updated . MIT licensed. Something wrong or out of date? Tell us.

esc
New

Introducing Codex Skills Pro

79 professional skills that take Codex through complete engagements, each with its own scripts, references and a report that verifies the result.

All-AccessOne-time payment, no subscription
$49
Get All-AccessOr browse individual skills from $2.99 →

Secure checkout by Creem