feat: allow building a catalogue before Stripe is configured - #85
Open
jsnapoli1 wants to merge 1 commit into
Open
feat: allow building a catalogue before Stripe is configured#85jsnapoli1 wants to merge 1 commit into
jsnapoli1 wants to merge 1 commit into
Conversation
Creating a product with no STRIPE_SECRET_KEY set failed with a 500:
{"error":"Neither apiKey nor config.authenticator provided"}
POST /api/admin/products syncs to Stripe before writing to KV, and the
Stripe client throws on construction with an empty key. So a store could
not be stocked, previewed, or demoed until payment credentials existed —
even though building a catalogue usually comes first.
StripeService already had the mechanism for this in isLocalNoNetwork,
which skips remote sync and returns stub ids while KV writes continue.
This generalises that to "no key configured" via skipsRemoteSync, and
adds the pieces needed to make it safe on a live store:
- Product create/update/archive and price create/archive no-op, writing
placeholder ids (prod_unlinked, price_unlinked).
- Both checkout paths refuse with 503 "This store is not accepting
payments yet." Taking money must not degrade quietly: there is no
account to charge and the placeholder ids do not exist in Stripe.
- GET /api/payments-status reports whether payments are live, so the
storefront can hide Buy buttons. It exposes only presence, never the
key.
- The admin panel shows a banner in catalogue-only mode.
- Saving an unlinked product once a key is configured creates it in
Stripe for real, rather than updating an id that never existed there,
and writes the real ids back to KV.
- validateEnv no longer requires STRIPE_SECRET_KEY, which otherwise
reports a store as invalid when it is merely not selling yet.
Adds tests/integration/catalogue-only.test.js covering all five
behaviours. Full suite: 283 passing.
Claude-Session: https://claude.ai/code/session_015XLFFfHWNeazSuz6UcsQ4C
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Creating a product with no
STRIPE_SECRET_KEYset fails with a 500:{"error":"Neither apiKey nor config.authenticator provided","status":500}POST /api/admin/productssyncs to Stripe before writing to KV, andnew Stripe(undefined)throws on construction. So a store cannot be stocked, previewed, or demoed until payment credentials exist — even though building a catalogue usually comes first, and Stripe onboarding (business details, bank account) can take days.Approach
StripeServicealready had the mechanism for this inisLocalNoNetwork, which skips remote sync and returns stub ids while KV writes continue. It was gated to a dev-only sentinel. This generalises it to "no key configured" via askipsRemoteSyncgetter, then adds what's needed to make it safe on a live store.Product writes degrade; payments do not. That asymmetry is the core of the design — a store that silently accepted uncharged orders would be worse than one that fails to start.
Changes
prod_unlinked,price_unlinked).503 This store is not accepting payments yet.There is no account to charge, and the placeholder ids don't exist in Stripe.GET /api/payments-statusreports whether payments are live, so a storefront can hide Buy buttons. Exposes only presence, never the key.validateEnvno longer requiresSTRIPE_SECRET_KEY, which otherwise reports a store as invalid when it's merely not selling yet.docs/STRIPE.md.Verification
Tests — adds
tests/integration/catalogue-only.test.js(5 cases: status reporting both ways, product create without Stripe, checkout refusal, backfill-on-save).npm run lint— 0 errors (10 pre-existing warnings in untouched files).npm run harness:docspasses.Live Cloudflare Workers deployment, no
STRIPE_SECRET_KEYset:Notes
The
sk_test_local_no_networksentinel keeps its existing behaviour and its distinct log message; catalogue-only mode is a separate condition that happens to share the skip path.Depends on nothing, but stacks cleanly with #84 (unrelated admin crash fix).
https://claude.ai/code/session_015XLFFfHWNeazSuz6UcsQ4C