/compliance-check — GDPR + ePrivacy Compliance

SkillDev tools

GDPR + ePrivacy audit — consent, privacy policy, data handling, right-to-deletion, DPAs. Deep-dive for /launch-check compliance.

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the /compliance-check — GDPR + ePrivacy Compliance skill

What this skill tells your AI

The instructions your AI receives, as published by me2resh/apexyard in .claude/skills/compliance-check/SKILL.md and read by ahel’s review.

Deep-dive regulatory compliance analysis. Checks cookie consent, privacy policy, terms of service, data handling, and user rights. Invoke when /launch-check's compliance row shows WARN or FAIL, or proactively before launching in the EU/UK.

Consumes the DFD produced by /dfd for data-handling analysis (Step 4). The DFD's classifications table at projects/<project>/architecture/dfd.md is the source of truth for which fields are PII / PCI / secrets, and the DFD's external-services list is the source of truth for cross-border transfers and third-party processors. If the DFD doesn't exist, this skill falls back to its own grep-based discovery (degraded mode — surface in the output banner). See AgDR-0026 for the single-source-of-truth rationale.

Compliance Areas

AreaRegulationKey requirement
Cookie consentePrivacy DirectiveInformed consent before setting non-essential cookies
Privacy policyGDPR Art. 13-14Clear disclosure of what data is collected, why, and how long
Right to deletionGDPR Art. 17Users can request their data be deleted
Data minimizationGDPR Art. 5Collect only what's necessary
Data retentionGDPR Art. 5Don't keep data longer than needed
Terms of serviceContract lawClear terms governing use of the service
Third-party data sharingGDPR Art. 28Data processing agreements with third parties

Process

Step 1: Cookie and tracking audit

  • Grep for cookie-setting code (document.cookie, setCookie, cookie-parser, js-cookie)
  • Grep for analytics SDKs (Google Analytics, Mixpanel, Amplitude, PostHog, Segment, Facebook Pixel)
  • Grep for cookie consent libraries (cookieconsent, react-cookie-consent, cookie-banner, consent-manager)
  • Check if consent is obtained BEFORE analytics/tracking scripts load (not after)
  • Check for a cookie policy page listing all cookies and their purposes

Step 2: Privacy and legal pages

  • Check for /privacy or /privacy-policy route
  • Check for /terms or /terms-of-service route
  • Check if privacy policy covers: what data is collected, legal basis, retention period, third parties, user rights, contact info
  • Check for a link to the privacy policy in the sign-up flow and footer

Step 3: User rights implementation

  • Check for a "delete account" or "delete my data" feature
  • Check for a "download my data" / data portability feature
  • Check for opt-out mechanisms for marketing communications
  • Check if the auth system supports account deactivation

Step 4: Data handling (DFD-driven)

Prefer the DFD when present. Read the classifications table at projects/<project>/architecture/dfd.md § "Data classifications" — that's the canonical view of PII / PCI / secrets across the system, produced by /dfd's three-pathway heuristic walk (annotations + env-var heuristics + schema columns) plus any explicit registry the project ships.

source "$(git rev-parse --show-toplevel)/.claude/hooks/_lib-read-config.sh"
source "$(git rev-parse --show-toplevel)/.claude/hooks/_lib-portfolio-paths.sh"
projects_dir=$(portfolio_projects_dir)

dfd="${projects_dir}/${project_name}/architecture/dfd.md"
if [ -f "$dfd" ]; then
  # DFD present — use it as source of truth
  : # parse the Classifications table + External actors block
else
  # Degraded mode — surface in output banner, fall back to grep walk
  : # legacy independent scan
fi

From the DFD's classifications + flows, derive:

  • What PII is stored — every row labelled pii in the classifications table
  • What PCI data crosses the system — every row labelled pci (any presence triggers stricter retention + encryption rules)
  • Where secrets live — every row labelled secrets (env vars + schema columns) — confirm they're loaded from a secrets manager, not committed
  • Cross-border transfers — every External Service actor + its inferred region (Stripe-US, SendGrid-US, Auth0-US, Cognito-region-dependent, etc.) — flag if any PII flow lands on a non-EU vendor without a Standard Contractual Clause
  • Third-party processors — every External Service is a candidate Data Processing Agreement (DPA) requirement

Then complement with the inline checks (still needed regardless of DFD source):

  • Check if PII is encrypted at rest (DB encryption flag / column-level encryption)
  • Check if sensitive data is logged (grep for logging calls that might include user data — the DFD lists the fields; this step verifies they're not in logs)
  • Check for data retention policies (is old data cleaned up? — usually only in cron specs or DB triggers)

Step 5: Output findings

COMPLIANCE CHECK — <project> @ <sha>

| # | Area | Status | Finding | Action |
|----|------|--------|---------|--------|
| C1 | Cookies | FAIL | Analytics loads before consent | Gate GA4 behind consent callback |
| C2 | Privacy | WARN | Policy exists but doesn't list retention periods | Add retention section |
| C3 | Deletion | FAIL | No delete-account endpoint | Add DELETE /api/user/me endpoint |
| C4 | Data minimization | PASS | Only email + name collected at signup | — |

Summary: <N> findings (<N> fail, <N> warn, <N> pass)
GDPR readiness: <READY / PARTIAL / NOT READY>

Persist the run + render trend

After printing the findings table (Step 5), persist a structured artefact via the shared audit-history lib so the compliance trend across runs becomes legible. See docs/agdr/AgDR-0019-audit-artefact-persistence.md for the schema rationale.

Resolve project name + score + verdict

<project-name> is the project's registered name in apexyard.projects.yaml. If unregistered, use the basename of the project path and tell the operator to /handover it.

Compute the headline score: score = max(0, 100 - 25*critical - 10*high - 3*medium - 1*low). Compute the verdict by worst-severity: critical/highfail, mediumconditional, low/none → pass. The legacy "GDPR readiness" three-state vocabulary maps cleanly: NOT READY → fail, PARTIAL → conditional, READY → pass.

Persist + render

source "$(git rev-parse --show-toplevel)/.claude/hooks/_lib-audit-history.sh"

# Lowercase severity in the payload — the lib expects critical/high/medium/low/info.
payload=$(mktemp); cat > "$payload" <<'EOF'
{
  "schema_version": 1,
  "findings": [
    {"id": "C1", "severity": "high",   "status": "open", "summary": "No cookie consent UI; analytics fires before opt-in"},
    {"id": "C3", "severity": "medium", "status": "open", "summary": "Missing DPA with analytics vendor"},
    {"id": "C4", "severity": "high",   "status": "open", "summary": "No self-serve right-to-deletion endpoint"}
  ]
}
EOF

# Body: per templates/audits/compliance-check.md
body=$(mktemp); cat > "$body" <<'EOF'
... (filled-in body — findings table + Regulatory exposure + Recommended priority) ...
EOF

ts=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
audit_run_persist "<project-name>" "compliance-check" "$ts" "fail" 55 "$body" < "$payload"
rm -f "$payload" "$body"

audit_render_trend "<project-name>" "compliance-check" 5

Opt-in commit (history-tracked marker)

touch projects/<name>/audits/compliance-check/.audit-history-tracked

The MD artefacts are committed regardless; the marker controls whether the per-run JSON files are.

Rules

  1. Not legal advice. This audit identifies technical gaps. The user should consult a lawyer for legal compliance.
  2. Region-aware. If the project doesn't target EU/UK users, some GDPR requirements may not apply. Ask the user about target markets if unclear.
  3. Auto-PASS for non-user-facing projects. Internal tools, CLIs, and libraries without user data collection don't need this.
  4. Check third-party SDKs. Analytics, error tracking, and ad SDKs often set cookies and process data — they need consent too.
  5. Always persist via the lib. The persist step runs regardless of opt-in commit state. The marker only controls whether the JSON is committed.
  6. Severity vocabulary in the JSON is lowercase. The lib's stats.by_severity derivation expects critical/high/medium/low/info. The human-readable findings table can use whatever capitalisation reads best.

Part of ApexYard — multi-project SDLC framework for Claude Code · MIT.

Signals

GitHub stars
498
Forks
271
Last commit
Sep 2026
Advanced
Catalog kind
skill
Gateway key
compliance-check-me2resh
Source
github.com/me2resh/apexyard