Initial Commit
This commit is contained in:
@@ -0,0 +1,135 @@
|
||||
# Add @suaveplan/payment-provider-stripe sibling adapter
|
||||
|
||||
**Package**: `@suaveplan/payment-provider-stripe`
|
||||
**Status**: PROPOSED
|
||||
**Type**: new-package
|
||||
|
||||
## Why
|
||||
|
||||
The `2026-05-17-slim-payment-providers` change extracted the five
|
||||
concrete provider adapters (Stripe, PayPal, Square, Mollie, Adyen) out
|
||||
of `@suaveplan/payment-providers` and into sibling packages so
|
||||
consumers pay only for the providers they install. This change lands
|
||||
the **Stripe** sibling.
|
||||
|
||||
`@suaveplan/payment-provider-stripe` re-lands the `StripeProvider`
|
||||
class (previously `@suaveplan/payment-providers.StripeProvider` prior
|
||||
to the slim-down) verbatim against the slim foundation. It implements
|
||||
`PaymentProvider` from `@suaveplan/payment`, uses `httpRequest` from
|
||||
the slim foundation for every HTTP call, forwards Bearer auth and the
|
||||
caller-supplied `Idempotency-Key` header on every mutating request,
|
||||
maps Stripe payment-intent / refund status codes to the domain
|
||||
`PaymentStatus` / `RefundStatus` enums, and raises only
|
||||
`PaymentProviderError`.
|
||||
|
||||
## What changes
|
||||
|
||||
- ADDED: `@suaveplan/payment-provider-stripe` package at
|
||||
`packages/universal/payment-provider-stripe/` (`0.1.0`, universal
|
||||
tier, `sideEffects: false`).
|
||||
- ADDED: `class StripeProvider implements PaymentProvider` with
|
||||
literal `name: "stripe"`. Constructor accepts a `StripeConfig`
|
||||
extending `ApiKeyConfig` (Stripe secret key + optional
|
||||
`webhookSecret`, plus the shared `ProviderCommonOptions`).
|
||||
- ADDED: All six `PaymentProvider` methods — `createIntent`,
|
||||
`confirmIntent`, `captureIntent`, `cancelIntent`, `refund`,
|
||||
`getIntent` — each routed through `httpRequest` against the Stripe
|
||||
REST API.
|
||||
- ADDED: Stripe-domain → `PaymentIntent` / `Refund` mappers
|
||||
(`mapIntent`, `mapRefund`, `mapStatus`, `mapRefundStatus`,
|
||||
`mapRefundReason`) that translate every Stripe lifecycle state into
|
||||
the `@suaveplan/payment` enums.
|
||||
- ADDED: `StripeConfig` type re-export so consumers can pin the
|
||||
construction shape without reaching into the slim core for
|
||||
`ApiKeyConfig`.
|
||||
- ADDED: Subpath exports for `./stripe/stripe` so consumers can
|
||||
tree-shake the provider class directly.
|
||||
|
||||
## Out of scope
|
||||
|
||||
- Webhook signature verification — `@suaveplan/payment` already ships
|
||||
the `WebhookVerifier`; this package only carries the
|
||||
`webhookSecret` field on `StripeConfig` for downstream wiring.
|
||||
- OpenTelemetry spans / counters on the provider — defers to a
|
||||
monorepo-wide observability pass tracking
|
||||
`@suaveplan/payment`-level instrumentation.
|
||||
- Stripe Connect, Customer / Setup-intent / Subscription APIs — the
|
||||
`PaymentProvider` contract only covers payment-intent + refund
|
||||
lifecycle; non-contract Stripe surfaces are deferred to dedicated
|
||||
follow-up packages.
|
||||
- Currency conversion — Stripe's minor-unit (cents) amount is mapped
|
||||
to `MoneyLike.amount: bigint` 1:1 with currency uppercased; no
|
||||
zero-decimal currency adjustment is performed in this change
|
||||
(parity with the pre-slim shape).
|
||||
|
||||
## Source mapping
|
||||
|
||||
This change derives from `../suaveplan/enterprise/payment-providers.md`
|
||||
and the verbatim upstream Stripe implementation that was bundled into
|
||||
the just-slimmed `@suaveplan/payment-providers` package.
|
||||
|
||||
| Requirement | Source lines | Notes |
|
||||
|---|---|---|
|
||||
| Universal-tier purity (no Node / browser / React deps) | `enterprise/payment-providers.md` L37 | verbatim cross-cutting rule |
|
||||
| Zero `Math.random` / `Date.now` at module scope; injectable seams | `enterprise/payment-providers.md` L40 | satisfied via shared `ProviderCommonOptions` (fetch/timeoutMs/signal) |
|
||||
| Structured errors extending `@suaveplan/error` | `enterprise/payment-providers.md` L42, L61 | uses `PaymentProviderError` from the slim core; raises no raw `Error` |
|
||||
| `AbortSignal` everywhere async, per-call timeout | `enterprise/payment-providers.md` L43 | inherits `httpRequest` composition of caller `signal` + internal timeout |
|
||||
| Idempotency-key wiring on mutating calls | `enterprise/payment-providers.md` L44 | `createIntent` / `refund` forward `Idempotency-Key` when caller supplies it |
|
||||
| Tree-shakeable, `sideEffects: false` | `enterprise/payment-providers.md` L55 | verbatim |
|
||||
| `workspace:^` internal deps + Bun catalog externals | `enterprise/payment-providers.md` L56 | verbatim |
|
||||
| 100% Istanbul coverage + 100% docs coverage | `enterprise/payment-providers.md` L50-L51 | genesis-wide policy as well |
|
||||
| File-size budget (250 soft / 300 hard / 500 test) | `enterprise/payment-providers.md` L52 | verbatim |
|
||||
| StripeProvider full lifecycle (`createIntent` / `confirmIntent` / `captureIntent` / `cancelIntent` / `refund` / `getIntent`) | `/mnt/s/web/suaveplan/packages/universal/payment-providers/src/stripe.ts` L130-L209 | verbatim port against slim foundation; previously folded as a removed requirement by `2026-05-17-slim-payment-providers` (`specs/payment-providers/spec.md` "Requirement: StripeProvider full lifecycle") |
|
||||
| Stripe status → `PaymentStatus` mapping table | `/mnt/s/web/suaveplan/packages/universal/payment-providers/src/stripe.ts` L45-L56 | verbatim 7-row mapping including `unknown → failed` fallback |
|
||||
| Stripe refund status → `RefundStatus` mapping | `/mnt/s/web/suaveplan/packages/universal/payment-providers/src/stripe.ts` L58-L62 | verbatim 3-branch mapping (`succeeded` / `pending` / `failed`) |
|
||||
| Stripe refund reason → `RefundReason` mapping | `/mnt/s/web/suaveplan/packages/universal/payment-providers/src/stripe.ts` L104-L111 | verbatim 4-branch mapping (`duplicate` / `fraudulent` / `requested_by_customer` / `other`) |
|
||||
| Bearer auth header on every request | `/mnt/s/web/suaveplan/packages/universal/payment-providers/src/stripe.ts` L211-L217 | verbatim `Authorization: Bearer <apiKey>` header |
|
||||
| `StripeProvider.name === "stripe"` | `/mnt/s/web/suaveplan/packages/universal/payment-providers/src/stripe.ts` L119 | verbatim literal name |
|
||||
|
||||
### Requirements with no source line
|
||||
|
||||
| Requirement | Justification |
|
||||
|---|---|
|
||||
| `provider: "stripe"` discriminant on every raised `PaymentProviderError` | Slim-foundation `httpRequest` accepts a `provider` field on `HttpOptions`; wiring it on every call lets consumers discriminate Stripe failures from sibling-package failures without parsing messages. Not required by the upstream file but mandatory for the slim-core contract. |
|
||||
| Injectable `fetch` / `signal` / `timeoutMs` forwarded to `httpRequest` on every call | The upstream file held its own `timeoutMs` but never forwarded the caller's external `signal` or `fetch`. Required by the slim foundation (every sibling MUST flow through `ProviderCommonOptions`); upgraded from the upstream surface in this migration. |
|
||||
|
||||
## Verification approach
|
||||
|
||||
Every requirement in `specs/payment-provider-stripe/spec.md` carries a
|
||||
`**Verified by:**` line citing concrete `it(...)` titles in:
|
||||
|
||||
- `src/stripe/stripe.test.ts` — every `PaymentProvider` method, the
|
||||
Bearer / `Idempotency-Key` header forwarding, every status / refund-
|
||||
status / refund-reason branch, `provider` discriminant on raised
|
||||
errors, injected `FetchLike` + `signal` forwarding.
|
||||
- `tests/dep-graph.test.ts` — pins universal-tier purity (no
|
||||
`node:` / `bun:` / `fs` / `path` / etc imports under `src/`).
|
||||
|
||||
Tests use a real recording `FetchLike` closure — no `vi.mock`, no
|
||||
`vi.stubGlobal`. The Stripe REST API surface is exercised purely
|
||||
through the injected fetch.
|
||||
|
||||
## Migration impact
|
||||
|
||||
None — additive only. This package is brand new under
|
||||
`packages/universal/payment-provider-stripe/` and is not yet consumed
|
||||
by any other package in the monorepo. Consumers that previously
|
||||
imported `StripeProvider` from `@suaveplan/payment-providers` (none
|
||||
exist on genesis; that surface was removed by
|
||||
`2026-05-17-slim-payment-providers` before any consumer landed) will
|
||||
import from the new package per the slim-core migration table.
|
||||
|
||||
## Impact
|
||||
|
||||
### Affected dependents
|
||||
|
||||
Run `bunx turbo ls --filter=...@suaveplan/payment-provider-stripe` to
|
||||
enumerate. The package is brand new with no current dependents.
|
||||
|
||||
| Dependent | Action |
|
||||
|---|---|
|
||||
| (none) | [x] no action needed — new package, no consumers yet |
|
||||
|
||||
Future dependents will be: `@suaveplan/api-plugin-payment` (when it
|
||||
lands as a Stripe-configurable host) and any application-layer
|
||||
package that wires the `PaymentEngine` to Stripe.
|
||||
Reference in New Issue
Block a user