You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The original framing of this issue ("build /payment/result page + retry surface + offline error banner") was wrong. The route already exists.
src/app/payment-result/page.tsx shipped in commit ffb33a1 on 2026-04-16 — a 290-LOC, 6-state page with auth gating, suspense, real-time updates via usePaymentRealtime, and a working retry button. The 2026-04-25 audit cross-referenced spec text against documented status rather than the filesystem and concluded "route missing"; that error then propagated through STATUS.md, PRP-STATUS.md, the spec, the truth-table, the stability tracker, and the session handoff.
Doc-correction PR: #62. Real B1 code work: see "Real gaps" below — follow-up PR.
4 live E2E tests in tests/e2e/payment/03-failed-payment-retry.spec.ts (missing-session, malformed-ID, payment demo loads, consent flow)
Real gaps (this is what B1 actually closes)
In this issue's scope (recommended next PR — gaps 1-5)
Retry button regenerates idempotency_key.retryFailedPayment() (src/lib/payments/payment-service.ts:237) calls createPaymentIntent() for a fresh INSERT, which loses the queued idempotency_key and bypasses the partial unique index that landed in PR fix(offline-queue): watchdog reclaim + idempotent payment INSERTs (#52) #59. The retry button on /payment-result should reuse the queued key.
No retry attempt counter or cooling period (FR-008, FR-009, FR-010). Currently: unlimited rapid retries permitted.
No error categorization (FR-002 — 8 error types defined, none mapped). Current UI shows status === 'failed' with no reason context.
No offline error banner.
No audit log on retry attempts (NFR-007).
Deferred to a follow-up PR (Stories 3 and 4 — large, P1 in spec but separate scope)
User Story 3 — Update Payment Method (FR-011-FR-015). Has stripe.js + PCI surface considerations that warrant their own design pass.
User Story 4 — Guided Recovery Wizard (FR-016-FR-019). Largest piece by far.
Status correction (2026-04-27)
The original framing of this issue ("build /payment/result page + retry surface + offline error banner") was wrong. The route already exists.
src/app/payment-result/page.tsxshipped in commitffb33a1on 2026-04-16 — a 290-LOC, 6-state page with auth gating, suspense, real-time updates viausePaymentRealtime, and a working retry button. The 2026-04-25 audit cross-referenced spec text against documented status rather than the filesystem and concluded "route missing"; that error then propagated through STATUS.md, PRP-STATUS.md, the spec, the truth-table, the stability tracker, and the session handoff.Doc-correction PR: #62. Real B1 code work: see "Real gaps" below — follow-up PR.
What's shipped
src/lib/payments/payment-service.ts—retryFailedPayment(intentId)retry logicsrc/app/payment-result/page.tsx(commitffb33a1, 2026-04-16) — 6-state route with auth + Suspense + retry buttonsrc/components/payment/PaymentStatusDisplay/PaymentStatusDisplay.tsx— status badge + details + real-time updates + retry CTAtests/e2e/payment/03-failed-payment-retry.spec.ts(missing-session, malformed-ID, payment demo loads, consent flow)Real gaps (this is what B1 actually closes)
In this issue's scope (recommended next PR — gaps 1-5)
idempotency_key.retryFailedPayment()(src/lib/payments/payment-service.ts:237) callscreatePaymentIntent()for a fresh INSERT, which loses the queuedidempotency_keyand bypasses the partial unique index that landed in PR fix(offline-queue): watchdog reclaim + idempotent payment INSERTs (#52) #59. The retry button on/payment-resultshould reuse the queued key.status === 'failed'with no reason context.Deferred to a follow-up PR (Stories 3 and 4 — large, P1 in spec but separate scope)
Reference
features/payments/040-payment-retry-ui/spec.mdfeatures/payments/040-payment-retry-ui/040_payment-retry-ui_feature.md/payment-dashboard), [Eval-Backlog] PAYMENT-OFFLINE-UI: UI layer for existing offline payment queue #4 (/payment-history+ offline UI), [Eval-Backlog] SUBSCRIPTION-MGMT: subscription management route + 4 edge functions + grace-period wiring #5 (/payment-subscriptions)