PCI DSS
How Pact keeps cardholder data out of scope by delegating every payment surface to Stripe's hosted pages — Pact never stores, processes, or transmits a card number.
The shortest true statement about Pact and PCI DSS is this: Pact never touches a card number. Every payment surface is a hosted Stripe page. Your card details are entered on Stripe's domain, tokenized by Stripe, and stored by Stripe — they never transit or land in Pact's backend, database, or logs.
Why this matters for your PCI scope
Because cardholder data never enters Pact's environment, using Pact does not pull Pact into the card-data portion of your own PCI assessment. Pact's billing integration is built on the same outsourced-payment pattern (SAQ A shape) that a merchant uses when redirecting to a hosted payment page: the sensitive surface belongs to the payment provider.
How billing is wired
Billing lives behind a provider abstraction (core/billing.py) so no route imports the stripe SDK directly. The two customer-facing entry points are both hosted by Stripe:
POST /v1/billing/checkout— opens a Stripe Checkout session for an upgrade. The customer lands oncheckout.stripe.com, enters their card there, and returns.POST /v1/billing/portal— opens the Stripe Customer Portal, where the customer manages their subscription and payment method on Stripe's domain.
There is also a setup-mode checkout (create_setup_checkout_session) that puts a card on file for a later one-click upgrade. Even here, the card is captured by Stripe in setup mode and is never charged inline — Pact only ever receives a Stripe customer/payment-method reference, not the PAN.
Customer ──card──▶ checkout.stripe.com (Stripe's PCI-scoped environment)
│
▼
Stripe ──customer_id, subscription_id──▶ Pact backend (no card data)
When the platform Stripe credential is not configured, every billing write returns 503 stripe_not_configured rather than attempting to collect payment details itself — there is no in-app card-entry fallback by design.
What Pact stores
Pact persists only non-sensitive Stripe references — customer IDs, subscription IDs, price/plan identifiers, and usage counters for metered billing. It does not store, and has no schema column for, a primary account number, CVV, or full magnetic-stripe data.
Webhook signature verification (verify_stripe_signature) re-implements Stripe's documented HMAC-SHA256 scheme so inbound webhook events are authenticated, but the events Pact consumes carry subscription state, not card data.
Where the formal attestation stands
Roadmap: formal PCI attestation
The architecture above keeps cardholder data out of Pact's environment today. A formal, signed SAQ A attestation and an AOC that you can attach to a vendor-security questionnaire is a planned compliance-program artifact, tracked alongside the SOC 2 evidence work. If you need documentation for a procurement review before then, contact your Pact representative — the outsourced-payment design is the substance behind the eventual attestation.