effaced-stripe
effaced-stripe — first-party Stripe resolver for effaced.
StripeResolver
Section titled “StripeResolver”class StripeResolver: def __init__(api_key: str, *, http_client: HTTPClient | None = None) -> NoneExports, erases, and rectifies a subject’s PII held in Stripe.
Expects refs of kind "stripe" (refs are routed to the resolver
whose name equals their kind — ADR 0008) whose value is the Stripe
customer id. Erasure uses Stripe’s customer deletion, which Stripe
itself implements as a GDPR-aware redaction.
Idempotency: a customer Stripe no longer knows yields
already_absent=True on erasure and already_consistent=True on
rectification — success, never an error. Rectification is convergent
and structurally satisfies RectifyingResolver
(see rectify_subject for the curated category mapping).
Error taxonomy (see effaced_stripe.errors): authentication,
permission, and malformed-request failures raise
ResolverError; rate limits, connection
faults, and Stripe-side errors propagate so the saga runner retries.
SDK-internal retries are disabled (max_network_retries=0) — the
saga runner owns retry and backoff (ADR 0010).
Fields:
- covered_surface (
CoveredSurface): The Stripe PII this resolver claims to reach (AttestingResolver). Returns:STRIPE_COVERED_SURFACE, built from the exporter’s field tuples so it cannot drift. - name (
str): Stable resolver name recorded in manifests and audits.
StripeResolver.erase_subject
Section titled “StripeResolver.erase_subject”async def erase_subject(ref: SubjectRef) -> ResolverErasureDelete the customer in Stripe (Art. 17).
Args:
- ref (
SubjectRef):kind="stripe",value=<customer id>.
Returns:
ResolverErasure— The outcome;already_absent=Trueif Stripe already had noResolverErasure— such customer.
Raises:
ResolverError— The key is invalid, lacks a permission, or the request was malformed — retrying cannot succeed.
StripeResolver.export_subject
Section titled “StripeResolver.export_subject”async def export_subject(ref: SubjectRef) -> ResolverExportCollect the customer’s Stripe-held PII (Art. 15).
Args:
- ref (
SubjectRef):kind="stripe",value=<customer id>.
Returns:
ResolverExport— Customer profile, addresses, and payment-method metadata —ResolverExport— never full card numbers (Stripe does not expose them). EmptyResolverExport— when Stripe holds no such customer.
Raises:
ResolverError— The key is invalid, lacks a permission, or the request was malformed — retrying cannot succeed.
StripeResolver.rectify_subject
Section titled “StripeResolver.rectify_subject”async def rectify_subject(ref: SubjectRef, corrections: tuple[Correction, ...]) -> ResolverRectificationApply category-keyed corrections to the customer (Art. 16).
Maps corrections onto Stripe Customer fields through a curated,
single-field-per-category table: PiiCategory.IDENTITY to
name and PiiCategory.CONTACT to email. Every other
category is ignored — a category that maps to no field is a
complete answer, not a failure (ADR 0013).
Deliberate limitation: Stripe also files phone and the
address.* components under PiiCategory.CONTACT, but a
coarse category-keyed scalar cannot tell email from phone from a
postal address. Writing one value to all three would manufacture
fresh inaccuracy, which Art. 16 exists to prevent — so only
email is rectified for CONTACT. Field-keyed corrections are
left to a future, finer vocabulary.
Convergence: the customer is retrieved first; only fields that
actually drift from their correction are written, and a customer
Stripe no longer holds is reported already_consistent=True.
Re-applying corrections Stripe already reflects writes nothing and
returns already_consistent=True — the rectification analogue of
erasure’s already_absent, which saga retries depend on.
Args:
- ref (
SubjectRef):kind="stripe",value=<customer id>. - corrections (
tuple[Correction, ...]): Category-keyed corrected values to apply.
Returns:
ResolverRectification— The outcome;already_consistent=Truewhen nothing mapped,ResolverRectification— the customer was absent, or Stripe already held every targetResolverRectification— value.
Raises:
ResolverError— The key is invalid, lacks a permission, or the request was malformed — retrying cannot succeed.