diff --git a/.planning/phases/18.1-payment-gateway-subscriptions/18.1-CONTEXT.md b/.planning/phases/18.1-payment-gateway-subscriptions/18.1-CONTEXT.md index 30d827c..c29f64f 100644 --- a/.planning/phases/18.1-payment-gateway-subscriptions/18.1-CONTEXT.md +++ b/.planning/phases/18.1-payment-gateway-subscriptions/18.1-CONTEXT.md @@ -65,6 +65,7 @@ Research (`18.1-RESEARCH.md` ยง Premise Shifts S-1..S-10) found premises that no - **D-19 (S-5):** The hard-coded `metadata.app = 'queststream'` becomes a config key on the Stripe subscriptions plugin, empty by default (write nothing, filter nothing). Horoskopia's cutover sets it to `queststream`. `billing_owner_id` is dropped from the generic gateway; apps add metadata through a checkout options map. - **D-20 (S-8, S-9):** The Stripe subscriptions subpackage is its own party plugin, `golem15.pgstripesubscriptions`, at module path `git.golem15.com/golem15/sm-pgstripe-plugin/subscriptions`. It gets its own importable or package-local Stripe fake; P18's root `stripefake_test.go` stays unchanged. - **D-21:** Behaviour defaults: keep PHP's `cancel_at_period_end` mapping (a manual test-mode check decides whether `cancel_at` from the billing portal also needs handling); out-of-order events behave as PHP does; the job reads both pre-basil and basil payload shapes; customer `GET /subscription` returns the latest subscription with `has_access` and `in_grace_period` flags. +- **D-21 amendment (2026-10-14, gap closure 18.1-07, user decision on verification human item 1):** out-of-order events no longer behave as PHP; created and updated events apply the subscription Stripe holds, serialised per subscription, and a deletion before its subscription is stored is retried. D-21's other defaults are unchanged. - **D-22 (plan split, 6 plans):** (1) framework: cabana flat reorder + `taglist`; (2) pgsub core tracer in the new repo (created with `tea repos create --owner golem15`); (3) pgstripe secret columns + import mapping + `subscriptions` plugin (gateway, both webhook routes, River job, host test); (4) pgsub admin screens + customer API; (5) `vue-paymentgateway-layer` pieces (tag `v0.2.0` only on go-ahead); (6) unit tests across all repos + `scripts/check-phase18.1.sh`. Plan 2's repo is committed before plan 3's `go.mod` points at it. No push, tag or deploy without the user's go-ahead. ### Claude's Discretion diff --git a/.planning/phases/18.1-payment-gateway-subscriptions/COVERAGE.md b/.planning/phases/18.1-payment-gateway-subscriptions/COVERAGE.md index 8e03d00..f6bd796 100644 --- a/.planning/phases/18.1-payment-gateway-subscriptions/COVERAGE.md +++ b/.planning/phases/18.1-payment-gateway-subscriptions/COVERAGE.md @@ -13,7 +13,7 @@ Scope: the Stripe Billing surface the frozen PHP `SubscriptionGateway` contract | checkout.sessions.retrieve (after the success redirect) | OPT-OUT | not in the frozen PHP contract: activation comes from the signed customer.subscription.created event | | billing_portal.sessions.create | INTEGRATE | | | billing_portal.configurations (create or update) | OPT-OUT | not in the frozen PHP contract: the portal is configured per account in the Stripe dashboard | -| subscriptions.retrieve (syncSubscription / reconcile) | INTEGRATE | | +| subscriptions.retrieve (syncSubscription / reconcile) | INTEGRATE | also the webhook job's fresh-state retrieval: created and updated events apply the subscription Stripe holds, not the event snapshot (CR-01, plan 18.1-07); a 404 falls back to the snapshot. `Service.SyncSubscription` uses it through `contracts.SubscriptionRetriever` and refreshes the plan (WR-06) | | subscriptions.update cancel_at_period_end true (cancel at period end) | INTEGRATE | | | subscriptions.cancel (cancel immediately) | INTEGRATE | | | subscriptions.update cancel_at (flexible-billing cancel enums) | OPT-OUT | D-21 keeps PHP's cancel_at_period_end mapping; a manual Stripe test-mode check at UAT decides a follow-up |