Files
2026-05-27 23:29:53 +01:00

6.5 KiB

Tasks — add @suaveplan/payment-providers

Every checkbox MUST reflect work actually done in this change. Retroactive ticking is forbidden.

1. Spec authoring

  • 1.1 Read ../suaveplan/enterprise/payment-providers.md end-to-end.
  • 1.2 Read upstream source at ../suaveplan/packages/universal/payment-providers/src/ end-to-end.
  • 1.3 Read openspec/AGENTS.md §13 + §14.
  • 1.4 Draft proposal.md from template.
  • 1.5 Fill ## Source mapping table — every requirement cites a line range or appears in the "no source line" table with justification.
  • 1.6 Draft specs/payment-providers/spec.md from template.
  • 1.7 Every requirement carries a **Verified by:** line at draft time.

2. Implementation

  • 2.1 src/types/provider.ts — ApiKeyConfig, OAuthConfig, MerchantKeyConfig, ProviderResponse<T>, HttpOptions. Add optional fetch?: FetchLike, now?: () => number, randomId?: () => string, base64Encode?: (s: string) => string, signal?: AbortSignal config fields.
  • 2.2 src/error-codes/error-codes.ts — PAYMENT_PROVIDER_CODES (HTTP_ERROR, TIMEOUT, PARSE_ERROR, OAUTH_TOKEN_FAILURE) via defineCodes; PaymentProviderError extends SuaveplanError<PaymentProviderErrorCode> carrying provider/httpStatus/bodyExcerpt/url discriminants; 4 factory functions.
  • 2.3 src/http/http.ts — FetchLike type; httpRequest<T> with injectable FetchLike, timeout via AbortSignal, JSON serialisation, typed-error wrapping.
  • 2.4 src/providers/stripe/stripe.ts — StripeProvider implements PaymentProvider; status + refund-reason mapping; idempotency key forwarding; injectable FetchLike.
  • 2.5 src/providers/paypal/paypal.ts — PayPalProvider implements PaymentProvider; OAuth2 client-credentials token cache; injectable now() for TTL and base64Encode for Basic header.
  • 2.6 src/providers/square/square.ts — SquareProvider implements PaymentProvider; Square-Version header; injectable randomId for default idempotency keys.
  • 2.7 src/providers/mollie/mollie.ts — MollieProvider implements PaymentProvider; string amount marshalling; redirect URL default.
  • 2.8 src/providers/adyen/adyen.ts — AdyenProvider implements PaymentProvider; merchant-account context; injectable randomId.
  • 2.9 Per-feature index.ts barrels — explicit named re-exports only (no export *).
  • 2.10 src/index.ts — explicit named root barrel re-exporting every public symbol.
  • 2.11 package.json at 0.1.0 with workspace:^ for @suaveplan/{payment,error} and catalog:build for tslib; 9 subpath exports; sideEffects: false.
  • 2.12 vite.config.ts + tsconfig{,.lib}.json + vitest.config.ts + tests/setup/polyfills.ts.
  • 2.13 tests/dep-graph.test.ts — universal-tier purity grep.

3. Tests

  • 3.1 src/error-codes/error-codes.test.ts — every code reachable via factory; discriminants set / unset; cause propagation.
  • 3.2 src/http/http.test.ts — GET / POST / DELETE / PATCH, custom headers, JSON body, empty body, 204, non-ok with message, non-ok with error, timeout abort, typed-error wrapping.
  • 3.3 src/providers/stripe/stripe.test.ts — every method, status-mapping matrix (7 entries), refund-reason mapping (4 entries), idempotency header, no-payment-method branch, custom baseUrl.
  • 3.4 src/providers/paypal/paypal.test.ts — every method, OAuth token cache hit / refresh / expiry boundary, AUTHORIZE vs CAPTURE intent, status-mapping matrix, refund-status mapping, missing payments field.
  • 3.5 src/providers/square/square.test.ts — every method, status-mapping matrix, refund-status mapping (COMPLETED / PENDING / REJECTED), default-idempotency-key via injected randomId, no-card-details branch, refund-without-reason.
  • 3.6 src/providers/mollie/mollie.test.ts — every method, status-mapping matrix (8 entries), refund-status mapping (5 entries), default description / redirect, non-card method as wallet, missing method.
  • 3.7 src/providers/adyen/adyen.test.ts — every method, status-mapping matrix (11 entries), refund-status mapping (received → pending, other → failed), idempotency header, missing paymentMethod, non-scheme type as wallet.
  • 3.8 tests/dep-graph.test.ts — grep for forbidden node: / bun: / fs / path / crypto / http imports.
  • 3.9 Every it(...) carries { timeout: 5000 } (or 30000 for async network — none here, all are deterministic with injected FetchLike).

4. Documentation

  • 4.1 Sibling .md for every implementation .ts (10 modules) — ≥200 words, basic + advanced examples, full API reference.
  • 4.2 README.md linking every co-located .md under ## Modules.
  • 4.3 Update CLAUDE.md package listing — payment-providers entry already exists under the package family, no edit required; verified before archive.

5. Pre-archive verification (the 5-gate triple)

  • 5.1 bun run check — Biome 0/0/0 across the monorepo.
  • 5.2 bunx turbo lint typecheck test --filter=@suaveplan/payment-providers — green.
  • 5.3 bunx turbo test:coverage --filter=@suaveplan/payment-providers — 100/100/100/100.
  • 5.4 bunx turbo build --filter=@suaveplan/payment-providers — green.
  • 5.5 Banned-pattern scan (@deprecated/TODO/FIXME/ts-ignore/ts-expect-error/.skip/.only) — zero output.

6. Pre-archive 9-row checklist (AGENTS.md §13)

  • 6.1 Generics threaded; no any.
  • 6.2 Zod schemas wired at every declared boundary — N/A (deferred per ## Out of scope; provider contracts are upstream-validated upstream of the network).
  • 6.3 Every error code in PAYMENT_PROVIDER_CODES thrown by a production path.
  • 6.4 Strict-mode behaviours tested both on and off — N/A (no strict-mode toggle).
  • 6.5 OTel instruments emitted from production paths — N/A (deferred per ## Out of scope).
  • 6.6 Lifecycle dedup tested where claimed — yes (PayPal token cache hit / refresh tests).
  • 6.7 No retroactive tick.
  • 6.8 No export * in any feature-module barrel.
  • 6.9 No direct vitest / bun:test imports in test files.

7. Archive

  • 7.1 Fold spec delta into openspec/specs/payment-providers/spec.md.
  • 7.2 Move openspec/changes/add-payment-providers/ → openspec/archive/2026-05-17-add-payment-providers/.
  • 7.3 Refresh MANIFEST.md via bun scripts/folder-reorg/generate-manifest.ts.
  • 7.4 Update STATUS.md — flip @suaveplan/payment-providers from Pending to Completed.