This guide is the high-level map of money movements. It connects the intent builders, templates, balance deltas, and workflows so it is easier to trace a flow end-to-end.

Core Building Blocks

  • Intent builders: internal/moneyflow/intent builds a cardpipeline.Request for each flow.
  • Templates: internal/moneyflow/intent/templates/templates.go defines the expected legs for each intent kind.
  • Balance deltas: docs/balances.md and internal/balances/deltas.go define how each type/subtype mutates balances.
  • Execution: internal/temporal/workflows/cardpipeline/pipeline.go persists account/card legs and emits hooks.
  • Entry workflows: provider hooks and API workflows call the intent builders, then execute the pipeline.

ID Glossary (How Legs Tie Together)

  • LedgerTx: The flow root ID shared by every leg in a movement. This is the canonical flow ID.
  • ReferenceID: Usually equals LedgerTx. For card follow-ups, it may point at the original auth reference so all legs stay linked.
  • TransactionID: Per-leg ID (derived from LedgerTx when missing).
  • linkedId (card webhooks): Provider-side linkage for auth -> settle -> refund chains. We mirror this on the card transaction feed.
  • Idempotency-Key: Client-supplied key for API-triggered movements; used to seed IDs when present.

Rule of thumb: when tracing a flow, start from referenceId and join card/account/user ledger feeds by that UUID.

Flow Map (Intent -> Ledger Legs)

Legend: account legs are type/subtype. User legs apply only when UseUserFunds is set and a user account exists.

Intent key Card tx type Account legs Optional user legs Zero-sum
authorization authorization pending/settle_fee (hold) lock_user_funds for user-backed holds No
settlement settle fee/settle_fee (release), deposit/settle_fee (fee credit) spend_user_funds when user-backed No
reversal cancel transfer/settle_fee (release) unlock_user_funds Yes
refund refund none refund_user_funds Yes
decline decline fee/decline_fee none No
topup topup pending/card_topup_hold, transfer/card_deposit Card funding posts to user account if user-backed Yes
withdraw withdraw transfer/card_withdraw Card return posts to user account if user-backed Yes
close close transfer/card_closed_refund, withdraw/card_closed_adjustment Card return posts to user account if user-backed Yes
issue issue transfer/card_deposit, pending/card_issue, fee/issue_fee, deposit/issue_fee User-backed issuance adds user holds + withdraw_user + deposit_user No
monthly_fee none pending/issue_fee, fee/issue_fee none No
account_topup none deposit/* (wire, sepa, crypto, user, reconcilation), fee/settle_fee (optional) none No
account_withdraw none withdraw/withdraw_system none No

User fee reimbursement: when UseUserFunds is on, fee funding is paired as withdraw_user (user) + deposit_user (parent) so the parent account stays whole.

Where Flows Enter the System

  • Provider card events: internal/temporal/workflows/connex, internal/temporal/workflows/monavate, internal/temporal/workflows/reap_transaction.go, internal/temporal/workflows/fank_hook.go
  • Card lifecycle (issue/topup/withdraw/close): internal/temporal/workflows/issue.go, internal/temporal/workflows/topup_card.go, internal/temporal/workflows/withdraw.go, internal/temporal/workflows/close.go
  • User transfers: internal/temporal/workflows/user_transfers.go (uses account-only intents with deposit_user / withdraw_user)
  • Account topup/withdraw: internal/temporal/workflows/topup_account.go, internal/temporal/workflows/withdraw_account.go

Step-by-Step Trace (Debugging Checklist)

  1. Start from a webhook or API response and capture referenceId and linkedId.
  2. Pull card transactions by card ID and filter by referenceId to get the card leg chain.
  3. Pull account transactions by account ID and filter by the same referenceId to see fees, holds, and transfers.
  4. If the card is user-backed, pull user account transactions and join by the same referenceId.
  5. If there is a mismatch, compare each leg to docs/balances.md and the intent template to verify expected subtypes.

For balance deltas and exact subtype rules, see Balance-Only Money Movements.