Repository navigation
Add a payment-provider circuit breaker, structured logging, and API hardening - #1913
Merged
yusuftomilola merged 2 commits intoSep 25, 2026
Conversation
…API hardening Wraps the outbound payment-rail initiation in a per-rail opossum circuit breaker configured from the environment, so a degraded provider is short-circuited instead of being hammered on every request. Business rejections do not count toward opening the circuit, a volume threshold keeps a low-traffic rail from tripping on one error, and an open breaker surfaces as a clear 503. The breaker is created lazily so the existing service constructor and tests are unchanged. Adds pino-backed structured JSON logging for production (with a LOG_JSON override), promoting the Nest logger context and request id to real fields, plus one structured access-log line per completed response. Completes the admin OpenAPI surface: reconciliation metrics, ledger integrity, payment sweep and settlement run now have typed response DTOs, and previously undocumented query/path parameters are declared, with a reflection-based spec that fails if any admin handler loses its operation or response metadata. Configures an explicit, configurable request body size limit on the JSON and urlencoded parsers while preserving the raw-body capture the payment webhook HMAC verification depends on. Closes DistinctCodes#1797 Closes DistinctCodes#1796 Closes DistinctCodes#1795 Closes DistinctCodes#1794
|
@phertyameen is attempting to deploy a commit to the naijabuz's projects Team on Vercel. A member of the Team first needs to authorize it. |
|
@phertyameen 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! 🚀 |
…er-logging-swagger-body-limit # Conflicts: # backend/.env.example # backend/src/main.ts # backend/src/payments/payments-admin.controller.ts # backend/src/payments/payments.service.ts
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
Closes four issues assigned to this account, all in the backend.
Provider circuit breaker (#1797)
progressToAwaitingConfirmationcalled the rail adapter directly on every request, so a degraded provider was hammered indefinitely. The outbound call is now wrapped in a per-railopossumcircuit breaker:timeout,errorThresholdPercentageandresetTimeout, with avolumeThresholdso a low-traffic rail does not open on a single transient error.errorFilterso business rejections (e.g.ConflictException) do not count toward opening, while transport/timeout failures do.ServiceUnavailableException(HTTP 503) rather than an opaque error, while still rethrowing genuine failures unchanged when the rail is healthy.PaymentsService's constructor signature is unchanged, keeping the existing spec's construction intact; the spec was extended to cover the success path and the open-breaker path.Structured JSON logging (#1796)
Adds a pino-backed
LoggerServicethat promotes Nest's logger context and the current request id to real JSON fields, plus one structured access-log line per completed response (method, url, path, status, duration, request id). Enabled in production, with aLOG_JSON=trueoverride for other environments; development keeps Nest's readable logger. No existing service constructor changed, so unit tests are unaffected.Admin endpoints in the OpenAPI docs (#1795)
Both admin controllers already had class-level tags and most
@ApiOperationdecorators, so the real gap was incomplete responses: reconciliation metrics, ledger integrity, the payment sweep and the settlement run had no response documentation at all and rendered untyped in the generated document. Each now has a proper response DTO built from the real service return type, the xlsx export declares its media type, and previously undocumented@ApiQuery/@ApiParaminputs are declared.admin-swagger.spec.tsguards this with reflection so an admin handler cannot silently lose its operation or response metadata again.Request body size limit (#1794)
The body parsers are now registered explicitly with a configurable limit (
REQUEST_BODY_LIMIT, default1mb) instead of relying on Nest's implicit defaults. Registering them manually is what makes the limit configurable, and theverifycallback preserves the exact raw bytes the payment webhook's HMAC verification depends on — that requirement is called out in a comment so it is not lost in a future refactor.Configuration
REQUEST_BODY_LIMIT1mbLOG_JSONPAYMENT_PROVIDER_BREAKER_TIMEOUT_MS10000PAYMENT_PROVIDER_BREAKER_ERROR_THRESHOLD_PERCENT50PAYMENT_PROVIDER_BREAKER_RESET_TIMEOUT_MS30000Testing
Per the task constraints, no install, build, lint, or test run was performed — the maintainer runs those manually. New spec:
payments/admin-swagger.spec.ts.payments.service.spec.tswas extended.backend/package-lock.jsonis intentionally not regenerated; the new dependencies are declared inpackage.jsonand the lockfile needs annpm installbeforenpm ciwill succeed.New dependencies
opossum,pino.Reviewer note
backend/src/credits/credits-admin.controller.spec.tsandbackend/src/payments/payments-admin.spec.tsare already broken onmain— they import modules that do not exist (./credits-admin.service,../../common/guards/jwt-auth.guard,../../users/entities/user.entity) and call controller methods that no longer exist. They were left untouched here as out of scope.Closing issues
Closes #1797
Closes #1796
Closes #1795
Closes #1794