Skip to content

fix: allow external accounts to hold positive balance#2097

Merged
ClaraTersi merged 3 commits into
mainfrom
hotfix/overdraft-outflow
May 7, 2026
Merged

fix: allow external accounts to hold positive balance#2097
ClaraTersi merged 3 commits into
mainfrom
hotfix/overdraft-outflow

Conversation

@ClaraTersi
Copy link
Copy Markdown
Member

Summary

  • Removes the Lua atomic script guard that rejected any CREDIT operation on @external/{asset} whose post-mutation Available would go positive (balance_atomic_operation.lua:573-576). The guard returned error 0018 Insufficient Funds and made customer outflows to @external impossible on a fresh ledger.
  • The rule was incompatible with the direction-debit balance model introduced by the overdraft feature: a ledger composed of debit-direction accounts may legitimately send more to the external world than it has received, leaving @external net-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.
  • Updates the 0018 → ErrInsufficientFunds mapping comment in consumer.redis.go:748 to drop the stale or positive on external CREDIT clause; the source-side floor at line 566 of the Lua script remains the sole emitter of 0018.
  • Inverts two subtests in TestIntegration_Redis_ExternalAccountCreditValidation so they assert success (with the expected post-mutation Available) instead of 0018 rejection. 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

  • Before: POST /v1/.../transactions/outflow (or /transactions/json with distribute.to: @external/{asset}) from a zero-balance overdraft-enabled account returned 422 / 0018 on a fresh ledger.
  • After: same call returns 201 with the overdraft enrichment producing the source default DEBIT, the source overdraft companion DEBIT, and the @external/{asset} CREDIT, leaving @external at the new positive value.

Implementation impact

  • Lua-only behavioral change; no Go business-logic edits. No schema or data migration required.
  • Existing ledgers where @external is currently <= 0 are unaffected. Future transactions on those ledgers can now drive @external positive for the first time.
  • Operational dashboards or reconciliation jobs that hard-coded @external.Available <= 0 will need to be reviewed (no internal consumer in this repo asserts that invariant).

@ClaraTersi ClaraTersi requested a review from a team as a code owner May 6, 2026 19:45
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 6, 2026

Review Change Stack

Walkthrough

External 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.

Changes

External Account Balance Constraint Relaxation

Layer / File(s) Summary
Core Validation Logic
components/ledger/internal/adapters/redis/transaction/scripts/balance_atomic_operation.lua
Removed the atomic validation block that prevented CREDIT operations on external accounts from yielding positive balances. Updated AccountType documentation to reflect the carve-out behavior (skip overdraft/floor logic for external accounts).
Error Documentation
components/ledger/internal/adapters/redis/transaction/consumer.redis.go
Updated inline comment for error code "0018" in mapBalanceAtomicScriptError to clarify it refers to negative available balance on non-external, non-overdraft-capable accounts.
Test Refactoring & Verification
components/ledger/internal/adapters/redis/transaction/consumer.redis_integration_test.go
Reorganized TestIntegration_Redis_ExternalAccountCreditValidation into multiple subtests verifying CREDIT/DEBIT symmetry for external accounts. Added scenarios confirming external accounts can cross zero and become positive, with assertions on post-mutation Available values and a final log confirming symmetry verification.
Documentation
README.md
Inserted an “Ask DeepWiki” badge/link into the top centered badge section.

Comment @coderabbitai help to get the list of available commands and usage tips.

@lerian-studio
Copy link
Copy Markdown
Contributor

lerian-studio commented May 6, 2026

📊 Unit Test Coverage Report: midaz-ledger

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

@lerian-studio
Copy link
Copy Markdown
Contributor

lerian-studio commented May 6, 2026

🔒 Security Scan Results — ledger

Trivy

Filesystem Scan

✅ No vulnerabilities or secrets found.

Docker Image Scan

✅ No vulnerabilities found.


Docker Hub Health Score Compliance

✅ Policies — 4/4 met

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.


🔍 View full scan logs

gandalf-at-lerian and others added 2 commits May 7, 2026 15:14
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
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 ([![Ask
DeepWiki](https://deepwiki.com/badge.svg)](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

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: c5e15500-5cd8-492d-8111-ae7c94fb80a1

📥 Commits

Reviewing files that changed from the base of the PR and between 7944712 and 6bf6e5c.

📒 Files selected for processing (1)
  • README.md

Comment thread README.md
@ClaraTersi ClaraTersi merged commit 383d5eb into main May 7, 2026
21 checks passed
@ClaraTersi ClaraTersi deleted the hotfix/overdraft-outflow branch May 7, 2026 18:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants