Skip to content

Sasquatch National Bank — Rails

Each Rail is a single money-movement primitive. TwoLegRail posts one debit + one credit; SingleLegRail posts a single leg (must be reconciled by a Transfer Template or aggregating rail).

Total: 29 rails declared on l2.yaml. The accounts diagram on the overview shows every rail as a labeled edge.

CustomerInboundACH — {{ no such element: recon_gen.common.l2.primitives.TwoLegRail object['rail_name'] }}

Inbound ACH credit originated by an external party (employer payroll, vendor payment, peer transfer). External party drives the rail (force-posts via the ACH network); SNB records the offsetting credit on the receiving customer's DDA. Bank trace number (external_reference) is required to reconcile the Fed-statement view.

  • Shape: Two-leg (('ExternalCounterparty',) → ('CustomerDDA',))
  • Posted requirements: external_reference, customer_id
  • Aging — pending: legs SHOULD post within 1 day, 0:00:00 (Stuck Pending matview surfaces violations)
  • Metadata keys: external_reference, originator_id, customer_id

CustomerOutboundACH — {{ no such element: recon_gen.common.l2.primitives.TwoLegRail object['rail_name'] }}

Outbound ACH debit initiated by SNB on behalf of a customer (bill pay, vendor payment, recurring transfer). Both legs are internally initiated until the Fed force-posts the matching settlement to CashDueFRB. ETL must capture customer_id before posting.

  • Shape: Two-leg (('CustomerDDA',) → ('ExternalCounterparty',))
  • Posted requirements: customer_id
  • Aging — pending: legs SHOULD post within 1 day, 0:00:00 (Stuck Pending matview surfaces violations)
  • Metadata keys: external_reference, customer_id, beneficiary_id

CustomerInboundWire — {{ no such element: recon_gen.common.l2.primitives.TwoLegRail object['rail_name'] }}

Inbound wire credit. Fedwire is real-time so the same-day reconciliation window is tight (PT4H). The fedwire_imad is the Federal Reserve's input message accountability data — mandatory for wire reconciliation and audit.

  • Shape: Two-leg (('ExternalCounterparty',) → ('CustomerDDA',))
  • Posted requirements: fedwire_imad, customer_id
  • Aging — pending: legs SHOULD post within 4:00:00 (Stuck Pending matview surfaces violations)
  • Metadata keys: fedwire_imad, originator_id, customer_id

CustomerOutboundWire — {{ no such element: recon_gen.common.l2.primitives.TwoLegRail object['rail_name'] }}

Outbound wire initiated by SNB. The fedwire_omad is captured after Fedwire acknowledges the outbound message; until then the leg is Pending. The wire-suspense GL holds the balance mid-flight.

  • Shape: Two-leg (('CustomerDDA',) → ('ExternalCounterparty',))
  • Posted requirements: fedwire_omad, customer_id
  • Aging — pending: legs SHOULD post within 4:00:00 (Stuck Pending matview surfaces violations)
  • Metadata keys: fedwire_omad, customer_id, beneficiary_id

CustomerCashDeposit — {{ no such element: recon_gen.common.l2.primitives.TwoLegRail object['rail_name'] }}

Physical cash deposit at an SNB branch. The "external" source is the depositor walking in with cash — SNB models this as external because the cash isn't on SNB's books until it lands on the customer DDA. Branch + teller IDs are operational audit context.

  • Shape: Two-leg (('ExternalCounterparty',) → ('CustomerDDA',))
  • Posted requirements: customer_id
  • Metadata keys: branch_id, teller_id, customer_id

CustomerCashWithdrawal — {{ no such element: recon_gen.common.l2.primitives.TwoLegRail object['rail_name'] }}

Physical cash withdrawal at an SNB branch. Customer DDA debits; cash leaves SNB's vault. Same operational audit context as the deposit rail.

  • Shape: Two-leg (('CustomerDDA',) → ('ExternalCounterparty',))
  • Posted requirements: customer_id
  • Metadata keys: branch_id, teller_id, customer_id

InternalTransferDebit — {{ no such element: recon_gen.common.l2.primitives.SingleLegRail object['rail_name'] }}

Debit leg of an on-us transfer cycle. Posts against the source customer's DDA. Joins the shared InternalTransferCycle Transfer via the internal_transfer_id TransferKey (declared first in metadata_keys because it's auto-derived as a PostedRequirement from the template's transfer_key).

  • Shape: Single-leg (('CustomerDDA',), direction Debit)
  • Metadata keys: internal_transfer_id, source_customer_id, destination_customer_id, transfer_purpose

InternalTransferCredit — {{ no such element: recon_gen.common.l2.primitives.SingleLegRail object['rail_name'] }}

