Fleetmesh fleetmesh

The fleetmesh Protocol · part 2 of 10

Boundaries & governance

Isolation boundaries between private infrastructure and the public mesh, alongside decentralized governance.

Two networks

Boundary Architecture Between Mesh & Private Infrastructure

Operators joining the mesh often maintain existing infrastructure. Reusing an existing production cluster directly as a mesh node is a dangerous shortcut. That shortcut produces three predictable failures: a network that collapses if a business fails, private users exposed to unvetted traffic, and a single operator gaining an unearned veto. Fleetmesh defines the junction between private estates and the public mesh as a strict security boundary. These rules apply universally, from commercial cloud operators to home servers.

AN OPERATOR’S OWN SERVICES THE MESH — ALPHA, OPEN private relays · SLA custodial signer accounts · billing private blob storage databases · bus · secrets bootstrap anchors third-party anchors edge nodes · behind NAT leaves · phones, browsers grants · reports · receipts mesh gateway wss · NIP-77 only no shared database · no shared bus · no shared secrets · no shared identity
The gateway is an ordinary relay client. It authenticates to the local relay the way any client does, reads what it is permitted to read, and writes into the mesh; nothing on the operator's own side imports a mesh library or opens a mesh port. The mesh panel is drawn open because its membership is: any node may join it, and none of them can reach anything on the left.

The gateway

A gateway is a separate process, in its own isolation boundary, holding its own node key, its own storage and its own resource budget. Its only interface to the operator's own services is wss:// plus NIP-77 range sync — the same protocol any third-party client speaks. That is deliberately the weakest coupling available, and it buys three things:

  • The estate cannot be broken by the mesh. A malfunctioning or attacked gateway appears to internal relays as a single misbehaving client. Relays handle this natively with existing rate limits and connection drops.
  • The mesh cannot be broken by the estate. The gateway is one anchor among many. If the entire estate behind it is down, the mesh loses one node's coverage.
  • The boundary is testable. Internal isolation is mechanically provable. The gateway holds no credentials beyond an ordinary relay WebSocket connection. This is a verifiable deployment property rather than an assumption about application logic.

What crosses, in each direction

Direction Rule
estate → mesh Per-shard, opt-in, and the opt-in belongs to the account that owns the data — never to the operator carrying it. A relay publishes nothing into the mesh until the shard is turned on, and turning it off stops new publication immediately. Public events only; the never-crosses list below is enforced at the gateway and again at every receiving node.
mesh → estate Quarantined. Mesh-sourced events land in a separate store and are never auto-promoted into the relay behind the gateway. Backfill is requested per shard and arrives as an explicit import with its provenance recorded. Anything else lets strangers write into a service whose users never consented to them.
reputation Does not cross in either direction. A pubkey the mesh has judged hostile keeps whatever service its own relay grants it; an account in good standing on that relay starts at probation in the mesh like everyone else. Delegating moderation of your own users to a permissionless network is not a feature, and importing a stranger's standing is not either.
identity Separate keys. A mesh node key is generated for the mesh and lives only in the gateway's own secret store. Existing service identities MUST NOT be reused, so a mesh key compromise never produces a signature anyone trusted for something else.
money & status Mesh traffic is never metered to a user and never counts against a quota. Mesh incidents are not incidents of the service beside it, and no service commitment anywhere should make a statement about the mesh.

Never crosses, in any version

Data Why
custodial keys Encrypted nsecs, the secret that unlocks them, and signer session state. Replicating them turns custody into distribution.
kind 24133 NIP-46 signer traffic. Ephemeral, and federating it would expose every pairing and every signing event of every reachable signer.
kind 1059 Gift wraps, under the rule in § Replication. Stated there once and normatively; repeated here only because the boundary table would be misleading without it.
billing & push Payment records, balances, push subscriptions. Commercial and contact data belonging to people who never joined the mesh.
client IPs Connection metadata stays on the node that observed it. Reports carry counts, never addresses.

Nothing is a constant

relay.example.org appears in this specification exactly as an example. Three rules keep it that way:

  • Bootstrap is a file, not a constant. Default peers ship as a plain, editable file. A single --bootstrap CLI flag bypasses this file entirely. A build shipping an empty bootstrap list MUST operate without error. The composition rule is staged progressively (see § Governance) to allow network bootstrap from genesis without artificial barriers.
  • DNS seeds are optional. A node MAY discover peers through DNS TXT records, the way Bitcoin does, and MUST NOT require them. Losing every seed domain slows discovery for new nodes and does nothing to established ones.
  • Protocol identifiers are neutral. The https:// URIs naming the DIDComm protocols, the gossipsub topics and the transport ALPNs all sit under fleetmesh.org rather than a product domain. They are identifiers, never dereferenced, so this buys nothing at runtime — it buys not having to hold a flag day later, when renaming stops being free. See § Governance.
