Testland
Browse all skills & agents

pci-dss-scope-reference

Pure-reference catalog of PCI DSS v4.0 scope reduction techniques + the testable scope boundaries. Covers the SAQ levels (A through D, picked by how cardholder data flows), the PAN-storage prohibitions (only first-6 + last-4 retained; nothing else cleartext), the tokenization + hosted-fields scope-reduction patterns (Stripe Elements / Adyen Drop-in / Braintree Hosted Fields keep PAN off your servers), Network-Segmentation as PCI scope-reduction, and the testable behaviours the scope boundary creates. This is the catalog of WHY the boundary matters and what it makes testable - not a checker that verifies a given integration against the standard. Use when designing or auditing the PCI scope of a payment integration.

Install with skills.sh (any agent)

npx skills add testland/qa --skill pci-dss-scope-reference
View source

pci-dss-scope-reference

Scope reduction is the dominant strategy: keep card data off your systems entirely, so PCI compliance becomes minimal SAQ A instead of full SAQ D.

This skill is distinct from a scope checker that verifies the boundary holds in code. This skill explains what the boundary IS and the test surface it creates.

How to use this catalog

  1. Identify your integration pattern - Review the scope-reduction patterns below (hosted fields, redirect, tokenization, network segmentation) and match the one your payment integration uses.
  2. Determine your SAQ level - Use the SAQ table to confirm which Self-Assessment Questionnaire level applies given how cardholder data flows through your system.
  3. Verify testable behaviours - Cross-reference the Testable behaviours table and anti-patterns to confirm the scope boundary is preserved and hand off specific tests to pci-dss-control-test-author.

SAQ levels (Self-Assessment Questionnaire)

Per pcisecuritystandards.org (opens in new window):