Credit leg of an on-us transfer cycle. Posts against the destination customer's DDA. Joins the shared InternalTransferCycle Transfer via the internal_transfer_id TransferKey; the matching debit and suspense-close legs share its ID.

  • Shape: Single-leg (('CustomerDDA',), direction Credit)
  • Metadata keys: internal_transfer_id, source_customer_id, destination_customer_id, transfer_purpose

InternalTransferSuspenseClose — {{ no such element: recon_gen.common.l2.primitives.SingleLegRail object['rail_name'] }}

Closing leg of an on-us transfer cycle on the suspense GL. Variable direction — both amount and direction are computed at posting time so that the bundle's net equals the template's ExpectedNet of 0. MUST be the last leg posted on its Transfer (sibling legs MUST be Posted first); a same-day business_day_end+1d Completion gives operators a window to repair before Conservation flags a stuck cycle.

  • Shape: Single-leg (('InternalTransferSuspense',), direction Variable)
  • Metadata keys: internal_transfer_id

CustomerFeeAccrual — {{ no such element: recon_gen.common.l2.primitives.SingleLegRail object['rail_name'] }}

Daily fee accrual posting (monthly maintenance, overdraft, stop-pay, etc.). Bundled by the monthly settlement aggregating rail; un-bundled rows older than 31 days surface as exceptions (the bundler missed them — investigate ETL or the settlement job). The union leg_role lets the rail land on either a customer DDA or the recon suspense GL for held accounts.

  • Shape: Single-leg (('CustomerDDA', 'InternalSuspenseRecon'), direction Debit)
  • Posted requirements: customer_id, fee_type
  • Aging — unbundled: posted legs SHOULD bundle within 31 days, 0:00:00 (Stuck Unbundled matview surfaces violations)
  • Metadata keys: customer_id, fee_type, accrual_period

ZBASweep — {{ no such element: recon_gen.common.l2.primitives.TwoLegRail object['rail_name'] }}

Nightly zero-balance-account sweep. Each operating ZBA sub-account transfers its EOD balance to the cash-concentration master, leaving the sub-account at zero. One ZBASweep firing per (sub-account, business-day) — a missing sweep means a sub-account didn't zero out and either the customer's reporting or SNB's funding is wrong.

  • Shape: Two-leg (('ZBASubAccount',) → ('ConcentrationMaster',))
  • Metadata keys: sweep_date, location_id

ConcentrationToFRBSweep — {{ no such element: recon_gen.common.l2.primitives.TwoLegRail object['rail_name'] }}

Daily aggregate transfer from the cash-concentration master to the Federal Reserve. Consolidates the day's ZBA-swept balances into a single Fedwire — drastically reducing the per-sub-account Fed traffic. Fedwire ack provides the OMAD that closes the leg.

  • Shape: Two-leg (('ConcentrationMaster',) → ('ExternalCounterparty',))
  • Posted requirements: fedwire_omad
  • Aging — pending: legs SHOULD post within 4:00:00 (Stuck Pending matview surfaces violations)
  • Metadata keys: sweep_date, fedwire_omad

ACHOriginationDailySweep — {{ no such element: recon_gen.common.l2.primitives.TwoLegRail object['rail_name'] }}

End-of-business-day sweep that consolidates the day's outbound ACH activity from the origination GL to the Fed-due GL. Reduces per-customer Fed traffic to one consolidated entry. The BundleSelector [CustomerOutboundACH] matches every Posted + unbundled leg of that rail.

  • Shape: Two-leg (('ACHOrigSettlement',) → ('CashDueFRB',))
  • Aggregating: YES — bundles CustomerOutboundACH
  • Metadata keys: sweep_date, settlement_batch_id

CustomerFeeMonthlySettlement — {{ no such element: recon_gen.common.l2.primitives.SingleLegRail object['rail_name'] }}