The unplug test

The conformance suite includes a dedicated run with all default anchors and fleetmesh-operated infrastructure removed. The test disables all gateways, seed domains, and sets fleetmesh.org to resolve to nothing. Discovery, bilateral peering, state synchronization, grant issuance, and conformance reporting must all execute successfully. This test runs in continuous integration on every commit to enforce absolute infrastructural independence.

Governance

Protocol Assets & Decentralized Governance

Network governance spans four distinct operational assets. Treating them as a single problem creates unnecessary bureaucracy. Separating them reveals that three are already decentralized by design, and the fourth requires no central authority.

AssetWhat it actually risksDisposition
protocol identifiers Nothing technical — they are never dereferenced. Only that a network meant to outlive a company carries its name. registered fleetmesh.org, held as the project’s own name rather than a product’s.
kind registrations Nothing, once submitted. A merged entry in registry-of-kinds lives in a repository neither project owns nor can revoke. self-neutralising Submitting them is itself an act of decentralisation.
bootstrap.toml Soft power over who a new node meets first. Not a takeover vector — established nodes have persisted peers, and one --bootstrap address bypasses it entirely. unsigned A convenience whose composition is disclosed. See below.
protocol versions Looks like the dangerous one: whoever decides what the protocol is decides what everyone must implement. It stops being dangerous when nobody decides. declared, not decreed

Versions are declared, not decreed

There is no release authority, and there is no signer set. A k-of-n scheme, under which a change is valid once k of n signers endorse the announcement hash, operates by decree. Everything else in this document relies on empirical verification, and a version is not the one place to make an exception.

Everything else here works by declaration. A grant is a published budget. Coverage is a falsifiable claim. Conformance is your signed statement measured against my observation. A compute result is a hash the seller signs and a re-run can contradict. In every case the shape is the same: declare, be observed, and let divergence be the offence. A protocol version is exactly that kind of claim, so it gets exactly that treatment.

Each node declares its protocol version in its own descriptor. The descriptor names the protocols the node implements, each with a version, and two nodes peer on the ones they share: same major, the peer's minor at or above this node's floor. The required peering and budget protocols must be compatible or the peering is declined with UNSUPPORTED_PROTOCOL; a peering whose policy needs another protocol the peer lacks is declined the same way. The schema digest records which schema a node was built from and is surfaced to the operator, not refused on its own. There is no governance announcement, notice period, or signing committee. A version exists when active nodes declare it and disappears when they stop. Adoption is measured directly from public on-wire data.

A version is a digest, and a protocol is a version

Version names alone are insufficient. Two independent operators could deploy incompatible implementations both labelled fleetmesh/1 and discover discrepancies only after corrupting state. Declarations therefore carry a canonical digest over the whole schema, which says exactly what a node was built from. Compatibility, though, is decided one protocol at a time: each protocol identifier carries a version (sync/1.0) that MUST move when its wire moves, schema/PROTOCOLS records a digest of each protocol's block against that version and CI refuses a block that changes under an unchanged version. Nodes peer on the protocols whose versions are compatible and surface a differing whole-schema digest to the operator instead of refusing it.

what the version digest covers — and what it deliberately does not

kinds.json       every event kind this version defines: number, class,
                 required and optional tags, content type
messages.json    every DIDComm protocol: piuri, message types, body schemas
constants.json   every number the arithmetic depends on: the 110% threshold,
                 the divergence floor, AIMD step, tier weights, hop limit,
                 window sizes, sampling defaults

digest        := sha256(kinds.json || messages.json || constants.json)
                 each canonicalised, concatenated in that order

NOT covered: this document's prose, examples, rationale, section order,
or any wording anywhere. A typo fix MUST NOT fork the network.

Scoping the digest to the machine-readable schema is the whole trick. Too narrow and incompatible implementations still collide silently; too broad and correcting a sentence becomes a breaking change. What two implementations must agree on byte-for-byte is exactly what belongs in the hash, which is the same rule § Governance already applies to deciding which names are the protocol's.

Each protocol identifier carries a version of its own, as in sync/1.0. Those are informative labels; the digest is normative, and a node negotiates nothing below it. An identifier's version is bumped when its messages or fields change, so a reader can see which protocol moved without diffing the schema.

This mechanism is not new to the document either. Kind 11801 already pins an operator's policy document by digest, and changing that document without republishing the digest is already an S2 misreport. Version pinning is the identical mechanism pointed at the protocol instead of at the policy.

