Skip to content

Architecture overview

Corridor is a modular TypeScript monorepo. Its central design rule is that every corridor runs through the same engines: a KES payout through an anchor and a naira payout through an off-Stellar partner differ only in the path the planner chooses, not in which subsystem handles them.

Two things about Stellar decide the shape of the system:

  1. MEMO_HASH is exactly 32 bytes, which is exactly a Corridor Reference. The reference travels whole, as part of the signed transaction, so reconciliation is a join rather than an inference.
  2. Anchors settle on Stellar itself. The fiat spoke touches the hub directly, so the common payout path has no bridge in it at all.
Corridor system architecture
Fig. 01 · Clients, control plane, execution legs, observers and books. One engine per concern serves every corridor.

Everything in that diagram runs in the customer’s own environment.

Route planner (packages/routing)

Turns a request (corridor, purpose, privacy, source, destination, environment) into an ordered list of legs by searching a graph of venue/asset positions. It rejects any payout not funded from the Stellar hub and any collection that does not land on it, and it is the only place privacy is decided — today by refusing privacy: "shielded", because no shielded venue is configured. Routing →

Saga engine (packages/saga)

Runs a plan as durable steps in Postgres. Each leg has forward and an optional compensate. Steps retry with backoff, a lease keeps one worker per saga, and a failure compensates completed steps in reverse order. Failures after money has left Corridor’s control stop at manual_review instead. Saga →

Legs (packages/legs and chain packages)

Each implemented leg kind (stellar.transfer, partner.payout, partner.collect, ledger.reserve, ledger.credit, bridge.simulated) moves value on one venue and returns the ledger entries that describe what it did. Two more, stellar.pathPayment and cctp.transfer, are declared in the route graph and not yet written. Legs are idempotent: before sending, they ask the network whether the movement already landed. Stellar →

Ledger (packages/ledger)

Double-entry, append-only journal on Postgres, at Stellar’s own 7 decimal places. Postings balance per asset, accounts can be flagged no-overdraft, and each external movement is booked exactly once through a unique (venue, external_ref). Ledger →

Anchors (packages/partners)

Every fiat spoke sits behind one partner interface. SepAnchor implements it over SEP-1, 10, 12, 38 and 31; PajPartner and MockPartner implement the same interface for currencies no Stellar anchor serves yet. Anchors →

Observers and reconciliation (packages/recon)

Observers turn Horizon payments, anchor status and partner webhooks into one Observation shape. The matcher joins them with ledger entries on the external reference, and a vault check compares each vault’s on-chain balance with the books. Reconciliation →

Package Responsibility
@corridor/core Venues, 32 fiat currencies with stable one-byte indices, digital assets at 7 dp, Money in integer minor units, Corridor Reference codec, Observation
@corridor/chain-stellar Horizon client, asset registry by issuer, transferWithReference, StellarObserver, trustlines
@corridor/routing Route graph (DEFAULT_EDGES), planRoute, hub enforcement
@corridor/saga SagaEngine, Leg, NonRetryableError, ManualReviewError, reserve leg
@corridor/ledger Schema, Ledger.post, invariants, named Accounts
@corridor/legs Stellar transfer, simulated bridge, anchor payout and collect, ledger credit
@corridor/partners RampPartner, SepAnchor, PartnerRegistry, Paj adapter, mock partner, webhook signing
@corridor/recon reconcile, reconcileReadOnly, bookVaultMovements, checkVaults
@corridor/signer Signer interface for Ed25519 and secp256k1; local, AWS KMS and Turnkey adapters
@corridor/webhooks Partner webhook server, event store, exactly-once order links
@corridor/chain-solana, @corridor/chain-evm The cross-chain spokes, for currencies no Stellar anchor serves yet

The authoritative version of all of this is docs/ARCHITECTURE.md in the repository.