Design decisions
Each decision records one choice between real alternatives: why Dassie works the way it does, and what it chose not to do. Here they all are, one line each. The full text lives with the specification on GitHub.
On this page
Reading a decision
A decision is a short Markdown file in
spec/decisions/.
Each one has the same parts:
- Areas: the parts of Dassie it shapes.
- Facts: what forced a choice.
- Decision: what was chosen.
- Accepted: what the choice costs, said plainly.
- Rejected: the other options, and why each lost.
A decision keeps the reasons. The rules themselves are in the area docs of the specification, and the values are in the code. Read a decision before you change the rule it explains.
Decisions have names, such as own-books, and a name is
never given to another decision, so code and docs can cite it for
good. Older commits and issues cite some decisions by a number
instead; the
table of former numbers
translates them.
"Not built" or "partly built" in a line means the choice is made, but the code does not do all of it yet. What is missing is on What's next.
Engineering, testing and releases
How the code is written, tested, built and shipped. The rules themselves are in Engineering, Testing, Release, Website.
build-system-
A Nix flake builds CI's checks and the releases; plain
cargoandnode --runwork locally. crash-drift-
The simulation rules out a link that crashes drifted past what it survives.
crate-by-crate-builds-
CI builds the Rust workspace crate by crate.
docs-section-
The docs are hand-written pages under
/docs/, searched with Pagefind, and link the spec on GitHub. granite-rocks-
Kopje's rocks are granite: gray blocks with hard edges, stacked, bigger than the dassies, and the brand page says why.
named-decisions-
Decisions are named, not numbered.
nix-flake-on-the-mirror-
NixOS takes a release from a flake on the mirror.
no-simulations-in-tests-
No test runs a simulation: a case one finds becomes a targeted test.
node-and-pnpm-
Tooling on Node and pnpm, not Deno.
own-books-
Each node keeps its own books.
random-seed-simulations-
Simulations run continuously, from random seeds (partly built).
release-integrity-
Releases are signed with minisign, checked before anything is unpacked, and roll back if they do not start.
rust-and-typescript-
What runs in Rust and what in TypeScript.
tigerstyle-
Engineering style: pragmatic TigerStyle and deterministic simulation.
visual-identity-
Dassie's visual identity is Kopje: solid rocks, nimble dassies, first light.
website-hosting-
dassie.land is a bucket behind the mirror's load balancer.
The node, its keys and its owner
Your recovery phrase, the daemon, the owner's RPC and the desktop app. The rules themselves are in Identity, Node, RPC, Desktop.
database-continuity-
The database starts fresh: no data of the original implementation or the early testnet is read.
default-relay-
A node without a hostname keeps the dassiepay.net front door as its relay, unless its owner names another or none.
desktop-app-
The desktop app runs the node in its process and shows the wallet from the node's origin.
device-pairing-
Only the owner on the node's machine pairs a device, with a secret kept in memory.
headless-setup-
An owner who keeps the recovery phrase on the node's host sets the node up with
dassie setup, through the node's own setup route. phrase-format-
A phrase says its realm and when it was made, and corrects its own errors.
post-quantum-node-id-
A node ID commits to an SLH-DSA key beside the Ed25519 key, so that a node can prove it is itself once Ed25519 falls (proving continuity not built).
ready-after-first-step-
A node is up once its engine has committed a step.
rpc-contract-
One protobuf contract serves the wallet and the
dassiecommand, with live data from streams. secrets-at-rest-
Tokens are stored only as hashes; the node key stays in plaintext, readable only by the node.
Peers and the network
How nodes find each other, talk, peer and stop peering. The rules themselves are in Network, Peer protocol.
bootstrap-network-
The project runs five bootstrap nodes in one region, four of which also validate the testnet's settlement hubs.
core-and-periphery-
Nodes with a public IP form the core, and nodes without one join the periphery through uplinks (design, partly built).
ended-for-room-
A peering ended for room stays apart.
ending-a-peering-
A node that ends a peering collects first, and pays nothing.
free-receivers-half-
Free receivers take at most half of the downlinks' places, and a downlink is free until its first settlement.
lazy-downlink-accounts-
A downlink's accounts open once value first moves with it, in room kept for it while its channel is open.
membership-economics-
Bootstrap nodes list the nodes that register; registration is free and throttled until a fee is built.
names-by-earliest-commitment-
A name goes to its earliest sealed commitment, held by a quorum of the bootstrap nodes' lists (design, partly built).
peer-protocol-v1-
Peer protocol v1: the sender of a request is the key its connection proved.
peering-lifecycle-
How a peering is requested, kept alive and ended, and when a node looks for more peers.
periphery-lists-no-neighbors-
A periphery node's link state lists no neighbors, so it may keep many uplinks.
places-by-proved-key-
A connection holds a place by the key it proved.
promotion-to-core-
A node becomes core by registering and being promoted (not built).
protocol-upgrades-
A peer-protocol version is an ALPN name, and a release speaks the one before too; version 2 is spoken alone.
quic-only-
The peer protocol and the hubs' messages travel over QUIC only.
quic-over-websocket-
Where UDP is blocked, a periphery node carries its QUIC packets over a WebSocket, to its uplinks and to a front door as its relay.
settlement-methods-
A peering settles over every hub both nodes are in, and a packet keeps its ledger where it can.
settlement-offers-
A link state offers the schemes a node takes peers on in one list, each with its scheme's own details.
Routing, rates and fees
How a node passes packets on, what it charges and converts at, and how it swaps assets with its peers. The rules themselves are in Connector, Rate feed.
connector-timing-
Connector timing and packet limits: the connector waits as ILPv4 says, where the original did not.
exchange-rates-
Exchange rates, fees and spread: a rate is the median of three independent sources.
open-rate-sources-
A node takes its rates only from sources whose terms allow its use: XRP's from mainnet's XRP/RLUSD pool, the fiat currencies' from central banks, with no peg guard until a dollar token has a price of its own (not built).
packets-in-flight-
Money in flight with a peer stays within a few packets.
passive-rebalancing-
Nodes rebalance passively: inventory pricing, published prices and market makers.
peer-swaps-
Nodes swap assets with their peers, priced by snapshots of ladders per asset.
route-back-is-temporary-
A route that leads only back to the packet's source answers T01, not F02.
unreachable-peers-
A node takes no Prepare from a peer it cannot reach.
weighted-next-hops-
A packet's next hop is drawn at random among its first hops, weighted by the fees each earned us.
Payments
Open Payments and STREAM: how money is asked for, sent and received. The rules themselves are in Payments, STREAM.
close-rather-than-lower-
A receiver never lowers a maximum it told: it closes a connection that no longer fits.
full-or-stopped-short-
A receiver says whether it is full or stopped short.
one-address-per-asset-
One wallet address per asset, booking where the asset arrives.
one-balance-per-asset-
The owner holds one balance per asset, and the node manages the hub's part of it.
open-payments-
Open Payments, fully, and no SPSP.
-
Strangers never take the owner's share of a pool.
paid-within-a-tolerance-
A payment within a tolerance of its amount is paid in full.
path-failures-retried-
A sender sends money again after a too-low rate or a node's final error, until failures without progress stop it.
public-domains-
Payment names live under dassiepay.net, memo types and the mirror under dassie.land.
receive-limit-alone-
A receive limit alone bounds nothing: it is refused.
receive-limit-caps-delivery-
A receive limit caps what payments deliver, not only what they reserve.
unusable-limits-
A limit no payment can use is caught before approval.
Settlement, ledgers and real money
How peers square up on a real ledger, how a node keeps its books, and what stands between Dassie and real money. The rules themselves are in Settlement, Ledger, XRPL.
account-budgets-
Core peers and downlinks each have a share of the peers' accounts, counted by the kind they were opened as.
closing-channels-
A settlement channel left idle closes to disk, whatever the balance.
dsusd-
A testnet dollar of our own, bought only with XRP through a pool we keep at the market.
external-assets-
External assets apart from settlement schemes.
issued-assets-
An issued asset's issuer is the owner's counterparty, and a dollar token pauses off its peg (transfer fees not built).
ledger-resets-
A ledger below the newest seen is a reset only on the testnet, and only once its UNL validates it (the UNL's part, the network's constant as the gate and a proven absence not built).
mainnet-schemes-
Mainnet has schemes of its own, and a ledger runs only in its node's realm (a live node without the test network's defaults not built).
own-fulfills-
Each node books its own Fulfills.
owner-ledger-
The owner's funds on each ledger are one pool with a limit, and what the node gains or loses is the owner's.
real-money-
The conditions that must hold before a node takes real money.
resident-peers-
A peer is in memory only while it is needed: a downlink while it is connected, a core peer while its channel is open.
scheme-names-
A scheme's ID names its ledger, network and asset, and a wallet address names the asset alone.
stub-in-debug-builds-
The stub scheme runs only in builds with debug assertions.
synced-before-peering-
A node peers on a scheme only once it has seen its ledger.
thresholds-in-packets-
A link's thresholds are counted in its largest packet.
verified-ledgers-
The node books only what ledgers its own UNL validated prove (partly built).
Settlement hubs
The shared ledgers that peers settle over. The rules themselves are in Settlement hubs.
epoch-handover-
Each validator set runs an epoch of its own, and a repeat finalizes an epoch's last block.
finality-after-any-outage-
A hub finalizes again after any outage, in bounded memory.
hub-founding-
The sponsor founds a hub over a stream of its own, and a quorum's signatures of the genesis found it.
hub-keys-by-network-
A hub's keys name its network, and a validator validates on its owner's network.
hub-named-when-added-
A hub scheme names its hub from the moment it is added (moving a scheme to another hub not built).
hub-protocol-version-
A hub runs one version of the hub protocol, which its ID commits to (moving a hub to another version not built).
hub-scheme-names-
A hub scheme's ID names its underlying ledger and its asset.
hubs-only-
Peers settle only over settlement hubs.
settlement-hubs-
Settlement hubs: ledgers kept by validators and backed by an escrow on the XRP Ledger (design, partly built).
token-hubs-
A hub may hold an issued token; its issuer's freeze pauses it, a clawback ends it, and its fees are paid in XRP anyone may send (partly built).