Repository navigation
fix(upi): M4.3.1 remediation of independent review findings REV-01 through REV-07 on PR #30 - #31
Open
Satelink-Protocol wants to merge 1 commit into
Conversation
… on PR #30 - REV-01: Correct ISO/IEC 18004 QR alignment patterns, RS polynomial generator, Table 12 Format Info, and BCH(18,6) Version Info across V1-V14 with independent jsQR validation - REV-02: Prevent duplicate active bookings at intent creation, confirmation locked tx, guest claims, and handle SQLSTATE 23505 via defensive savepoints - REV-03: Enable operational recovery for refund_pending payments, isolate gateway calls outside holding transactions, and support manual finance reconciliation - REV-04: Enforce strict safe positive integer paise amount matching, exact currency match, and merchant association, preventing underpayment attacks - REV-05: Expand QR capacity to V14 (362B), enforce byte-length checks, and return HTTP 400 QrPayloadTooLargeError without truncating payment details - REV-06: Strictly verify webhook merchantId against configured identity, rejecting missing or mismatched IDs with 401 - REV-07: Add additive migration 017 with idx_payments_active_tier_holds index, verified via EXPLAIN Bitmap Index Scan - docs: update UPI_SECURITY_AUDIT.md, UPI_PROVIDER_READINESS.md, and PROJECT_STATE.md with M4.3.1 remediation matrix
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
This was referenced Nov 4, 2026
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
This PR delivers Milestone M4.3.1 — Independent Review Remediation for PR #30, addressing and fully resolving all seven defects (REV-01 through REV-07, including 4 merge blockers) identified during the independent review of PR #30 (
feature/m4-3-upi-security-remediation).Target base branch:
feature/m4-3-upi-security-remediationAssociated Documentation: See remediation matrix in
docs/UPI_SECURITY_AUDIT.md,docs/UPI_PROVIDER_READINESS.md, anddocs/PROJECT_STATE.md.Remediated Findings (REV-01 through REV-07)
1. REV-01 (Merge Blocker) — QR Alignment Patterns & Independent Decoder Validation
(size - 8, 8); added BCH(18,6) version blocks for V7–V14; corrected RS polynomial math.jsQRdecoding across all versions V1–V14 and real 243-byte UPI URI payloads.2. REV-02 (Merge Blocker) — Duplicate Active Bookings & SQLSTATE 23505 Recovery
createUpiPaymentIntentrejecting users with active bookings (pending_approval,pending_payment,confirmed,checked_in) with HTTP 409already_booked.applySuccessfulUpiPayment; transitions payment torefund_pendingwith reason'duplicate_booking'if active booking exists.SAVEPOINT sp_confirm_bookingwrapping booking insertion; catches23505unique violations and cleanly transitions payment torefund_pendingwithout throwing HTTP 500.claimUpiBookingchecking for active bookings (HTTP 409) and wrapped inSAVEPOINT sp_claim_booking.3. REV-03 (Merge Blocker) —
refund_pendingOperational RecoveryrefundUpiOrderonly permitted refunds for payments insucceededstatus; external gateway network calls were inside database transactions holding locks.refundUpiOrderto support payments in bothsucceededandrefund_pendingstatus.status: 'refunded', duplicate: true).refund_pendingwithfailure_reason = 'refund_failed: ...'.manualReconciliation: true) allowing finance officers to complete refunds with external transaction proof.lib/services/refunds.jsto dispatch UPI refunds torefundUpiOrder.4. REV-04 (Merge Blocker) — Mandatory Verified Amount Exact Match
applySuccessfulUpiPaymentcould receive missing, non-numeric, or malformed amounts without strict type and equality guards.verifiedAmountPaisemust be a safe positive integer (Number.isSafeInteger(n) && n > 0).verifiedAmountPaise === Number(payment.amount)).INR) and merchant ID match.disputed, writes immutable audit ledger entry, and creates 0 confirmed bookings or Telegram invites.5. REV-05 (Medium) — QR Payload Byte Limits & User-Facing Error
Buffer.byteLength(uri, 'utf8')check; throws structured HTTP 400QrPayloadTooLargeError(payload_too_large); ensuredbuildUpiUrinever truncates parameters.6. REV-06 (Medium) — Strict Webhook Merchant ID Verification
merchantId, risking spoofed callbacks.PhonePeAdapter.verifyWebhookandMockUpiAdapter, verifieddata.merchantId === this.merchantId; missing, null, or mismatched merchant IDs are rejected with HTTP 401PaymentAdapterError.7. REV-07 (Low) — Ticket-Tier Active Hold Index (Migration 017)
activeTierPaymentHoldslacked an exact matching composite index.migrations/017_payments_tier_holds_index.sql:Verified query plan executes Bitmap Index Scan via
EXPLAIN.Migration 017 Details
migrations/017_payments_tier_holds_index.sqlidx_payments_active_tier_holdsonpayments (((raw_ref->>'ticketTypeId')::uuid), status, expires_at).IF NOT EXISTS), maintains sequential migration ordering (003through017), zero modification to historical migrations.EXPLAINquery intest/migrations.test.jsshowing index scan utilization.Test Results
test/upi-checkout.test.js): 31/31 passed (100%)jsQRdecode: PASSrefund_pendingrecovery & manual finance reconciliation: PASStest/migrations.test.js): 8/8 passed (100%)npm test): 464 passed, 2 skipped, 0 failednpm run lint): 140/140 files cleannpm run test:e2e): 157 passed, 11 skipped, 0 regressionsAbsolute Safety Gates Preserved
feature/m4-3-upi-security-remediation(does not touchlaunch-mvpormain).ENABLE_LIVE_PAYMENTS=falsestrictly preserved across all environments.