docs(18.1-05): complete vue-paymentgateway-layer subscription pieces plan (release held)
This commit is contained in:
@@ -0,0 +1,337 @@
|
||||
---
|
||||
phase: 18.1-payment-gateway-subscriptions
|
||||
plan: 05
|
||||
subsystem: payments
|
||||
tags: [subscriptions, nuxt, layer, vue, i18n, stripe-checkout, billing-portal, node-test]
|
||||
|
||||
# Dependency graph
|
||||
requires:
|
||||
- phase: 18.1-04
|
||||
provides: the customer API under /_paymentgatewaysubscriptions/api/v1 with the "api-research" contract (money objects per currency, 404 {"error": "Subscription not found"} without a subscription)
|
||||
- phase: 18-payment-gateway
|
||||
provides: vue-paymentgateway-layer v0.1.0 (PgMoney, PaymentGatewayFetcher, errorStatus, formatMoney, PgConfirm, the paymentGatewayAuth hook, testing/load.ts)
|
||||
provides:
|
||||
- "vue-paymentgateway-layer: typed subscriptions client createSubscriptionsClient (plans, subscription, checkout, portal, cancel) with hasNoSubscription and price/status/interval helpers"
|
||||
- "flows createSubscribeFlow and createManageFlow (busy guard, one location.assign of an http(s) checkout_url or portal_url, status-to-copy mapping)"
|
||||
- "composables useSubscriptionsApi, usePlans (pg:subscriptions:plans), useSubscription (pg:subscriptions:current, 404 as null)"
|
||||
- "components PgPlans, PgSubscribeButton, PgMySubscription, PgManageSubscriptionButton"
|
||||
- "runtime config paymentgatewaysubscriptions.apiBase and public.paymentgatewaysubscriptions.apiBase; 41 pg.subscriptions.* keys in en and pl; README section Subscriptions; package version 0.2.0 (not tagged: reply hold)"
|
||||
affects: [18.1-06, consuming applications' pricing and account pages, scripts/check-phase18.1.sh]
|
||||
|
||||
# Actuals (#2632): chars/4 over the added lines of ac2b960..3dea9cd in vue-paymentgateway-layer
|
||||
actuals:
|
||||
tokens: 18765
|
||||
tasks: 3
|
||||
commits: 2
|
||||
commits: 2
|
||||
plan_head_before: ac2b96023f985ccaa2e8a571952fbc9535892c60
|
||||
plan_head_after: 3dea9cd8cf82d46a9317e4f120c7544384c68ca3
|
||||
|
||||
tech-stack:
|
||||
added: []
|
||||
patterns:
|
||||
- "Subscription flows in plain TS with an injected client and location (the checkout.ts pattern), so node --test drives them; components stay thin"
|
||||
- "A navigation target from an API answer is followed only when it is an absolute http(s) URL"
|
||||
- "A 404 that means 'none' becomes data null inside the useAsyncData handler, so a page tells 'nothing yet' from a failed load"
|
||||
|
||||
key-files:
|
||||
created:
|
||||
- ../vue-paymentgateway-layer/app/utils/subscriptionsClient.ts
|
||||
- ../vue-paymentgateway-layer/app/utils/subscribe.ts
|
||||
- ../vue-paymentgateway-layer/app/composables/useSubscriptionsApi.ts
|
||||
- ../vue-paymentgateway-layer/app/composables/usePlans.ts
|
||||
- ../vue-paymentgateway-layer/app/composables/useSubscription.ts
|
||||
- ../vue-paymentgateway-layer/app/components/Pg/Plans.vue
|
||||
- ../vue-paymentgateway-layer/app/components/Pg/SubscribeButton.vue
|
||||
- ../vue-paymentgateway-layer/app/components/Pg/MySubscription.vue
|
||||
- ../vue-paymentgateway-layer/app/components/Pg/ManageSubscriptionButton.vue
|
||||
- ../vue-paymentgateway-layer/.playground/app/pages/subscriptions/index.vue
|
||||
- ../vue-paymentgateway-layer/tests/subscriptions.test.ts
|
||||
- ../vue-paymentgateway-layer/tests/subscribe.test.ts
|
||||
- ../vue-paymentgateway-layer/tests/subscriptionComponents.test.ts
|
||||
modified:
|
||||
- ../vue-paymentgateway-layer/nuxt.config.ts
|
||||
- ../vue-paymentgateway-layer/i18n/locales/en.json
|
||||
- ../vue-paymentgateway-layer/i18n/locales/pl.json
|
||||
- ../vue-paymentgateway-layer/app/assets/css/pg-base.css
|
||||
- ../vue-paymentgateway-layer/package.json
|
||||
- ../vue-paymentgateway-layer/README.md
|
||||
- ../vue-paymentgateway-layer/tests/i18n.test.ts
|
||||
- .planning/phases/18.1-payment-gateway-subscriptions/deferred-items.md
|
||||
|
||||
key-decisions:
|
||||
- "Release decision at Task 3: human reply \"hold\"; no v0.2.0 tag and no push, plan 06's final push publishes the layer"
|
||||
- "Checkout and portal redirects follow only absolute http(s) URLs from the API answer; anything else is the generic error"
|
||||
- "A plan without a price in the chosen currency shows its first price, and the subscribe button sends that price's currency"
|
||||
- "429 maps to the existing pg.error.throttled; days until renewal is a label plus the number (no plural forms)"
|
||||
|
||||
patterns-established:
|
||||
- "Subscription component specs: SSR render with stubbed usePlans/useSubscription/useSubscriptionsApi and stubbed child components"
|
||||
|
||||
requirements-completed: [SC-3, D-13, D-14, D-21, D-22]
|
||||
|
||||
coverage:
|
||||
- id: D1
|
||||
description: "Typed subscriptions client: five routes with their methods and bodies, {data} unwrap, no redirect URL or id sent, 404 read as no subscription"
|
||||
requirement: D-14
|
||||
verification:
|
||||
- kind: unit
|
||||
ref: "tests/subscriptions.test.ts#subscriptions: every route hits its path with its method and body; #the client never sends a redirect URL, a price, a subscriber or a subscription id; #hasNoSubscription is a 404 only"
|
||||
status: pass
|
||||
human_judgment: false
|
||||
- id: D2
|
||||
description: "useSubscriptionsApi: server base with x-forwarded-for and Bearer during SSR, public base and Bearer only in the browser, no header without a token"
|
||||
requirement: D-14
|
||||
verification:
|
||||
- kind: unit
|
||||
ref: "tests/subscriptions.test.ts#subscriptions: on the server the composable ...; in the browser ...; without a token ..."
|
||||
status: pass
|
||||
human_judgment: false
|
||||
- id: D3
|
||||
description: "Subscribe and manage flows: one location.assign, busy kept, second click sends nothing, 401/404/409/422/429/502/503 mapped to copy, non-http(s) answers never followed, cancel resolves the updated subscription"
|
||||
requirement: D-21
|
||||
verification:
|
||||
- kind: unit
|
||||
ref: "tests/subscribe.test.ts (4 flow specs); tests/subscriptionComponents.test.ts#the manage flow ...; #the cancel flow ..."
|
||||
status: pass
|
||||
human_judgment: false
|
||||
- id: D4
|
||||
description: "PgPlans and PgMySubscription states: prices, features as text, free plan without button, filter, skeleton/error/empty; none, active, scheduled cancel, past_due grace, canceled, 401 login"
|
||||
requirement: D-14
|
||||
verification:
|
||||
- kind: unit
|
||||
ref: "tests/subscriptionComponents.test.ts (9 SSR specs); tests/subscribe.test.ts#PgPlans lists the plans with a working PgSubscribeButton per paid plan"
|
||||
status: pass
|
||||
human_judgment: false
|
||||
- id: D5
|
||||
description: "pg.subscriptions.* copy in en and pl with identical keys and placeholders, every status and interval labelled, every used key present"
|
||||
requirement: D-14
|
||||
verification:
|
||||
- kind: unit
|
||||
ref: "tests/i18n.test.ts#subscriptions: pl and en carry the same pg.subscriptions keys and placeholders; #every status and interval is labelled ..."
|
||||
status: pass
|
||||
human_judgment: false
|
||||
- id: D6
|
||||
description: "Playground prepares with the four components and the runtime config"
|
||||
requirement: D-14
|
||||
verification:
|
||||
- kind: other
|
||||
ref: "pnpm --dir ../vue-paymentgateway-layer run dev:prepare (Task 2 verify, VERIFY2_OK)"
|
||||
status: pass
|
||||
human_judgment: false
|
||||
- id: D7
|
||||
description: "Real browser flow against a running API and Stripe test mode: plans page look, Checkout and portal redirects, cancel confirm dialog, EN/PL copy reading well"
|
||||
requirement: SC-3
|
||||
verification: []
|
||||
human_judgment: true
|
||||
rationale: "The specs render on the server with stubbed composables; no automated browser test drives the components against a live API and Stripe"
|
||||
- id: D8
|
||||
description: "Release decision recorded: reply \"hold\", no tag, no push"
|
||||
requirement: D-22
|
||||
verification:
|
||||
- kind: other
|
||||
ref: "git -C ../vue-paymentgateway-layer ls-remote --tags origin v0.2.0 (empty); git log --oneline origin/main..main (38c8a74, 3dea9cd)"
|
||||
status: pass
|
||||
human_judgment: false
|
||||
|
||||
duration: 20min
|
||||
completed: 2026-10-14
|
||||
status: complete
|
||||
---
|
||||
|
||||
# Phase 18.1 Plan 05: vue-paymentgateway-layer subscription pieces Summary
|
||||
|
||||
**`vue-paymentgateway-layer` now has the subscription pieces, built on plan 04's "api-research" customer API:**
|
||||
- **Client:** `createSubscriptionsClient`, a typed client over the injected fetcher.
|
||||
- **Composables:** `useSubscriptionsApi`, `usePlans` and `useSubscription`.
|
||||
- **Components:** `PgPlans`, `PgSubscribeButton`, `PgMySubscription` (with cancel through PgConfirm) and `PgManageSubscriptionButton`.
|
||||
- **Redirects:** subscribe and manage send the browser to the Checkout or portal URL once, and only when it is an absolute http(s) URL.
|
||||
- **Docs and release:** 41 EN/PL `pg.subscriptions.*` keys, the README section and version 0.2.0.
|
||||
|
||||
The human replied "hold" at the release checkpoint. Nothing was tagged or pushed.
|
||||
|
||||
## Performance
|
||||
|
||||
- **Duration:** about 20 min. That is 11 min of execution up to the checkpoint, then the continuation.
|
||||
- **Started:** 2026-10-14T16:21:07Z
|
||||
- **Completed:** 2026-10-14T16:41Z
|
||||
- **Tasks:** 3 (2 implementation tasks, then the Task 3 release decision)
|
||||
- **Files:** 20 in the layer repository (+1611/-8), plus `deferred-items.md` in this phase directory
|
||||
|
||||
## Repository
|
||||
|
||||
- The commits are in `../vue-paymentgateway-layer`, on branch `main`, from `ac2b960` to `3dea9cd`.
|
||||
- `origin/main` is still `ac2b960`, and the tag `v0.2.0` does not exist on origin. The only tag is `v0.1.0` (`14d4522`).
|
||||
- `pnpm-lock.yaml` is unchanged (sha256 `bc48fe50…`), and `package.json` changed only its version field.
|
||||
- The backend the layer calls (`sm-paymentgatewaysubscriptions-plugin`) is at `b728762` locally and `aad4647` on origin, with no tags.
|
||||
|
||||
## Task Commits
|
||||
|
||||
| Task | Name | Commit | Repo |
|
||||
|------|------|--------|------|
|
||||
| 1 | Tracer: typed client, PgPlans and PgSubscribeButton with a one-time checkout redirect | `38c8a74` | vue-paymentgateway-layer |
|
||||
| 2 | PgMySubscription with cancel, PgManageSubscriptionButton, useSubscription, copy, playground, README and version 0.2.0 | `3dea9cd` | vue-paymentgateway-layer |
|
||||
| 3 | Release decision (checkpoint:decision, blocking-human) | none (reply "hold") | n/a |
|
||||
|
||||
**Plan metadata:** the docs commit that adds this SUMMARY and the deferred items, in the framework repo.
|
||||
|
||||
## Task 3: release sheet and reply
|
||||
|
||||
**Automated pre-checks:**
|
||||
- `git status --porcelain` was empty, and the branch was `main`.
|
||||
- `git fetch origin --tags` succeeded, and `git log HEAD..origin/main` was empty.
|
||||
- `git ls-remote --tags origin v0.2.0` was empty.
|
||||
- The verify printed `layer-release-sheet-ok`.
|
||||
|
||||
**What main would publish since v0.1.0:**
|
||||
- `ac2b960`: the 18-07 layer specs. This commit is already on `origin/main`; `v0.1.0` was one commit behind it.
|
||||
- `38c8a74`: Task 1.
|
||||
- `3dea9cd`: Task 2.
|
||||
|
||||
**New public surface:**
|
||||
- **Client:** `createSubscriptionsClient`, plus `hasNoSubscription`, `planPrice`, `subscriptionStatusKey`, `billingIntervalKey`, `SUBSCRIPTION_STATUSES` and `BILLING_INTERVALS`.
|
||||
- **Flows:** `createSubscribeFlow`, `createManageFlow`, `subscriptionErrorKey` and `isNavigableURL`.
|
||||
- **Composables:** `useSubscriptionsApi`, `usePlans` and `useSubscription`.
|
||||
- **Components:** `PgPlans`, `PgSubscribeButton`, `PgMySubscription` and `PgManageSubscriptionButton`.
|
||||
- **Runtime config:** `paymentgatewaysubscriptions.apiBase` and `public.paymentgatewaysubscriptions.apiBase`.
|
||||
- **Copy:** 41 `pg.subscriptions.*` keys.
|
||||
|
||||
Applications pin the layer by tag, so `v0.2.0` is what they will install. "hold" leaves plan 06's final push to publish it.
|
||||
|
||||
**Options:** tag-and-push, push-only, hold.
|
||||
|
||||
**Reply (verbatim):** "hold"
|
||||
|
||||
**Result:**
|
||||
- No tag and no push.
|
||||
- `git ls-remote --tags origin v0.2.0` is empty.
|
||||
- `git log --oneline origin/main..main` lists `3dea9cd` and `38c8a74`.
|
||||
- No hashes were pushed.
|
||||
|
||||
## Accomplishments
|
||||
|
||||
- **Client** (`app/utils/subscriptionsClient.ts`):
|
||||
- `plans()` calls GET `/plans` and unwraps `{data}`.
|
||||
- `subscription()` calls GET `/subscription`.
|
||||
- `checkout(planCode, currency?)` posts `{plan_code, currency?}`, leaving the currency out when it is absent.
|
||||
- `portal()` and `cancel()` post with no body.
|
||||
- It reuses `PgMoney`, `PaymentGatewayFetcher` and `errorStatus` from `client.ts`, with no duplicates.
|
||||
- `hasNoSubscription` is true for a 404, which is the "api-research" no-subscription answer.
|
||||
- **Flows** (`app/utils/subscribe.ts`):
|
||||
- `createSubscribeFlow` keeps a busy guard and calls `location.assign(checkout_url)` exactly once. The button stays busy while the browser leaves.
|
||||
- `createManageFlow.open()` does the same with `portal_url`; a 404 there shows `no_billing_account`.
|
||||
- `createManageFlow.cancel()` resolves the updated subscription, or null with the mapped error.
|
||||
- Error copy by status: 401 login, 409 already_subscribed, 422 unavailable, 429 `pg.error.throttled`, 502/503 provider, anything else generic.
|
||||
- **Composables:**
|
||||
- `useSubscriptionsApi` is the twin of `usePaymentGatewayApi`: the server base with forwarded `x-forwarded-for`, the public base in the browser, and the `paymentGatewayAuth` Bearer hook.
|
||||
- `usePlans` wraps `useAsyncData` with the key `pg:subscriptions:plans`.
|
||||
- `useSubscription` uses the key `pg:subscriptions:current` and turns the 404 into null.
|
||||
- **PgPlans:**
|
||||
- One card per plan: name, description, the price in the chosen currency through `formatMoney` with its interval label, the features as a text list, and a subscribe button for paid plans. A free plan shows the free label.
|
||||
- Props `currency` and `planCodes`; slot `#plan-actions`.
|
||||
- Skeleton cards while loading, the load error with Retry, and the empty copy.
|
||||
- **PgSubscribeButton:** disabled while busy, with an error line under it. On a 409 it also offers `PgManageSubscriptionButton`.
|
||||
- **PgMySubscription:**
|
||||
- Shows the plan name and the localized status with a tone bar.
|
||||
- Shows the period end as a locale date, the days until renewal and the trial end.
|
||||
- Shows the will-cancel notice with the date, the grace notice and the access line.
|
||||
- Offers Manage billing, and Cancel subscription through PgConfirm. Cancel shows only for an active or trialing subscription with no cancel scheduled; after a confirmed cancel the panel refreshes.
|
||||
- Without a subscription it shows the none state and a `plansTo` link. A 401 shows the login copy, and other failures show the load error with Retry. Slot `#none`.
|
||||
- **PgManageSubscriptionButton:** the portal redirect, with an error line under the button.
|
||||
- **Copy, config and docs:**
|
||||
- 41 `pg.subscriptions.*` keys in en and pl.
|
||||
- Runtime config with comments naming the `NUXT_*` variables; the existing `paymentgateway` keys are unchanged.
|
||||
- Playground page `/subscriptions`.
|
||||
- README: the Subscriptions section (backend requirement, auth, redirects, client methods table, helpers, composables, components table, error keys, overriding), the runtime config rows, the copy, the Testing table, and the install example on `#v0.2.0`. It names no consuming application.
|
||||
- `package.json` version 0.2.0.
|
||||
- Plans styles on the existing tokens in `pg-base.css`.
|
||||
|
||||
## Tests
|
||||
|
||||
- **Full layer suite:** 96 pass, 0 fail, 0 skipped. Of these, 27 are "subscriptions:" tests; 69 tests existed before this plan.
|
||||
- `tests/subscriptions.test.ts`: 8 tests.
|
||||
- `tests/subscribe.test.ts`: 5 tests, including the tracer render of PgPlans with the real PgSubscribeButton.
|
||||
- `tests/subscriptionComponents.test.ts`: 12 tests.
|
||||
- `tests/i18n.test.ts`: 2 new tests.
|
||||
- **Task 1 verify:** VERIFY1_OK, and still OK after Task 2.
|
||||
- **Task 2 verify:** VERIFY2_OK, including `nuxt prepare .playground`.
|
||||
- **Task 3 verify:** `layer-release-sheet-ok`.
|
||||
- **Tracer gate:** auto mode was off, `human_verify_mode` was end-of-phase and the verify was automated only, so the verify was re-run end to end before Task 2 began.
|
||||
- **Acceptance greps, all as required:**
|
||||
- `createSubscriptionsClient` is present, and `interface PgMoney` appears 0 times in the client.
|
||||
- 4 `paymentgatewaysubscriptions` lines in `nuxt.config.ts`.
|
||||
- `v-html` appears 0 times in all four components.
|
||||
- No `success_url`, `cancel_url` or `return_url` in the client.
|
||||
- 4 component files.
|
||||
- One `## Subscriptions` heading.
|
||||
- No consuming-application names in the README or `app/`.
|
||||
- `OrderPage.vue`, `Checkout.vue`, `client.ts` and `checkout.ts` are unchanged since `ac2b960`.
|
||||
- **Type check:** `tsc` over the layer reports no errors from the new code, only the existing Nuxt auto-import ones that the standalone tsconfig cannot resolve.
|
||||
- **Timezones:** the date fixtures use midday UTC. The suite passes from UTC-12 to UTC+12. Under UTC+13/+14 the two date assertions fail, and so does the existing order-list date spec, a limit that predates this plan.
|
||||
|
||||
## Decisions Made
|
||||
|
||||
- The release decision is the human's reply "hold", so nothing is tagged or pushed in this plan.
|
||||
- The redirect targets are the API's `checkout_url` and `portal_url` only, and only when they are absolute http(s) URLs.
|
||||
- The plans table never computes a price. It picks the money object for the chosen currency, or else the plan's first price, and the subscribe button sends the currency of the price it shows.
|
||||
- PgMySubscription includes cancel at the period end, as planned. Immediate cancel stays a service and admin capability.
|
||||
|
||||
## Deviations from Plan
|
||||
|
||||
### Auto-fixed issues and adaptations
|
||||
|
||||
1. **[Rule 3 - Blocking] pnpm dependency check after the version bump.**
|
||||
- **Found during:** Task 2 verify.
|
||||
- **Issue:** once `package.json` changed, `pnpm test` ran `pnpm install` and aborted with `ERR_PNPM_ABORTED_REMOVE_MODULES_DIR_NO_TTY`. `node_modules` had been installed against the store `/media/nvme/dev/golem15/summercms.io/summercms/.pnpm-store/v11`, but pnpm now resolves `/media/nvme/.pnpm-store/v11`, so it wanted to purge and reinstall.
|
||||
- **Fix:** `pnpm install --frozen-lockfile --offline --store-dir /media/nvme/dev/golem15/summercms.io/summercms/.pnpm-store`. The lockfile sha256 is unchanged, no package was added, and only local state changed; nothing was committed.
|
||||
- **Follow-up:** logged as a watch item in `deferred-items.md`.
|
||||
2. **[Rule 2 - Missing critical] Plans styles.**
|
||||
- **Issue:** the plans grid needed styles that the existing classes do not provide.
|
||||
- **Fix:** a "Subscriptions" block in `app/assets/css/pg-base.css` (`.pg-plans`, `.pg-plans__list`, `.pg-plan*`, `.pg-subscribe`) on the existing tokens only. The plan's file list did not include this file.
|
||||
- **Commit:** `38c8a74`.
|
||||
3. **[Rule 2 - Security, T-18.1-28] URL check before navigating.**
|
||||
- **Fix:** the flows assign `checkout_url` and `portal_url` only when `isNavigableURL` accepts them (absolute http(s)). A `javascript:`, `data:`, relative or scheme-relative answer gives the generic error and is never assigned.
|
||||
- **Verification:** specs in `tests/subscribe.test.ts` and `tests/subscriptionComponents.test.ts`.
|
||||
- **Commits:** `38c8a74`, `3dea9cd`.
|
||||
4. **Extra status mapping.** 429 maps to the existing `pg.error.throttled`. The plan listed 401, 409, 422 and 502/503, with everything else generic. The API has a 120-per-minute throttle bucket.
|
||||
5. **SubscribeButton changed in Task 2.** The 409 branch renders `PgManageSubscriptionButton`, which the D-21 truth requires. That component only exists from Task 2, so the change landed in `3dea9cd`.
|
||||
6. **Copy and helpers beyond the plan's list.**
|
||||
- Extra keys: `error.load`, `error.load_subscription`, `label`, `see_plans`, `trial_ends`, `will_cancel_soon`, `cancel.title`, `cancel.keep`.
|
||||
- `renews_in` is the label "Days until renewal", with the number in its own cell. This avoids plural forms, because the copy test bars vue-i18n's `|`.
|
||||
- Extra exported helpers: the status, interval and price helpers, `subscriptionErrorKey`, `isNavigableURL`, `FlowLocation` and `ManageFlow`.
|
||||
7. **Plan price fallback.** When the chosen currency has no price, a plan shows its first price, and the subscribe button sends that price's currency, so the visitor pays what they see.
|
||||
|
||||
**Total deviations:** 3 auto-fixes (1 Rule 3, 2 Rule 2) and 4 documented adaptations.
|
||||
**Impact on plan:** every behaviour the plan asks for is delivered. No dependency was added and the order pieces are unchanged.
|
||||
|
||||
## Threat Model Coverage
|
||||
|
||||
- **T-18.1-28 (open redirect):** only `checkout_url` and `portal_url` from the API answer, and only as absolute http(s). The client sends no redirect URL (acceptance grep).
|
||||
- **T-18.1-29 (token):** the token comes only from the app's `paymentGatewayAuth` hook, as `Authorization: Bearer`. Nothing is stored, and the SSR base is always runtime config.
|
||||
- **T-18.1-30 (XSS):** text interpolation only, with 0 `v-html`. A spec renders a plan name, description and feature containing markup as escaped text.
|
||||
- **T-18.1-31 (double submit):** the busy guard stays busy once redirecting. Specs cover a second click both while the request runs and after the redirect starts.
|
||||
- **T-18.1-SC (supply chain):** no npm package was added. The lockfile is unchanged since `ac2b960`, and `package.json` names no Stripe package.
|
||||
|
||||
## Issues Encountered
|
||||
|
||||
- The pnpm store mismatch is described under deviation 1.
|
||||
- `scripts/check-git-install.sh` in the layer targets `vue-journal-layer`. It predates this plan and is out of scope; it is logged in `deferred-items.md` for plan 06.
|
||||
|
||||
## Known Stubs
|
||||
|
||||
None.
|
||||
|
||||
## User Setup Required
|
||||
|
||||
None. An application that uses the subscription components serves plan 04's customer API. It sets `NUXT_PAYMENTGATEWAYSUBSCRIPTIONS_API_BASE` and `NUXT_PUBLIC_PAYMENTGATEWAYSUBSCRIPTIONS_API_BASE` when the defaults do not fit, and provides the `paymentGatewayAuth` hook.
|
||||
|
||||
## Next Phase Readiness
|
||||
|
||||
Plan 06 owns:
|
||||
- the unit tests and `scripts/check-phase18.1.sh`, which should require the three new layer spec files and their "subscriptions:" test names;
|
||||
- the pushes, including this layer's `main` (`38c8a74`, `3dea9cd`) and the `v0.2.0` tag on the human's go-ahead;
|
||||
- the two open items in `deferred-items.md`: the `reorder.flat` list schema and `check-git-install.sh`.
|
||||
|
||||
---
|
||||
*Phase: 18.1-payment-gateway-subscriptions*
|
||||
*Completed: 2026-10-14*
|
||||
@@ -7,3 +7,13 @@
|
||||
**Found during:** plan 18.1-04 Task 2 (TestAdminPlansSmoke/flat_reorder).
|
||||
**What:** `modules/cabana/list_schema.go` builds the localized `ListReorder` with the title and the partition only (around line 618), so `GET .../schema/list` answers `"reorder":{"title":...}` without `"flat":true` for a flat reorder page, although the compiled `ListReorder.Flat` is set and documented as part of the list schema (plan 18.1-01). The reorder page itself is unaffected: the SPA reads `flat` from `GET .../reorder` (`AdminReorderTree.Flat`), which answers it correctly.
|
||||
**Fix:** copy `Flat` into the localized `ListReorder` and add the assertion to `reorder_flat_test.go`'s HTTP path; a framework change for plan 18.1-06 or a quick task (out of scope for the plugin repository plan 04 commits to).
|
||||
- The layer's `scripts/check-git-install.sh` targets `vue-journal-layer`
|
||||
status: open
|
||||
**Found during:** plan 18.1-05 Task 3 (release sheet).
|
||||
**What:** `../vue-paymentgateway-layer/scripts/check-git-install.sh`, shipped since v0.1.0 and run by `pnpm run check:git-install <tag>`, was copied from the journal layer. `REPO_URL`, the scratch app's dependency name, `extends` and the messages (12 "journal" references) point at `vue-journal-layer`, and it expects `testing/expect-acme.txt`, which the payment gateway layer does not have. Running `pnpm run check:git-install v0.2.0` would check the wrong repository.
|
||||
**Fix:** for plan 18.1-06, point the script at `git.golem15.com/golem15/vue-paymentgateway-layer.git` and the package name `vue-paymentgateway-layer`, and replace the journal fixture check with a payment gateway build check. Run it after the `v0.2.0` tag exists.
|
||||
- Watch: pnpm store-dir mismatch in `vue-paymentgateway-layer`
|
||||
status: open
|
||||
**Found during:** plan 18.1-05 Task 2 verify.
|
||||
**What:** the layer's `node_modules` was installed against the store `/media/nvme/dev/golem15/summercms.io/summercms/.pnpm-store/v11`, but pnpm 11.3.0 now resolves `/media/nvme/.pnpm-store/v11`. After any `package.json` change, `pnpm test` runs `pnpm install` first and aborts without a TTY (`ERR_PNPM_ABORTED_REMOVE_MODULES_DIR_NO_TTY`). Plan 05 fixed the local state with `pnpm install --frozen-lockfile --offline --store-dir /media/nvme/dev/golem15/summercms.io/summercms/.pnpm-store`, which left the lockfile unchanged and added no package.
|
||||
**Fix:** plan 18.1-06's `scripts/check-phase18.1.sh` (and any other checkout) may hit the same thing. Either pin `store-dir` in the layer's `pnpm-workspace.yaml`, or run the frozen offline install before the layer stage. Close this item once the check script runs the layer suite green from a clean shell.
|
||||
|
||||
Reference in New Issue
Block a user