Apply GDPR-compliant engineering practices across code, APIs, data models, authentication, logging, retention, deletion jobs, cloud infrastructure, and pull requests. Use this skill when handling personal data, user accounts, cookies, analytics, emails, audit logs, encryption, pseudonymization, anonymization, data exports, breach response, CI/CD pipelines with real data, or questions asking whether a design is GDPR-compliant.
Use this skill to translate GDPR principles into concrete engineering decisions for data collection, APIs, logs, retention, security, cloud infrastructure, and pull request review, then return a compliance verdict with required fixes.
When to invoke
"Is this API GDPR-compliant?"
"Review this data model for privacy and retention issues."
"Design user data export, deletion, consent, or audit logging."
"Check whether our logging, analytics, cookies, or emails expose personal data."
"Assess GDPR compliance for a pull request, CI/CD pipeline, or cloud design."
Core GDPR principles
Golden rule: collect less, store less, expose less, retain less. Inspired by CNIL developer guidance and GDPR Articles 5, 25, 32, 33, and 35.
Principle
Engineering obligation
Lawfulness, fairness, transparency
Document legal basis for every processing activity in the RoPA.
Purpose limitation
Data collected for purpose A must not be reused for purpose B without a new legal basis.
Data minimization
Collect only fields with a documented business need today.
Accuracy
Provide update endpoints and propagate corrections to downstream stores.
Storage limitation
Define TTL at schema design time, never after.
Integrity & confidentiality
Encrypt at rest and in transit; restrict and audit access.
Accountability
Maintain evidence of compliance; keep the RoPA ready for DPA inspection at any time.
Privacy by design and data minimization
Area
Must do
Must not do
New processing
Update the RoPA, document legal basis, and sign a DPA with every sub-processor before data flows.
Ship a new data collection feature without a legal basis or store personal data in a system not listed in the RoPA.
High-risk processing
Conduct a DPIA before biometrics, health data, large-scale profiling, or systematic monitoring.
Treat high-risk processing as a normal feature toggle.
Defaults
Default optional data collection to off; users opt in.
Enable analytics, tracking, or telemetry by default without explicit consent.
Models and DTOs
Map every DTO/model field to a business need; use separate DTOs for create, read, and update.
Reuse the same object everywhere or keep undocumented fields.
Responses
Return only what the caller is authorized to see; use projections.
Include DOB, national ID, health, or other sensitive fields in default list/search projections.
Identifiers
Use UUIDs or opaque public identifiers.
Use sequential integer IDs in public URLs.
URLs
Keep personal data out of path segments and query parameters because CDN logs and browser history retain them.
Put PII in GET query params, URL paths, or referrers.
Mask sensitive values at the edge, for example return ****1234 for card numbers and never the full value.
Storage limitation, retention, and erasure
Every table holding personal data must have a defined retention period, CreatedAt, and RetentionExpiresAt. Enforce retention automatically with a scheduled job such as Hangfire or cron; never rely on a manual process. Use soft-delete with DeletedAt only as a temporary erasure window, then hard-delete or anonymize after the erasure request window, commonly 30 days.
Data type
Max retention
Auth / audit logs
12–24 months
Session / refresh tokens
30–90 days
Email / notification logs
6 months
Inactive user accounts
12 months after last login → notify → delete
Payment records
As required by tax law, commonly 7–10 years, minimized
Analytics events
13 months
Do not retain personal data indefinitely "in case it becomes useful later." When erasing a user, anonymize records that must be retained for financial or audit reasons rather than deleting them.
API, logging, and error handling rules
Topic
Required rule
Authentication
Authenticate every endpoint that returns or accepts personal data.
Actor identity
Extract the acting user from the JWT, never from the request body.
Ownership
Validate ownership on every resource: if (resource.OwnerId != currentUserId) return 403.
Sensitive endpoints
Rate-limit login, data export, and password reset.
Browser policy
Set Referrer-Policy: no-referrer and an explicit CORS allowlist.
CORS
Never use Access-Control-Allow-Origin: * on authenticated APIs.
API errors
Use Problem Details (RFC 7807); return generic errors and a correlation ID.
Server logs
Log full error detail server-side with correlation ID.
Never return stack traces, internal paths, database errors, file paths, class names, line numbers, or personal data in API error responses. Replace errors such as Column 'email' violates unique constraint on table 'users' with A user with this email address already exists.
Logging requirements:
Anonymize IPs in application logs: mask the last octet for IPv4, for example 192.168.1.xxx, and the last 80 bits for IPv6.
Never log passwords, tokens, session IDs, credentials, card numbers, national IDs, health data, full request bodies, or full response bodies where PII may be present.
Log events, not data: prefer "User {UserId} updated email" over old and new email addresses.
Use structured logging with userId as an internal identifier, not an email address.
Separate audit logs for sensitive access and admin actions from application logs because retention and ACLs differ.
Security, encryption, and secrets
Scope
Minimum standard
Standard personal data
AES-256 disk/volume encryption.
Sensitive data: health, financial, biometric
AES-256 column-level encryption plus envelope encryption through KMS.
In transit
TLS 1.2+; prefer TLS 1.3 and enforce HSTS.
Keys
HSM-backed KMS; rotate DEKs annually.
Passwords
Argon2id preferred, or bcrypt with cost ≥ 12; use a unique salt per password and store only the hash.
Secrets
Store in Azure Key Vault, AWS Secrets Manager, GCP Secret Manager, HashiCorp Vault, or another KMS.
Secret scanning
Use pre-commit hooks such as gitleaks or detect-secrets.
.gitignore must include .env, .env.*, *.pem, *.key, *.pfx, *.p12, and secrets/. Rotate secrets on developer offboarding, annual schedule, or suspected compromise. Do not allow TLS 1.0/1.1, null cipher suites, hardcoded encryption keys, committed secrets, plaintext environment variable defaults, plaintext reset tokens, passwords in URLs, or passwords in logs.
Anonymization is irreversible and falls outside GDPR scope. Pseudonymization is reversible with a key and remains personal data. Store the pseudonymization key in KMS, never in the same database as the pseudonymized data. Do not call data "anonymized" if linkage attacks can re-identify it.
Testing, infrastructure, and PR review
Use synthetic data in dev, staging, and CI. Do not use production personal data or restore production DB backups to non-production without scrubbing PII first. Use generators such as Bogus for .NET and Faker for JS, Python, or Ruby. Use @example.com for all test email addresses.
PR review checklist:
Area
Checks
Data model
New PII column has purpose and retention; sensitive fields use column-level encryption; public identifiers are not sequential integer PKs.
API
No PII in URL paths or query parameters; all personal data endpoints are authenticated; ownership checks prevent cross-user access; sensitive endpoints are rate-limited.
Logging
No passwords, tokens, credentials, full request/response bodies, or raw IPs; IPs are anonymized.
Infrastructure
No public storage buckets or public-IP databases; cloud resources tagged with DataClassification; encryption at rest enabled; new regions are EEA-compliant or covered by SCCs.
Secrets and CI/CD
No secrets in source or config; new secrets are in KMS and inventory; CI/CD secrets are masked in pipeline logs.
Retention and erasure
Retention enforcement job or policy covers new stores and fields; erasure pipeline includes the new data store.
User rights and governance
Data export includes new personal data fields; RoPA updated; DPA signed for sub-processors; DPIA triggered for high-risk processing.
Common anti-patterns and corrections:
Anti-pattern
Correct approach
PII in URLs
Opaque UUIDs as public identifiers.
Logging full request bodies
Log structured event metadata only.
"Keep forever" schema
TTL defined at design time.
Production data in dev/test
Synthetic data plus scrubbing pipeline.
Shared credentials across teams
Individual accounts plus RBAC.
Hardcoded secrets
KMS plus secret manager.
Access-Control-Allow-Origin: * on auth APIs
Explicit CORS allowlist.
Storing consent with profile data
Dedicated consent store.
PII in GET query params
POST body or authenticated session.
Sequential integer IDs in public URLs
UUIDs.
"Anonymized" data with quasi-identifiers
Apply k-anonymity and test linkage resistance.
Mixing backup regions outside EEA
Explicit region lockdown on backup jobs.
Progressive disclosure and bundled resources
Read bundled references only when the task needs depth beyond this summary:
references/data-rights.md: user rights endpoints, DSR workflow, and RoPA.
references/Security.md: encryption, hashing, secrets, anonymization, and pseudonymization.
references/operations.md: referenced by the original skill for cloud, CI/CD, incident response, and architecture patterns, but not currently bundled in this package.
GDPR vocabulary and examples
Use the original engineering vocabulary when reviewing privacy work: DevOps, MUST, SHOULD, JSON, ENISA, OWASP, NIST, references/, references/security.md, retention/deletion, default-on, plain-text, public-facing, re-identification, dateOfBirth, and JS/Python/Ruby. The canonical examples are GET /users/{userId}, "Column 'email' violates unique constraint on table 'users'", "A user with this email address already exists.", and "Email changed from a@b.com to c@d.com".
Every personal data field has a documented purpose, legal basis, and retention period.
Data minimization, purpose limitation, storage limitation, and accountability are explicitly checked.
No personal data appears in URL paths, query parameters, raw logs, stack traces, or default projections.
Authenticated endpoints derive identity from JWT and enforce ownership checks.
Encryption, password hashing, KMS-backed secret storage, and secret scanning are covered where relevant.
Retention, erasure, export, rectification, RoPA, DPA, and DPIA impacts are reported.
Non-production environments use synthetic or scrubbed data only.
The result states whether the design is compliant, needs changes, or is blocked by missing evidence.
1---2name: gdpr-compliant3description: Apply GDPR-compliant engineering practices across code, APIs, data models, authentication, logging, retention, deletion jobs, cloud infrastructure, and pull requests. Use this skill when handling personal data, user accounts, cookies, analytics, emails, audit logs, encryption, pseudonymization, anonymization, data exports, breach response, CI/CD pipelines with real data, or questions asking whether a design is GDPR-compliant.4---56<!-- Generated from harness/github-copilot/skills/gdpr-compliant/SKILL.md by harness/claude-code/scripts/convert_from_copilot.py. Edit the source, not this file. -->78# GDPR-compliant engineering910Use this skill to translate GDPR principles into concrete engineering decisions for data collection, APIs, logs, retention, security, cloud infrastructure, and pull request review, then return a compliance verdict with required fixes.1112## When to invoke1314- "Is this API GDPR-compliant?"15- "Review this data model for privacy and retention issues."16- "Design user data export, deletion, consent, or audit logging."17- "Check whether our logging, analytics, cookies, or emails expose personal data."18- "Assess GDPR compliance for a pull request, CI/CD pipeline, or cloud design."1920## Core GDPR principles2122Golden rule: collect less, store less, expose less, retain less. Inspired by CNIL developer guidance and GDPR Articles 5, 25, 32, 33, and 35.2324| Principle | Engineering obligation |25| --- | --- |26| Lawfulness, fairness, transparency | Document legal basis for every processing activity in the RoPA. |27| Purpose limitation | Data collected for purpose A must not be reused for purpose B without a new legal basis. |28| Data minimization | Collect only fields with a documented business need today. |29| Accuracy | Provide update endpoints and propagate corrections to downstream stores. |30| Storage limitation | Define TTL at schema design time, never after. |31| Integrity & confidentiality | Encrypt at rest and in transit; restrict and audit access. |32| Accountability | Maintain evidence of compliance; keep the RoPA ready for DPA inspection at any time. |3334## Privacy by design and data minimization3536| Area | Must do | Must not do |37| --- | --- | --- |38| New processing | Update the RoPA, document legal basis, and sign a DPA with every sub-processor before data flows. | Ship a new data collection feature without a legal basis or store personal data in a system not listed in the RoPA. |39| High-risk processing | Conduct a DPIA before biometrics, health data, large-scale profiling, or systematic monitoring. | Treat high-risk processing as a normal feature toggle. |40| Defaults | Default optional data collection to off; users opt in. | Enable analytics, tracking, or telemetry by default without explicit consent. |41| Models and DTOs | Map every DTO/model field to a business need; use separate DTOs for create, read, and update. | Reuse the same object everywhere or keep undocumented fields. |42| Responses | Return only what the caller is authorized to see; use projections. | Include DOB, national ID, health, or other sensitive fields in default list/search projections. |43| Identifiers | Use UUIDs or opaque public identifiers. | Use sequential integer IDs in public URLs. |44| URLs | Keep personal data out of path segments and query parameters because CDN logs and browser history retain them. | Put PII in GET query params, URL paths, or referrers. |4546Mask sensitive values at the edge, for example return `****1234` for card numbers and never the full value.4748## Storage limitation, retention, and erasure4950Every table holding personal data must have a defined retention period, `CreatedAt`, and `RetentionExpiresAt`. Enforce retention automatically with a scheduled job such as Hangfire or cron; never rely on a manual process. Use soft-delete with `DeletedAt` only as a temporary erasure window, then hard-delete or anonymize after the erasure request window, commonly 30 days.5152| Data type | Max retention |53| --- | --- |54| Auth / audit logs | 12–24 months |55| Session / refresh tokens | 30–90 days |56| Email / notification logs | 6 months |57| Inactive user accounts | 12 months after last login → notify → delete |58| Payment records | As required by tax law, commonly 7–10 years, minimized |59| Analytics events | 13 months |6061Do not retain personal data indefinitely "in case it becomes useful later." When erasing a user, anonymize records that must be retained for financial or audit reasons rather than deleting them.6263## API, logging, and error handling rules6465| Topic | Required rule |66| --- | --- |67| Authentication | Authenticate every endpoint that returns or accepts personal data. |68| Actor identity | Extract the acting user from the JWT, never from the request body. |69| Ownership | Validate ownership on every resource: `if (resource.OwnerId != currentUserId) return 403`. |70| Sensitive endpoints | Rate-limit login, data export, and password reset. |71| Browser policy | Set `Referrer-Policy: no-referrer` and an explicit `CORS` allowlist. |72| CORS | Never use `Access-Control-Allow-Origin: *` on authenticated APIs. |73| API errors | Use Problem Details (RFC 7807); return generic errors and a correlation ID. |74| Server logs | Log full error detail server-side with correlation ID. |7576Never return stack traces, internal paths, database errors, file paths, class names, line numbers, or personal data in API error responses. Replace errors such as `Column 'email' violates unique constraint on table 'users'` with `A user with this email address already exists.`7778Logging requirements:7980- Anonymize IPs in application logs: mask the last octet for IPv4, for example `192.168.1.xxx`, and the last 80 bits for IPv6.81- Never log passwords, tokens, session IDs, credentials, card numbers, national IDs, health data, full request bodies, or full response bodies where PII may be present.82- Log events, not data: prefer `"User {UserId} updated email"` over old and new email addresses.83- Use structured logging with `userId` as an internal identifier, not an email address.84- Separate audit logs for sensitive access and admin actions from application logs because retention and ACLs differ.8586## Security, encryption, and secrets8788| Scope | Minimum standard |89| --- | --- |90| Standard personal data | AES-256 disk/volume encryption. |91| Sensitive data: health, financial, biometric | AES-256 column-level encryption plus envelope encryption through KMS. |92| In transit | TLS 1.2+; prefer TLS 1.3 and enforce HSTS. |93| Keys | HSM-backed KMS; rotate DEKs annually. |94| Passwords | Argon2id preferred, or bcrypt with cost ≥ 12; use a unique salt per password and store only the hash. |95| Secrets | Store in Azure Key Vault, AWS Secrets Manager, GCP Secret Manager, HashiCorp Vault, or another KMS. |96| Secret scanning | Use pre-commit hooks such as `gitleaks` or `detect-secrets`. |9798`.gitignore` must include `.env`, `.env.*`, `*.pem`, `*.key`, `*.pfx`, `*.p12`, and `secrets/`. Rotate secrets on developer offboarding, annual schedule, or suspected compromise. Do not allow TLS 1.0/1.1, null cipher suites, hardcoded encryption keys, committed secrets, plaintext environment variable defaults, plaintext reset tokens, passwords in URLs, or passwords in logs.99100Anonymization is irreversible and falls outside GDPR scope. Pseudonymization is reversible with a key and remains personal data. Store the pseudonymization key in KMS, never in the same database as the pseudonymized data. Do not call data "anonymized" if linkage attacks can re-identify it.101102## Testing, infrastructure, and PR review103104Use synthetic data in dev, staging, and CI. Do not use production personal data or restore production DB backups to non-production without scrubbing PII first. Use generators such as `Bogus` for .NET and `Faker` for JS, Python, or Ruby. Use `@example.com` for all test email addresses.105106PR review checklist:107108| Area | Checks |109| --- | --- |110| Data model | New PII column has purpose and retention; sensitive fields use column-level encryption; public identifiers are not sequential integer PKs. |111| API | No PII in URL paths or query parameters; all personal data endpoints are authenticated; ownership checks prevent cross-user access; sensitive endpoints are rate-limited. |112| Logging | No passwords, tokens, credentials, full request/response bodies, or raw IPs; IPs are anonymized. |113| Infrastructure | No public storage buckets or public-IP databases; cloud resources tagged with `DataClassification`; encryption at rest enabled; new regions are EEA-compliant or covered by SCCs. |114| Secrets and CI/CD | No secrets in source or config; new secrets are in KMS and inventory; CI/CD secrets are masked in pipeline logs. |115| Retention and erasure | Retention enforcement job or policy covers new stores and fields; erasure pipeline includes the new data store. |116| User rights and governance | Data export includes new personal data fields; RoPA updated; DPA signed for sub-processors; DPIA triggered for high-risk processing. |117118Common anti-patterns and corrections:119120| Anti-pattern | Correct approach |121| --- | --- |122| PII in URLs | Opaque UUIDs as public identifiers. |123| Logging full request bodies | Log structured event metadata only. |124| "Keep forever" schema | TTL defined at design time. |125| Production data in dev/test | Synthetic data plus scrubbing pipeline. |126| Shared credentials across teams | Individual accounts plus RBAC. |127| Hardcoded secrets | KMS plus secret manager. |128| `Access-Control-Allow-Origin: *` on auth APIs | Explicit CORS allowlist. |129| Storing consent with profile data | Dedicated consent store. |130| PII in GET query params | POST body or authenticated session. |131| Sequential integer IDs in public URLs | UUIDs. |132| "Anonymized" data with quasi-identifiers | Apply k-anonymity and test linkage resistance. |133| Mixing backup regions outside EEA | Explicit region lockdown on backup jobs. |134135## Progressive disclosure and bundled resources136137Read bundled references only when the task needs depth beyond this summary:138139- `references/data-rights.md`: user rights endpoints, DSR workflow, and RoPA.140- `references/Security.md`: encryption, hashing, secrets, anonymization, and pseudonymization.141- `references/operations.md`: referenced by the original skill for cloud, CI/CD, incident response, and architecture patterns, but not currently bundled in this package.142143144## GDPR vocabulary and examples145146Use the original engineering vocabulary when reviewing privacy work: DevOps, `MUST`, `SHOULD`, `JSON`, ENISA, OWASP, NIST, `references/`, `references/security.md`, `retention/deletion`, `default-on`, `plain-text`, `public-facing`, `re-identification`, `dateOfBirth`, and `JS/Python/Ruby`. The canonical examples are `GET /users/{userId}`, `"Column 'email' violates unique constraint on table 'users'"`, `"A user with this email address already exists."`, and `"Email changed from a@b.com to c@d.com"`.147148## Output template149150```markdown151### GDPR engineering result152153**Status:** compliant | changes required | blocked154**Scope reviewed:** <API/model/logging/infrastructure/PR/files>155**Personal data involved:** <fields/categories or none found>156**Legal basis / purpose evidence:** <documented basis or missing>157158| Area | Finding | Severity | Required change | Evidence |159| --- | --- | --- | --- | --- |160| Data minimization | <finding> | High | <change> | `<file/field/endpoint>` |161| Retention | <finding> | Medium | <change> | `<table/job/policy>` |162| Security | <finding> | High | <change> | `<config/code/log>` |163164**User rights impact**165- Export: <covered/missing>166- Rectification: <covered/missing>167- Erasure: <covered/missing>168- Consent/RoPA/DPIA/DPA: <status>169170**Validation**171- <check performed>: pass | fail | blocked, <evidence>172```173174## Quality gate175176- [ ] Every personal data field has a documented purpose, legal basis, and retention period.177- [ ] Data minimization, purpose limitation, storage limitation, and accountability are explicitly checked.178- [ ] No personal data appears in URL paths, query parameters, raw logs, stack traces, or default projections.179- [ ] Authenticated endpoints derive identity from JWT and enforce ownership checks.180- [ ] Encryption, password hashing, KMS-backed secret storage, and secret scanning are covered where relevant.181- [ ] Retention, erasure, export, rectification, RoPA, DPA, and DPIA impacts are reported.182- [ ] Non-production environments use synthetic or scrubbed data only.183- [ ] The result states whether the design is compliant, needs changes, or is blocked by missing evidence.
Run npx skillmds@latest add paulasilvatech/gdpr-compliant in your terminal (requires Node.js), paste this page's agent-chat prompt into Claude, Cursor, or any MCP-connected agent, or download the SKILL.md file and copy it into your agent's skills directory.
Apply GDPR-compliant engineering practices across code, APIs, data models, authentication, logging, retention, deletion jobs, cloud infrastructure, and pull requests. Use this skill when handling personal data, user accounts, cookies, analytics, emails, audit logs, encryption, pseudonymization, anonymization, data exports, breach response, CI/CD pipelines with real data, or questions asking whether a design is GDPR-compliant. It is listed under DevOps & Infra on SkillMD.
This skill has not completed SkillMD's automated safety review yet. SkillMD never runs a skill's scripts for you; review the SKILL.md before installing.
This skill is tagged as working with Claude Code, Claude.ai, OpenAI Codex. SKILL.md is an open format, so most agents that read a skills directory can load it too.
Yes. Installing skills from SkillMD is free, and the skill stays under its author's original license.
paulasilvatech (@paulasilvatech) published this skill. Their other Agent Skills are listed on their SkillMD profile.