docs(stripe): document the app-tagged product/price checkout prerequisite (BUNYIP-175) #209

Merged
longjacksonle merged 1 commit from docs/BUNYIP-175-tagged-product-step into main 2026-06-24 03:31:30 +02:00

What

Closes the documentation gap that blocked a real subscribe during BUNYIP-175 verification. Companion to the merged #206 / #207 / #208.

Why

On a fresh test account the Subscribe button failed with 400 price_id: No active price configured and the web silently redirected back to /membership. The checkout handler only sells prices whose product carries metadata.app = STRIPE_APP_TAG (default app=bunyip); untagged products are filtered out by list_prices/list_products. Nothing documented that, so the wall is invisible.

Changes to dev-docs/stripe-test-mode.md

  • New required Step 3: create an app-tagged product + recurring price (admin Stripe UI auto-tags; or stripe products create -d metadata[app]=bunyip + stripe prices create --recurring).
  • Tier mapping demoted to optional Step 4, flagged as likely-retired per the M1 single-plan decision. Lifecycle becomes Step 5.
  • Corrected the grace-path note: a bare stripe trigger invoice.payment_failed invents its own customer (User not found), so it does nothing for a real member. Documented the customer-scoped, locally-signed event (real HMAC) that drives the cycle.
  • Replaced the stale "needs a live test account" section with the verified status.

Verified this session

Subscribe with 4242 -> subscription_status=active, price_locked=true. Grace cycle: signed invoice.payment_failed -> grace_period (+30d); invoice.payment_succeeded -> active.

Docs only; no code changes.

🤖 Generated with Claude Code

## What Closes the documentation gap that blocked a real subscribe during BUNYIP-175 verification. Companion to the merged #206 / #207 / #208. ## Why On a fresh test account the Subscribe button failed with `400 price_id: No active price configured` and the web silently redirected back to `/membership`. The checkout handler only sells prices whose product carries `metadata.app = STRIPE_APP_TAG` (default `app=bunyip`); untagged products are filtered out by `list_prices`/`list_products`. Nothing documented that, so the wall is invisible. ## Changes to `dev-docs/stripe-test-mode.md` - New required **Step 3**: create an app-tagged product + recurring price (admin Stripe UI auto-tags; or `stripe products create -d metadata[app]=bunyip` + `stripe prices create --recurring`). - Tier mapping demoted to optional **Step 4**, flagged as likely-retired per the M1 single-plan decision. Lifecycle becomes **Step 5**. - Corrected the grace-path note: a bare `stripe trigger invoice.payment_failed` invents its own customer (`User not found`), so it does nothing for a real member. Documented the customer-scoped, locally-signed event (real HMAC) that drives the cycle. - Replaced the stale "needs a live test account" section with the verified status. ## Verified this session Subscribe with `4242` -> `subscription_status=active`, `price_locked=true`. Grace cycle: signed `invoice.payment_failed` -> `grace_period` (+30d); `invoice.payment_succeeded` -> `active`. Docs only; no code changes. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
docs(stripe): document the app-tagged product/price checkout prerequisite (BUNYIP-175)
All checks were successful
E2E / Playwright against deployment (pull_request) Successful in 34s
Check / fmt + clippy + build + tests (pull_request) Successful in 4m34s
Create release / Create release from merged PR (pull_request) Has been skipped
8f69fc1298
Subscribing failed on a fresh test account with `400 price_id: No active price configured` and the web silently bounced back to /membership. Root cause: the checkout handler auto-selects the first active price whose product carries `metadata.app = STRIPE_APP_TAG` (default `app=bunyip`); untagged products are filtered out by `list_prices`/`list_products`. A new test account has no tagged product, so checkout has nothing to sell.

Add a required Step 3 that documents creating a tagged product + recurring price (admin Stripe UI, which auto-injects the tag, or the explicit `stripe products create -d metadata[app]=bunyip` + `stripe prices create --recurring` CLI form). Renumber the tier-mapping step to Step 4 and mark it optional, noting the M1 plan removes tiers. Renumber drive-the-lifecycle to Step 5.

Correct the grace-path note: a bare `stripe trigger invoice.payment_failed` invents its own customer, so the handler logs `User not found` and does nothing for a real member. Document the customer-scoped, locally-signed event (real HMAC over `<ts>.<payload>` with STRIPE_WEBHOOK_SECRET) that actually drives the grace cycle.

Replace the stale "still needs a live test account" section with the verified status: the 4242 checkout activation and the failed -> grace -> succeeded -> active cycle were both confirmed end to end on dev-sso.

#BUNYIP-175

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
longjacksonle scheduled this pull request to auto merge when all checks succeed 2026-06-24 03:27:24 +02:00
longjacksonle deleted branch docs/BUNYIP-175-tagged-product-step 2026-06-24 03:31:30 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
psa-systems/bunyip!209
No description provided.