Files
suaveplan/openspec/archive/2026-05-17-add-payment/tasks.md
2026-05-27 23:29:53 +01:00

7.7 KiB
Raw Blame History

Tasks — add @suaveplan/payment

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

1. Spec authoring

  • 1.1 Read ../suaveplan/enterprise/payment.md end-to-end.
  • 1.2 Read upstream source at ../suaveplan/packages/universal/payment/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 line range or appears in the "no source line" table with justification.
  • 1.6 Draft specs/payment/spec.md from template.
  • 1.7 Every requirement carries a **Verified by:** line at draft time.

2. Implementation

  • 2.1 src/types/payment.ts — PaymentStatus, PaymentMethod{,Type}, CardBrand, PaymentIntent, PaymentProvider, PaymentEventMap, Refund{,Status,Reason,Input}, Dispute{,Evidence}, CreatePaymentIntentInput, VALID_TRANSITIONS (frozen).
  • 2.2 src/error-codes/error-codes.ts — PAYMENT_CODES (13 codes) via defineCodes; PaymentError extends SuaveplanError<PaymentErrorCode> with intentId/currentStatus/targetStatus/ageMs discriminants; 12 factory functions.
  • 2.3 src/hooks/hooks.ts — generic Hooks<TMap> + paymentHooks singleton + onPaymentProcessing shortcut.
  • 2.4 src/engine/engine.ts — PaymentEngine over EventBus<PaymentEventMap>, state-machine enforcement, refund-balance guard, hook pipeline, explicit markFailed/openDispute/closeDispute emitters.
  • 2.5 src/webhook/webhook.ts — WebhookVerifier using @suaveplan/crypto-hash HMAC + @suaveplan/crypto-utils constantTimeEqual; injectable now().
  • 2.6 src/receipt/receipt.ts — ReceiptGenerator + resetReceiptCounter + plain-text renderer; injectable now()/nextId.
  • 2.7 src/gateway/types.ts — PaymentGateway + GatewayChargeStatus + GatewayResult + GatewayCharge + ValidationResult + ChargeOptions.
  • 2.8 src/gateway/test.ts — TestGateway + resetChargeCounter; injectable now().
  • 2.9 src/gateway/stripe.ts — StripeGateway over injected FetchLike; typed-error wrap; status map.
  • 2.10 src/gateway/paypal.ts — PayPalGateway over injected FetchLike/now/btoa; OAuth token cache.
  • 2.11 src/fraud/fraud.ts — FraudDetector; injectable now().
  • 2.12 src/refund/refund.ts — RefundManager + resetRefundCounter; typed PaymentErrors; injectable now()/nextId.
  • 2.13 src/retry/retry.ts — PaymentRetrier; injectable random()/sleep().
  • 2.14 src/tax/tax.ts — TaxCalculator.
  • 2.15 src/tokenization/tokenization.ts — CardTokenizer; typed PaymentError(INVALID_CARD); injectable SubtleCrypto/now().
  • 2.16 src/reconciliation/reconciliation.ts — PaymentReconciliation; injectable now().
  • 2.17 src/index.ts — explicit named root barrel re-exporting every public symbol.
  • 2.18 Per-feature index.ts barrels — explicit named re-exports only.
  • 2.19 package.json at 0.1.0 with workspace:^ for @suaveplan/{error,events,money,crypto-hash,crypto-utils} and catalog:build for tslib; 16 subpath exports; sideEffects: false.
  • 2.20 vite.config.ts + tsconfig{,.lib}.json + vitest.config.ts + tests/setup/polyfills.ts.

3. Tests

  • 3.1 src/error-codes/error-codes.test.ts — registry shape; every code reachable from a factory; discriminants set / unset; cause passthrough on the three cause-bearing factories.
  • 3.2 src/hooks/hooks.test.ts — no-op pass-through; priority ordering; async handler support; unsubscribe idempotence; clear / count; singleton + shortcut.
  • 3.3 src/engine/engine.test.ts — every lifecycle method, every transition guard, every provider-error wrap (Error + non-Error throws), out-of-band emitters, canTransition matrix.
  • 3.4 src/webhook/webhook.test.ts — sign determinism; verify valid + expired + future + bad-sig + bad-length-sig + non-hex-sig + odd-length-sig + tampered-body + invalid-JSON + custom tolerance + SHA-512 + Date.now fallback.
  • 3.5 src/receipt/receipt.test.ts — structured generate, injected nextId + taxLabel, plain-text full + minimal render.
  • 3.6 src/gateway/test.test.ts — happy + delay + failure + missing charge + shouldFail mid-stream for capture / refund + validate matrix.
  • 3.7 src/gateway/stripe.test.ts — success / canceled / unknown / HTTP-error paths + capture (with/without amount) + refund (success + fallback) + get (with/without charges array) + validate matrix + baseUrl normalisation.
  • 3.8 src/gateway/paypal.test.ts — auth + create + token cache + token refresh + auth failure + order failure + custom baseUrl + capture (with/without amount) + refund (success + no-capture + PENDING) + get (aggregation + empty units + unknown status) + validate matrix + empty body.
  • 3.9 src/fraud/fraud.test.ts — clean allow, missing-customer flag, high-amount flag, velocity → block, between-thresholds review, score cap, reset, early-return when no customerId.
  • 3.10 src/refund/refund.test.ts — every typed error reachable, summary balances, fullyRefunded flag, byReason filter, canRefund matrix, injected nextId.
  • 3.11 src/retry/retry.test.ts — success / retry-success / non-retryable result / non-retryable thrown / exhaustion / non-Error wrap / default sleep / calculateDelay matrix (no-jitter / cap / +jitter / -jitter never-negative).
  • 3.12 src/tax/tax.test.ts — fallback default, region override, removeRate, exclusive, inclusive, exempt, empty input.
  • 3.13 src/tokenization/tokenization.test.ts — tokenize + custom prefix + bad Luhn + bad month + expired + Luhn matrix + brand matrix (8 brands + unknown).
  • 3.14 src/reconciliation/reconciliation.test.ts — matched + discrepancy + unmatched (both sides) + status normalisation + reconciledAt clock.
  • 3.15 Every it(...) carries { timeout: 5000 }.

4. Documentation

  • 4.1 Sibling .md for every implementation .ts (16 modules) — ≥200 words, basic + advanced examples, full API reference.
  • 4.2 README.md linking every co-located .md under ## Modules.

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 — green.
  • 5.3 bunx turbo test:coverage --filter=@suaveplan/payment — 100/100/100/100.
  • 5.4 bunx turbo build --filter=@suaveplan/payment — 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).
  • 6.3 Every error code in PAYMENT_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 — N/A (idempotency deferred).
  • 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/spec.md.
  • 7.2 Move openspec/changes/add-payment/ → openspec/archive/2026-05-17-add-payment/.
  • 7.3 Refresh MANIFEST.md via bun scripts/folder-reorg/generate-manifest.ts.
  • 7.4 Update STATUS.md to flip @suaveplan/payment from – → ✅.
  • 7.5 Update SUMMARY.md with the shipped surface.
  • 7.6 bunx markdownlint-cli2 --fix across touched markdown.