openpay/
compliance/ PCI-DSS readiness package (scope-map,
pci-zero-architecture, hsm-kms-guidance,
qsa-checklist), citing PCI-DSS v4.0.1
requirements. (#1)
examples/pci-zero/ Runnable example demonstrating a deployment
where merchant code never touches a PAN. (#1)
crates/op-core/ Tokenized<Card> typestate + NetworkToken
+ CardNetwork + Cryptogram. (#2)
crates/op-rails-card/network_token/
NetworkTokenProvider trait + VTS adapter
+ MDES adapter, with deterministic stubs
behind a 'live' feature flag. (#2)
crates/op-driver-sdk/conformance/network_token.rs
Conformance harness for third-party
NetworkTokenProvider implementations. (#2)
crates/op-cli/src/ledger/ 'openpay ledger as-of' subcommand for
bi-temporal queries. (#3)
crates/op-orchestrator/src/telemetry.rs
OpenTelemetry span emission per
Payment<S> transition with semantic-
conventions tags. (#3)
docs/observability/ Grafana dashboard JSON + wiring guide
for the bi-temporal ledger lens. (#3)
smart-byte/
smart-byte-rs/ Rust reference implementation: envelope
encode/decode (canonical CBOR + BLAKE3
content addressing), Ed25519 sign +
verify, lockstep BFT commit MVP, Iroh
transport scaffold, CLI. (#4)
spec/identity_and_key_rotation.md
Adopts KERI SAIDs + key-event log
format; explicitly does not adopt ACDC
chaining wholesale. (#5)
conformance/v1/ 21 test vectors covering canonicalisation,
SAID computation, signature verification,
lockstep commit, gossip propagation.
CI gate enforces spec/vector coupling. (#6)
eoc/
eoc-rs/ Rust + WASM reference implementation:
4-stage cascade (cache -> kv -> graph ->
neural), joule counters via RAPL / NVML /
powermetrics, CLI, wasm-bindgen surface.
18 tests pass. (#7)
eoc-bench/ Benchmark harness, MT-Bench and Router
case sets, 'joules per MT-Bench point'
metric, 'eoc-bench run | compare' CLI. (#8)
standards/sci-for-ai-submission.md
Submission proposal mapping EOC's
receipt schema to GSF SCI-for-AI. (#9)
cookbook/ HuggingFace-style cookbook (markdown +
runnable Python) demonstrating EOC's
cascade with HF AI Energy Score. (#9)
docs/bench-v0.md Reproducibility doc for eoc-bench.
Workspace state:
- openpay clippy -- -D warnings: clean across all touched crates
- smart-byte-rs cargo test --workspace + clippy: clean
- eoc-rs cargo test --workspace + clippy: clean (18 tests)
- eoc-bench cargo check --workspace + clippy + 15 tests: clean
Rust 1.95.0 edition 2024 pinned at the open-standards root via
rust-toolchain.toml; every workspace inherits.
Closes #1 #2 #3 #4 #5 #6 #7 #8 #9.
102 lines
4.7 KiB
Rust
102 lines
4.7 KiB
Rust
//! # `op-orchestrator` — Cross-rail payment orchestration
|
|
//!
|
|
//! Coordinates the OpenPay stack into an end-to-end flow:
|
|
//!
|
|
//! ```text
|
|
//! PaymentIntent
|
|
//! │
|
|
//! ▼
|
|
//! ┌──────────────────────────────────────────┐
|
|
//! │ 1. Idempotency check (in-process cache) │
|
|
//! ├──────────────────────────────────────────┤
|
|
//! │ 2. Fraud scoring (op-fraud) │
|
|
//! ├──────────────────────────────────────────┤
|
|
//! │ 3. Routing (Router trait) │
|
|
//! │ decide rail order and retry budget │
|
|
//! ├──────────────────────────────────────────┤
|
|
//! │ 4. Attempt loop │
|
|
//! │ • call rail (op-rails-card / a2a) │
|
|
//! │ • classify outcome (Final/Retry/ │
|
|
//! │ Fallback) │
|
|
//! │ • on Fallback: next rail w/ SAME │
|
|
//! │ idempotency key │
|
|
//! │ • on Retry: backoff + same rail │
|
|
//! │ • circuit breaker per (rail, psp) │
|
|
//! ├──────────────────────────────────────────┤
|
|
//! │ 5. Persist terminal state │
|
|
//! │ future-replay of the same intent │
|
|
//! │ key returns the same outcome │
|
|
//! └──────────────────────────────────────────┘
|
|
//! │
|
|
//! ▼
|
|
//! OrchestrationOutcome
|
|
//! ```
|
|
//!
|
|
//! ## Why this lives outside the rail crates
|
|
//!
|
|
//! Each rail crate (`op-rails-card`, `op-rails-a2a`) knows how to
|
|
//! talk to its own backends. They do **not** know about cross-rail
|
|
//! fallback, fraud gating, or idempotency. Mixing those concerns
|
|
//! into the rail crates would create a circular dependency (fraud
|
|
//! needs to score a generic payment, not a card-specific one) and
|
|
//! would prevent operators from swapping in their own rail drivers
|
|
//! while reusing the orchestrator.
|
|
//!
|
|
//! ## Design rationale verified against industry practice
|
|
//!
|
|
//! - **Idempotency keys (UUIDv4/v7)** — Adyen / Stripe convention.
|
|
//! Same key carries across retries AND rail fallbacks. 7-day
|
|
//! minimum TTL per Adyen docs.
|
|
//! - **State machine** — payment is a workflow, not a record.
|
|
//! Stripe's interview prompt; valid transitions enforced.
|
|
//! - **Exponential backoff with jitter** — industry standard for
|
|
//! non-idempotent operations after timeouts.
|
|
//! - **Circuit breaker** — 5 consecutive failures → open for 60s
|
|
//! cooldown → half-open probe → close on success. Standard
|
|
//! resilience pattern.
|
|
//! - **No floats for money** — already enforced by `op-core::Money`
|
|
//! (i64 minor units).
|
|
//!
|
|
//! ## What this crate does NOT do
|
|
//!
|
|
//! - **No async runtime.** The orchestrator is sync, like the
|
|
//! acquirer traits it sits on top of. Async is an
|
|
//! integration concern; wrap with `tokio::task::spawn_blocking`
|
|
//! if needed.
|
|
//! - **No persistent idempotency store.** The default
|
|
//! [`InMemoryIdempotencyStore`] is for tests and short-lived
|
|
//! processes. Production deployments plug in their own
|
|
//! [`IdempotencyStore`] backed by Redis / Postgres / Spanner.
|
|
//! - **No webhook fanout.** Terminal outcomes are returned
|
|
//! synchronously; emitting webhooks is the caller's job.
|
|
//! - **No ledger.** The orchestrator returns outcomes; persisting
|
|
//! them into a double-entry ledger is downstream.
|
|
|
|
#![deny(unsafe_code)]
|
|
#![warn(missing_docs)]
|
|
|
|
pub mod adapters;
|
|
pub mod circuit_breaker;
|
|
pub mod engine;
|
|
pub mod error;
|
|
pub mod idempotency;
|
|
pub mod intent;
|
|
pub mod outcome;
|
|
pub mod router;
|
|
pub mod signals;
|
|
pub mod telemetry;
|
|
|
|
pub use adapters::{A2aAdapter, CardAdapter, CryptoAdapter, MerchantBankProfile};
|
|
pub use circuit_breaker::{CircuitBreaker, CircuitState, InMemoryCircuitBreaker};
|
|
pub use engine::{BackoffPolicy, Orchestrator, OrchestratorConfig};
|
|
pub use error::{Error, Result};
|
|
pub use idempotency::{
|
|
IdempotencyKey, IdempotencyRecord, IdempotencyStore, InMemoryIdempotencyStore,
|
|
};
|
|
pub use intent::{PaymentIntent, RoutingHints};
|
|
pub use outcome::{Attempt, AttemptOutcome, OrchestrationOutcome, TerminalStatus};
|
|
pub use router::{PolicyRouter, RailChoice, Router, RoutingDecision};
|
|
pub use signals::{
|
|
AttemptResultClass, NoOpRailTelemetry, NoOpRoutingSignals, RailTelemetry, RoutingSignals,
|
|
SignalCombiner, noop_signals, noop_telemetry,
|
|
};
|