open-standards/openpay/crates/op-statements/src/lib.rs
Transaction Science fdc9cf6ab0 ingest wave C: 3 crates · op-statements + smart-byte-activitypub + eoc-observability
OpenPay (1 crate, ~2940 LOC, 40 tests)
  op-statements         Statement generation + reconciliation + fee accounting.
                        Render targets: PDF (template), CSV, JSON, 94-char
                        NACHA fixed-width. ISO 20022 camt.053 with full
                        BkToCstmrStmt envelope (GrpHdr/Stmt/Bal/Ntry). BAI2
                        with 01/02/03/16/49/98/99 records. MT940/MT942
                        SWIFT with :20:/:25:/:28C:/:60F:/:61:/:86:/:62F:
                        + :90C:/:90D: counters. FeeBucket (interchange/scheme/
                        acquirer/fx/settlement-network/bnpl) + FeeSchedule
                        with bps + flat rules. Cadence (daily/weekly/monthly/
                        custom). Two-tier Reconciler (external_id → window
                        heuristic).

Smart Byte (1 crate, 3032 LOC, 39 tests)
  smart-byte-activitypub ActivityPub W3C Rec (2018). AS2 vocab + Public
                         addressing; Actor (Person/Application/Group/
                         Organization/Service) with publicKey + shared-inbox;
                         Object (Note/Article/Image/Video/Tombstone) with
                         Mastodon extensions (sensitive, CW summary,
                         conversation, blurhash); 12 Activity types
                         (Create/Update/Delete/Follow/Accept/Reject/Announce/
                         Like/Undo/Move/Block/Flag) with side-effect rules;
                         OrderedCollection + Page; Webfinger (RFC 7033);
                         HTTP Signatures (cavage draft-12 + RFC 9421);
                         SHA-256 Digest; Ed25519 sign/verify.

EOC (1 crate, 2759 LOC, 20 tests)
  eoc-observability     OpenTelemetry-compatible tracing + metrics + logs.
                        W3C tracecontext + baggage. Span / SpanKind / Status.
                        Samplers: AlwaysOn/Off/RatioBased/ParentBased. Sync
                        BatchSpanProcessor + Exporter trait. Counter / Gauge /
                        Histogram. Prometheus text exposition (HELP/TYPE/
                        _bucket/_sum/_count/+Inf). StatsD / DogStatsD lines.
                        GenAI semconv (gen_ai.{operation,system,request.*,
                        response.*,usage.*}) + EOC extensions (eoc.joules.*,
                        eoc.co2e_grams, eoc.cost.usd). USD + gCO2e attribution
                        with PUE. LangSmith + LangFuse export adapters.

Co-Authored-By: Claude Opus 4.7 <[email protected]>
2026-05-24 13:51:09 -04:00

89 lines
3.7 KiB
Rust

//! # `op-statements` — Merchant statements, reconciliation feeds, fee accounting
//!
//! Every payment system eventually owes the merchant a piece of paper
//! (or its electronic equivalent) that says: here is the gross volume
//! you processed, here is what we kept in fees, here is what we paid
//! out, and here is what survived as your ending balance. That piece
//! of paper is the **statement**.
//!
//! `op-statements` is the lowest common denominator implementation of
//! statement generation and reconciliation feed production, sitting
//! above [`op-ledger`](../op_ledger) (the source of truth for money
//! movement) and consuming the same normalized vocabulary as
//! [`op-reconciliation`](../op_reconciliation) (statement lines).
//!
//! ## Architectural place in the stack
//!
//! ```text
//! op-ledger ─► op-statements ─► RenderTarget {Pdf,Csv,Json,FixedWidth}
//! │
//! ├─► iso20022::camt.053 builder
//! ├─► bai2 writer
//! └─► mt940 writer
//! ```
//!
//! ## What ships in v1
//!
//! - [`Statement`] — the merchant-facing aggregate: period, currency,
//! gross volume, refunds, chargebacks, fees, payouts, balances.
//! - [`render::RenderTarget`] — pluggable serializer for the four
//! canonical output shapes ([`render::Pdf`] template-driven,
//! [`render::Csv`], [`render::Json`], [`render::FixedWidth`]
//! NACHA-style).
//! - [`iso20022::Camt053Builder`] — emits an ISO 20022 `camt.053`
//! end-of-day statement XML from the same [`Statement`] aggregate.
//! - [`bai2::Bai2Writer`] — Bank Administration Institute BAI2
//! transmission file.
//! - [`mt940::Mt940Writer`] — SWIFT MT940 customer statement message
//! (and MT942 intra-day report).
//! - [`fees::FeeBucket`] / [`fees::FeeLine`] — typed fee accrual
//! (interchange, scheme, acquirer, FX, settlement-network, BNPL).
//! - [`reconcile::Reconciler`] — pairs statement lines against
//! [`reconcile::LedgerEntry`] rows (a structural copy of the op-ledger
//! contract; we don't depend on op-ledger directly to keep this
//! crate's dependency graph minimal).
//! - [`cadence::Cadence`] — daily/weekly/monthly/custom schedules with
//! deterministic period enumeration.
//!
//! ## What this crate does NOT do
//!
//! - **No real PDF binary emission.** [`render::Pdf`] produces a
//! template-driven plain-text rendering of the statement
//! ("template-driven PDF" in the OpenPay sense means: a structured
//! text artifact a downstream PDF library can consume). Embedding a
//! PDF stack would bloat the dependency graph and tie us to one
//! licence model.
//! - **No clock.** All cadence enumeration is caller-supplied unix
//! epoch seconds. Tests and replay stay deterministic.
//! - **No persistence.** Statements are values; the operator picks the
//! store.
//! - **No FX rate sourcing.** Multi-currency aggregation carries
//! per-currency totals and an FX-adjusted view only when the caller
//! supplies the rate.
#![forbid(unsafe_code)]
#![warn(missing_docs)]
#![warn(clippy::pedantic)]
#![allow(clippy::module_name_repetitions)]
pub mod bai2;
pub mod cadence;
pub mod error;
pub mod fees;
pub mod iso20022;
pub mod mt940;
pub mod reconcile;
pub mod render;
pub mod statement;
pub use bai2::Bai2Writer;
pub use cadence::{Cadence, Period};
pub use error::{Error, Result};
pub use fees::{FeeBucket, FeeLine, FeeRule, FeeSchedule};
pub use iso20022::Camt053Builder;
pub use mt940::Mt940Writer;
pub use reconcile::{LedgerEntry, ReconRecord, Reconciler};
pub use render::{Csv, FixedWidth, Json, Pdf, RenderTarget};
pub use statement::{
BalanceSnapshot, CurrencyAggregate, FxRate, Statement, StatementLine, StatementLineKind,
};