Skip to content

feat: allow building a catalogue before Stripe is configured - #85

Open
jsnapoli1 wants to merge 1 commit into
AJFrio:mainfrom
jsnapoli1:feat/catalogue-only-without-stripe
Open

feat: allow building a catalogue before Stripe is configured#85
jsnapoli1 wants to merge 1 commit into
AJFrio:mainfrom
jsnapoli1:feat/catalogue-only-without-stripe

Conversation

@jsnapoli1

Copy link
Copy Markdown

Problem

Creating a product with no STRIPE_SECRET_KEY set fails with a 500:

{"error":"Neither apiKey nor config.authenticator provided","status":500}

POST /api/admin/products syncs to Stripe before writing to KV, and new 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

StripeService already had the mechanism for this in isLocalNoNetwork, 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 a skipsRemoteSync getter, 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

  • Product create/update/archive and price create/archive no-op when unconfigured, writing placeholder ids (prod_unlinked, price_unlinked).
  • Both checkout paths refuse with 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-status reports whether payments are live, so a storefront can hide Buy buttons. Exposes only presence, never the key.
  • The admin panel shows a banner in catalogue-only mode.
  • Backfill: saving an unlinked product once a key is configured creates it in Stripe 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's merely not selling yet.
  • Documented in 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).

Test Files  24 passed (24)
     Tests  283 passed (283)

npm run lint — 0 errors (10 pre-existing warnings in untouched files). npm run harness:docs passes.

Live Cloudflare Workers deployment, no STRIPE_SECRET_KEY set:

GET  /api/payments-status        → {"paymentsEnabled":false}
POST /api/admin/products         → 201  (previously 500)
                                   stripeProductId: "prod_unlinked"
POST /api/create-checkout-session → 503  {"error":"This store is not accepting payments yet."}

Notes

The sk_test_local_no_network sentinel 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

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
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