Skip to content

fix(payments): refine callback response contracts - #8666

Open
iscekic wants to merge 13 commits into
mainfrom
drain/payment-route-contract
Open

iscekic wants to merge 13 commits into
mainfrom
drain/payment-route-contract

Conversation

@iscekic

@iscekic iscekic commented Oct 22, 2026 •

Copy link
Copy Markdown
Collaborator

Evidence

Evidence: demonstrated — a production-mode Next.js server from this head served /api/stripe/webhook over HTTP with a local Sentry-compatible ingest as the configured monitoring endpoint: a failed signature verification returned the fixed refusal and delivered one tagged event for the reporting cadence, a request without a signature header delivered none, a verified event that failed in processing delivered one untagged event, and an unconfigured signing secret delivered one event.

Change

The payment callback keeps one fixed response for requests it cannot verify and reports a failed signature verification at a fixed cadence per server instance, with the route's source tag attached. Verified-event processing errors and a missing signing configuration keep their existing responses and reporting. Route tests cover the refusal, the cadenced report, the processing error, and the configuration error.

The branch touches only apps/web/src/app/api/stripe/webhook/route.ts and its test.

Verification (end to end)

Setup: next build and next start from this head with NODE_ENV=production, real HTTP requests to /api/stripe/webhook, and a local Sentry-compatible ingest accepting the envelope requests the route's real monitoring calls make. Envelopes were decoded and classified as error events versus session and log envelopes, so the outcomes below describe error events only. Request signatures were generated with Stripe's documented signing scheme for the fixture secret.

Observed outcomes, error events only:

  • A request without a signature header gets the fixed refusal and sends no monitoring event.

  • The first failed verification in a cadence window gets the fixed refusal and sends a single tagged event.

  • Further verification failures inside that window get the fixed refusal and send no additional events.

  • Verification failures after the window elapsed send another tagged event.

  • A valid signature for an event type with no handler is acknowledged, with no monitoring event.

  • A valid signature whose processing fails gets a refusal carrying the provider message and sends a single untagged event.

  • An unconfigured signing secret gets the configuration refusal and sends a single event.

  • Focused route Jest suite passes on this head.

  • Focused lint and format checks pass on the changed files.

  • No payment-provider operation succeeded: the local provider key is invalid, so the processing-failure case stops at the provider call.

  • The surface is HTTP-only, so there is no visual artifact to attach.

Production prerequisites

None.

Proxy answers

  1. Question: Keep this change limited to the approved response and reporting contract and route coverage, preserving processing-error responses and leaving resource controls out of scope?
    Answer: Approved narrow scope.
    Confidence: 0.85

  2. Question: A worker terminal test times out on both this branch and the base; how should the check be handled?
    Answer: Repair the fixture at its root cause in a separate change, confirm it on the main history, then merge main into this branch without rebasing and keep this branch route-only.
    Confidence: 0.62

  3. Question: The independent repair is a separate pull request that this session cannot merge; which permitted path applies?
    Answer: Use a stacked dependency.
    Confidence: 0.60

  4. Question: The review app failed for infrastructure reasons on a new head and cannot be re-run directly; how should a review attempt be obtained?
    Answer: Create the smallest possible new head for a fresh review attempt, and record the infrastructure gap in the pull request if it recurs.
    Confidence: 0.50

  5. Question: Which monitoring case remains reportable for the payment callback?
    Answer: Report configuration failures.
    Confidence: 0.50

  6. Question: The verify job fails in extension lint outside this branch's files; how should the check be handled?
    Answer: Merge main first, then resolve the lint failure through the smallest available change without leaving the route scope.
    Confidence: 0.55

  7. Question: The lint failure persisted after merging main and a separate pull request could not land from this session; which permitted path applies?
    Answer: Add the minimal edits to this pull request.
    Confidence: 0.60

  8. Question: The review app does not start a review for a merge-commit head, and completion needs a completed review of the head; which path applies?
    Answer: Add small route-test assertions so the review runs on a normal head.
    Confidence: 0.80

Owner review direction on 2026-10-24: the branch is limited to the payment route, so the extension edit and the documentation note are gone from the diff.

@iscekic iscekic added drain Work item from the findings drain janitor:trust Janitor finding: trust boundary hardening labels Oct 22, 2026
@kilo-code-bot

kilo-code-bot Bot commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor

Code Review Summary

