From 6ae1c1c07763105f272e94b788980b1b3b9c8931 Mon Sep 17 00:00:00 2001 From: Jakub Zych Date: Fri, 16 Oct 2026 17:02:58 +0200 Subject: [PATCH] test(18.1): complete UAT - 3 passed, 3 issues (2 resolved by gap closure pending) --- .../18.1-UAT.md | 55 ++++++++++++++++--- 1 file changed, 48 insertions(+), 7 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 757482a0..5bf0ca07 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-16T15:30:00Z +updated: 2026-10-16T15:20:00Z --- ## Current Test @@ -33,7 +33,9 @@ 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) -result: [pending] +result: issue +reported: "Taglist pass; reorder pass; sync actions pass; playground subscribe, Back from Checkout and 409 pass. Subscriptions list: shows subscriber ID, expected some sort of field: type: relation select: email so we could easily identify subscriber. Otherwise works. Cancel through PgConfirm not run (blocked by test 7)." +severity: minor ### 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 @@ -42,11 +44,14 @@ note: all seven fixed in quick task 261016-myi (pgsub 2c9e5ef, pgstripe 2e44508) ### 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 -result: [pending] +result: pass +note: source=stripe logged, activated fired once, second subscribe refused ### 7. Billing-portal cancellation (D-21 cancel_at question): open the portal through PgManageSubscriptionButton, cancel the subscription, inspect the delivered customer.subscription.updated and the retrieved subscription 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] +result: issue +reported: "Fail. Subscription canceled on Stripe, playground still showing 'Days until renewal 30'" +severity: major ### 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 @@ -57,9 +62,9 @@ severity: blocker ## Summary total: 8 -passed: 2 -issues: 1 -pending: 3 +passed: 3 +issues: 3 +pending: 0 skipped: 2 blocked: 0 @@ -80,3 +85,39 @@ blocked: 0 missing: - "Build the service in lagoon.OnDatabase; test with plugins activated before the DB is published" debug_session: "" + +- gap_id: G-18.1-4 + truth: "The admin subscriptions list and form identify the subscriber by a readable value (e-mail / display name), not only type and id" + status: failed + reason: "User reported: Shows subscriber ID, expected some sort of field: type: relation select: email so we could easily identify subscriber" + severity: minor + test: 4 + root_cause: "models/subscription/columns.yaml and fields.yaml render subscriber_type and subscriber_id only; PHP's subscriber_display_name accessor was deliberately dropped. The subscriber registry (contracts.SubscriberResolver) can already resolve display data (used by the _subscription_subscriber header partial)" + artifacts: + - path: "../sm-paymentgatewaysubscriptions-plugin/models/subscription/columns.yaml" + issue: "no subscriber display column" + - path: "../sm-paymentgatewaysubscriptions-plugin/models/subscription/fields.yaml" + issue: "subscriber shown as type + id" + missing: + - "A subscriber column (e-mail / display name resolved through the subscriber registry, batched for the list page) on the list, and the same value on the form; searchable by e-mail if feasible" + debug_session: "" + +- gap_id: G-18.1-7 + truth: "A cancellation in the Stripe billing portal shows as will-cancel (cancel_at_period_end true) on the row and in PgMySubscription" + status: failed + reason: "User reported: Subscription canceled on Stripe, playground still showing 'Days until renewal 30'" + severity: major + test: 7 + root_cause: "On API 2026-09-30.endive the portal cancel returns cancel_at_period_end=false with cancel_at= and canceled_at set (verified on sub_1URCbD4Ba6xZslcbFdpiwvHX). pgstripe maps only CancelAtPeriodEnd (subscriptions/decode.go:165, job.go:295, gateway.go:422), so the row keeps false and the layer shows a renewing subscription; canceled_at is stored on an active row" + artifacts: + - path: "../sm-pgstripe-plugin/subscriptions/decode.go" + issue: "cancel_at not decoded/mapped" + - path: "../sm-pgstripe-plugin/subscriptions/job.go" + issue: "fresh-state mapping ignores cancel_at" + - path: "../sm-pgstripe-plugin/subscriptions/gateway.go" + issue: "RetrieveSubscription mapping ignores cancel_at" + missing: + - "Map a pending cancellation: cancel_at_period_end = s.CancelAtPeriodEnd || (s.CancelAt set while active/trialing), in snapshot and fresh paths; un-cancel (cancel_at cleared) maps back to false so reactivated fires" + - "Tests for both payload shapes (cancel_at_period_end and cancel_at-only) and for un-cancel; amend D-21 note" + - "Re-run UAT 7 and the site-side cancel (test 4 part E) in the demo" + debug_session: ""