SAQDescriptionScope
ACard-not-present, fully outsourced (hosted gateway pages, iFrame redirects, Stripe Elements)Smallest - your servers never see PAN
A-EPHosted-form-with-merchant-customisation (e.g., your domain shows the form but iframe is the gateway's)Slightly larger; some elements visible to your server
DAll merchants not covered by A-C; full PCI DSSLargest - for cases where you must handle PAN

Choose A when feasible: PAN never touches your servers because the customer inputs it directly into a gateway-hosted iframe / element.

PAN storage rules

Per PCI DSS v4.0 §3.4: prohibited storage of:

  • Full PAN cleartext anywhere
  • Sensitive authentication data (full track, CVV/CVC, PIN/PIN block) post-authorisation
  • More than first-6 + last-4 digits in any retained data (truncated)

Allowed:

  • First-6 + last-4 digits (truncated PAN)
  • Tokens issued by the gateway (e.g., Stripe pm_*)
  • Encrypted PAN with strong key management (if you must store full PAN)

Tests for storage (PostgreSQL ~ regex operator):

-- Detect prohibited PAN patterns in any string column
SELECT * FROM <any_table>
WHERE  column ~ '^[0-9]{13,19}$'
    OR column ~ '^4[0-9]{15}$'
    OR column ~ '^5[1-5][0-9]{14}$'
LIMIT 10;
-- Expect: 0 rows

Scope-reduction patterns

1. Hosted fields / Elements

Per stripe.com/docs/payments/payment-element (opens in new window), docs.adyen.com/payment-methods/cards/web-drop-in (opens in new window), developer.paypal.com/braintree/docs/start/hosted-fields (opens in new window):

<!-- Stripe Element -->
<form>
  <div id="payment-element"></div>   <!-- iframe; PAN stays in Stripe's iframe -->
  <button>Pay</button>
</form>

PAN never reaches your JS or backend. The Element sends to Stripe directly; your server gets a token.

2. Redirect-to-gateway

Customer redirects to gateway-hosted page; pays; redirects back with a token / transaction ID.

PCI-friendly because PAN never on your domain. UX-tradeoff: slower, less branded.

3. Tokenization API

Backend-to-backend: customer submits PAN to gateway directly (via JS); gateway returns token; your code uses token.

Variants per gateway: Stripe setupIntent for saved cards; Adyen paymentMethods.storeDetails; PayPal Vault.

4. Network segmentation

If you must touch PAN, isolate it in a separate network with strict ingress / egress + monitoring. Reduces scope of the broader IT environment.

Testable behaviours

BehaviourTest
No 16-digit numbers in DBSQL regex against all string columns
No CVV / CVC storedSearch code for cvc, cvv, cardholderVerification
Hosted fields render without exposing PAN to your JSBrowser DevTools Network tab - no PAN in requests to your origin
Webhooks contain tokens not PANParse webhook payloads; assert no 16-digit numbers
Log scrubbingTest logs for PAN patterns; should be redacted
Backup snapshots PAN-freeSame regex against backup files
Egress firewall blocks card-network IPsNetwork test

A pci-dss-control-test-author runs these adversarially. This skill provides the catalog.

Anti-patterns

Anti-patternWhy it failsFix
Log entire payment request bodyPAN in logsScrub at log emit
Stage card-collection on your own pageCards now in your domain → SAQ DUse hosted fields
Send PAN to backend then forward to gatewayServer now PCI-scopeDirect JS-to-gateway
Store PAN encrypted "just in case"Key management is half of PCI DSSUse tokens
Test PAN in fixturesReal PAN in commitsUse only platform-provided test PANs
Capture CVV server-sidePCI DSS v4.0 §3.2.1: prohibited post-authDon't capture or capture in scoped iframe
Skip scope-checker in CIDrift over timePeriodic scope audit

Limitations

  • PCI DSS v4.0 is paywalled (cite by stable ID). Gateway docs paraphrase the relevant clauses.
  • Scope is a moving target. Adding a new feature can pull PAN into your system; re-audit on architecture changes.
  • PCI compliance ≠ PCI security. Compliance is a baseline; actual security needs more (threat modeling, pentest, etc.).
  • Doesn't cover PA-DSS (Payment Application DSS for POS software).

References

Related skills

3ds-test-flow-reference

Cross-gateway, protocol-level reference for 3-D Secure (3DS 2.x) test coverage. Covers the EMVCo frictionless / challenge / not-applicable flow paths, SCA under EU PSD2, and the per-PAN test cards for Stripe, Adyen, and Braintree. The gateway-specific wrappers (adyen-test-mode / stripe-test-cards-and-webhooks / braintree-test-cards) compose this skill for single-gateway work, so use one of those for a single-gateway query. Use this skill when designing multi-gateway 3DS test coverage, auditing a 3DS redirect round-trip, or investigating a challenge-flow regression that is not gateway-specific.

adyen-test-mode

Wraps Adyen test-mode patterns: test-API-key initialization, the canonical Adyen test cards (Visa 4111 1111 1111 1111; 5454 5454 5454 5454 3DS frictionless; 4917 6100 0000 0000 3DS 2 challenge), the per-flow result codes (Authorised / Refused / Pending / RedirectShopper / Error), the HMAC-SHA256 webhook validation, and notifications-vs-API duality (Adyen separates synchronous API calls from asynchronous notifications). Use when testing Adyen-integrated code.

braintree-test-cards

Wraps Braintree (PayPal-owned) sandbox testing patterns: sandbox merchant credentials, Drop-in / Hosted Fields client-side patterns, the Transaction lifecycle (submitted_for_settlement → settled), Braintree's distinctive test-card behaviours (specific PANs trigger specific errors), and the webhook verification (Braintree Webhook Parser). Use when testing Braintree-integrated code.

chargeback-flow-test-author

Workflow-driven skill that builds the chargeback / dispute test suite: canonical reason codes (Visa 10.4 fraud, 13.1 services-not-provided; Mastercard MCC 4855), per-gateway dispute APIs (Stripe Disputes, Adyen Chargeback notifications, PayPal Disputes), the evidence-submission flow + window, and disposition outcomes (won / lost / accepted). Use when designing dispute coverage; for refunds use refund-test-matrix-builder, for webhook redelivery + idempotency use payment-webhook-replay, and for the lifecycle state model use payment-flow-states-reference.

payment-flow-states-reference

Pure-reference catalog of payment lifecycle state machines across Stripe, Adyen, PayPal, and Braintree: canonical states (created / requires_action / processing / succeeded / requires_capture / canceled / failed), authorisation vs capture, asynchronous webhook states, and refund / dispute / chargeback transitions. Use when designing tests for payment flows or auditing state-handling code; this is the state model, not a builder - to author suites on it use refund-test-matrix-builder (refunds), chargeback-flow-test-author (disputes), or payment-webhook-replay (webhook replay).

payment-webhook-replay

Workflow-driven skill that builds payment webhook replay + recovery tests. Covers the idempotency contract (every webhook handler must handle redelivery without side effects), the replay simulators (Stripe CLI `stripe trigger`, Adyen Customer Area resend, PayPal Webhook Simulator, Braintree webhook test), the signature-verification gauntlet (HMAC-SHA256 per gateway, expired-timestamps rejection), and the partial-failure recovery scenarios. Use when designing webhook robustness tests.

paypal-sandbox

Wraps PayPal Sandbox testing patterns: sandbox account creation (Business + Personal accounts in developer.paypal.com), the Orders v2 API (create / capture / refund), webhook event simulator (developer.paypal.com webhook simulator), sandbox-account-specific test cards, and the OAuth2 client-credentials flow for sandbox. Use when testing PayPal-integrated code.

refund-test-matrix-builder

Workflow-driven skill that builds a refund test matrix from a payment-flow inventory: refund variants (full / partial / multiple-partials / over-refund / refund-on-disputed / refund-on-already-refunded), per-gateway nuances (Stripe, Adyen, PayPal, Braintree refund APIs), and timing variants (immediate / next-day / declined-by-bank), one test case per cell. Use for refund coverage on a new integration; for chargeback / dispute coverage use chargeback-flow-test-author, for webhook redelivery + idempotency use payment-webhook-replay, and for the state model use payment-flow-states-reference.

stripe-subscription-billing-test-author

Builds test suites for Stripe recurring-billing flows: trial-to-paid conversion, proration on plan upgrade and downgrade, dunning on failed renewal, cancel and reactivation, and the full subscription webhook event matrix (invoice.payment_failed, customer.subscription.updated, customer.subscription.deleted, invoice.paid). Uses Stripe Billing test clocks (POST /v1/test_helpers/test_clocks) to time-travel through billing cycles without calendar delay. Distinct from stripe-test-cards-and-webhooks (one-time PaymentIntents) and payment-webhook-replay (idempotency + replay robustness). Does not cover single-event CLI replay or handler idempotency testing (see payment-webhook-replay for those). Use when authoring tests for subscription or recurring-billing integrations.

stripe-test-cards-and-webhooks

Wraps Stripe API testing patterns: test-mode initialization, the canonical test cards (4242 success; 4000 0000 0000 0002 declined; 4000 0027 6000 3184 3DS challenge per 3ds-test-flow-reference), the Stripe CLI webhook flow (`stripe listen --forward-to`), the Stripe CLI fixture commands (`stripe trigger payment_intent.succeeded`), and the webhook signature verification (Stripe-Signature header + HMAC-SHA256). Use when testing Stripe-integrated code.