Testland
Browse all skills & agents

gdpr-test-patterns

Reference catalog of GDPR-aligned test patterns - data-subject-rights workflows (Art. 15 access, Art. 16 rectification, Art. 17 erasure / "right to be forgotten", Art. 18 restriction, Art. 20 portability, Art. 21 objection); consent recording + revocation per Art. 7; data-residency assertions per Art. 44 - 50 international transfers; breach-notification timing tests per Art. 33 (72 hours); data-minimization assertions in fixtures per Art. 5(1)(c). The California analogue - CCPA/CPRA patterns by Cal. Civ. Code section, including Global Privacy Control (GPC) opt-out, right-to-know, deletion, right-to-correct, and sensitive-PI limits - lives in references/ccpa.md. Use when authoring GDPR- or CCPA/CPRA-readiness tests for any product processing EU or California personal data.

Install with skills.sh (any agent)

npx skills add testland/qa --skill gdpr-test-patterns
View source

gdpr-test-patterns

Overview

Per gdpr.eu (opens in new window) (community-maintained reference; canonical text at eur-lex.europa.eu Regulation 2016/679):

GDPR (General Data Protection Regulation, in force 2018-05-25) applies to any processing of EU personal data regardless of the processor's location. Failure to demonstrate compliance carries fines up to €20M or 4% of global annual turnover (whichever higher).

This is a reference skill - defines the test-pattern catalog by Article. Tests use the team's existing test framework; this skill is the per-Article test recipe.

For products also processing California consumer data, the CCPA/CPRA catalog by Cal. Civ. Code section - GPC opt-out (§1798.135), right-to-know, deletion, right-to-correct, sensitive-PI limits - is in references/ccpa.md.

When to use

  • Product processes EU personal data (regardless of processor location).
  • Regulatory audit requires evidence of test coverage for data-subject rights.
  • New feature touches PII handling (signup, profile, billing, analytics, third-party sharing).
  • DPIA (Data Protection Impact Assessment) requires test evidence.

How to use

  1. Inventory every system that stores PII for a data subject (app DB, billing, analytics, CRM, support, backups) - this list drives the multi-system assertions.
  2. Pick the Articles in scope for the feature under test (consent, access, erasure, portability, breach, residency, minimization).
  3. Copy the matching per-Article pattern below and point it at your framework's client + models.
  4. Generate fixture data with synthetic-pii-generator - never real customer PII.
  5. Assert across ALL systems from step 1, not just the main store; add the deadline assertions (SAR 1 month per Art. 12(3), breach 72 hours per Art. 33) where the Article sets one.
  6. Pin every timeline assertion to your written policy doc, not a hardcoded 30-day guess.
  7. Wire the tests into CI so a schema change that reintroduces PII or skips a system fails the build.

Test patterns by GDPR Article

Art. 7 - Conditions for consent

def test_consent_recorded_at_collection_time():
    response = client.post('/signup', json={
        'email': 'alice@example.com',
        'consent_marketing': True,
        'consent_timestamp': '2026-05-06T12:00:00Z',
    })
    user = User.objects.get(email='alice@example.com')
    consent = ConsentRecord.objects.get(user=user, scope='marketing')
    assert consent.granted is True
    assert consent.granted_at is not None
    assert consent.granted_via == 'signup-form'   # auditable evidence

def test_consent_revocable():
    revoke_consent(user, scope='marketing')
    consent = ConsentRecord.objects.get(user=user, scope='marketing')
    assert consent.granted is False
    assert consent.revoked_at is not None
    # Subsequent marketing emails must not be sent:
    assert not user.is_eligible_for(EmailType.MARKETING)

Art. 15 - Right of access

def test_subject_access_request_returns_all_personal_data():
    response = authenticated_client.post('/sar', json={'subject_email': 'alice@example.com'})
    assert response.status_code == 200
    data = response.json()
    # Must include data from EVERY system that holds PII for this subject:
    assert 'profile' in data
    assert 'billing' in data
    assert 'support_tickets' in data
    assert 'analytics' in data       # often forgotten; tests catch it
    assert 'third_party_sharing' in data
    # Response must arrive within 1 month per Art. 12(3):
    assert response.headers['X-Processing-Time'] < timedelta(days=30)

