Skip to content

Sasquatch National Bank — Transfer templates

A Transfer Template chains multiple Rail firings into a single business-meaningful Transfer (e.g. "ACH origination cycle: customer debit + sweep + Fed master credit"). The template's expected_net closes the bundle — every leg's signed amount MUST sum to that value (L1 Conservation invariant).

Total: 3 templates declared on l2.yaml.

InternalTransferCycle

Three-leg suspense-mediated on-us transfer cycle. The source DDA debits, the destination DDA credits, and the suspense GL holds the difference until the cycle closes net-zero by the next business day end. The suspense-close leg's Variable direction lets it absorb either side of the cycle's imbalance — the cycle always closes to zero regardless of which DDA's posting lands first or last.

  • Expected net: 0
  • Leg rails: {{ no such element: str object['rail_name'] }} → {{ no such element: str object['rail_name'] }} → {{ no such element: str object['rail_name'] }}

MerchantSettlementCycle

TransferKey-grouped merchant settlement. All MerchantCardSale firings carrying the same (merchant_id, settlement_period) pair join one shared Transfer. Net is zero (each sale firing's external-debit + clearing-credit nets to zero, and the sum across firings preserves that). Completion at business_day_end triggers the chain: per the PayoutVehicle XOR group, exactly one of MerchantPayoutACH / Wire / Check fires to drain the merchant's accumulated clearing balance.

AB.3.6 (2026-05-19): per-merchant config picks one settlement- timing variant AND one fraud-review variant per cycle. Two independent XOR groups in leg_rail_xor_groups — auto/standard/ slow for the cycle's close cadence, no/standard/enhanced for the review level. Each variant carries its own max_pending_age so the L1 stuck_pending matview surfaces a different SLA for each operating mode. ETL bugs where a cycle fires zero or two+ members of a group surface on the AB.3.3 xor_group_violation matview.

  • Expected net: 0
  • Leg rails: {{ no such element: str object['rail_name'] }} → {{ no such element: str object['rail_name'] }} → {{ no such element: str object['rail_name'] }} → {{ no such element: str object['rail_name'] }} → {{ no such element: str object['rail_name'] }} → {{ no such element: str object['rail_name'] }} → {{ no such element: str object['rail_name'] }}

MerchantWeeklyPayoutBatch

AB.4.6 fan-in batch template (gap doc §2 MerchantPayoutBatch example). 5 daily MerchantDailySettleAggregator firings share one MerchantWeeklyPayoutBatch Transfer — the week's per-merchant payouts aggregate into a single closure leg posting. The L1 _fan_in_disagreement matview reads parent_count per child Transfer and flags batches with too few (missing contribution) or too many (cross-batch contamination) parent firings.

  • Expected net: 0
  • Leg rails: {{ no such element: str object['rail_name'] }}