Skip to content
GitLab
Projects Groups Topics Snippets
  • /
  • Help
    • Help
    • Support
    • Community forum
    • Submit feedback
    • Contribute to GitLab
  • Register
  • Sign in
  • A Ahad Mobile
  • Project information
    • Project information
    • Activity
    • Labels
    • Members
  • Repository
    • Repository
    • Files
    • Commits
    • Branches
    • Tags
    • Contributor statistics
    • Graph
    • Compare revisions
  • Issues 0
    • Issues 0
    • List
    • Boards
    • Service Desk
    • Milestones
  • Merge requests 0
    • Merge requests 0
  • CI/CD
    • CI/CD
    • Pipelines
    • Jobs
    • Schedules
  • Deployments
    • Deployments
    • Environments
    • Releases
  • Packages and registries
    • Packages and registries
    • Package Registry
    • Terraform modules
  • Monitor
    • Monitor
    • Incidents
  • Analytics
    • Analytics
    • Value stream
    • CI/CD
    • Repository
  • Wiki
    • Wiki
  • Snippets
    • Snippets
  • Activity
  • Graph
  • Create a new issue
  • Jobs
  • Commits
  • Issue Boards
Collapse sidebar
  • holatech
  • Ahad Mobile
  • Merge requests
  • !93

fix(card-account): size the open-fee top-up against the keysecure balance

  • Review changes

  • Download
  • Patches
  • Plain diff
Merged Khanh Pham requested to merge fix/keysecure-card-spendable-provider into develop Oct 02, 2026
  • Overview 0
  • Commits 1
  • Pipelines 1
  • Changes 3

Summary

Card apply decided the open-fee top-up from our own card ledger alone. KeySecure webhooks don't reach staging yet, so the first card's Open_card fee was never posted:

  • our ledger says 2.00;
  • KeySecure's cardholder balance is 0;
  • the second apply skipped the top-up and got 3008, so the card went FAILED and the app got a 502.

Apply now also reads the KeySecure balance and uses whichever figure is lower.

  • Where it reads: inside the existing per-account advisory-locked transaction, apply() reads account.info for the cardholder (sum of usdBalance).
  • Top-up size: openCost - min(ledger spendable, provider balance), rounded up to 2 dp.
  • Ledger ahead of KeySecure: if the ledger exceeds the KeySecure balance by more than 0.01, apply logs a WARN with numbers only. Reconciliation already alerts on that drift.
  • Provider read fails: it maps like the package fee read (503 not configured, 502 provider refused, transport errors pass through). Nothing is created.
  • Sweeper path: unchanged.

Testing

  • yarn jest src/modules/card-account: 226 pass. Includes the staging case (ledger 2, provider 0, so it tops up 2.00), the reverse case, the no-top-up case, a multi-item sum, and error mapping.
  • RUN_DB_TESTS=1 on a disposable DB: 233 pass. yarn build and eslint are clean.
  • Mutation check: replacing min with the ledger value fails the staging test.

Notes

  • Lock held during the KeySecure call: the DB transaction and its connection stay open while KeySecure answers, up to about 35s worst case on retries. That's acceptable: apply is rare and the lock is per card account.
  • Concurrent applies (existing, out of scope): two applies at once can still count the same money, because KeySecure takes the fee after the lock is released. One of them gets 3008.
  • Root cause still open: KeySecure webhooks must be enabled so Open_card fees and swipes get posted.

🤖 Generated with Claude Code

Assignee
Assign to
Reviewers
Request review from
Time tracking
Source branch: fix/keysecure-card-spendable-provider