Files
varde/docs/milestone-1.md
T
bl 4e1a95613b Milestone 1: workspace skeleton, wire protocol, socket round-trip
Three-crate workspace per SPECS.md. varde-proto defines the full JSON
Lines protocol (requests, envelopes, structured errors, events) with
string-typed hashes so the crate carries no iroh dependency. The daemon
binds its unix socket, loads config with flags > env > file > defaults
precedence, and answers status/list; everything else returns a
structured "unimplemented" error. varde-ctl maps subcommands 1:1 onto
requests and round-trips status against a real daemon in the tests.

Dependencies: serde/serde_json (wire format), tokio (async runtime and
unix sockets), tracing/tracing-subscriber (structured logging), toml
(config file), anyhow (binary-edge errors), thiserror (reserved for
library errors), clap (ctl flag parsing, per spec), tempfile (dev-only,
ephemeral test dirs).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 20:10:29 +02:00

2.6 KiB

Milestone 1 — Skeleton

Workspace with the three crates from the spec, the full wire protocol, a daemon that binds its socket and answers, and a varde-ctl that round-trips status against it.

Decisions

  • Wire types use strings for hashes/tickets/node ids. varde-proto stays free of iroh dependencies ("No I/O" taken to also mean no heavy type imports), and the protocol is consumable from any language without linking iroh. The daemon parses/validates at its boundary.
  • Envelope shape. Every reply is {"ok": bool, "data": {...}} or {"ok": false, "error": {"code", "message"}}. data is internally tagged with kind so clients can dispatch without guessing. Error codes are a closed enum (bad_request, invalid_argument, not_found, io, internal, unimplemented).
  • The full request surface is defined now, including peer-trust and ticket ops. Unimplemented handlers return a structured unimplemented error instead of the protocol growing per milestone.
  • varde-daemon is a lib + thin bin. Integration tests run real daemons: the daemon crate's tests spawn the actual binary (CARGO_BIN_EXE_varde-daemon) on ephemeral sockets; the ctl crate's test runs an in-process daemon (same run() entry point) and drives the real varde-ctl binary against it. No mocked transport anywhere.
  • Daemon flag parsing is hand-rolled (five flags); the spec reserves clap for varde-ctl. Mode (system/user) defaults from euid — root gets /var/lib/varde + /run/varde/varde.sock, users get XDG paths — and geteuid is called through a two-line FFI shim instead of pulling in the libc crate for one function.
  • Config precedence is flags > VARDE_* env > TOML file > defaults, implemented per-field so partial configs compose. An absent or empty default config file is valid; an explicitly named one must exist. Unknown keys in the file are rejected (deny_unknown_fields) so typos fail loudly at startup rather than silently using defaults.
  • Defaults encode the traffic posture: wan_upload = false, upload cap 10 MB/s, discovery on (discovery is the open tier; serving is still gated on trust, which doesn't exist until milestone 4).
  • Event plumbing exists from day one. Subscribe flips a connection into a one-way stream fed by a bounded tokio::broadcast channel (laggards drop events rather than buffering unboundedly). Milestones 3/4 publish into it.

Deviations from the spec

None of substance. --json output for varde-ctl (a milestone 5 item) landed early because the printing layer needed a shape anyway.