OpenPay (1 crate, 1801 LOC, 57 tests)
op-bin BIN/IIN database + range matching + card-network
classification. 8-digit normalized prefix Bin +
BinRange. Sorted-vec interval tree with O(log N) point
lookup + overlap rejection. CardNetwork classify()
with structural rules (Visa 4, MC 51-55/2221-2720,
Amex 34/37, Discover, JCB, Diners, UnionPay, RuPay,
Mir, Troy, Maestro, Elo). Static prefix tables +
build_default_tree(). ISO/IEC 7812-1 Annex B Luhn
(validate / is_valid / check_digit). Card-type +
issuer-country + Durbin regulated-debit. PCI-safe:
8-digit cap, no full-PAN APIs.
Smart Byte (1 crate, ~1500 LOC, 20 tests)
smart-byte-tendermint BFT consensus. Step enum + Round + propose/prevote/
precommit/commit FSM with voting-power tallies.
ValidatorSet with 2/3+1 quorum, 1/3+1 trust
threshold, round-robin proposer. Block / Header /
Commit / CommitSig with Blake3 hashing. Light client
(sequential + skipping). ABCI Application trait +
EchoApp. DuplicateVoteEvidence + LightClientAttackEvidence.
IBC ClientState + ConsensusState + light-client
update.
EOC (1 crate, 2084 LOC, 23 tests)
eoc-safety AI safety primitives. RegexSet over 16 prompt-injection
signatures. 13-family jailbreak detector (DAN/DUDE/
Grandma/STAN/AIM/dev-mode/etc.). Presidio-style PII
redactor with Luhn-validated CC. Toxicity / bias /
NSFW classifier traits + heuristic baselines (5-axis
bias, 4-category NSFW with hard-reject for minors).
Constitutional AI critique→revise loop. Composable
InputGuard / OutputGuard pipelines. JSON-Schema-subset
output validator. Token-bucket rate limiter +
abuse-window detection. Red-team replay harness.
Co-Authored-By: Claude Opus 4.7 <[email protected]>
89 lines
2.9 KiB
Rust
89 lines
2.9 KiB
Rust
//! Durbin Amendment / Federal Reserve Regulation II helpers.
|
|
//!
|
|
//! The Durbin Amendment (section 1075 of the Dodd-Frank Act,
|
|
//! implemented by the Fed's Regulation II) caps debit-interchange
|
|
//! fees on cards issued by banks with **>= $10 billion in
|
|
//! consolidated assets**. The merchant-side cap as of 2026 is
|
|
//! `$0.21 + 5 bps + $0.01 (fraud-adjustment)` per transaction.
|
|
//!
|
|
//! ## What we can determine from a BIN
|
|
//!
|
|
//! - **Card type must be debit** (or prepaid that is treated as
|
|
//! debit under Reg II Subpart C). Credit and charge cards are
|
|
//! never regulated under Durbin.
|
|
//! - **Issuer asset size**: not derivable from the BIN structure
|
|
//! alone. The reference stack flags each [`BinRange`] with a
|
|
//! `durbin_regulated` boolean populated from operator-supplied
|
|
//! tables; the helpers in this module fold that flag with the
|
|
//! card-type test.
|
|
//!
|
|
//! ## What this module is NOT
|
|
//!
|
|
//! Not a fee calculator — Reg II compliance interacts with
|
|
//! routing requirements (the merchant's right to route over a
|
|
//! second unaffiliated network), exclusivity prohibitions, and
|
|
//! the Fed's annual revision of the asset threshold. Use this
|
|
//! module only to answer "is this BIN subject to Reg II's
|
|
//! interchange cap?", not "what is the cap?".
|
|
//!
|
|
//! [`BinRange`]: crate::bin::BinRange
|
|
|
|
use crate::bin::BinRange;
|
|
use crate::card_type::CardType;
|
|
|
|
/// True iff a transaction on the given range is subject to
|
|
/// Regulation II's interchange cap.
|
|
///
|
|
/// Requires both:
|
|
/// 1. `card_type` is `Debit` or `Prepaid`, AND
|
|
/// 2. `durbin_regulated` is set on the range (issuer >= $10B in
|
|
/// assets, populated from operator data).
|
|
pub fn is_regulated(range: &BinRange) -> bool {
|
|
matches!(range.card_type, CardType::Debit | CardType::Prepaid) && range.durbin_regulated
|
|
}
|
|
|
|
/// True iff the issuing institution is "exempt" — issuer assets
|
|
/// below the Reg II threshold, OR the card is not debit/prepaid.
|
|
/// Provided as a counterpart for caller readability.
|
|
pub fn is_exempt(range: &BinRange) -> bool {
|
|
!is_regulated(range)
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
use crate::network::CardNetwork;
|
|
|
|
fn mk(card_type: CardType, durbin: bool) -> BinRange {
|
|
BinRange::new(
|
|
40_000_000,
|
|
50_000_000,
|
|
CardNetwork::Visa,
|
|
card_type,
|
|
None,
|
|
durbin,
|
|
)
|
|
.expect("valid range")
|
|
}
|
|
|
|
#[test]
|
|
fn debit_with_durbin_flag_is_regulated() {
|
|
assert!(is_regulated(&mk(CardType::Debit, true)));
|
|
}
|
|
|
|
#[test]
|
|
fn debit_without_durbin_flag_is_exempt() {
|
|
assert!(is_exempt(&mk(CardType::Debit, false)));
|
|
}
|
|
|
|
#[test]
|
|
fn credit_never_regulated() {
|
|
assert!(!is_regulated(&mk(CardType::Credit, true)));
|
|
assert!(is_exempt(&mk(CardType::Credit, true)));
|
|
}
|
|
|
|
#[test]
|
|
fn prepaid_can_be_regulated() {
|
|
assert!(is_regulated(&mk(CardType::Prepaid, true)));
|
|
}
|
|
}
|