Skip to content

Fix/payment index validation tsconfig strictness - #276

Merged
martinzhames merged 4 commits into
dupdab:mainfrom
Mac-5:fix/payment-index-validation-tsconfig-strictness
Sep 1, 2026
Merged

Fix/payment index validation tsconfig strictness#276
martinzhames merged 4 commits into
dupdab:mainfrom
Mac-5:fix/payment-index-validation-tsconfig-strictness

Conversation

@Mac-5

@Mac-5 Mac-5 commented Aug 31, 2026

Copy link
Copy Markdown
  1. 28a7a49 — Add @Index() on merchantId + composite indexes (merchantId, status) / (merchantId, createdAt) on Payment entity.
  2. f323814 — Cap amountUsd at 1M via @max(), add a new reusable @MaxJsonSize validator (src/common/decorators/max-json-size.decorator.ts) capping metadata at 4KB serialized, applied to both single and batch payment DTOs.
  3. 0c2e4ab — Add @ispositive() + @max(1440) to CreatePaymentDto.expiryMinutes, aligning it with (and capping) the batch DTO too.
  4. 3ad85e5 — Flip strictNullChecks/noImplicitAny to true in tsconfig.json; added the summary README noting full codebase type-error cleanup is follow-up work.

Closes #145
Closes #146
Closes #147
Closes #148

Mac-5 added 4 commits August 31, 2026 10:23
Payment entity had no @Index decorators despite merchantId being the
WHERE clause for findAll/findOne/getStats and the AML velocity-check
join key, causing sequential scans as the payments table grows.

Adds @Index() on merchantId plus composite indexes on
(merchantId, status) and (merchantId, createdAt) to match the actual
query patterns.
create-payment.dto.ts validated amountUsd with only @isnumber()/
@ispositive() (no ceiling) and metadata with only @isObject(), storing
directly into a jsonb column with no size limit — a low-effort
storage/DoS vector and a source of confusing downstream math at
extreme values.

Adds @max(1_000_000) to amountUsd on both CreatePaymentDto and
BatchPaymentItemDto, and a new reusable @MaxJsonSize custom validator
(src/common/decorators/max-json-size.decorator.ts) capping serialized
metadata at 4KB on both DTOs.
CreatePaymentDto.expiryMinutes only had @isnumber(), unlike
BatchPaymentItemDto.expiryMinutes which already required @ispositive().
PaymentsService.create() applied the value with no clamping, so a
caller could pass 0/negative (payment expired at creation) or an
arbitrarily large value (effectively never-expiring payment).

Adds @ispositive() and @max(1440) (24h cap) to
CreatePaymentDto.expiryMinutes, aligning single-payment creation with
the batch DTO's validation, and applies the same 1440 cap to the batch
DTO for consistency.
tsconfig.json disabled both flags, removing two of TypeScript's most
important safety nets for a financial codebase full of nullable
entity columns (Payment, Settlement, Merchant, Webhook) and optional
DTO fields, letting null/undefined bugs and any-typed values pass
compilation unchecked.

Flips strictNullChecks and noImplicitAny to true. Full project-wide
type-error cleanup surfaced by this flag flip is tracked as follow-up
work rather than attempted in this change (see docs/fixes/payment-hardening.md).

Also adds docs/fixes/payment-hardening.md summarizing all four fixes
made on this branch: merchantId indexes, amountUsd/metadata payload
caps, expiryMinutes bounds, and this tsconfig strictness change.
@drips-wave

drips-wave Bot commented Aug 31, 2026

Copy link
Copy Markdown

@Mac-5 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! 🚀

Learn more about application limits

@martinzhames
martinzhames merged commit 570708f into dupdab:main Sep 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants