Files
frid/ARCHITECTURE.md
T
Ultradesu c6b2a066b4
CI / check (push) Successful in 5m17s
prepared release
2026-07-26 03:48:30 +03:00

8.1 KiB

Frid architecture

Frid separates decentralized applications into a transport layer and a domain-specific overlay. The transport answers how peers find and talk to each other; the overlay answers what data is routed, replicated, and queried.

application
    │
    ├── domain API, persistence, policy
    │
music-dht
    ├── Kademlia routing and iterative lookup
    ├── replicated records, revisions, TTLs, tombstones
    ├── catalog/content discovery
    │
federation-net
    ├── authenticated iroh connections
    ├── typed bounded messages
    ├── application ALPN byte streams
    └── optional Mainline-DHT rendezvous

Neither layer assigns a permanent server role to a peer.

Transport: federation-net

Identity and authentication

Every engine owns a persistent iroh secret key. Its public endpoint ID is the peer identity used by connections, tickets, events, and higher-level routing. Authentication comes from the iroh connection; address or ticket payloads are never treated as proof of peer identity.

Keeping transport identity stable across restarts lets overlays derive stable node IDs and retain routing knowledge without a separate account system.

Network and schema isolation

The transport ALPN identifies the federation-net protocol. An application handshake then verifies:

  • protocol version;
  • NetworkId, which selects an independent deployment;
  • SchemaId, which identifies the typed message format.

This is intentional double isolation: the ALPN selects the transport protocol, while network and schema IDs prevent unrelated deployments or incompatible applications from exchanging domain payloads.

Changing serialized messages incompatibly requires a new schema ID. Changing the transport handshake incompatibly requires a protocol-version/ALPN plan.

Discovery is not authorization

Automatic discovery publishes short-lived endpoint records into a network-specific BEP44 mutable record in the public BitTorrent Mainline DHT. The signing key is derived from the network ID, allowing equal peers to update the shared rendezvous set without a dedicated bootstrap service.

Knowing a network ID allows discovery. It does not establish application authorization. Private membership, ACLs, or trusted-device pairing belong in a higher-level protocol.

Tickets provide explicit discovery and carry enough connection information to dial a peer directly. They remain useful when public rendezvous is disabled or unavailable.

Two data paths

Typed messages and raw byte streams serve different workloads:

  • the message channel carries bounded, serde/postcard application messages and emits them through a bounded event queue;
  • registered ALPN streams carry protocol-specific request/response or bulk data directly between authenticated peers.

This prevents catalogs, media, and synchronization payloads from inflating the control/event channel. Higher layers can evolve their stream protocols without adding domain logic to federation-net.

Overlay: music-dht

Routing

Each peer derives a stable 256-bit NodeId from its endpoint identity. Routing uses XOR distance and Kademlia-style buckets. Iterative lookups query a bounded number of the closest known peers in parallel and learn additional contacts from responses.

The overlay is not broadcast-based. Query cost follows the routing graph, and contacts are dialed on demand using stored peer tickets.

Records and indexing

LibraryItem is the published domain record. An item is indexed under several BLAKE3-derived DHT keys:

  • the complete normalized name;
  • tokens from names, artists, featured artists, and release titles;
  • an exact content key when a content ID is available.

Multiple index keys point to the same stable item identity. This makes search and exact-content resolution different queries over one record model rather than separate databases.

Publishers declare their complete desired library through sync_library. The service diffs that declaration against owned state, republishes changes, and tombstones removed items. Callers do not manually maintain every DHT index entry.

Replication and convergence

Records are stored on the K known nodes closest to each key. Owners advance revisions and periodically republish active state. Replicas expire after a TTL if their owner disappears.

Deletion uses revisioned tombstones. A tombstone wins over an active record at the same or an older revision, preventing delayed replication from immediately resurrecting deleted content. Tombstones have a longer lifetime than ordinary records so the removal has time to propagate.

This model provides eventual availability and convergence without consensus. The DHT is a distributed directory, not a transactional global database.

Persistence abstraction

MusicDhtStorage separates protocol behavior from storage ownership. The default backend stores local items, replicas, routing contacts, and publication state in SQLite. Applications may supply another durable implementation while preserving the same service semantics.

Database work is executed outside async reactor threads. Corrupt or expired replica payloads are isolated from healthy records rather than crashing the node.

Extension protocols

Music discovery identifies an owner and content; it does not force all domain traffic through DHT messages. music-dht exposes the underlying authenticated stream capability and defines shared wire models for Furumi catalog and device sync protocols. Audio transfer, rich catalog exchange, and synchronization can therefore use dedicated ALPNs while sharing identity and connectivity.

Failure model

Frid assumes normal distributed-system failures:

  • discovered peers may be offline before they are dialed;
  • connections may change between direct and relay paths;
  • rendezvous records may be stale, malformed, or concurrently updated;
  • messages may time out after a peer disconnects;
  • routing tables may contain dead contacts;
  • replicas may expire before an owner returns;
  • event consumers may be slower than producers.

The response is bounded degradation, not global failure. Dial backoff limits repeated failures, lookup budgets guarantee termination, stale records expire, per-connection errors become events, and bounded channels apply backpressure.

Resource boundaries

Untrusted network input is bounded before allocation or fan-out:

  • maximum typed-message frame size;
  • ticket and rendezvous record sizes;
  • event channel capacity;
  • concurrent streams per peer;
  • pending request count and lookup budget;
  • peer-exchange contacts;
  • records per response and store batch;
  • item names, artist lists, tokens, and content IDs.

New protocols must define equivalent limits. A valid peer identity does not make its payloads trusted.

Compatibility rules

Frid is consumed by multiple applications, so compatibility is an architectural constraint:

  1. Do not change existing ALPN bytes, ticket formats, protocol versions, derivation domains, or serialized wire layouts accidentally.
  2. Additive serialized fields require an explicit backward-compatibility strategy; postcard formats do not become extensible automatically.
  3. Changes to normalization or key derivation alter where records live and require a migration/protocol plan.
  4. SQLite schema changes must preserve existing identities, owned records, and routing state.
  5. Public re-exports are part of the library API even when their definitions live in another crate.
  6. A refactor is not behavior-preserving until unit, integration, and doctests pass with real peer connections.

Architectural invariants

  • No Frid-operated service is required for peer communication.
  • All peers can initiate, route, store, and query according to the same rules.
  • Discovery mechanisms do not silently become authorization mechanisms.
  • Domain policy stays above federation-net.
  • DHT operations remain bounded and terminate in the presence of dead peers.
  • Local durable state survives ordinary peer and network failure.
  • Additional stream protocols reuse authenticated connectivity without coupling bulk data to the typed control channel.