feat(payments): rate-limit GET /path-payment-quote/:id#732
Open
davedumto wants to merge 1 commit into
Open
Conversation
Adds a per-payment-id rate limiter to GET /api/path-payment-quote/:id. Each (paymentId, actor) pair is throttled independently (actor = API key hash, merchant id, or client IP — same precedence as the create-payment limiter), so a leaked API key cannot fan out across unrelated payment ids and a single payment id cannot be flooded from one IP. Defaults: 20 requests / 60s. Configurable via PATH_PAYMENT_QUOTE_RATE_LIMIT_MAX and PATH_PAYMENT_QUOTE_RATE_LIMIT_WINDOW_MS. Returns 429 with X-RateLimit-* / Retry-After headers when blocked. Co-Authored-By: Claude <noreply@anthropic.com>
|
@davedumto is attempting to deploy a commit to the Emmanuel's projects Team on Vercel. A member of the Team first needs to authorize it. |
|
@davedumto Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits. You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀 |
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
Adds a dedicated rate limiter to the
GET /api/path-payment-quote/:idendpoint, the one entry to the Path Payment Service that previously had no abuse controls. Mirrors the structure of the existingcreateCreatePaymentRateLimitso the surface is consistent with the rest of the payments router.closes #599
Changes
src/lib/path-payment-quote-rate-limit.jsexportingcreatePathPaymentQuoteRateLimitplus the helpersgetPathPaymentQuoteRateLimitConfig,getPathPaymentQuoteRateLimitKey, andgetRetryAfterSeconds(same factored shape ascreate-payment-rate-limit.js).(paymentId, actor)pair, where actor precedence is: hashedx-api-keyheader →req.merchant.id→ client IP (viaexpress-rate-limit'sipKeyGenerator). Scoping by payment id stops one merchant/IP from monopolising quote requests for a specific payment, while the actor portion stops a leaked API key from fanning out across unrelated payments.PATH_PAYMENT_QUOTE_RATE_LIMIT_MAXandPATH_PAYMENT_QUOTE_RATE_LIMIT_WINDOW_MS; invalid values fall back to defaults.429with{ error: "Too many path payment quote requests, please try again later." }, plusRetry-Afterand standardX-RateLimit-*headers (legacy headers off, matching the rest of the codebase).src/routes/payments.js: importscreatePathPaymentQuoteRateLimit, instantiates it once at module load (alongsidecreatePaymentRateLimit), and applies it as the first middleware onrouter.get("/path-payment-quote/:id", …), beforevalidateUuidParam()/validateRequestso throttled requests don't pay validation cost.Test plan
src/lib/path-payment-quote-rate-limit.test.js(11 tests, all passing locally):x-api-key, merchant id, IP fallback, unknown-payment markergetRetryAfterSecondsrounding + window fallback429withRetry-Afterand the expected error bodysrc/lib/create-payment-rate-limit.test.js(10),src/lib/rate-limit.test.js(9),src/routes/payments-path-quote.test.js(3).npx vitest run src/lib/path-payment-quote-rate-limit.test.js(and the three above).Scope notes / sibling issues
This PR intentionally addresses only #599. The three other Path Payment Service issues opened alongside it were inspected and not bundled in:
src/(a repo-widegrep -i trustline src/returns no hits). The audit has no concrete target until that module exists, so this needs scoping from the maintainers before a PR is appropriate./path-payment-quote/:idis a read-only GET that returns a quote — there is no client-signed transaction in the request to verify. The actual signature-verified path isverifyTransactionSignatureon theconfirm-paymentflow, which already calls it. Needs clarification on which surface is meant..from("payments").select(...).eq("id", ...).is("deleted_at", null).maybeSingle()against an indexed PK — there's no measurable optimisation to make without a profile pointing at a specific slow query.Happy to take any of those on once they're scoped concretely.
This contribution was authored with AI assistance (Claude Code).