Art. 17 - Right to erasure ("right to be forgotten")

def test_erasure_removes_all_personal_data():
    erase_subject('alice@example.com')

    # Across ALL systems:
    assert User.objects.filter(email='alice@example.com').count() == 0
    assert BillingRecord.objects.filter(user_email='alice@example.com').count() == 0
    assert AnalyticsEvent.objects.filter(user_email='alice@example.com').count() == 0
    # Backup retention: erasure marker recorded; backup expires within retention window
    assert ErasureMarker.objects.filter(subject='alice@example.com').exists()

Art. 20 - Right to data portability

def test_data_portability_export_machine_readable():
    response = client.post('/data-export', json={'subject': 'alice@example.com'})
    export = response.json()
    # Must be in "structured, commonly used and machine-readable format"
    assert response.headers['Content-Type'] in ['application/json', 'text/csv', 'application/xml']
    # Format must be self-describing (keys not random IDs):
    assert 'profile' in export
    assert 'orders' in export

Art. 33 - Breach notification (72-hour test)

def test_breach_notification_workflow_within_72h():
    # Simulate a breach detection event
    breach = BreachIncident.create(detected_at=timezone.now())
    # Workflow MUST notify supervisory authority within 72 hours:
    deadline = breach.detected_at + timedelta(hours=72)
    notification = BreachNotification.objects.filter(incident=breach).first()
    assert notification is not None
    assert notification.sent_at <= deadline
    assert notification.recipient == 'supervisory.authority@dpa.example.eu'

Art. 44 - 50 - International transfers (data residency)

def test_eu_user_data_stored_in_eu_region():
    user = User.objects.create(email='alice@example.fr', region='EU')
    # Storage assertions vary by infra (AWS region, GCP region, etc.):
    assert user.storage_region in ['eu-west-1', 'eu-central-1', 'eu-north-1']
    # Cross-region replication MUST stay in EU:
    backups = Backup.objects.filter(user=user)
    for b in backups:
        assert b.region in EU_REGIONS

Art. 5(1)(c) - Data minimization

def test_signup_fixtures_contain_only_required_pii():
    fixture = load_fixture('user_signup.json')
    required = {'email', 'consent_terms', 'consent_marketing'}
    optional = {'phone', 'city', 'date_of_birth'}
    for k in fixture.keys():
        assert k in required | optional, f"Unrecognized field: {k}"
    # No SSN, no passport number, no genetic / biometric data unless explicitly justified:
    forbidden = {'ssn', 'passport', 'genetic_data', 'biometric_data'}
    for k in forbidden:
        assert k not in fixture, f"Forbidden PII type: {k}"

Worked example

A support agent triggers an Art. 17 erasure for alice@example.com. The team already has test_erasure_removes_all_personal_data (above), which asserted the app User table was empty and passed. Running the multi-system version reveals AnalyticsEvent still holds rows keyed by user_email, because analytics writes were never wired into the erasure job. The test fails on AnalyticsEvent.objects.filter(...).count() == 0. The team adds analytics to the erasure fan-out, re-runs, and the test goes green with an ErasureMarker recorded so the nightly backup expiry honors the request within the retention window.

Key compliance gaps tests should catch

GapDetection
Marketing emails sent to revoked-consent usersStep Art. 7 + email-flow tests
SAR returns incomplete dataset (missing analytics/CRM)Step Art. 15 multi-system assertion
Erasure leaves data in unindexed backup tablesStep Art. 17 multi-system assertion
EU user data quietly replicated to US regionStep Art. 44 - 50 region assertion
Breach detected but DPO not notified within 72hStep Art. 33 timing test

Anti-patterns

