From 8a04416b0c7b322f48670a58cee6cd06f420eb25 Mon Sep 17 00:00:00 2001 From: Jakub Zych Date: Fri, 16 Oct 2026 16:47:08 +0200 Subject: [PATCH] test(18.1): UAT progress - 1, 5 passed; 2, 3 duplicates; boot-order gap found and fixed --- .../18.1-UAT.md | 46 +++++++++++++++---- 1 file changed, 36 insertions(+), 10 deletions(-) diff --git a/.planning/phases/18.1-payment-gateway-subscriptions/18.1-UAT.md b/.planning/phases/18.1-payment-gateway-subscriptions/18.1-UAT.md index 4155689..757482a 100644 --- a/.planning/phases/18.1-payment-gateway-subscriptions/18.1-UAT.md +++ b/.planning/phases/18.1-payment-gateway-subscriptions/18.1-UAT.md @@ -3,7 +3,7 @@ status: testing phase: 18.1-payment-gateway-subscriptions source: [18.1-VERIFICATION.md] started: 2026-10-14T19:30:26.848Z -updated: 2026-10-16T12:15:52.076Z +updated: 2026-10-16T15:30:00Z --- ## Current Test @@ -18,15 +18,18 @@ awaiting: user response ### 1. Decide on review findings CR-01 (out-of-order webhook snapshots) and CR-02 (checkout currency fallback to stripe_price_id) before the production cutover expected: Either accept them as PHP parity (D-21 and the frozen getStripePriceId fallback), recorded as overrides or a backlog item, or open a decimal gap-closure phase or quick task: CR-01 by retrieving the subscription from Stripe in the job (or an event.created watermark) and retrying ApplyDeleted on an unknown row; CR-02 by refusing a currency without its own entry in stripe_prices in api/subscription.go and in CreateCheckoutSession -result: [pending] +result: pass +note: CR-01 fixed in plan 18.1-07 (fresh-state retrieval, deletion retry), CR-02 in 18.1-08 (currency without own price refused); both covered by tests ### 2. Live Stripe test-mode checkout end to end: test-mode keys and the subscription webhook secret in pgstripe settings, `stripe listen --forward-to /webhook/stripe/subscriptions`, run checkout from the layer playground (PgPlans -> PgSubscribeButton) with the user subscriber expected: Stripe Checkout opens on the plan's price in the shown currency; after payment the webhook answers 200 'Webhook received', the job stores the subscription as active, golem15.pgsub.subscription.activated fires once, GET /subscription answers has_access true; observe whether customer.subscription.created arrives as incomplete followed by updated active (the CR-01 race window) -result: [pending] +result: skipped +reason: duplicate of test 6 (re-seeded after gap closure) ### 3. Billing-portal cancellation (D-21 cancel_at question): open the portal through PgManageSubscriptionButton, cancel the subscription, inspect the delivered customer.subscription.updated expected: If Stripe sends cancel_at_period_end: true, the row gets cancel_at_period_end true and PgMySubscription shows the will-cancel notice. If it sends only cancel_at (newer API versions), the row keeps cancel_at_period_end false and the cancellation is invisible; that would need a follow-up mapping -result: [pending] +result: skipped +reason: duplicate of test 7 (re-seeded after gap closure) ### 4. Browser pass through the admin screens and the layer components expected: Taglist chips (Enter, comma, remove, suggestions, read-only) on the plan form; flat drag reorder of plans writes sort_order; bulk sync_to_stripe and toolbar sync_all_to_stripe toasts with per-plan failures; Subscriptions list filters and the preview subscriber partial; the layer's plans table, subscribe redirect, my-subscription cancel through PgConfirm, portal redirect; press Back from Stripe Checkout and check whether the subscribe button is stuck on 'Subscribing...' (review WR-07, unfixed in app/utils/subscribe.ts) @@ -34,7 +37,8 @@ result: [pending] ### 5. Disposition of the re-review warnings (18.1-REVIEW.md, 2026-10-16; 18.1-REVIEW-DISPOSITION.md lists all open) before the Horoskopia cutover expected: Each of WR-01 to WR-07 is accepted (backlog item or deferred-items entry) or scheduled as a quick task or decimal phase. The money- and listener-relevant ones: WR-02 SubscriptionCanceled fires twice in the deleted-before-created sequence (ordering_test.go never counts canceled); WR-01 Service.Cancel race; WR-03 concurrent plan syncs can create duplicate Stripe products (row lock lost with Detached); WR-04 unpaid open Checkout Sessions not refused; WR-06 checkout bills the last-synced amount, not the shown one; WR-05 gbp/cad/aud/chf plans become unbuyable after a sync; WR-07 incomplete blocks checkout for about 23 h -result: [pending] +result: pass +note: all seven fixed in quick task 261016-myi (pgsub 2c9e5ef, pgstripe 2e44508); WR-02 now fires canceled once (deviation from PHP) ### 6. Live Stripe test-mode checkout end to end: test-mode keys and the subscription webhook secret in pgstripe settings, `stripe listen --forward-to /webhook/stripe/subscriptions`, checkout from the layer playground (PgPlans -> PgSubscribeButton) with the user subscriber expected: Checkout opens on the plan's price in the shown currency; after payment the webhook answers 200 'Webhook received'; the job logs source=stripe (fresh retrieval, not snapshot), stores the subscription active; golem15.pgsub.subscription.activated fires once even when created(incomplete) and updated(active) arrive together; GET /subscription answers has_access true. A second Subscribe answers 409 @@ -44,13 +48,35 @@ result: [pending] expected: If Stripe reports cancel_at_period_end true, the row gets it and PgMySubscription shows the will-cancel notice. If it reports only cancel_at, the row keeps cancel_at_period_end false and the cancellation is invisible; that needs a follow-up mapping result: [pending] +### 8. pgsub boots in an application built with `summer build` +expected: A summer-built app with pgsub and pgstripe runs migrate, serve and admin:create +result: issue +reported: "Found while setting up the UAT demo app: every command fails with 'party: boot golem15.paymentgatewaysubscriptions: ... boot service: database is not published' (boot.go bootService looks up *gorm.DB during Boot; generated main.go activates plugins before the database is published)" +severity: blocker + ## Summary -total: 7 -passed: 0 -issues: 0 -pending: 7 -skipped: 0 +total: 8 +passed: 2 +issues: 1 +pending: 3 +skipped: 2 blocked: 0 ## Gaps + +- gap_id: G-18.1-8 + truth: "A summer-built app with pgsub boots: migrate, serve and admin:create run" + status: resolved + resolved_by: quick 261016-myi (pgsub ab46d6f, TestBootBeforeDatabase) + resolved_at: 2026-10-16 + reason: "Demo app setup: boot service: database is not published" + severity: blocker + test: 8 + root_cause: "sm-paymentgatewaysubscriptions-plugin boot.go bootService requires *gorm.DB at Boot; internal/build main.go runs party.Activate before commands open the database; test hosts publish the DB before activation so tests miss it" + artifacts: + - path: "../sm-paymentgatewaysubscriptions-plugin/boot.go" + issue: "app.Lookup[*gorm.DB] at Boot" + missing: + - "Build the service in lagoon.OnDatabase; test with plugins activated before the DB is published" + debug_session: ""