fix: address Devin Review financial-correctness findings from PR #31#34
Merged
devin-ai-integration[bot] merged 1 commit intoJul 6, 2026
Merged
Conversation
- transferPipeline: derive deterministic pending transfer id from the transfer UUID so saga compensation voids the real hold (not a random id) - propertyEscrow: refund wallet debit if the escrow ledger hold fails; skip the pipeline ledger step for deposits to avoid double-booking - ledger-service (Go): reject non-positive amounts, fail-closed on any non-ErrNoRows lookup error in post/void, wrap insert+balance updates in a transaction, require DATABASE_URL in production - rust-tigerbeetle-service: reject non-positive/non-finite amounts, record transfer + balance updates atomically in one DB transaction - reconciliation (Python): round major->minor conversion to avoid float truncation manufacturing phantom drift Co-Authored-By: Patrick Munis <pmunis@gmail.com>
Contributor
Author
Original prompt from Patrick
|
Contributor
Author
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
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
Devin Review flagged 11 issues on the (already-merged) PR #31. Most are concrete financial-correctness bugs that are now live in
base. This PR fixes them and verifiestsc,go build, andcargo checkall pass.TypeScript — transfer pipeline & escrow
Saga compensation voided a fabricated pending id.
compensateFailedTransfergeneratedpendingIdfromDate.now()*999 + random, sovoidPendingTransfernever targeted the hold created by the pipeline — the real TigerBeetle hold leaked. Fixed by deriving a deterministic id from the transfer UUID in both places:Escrow wallet debit was not refunded if the ledger hold failed.
payDeposit/payInstallmentdebited the wallet (auto-committed), then calledcreatePendingTransfer; a throw left the buyer short with no escrow record. Now the TB call is wrapped and the wallet debit is refunded before rethrowing.Double TB hold on deposit.
payDepositcreated its own escrow-ledger hold and then calledexecuteTransferPipeline, which created a second generic hold for the same funds. Added askipLedgeroption to the pipeline;payDepositsets it (sanctions/fraud/Kafka still run).payInstallmentdoes not call the pipeline, so it was already single-hold.Go ledger service (
services/ledger-service/main.go)handleCreateTransfernow rejectsamount <= 0(a negative amount passed theavailable < amountbalance check and reversed fund flow).ErrNoRowserrors, proceeding with emptydebitID/creditID/amountStr. Both handlers now fail-closed (500) on any DB error.UPDATEs now run inside a singlesql.Tx(begin/commit/rollback), so a crash between them can't leave the ledger inconsistent.initDBnow refuses to fall back to theremitflow:remitflow123@localhostdefault whenNODE_ENV/GO_ENVisproduction.go.mod/go.sum(the rewritten service importslib/pq;go buildnow succeeds).Rust ledger service (
services/rust-tigerbeetle-service/src/main.rs)initiate_transferrejects!amount.is_finite() || amount <= 0.0(a negativef64cast tou128wraps to a huge value and bypasses the balance check).db_record_transfer_atomicruns the insert and both balance updates in onesqlxtransaction; the previous code also only logged balance-update failures (transfer persisted, balances didn't) — now it fails closed.Python reconciliation (
services/python-tigerbeetle-reconciliation/main.py)int(float(x) * 1_000_000)truncates (0.07 * 1e6 == 69999.999…→69999). Replaced with a_to_minorhelper that rounds, so the reconciliation worker doesn't flag (or mask) false 1-unit drifts.Verification
npx tsc --noEmit→ 0 errorsgo build ./...(ledger-service, Go 1.22) → successcargo check(rust-tigerbeetle-service) → success (warnings only)python3 -m astparse of reconciliationmain.py→ OKvitest run→ 164 failed / 1804 passed — all failures are pre-existing environmental failures (no live PostgreSQL), ≤ the ~175 baseline; no new regressions.Link to Devin session: https://app.devin.ai/sessions/64d054ae77da41e9a2b74d8593fa635c
Requested by: @munisp