Month-end single-leg sweep settling the month's accrued fees out to the contracted billing processor. Single-leg per SPEC's "permitted" example — by design the drift it surfaces exits the system into the External counterparty (the processor's books are where the receivable lands). Cadence monthly-eom mirrors the contracted processor billing cycle.

  • Shape: Single-leg (('ExternalCounterparty',), direction Debit)
  • Aggregating: YES — bundles CustomerFeeAccrual
  • Metadata keys: settlement_period, contracted_processor_id

CustomerInboundACHReturnNSF — {{ no such element: recon_gen.common.l2.primitives.TwoLegRail object['rail_name'] }}

ACH return path for NACHA reason code R01 (insufficient funds). Reverses the inbound ACH credit by debiting the customer DDA and re-crediting the originator's external counterparty. Fires only when SNB couldn't honor the inbound credit — typically same-day or next-business-day after the original posting.

  • Shape: Two-leg (('CustomerDDA',) → ('ExternalCounterparty',))
  • Posted requirements: original_external_reference, return_reason_code
  • Metadata keys: original_external_reference, return_reason_code, customer_id

CustomerInboundACHReturnStopPay — {{ no such element: recon_gen.common.l2.primitives.TwoLegRail object['rail_name'] }}

ACH return path for NACHA reason code R08 (stop payment by receiver). Same posting shape as the NSF return; the difference is provenance — the customer affirmatively stopped the payment vs SNB returning for inability to settle.

  • Shape: Two-leg (('CustomerDDA',) → ('ExternalCounterparty',))
  • Posted requirements: original_external_reference, return_reason_code
  • Metadata keys: original_external_reference, return_reason_code, customer_id

MerchantCardSale — {{ no such element: recon_gen.common.l2.primitives.TwoLegRail object['rail_name'] }}

One merchant card-sale posting. Card network force-posts the external (debit) leg via daily settlement file; SNB records the matching credit on the MerchantPayableClearing GL. The transfer_key of (merchant_id, settlement_period) joins this firing into the shared MerchantSettlementCycle Transfer — many sales for one (merchant, period) share one Transfer.id. Note: NO expected_net on this rail because it's a leg of the MerchantSettlementCycle template (S2: template legs MUST NOT carry expected_net).

  • Shape: Two-leg (('ExternalCardNetwork',) → ('MerchantPayableClearing',))
  • Posted requirements: merchant_id, settlement_period, card_network_ref
  • Aging — pending: legs SHOULD post within 1 day, 0:00:00 (Stuck Pending matview surfaces violations)
  • Aging — unbundled: posted legs SHOULD bundle within 2 days, 0:00:00 (Stuck Unbundled matview surfaces violations)
  • Metadata keys: merchant_id, settlement_period, card_network_ref, card_brand

MerchantPayoutACH — {{ no such element: recon_gen.common.l2.primitives.TwoLegRail object['rail_name'] }}

ACH payout vehicle for merchants who hold an SNB DDA. Debits the MerchantPayableClearing GL and credits the merchant's DDA directly (internal flow — no Fed leg). One of the three XOR payout vehicles; per chain semantics, exactly one fires per settled cycle. Lower friction than wire — SNB's preferred path for SNB-banking merchants.

  • Shape: Two-leg (('MerchantPayableClearing',) → ('MerchantDDA',))
  • Posted requirements: merchant_id, settlement_period
  • Aging — pending: legs SHOULD post within 1 day, 0:00:00 (Stuck Pending matview surfaces violations)
  • Metadata keys: merchant_id, settlement_period, payout_batch_id

MerchantPayoutWire — {{ no such element: recon_gen.common.l2.primitives.TwoLegRail object['rail_name'] }}

Wire payout vehicle for merchants banking elsewhere. Debits the MerchantPayableClearing GL and credits the merchant's external counterparty bank via Fedwire. Per-leg origin: SNB initiates the outbound leg (InternalInitiated); Fed force-posts the external-counterparty leg when Fedwire confirms.

  • Shape: Two-leg (('MerchantPayableClearing',) → ('ExternalCounterparty',))
  • Posted requirements: merchant_id, settlement_period, fedwire_omad
  • Aging — pending: legs SHOULD post within 4:00:00 (Stuck Pending matview surfaces violations)
  • Metadata keys: merchant_id, settlement_period, fedwire_omad, beneficiary_bank

MerchantPayoutCheck — {{ no such element: recon_gen.common.l2.primitives.TwoLegRail object['rail_name'] }}

Paper-check payout vehicle (legacy merchants who don't yet accept ACH or wire). SNB cuts the check; the external leg doesn't post until the merchant deposits and the check clears back through the banking system. max_pending_age of 7 days reflects the tolerance for check-clearing latency before surfacing as stuck.

  • Shape: Two-leg (('MerchantPayableClearing',) → ('ExternalCounterparty',))
  • Posted requirements: merchant_id, settlement_period, check_number
  • Aging — pending: legs SHOULD post within 7 days, 0:00:00 (Stuck Pending matview surfaces violations)
  • Metadata keys: merchant_id, settlement_period, check_number, payee_address

ExternalCardSettlement — {{ no such element: recon_gen.common.l2.primitives.SingleLegRail object['rail_name'] }}

Daily aggregating rail that bundles the day's MerchantCardSale activity for reporting back to the card network. Single-leg per the SPEC's "single-leg sweep that lands in External" pattern — bundles all sales in the day's window and reports the net to the card network's reconciliation file. Force-posted origin: the card network's settlement file is the authoritative record.

  • Shape: Single-leg (('ExternalCardNetwork',), direction Credit)
  • Aggregating: YES — bundles MerchantCardSale
  • Metadata keys: settlement_period, card_brand

SettlementAutoSettle — {{ no such element: recon_gen.common.l2.primitives.SingleLegRail object['rail_name'] }}

AB.3.6 settlement-timing variant — auto-settle (T+0). High-volume merchants enrolled in intraday clearing close their cycle within 4 hours of business_day_end. Tight max_pending_age surfaces ETL delays on the L1 stuck_pending matview within the same day.

  • Shape: Single-leg (('MerchantPayableClearing',), direction Variable)
  • Aging — pending: legs SHOULD post within 4:00:00 (Stuck Pending matview surfaces violations)
  • Metadata keys: merchant_id, settlement_period

SettlementStandardSettle — {{ no such element: recon_gen.common.l2.primitives.SingleLegRail object['rail_name'] }}

AB.3.6 settlement-timing variant — standard-settle (T+1). The common case for most merchants — cycle closes the business day after the card-sale period ends.

  • Shape: Single-leg (('MerchantPayableClearing',), direction Variable)
  • Aging — pending: legs SHOULD post within 1 day, 0:00:00 (Stuck Pending matview surfaces violations)
  • Metadata keys: merchant_id, settlement_period

SettlementSlowSettle — {{ no such element: recon_gen.common.l2.primitives.SingleLegRail object['rail_name'] }}

AB.3.6 settlement-timing variant — slow-settle (weekly batch). Low-volume merchants opt into a weekly batch close; 7-day max_pending_age tolerance reflects the cadence.

  • Shape: Single-leg (('MerchantPayableClearing',), direction Variable)
  • Aging — pending: legs SHOULD post within 7 days, 0:00:00 (Stuck Pending matview surfaces violations)
  • Metadata keys: merchant_id, settlement_period

NoFraudReview — {{ no such element: recon_gen.common.l2.primitives.SingleLegRail object['rail_name'] }}

AB.3.6 fraud-review variant — no review (auto-approved). Trusted high-volume merchants with clean fraud histories skip manual review; the cycle clears immediately on close. PT15M max_pending_age is operational latency only.

  • Shape: Single-leg (('InternalSuspenseRecon',), direction Variable)
  • Aging — pending: legs SHOULD post within 0:15:00 (Stuck Pending matview surfaces violations)
  • Metadata keys: merchant_id, settlement_period

StandardFraudReview — {{ no such element: recon_gen.common.l2.primitives.SingleLegRail object['rail_name'] }}

AB.3.6 fraud-review variant — analyst review. New or medium-volume merchants pass through standard fraud-team review before the cycle closes (4-hour SLA).

  • Shape: Single-leg (('InternalSuspenseRecon',), direction Variable)
  • Aging — pending: legs SHOULD post within 4:00:00 (Stuck Pending matview surfaces violations)
  • Metadata keys: merchant_id, settlement_period

EnhancedFraudReview — {{ no such element: recon_gen.common.l2.primitives.SingleLegRail object['rail_name'] }}

AB.3.6 fraud-review variant — escalated review. Flagged merchants or unusual-pattern cycles route through enhanced review (3-day SLA). Surfaces as stuck_pending when the compliance team lags beyond the cap.

  • Shape: Single-leg (('InternalSuspenseRecon',), direction Variable)
  • Aging — pending: legs SHOULD post within 3 days, 0:00:00 (Stuck Pending matview surfaces violations)
  • Metadata keys: merchant_id, settlement_period

MerchantDailySettleAggregator — {{ no such element: recon_gen.common.l2.primitives.TwoLegRail object['rail_name'] }}

AB.4.6 fan-in parent rail. Each daily merchant settlement legs out a balance from MerchantPayableClearing into WireSettlementSuspense tagged with the batch id it'll contribute to. The week's 5 daily firings then aggregate into one MerchantWeeklyPayoutBatch Transfer per merchant via the AB.4 fan-in chain below.

  • Shape: Two-leg (('MerchantPayableClearing',) → ('WireSettlementSuspense',))
  • Metadata keys: merchant_id, payout_batch_id

MerchantWeeklyBatchClose — {{ no such element: recon_gen.common.l2.primitives.SingleLegRail object['rail_name'] }}

AB.4.6 fan-in child closure leg. Posts ONCE per weekly MerchantWeeklyPayoutBatch firing to credit WireSettlementSuspense for the aggregated payout. Reconciles via MerchantWeeklyPayoutBatch.leg_rails (S3 — every single-leg non-aggregating rail must appear in some template's leg_rails).

  • Shape: Single-leg (('WireSettlementSuspense',), direction Credit)
  • Metadata keys: merchant_id, payout_batch_id