The broker reference implementation of the KOTVA standard.
KOTVA's coordinator contract names the parts of a peer-to-peer system that genuinely need one party in the middle: routing packets past a NAT, bridging to legacy mail, giving two strangers a place to rendezvous. Pier is the reference implementation of that contract — the code you read to find out what the prose actually means, and the code you fork when you decide to run one yourself. Every kind it houses is accountable, swappable and self-hostable, and what it can see of your traffic is declared in a signed descriptor rather than promised in a README.
Nobody runs Pier for you. There is no default instance, no hosted tier, no directory to register in and no operator behind it. Every pier that exists is somebody's own — stood up under their own name, on their own terms, answerable to their own users. A client uses whichever one it can reach and leaves when it likes. That is the entire point of the name: a pier is infrastructure that serves vessels it does not own, and the berth belongs to whoever ties up there.
pier-client JS SDK remain the working implementation in
production today. Four of the eleven coordinator kinds are built; the rest are
declared scaffolds, itemised below.
Read the full status →
-D warningskotva-* crates in the KOTVA repo, which this workspace consumes.
Every manifest here sets publish = false, the workspace default does too
so a new crate inherits the rule, and scripts/check-no-publish.sh fails
the build on any cargo publish — with a crate-count floor, so an empty
glob cannot report a vacuous pass.
console/ built with
VITE_MOCK=1. The console says so itself: the amber strip along the top of
the shot is its own permanent fixture-data disclosure, on every page of it. Declared
visibility, the COORD-1..8 strip, and a "Declared, not verified" warning are
all on-screen precisely because none of them is a promise this page is willing to make
silently.A pier serves vessels it does not own.
Many independent piers exist; you use whichever one you reach, and you
leave. The same shape survives
in the software: a coordinator is hired for a function, not depended on
for identity. It sits on the wire between two peers only because one of
KOTVA's eleven coordinator kinds needs to — routing around a NAT, bridging to legacy
mail, brokering a rendezvous — and it leaves no residue when you stop hiring it: no
migration, no re-keying, no lock-in. The one kind that genuinely holds your data at
rest rather than in flight, infra-service, is the exception the spec
calls out by name, and it is not part of Core v1.
Content-visibility is a checkable type, not a policy promise.
pier-economics models it as VisibilityClass
(blind / blind-routing / terminating) crossed
with AssuranceLevel (structural / attested /
declared) — CONTRACT §3 — and pier-conformance's
COORD-1..8 harness checks a coordinator's implementation
against its own declaration instead of trusting prose. A coordinator authorizes from
identity and rate; it never classifies content on a delivery path — that judgement
stays with the recipient.
Declared content-visibility
| Kind | Class | Assurance |
|---|---|---|
| relay | blind | structural unconditional |
| reachability-adapter | blind-routing | structural own domain · declared shared vanity |
| media-relay | blind-routing only if sframe_required | structural when sealed · otherwise the class itself is terminating |
| gateway | terminating | disclosed exception, not blind by design |
reachability-adapter only
promises it is blind; nothing structural stops it lying, and a relying
party cannot check a declared claim independently (CONTRACT §3.4).
Across the eleven kinds only relay and
reachability-adapter are unconditionally blind — an SFU that will
accept unprotected media if offered can read it, so media-relay
earns blind-routing only where the operator published
sframe_required. Disclosed trust is this family's majority position,
not its exception.
Content-blind at the wire
Every coordinator function lives behind the same contract.
A coordinator is any party providing a function the peer-to-peer substrate can't provide reciprocally: a global view, a scarce resource, a legal anchor. CONTRACT §5 is the canonical, exhaustive list at eleven — no other document may enumerate a different count. Four are running implementations here today; five are signed, conformance-tested scaffolds whose own function (ranking, arbitration, attestation…) is disclosed future work rather than a silent stub; and two have no crate in this workspace at all. The Status column below says which is which, per kind, with the test counts it is drawn from.
| Kind | Provides | Visibility | Status in this workspace |
|---|---|---|---|
| gateway | Legacy mail bridge — MX, SPF, DKIM, DMARC, MTA-STS, SMTP/IMAP/POP3 | terminating (legacy leg is plaintext) | built · 320 tests |
| relay | Mesh reachability for NAT'd peers — a real libp2p Circuit Relay v2 server | blind / structural | built · 12 tests |
| reachability-adapter | ngrok-style public subdomains for box services, SNI-passthrough | blind-routing | built · 32 tests — control channel not yet Noise-encrypted; zone and descriptor modules not started |
| media-relay | Orchestrates an external SFU (coturn / livekit-server) — it does not embed one | blind-routing only where sframe_required; else terminating | orchestration only · 24 tests — no media plane, no RTP and no SFrame code lives here |
| indexer | Search / discovery over an opt-in public corpus | corpus public; query channel terminating unless attested | scaffold · 8 tests |
| labeler | Moderation labels, opt-in and subscribable | n/a — labels public objects | scaffold · 7 tests |
| matcher | Real-time supply↔demand matching | terminating always; optionally attested via TEE | scaffold · 8 tests |
| arbiter | Dispute resolution over disclosed evidence (staked jury) | terminating for evidence, disclosed | scaffold · 7 tests |
| oracle | Physical-world / real-fact attestation | terminating, disclosed | scaffold · 7 tests |
| infra-service | Managed infrastructure — the four DEPOT elementals bucket, volume, edge-fn, box, plus a control plane | per service — bucket/volume blind only for what the client encrypted; edge-fn/box terminating | no crate — spec is DRAFT and deferred, not Core v1 |
| custodial-escrow | Holds the trade float for a trade window | terminating for evidence, disclosed | no crate — commerce extension, not Core v1 |
compute kind and folded it into
infra-service: renting a GPU to run a model is running code you did not
write on hardware you do not hold, which is an edge-fn whose class declares
gpu-count — an attribute wearing a kind's clothes. This workspace has not
caught up. pier-economics's CoordinatorKind enum still carries
Compute and has no InfraService variant, and a
pier-compute scaffold crate still sits in the workspace. Both counts read
"eleven"; they are not yet the same eleven. The rename is outstanding work, not a
position.
What infra-service will mean
The infra-service kind is specified by
DEPOT, the KOTVA family's
managed-infrastructure profile. DEPOT names the elementals of a cloud and the
control plane that provisions them — and stops there. It defines no runtime, no
storage format, no query language, no economics and no cloud. Four irreducible
resources, split bytes-versus-code against cold-versus-hot:
| Elemental | Is | Adopts, rather than invents |
|---|---|---|
| bucket | bytes, cold | S3 API + content-addressing + HTTP caching |
| volume | bytes, hot | virtio-blk / NVMe-oF / iSCSI |
| edge-fn | code, cold | WASI / OCI |
| box | code, hot | cloud-init, and any OS |
Everything a platform sells beyond those four —
a database, a queue, a CDN, an image registry, a static site, hosted inference —
composes from them and is a
product, never a spec change. An operator brings its own implementation: back
bucket with Tigris, MinIO or Ceph, back box with a rack in
a basement. DEPOT deliberately cannot tell, and does not care. What it requires is
that the operator declare honestly what it can see, speak the adopted standard,
accept the same control verbs, and let the user leave with their bytes in a format
someone else can read.
matcher costs
nothing; leaving a box or a volume costs a migration —
which is why swappability, not cryptography, does the work in that profile.
Swapping a coordinator is a config change
Same identity key, same descriptor shape — only kind and the
tariff move. No migration, no re-keying, no data to carry over, because a coordinator
was never the thing your identity depended on.
kind = "reachability-adapter" identity = "b47a…9de3" visibility = "blind-routing"
kind = "relay" identity = "b47a…9de3" visibility = "blind"
No token. Existing rails, signed receipts.
A signed Descriptor carries an identity, a kind, a declared
visibility, and an optional tariff — structurally nothing else. There is no stake
field and no price-ranking field to invent one from later. Billing runs on prepaid
credit: a payer tops up a balance over an existing stablecoin or fiat rail, usage
debits it, and every debit gets a signed UsageReceipt the payer can
verify. Read .verify() honestly: it proves the coordinator
signed a claim, never that the claim is true, and never that no unreceipted
charge happened elsewhere — a one-directional audit, demonstrated by a test rather
than asserted in prose. Pier itself holds no funds and brokers no settlement; it
adapts onto rails it doesn't operate.
Honest limits
Residuals the project states about itself, not ones a reader has to find:
UsageReceipt::verify() proves the coordinator's key signed a claim,
never that the claim is true or complete.
SettlementRail and StakeVerifier each ship exactly one
mock reference adapter (an in-memory ledger; a fail-closed no-stake rail). The real
Stellar adapter is excluded from the workspace and from CI, and its own manifest
says so in capitals: UNVERIFIED AGAINST LIVE STELLAR. Disclosed in-crate,
not merely absent.
compute crate are scaffolds. A real signed descriptor and
conformance posture exist; the kind's own function does not yet. Their tests assert
the declaration — that it signs, that it declares the right visibility, that
check() passes — never a behaviour.
media-relay orchestrates an external SFU; it does not embed
one. It writes config and supervises a coturn /
livekit-server binary. There is no media plane, no RTP and no SFrame
implementation in this crate — bind-don't-reinvent, by design, and large-scale SFU
capacity is out of scope for it.
pier-conformance is a trait plus a checklist, not a replayed wire-vector
suite — there are no vectors in this repo. COORD-5 (does observed behaviour match the
declaration?) is decidable only against real traffic, so the harness returns it as
Behavioral; a Behavioral finding does not block
is_conformant(). For a scaffold, conformance therefore means only that
the descriptor is well-shaped and its declared posture is self-consistent.
Descriptor / Tariff /
UsageReceipt (canonical §18.1.1 CBOR, Ed25519, DS-tagged) is logged for
the spec session but not yet ratified into coordinator/CONTRACT.md.
Run the console, or build the workspace.
Pier is MIT OR Apache-2.0
licensed, with no token, ever — the broker reference implementation of the
KOTVA
standard. Nothing here is published to crates.io, so there is nothing to
cargo add: you clone it, read it, and run your own.
# http://localhost:5173, VITE_MOCK=1 by default
cd console
pnpm install
pnpm dev
cargo build
cargo test # 556 tests
cargo clippy --all-targets -- -D warnings
go build ./... go test -race ./...
./scripts/install.sh \ --domain relay.example.com
Full commands, flags and CI gates: README → Development.
Read the contract. Read the code.
MIT OR Apache-2.0. Every claim on this page traces to a crate, a test, or the README it was drawn from.