fix: allow external accounts to hold positive balance#2097
Merged
Conversation
WalkthroughExternal account credit operations are modified to allow positive balances. The Lua validation that prevented CREDIT on external accounts from resulting in positive values is removed. Tests are refactored to verify external accounts can cross zero and reach positive balances, while internal accounts remain unaffected. Error documentation is clarified. ChangesExternal Account Balance Constraint Relaxation
Comment |
Contributor
📊 Unit Test Coverage Report:
|
| Metric | Value |
|---|---|
| Overall Coverage | 85.3% ✅ PASS |
| Threshold | 85% |
Coverage by Package
| Package | Coverage |
|---|---|
github.com/LerianStudio/midaz/v3/components/ledger/internal/adapters/http/in |
85.7% |
github.com/LerianStudio/midaz/v3/components/ledger/internal/adapters/mongodb/onboarding |
66.7% |
github.com/LerianStudio/midaz/v3/components/ledger/internal/adapters/mongodb/transaction |
66.7% |
github.com/LerianStudio/midaz/v3/components/ledger/internal/adapters/postgres/account |
100.0% |
github.com/LerianStudio/midaz/v3/components/ledger/internal/adapters/postgres/accounttype |
66.7% |
github.com/LerianStudio/midaz/v3/components/ledger/internal/adapters/postgres/asset |
100.0% |
github.com/LerianStudio/midaz/v3/components/ledger/internal/adapters/postgres/assetrate |
100.0% |
github.com/LerianStudio/midaz/v3/components/ledger/internal/adapters/postgres/balance |
97.5% |
github.com/LerianStudio/midaz/v3/components/ledger/internal/adapters/postgres/ledger |
100.0% |
github.com/LerianStudio/midaz/v3/components/ledger/internal/adapters/postgres/operation |
89.9% |
github.com/LerianStudio/midaz/v3/components/ledger/internal/adapters/postgres/operationroute |
100.0% |
github.com/LerianStudio/midaz/v3/components/ledger/internal/adapters/postgres/organization |
100.0% |
github.com/LerianStudio/midaz/v3/components/ledger/internal/adapters/postgres/portfolio |
100.0% |
github.com/LerianStudio/midaz/v3/components/ledger/internal/adapters/postgres/segment |
100.0% |
github.com/LerianStudio/midaz/v3/components/ledger/internal/adapters/postgres/transaction |
94.9% |
github.com/LerianStudio/midaz/v3/components/ledger/internal/adapters/postgres/transactionroute |
100.0% |
github.com/LerianStudio/midaz/v3/components/ledger/internal/adapters/rabbitmq |
90.6% |
github.com/LerianStudio/midaz/v3/components/ledger/internal/adapters/redis/transaction/balance |
100.0% |
github.com/LerianStudio/midaz/v3/components/ledger/internal/services/command |
87.0% |
github.com/LerianStudio/midaz/v3/components/ledger/internal/services/query |
93.1% |
github.com/LerianStudio/midaz/v3/components/ledger/internal/services |
0.0% |
Generated by Go PR Analysis workflow
Contributor
🔒 Security Scan Results —
|
| Policy | Status |
|---|---|
| Default non-root user | ✅ Passed |
| No fixable critical/high CVEs | ✅ Passed |
| No high-profile vulnerabilities | ✅ Passed |
| No AGPL v3 licenses | ✅ Passed |
Pre-release Version Check
✅ No unstable version pins found.
Replicates the DeepWiki badge added in #2098 onto hotfix/overdraft-outflow so the badge survives the hotfix merge. Using chore: prefix to keep semantic-release at patch level instead of minor. Requested-by: @ClaraTersi
…x-overdraft-outflow chore: add DeepWiki badge to README
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@README.md`:
- Line 9: The README change adds an unrelated badge ([](https://deepwiki.com/LerianStudio/midaz))
to this hotfix branch; revert or remove that badge addition from the current
commit/branch so the hotfix only contains the external account balance/Lua guard
changes, then create a separate documentation PR against main containing the
badge markdown for later merging.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
Ygohr
approved these changes
May 7, 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
@external/{asset}whose post-mutation Available would go positive (balance_atomic_operation.lua:573-576). The guard returned error0018 Insufficient Fundsand made customer outflows to@externalimpossible on a fresh ledger.@externalnet-positive. The remaining external-account carve-outs (AccountType ~= "external"checks at lines 487, 515, 526) are unchanged — external accounts still bypass the negative-balance floor on debits.0018 → ErrInsufficientFundsmapping comment inconsumer.redis.go:748to drop the staleor positive on external CREDITclause; the source-side floor at line 566 of the Lua script remains the sole emitter of0018.TestIntegration_Redis_ExternalAccountCreditValidationso they assert success (with the expected post-mutation Available) instead of0018rejection. Subtest names and docstrings updated to reflect the new contract; the negative-side carve-out subtests and the internal-account subtest are unchanged.User-visible behavior change
POST /v1/.../transactions/outflow(or/transactions/jsonwithdistribute.to: @external/{asset}) from a zero-balance overdraft-enabled account returned422 / 0018on a fresh ledger.201with the overdraft enrichment producing the source default DEBIT, the source overdraft companion DEBIT, and the@external/{asset}CREDIT, leaving@externalat the new positive value.Implementation impact
@externalis currently<= 0are unaffected. Future transactions on those ledgers can now drive@externalpositive for the first time.@external.Available <= 0will need to be reviewed (no internal consumer in this repo asserts that invariant).