clone

a self-hosted sync node for lofi apps: jazz sync over iroh, ticket-gated, with no static ip or cloud needed

feat/connection-observability
lofi-node / docs / site / architecture.md
architecture.md 2.8K rendered
1# Architecture and provenance23<!-- Source: FelineStateMachine/lofi-node README.md, src/{gate,tunnel,node}.ts,4 native/iroh-js/UPSTREAM.md, docs/port-iroh-js.md, CONTRIBUTING.md. -->56One daemon, three layers, each with a single job:78```mermaid9flowchart LR10 subgraph Device["User devices"]11 App["lofi app (browser)"]12 end13 subgraph Node["lofi-node daemon"]14 Gate["Access gate<br/>public port, tickets"]15 Jazz["Jazz sync server<br/>loopback-only, SQLite"]16 Tunnel["iroh tunnel<br/>node-to-node"]17 end18 subgraph Peer["Paired node"]19 Root["Root store"]20 end2122 App -->|"WS + HTTP with /t/(secret)"| Gate23 Gate --> Jazz24 Jazz --- Tunnel25 Tunnel -->|"QUIC, dialed by key"| Root26```2728- **The gate is both enforcement and reachability.** The embedded Jazz server binds loopback-only29 and is verified to; the only path to it is through the gate, which validates tickets, strips and30 injects admin headers, and re-originates WebSockets. Access control is therefore not a mode the31 store honors — it is the shape of the network.32- **The tunnel carries exactly what Jazz speaks.** One iroh connection per WebSocket or HTTP33 request, opened with a HELLO frame naming its kind, path, and headers. Sync and catalogue traffic34 both ride it, which is why deploying against a leaf lands on the root without either side35 special-casing anything.36- **Pairing is upstream election.** A leaf's Jazz server chains to the root; re-election at runtime37 restarts Jazz on the same internal port while the gate keeps the public port stable.3839## The version invariant4041The data plane is Jazz 2.0 **alpha**, pinned exactly. A node must run the same alpha as the apps it42serves — treat version bumps as coordinated, release-lockstep changes, never drive-by. This is a43stated contract of the lofi-node repo (its contributing guide calls version pins decisions, with the44full suite as evidence).4546## Native layer provenance4748The iroh transport is a vendored port of the upstream `n0-computer/iroh-ffi` napi crate at module49granularity, with every local edit marked and an `UPSTREAM.md` recording provenance and the50tag-bump-by-diff procedure. Prebuilt libraries for the supported platform matrix are committed51in-repo, digest-pinned, and embedded into the compiled binary; at first run the right one extracts52to a version-keyed OS cache. Contributors changing the native layer start from53`native/iroh-js/UPSTREAM.md` and `docs/port-iroh-js.md` in the lofi-node repo.5455## The library surface5657Everything the CLI does, an embedder can do: `createSyncNode()` returns a node whose58`url`/`ticket()`/`issueTicket()`/`pair()`/`status()`/`stop()` are the same operations, and a test59mesh helper stands up paired topologies for suites. The generated [API reference](/node/api) covers60the full surface.