Status: No Issues Found | Recommendation: Merge

Executive Summary

The incremental head 9859ab86 adds a 60-second per-instance cadence to the signature-verification failure report, attaches the stripe_webhook_signature source tag, and pins that behavior in the route tests, while the PR diff remains limited to the payment route.

Assumptions: [INFERENCE] the suite was not executed in this read-only review; validation relies on code inspection. The shared cadence means that, on a warm instance, a continuous stream of forged invalid-signature requests can keep deferring the report of a genuine signing-secret misconfiguration; this is the owner-requested throttle tradeoff rather than an unaddressed defect.

Files Reviewed (2 files)
  • apps/web/src/app/api/stripe/webhook/route.ts
  • apps/web/src/app/api/stripe/webhook/route.test.ts
Previous Review Summaries (4 snapshots, latest commit 2bd74df)

Current summary above is authoritative. Previous snapshots are kept for context only.

Previous review (commit 2bd74df)

Status: No Issues Found | Recommendation: Merge

Executive Summary

The incremental head 2bd74df1 adds only a behavior-preserving ||= simplification in browser-tool-redaction.ts plus a main merge; the payments route and its test are unchanged from the previously reviewed head and remain consistent.

Assumptions: [INFERENCE] the suite was not executed in this read-only review. The merge of origin/main was verified as non-conflicting for the files in this PR's diff (git diff e66156e..HEAD shows only the PR's four files).

Files Reviewed (4 files)
  • apps/web/src/app/api/stripe/webhook/route.ts
  • apps/web/src/app/api/stripe/webhook/route.test.ts
  • apps/extension/src/shared/browser-tool-redaction.ts
  • DEVELOPMENT.md

Previous review (commit 6fdcea8)

Status: No Issues Found | Recommendation: Merge

Executive Summary

The incremental head 6fdcea8f re-adds error-monitoring capture for the unconfigured STRIPE_WEBHOOK_SECRET path and updates the focused route test to assert exactly one report; the change is internally consistent with the existing 500 response contract and leaks no secret material.

Assumptions: [INFERENCE] the suite was not executed in this read-only review; validation relies on code inspection. Sentry grouping is assumed to collapse the repeated config-error reports that Stripe retries generate while the secret is unset.

Files Reviewed (2 files)
  • apps/web/src/app/api/stripe/webhook/route.ts
  • apps/web/src/app/api/stripe/webhook/route.test.ts

Previous review (commit b889af5)

Status: No Issues Found | Recommendation: Merge

Executive Summary

Reviewed the incremental changes since 9e89a10b — the new Stripe signature-fixture and unconfigured-secret response tests, plus the terminal-runtime fixture initialization and its README note — and found no high-confidence defects; the added tests match the current route contract.

Assumptions: [INFERENCE] the suite was not executed in this read-only sandbox; validation relies on code inspection, and the stale-signature fixture assumes Stripe SDK 19.3.1 supports generateTestHeaderString's timestamp option with the default 300-second tolerance, and that STRIPE_SECRET_KEY resolves through the mocked getEnvVariable at import time.

Files Reviewed (3 files)
  • apps/web/src/app/api/stripe/webhook/route.test.ts
  • services/cloud-agent-next/README.md
  • services/cloud-agent-next/test/integration/control-plane-terminal-v2.test.ts

Previous review (commit 9e89a10)

Status: No Issues Found | Recommendation: Merge

Executive Summary

Reviewed the Stripe webhook route's refined response contract, its new SDK-backed Jest coverage, and the DEVELOPMENT.md verification note; the implementation, error classification, and tests are consistent and I found no high-confidence defects.

Assumptions: [INFERENCE] Signature-verification failures are now intentionally returned as a generic 400 without Sentry capture, so a mis-set STRIPE_WEBHOOK_SECRET will surface only through Stripe delivery metrics; [INFERENCE] the suite and typecheck were not executed in this read-only sandbox, so results rely on code inspection.

Files Reviewed (3 files)
  • apps/web/src/app/api/stripe/webhook/route.ts - 0 issues
  • apps/web/src/app/api/stripe/webhook/route.test.ts - 0 issues
  • DEVELOPMENT.md - 0 issues

Reviewed by deepseek-flash-latest · Input: 49.8K · Output: 9.6K · Cached: 317.7K

Review guidance: REVIEW.md from base branch main

