This FRD ships @dmwd-io/payments as an optional package that re-exports stripe as the platform standard for payment processing. The value is standards enforcement and drift prevention — not a custom abstraction layer. Per ADR-014, the library’s own API is the interface.
Introduction
Overview
Per ADR-014 (Open Source First), the platform designates stripe as the community library standard for payment processing. Rather than building a custom PaymentsProvider interface and adapter layer, @dmwd-io/payments is a thin re-export package that surfaces stripe directly and documents platform conventions on top: the canonical env var names (STRIPE_SECRET_KEY, STRIPE_PUBLISHABLE_KEY, STRIPE_WEBHOOK_SECRET), PII sanitization requirements, and event naming conventions. Consuming apps import from @dmwd-io/payments instead of stripe directly, which gives the platform a single upgrade and governance point without hiding the library’s native API.
Goals
Designate stripe as the platform standard for payment processing via ADR-014.
Ship @dmwd-io/payments as a thin re-export of stripe so all apps share a single governed version.
Document STRIPE_SECRET_KEY, STRIPE_PUBLISHABLE_KEY, and STRIPE_WEBHOOK_SECRET as the canonical platform env var names.
Prevent per-app SDK version drift by centralizing the stripe dependency.
Include examples showing checkout flow, saved payment methods, and failure handling using the native stripe API.
Non-Goals
Building a custom PaymentsProvider interface or adapter layer — the library’s own API is the interface (per ADR-014).
Building a production adapter for PayPal or Square.
Implementing subscription billing logic (see FRD: Billing Provider Wrapper).
PCI compliance scope — tokenization is delegated to the vendor’s client-side SDK (Stripe Elements).
Building new payment UI components beyond integrating with the existing payment-form widget.
Currency conversion or multi-currency routing.
Scope
In Scope
Area
Description
Re-export package
@dmwd-io/payments with stripe as a peer dependency and export * from 'stripe' barrel
PaymentFormCallbacks type that the payment-form widget accepts for integration
Webhook events
Platform event naming conventions layered on top of Stripe’s native webhook types
PII conventions
Documentation of which Stripe error fields must be sanitized before logging
Out of Scope
Area
Reason
Custom provider interface
Per ADR-014 — library API is the interface
Vendor adapter implementations
Not needed; stripe is the standard
Subscription management
Covered by FRD: Billing Provider Wrapper
PCI-scoped tokenization
Handled by Stripe Elements client-side SDK
Fraud detection
Vendor-side or dedicated service
Payment form UI redesign
Existing widget is sufficient; visual changes are a separate effort
Users and Pain Points
User Groups
User
Description
Needs
App developers
Engineers building checkout flows
A single governed import path for payment processing
QA engineers
Testers validating payment scenarios
Deterministic test outcomes using Stripe test mode keys
Design system maintainers
Library contributors
A thin package that enforces version alignment without hiding the library
Pain Points
User
Pain Point
Impact
App developers
Each app pins its own stripe version, causing silent API drift
Breaking changes surface inconsistently across apps
App developers
The payment-form widget has no standard callback contract for processing
Developers wire callbacks ad-hoc; shapes vary between apps
QA engineers
No platform guidance on Stripe test mode key usage or fixture setup
Payment error paths are tested inconsistently
Definitions
Term
Definition
Checkout session
A server-created session representing a payment intent, optionally redirecting to a Stripe-hosted page
Payment method
A stored instrument (card, bank account) associated with a customer
Charge
A completed or attempted payment against a payment method
Refund
A full or partial reversal of a completed charge
Receipt
A confirmation record for a completed charge, suitable for display or email
Payment token
A Stripe-issued opaque string representing card details collected client-side
Thin re-export
A package whose primary job is export * from '<library>' plus platform conventions
Current State
Existing Behavior
The payment-form.tsx widget renders card input fields and a submit button. It accepts an onSubmit callback but has no opinion on what happens after form submission. Each app implements its own Stripe PaymentIntent creation, confirmation, and error display logic by importing stripe directly.
Current Limitations
No shared import path — apps depend on different stripe versions independently.
No platform guidance on env var naming; apps use inconsistent names like STRIPE_KEY, STRIPE_API_KEY, or NEXT_PUBLIC_STRIPE_KEY.
Payment error messages are vendor-specific strings displayed raw to users.
No shared receipt generation — each app formats confirmation differently.
Existing Workarounds
Apps import Stripe SDK directly in API routes and client components.
Storybook stories for payment-form pass a no-op onSubmit that logs to console.
Proposed Solution
Summary
Per ADR-014, @dmwd-io/payments is a thin re-export package: stripe is declared as a peer dependency, and src/index.ts re-exports everything from it. No custom interface is built — the library’s API is the interface. Platform conventions (env var names, PII sanitization, event naming) are documented alongside the package but do not wrap or replace any native API surface.
packages/payments/src/index.ts
export*from"stripe";
// Consuming app — import from the platform package, not stripe directly
No custom interface is built — the library’s API is the interface.
Key Capabilities
All native stripe SDK capabilities are available via the re-export.
Platform env var names are the single source of truth across all apps.
PaymentFormCallbacks type bridges the existing payment-form widget to Stripe’s native callback shapes.
PII sanitization conventions prevent card numbers and tokens from appearing in logs.
User Experience
End users see more consistent error messages when payments fail because all apps follow the same platform conventions for error handling. No direct user-facing changes — the package governs the data layer that powers existing UI components.
Developer Experience
Developers import from @dmwd-io/payments instead of stripe. They initialize Stripe using STRIPE_SECRET_KEY and use the full native stripe API without any custom wrapper. The PaymentFormCallbacks type is available as a platform-standard bridge to the payment-form widget.
Requirements
ID
Requirement
Priority
Notes
FR-001
@dmwd-io/payments re-exports all stripe exports
Must
-
FR-002
stripe is declared as a peer dependency in package.json
Must
-
FR-003
STRIPE_SECRET_KEY, STRIPE_PUBLISHABLE_KEY, STRIPE_WEBHOOK_SECRET are documented as canonical env var names
Must
-
FR-004
Export PaymentFormCallbacks type compatible with payment-form widget’s onSubmit/onError props
Should
-
FR-005
Document PII sanitization requirements for Stripe error objects
Must
Per NFR-006
FR-006
Export PaymentEvent platform wrapper type for webhook normalization
Should
Per ADR-065
Priority Definitions
Priority
Meaning
Must
Required for this feature to ship.
Should
Important, but can be deferred if needed.
Could
Nice to have. Not required for initial release.
Functional Requirements
ID
Requirement
User Benefit
Priority
FUNC-001
import Stripe from "@dmwd-io/payments" works identically to import Stripe from "stripe"
Single governed import path
Must
FUNC-002
Platform docs show new Stripe(process.env.STRIPE_SECRET_KEY) as the canonical initialization pattern
Consistent initialization across apps
Must
FUNC-003
PaymentFormCallbacks type wires payment-form widget onSubmit/onSuccess/onError to Stripe’s native types
Eliminates ad-hoc wiring
Should
FUNC-004
Storybook docs page shows checkout session creation, payment method listing, and refund flows using native Stripe API
Developers can follow platform examples
Must
FUNC-005
PII sanitization helper strips card numbers and tokens from Stripe error objects before logging
Prevents sensitive data leakage
Must
Non-Functional Requirements
ID
Requirement
Category
Priority
NFR-001
Package adds zero net runtime dependencies beyond stripe itself
Performance
Must
NFR-002
Re-export barrel does not import or execute any Stripe SDK code at module load time
Performance
Must
NFR-003
stripe peer dependency version range is documented and kept current
Maintainability
Must
NFR-004
All monetary amounts in platform docs and examples use integers in smallest currency unit (cents)
Reliability
Must
NFR-005
Package does not wrap or proxy any native stripe method
Maintainability
Must
NFR-006
Payment tokens and card numbers must never appear in platform error conventions or log helpers
Handle PCI tokenization — that is Stripe Elements’ job.
Modify the payment-form widget — only define a callback type compatible with it.
Decision Log
Date
Decision
Reason
Owner
2026-05-26
PaymentFailure extends Error
Natural try/catch ergonomics; aligns with how auth provider throws
David Holmes
2026-05-26
Support both redirect URL and client secret on CheckoutSession
Accommodates vendor-hosted (Stripe Checkout) and embedded (Stripe Elements) flows
David Holmes
2026-05-26
Start with 6 failure codes, not an exhaustive vendor-specific list
Keeps the contract simple; vendors map edge cases to processing_error
David Holmes
2026-06-02
Reframed per ADR-014 (Open Source First): adopt stripe as thin re-export rather than building a custom provider interface. Library API is the interface.
ADR-014 establishes that well-maintained community libraries should not be wrapped in custom abstractions
David Holmes
Document History
Date
Author
Change
2026-05-26
David Holmes
Initial draft
2026-06-02
David Holmes
Reframed per ADR-014: ship as thin re-export of stripe, drop custom interface.