Skip to content

release: the mint chain runs end to end against the real Stripe test API - #239

Merged
mahmutkaya merged 1 commit into
mainfrom
develop
Sep 5, 2026
Merged

mahmutkaya merged 1 commit into
mainfrom
develop

Conversation

@mahmutkaya

Copy link
Copy Markdown
Contributor

Release — the mint chain runs end to end against the real Stripe test API

One commit (#238). Test coverage plus one output-format change.

The gap this closes. mintForProposal -> createExpressAccount -> recordConnectAccount -> payments link
was unit-tested and mutation-tested, and every Stripe call probed by hand, but the chain had never executed
in one piece in any environment
sofra-staging cannot rehearse it (no PROVISION_GITHUB_TOKEN). E8 would
have been its first run, on a real restaurant.

tests/e2e/connect-mint.spec.ts runs it against the REAL Stripe test API and the suite's throwaway Postgres.
Green standalone and inside a full unmocked run (83/83, including the real Mollie first payment).

What it proves, measured rather than asserted

  • Locale-freedom of the stored link — proven by fetching it with accept-language: fr and de and
    getting two different middleware redirects, not by inspecting a string.
  • Idempotency in both forms — a second proposal reuses the account, and after deleting the row (the
    crash window the table exists for) the next call recovers the same acct_ from the idempotency key
    rather than minting a twin. Stripe's own list, filtered on metadata[sofra_tenant], confirms one tenant one
    account — which the unique slug column cannot see.
  • EUR refused with no network call, proven by holding a deliberately broken key across two calls: CHF came
    back with Stripe's 401 (instrument awake), EUR came back with the country refusal instead.

Cleanup inventories the database and Stripe, not what a test remembered, and asserts deleted: true then
GET -> 403. Guards mirror billing-mollie.spec.ts: live keys hard-refused, and with no key the file skips
with a stated reason
— CI shard 1 reported "4 skipped, 40 passed", so the skip path is exercised.

One production-adjacent change

prisma/schema.prisma sets moduleFormat = "cjs". The generator was emitting an ESM-only client
(import.meta.url) into a package declaring no type, so only a bundler could load lib/db.tsthe real
reason this chain had never been exercisable outside a browser request.
Output format only:
lib/generated/ is gitignored and rebuilt on every build. Proven by the full 83/83 suite and by CI's build,
prisma drift check and both Playwright shards.

Sonar: gate OK, 0 open issues; three typescript:S1607 transitioned to ACCEPTED with a rationale, the same
triage billing-mollie.spec.ts:97 already carries.

…e test API (#238)

`mintForProposal -> createExpressAccount -> recordConnectAccount -> the fields a
registry entry carries` was unit- and mutation-tested and each Stripe call had
been probed by hand, but the CHAIN had never executed in one piece anywhere:
staging cannot rehearse it (`provisioningConfigured()` is
`Boolean(PROVISION_GITHUB_TOKEN)` and that variable is absent there), so the
first run of the hand-offs would have been a real restaurant's account.

tests/e2e/connect-mint.spec.ts runs everything below `openProvisioningPr`
against the REAL Stripe API on an `sk_test_` key and the suite's throwaway
Postgres. Nothing is mocked (CLAUDE.md §7). It asserts the minted `acct_`, the
locale-free `payments_link_url:` (and drives the middleware in French and in
German to prove one stored URL serves both), the StripeConnectAccount row, what
Stripe itself holds, that a cash-only tenant mints nothing, and that EUR is
refused BEFORE the call — proven with a deliberately broken key whose 401 the
CHF control does surface.

The assertion the file exists for is idempotency, in both forms: a re-run reads
our own row, and a run whose row is DELETED (the crash between the Stripe POST
and the write) recovers the SAME account from the idempotency key rather than
minting a twin. Stripe's own account list, filtered on `metadata[sofra_tenant]`,
is the only oracle that can see that failure — the unique slug column cannot.

Cleanup is asserted, not best-effort: every account is deleted (`deleted: true`,
then GET -> 403) from an inventory taken from the database AND from Stripe, so
an account created by a test that then failed is still removed.

Guards mirror billing-mollie.spec.ts: the suite and CI refuse anything but
`sk_test_`, and with no key the spec SKIPS with a stated reason.

prisma/schema.prisma: `moduleFormat = "cjs"`. The generator was emitting an
ESM-only client (`import.meta.url`) into a package that declares no `type`, so
only a bundler could load `lib/db.ts` — which is why this chain had no way to be
exercised outside a browser request. Output format only; lib/generated/ is
gitignored and rebuilt on every build.

Measured: the full unmocked suite is 83/83 green on this change (including the
real Mollie first payment), and the Stripe test platform holds no `e2e-` account
afterwards.
@sonarqubecloud

sonarqubecloud Bot commented Sep 5, 2026

Copy link
Copy Markdown

@mahmutkaya
mahmutkaya merged commit 10546c6 into main Sep 5, 2026
37 of 40 checks 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