What freezes fleetmesh/0, and who says so

Nobody says so, because declaration is the only mechanism there is. fleetmesh/0.1-draft becomes canonical fleetmesh/0 when at least three independently-operated anchors declare and peer with an identical protocol digest for 30 consecutive days with zero adverse divergence reports between them. Independence is judged under the Three-Layer Operator Independence Model below.

That is an observation about the network rather than a decision taken on its behalf. The condition is checkable by anyone holding the descriptors, no announcement makes it true, and no announcement is required. Until it holds, the digest may change on any day and nobody is owed a migration — see § Alpha contract.

Starting at fleetmesh/0.1-draft

fleetmesh/0.1-draft
Where the network starts, and where it is today. It promises nothing: the schema may change on any day, and two nodes both declaring 0-draft with different digests are simply incompatible — correctly, and with neither at fault. Nobody should build anything durable against it, and saying so in the version string itself is more honest than a warning in a document people skim.
fleetmesh/0
The first frozen version. Its digest is fixed at the moment of freezing and never moves again; a change after that is fleetmesh/1, not an amended 0. What event constitutes the freeze, and who gets to say it has happened, is genuinely unresolved — see § Open questions.
fleetmesh/N
Thereafter. Versions coexist rather than superseding each other: a node may declare several and speak whichever a given peer also declares. An old version dies when the last peer willing to grant it capacity stops.
Enforcement already exists

A node that declares a version it cannot speak commits a misreport. This triggers an S2 finding under the severity ladder. The peer's signed descriptor serves as direct cryptographic evidence. No new severity class, evidence type, or out-of-band machinery is required.

What the signing key was also doing

It had three jobs, and only one of them was versioning. The other two need answers:

signing bootstrap.toml
Dropped, not replaced. The signature was ceremony over a convenience file. Safety relies on manual escape hatches: named anchors carry their own signed descriptors, verified directly during connection setup. An editable unsigned list provides equivalent operational safety without unnecessary ceremony.
urgent advisories
A security advisory becomes a report, weighted by the reader's existing trust in whoever published it, exactly like any other finding in § Trust weighting. Note the key never forced an upgrade: it was a notification channel, and a notification channel does not need to be an authority to work.
What this costs

Fragmentation moves from prevented to visible. Nothing stops the network splitting into islands that never converge. The digest only guarantees that a split is loud and immediate rather than silent and slow. Deprecation gets slower too: without a flag day, an old version dies only when peers individually stop granting it capacity, which is a local reputation decision like every other one here. A network that cannot be steered also cannot be steered well, and that is the trade. Every other decision in this document has already been made in the same direction.

What the shipped bootstrap list may contain, and when

The obvious rule — "name at least three independently-operated anchors, no operator holding a majority" — is the right end state and an impossible beginning. At genesis there is one operator. A rule nobody can satisfy is not a safeguard; it is a line everyone learns to ignore. So the composition requirement is staged, and what holds at every stage is disclosure rather than diversity:

Independent operatorsWhat bootstrap.toml MUST do
1 — genesis Carry operators = 1 and name that operator. A node reading it can then see, without asking anyone, that its first view of the network comes from a single party. That is an acceptable start and an unacceptable thing to leave implicit.
2 Name both, and MUST NOT be sole-operator. The second operator is the point at which "diverse" starts meaning something, and the file should reflect it the day it becomes true rather than at the next release.
3 or more The full rule binds: at least three, with no single operator holding a majority of the entries. From here the staging is over and the requirement is absolute.

Every stage maintains the manual escape hatch. A single --bootstrap address supplied via CLI bypasses the file completely, and builds shipping empty bootstrap files operate normally. The file is an optional convenience whose composition is disclosed. It never functions as a gate.

The three-layer operator independence model

Operator identity is an empirical socio-economic fact. Node identity is a cryptographic key. Because key generation is free, treating "independent operator" as a purely mechanical wire primitive is a category error. Fleetmesh resolves operator independence across three decoupled layers:

