Skip to content

feat(adapters): stripe-style full API coverage — disputes, billing, checkout, connect - #53

Merged
deblasis merged 4 commits into
mainfrom
feat/stripe-full-coverage
Aug 16, 2026
Merged

feat(adapters): stripe-style full API coverage — disputes, billing, checkout, connect#53
deblasis merged 4 commits into
mainfrom
feat/stripe-full-coverage

Conversation

@deblasis

Copy link
Copy Markdown
Contributor

Closes the stripe-style adapter's gap against the real Stripe API: 48 → 158 endpoints, 15 → 32 collections.

What's new

  • Test Clocks/v1/test_clocks (+advance) and the real-path /v1/test_helpers/test_clocks aliases. A KV time offset drives every adapter timestamp through lib._now(), making subscription renewals, dispute settlement, capability activation and payout lifecycles deterministic without sleeps.
  • Disputes — dispute test cards (fraudulent / product_not_received) trigger on charge success; needs_response → under_review → won/lost derive-on-read state machine; all 27 real evidence fields; submit/close; funds withdrawn and reinstated through the ledger; full charge.dispute.* event set.
  • Balance transactions — real ledger across charge (2.9%+30¢ fee), refund, refund_failure, payout, transfer, transfer_reversal, application_fee(+refund), dispute, dispute_reversal; account-scoped; filtered lists + retrieval.
  • Billing suite — products, prices, subscriptions (clock-driven renewal + auto-charge, past_due on decline), subscription items, usage records (metered), invoices (finalize/pay/void/uncollectible/send/lines/upcoming), invoice items, credit notes (issuing real refunds), coupons, promotion codes, tax rates (exclusive + inclusive).
  • Checkout Sessions — payment/subscription/setup modes; hosted /c/pay/{id} completion page with {CHECKOUT_SESSION_ID} redirect substitution; decline injection via payment_method; expire; line items.
  • SetupIntents — confirm/cancel with SCA challenge and decline behavior.
  • Webhook endpoints — CRUD + registration-gated delivery by enabled_events (events always recorded in /v1/events).
  • Connect depth — persons, capabilities (pending→active via clock), external bank accounts (last4 only), application fees + refunds, login links, transfer partial reversals, payout lifecycle (pending→in_transit→paid) + cancel with funds return.
  • Refunds completion — cancel (failure_reason + refund_failure ledger row), list filters, balance_transaction linkage.
  • Engine lint — provider-ID heuristic now requires a digit in the suffix (file_links is API surface, not an id); regression tests added.

Gates

parse guard, QC boot, all Stripe tests, full go test ./..., just lint-adapters (all 94 adapters), gofmt, vet — all green.

Issues: stunt-mha

…heckout, connect

Close the gap between the stripe-style adapter and the real Stripe API
surface (48 -> 158 endpoints, 15 -> 32 collections):

- Test Clocks: /v1/test_clocks(+advance) and the real-path
  /v1/test_helpers/test_clocks aliases; KV time offset drives every
  timestamp via lib _now(), so billing cycles, dispute settlement and
  payout lifecycles are deterministic and assertable without sleeps
- Disputes: test-card triggered (fraudulent / product_not_received),
  needs_response -> under_review -> won/lost derive-on-read machine,
  27 real evidence fields, submit/close, funds withdrawn/reinstated
  through the ledger, full charge.dispute.* event set
- Balance transactions: real ledger (charge incl. 2.9%+30c fee, refund,
  refund_failure, payout, transfer, transfer_reversal, application_fee,
  application_fee_refund, dispute, dispute_reversal) with account
  scoping, filters and retrieval
- Billing: products, prices, subscriptions (renewal + auto-charge via
  clock, past_due on decline), subscription items, usage records,
  invoices (finalize/pay/void/uncollectible/send/lines/upcoming),
  invoice items, credit notes (with real refunds), coupons, promotion
  codes, tax rates (exclusive + inclusive)
- Checkout Sessions: payment/subscription/setup modes, hosted /c/pay
  completion page with {CHECKOUT_SESSION_ID} redirect substitution,
  decline via payment_method param, expire, line items
- SetupIntents: confirm/cancel with SCA challenge + decline behavior
- Webhook endpoints: CRUD + registration-gated delivery per
  enabled_events (recorded in /v1/events either way)
- Connect: persons, capabilities (pending -> active), external bank
  accounts (last4 only), application fees + refunds, login links,
  transfer partial reversals (trr_*), payout lifecycle
  (pending -> in_transit -> paid) + cancel with funds return
- Refunds: cancel (failure_reason + refund_failure ledger row),
  charge/payment_intent list filters, balance_transaction linkage
- Engine lint: provider-ID heuristic now requires a digit in the
  suffix so real API names (file_links) are not flagged; regression
  tests added
Majors:
- _refunded_total now excludes canceled refunds (a canceled refund no
  longer locks the charge-level /refund route or credit notes out of the
  remaining balance); refunds.star local twin deleted
- concurrency_key added to 5 read-modify-write routes (transfer
  reversals, PM attach/detach, customer + account update)
- setup-mode checkout sessions keep payment_status no_payment_required
  through completion (real Stripe reserves paid for funds received)
- invoice lines render in a real list envelope (object/data/has_more/
  url) incl. the upcoming preview — typed SDKs read invoice.lines.data
- application_fee.created is now emitted when a charge records its fee

Minors:
- _bad_body + _coupon_public hoisted into lib.star (14 and 2 identical
  local twins collapsed)
- dispute ids dp_* -> du_* matching real Stripe
- 404 messages quote the id (No such charge: 'ch_1'); hand-built 404s
  collapsed onto _not_found; starting_after message quoted too
- Idempotency-Key honored on POST transfers/payouts/files/
  webhook_endpoints
- _dispute_submit docstring matches behavior; stale digit-run invariant
  comment corrected
RFC3339 truncation made a now+1s schedule effectively 0-1s out, so the
'before send' read could already see it sent (CI flake). Schedule 2-3s
out on a rounded-up boundary and poll to the sent transition instead of
sleeping past a guessed deadline.
@deblasis
deblasis merged commit 8caf4dd into main Aug 16, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant