5.4.0
First public releaseThe public site goes live: a fee engine with a full breakdown, a payout rail catalogue with real limits, a corridor-based URL architecture, and the transparency pages that make all of it checkable. This log starts here, on the real publication date.
Added(21)
src/lib/pricing.ts
Fee engine with a full breakdown. Network cost is taken in kind on the asset before conversion, then our margin and the rail fee each get their own line. An accounting invariant checks on every quote that gross minus the sum of the lines equals net exactly, to the minor unit: if it does not balance we raise and refuse to quote rather than let a hidden margin through.
src/lib/pricing.ts
Spread policy published and enforced by the code: 90 basis points base, 35 more on a volatile asset, 25 more on a beta corridor, minus 15, 30 or 45 basis points across three volume tiers. No other charge exists on our side.
src/lib/pricing.ts
Reverse input: you can type what you want to RECEIVE and the required deposit is resolved by binary search. Fixed fees make the function non-linear — an algebraic inversion would be off by a few cents every time.
src/lib/money.ts
Every amount of money travels as an integer of minor units (bigint) and every rate as a Decimal. No amount goes through a JavaScript float, where 0.1 + 0.2 is not 0.3.
src/lib/rates.ts
Rate freshness is checked before every firm quote. Past the source’s maximum tolerated age the engine raises a stale-rate error and refuses to quote. Serving a stale price from a cache is treated here as a financial bug, not a performance one.
src/app/api/quote/route.ts
Public quote endpoint. Schema-validated input, no-store response, full line-by-line breakdown with the mid-market rate, the effective rate and the total gap in basis points. Rail limit breaches are returned in the response body rather than as an HTTP error, with the exact limit.
src/data/payout-rails.ts
Payout method catalogue carrying, for each one, the settlement currency, the countries served, p50 and p95 delays, business-day and cut-off rules, minimum and maximum amounts in minor units, real fees and the beneficiary field schema.
src/data/corridors.ts
Corridor-based URL architecture. A multi-country rail yields a single page per asset: SEPA is identical in France and Belgium, two pages would say the same thing. A local rail — PIX, SPEI, M-Pesa, NIP, Interac — yields one page per country, because the country carries the identifier format, the limits and the tax treatment. The raw ~2,200-combination matrix drops by an order of magnitude, and every surviving page carries facts only it can carry.
src/data/corridors.ts
Launch waves and an indexing gate. A corridor is only offered for indexing once its wave’s content is actually written; the others stay reachable and functional but out of the index. We do not ask a search engine to index a page we have not written yet.
src/data/assets.ts
Asset catalogue with base-unit decimals, accepted networks, the minimum deposit below which network fees eat the operation, and the rate lock duration — longer on a stablecoin than on a volatile asset.
src/data/networks.ts
Network catalogue with the required confirmation count, average block time, the address validation pattern and, for XRP, Stellar and TON, the memo field whose omission loses the funds.
src/data/geo.ts
Geographic reference data: open countries, countries in preparation, and refused countries with the reason — international sanctions, restrictive measures, or an unacceptable money laundering risk. The reason is published country by country.
src/config/company.ts
Single registry of factual claims about the company. Legal name, registration, incorporation year, regulatory status, volumes, reviews: each value is either filled in or marked as pending — and a pending value is never displayed. The site may only assert what is computed from its own data.
src/components/JsonLd.tsx
Structured data that omits every unfilled field. No founding date, no licence number and no aggregate rating are declared to search engines until they are real.
src/i18n/routing.ts
Locale prefix on every language, French included. Serving the same page at “/” and “/fr/” always ends in duplicates; symmetry removes every special case in hreflang and canonical tags.
src/app/[locale]/statut
Service status page: one component per payout rail and per watched network, the exact description of what the probe will check, the severity policy and the incident report template. No availability percentage appears there until it is measured.
src/app/[locale]/docs
Public API documentation: authentication, pagination, idempotency, error catalogue and signed webhooks. The sample responses are real responses from the quote endpoint, not mock-ups.
src/app/[locale]/reclamations
Written complaints procedure: what separates a complaint from a support request, the three escalation levels, the delays we hold to, and what happens if the answer does not satisfy you.
src/app/[locale]/presse
Media kit: downloadable logos generated from code, palette with exact values, short and long descriptions ready to quote. No press coverage is listed, for lack of coverage to cite.
src/app/[locale]/affiliation
Affiliate programme paid on margin actually collected, never on gross volume: a partner gains nothing by pushing a corridor that costs the customer more.
src/app/[locale]/plan-du-site
Site map generated from the data, with an instant search filter. Every published page appears there: if a page exists and is missing from this map, that is a defect.
Security(3)
src/lib/rates.ts
Production guard: the deterministic rate source used in development cannot boot in production. The process refuses to start rather than quote frozen prices.
src/middleware.ts
Geographic refusal before any render, with an explicit HTTP 451 rather than a 404: when we refuse, we say why. The refusal is re-checked server-side at order creation, since an IP address alone proves nothing.
next.config.ts
Security headers on every response: HSTS with preload, framing denied, MIME sniffing blocked, restricted referrer policy, cross-origin isolation, and microphone, geolocation and payment permissions switched off.
Policy(5)
src/data/payout-rails.ts
Collection rails — iDEAL, Bizum, BLIK, TWINT, Satispay, MB WAY, QRIS — are declared unavailable with their reason instead of being hidden. They let you pay a merchant, not receive funds; each one points to the rail we use instead.
src/data/payout-rails.ts
Zelle is marked permanently unavailable: its rules contractually forbid third-party commercial disbursement. No provider can push funds through it compliantly for us, and saying so beats letting people hope.
src/data/payout-rails.ts
Rails that are built but closed carry their exact regulatory reason: TDS withholding and FIU-IND registration for UPI, an MAS licence for PayNow, SARB reporting for South Africa, AUSTRAC registration for PayID, a licensed partner for PromptPay. We would rather name the obstacle than announce a date.
src/data/assets.ts
Monero is in the catalogue, flagged as an enhanced-anonymity asset and not offered. European anti-money-laundering regulation requires providers to delist it from 10 July 2027; we show it and explain it rather than making it quietly disappear.
docs/CONVENTIONS.md
Enforceable editorial rule: no founding year, no licence number, no processed volume, no customer count, no testimonial and no partner logo is hardcoded into a page. Maturity has to come from the depth of what is written, never from fabricated proof.