docs(audit): correct /payment-result route framing β already shipped 2026-04-16#62
Merged
TortoiseWolfe merged 1 commit intomainfrom Apr 27, 2026
Merged
Conversation
β¦2026-04-16 The 2026-04-25 audit cross-referenced spec text against documented status rather than the filesystem and concluded the /payment-result route was "missing." It is not. src/app/payment-result/page.tsx shipped in commit ffb33a1 on 2026-04-16 β a 290-LOC, 6-state page (loading, missing-id, not-configured, loaded, not-found, error) with auth gating, suspense, real-time updates via usePaymentRealtime, and a working retry button. The wrong "missing" framing then propagated through STATUS.md, PRP-STATUS.md, the spec, the truth-table, the stability tracker, and the session handoff. This commit corrects all seven surfaces and rewrites the gap list to reflect the real B1 work that #43 still demands: - Retry button regenerates idempotency_key instead of reusing the queued one (loses dedupe with the offline-queue replay path that landed in #59) - No retry attempt counter or cooling period (FR-008/009/010) - No error categorization β 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 Also corrects the assumed-future names of the three remaining payment routes from /payment/* (nested) to /payment-* (kebab-case) to match the existing convention shared with /payment-demo, /payment-result, and 8 other top-level kebab-case routes. There is no /payment/ parent in the app today and creating one for these routes hasn't been justified. No code changes. The next commit will close gaps 1-5 above; User Stories 3 + 4 are deferred to a follow-up PR. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
8 tasks
TortoiseWolfe
added a commit
that referenced
this pull request
Apr 28, 2026
β¦r + cooling, error categorization, offline banner, audit log (#43) (#63) Closes 5 of 7 gaps in #43. Route /payment-result itself shipped 2026-04-16 (commit ffb33a1); this PR closes the retry-UX gaps obscured by the original 'route missing' framing (corrected in #62). Closes (gaps 1-5 of #43): 1. Retry button regenerates idempotency_key. retryFailedPayment() now reuses parent's queued key; doubled clicks become server-side ON CONFLICT no-ops (matches PR #59's offline-queue dedupe). 2. No retry attempt counter or cooling. payment_intents gains retry_count + parent_intent_id; service refuses past RETRY_LIMIT=3 (FR-009); enforces COOLING_PERIOD_MS=30s (FR-010); custom error classes carry waitMs for UI countdown (FR-008). 3. No error categorization. New error-categorization.ts maps Stripe + PayPal error_code to one of FR-002's 8 categories with non-technical user message + resolution hint + recoverable flag (FR-001/003/006/NFR-001). 4. No offline error banner. New OfflineRetryBanner 5-file component reads useOfflineStatus + paymentQueue.getCount(); silent in steady state. 5. No audit log on retry. auth_audit_logs CHECK extended with payment_retry; every retry recorded with { original_intent_id, new_intent_id, retry_count, deduped }. Bonus: PaymentRetryExpiredError refuses retry past parent's 24h provider session. Deferred (gaps 6-7 to follow-up PR): - US3 (Update Payment Method, FR-011-FR-015) β has stripe.js + PCI surface - US4 (Guided Recovery Wizard, FR-016-FR-019) β largest piece E2E test fixes during CI: - 1ea0833 β Navigate online before flipping offline (static-export needs network for first load). - a350833 β Synthesize navigator.onLine + 'offline' event manually. Playwright's setOffline blocks request traffic but doesn't fire the offline browser event in Firefox/WebKit; only Chromium does. Real browsers DO fire the event on real network drops, so synthesizing it is closer to production behavior and works cross-browser. Verification: - pnpm test: 3249/3249 across 286 files (60 new for B1) - pnpm test:rls: 55/55 (new columns inherit existing policies) - pnpm run type-check, lint: clean - CI: 29/29 green incl. all three regression-target gen 3/6 shards (chromium, firefox, webkit) Schema applied locally; cloud apply is reviewer's call (idempotent, safe to re-apply). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The 2026-04-25 audit cross-referenced spec text against documented status rather than the filesystem and concluded the
/payment-resultroute was "missing." It is not.src/app/payment-result/page.tsxshipped in commitffb33a1on 2026-04-16 β a 290-LOC, 6-state page (loading, missing-id, not-configured, loaded, not-found, error) with auth gating, suspense, real-time updates viausePaymentRealtime, and a working retry button.The wrong "missing" framing then propagated through
STATUS.md,PRP-STATUS.md, the spec, the truth-table, the stability tracker, and the session handoff. This PR corrects all seven surfaces and rewrites the gap list to reflect the real B1 work that #43 still demands:idempotency_keyinstead of reusing the queued one (loses dedupe with the offline-queue replay path that landed in fix(offline-queue): watchdog reclaim + idempotent payment INSERTs (#52)Β #59 / PR fix(offline-queue): watchdog reclaim + idempotent payment INSERTs (#52)Β #59)status === 'failed'with no reason context (FR-002 lists 8 error types, none mapped)Also corrects the assumed-future names of the three remaining payment routes from
/payment/*(nested) to/payment-*(kebab-case) to match the existing convention shared with/payment-demo,/payment-result, and 8 other top-level kebab-case routes. There is no/payment/parent in the app today and creating one for these routes hasn't been justified.No code changes. A follow-up PR will close gaps 1-5 above. User Stories 3 + 4 are deferred to a separate PR after that.
Scope
7 doc files, +91/-73 lines:
STATUS.mdβ flip 040 from[!]to[~]; fix route count from 4 missing to 3features/payments/040-payment-retry-ui/spec.mdβ Status field + AUDIT-IMPL-STATUS block rewrittenfeatures/payments/040-payment-retry-ui/040_payment-retry-ui_feature.mdβ Status line rewrittendocs/prp-docs/PRP-STATUS.mdβ 040 row + recommended-actions list updateddocs/STABILITY-TRACKING.mdβ B1 description rewritten; B2/B3/B4 route names switched to kebab-casedocs/SESSION-HANDOFF-2026-04-27.mdβ inline "Correction" callout, B1 framing fixedscripts/audit/truth-table.jsonβ 040 entry: code_evidence expanded, gaps rewritten, notes explain how the audit went wrongTest plan
/payment/resultreferences in tracked docs (excluding the two intentional explanations of the divergence): `grep -rn '/payment/result' STATUS.md docs/ features/ scripts/`Why doc-only
Decoupling the truth surface from the code work means the wrong framing leaves `main` immediately, the next PR is pure code, and the diff stays trivial to review.
π€ Generated with Claude Code