open-standards/openpay/crates/op-settlement/src/lib.rs
Transaction Science 70ecd6caa0 Initial import — three open standards under one shelf
Transaction Science open standards monorepo. Each subdirectory is a
self-contained reference protocol with its own README and licence.

- openpay/    Apache-2.0  payment-acceptance stack (Rust, 26 crates)
- smart-byte/ CC-BY-4.0   content-addressed value carrier (spec)
- eoc/        CC-BY-4.0   energy-optimised compute (spec)

The wire format and the right to fork are public. The optional hosted
services are the offer; the protocols are not.
2026-05-23 07:58:09 -04:00

64 lines
2.5 KiB
Rust

//! # `op-settlement` — When does the vendor actually see the money?
//!
//! Posted ledger transactions are an accounting fact, not a bank
//! deposit. Between "we recorded a payment" and "funds landed in the
//! vendor's bank account" sits the **settlement layer**:
//!
//! 1. Batch posted transactions by **cutoff window** (daily,
//! multi-daily, manual).
//! 2. Subtract **holdbacks** — operator-configured reserve plus an
//! optional risk-driven adjustment for open disputes.
//! 3. Generate the **payout file** for the chosen rail (NACHA for
//! US ACH, `pacs.008` for SEPA / RTP / `FedNow` via
//! [`op_iso20022`]).
//! 4. Track the batch lifecycle: `Open → Closed → Paying → Paid`
//! (or `Failed`), with retries on the rail side.
//!
//! ## Architectural place
//!
//! `op-settlement` sits *downstream* of [`op_ledger`] (it consumes
//! posted transactions) and *upstream* of the rail payout mechanism
//! (NACHA file, ISO 20022 customer credit transfer). It does NOT
//! itself talk to a bank — that's the operator's payout adapter,
//! which the trait surface admits.
//!
//! ```text
//! op-ledger ──posted tx──► op-settlement ──batch──► op-iso20022
//! │ (pacs.008)
//! └─────────────► NACHA writer
//! ```
//!
//! ## What this crate does NOT do
//!
//! - **No bank connectivity.** We emit payout *files*; an operator
//! adapter SFTPs the NACHA to their ODFI or POSTs the pacs.008.
//! - **No FX.** A batch is single-currency. Multi-currency
//! operators run one batch per currency.
//! - **No persistence by default.** [`InMemorySettlementStore`] for
//! tests / single-process kiosks; production deployments plug in
//! their own [`SettlementStore`].
//! - **No clock.** All timestamps are caller-supplied unix epoch
//! seconds so tests and replay are deterministic.
#![deny(unsafe_code)]
#![warn(missing_docs)]
#![warn(clippy::pedantic)]
#![allow(clippy::module_name_repetitions)]
pub mod batch;
pub mod cutoff;
pub mod engine;
pub mod error;
pub mod holdback;
pub mod nacha;
pub mod payout;
pub mod store;
pub use batch::{Batch, BatchId, Status};
pub use cutoff::Cutoff;
pub use engine::SettlementEngine;
pub use error::{Error, Result};
pub use holdback::{Holdback, HoldbackPolicy};
pub use nacha::{NachaCredit, nacha_file};
pub use payout::PayoutRail;
pub use store::{InMemorySettlementStore, SettlementStore};