Public: anyone can read this; the crew can change it.
Stripe is connected by pasting one key: checkout and the customer portal run over fetch, with nothing to set up in Stripe's dashboard #11163
Check · Review · Land · Live — Its check is running.
The admin can now connect Stripe by pasting one key, and the Stripe client for checkout, portal and reconcile is written and tested against a fake `fetch`. Nothing calls checkout, portal or reconcile yet, and nothing receives `/hooks/stripe`.
12 files · +582 −10
working checking now deploy 5dc2d00
Check running · 2 min · 422 of 2713 files · 2595 passed, 0 failedCheck of 5dc2d00checked against main at 8869849fast tier: running · full gate runs on land
Website spec: 19 findings (report only)
- /board http://127.0.0.1:38749/board answered 303 — https://specification.website/
- /notes http://127.0.0.1:38749/notes answered 303 — https://specification.website/
- /feed http://127.0.0.1:38749/feed answered 303 — https://specification.website/
- /review http://127.0.0.1:38749/review answered 303 — https://specification.website/
- /new http://127.0.0.1:38749/new answered 303 — https://specification.website/
- /pinned http://127.0.0.1:38749/pinned answered 303 — https://specification.website/
- /releases http://127.0.0.1:38749/releases answered 303 — https://specification.website/
- /repos http://127.0.0.1:38749/repos answered 303 — https://specification.website/
- /map http://127.0.0.1:38749/map answered 303 — https://specification.website/
- /system http://127.0.0.1:38749/system answered 303 — https://specification.website/
- /talk http://127.0.0.1:38749/talk answered 303 — https://specification.website/
- /flow http://127.0.0.1:38749/flow answered 303 — https://specification.website/
- /resilience http://127.0.0.1:38749/resilience answered 303 — https://specification.website/
- /settings http://127.0.0.1:38749/settings answered 303 — https://specification.website/
- /preview-admin/sample expected exactly one <h1>, found 2 — headings
- /preview-admin/sample/next expected exactly one <h1>, found 2 — headings
- /preview-admin/sample/bets expected exactly one <h1>, found 2 — headings
- /preview-admin/sample/waves expected exactly one <h1>, found 2 — headings
- /preview-admin/sample/milestones expected exactly one <h1>, found 2 — headings
The admin can now connect Stripe by pasting one key, and the Stripe client for checkout, portal and reconcile is written and tested against a fake fetch. Nothing calls checkout, portal or reconcile yet, and nothing receives /hooks/stripe.
tsc, scripts/gate.ts, the design lint and the billing, Stripe and cloud-gate tests all pass. I also ran the manifest and cloud test files. One of them, test/cloud-accounts-etag.test.ts, printed a route-timings Invalid Date warning. I did not rerun it after the fix below, so I can't say it passes. I did not run the full suite. The keep_plan tool wasn't available to me, so no plan is kept on the issue.
- Stripe client:
src/billing/stripe.tsisfetchand Web Crypto only. It hascheckout,portal,reconcile,addWebhookandremoveWebhook. - Wire format: every call pins
Stripe-Version(theSTRIPE_VERSIONconstant), sendsAuthorization: Bearer, and uses the bracketed form encoding. Each POST carries anIdempotency-Key:checkout-<order>andportal-<order>. The webhook registration key is derived from the endpoint URL, since there is no order id at that point. - Errors: they carry Stripe's status and error code only, never the key or the request body.
- Admin Billing page: a Provider section takes the key. The word sandbox or live appears beside
stripe, and the key is never shown. The key is sealed asSTRIPE_KEY_TESTorSTRIPE_KEY_LIVE, so the mode comes from the secret's name and viewing the page opens no secret. - Connect: the forge registers its webhook at
<origin>/hooks/stripewith the five events and seals the signing secret. - Key problems: a key Stripe rejects is not stored. A key without webhook permission is stored, told so in plain words, and the page offers a
whsec_field. Disconnect removes the endpoint and the sealed values. - Vendor declaration: I added vendor
stripeand usepaymentsto thecloud.jsonsets. The forge declares them for itself inFORGE_STRIPE, and every call checksmayUsefirst. - Docs:
docs/PROFIT.mdhas the five-line "Connect Stripe" steps, withdocs/features/billing.mdanddocs/CLOUD.mdupdated. - Tests:
test/stripe.test.tsasserts the exact checkout form body and headers, the status mapping, error redaction and the same-origin refusal. It also checks that the key never reaches the page, the secrets table or the events. - Changed test: I changed one assertion in
test/billing.test.ts. It said the Billing page must not contain "Stripe", which was only true while no processor existed.
Left out:
- The
/hooks/stripereceiver and signature verification. - The buttons or routes that call
checkout,portalandreconcile. - A terminal or MCP door for connecting.
The signing secret is sealed but nothing reads it yet.
Try: open /settings/billing as an admin, paste a sk_test_ key under Provider and press Connect.
🤖 Generated with Claude Code
Stripe can now be connected by pasting one key. This push fixes the failing check: src/apps/cloud.ts is imported now, so it comes off the unreached allow list in scripts/unreached-allow.json. The pull imports it through the new src/billing/stripe.ts and src/billing/connection.ts.
Of the three failures in the check log, only that one needed a fix:
- Unreached list:
test/unreached.test.tsnow passes locally. test/traffic-history.test.ts: passes locally; I changed nothing there.test/quotas-running.test.ts: passes locally in about 19 s. The check log shows the preview-limit test taking 420 s, so I read that as the shard timing out under load, not as a code fault. I did not find a cause for it, so it may fail again.
bun x tsc --noEmit is clean. I did not re-run scripts/gate.ts or scripts/design-lint.ts for this one-line change.
To try it: open /settings/billing as an admin, paste an sk_test_ key under Provider and press Connect. The word "sandbox" then shows beside stripe.
The admin can now connect Stripe by pasting one key, and the Stripe client for checkout, portal and reconcile is written and tested against a fake
fetch. Nothing calls checkout, portal or reconcile yet, and nothing receives/hooks/stripe.tsc,scripts/gate.ts, the design lint and the billing, Stripe and cloud-gate tests all pass. I also ran the manifest and cloud test files. One of them,test/cloud-accounts-etag.test.ts, printed a route-timingsInvalid Datewarning. I did not rerun it after the fix below, so I can't say it passes. I did not run the full suite. Thekeep_plantool wasn't available to me, so no plan is kept on the issue.src/billing/stripe.tsisfetchand Web Crypto only. It hascheckout,portal,reconcile,addWebhookandremoveWebhook.Stripe-Version(theSTRIPE_VERSIONconstant), sendsAuthorization: Bearer, and uses the bracketed form encoding. Each POST carries anIdempotency-Key:checkout-<order>andportal-<order>. The webhook registration key is derived from the endpoint URL, since there is no order id at that point.stripe, and the key is never shown. The key is sealed asSTRIPE_KEY_TESTorSTRIPE_KEY_LIVE, so the mode comes from the secret's name and viewing the page opens no secret.<origin>/hooks/stripewith the five events and seals the signing secret.whsec_field. Disconnect removes the endpoint and the sealed values.stripeand usepaymentsto thecloud.jsonsets. The forge declares them for itself inFORGE_STRIPE, and every call checksmayUsefirst.docs/PROFIT.mdhas the five-line "Connect Stripe" steps, withdocs/features/billing.mdanddocs/CLOUD.mdupdated.test/stripe.test.tsasserts the exact checkout form body and headers, the status mapping, error redaction and the same-origin refusal. It also checks that the key never reaches the page, the secrets table or the events.test/billing.test.ts. It said the Billing page must not contain "Stripe", which was only true while no processor existed.Left out:
/hooks/stripereceiver and signature verification.checkout,portalandreconcile.The signing secret is sealed but nothing reads it yet.
Try: open
/settings/billingas an admin, paste ask_test_key under Provider and press Connect.🤖 Generated with Claude Code
Closes #11136