Anti-patternWhy it failsFix
Test only main-app data store on SAR/erasureMisses analytics, CRM, support, backupsMulti-system assertion (Steps Art. 15 + 17)
Hardcode 30-day SAR window assumptionGDPR allows extension to 3 months in complex casesTest timeline against actual policy doc
Test consent recording without revocationHalf the workflow uncoveredBoth grant + revoke tests (Step Art. 7)
Fixture data uses real customer PIIGDPR violation in tests themselvesUse synthetic-pii-generator
Skip data-minimization assertionsNew PII types creep in via schema changesStep Art. 5(1)(c) field-allowlist test

Limitations

  • This skill is a test-pattern catalog, not legal advice. GDPR interpretation has nuance per supervisory authority (CNIL, ICO, DPA per country).
  • Tests verify implementation; they don't replace a DPIA or legal review.
  • Article numbers refer to GDPR text; consult eur-lex.europa.eu for canonical wording.
  • Subject-access-request workflow varies per organization; test templates above are starting points.

References

  • gdpr (opens in new window) - community reference + Article navigation
  • eur-lex.europa.eu/eli/reg/2016/679/oj - canonical GDPR text
  • edpb.europa.eu - European Data Protection Board guidelines
  • ico.org.uk/for-organisations/uk-gdpr-guidance-and-resources/ - UK ICO guide
  • CCPA/CPRA California analogue (carries the oag.ca.gov + globalprivacycontrol.org citations): references/ccpa.md
  • synthetic-pii-generator - cross-plugin: safe test fixture generation
  • audit-trail-test-author - companion: GDPR audit logs

CCPA / CPRA test patterns

View source (opens in new window)

CCPA / CPRA test patterns

Companion reference for gdpr-test-patterns - the California analogue of the per-Article GDPR catalog, organized by Cal. Civ. Code section.

Overview

Per oag.ca.gov/privacy/ccpa (opens in new window) (California Attorney General authoritative source):

CCPA (California Consumer Privacy Act, in force 2020-01-01) and CPRA (California Privacy Rights Act, in force 2023-01-01) apply to businesses meeting one of three thresholds:

  • $25M+ annual gross revenue
  • Buys, sells, or shares the personal info of 100,000+ California consumers
  • Derives 50%+ revenue from selling/sharing California consumer info

Failure carries civil penalties up to $7,500 per intentional violation + $2,500 per non-intentional violation; private right of action for data breaches.

This reference defines the test-pattern catalog by Cal. Civ. Code section. The host skill gdpr-test-patterns covers the EU side of the international compliance footprint.

When to use

  • Product processes California consumer data + meets a CCPA threshold.
  • Privacy compliance program requires evidence of CCPA test coverage.
  • New feature touches consumer data (signup, profile, billing, analytics, third-party sharing).
  • CPRA-specific features (sensitive PI handling, right to correct) need verification.

Test patterns by Cal. Civ. Code section

§1798.135 - Right to opt out via Global Privacy Control (GPC)

CPRA mandates honoring the GPC browser signal (per globalprivacycontrol.org (opens in new window)):

def test_gpc_signal_blocks_sale_and_share():
    response = client.get('/page', headers={'Sec-GPC': '1'})
    # Page MUST treat the visitor as opted-out:
    assert 'do-not-sell-cookie' in response.cookies
    # Tracking pixels for sale/share must NOT fire:
    assert 'analytics-share.js' not in response.text
    assert 'ads-third-party.js' not in response.text
    # Status MUST be recorded for compliance evidence:
    assert OptOutRecord.objects.filter(visitor_id=session_id).exists()

§1798.110 - Right to know (categories of PI collected)

def test_consumer_request_returns_all_pi_categories():
    response = client.post('/privacy/right-to-know', json={
        'consumer_email': 'alice@example.com'
    })
    body = response.json()
    # CCPA Cat. 11 personal info categories:
    expected = {
        'identifiers',
        'commercial_info',
        'biometric_info',
        'internet_activity',
        'geolocation_data',
        'professional_or_employment',
        'inferences',
    }
    # Test asserts every category present in response (NULL acceptable):
    for cat in expected:
        assert cat in body

§1798.105 - Right to delete

def test_deletion_request_completes_within_45_days():
    request = DeletionRequest.create(consumer_email='alice@example.com')
    # CCPA: 45 days, extendable by 45 more (90 max) with notice
    deadline = request.received_at + timedelta(days=45)
    completion = DeletionRequest.objects.get(id=request.id)
    assert completion.status == 'completed'
    assert completion.completed_at <= deadline

§1798.121 - Right to limit sensitive PI use (CPRA)

def test_limit_sensitive_pi_use():
    # Consumer requests limit on sensitive PI (per CPRA SPI categories)
    submit_limit_request(consumer='alice@example.com')
    # Subsequent processing MUST NOT use SPI for inference / advertising:
    response = client.get('/recommendations', headers={'X-Consumer-Email': 'alice@example.com'})
    # Recommendations engine MUST NOT use SPI (geolocation, racial, religious, etc.):
    used_features = response.json()['feature_attribution']
    forbidden_spi = {'precise_geolocation', 'racial_ethnic', 'religious', 'union_membership'}
    for feature in used_features:
        assert feature not in forbidden_spi

§1798.106 - Right to correct (CPRA)

def test_correction_request_updates_records_within_45_days():
    submit_correction(consumer='alice@example.com', field='name', value='Alice Smith')
    deadline = timezone.now() + timedelta(days=45)
    # All systems must reflect the correction:
    assert User.objects.get(email='alice@example.com').name == 'Alice Smith'
    assert BillingRecord.objects.get(user_email='alice@example.com').name == 'Alice Smith'
    # Third parties that received the prior incorrect value must be notified:
    assert NotificationLog.objects.filter(
        type='correction_propagation',
        recipient='third-party-vendor@example.com',
    ).exists()

§1798.130 - Notice requirements

def test_privacy_policy_disclosed_at_collection():
    # Every PI collection point must disclose categories + purposes
    response = client.get('/signup')
    assert 'privacy-notice' in response.text
    assert any(link in response.text for link in [
        '/do-not-sell-or-share',
        '/limit-sensitive-pi-use',
    ])
    # Disclosed categories MUST match what's actually collected
    disclosed = parse_privacy_notice(response.text)
    actual = analyze_signup_form(response.text)
    assert disclosed >= actual   # disclosure is superset of collection

Sensitive Personal Information categories (CPRA §1798.140(ae))

CategoryExamples
Government IDsSSN, driver's license, passport, alien registration
Account login + credentialsUsername + password / security questions
Precise geolocation<1850 ft / 564 m radius
Racial / ethnic originSelf-reported demographics
Religious / philosophical beliefsReligious affiliation
Union membershipTrade union status
Communication contentEmail body, SMS body, message content
Genetic dataDNA test results
Biometric for unique identificationFaceprint, voiceprint, fingerprint
Health infoMedical history, medications
Sexual orientation / sex lifeSelf-reported orientation

Test patterns above (§1798.121) protect these categories specifically.

Anti-patterns

Anti-patternWhy it failsFix
Honor opt-out cookie but ignore GPC headerCPRA mandates GPC supportStep §1798.135 GPC test
Right-to-know returns only main app dataMisses analytics, CRMMulti-system response (Step §1798.110)
Correction propagated only locallyThird parties retain incorrect dataNotification log assertion (Step §1798.106)
SPI categorical restriction tested only at API edgeInference engines bypassFeature-attribution-level test (Step §1798.121)
Test fixtures use real California PIICCPA violation in testssynthetic-pii-generator

Limitations

  • This skill targets CCPA + CPRA. Other US state privacy laws (Virginia VCDPA, Colorado CPA, Connecticut CTDPA, Utah UCPA, Texas TDPSA, etc.) have similar but not identical patterns.
  • Tests verify implementation; legal review still required for compliance attestation.
  • CPRA enforcement by California Privacy Protection Agency (CPPA); sub-regulations evolve.
  • Some patterns (precise-geolocation 1850-ft threshold) require domain-specific test data.

References

  • ccpa-oag (opens in new window) - California Attorney General CCPA + CPRA reference
  • cppa.ca.gov - California Privacy Protection Agency
  • leginfo.legislature.ca.gov - California Civil Code §1798.100 - .199
  • globalprivacycontrol.org - GPC technical specification
  • iapp.org/resources/article/state-comparison/ - state-law comparison
  • gdpr-test-patterns - host skill: EU analogue
  • synthetic-pii-generator - safe test data generation
  • audit-trail-test-author - audit log requirements

Related skills

audit-trail-test-author

Build-an-X for audit-log tests across compliance frameworks - required-events catalog (auth events / privilege change / data access / admin action / config change / export / impersonation); structured-log-format assertions per OWASP A09:2021; tamper-evident chain (hash-chain + signed-batch patterns) for HIPAA §164.312(b) + PCI Req 10 + SOC 2 CC7.3; immutability + retention per framework; query-replay tests for forensic reconstruction. Use when authoring audit log tests for any compliance framework (HIPAA / PCI / SOC 2 / GDPR / etc.).

compliance-coverage-scoring

Scores existing tests and evidence against a named compliance framework's criteria list (GDPR, CCPA/CPRA, SOC 2 Trust Services Criteria, HIPAA Security Rule, PCI DSS, ISO/IEC 27001), marking every criterion met, partial, not met, or not applicable with a stated evidence requirement per state, and recording each scope exclusion with its criterion reference, reason, named approver, and re-review date. Includes an adversarial readiness-review mode with hard refusal rules (never "ready" with an unjustified gap), and the ISO/IEC 27001:2022 Annex A per-control test-pattern catalog in references/iso27001.md. Produces a readiness self-assessment only: not certification, not an audit opinion, not legal advice. Use when a framework version has been named and an evidence set already exists, and someone needs a per-criterion readiness score before an observation period opens, before a qualified assessor arrives, or in response to a regulator inquiry.

hipaa-test-patterns

Reference catalog of HIPAA Security Rule-aligned test patterns - administrative safeguards (45 CFR §164.308: workforce training, access management, contingency planning), physical safeguards (§164.310: facility access, workstation security, device disposal), technical safeguards (§164.312: access control, audit logs, integrity, transmission security); PHI handling assertions in fixtures; minimum-necessary tests per §164.502(b); BAA-scope boundary verification. Use when authoring HIPAA-readiness tests for any product handling Protected Health Information.

pci-dss-control-test-author

Build-an-X for PCI DSS v4.0 scope verification - cardholder data environment (CDE) boundary tests, segmentation tests (PCI Req 1), prohibited-data-storage assertions per Req 3 (no full track data, no CVV/CAV2/CVC2/CID, no PIN/PIN block post-authorization), key-management tests per Req 3.6, encryption-of-transmissions per Req 4; includes the scope catalog (SAQ A / A-EP / D levels, PAN-storage rules, hosted-fields / tokenization scope-reduction patterns) in references/pci-scope.md. Use when authoring PCI DSS scope-reduction + control tests for any system handling payment-card data, or when determining a payment integration's SAQ level.

soc2-evidence-collector

Build-an-X for SOC 2 Type II evidence collection and auditor-facing packaging - per-Trust-Services-Criterion test artifacts (Common Criteria CC1.1 - CC9.2; plus Availability A1, Confidentiality C1, Processing Integrity PI1, Privacy P1 - P9 if in scope); auto-collection from CI logs + audit trails + access logs + change-management records; alignment with Vanta / Drata / Secureframe evidence shapes; observation-period sampling. Cross-framework evidence packaging (control-evidence matrix, timestamped bundles, chain-of-custody notes per NIST SP 800-72 - also for ISO 27001 / HIPAA / PCI DSS / GDPR / FedRAMP) lives in references/evidence-packaging.md. Use when the team is preparing for SOC 2 Type II audit and needs continuous evidence collection, or when any audit engagement requires auditor-ready evidence packages built from automated test output.