diff --git a/STATUS.md b/STATUS.md index d6e1ff77..782bac41 100644 --- a/STATUS.md +++ b/STATUS.md @@ -69,7 +69,7 @@ Raw machine-readable data: [`scripts/audit/truth-table.json`](scripts/audit/trut - [~] **038 Payment Dashboard** — components built; `/payment/dashboard` route missing (#3) - [~] **039 Payment Offline Queue** — logic built; status indicator UI + `/payment/history` missing (#4) -- [!] **040 Payment Retry UI** — retry logic in service; `/payment/result` page + retry surface missing +- [~] **040 Payment Retry UI** — `/payment-result` route shipped (commit `ffb33a1`, 2026-04-16) — 6-state page + retry button. Real gaps (#43): retry doesn't reuse queued `idempotency_key`, no attempt counter / cooling period (FR-008-010), no error categorization (FR-002), no offline error banner, no audit log on retry, P1 stories 3+4 (update-method, recovery wizard) unbuilt - [~] **041 PayPal Subscriptions** — backend ready; `/payment/subscriptions` page + grace-period banner + duplicate prevention + 4 edge functions missing (#5) - [x] **042 Payment RLS Policies** — 20+ policies verified by `pnpm test:rls` (55/55 across 5 files, both local + cloud) — #44 closed 2026-04-26 @@ -134,7 +134,7 @@ The full code-review findings (35 high-confidence items) live in [`scripts/audit 1. Create Stripe sandbox + PayPal developer accounts (~30-60 min external setup) 2. Populate 6 keys in `.env` + Supabase Vault -3. Wire 4 missing routes (`/payment/dashboard`, `/payment/subscriptions`, `/payment/history`, `/payment/result`) +3. Wire 3 missing routes (`/payment-dashboard`, `/payment-subscriptions`, `/payment-history`); `/payment-result` already shipped — see 040 entry for its remaining UX gaps 4. Build offline-queue UI affordances (status indicator, sync pill, retry button) 5. As each route lands, remove the corresponding skips from `tests/e2e/payment/` per [#53](https://github.com/TortoiseWolfe/ScriptHammer/issues/53) diff --git a/docs/SESSION-HANDOFF-2026-04-27.md b/docs/SESSION-HANDOFF-2026-04-27.md index 4f7e4cb0..74e26572 100644 --- a/docs/SESSION-HANDOFF-2026-04-27.md +++ b/docs/SESSION-HANDOFF-2026-04-27.md @@ -25,12 +25,16 @@ Issues filed during the session that remain open: #49, #53, #57. - **`pnpm test:rls` recovers from killed prior runs.** A globalSetup hook walks the FK chain (`payment_intents → subscriptions → user_profiles → auth.deleteUser`) for every `*@scripthammer.test` user before tests collect, so the manual cleanup that was needed on 2026-04-26 is no longer needed. - **Three consecutive green chromium-msg shards.** PR #58, PR #59, PR #60 all passed messaging E2E on first try. The "9 rounds of flake mitigation" framing in STATUS.md may overstate the current frequency; #57 is probably P2, not P1, but I haven't downgraded its label yet. -## Recommended next pickup: B1 (#43, `/payment/result` page) +## Recommended next pickup: B1 (#43, `/payment-result` retry-UX gaps) -Reasoning: stability backlog is thin enough that user-facing work is now the higher-leverage front. #43 is the smallest of the four missing payment routes, and shipping it un-gates ~5 of the 84 `test.skip`s in `tests/e2e/payment/` (per #53's index). It's also the right warm-up because: +> **Correction (next session, 2026-04-27)**: I called the route "missing" here. It's not. `src/app/payment-result/page.tsx` shipped in commit `ffb33a1` on 2026-04-16 — a 290-LOC, 6-state page with auth gating, real-time updates, and a working retry button. The 2026-04-25 audit cross-referenced spec text rather than the filesystem and concluded "route missing"; that error then propagated through STATUS.md, PRP-STATUS.md, the spec, and into this doc. The route name is `/payment-result` (kebab-case, matching `/payment-demo`), not `/payment/result` (which never existed). +> +> The real B1 work is the _retry UX_ gaps that were obscured by the framing — see "Real B1 work" below. Doc-correction PR: branch `043/doc-fix-payment-result-route-name`. -- The route is a single `src/app/payment/result/page.tsx` plus its 5-file component suite per the project's atomic-design convention. -- The retry surface lives in the existing `src/services/payment-service.ts` — no new business logic needed. +Reasoning: stability backlog is thin enough that user-facing work is now the higher-leverage front. The remaining work in #43 is real: idempotency-key reuse on retry, retry attempt counter + cooling period (FR-008-010), error categorization (FR-002), offline error banner, audit-log on retry (NFR-007). User Stories 3 (update payment method) and 4 (recovery wizard) are P1 in the spec but likely a follow-up PR. + +- The page is at `src/app/payment-result/page.tsx`, with the retry button in `src/components/payment/PaymentStatusDisplay/PaymentStatusDisplay.tsx`. +- `retryFailedPayment()` is in `src/lib/payments/payment-service.ts:237` — currently calls `createPaymentIntent()` for a fresh INSERT, which loses the queued `idempotency_key` and bypasses the partial unique index. Fixing that is the first concrete change. - The PaymentConsentModal (already-resolved hotspot) handles the consent-gate flow, so there's no auth-race risk introduced. Alternatives the next session might prefer: @@ -47,33 +51,33 @@ Alternatives the next session might prefer: ## Open issues (gap-audit) — current state -| # | Title | Family | Notes | -| --- | ------------------------------------------------------------------------------- | ------------ | ------------------------------------------------------------------------------ | -| #21 | 001 WCAG AA: AAA scope gap + 4 ContactForm a11y failures | (audit-tier) | Pre-existing | -| #22 | 004 Mobile-First: regenerate wireframes + perf tests | (audit-tier) | Pre-existing | -| #23 | 005 Security Hardening: session-timeout UI + audit dashboard + secret detection | (audit-tier) | Pre-existing | -| #24 | 006 Template Fork: Supabase missing-config first-run banner | (audit-tier) | Pre-existing | -| #25 | 010 Unified Blog: offline edit + sync + migration | (audit-tier) | Pre-existing | -| #26 | 011 + 043 Group Chats: 8 stub member-management methods | (audit-tier) | Pre-existing | -| #27 | 012 + 014: welcome message admin gate flow | (audit-tier) | Pre-existing | -| #28 | 013 OAuth Messaging Password | (audit-tier) | Pre-existing | -| #29 | 015 OAuth Display Name | (audit-tier) | Pre-existing | -| #30 | 016 Messaging Critical Fixes (5 UX) | (audit-tier) | Pre-existing | -| #31 | 019 Google Analytics: wire NEXT_PUBLIC_GA_MEASUREMENT_ID | (audit-tier) | Pre-existing | -| #32 | 020 PWA Background Sync: Firefox/Safari fallback | (audit-tier) | Pre-existing | -| #34 | 023 EmailJS Integration: provider health dashboard | (audit-tier) | Pre-existing | -| #35 | 026 Unified Messaging Sidebar: mobile drawer + badge sync | (audit-tier) | Pre-existing | -| #37 | 028 Enhanced Geolocation: address search + mobile GPS | (audit-tier) | Pre-existing | -| #38 | 029 SEO Editorial Assistant: technical.ts test coverage | C1 | Pre-existing | -| #39 | 030 Calendar Integration: env vars + 32-theme mapping | (audit-tier) | Pre-existing | -| #41 | 035 Messaging Service Tests | C2 | Pre-existing; multi-day | -| #43 | 040 Payment Retry UI: `/payment/result` page + retry surface | **B1** | **Recommended next** | -| #45 | 044 Error Handler Integrations: Sentry/LogRocket | (audit-tier) | Pre-existing | -| #46 | 045 Disqus Theme: 32-theme mapping | (audit-tier) | Pre-existing | -| #47 | gdpr-compliance.spec.ts: ENOTFOUND scripthammer-supabase-kong-1 | (audit-tier) | Pre-existing — real bug, not in any family yet | -| #49 | auth_audit_logs sign_up events not written for all signup paths | **D2** | Filed in this session | -| #53 | tests/e2e/payment/: 84 test.skip — index by blocker | **B5** | Filed in this session; closes incrementally as B1–B4 ship | -| #57 | Messaging E2E: chromium-msg cross-window propagation | — | Filed in this session; possibly de-prioritize to P2 given 3 consecutive greens | +| # | Title | Family | Notes | +| --- | -------------------------------------------------------------------------------- | ------------ | ------------------------------------------------------------------------------ | +| #21 | 001 WCAG AA: AAA scope gap + 4 ContactForm a11y failures | (audit-tier) | Pre-existing | +| #22 | 004 Mobile-First: regenerate wireframes + perf tests | (audit-tier) | Pre-existing | +| #23 | 005 Security Hardening: session-timeout UI + audit dashboard + secret detection | (audit-tier) | Pre-existing | +| #24 | 006 Template Fork: Supabase missing-config first-run banner | (audit-tier) | Pre-existing | +| #25 | 010 Unified Blog: offline edit + sync + migration | (audit-tier) | Pre-existing | +| #26 | 011 + 043 Group Chats: 8 stub member-management methods | (audit-tier) | Pre-existing | +| #27 | 012 + 014: welcome message admin gate flow | (audit-tier) | Pre-existing | +| #28 | 013 OAuth Messaging Password | (audit-tier) | Pre-existing | +| #29 | 015 OAuth Display Name | (audit-tier) | Pre-existing | +| #30 | 016 Messaging Critical Fixes (5 UX) | (audit-tier) | Pre-existing | +| #31 | 019 Google Analytics: wire NEXT_PUBLIC_GA_MEASUREMENT_ID | (audit-tier) | Pre-existing | +| #32 | 020 PWA Background Sync: Firefox/Safari fallback | (audit-tier) | Pre-existing | +| #34 | 023 EmailJS Integration: provider health dashboard | (audit-tier) | Pre-existing | +| #35 | 026 Unified Messaging Sidebar: mobile drawer + badge sync | (audit-tier) | Pre-existing | +| #37 | 028 Enhanced Geolocation: address search + mobile GPS | (audit-tier) | Pre-existing | +| #38 | 029 SEO Editorial Assistant: technical.ts test coverage | C1 | Pre-existing | +| #39 | 030 Calendar Integration: env vars + 32-theme mapping | (audit-tier) | Pre-existing | +| #41 | 035 Messaging Service Tests | C2 | Pre-existing; multi-day | +| #43 | 040 Payment Retry UI: `/payment-result` retry-UX gaps (route shipped 2026-04-16) | **B1** | **Recommended next** | +| #45 | 044 Error Handler Integrations: Sentry/LogRocket | (audit-tier) | Pre-existing | +| #46 | 045 Disqus Theme: 32-theme mapping | (audit-tier) | Pre-existing | +| #47 | gdpr-compliance.spec.ts: ENOTFOUND scripthammer-supabase-kong-1 | (audit-tier) | Pre-existing — real bug, not in any family yet | +| #49 | auth_audit_logs sign_up events not written for all signup paths | **D2** | Filed in this session | +| #53 | tests/e2e/payment/: 84 test.skip — index by blocker | **B5** | Filed in this session; closes incrementally as B1–B4 ship | +| #57 | Messaging E2E: chromium-msg cross-window propagation | — | Filed in this session; possibly de-prioritize to P2 given 3 consecutive greens | Eval-backlog items (separate label): #3, #4, #5 — all map to Family B (B2, B3, B4 respectively). @@ -103,6 +107,6 @@ docker compose exec scripthammer git checkout -b 043/payment-result-page ## What would be a good shape for the next session's first message -> "Read STATUS.md and docs/SESSION-HANDOFF-2026-04-27.md. Pick up B1 (#43): build the /payment/result route per features/payments/040-payment-retry-ui/spec.md. Brainstorm-design-plan-implement per the superpowers workflow. Branch off main." +> "Read STATUS.md and docs/SESSION-HANDOFF-2026-04-27.md. Pick up B1 (#43): close the retry-UX gaps in `/payment-result` per features/payments/040-payment-retry-ui/spec.md. The route itself shipped 2026-04-16; real work is idempotency-key reuse on retry, attempt counter + cooling period, error categorization, offline error banner, audit-log on retry. Brainstorm-design-plan-implement per the superpowers workflow. Branch off main." That's enough to ground the next agent without re-deriving anything from this conversation. diff --git a/docs/STABILITY-TRACKING.md b/docs/STABILITY-TRACKING.md index 77046bf4..3a4ee2ed 100644 --- a/docs/STABILITY-TRACKING.md +++ b/docs/STABILITY-TRACKING.md @@ -4,7 +4,7 @@ **Family A status**: both items shipped (PR #56, PR #59). Family A is empty for now. **Family D status**: D1 shipped (PR #60). D2 (#49 audit instrumentation) is the only D item remaining. -**Next-session entry point**: Family B1 (#43, `/payment/result` page) — see `docs/SESSION-HANDOFF-2026-04-27.md`. +**Next-session entry point**: Family B1 (#43, `/payment-result` retry-UX gaps — page itself shipped 2026-04-16) — see `docs/SESSION-HANDOFF-2026-04-27.md`. This document is the cross-issue work-order. STATUS.md describes _what_ the gaps are; this describes _which order_ to close them in and _why_. New issues land here first, then graduate into PRs. @@ -49,13 +49,13 @@ The `feat/repo-overhaul-merge` of 2026-03-04 introduced patterns that have cause 20+ payment RLS policies are verified (#44, closed). The remaining work is route + UI: -| Order | Issue | Severity | Unblocks | -| ----- | -------------------------------------------------------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| B1 | [#43](https://github.com/TortoiseWolfe/ScriptHammer/issues/43) | P2 | `/payment/result` page + retry surface. Smallest of the four routes. Unblocks ~5 skips in `03-failed-payment-retry.spec.ts` per [#53](https://github.com/TortoiseWolfe/ScriptHammer/issues/53). | -| B2 | [#3](https://github.com/TortoiseWolfe/ScriptHammer/issues/3) | P2 | `/payment/dashboard`. Unblocks ~6 skips in `01-stripe-onetime`, `06-realtime-dashboard`, `07-performance`. | -| B3 | [#4](https://github.com/TortoiseWolfe/ScriptHammer/issues/4) | P2 | `/payment/history` + offline-queue UI affordances. Unblocks ~12 skips in `05-offline-queue` (whole file). Depends on A2 being landed cleanly so the UI describes a correct state machine. | -| B4 | [#5](https://github.com/TortoiseWolfe/ScriptHammer/issues/5) | P2 | `/payment/subscriptions` + grace period + duplicate prevention + 4 edge functions. Largest of the four; unblocks ~10 skips. | -| B5 | [#53](https://github.com/TortoiseWolfe/ScriptHammer/issues/53) | P2 | The test-skip index. Closes incrementally as B1–B4 land. | +| Order | Issue | Severity | Unblocks | +| ----- | -------------------------------------------------------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| B1 | [#43](https://github.com/TortoiseWolfe/ScriptHammer/issues/43) | P2 | `/payment-result` retry-UX gaps (route itself shipped 2026-04-16, commit `ffb33a1`). Real work: idempotency-key reuse on retry, attempt counter + cooling period (FR-008-010), error categorization (FR-002), offline error banner, audit-log on retry (NFR-007). User Stories 3 + 4 (update method, recovery wizard) likely a follow-up PR. Unblocks several skips in `03-failed-payment-retry.spec.ts` per [#53](https://github.com/TortoiseWolfe/ScriptHammer/issues/53). | +| B2 | [#3](https://github.com/TortoiseWolfe/ScriptHammer/issues/3) | P2 | `/payment-dashboard` (kebab-case, matching `/payment-demo` and `/payment-result`). Unblocks ~6 skips in `01-stripe-onetime`, `06-realtime-dashboard`, `07-performance`. | +| B3 | [#4](https://github.com/TortoiseWolfe/ScriptHammer/issues/4) | P2 | `/payment-history` + offline-queue UI affordances. Unblocks ~12 skips in `05-offline-queue` (whole file). Depends on A2 being landed cleanly so the UI describes a correct state machine. | +| B4 | [#5](https://github.com/TortoiseWolfe/ScriptHammer/issues/5) | P2 | `/payment-subscriptions` + grace period + duplicate prevention + 4 edge functions. Largest of the four; unblocks ~10 skips. | +| B5 | [#53](https://github.com/TortoiseWolfe/ScriptHammer/issues/53) | P2 | The test-skip index. Closes incrementally as B1–B4 land. | **Why B1 first:** smallest, lowest-risk, highest information density. Lets you exercise the "ship a route + remove its skips + close part of #53" loop on a tight feedback cycle before doing the harder routes. diff --git a/docs/prp-docs/PRP-STATUS.md b/docs/prp-docs/PRP-STATUS.md index 4d199f8a..a2f91dc8 100644 --- a/docs/prp-docs/PRP-STATUS.md +++ b/docs/prp-docs/PRP-STATUS.md @@ -152,11 +152,11 @@ A direct-verification audit found that **~70% of non-payment feature status fiel **What's actually missing (the real backlog)**: 1. **Obtain API keys** — create Stripe account + PayPal developer sandbox, set up webhook endpoints, populate 6 values: Stripe publishable + secret + webhook secret, PayPal client ID + secret + webhook ID. Public keys go in `.env` as `NEXT_PUBLIC_*`; server secrets go in Supabase Vault (accessed by Edge Functions via `Deno.env.get`). Budget 30-60 min of external account setup. Full walkthrough: [docs/PAYMENT-DEPLOYMENT.md](../PAYMENT-DEPLOYMENT.md). Forker-facing overview: [README.md "Payment Integration Setup"](../../README.md). -2. **4 route files** — wire existing components into new page.tsx files: - - `/payment/dashboard` (038) — compose `PaymentHistory` + `PaymentTrendChart` + live-update subscription - - `/payment/subscriptions` (038/040/041) — new component, list active subs, cancel/upgrade - - `/payment/history` (039) — wrapper around `PaymentHistory` component - - `/payment/result` (040) — post-redirect result page with retry CTA +2. **3 route files** — wire existing components into new page.tsx files: + - `/payment-dashboard` (038) — compose `PaymentHistory` + `PaymentTrendChart` + live-update subscription + - `/payment-subscriptions` (038/040/041) — new component, list active subs, cancel/upgrade + - `/payment-history` (039) — wrapper around `PaymentHistory` component + - (`/payment-result` (040) shipped 2026-04-16 in commit `ffb33a1` — UX gaps remain, see 040 row) 3. **Targeted UI affordances** — some components don't exist yet: - Offline queue status indicator / sync pill / count badge / retry button / clear-queue (039) - Grace period banner, duplicate-subscription prevention (041) @@ -165,22 +165,22 @@ A direct-verification audit found that **~70% of non-payment feature status fiel **The 47 skipped E2E tests are still the acceptance criteria** — un-skip them as each gap closes. But "un-skip a test" sometimes means "just flip the skip flag" (if the code already works) and sometimes means "build the missing page/component first". -| Feature | Real Status | Active Tests | Stubs Remaining | Notes | -| ------------------------------------------------------------------------------------------------------------------- | ------------------------------------------ | ------------------------------------------------ | ----------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| [024 Payment Integration](../../features/integrations/024-payment-integration/024_payment-integration_feature.md) | **Mostly Implemented — awaiting API keys** | 3 Stripe + 9 GDPR + 2 PayPal + 2 retry = 16 live | 1 + 12 + 14 + 2 = 29 across 4 files | Libs + Edge Functions + DB + components all exist; Stripe + PayPal keys NOT yet obtained (`.env` has empty commented templates). Needs account setup (~30-60 min) before any live payment flow works. Child features 038–042 hold the remaining work. | -| [038 Payment Dashboard](../../features/payments/038-payment-dashboard/038_payment-dashboard_feature.md) | **Components Built, Route Missing** | 2 | 20 | `PaymentHistory`, `PaymentTrendChart`, `AdminPaymentPanel` all exist; `/payment/dashboard` page.tsx does not; also needs real-time subscription wiring. | -| [039 Payment Offline Queue](../../features/payments/039-payment-offline-queue/039_payment-offline-queue_feature.md) | **Logic Built, UI Affordances Missing** | 2 | 18 | `offline-queue.ts` + `payment-adapter.ts` + `connection-listener.ts` work; missing: status indicator, sync pill, count, retry, overflow alert, `/payment/history` | -| [040 Payment Retry UI](../../features/payments/040-payment-retry-ui/040_payment-retry-ui_feature.md) | **Backend Ready, Routes + UX Missing** | 2 | 14 | Retry logic in `payment-service.ts`; missing: `/payment/result` page, offline error banner, retry surface | -| [041 PayPal Subscriptions](../../features/payments/041-paypal-subscriptions/041_paypal-subscriptions_feature.md) | **Backend Ready, UX Missing** | 2 | 12 | `paypal.ts` lib + `paypal-webhook` Edge Function + `subscriptions` table exist; missing: `/payment/subscriptions` page, grace period, duplicate prevention | -| [042 Payment RLS Policies](../../features/payments/042-payment-rls-policies/042_payment-rls-policies_feature.md) | **Policies Written, Unverified** | 2 | 25 | 20+ policies exist in monolithic migration; work is "un-skip tests, run them, fix any policies that fail" rather than "write from scratch". Also: rate-limit UI | -| 043 Group Service | N/A | — | — | Moved to `features/core-features/` on 2026-04-08 — it's a messaging feature, not a payment feature | -| 07 Payment Performance | (no feature file) | 2 | 14 | `07-performance.spec.ts` — needs a feature file or merge into 038 | +| Feature | Real Status | Active Tests | Stubs Remaining | Notes | +| ------------------------------------------------------------------------------------------------------------------- | ------------------------------------------- | ------------------------------------------------ | ----------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| [024 Payment Integration](../../features/integrations/024-payment-integration/024_payment-integration_feature.md) | **Mostly Implemented — awaiting API keys** | 3 Stripe + 9 GDPR + 2 PayPal + 2 retry = 16 live | 1 + 12 + 14 + 2 = 29 across 4 files | Libs + Edge Functions + DB + components all exist; Stripe + PayPal keys NOT yet obtained (`.env` has empty commented templates). Needs account setup (~30-60 min) before any live payment flow works. Child features 038–042 hold the remaining work. | +| [038 Payment Dashboard](../../features/payments/038-payment-dashboard/038_payment-dashboard_feature.md) | **Components Built, Route Missing** | 2 | 20 | `PaymentHistory`, `PaymentTrendChart`, `AdminPaymentPanel` all exist; `/payment/dashboard` page.tsx does not; also needs real-time subscription wiring. | +| [039 Payment Offline Queue](../../features/payments/039-payment-offline-queue/039_payment-offline-queue_feature.md) | **Logic Built, UI Affordances Missing** | 2 | 18 | `offline-queue.ts` + `payment-adapter.ts` + `connection-listener.ts` work; missing: status indicator, sync pill, count, retry, overflow alert, `/payment/history` | +| [040 Payment Retry UI](../../features/payments/040-payment-retry-ui/040_payment-retry-ui_feature.md) | **Partial — route shipped, UX gaps remain** | 4 | 12 | `payment-service.ts` retry logic + `/payment-result` route (commit `ffb33a1`, 2026-04-16) shipped; missing: idempotency-key reuse on retry, retry counter + cooling period, error-type categorization, offline error banner, audit log on retry, update-method flow, recovery wizard | +| [041 PayPal Subscriptions](../../features/payments/041-paypal-subscriptions/041_paypal-subscriptions_feature.md) | **Backend Ready, UX Missing** | 2 | 12 | `paypal.ts` lib + `paypal-webhook` Edge Function + `subscriptions` table exist; missing: `/payment/subscriptions` page, grace period, duplicate prevention | +| [042 Payment RLS Policies](../../features/payments/042-payment-rls-policies/042_payment-rls-policies_feature.md) | **Policies Written, Unverified** | 2 | 25 | 20+ policies exist in monolithic migration; work is "un-skip tests, run them, fix any policies that fail" rather than "write from scratch". Also: rate-limit UI | +| 043 Group Service | N/A | — | — | Moved to `features/core-features/` on 2026-04-08 — it's a messaging feature, not a payment feature | +| 07 Payment Performance | (no feature file) | 2 | 14 | `07-performance.spec.ts` — needs a feature file or merge into 038 | **Recommended next actions** (rough ordering): 1. **Unblock 024**: obtain Stripe + PayPal keys (create test-mode Stripe account + PayPal developer sandbox app, configure webhook endpoints), populate `.env` (public `NEXT_PUBLIC_*` vars) and Supabase Vault (server secrets), verify `/payment-demo` works end-to-end against sandbox APIs. (~1-2 hours including account setup) 2. **042 verification**: un-skip the 25 RLS tests one at a time, fix policies where assertions disagree. No new code, just verification + policy tweaks. (half-day) -3. **038 + 039 routes**: create `/payment/dashboard`, `/payment/history`, `/payment/result`, `/payment/subscriptions` page.tsx files wiring existing components. Some stubs will go green immediately. (1 day) +3. **038 + 039 routes**: create `/payment-dashboard`, `/payment-history`, `/payment-subscriptions` page.tsx files wiring existing components (kebab-case, matching `/payment-demo` and `/payment-result`). Some stubs will go green immediately. (1 day) 4. **039 UI affordances**: build missing queue-status / retry / clear-queue components. (1 day) 5. **040 + 041 UX**: result page polish, grace period handling, duplicate subscription prevention. (1 day) diff --git a/features/payments/040-payment-retry-ui/040_payment-retry-ui_feature.md b/features/payments/040-payment-retry-ui/040_payment-retry-ui_feature.md index 99362955..31c03123 100644 --- a/features/payments/040-payment-retry-ui/040_payment-retry-ui_feature.md +++ b/features/payments/040-payment-retry-ui/040_payment-retry-ui_feature.md @@ -3,7 +3,7 @@ **Feature ID**: 040 **Category**: payments **Source**: ScriptHammer README (SPEC-056) -**Status**: Backend Ready, Routes + UX Missing (2026-04-08). Built: `payment-service.ts` handles retry logic, `PaymentStatusDisplay` component exists. Missing: `/payment/result` page (for post-redirect result handling), offline error display surface (no "payment failed, retry when online" banner component), subscription-management retry surface (shared with 041). 14 E2E stubs in `tests/e2e/payment/03-failed-payment-retry.spec.ts` define the failure-recovery UX. Depends on 024 API keys. +**Status**: Partial — Route shipped, UX gaps remain (2026-04-27). Built: `payment-service.ts` retry logic, `` component, `/payment-result` route (commit `ffb33a1`, 2026-04-16) — 6-state page with retry button. Missing: idempotency-key reuse on retry, retry attempt counter + cooling period (FR-008-010), error-type categorization (FR-002), offline error banner, audit log on retry (NFR-007), update-payment-method flow (User Story 3), guided recovery wizard (User Story 4). Several E2E stubs in `tests/e2e/payment/03-failed-payment-retry.spec.ts` are still skipped pending Stripe API keys; some have been replaced with real assertions for the missing-session and malformed-ID empty states. Depends on 024 API keys. ## Description diff --git a/features/payments/040-payment-retry-ui/spec.md b/features/payments/040-payment-retry-ui/spec.md index a671fb0c..420e3975 100644 --- a/features/payments/040-payment-retry-ui/spec.md +++ b/features/payments/040-payment-retry-ui/spec.md @@ -2,7 +2,7 @@ **Feature Branch**: `040-payment-retry-ui` **Created**: 2025-12-30 -**Status**: Backend Only +**Status**: Partial (route shipped, UX gaps remain) **Input**: User description: "Error display, retry button, and payment method update flow. Provides clear UI for handling failed payments with actionable options to resolve payment issues." --- @@ -11,23 +11,29 @@ ## Implementation Status -**Last audited**: 2026-04-25 -**Real status**: Backend Only +**Last audited**: 2026-04-27 +**Real status**: Partial (route shipped, UX gaps remain) **Tracking**: see gap-audit GitHub issues + STATUS.md ### Shipped -- payment-service.ts retry logic; webhook handlers +- `payment-service.ts` retry logic (`retryFailedPayment`); Stripe + PayPal webhook handlers +- `/payment-result?id=` route (commit `ffb33a1`, 2026-04-16) — 6-state page (loading, missing-id, not-configured, loaded, not-found, error), `` gated, ``-wrapped +- `` with status badge, details panel, real-time updates via `usePaymentRealtime`, retry button for `status === 'failed'` ### Gaps -- /payment/result page route missing -- Offline error banner not implemented -- Retry surface (UI) missing +- Retry button regenerates `idempotency_key` instead of reusing the queued one (loses dedupe with offline-queue replay) +- No retry attempt counter / cooling period enforcement (FR-008, FR-009, FR-010) +- No error categorization — current UI only shows `status === 'failed'` with no reason context (FR-002 lists 8 error types, none mapped) +- No offline error banner +- No audit log on retry attempts (NFR-007) +- User Story 3 (Update Payment Method, FR-011-FR-015) — entirely unbuilt +- User Story 4 (Guided Recovery Wizard, FR-016-FR-019) — entirely unbuilt ### Notes -- Backend ready; user-facing routes + UX missing. +- Route name is `/payment-result` (kebab-case top-level, matches `/payment-demo` and 8 other flat routes); spec previously said `/payment/result` but the route was renamed at implementation time and the doc lagged. Future sibling routes (`/payment-dashboard`, `/payment-history`, `/payment-subscriptions`) are expected to follow the same convention unless a shared `/payment/` shell is justified. diff --git a/scripts/audit/truth-table.json b/scripts/audit/truth-table.json index 18f47c77..c16598ca 100644 --- a/scripts/audit/truth-table.json +++ b/scripts/audit/truth-table.json @@ -804,19 +804,27 @@ "id": "040-payment-retry-ui", "category": "payments", "stated_status": "Draft", - "real_status": "Backend Only", + "real_status": "Partial", "acceptance_count": 16, - "code_evidence": ["payment-service.ts retry logic; webhook handlers"], + "code_evidence": [ + "payment-service.ts retry logic; webhook handlers", + "src/app/payment-result/page.tsx (commit ffb33a1, 2026-04-16) — 6-state page", + "src/components/payment/PaymentStatusDisplay — retry button + real-time updates" + ], "test_evidence": [ - "tests/e2e/payment/03-failed-payment-retry.spec.ts (2 live + 14 stubs)" + "tests/e2e/payment/03-failed-payment-retry.spec.ts (4 live + 12 stubs)" ], "wireframe_evidence": "None", "gaps": [ - "/payment/result page route missing", + "Retry button regenerates idempotency_key instead of reusing the queued one (loses dedupe with offline-queue replay)", + "No retry attempt counter or cooling period (FR-008/009/010)", + "No error categorization — current UI only shows status === 'failed' with no reason context (FR-002)", "Offline error banner not implemented", - "Retry surface (UI) missing" + "No audit log on retry attempts (NFR-007)", + "User Story 3 (Update Payment Method, FR-011-FR-015) entirely unbuilt", + "User Story 4 (Guided Recovery Wizard, FR-016-FR-019) entirely unbuilt" ], - "notes": "Backend ready; user-facing routes + UX missing." + "notes": "Route shipped 2026-04-16 (`/payment-result`, kebab-case matching `/payment-demo`). The 2026-04-25 audit incorrectly flagged the route as missing because it cross-referenced spec text rather than the filesystem. Real B1 work is the retry-UX gaps listed above." }, { "id": "041-paypal-subscriptions",