1. Mechanical baseline (wire diversity)
Two anchors qualify as mechanically distinct if they declare distinct Nostr operator pubkeys in kind 11801, advertise endpoints on separate BGP Autonomous Systems (ASNs) or /24 IP prefixes, and hold distinct keyAgreement keys. This protects against physical routing outages and single-datacenter failure modes.
2. Subjective leaf sovereignty (local risk allocation)
Leaf dual-mediation is an operational resilience recommendation, not an on-wire consensus gate. A leaf selects two mediators that the leaf operator believes to be independent within its own subjective trust horizon. If a leaf chooses two anchors run by the same entity, the protocol functions normally; the leaf simply assumes its own downtime and correlation risk.
3. Fraud deterrence via the severity ladder (S2 misreport)
False independence attribution is explicitly priced. If an entity operates multiple anchors under collusive shadow identities to capture bootstrap slots or deceive peers, this constitutes an S2 Misreport (structural dishonesty). Evidence of shared signing infrastructure, identical payout destinations, or collusive receipt chains is grounds for a kind 30802 adverse report downgrading the offending operator to probation or revoked.

Where this document lives

The specification is published at www.fleetmesh.org/spec.html and developed in the open. The source code, brand assets, and build configurations reside in a public repository dedicated to the public domain under CC0 1.0. This mirrors the open licensing of official Nostr NIPs. A public standard must remain unencumbered by proprietary claims, allowing independent implementations to build freely.

Changes arrive as merge requests against that repository. The line that matters is not editorial: anything altering kinds.json, messages.json or constants.json changes the version digest, and therefore changes the protocol version a conformant node declares. Prose, examples and rationale do not. Merging a patch is never by itself what makes a version real — nodes declaring it is.

Which name goes where

One rule, applied without exception: fleetmesh names the protocol, and reference implementations adhere strictly to it. A string that two independent implementations must agree on byte-for-byte belongs to the protocol; everything else belongs to whoever is accountable for the code.

fleetmesh owns reference implementation owns
DIDComm PIURIs · gossipsub topics · transport ALPNs · the fleetmesh:// invitation scheme · the kind definitions · this document crates/mesh* in reference workspace · the fleetmesh-node daemon binary · the gateway · anchors on operator hostnames

The crates use standard names without colliding with third-party implementations, and a bug report should be unambiguous about whose code it is against.

What fleetmesh.org is, and what it must never become

Domain names frequently become centralized retrieval bottlenecks for peer lists, release binaries, and schemas. A single canonical host creates an unacceptable single point of failure.

Serves, never gates

Everything fleetmesh.org hosts MUST be a convenience mirror of something that already exists as signed data reachable without DNS. No node may require it to start, to find peers, to validate a release, or to resolve any identifier. It is a faster path to bytes that are obtainable anyway — and the unplug test now deletes it too.

Served at fleetmesh.org Canonical source, always
/.well-known/nostr.json NIP-05 for the project identity. A lookup aid and nothing more: no claim in this protocol has ever been validated by a DNS answer.
/bootstrap.toml A mirror of an unsigned file — there is no signer set, per § Governance. Fetching it from here confers no authority on it whatever, exactly as if it had arrived on a USB stick. What a node verifies is each named anchor's own signed descriptor at connection setup; the list is a hint about who to ask first, and nothing else.
_seed.fleetmesh.org TXT DNS seeds, one of four discovery paths and required by none. Losing them slows a first run and does nothing to an established node.
/npk/<sha256>.npk Release artifacts, keyed by their own hash and therefore immutable. A mirror, not a registry: the bytes are verified against the signed release, so serving them confers no authority and losing them costs a download location rather than a package.
/spec, /schema This document and the kind definitions. The kinds’ real home is registry-of-kinds, which nobody here controls.
nothing else No API, no directory service, no registry, no node that other nodes are expected to reach. The moment the domain serves something with no offline equivalent, it has become the hub this design exists to avoid.

Mirror hosting is an operational convenience. A node's declared protocol digest is authoritative over external mirror files. When declarations diverge from mirror files, nodes trust the direct peer declaration and distrust the mirror.

Neutrality timeline

Fleetmesh functions today as an open project identity and protocol namespace. The domain registration is held for the project. Maintaining a dedicated, neutral domain ensures eventual stewardship transfer occurs smoothly. When governance triggers fire, the project transfers an established name rather than conducting contentious rebranding negotiations.

The trigger for revisiting

Written down so it is not a judgement call made under pressure later. The question of a neutral organisation — entity, domain transfer, formal membership — is reopened on whichever comes first:

  • A second independent implementation of this specification ships. This is also the threshold the NIPs repository requires before a submission is even eligible, so the two milestones arrive together and should be handled together.
  • A third independent anchor operator joins the mesh, evaluated under the Three-Layer Operator Independence Model (distinct Nostr operator pubkeys, separate BGP ASNs, and independent production infrastructure for ≥ 90 days).

Until one of those happens, an organisation would be one group plus paperwork, and organisations formed before their communities are difficult to unwind. After one of them happens, holding everything is no longer defensible. The trigger exists so that the transition is scheduled rather than conceded.