A corridor is two banks, one product on one route, one agreed band table and one shared secret. This page walks the whole life of one, in order, and names the code behind each step. Mirror authors no table and supplies no price at any step: every number in a corridor is the pair's.
| Step | What happens | Where it runs | Code |
|---|---|---|---|
| 0. Or skip the table | For goods with public reference prices: a ratio corridor bands price ÷ a cited public reference on a published table, so no price table is negotiated at all. One bank opens it; the other accepts it | One bank, then the other | band --reference-set, mirror-bander accept, mirror-bander screen |
| 1. Start from a template | Pick the template for the goods: what to band, which legs, which must come from a party with no stake in the price | Either bank | corridor library, mirror-library |
| 2. Find a table you both hold | Each bank signs the list of tables it already supports; both compute the same finest shared one | Bank to bank | mirror-discovery |
| 3. Try it on your own book | Run candidate tables over the bank's own legs; see what each would reconcile and how much it hides | Inside each bank | mirror-bander shadow, mirror-shadow |
| 4. Agree the terms | The charter: roles, legal basis, witnesses, what each party may learn | The pair | mirror-charter |
| 5. Hold the ceremony | Import the corridor secret, compare check values, optionally start a hash ratchet | Both banks, together | mirror-ceremony, mirror-bander ratchet-start |
| 6. Ratify | Propose and ratify the table by quorum - closed, with a match ceiling - with a start and, if wanted, an end | The registry | mirror-bander table-import --closed --max-ratio, corridor.propose, corridor.ratify |
| 7. Run | Band, commit, reconcile; convert currencies on one ratified FX basis; cite a public market figure as a third record; zoom into one shipment by consent | Banks and operator | mirror-bander band, mirror-fxbasis, mirror-bander benchmark-leg, mirror-zoom |
| 8. Change | Turn the ratchet, rotate the secret, renew or retire the table | The pair | ratchet-turn, rotate-plan, a new version |
1. Start from a template#
The corridor library holds templates for goods that trade-based laundering favours. A template says which dimensions a corridor must band, which legs it must require, which of them must be independent, which identifiers join the legs and which typologies it reaches. It carries no price, no band edge and no tolerance. mirror-library.validateProposal checks the shape of a pair's table against its template and never its values.
2. Find a table you both hold — the discovery handshake#
Agreeing a table is the slow, legal step that stops corridors starting. Often it need not be a negotiation: both banks already support tables, from the library, the open table standard or corridors each runs with someone else.
- The offer. Each bank signs, with its member key, the list of tables it supports for the prospective corridor. Each table is named by its 64-hex id (the hash of the published table) with its granularity: how many bands, and the widest bounded price ratio one band spans. No edge and no price travel.
- The selection.
select()verifies both offers, intersects them, sets aside any table the two offers describe differently (one side holds a different file), and picks the finest: smallest widest-band ratio, then most bands, then lowest id. The order is total, so either bank gets the same answer. - No shared table is a clean
undetermined · no_shared_table. Never a "closest" table, never one a side does not hold.
What it costs: each bank learns which tables the other supports. Tables are public artefacts, so this is a disclosure of capability, not of any trade, and it is not private set intersection. The operator never sees an offer. The handshake chooses a candidate; the corridor still ratifies it.
3. Try it on your own book — shadow mode#
A coarse table reconciles more and hides more. A fine one hides less and throws more honest rounding into divergent. Shadow mode puts that trade-off in front of the officer who ratifies:
mirror-bander shadow --in legs.csv --tables candidates.json --roles invoice,payment --out shadow.json
candidates.json is a list of candidate tables, for example [{"label":"coarse","edges":[50,100,150,200]},{"label":"fine","edges":[50,75,100,125,150,175,200]}]. The bander reads the bank's own legs (the invoice it finances, the draft, the insurance certificate) with the same reader as band, runs the operator's own reconciliation kernel once per table, and submits nothing. Per table it reports:
- how many shipments would reconcile, diverge or stay undetermined, and why;
- the table's widest bounded hiding place (
mirror-geometry); - between every two tables, how many shipments change answer.
It reports counts only. It does not rank the tables or recommend one, and no figure from the book appears in the report. Legs in two currencies on one shipment are counted as unbandable rather than compared.
What it cannot tell you: the counterparty's books are not in it. A table that reconciles everything in-house can still diverge across the corridor. And legs one customer wrote agree because that customer wrote them.
4–5. Agree the terms, hold the ceremony#
The charter (mirror-charter, POST /charter/build) records what the pair agreed. At the ceremony both banks load the corridor secret and prove they loaded the same one without either sending it (mirror-ceremony; mirror-bander kcv prints a key's check value, and custody covers a key that lives in an HSM).
Forward secrecy, optional. A corridor secret held in a file can be turned into a calendar hash ratchet at the ceremony:
mirror-bander ratchet-start --root-file root.txt --rule rule.json --out epoch0.txt
rule.json is the ratified calendar, for example {"period":"week","origin":"2026-10-05","grace_days":7}.
- Epoch 0 is
HMAC(root, "mirror:ratchet:v1:0"). Each later epoch is the keyed hash of the one before. - Both banks compare epoch 0's check value, then destroy the root.
- A stolen epoch secret opens its own epoch and later ones, never an earlier one.
The ratchet turns on the calendar, not per trade. A per-trade ratchet would need the two banks' chains kept in step message by message, and one missed trade would split them. With the calendar, each bank computes the epoch from the shipment's date. Banding is unchanged: an epoch file is a corridor secret like any other, and the operator cannot tell a ratcheted corridor from any other. The honest limit: backups and snapshots of an old epoch file defeat it, and a key held in an HSM gets forward secrecy by rotation instead.
6. Ratify: a start, and if wanted an end#
A table is proposed and ratified by quorum (corridor.propose, corridor.ratify) and becomes part of the signed registry.
The shape the operator admits. A clear is only as strong as the window its legs agreed within, so a new corridor must be:
- closed (
closed: true). A table's outer bands run to zero and to infinity, so on an open table two legs four times above the last edge share the top band and clear. On a closed table a price outside(first edge, last edge]commits markers that match nothing: it can only read divergent, and goes to review. - ceilinged (
max_ratio, above 1 and at most 1.5). The widest price ratio a clear on this corridor may stand for. A clear whose window is wider - because the legs were banded at more tolerance than the ceiling allows - is held,match_ceiling, and the hold is signed and verifies. - consistent: the table's widest band at tolerance 0 must fit under its own ceiling, or that band could never clear.
mirror-bander table-import --closed --max-ratio 1.2 writes the proposal and refuses one outside the rule before anything is signed; the operator refuses it again at /registry/event with a code that names the problem. Corridors ratified before the rule judge exactly as they did. Then band every leg on the corridor with band --closed.
Two optional times bound a table's life:
effective_from(on a ratification): the table is frozen until then. A member cannot widen a corridor the day before a trade it wants cleared. A reconciliation that names it early is refused,table_not_in_force.valid_until(on the proposal): a time-bound corridor. From that moment the table judges nothing. A reconciliation that names it is refused,table_expired. It never falls back to another version. Because a version is written once, the end cannot be extended in place: a renewal is a new version, with the same edges and a later end.
Every verdict carries a salted commitment to the table it was judged under, and names the version when the pair's policy does, so an examiner who opens it can prove which table applied.
7. Run#
Band and reconcile.
mirror-bander bandbands each leg inside the bank and writes only commitments. The operator compares them blind.One FX basis. When legs are invoiced in different currencies, both banks convert on the bank's own machine with one public rate file the pair ratified:
- the corridor names a publisher (never Mirror or the operator), the file's base currency, and a rule that picks the file for a shipment (on-board date, invoice date, payment value date or a fixed date);
- each bank fetches the publisher's file itself;
band --basis EUR,t,CIF,Rotterdam --fx-rates rates.json --fx-rule invoice_dateconverts exactly (rational arithmetic, half-even rounding) and commits the file's pin inside the pricing basis.
Two legs converted with different files commit different bases, and the reading stays undetermined (
basis_mismatch). The operator learns "same FX basis or not" — never a rate, a pair or an amount.A cited market figure as a third record. Two banks comparing an invoice with a payment can only say the two agree with each other; two documents over-invoiced by the same amount agree. A corridor can require a third leg with the role
benchmark: a public market figure (an exchange settlement price, a published assessment) that one bank cites, fetches itself and bands under the shipment's own salt, with a market window the pair agrees.mirror-bander benchmark-leg --shipment-ref S-1 --source source.json --figure-file price.txt --edges <table> --window 2 --secret-file corridor.txt --basis USD,t,CIF,Rotterdam --key member.jwk --out benchmark.jsonwrites the leg. The figure and its citation stay in an owner-only file beside it, under a key the operator's raw-data wall refuses.- The operator compares the benchmark with every trade leg like any required role. A trade leg outside the window around the cited figure is
divergent, and the pair names the benchmark. - The benchmark is kept out of the trade match window, and out of the in-band (fine) judgement, so its wider window never widens what a clear asserts about the trade legs.
- Adding a required role can only add a comparison, so a benchmark can make a reading stricter and never clears what the trade legs alone would not.
- The honest limits: Mirror never sees, fetches or chooses the figure. The counterparty can recover its band, as with any leg. Whether the cited figure prices this grade, basis and date is checked at audit, by opening the leg against the public document. A figure on another pricing basis holds the reading (
basis_mismatch). The benchmark is not a witness: it never satisfies the independence gate.
Progressive zoom. When one bank wants more assurance on one shipment, it signs a zoom request (
mirror-zoom). The request names the shipment's opaque locator, the coarse table, a finer ratified, nested table, the coarse verdict it follows, and a reason from a closed list. The counterparty signs consent or decline within the window.assess()checks it all offline:consented,declined,unanswered,pendingorinvalid.- A consent changes nothing by itself. Both banks re-commit under the finer table (
mirror-nested), and the finer reading is a new verdict. - A decline is a signed fact, not evidence of wrongdoing.
- The operator never sees a request unless a member attaches it to a dispute, a case chain or an examiner pack.
- A consent changes nothing by itself. Both banks re-commit under the finer table (
8. Change#
- Turn the ratchet each period:
mirror-bander ratchet-turn --secret-file epoch3.txt --from 3 --to 4 --rule rule.json --out epoch4.txt. Destroy each epoch's file after itsdestroy_afterdate, or pass--destroy-previous. - Rotate the secret to fresh entropy by corridor version: rotating a corridor secret.
- Renew a time-bound table by ratifying a new version before the old one ends.
- Retire a table by letting its end pass, or by ratifying its successor.
What is a command, and what is a library call#
The bander carries shadow, band (with the FX basis), benchmark-leg, ratchet-start and ratchet-turn, the rotation commands and the ceremony's key check values, and two on-ramps that feed band and the duplicate-financing check: docai-import (document AI) and exposure-claim (duplicate financing). Discovery offers and zoom requests are signed records built by kernel/mirror-discovery.js and kernel/mirror-zoom.js. Today a bank calls them from Node over this release's files; bander commands for both are on the roadmap.