@iscekic iscekic added merge:blocked:insufficient-e2e Verification does not cover the change merge:human Substantive functional risk requires human review. labels Oct 22, 2026
Add the 500 response for a route with no signing secret and the SDK verification failure for a timestamp outside the tolerance window.
@iscekic iscekic removed merge:blocked:insufficient-e2e Verification does not cover the change merge:human Substantive functional risk requires human review. labels Oct 23, 2026
@iscekic iscekic added the merge:human Substantive functional risk requires human review. label Oct 23, 2026

@iscekic iscekic left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Request changes: keep the fixed response text for deliveries that fail signature verification. Keep reporting those failures to error monitoring so a misconfigured signing secret stays visible. Limit the change to the payment route; the unrelated terminal-fixture edits belong with their own dependency.

@iscekic iscekic removed the merge:human Substantive functional risk requires human review. label Oct 23, 2026
@iscekic

iscekic commented Oct 23, 2026

Copy link
Copy Markdown
Collaborator Author

bot: Per the owner’s direction, reporting covers missing signing configuration; the webhook response remains fixed, and verified-event diagnostics keep their existing handling. The terminal-fixture repair has merged separately. The focused route suite passes, and a local HTTP check confirmed the response contract.

@iscekic iscekic added merge:blocked:insufficient-e2e Verification does not cover the change merge:human Substantive functional risk requires human review. merge:blocked:judge-unavailable Risk assessment unavailable merge:bot Bot-owned review; merge when ready once readiness passes and a review approves. and removed merge:blocked:insufficient-e2e Verification does not cover the change merge:human Substantive functional risk requires human review. labels Oct 23, 2026
@iscekic iscekic added merge:human Substantive functional risk requires human review. and removed merge:blocked:judge-unavailable Risk assessment unavailable merge:bot Bot-owned review; merge when ready once readiness passes and a review approves. labels Oct 23, 2026
@iscekic iscekic removed the merge:blocked:insufficient-e2e Verification does not cover the change label Oct 24, 2026
@iscekic

iscekic commented Oct 24, 2026

Copy link
Copy Markdown
Collaborator Author

Changes requested: keep reporting Stripe signature-verification failures to error monitoring, as the earlier review asked.

  • In apps/web/src/app/api/stripe/webhook/route.ts, a StripeSignatureVerificationError now returns 400 before captureException, and route.test.ts (around line 79) asserts that nothing is reported.
  • If STRIPE_WEBHOOK_SECRET is set but wrong (for example after a rotation), every Stripe delivery then fails silently. Report this case to Sentry. Throttle the report if needed so that forged requests cannot flood it.
  • Keep the fixed Webhook Error response text and the 400 status.
  • Update the test to assert the report for a signature failure.
  • Limit the PR to the payment route: revert apps/extension/src/shared/browser-tool-redaction.ts and the DEVELOPMENT.md note to match main.

Report failed signature verification to monitoring at most once per
instance per minute while keeping the fixed refusal response, and cover
the reporting contract in the route tests.
@iscekic iscekic removed the merge:human Substantive functional risk requires human review. label Oct 24, 2026
@iscekic

iscekic commented Oct 24, 2026

Copy link
Copy Markdown
Collaborator Author

bot: Applied both points on the current head.

  • The route reports a failed signature verification to monitoring at a fixed cadence per server instance, with the source tag attached. The refusal keeps the fixed text and status.
  • The route tests assert that report, and the suppression of a second report inside the same cadence window.
  • The branch now touches only the payment route: the extension edit and the documentation note are gone from the diff after merging main (the extension file is identical to main).

End-to-end HTTP check rerun on this head with a production-mode server and a local Sentry-compatible ingest: a failed verification gives the fixed refusal and a single tagged event per cadence window, further failures inside the window add none, a verified event that fails in processing gives a refusal carrying the provider message plus a single untagged event, and an unconfigured signing secret still gives its own refusal and event.

Assert the reported failure is the provider SDK verification error, and
that the cadence is shared across verification failure causes.
@iscekic iscekic added merge:blocked:kilobot-not-ready Review bot has not recommended merge at this head merge:human Substantive functional risk requires human review. and removed merge:blocked:kilobot-not-ready Review bot has not recommended merge at this head labels Oct 24, 2026

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

drain Work item from the findings drain janitor:trust Janitor finding: trust boundary hardening merge:human Substantive functional risk requires human review.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant