Documentation
¶
Overview ¶
Package forest is the network of arbos nodes (ADR-0034): the head side — a self-hostable registry + relay that gives each joined node an ephemeral public URL — and the node side, a client that registers a device identity, leases a name, and serves its gateway back through an outbound tunnel.
The wire surface is the subset of docs/account-api-contract.md a forest head implements: device registration, signed-challenge token mint, the node heartbeat (which carries the lease), and the tunnel handshake. A node built against this package works against the hosted head and a self-hosted one identically — the head is part of the swappable backend, per ADR-0033.
Index ¶
Constants ¶
const DefaultHead = "https://arbos.life"
DefaultHead is the forest a bare `arbos web` joins when no --forest/--local override is given: the canonical "one command, get a URL" path. Nodes are auth-gated by their own login token; the head is transport, not a trust boundary, so defaulting in is safe — but the join is always printed loudly so nobody is surprised their node has a public name.
Variables ¶
This section is empty.
Functions ¶
func LoadOrCreateAgentKey ¶
func LoadOrCreateAgentKey(dir string) (ed25519.PrivateKey, error)
LoadOrCreateAgentKey returns the per-directory agent key, generating one on first run at <dir>/.arbos/agent.key. Unlike the device key it is not a secret (ADR-0035): its public half is a binding input that, composed with the device key, derives this agent's stable URL — same directory on the same machine yields the same URL, with no login. It travels with the directory; the secret that gates the URL stays the device key, on the box.
func LoadOrCreateDeviceKey ¶
func LoadOrCreateDeviceKey(path string) (ed25519.PrivateKey, error)
LoadOrCreateDeviceKey returns the device's ed25519 key, generating one on first run. The keypair is the device (ADR-0033): the only durable local secret, stored as the 32-byte seed at path (0600, dir 0700). The account subsystem (ADR-0033 P1) will lift this same file; the forest client is its first consumer.
Types ¶
type Client ¶
type Client struct {
// Base is the forest head's URL, e.g. "http://204-12-163-231.sslip.io:8080".
Base string
// KeyPath is the device key seed (LoadOrCreateDeviceKey).
KeyPath string
// AgentDir is the workspace whose per-directory key (<dir>/.arbos/agent.key)
// composes with the device to derive a stable URL (ADR-0035). Empty leaves
// the name a function of the device alone.
AgentDir string
// Handler is served to tunneled requests — the same gateway handler the
// local listener serves, auth gate included. Serving it directly off the
// tunnel (no loopback hop) is deliberate: tunneled requests must never
// look like local ones to the gate (ADR-0034).
Handler http.Handler
// OnJoin fires whenever a join (or rejoin) succeeds.
OnJoin func(JoinInfo)
Logf func(format string, args ...any)
// contains filtered or unexported fields
}
Client joins a node to a forest: registers the device, mints a token, heartbeats to hold the lease, and serves Handler back through an outbound tunnel. Run blocks and reconnects forever — a dropped tunnel or a restarted head is rejoined with backoff, because the lease model already assumes nodes come and go.
type Head ¶
type Head struct {
// contains filtered or unexported fields
}
Head is the forest head: device registry, token mint, lease table, and the relay that routes "<name>.<domain>" requests down each node's tunnel. The relay is a dumb pipe — it never makes auth decisions for a node; the node's own gateway gate does (ADR-0034).
func NewHead ¶
func NewHead(cfg HeadConfig) (*Head, error)
NewHead loads persisted devices and returns a serving-ready head.
type HeadConfig ¶
type HeadConfig struct {
// Domain is the public apex the head answers as, including a non-default
// port if any (e.g. "204-12-163-231.sslip.io:8080"). Lease hosts are
// "<name>.<Domain>"; anything else 404s.
Domain string
// Scheme ("http" | "https") for the URLs minted into heartbeat
// responses. The head itself only listens plain; TLS termination in
// front (or autocert, later) flips this to https.
Scheme string
// StatePath persists registered devices (a JSON map), so an anonymous
// account survives head restarts. Leases are deliberately not persisted:
// they are ephemeral by design and re-establish on the next heartbeat.
StatePath string
// LeaseTTL is how long a lease outlives its last heartbeat. Heartbeat is
// the cadence handed to nodes. Head-controlled on purpose.
LeaseTTL time.Duration
Heartbeat time.Duration
Logf func(format string, args ...any)
}
HeadConfig configures a forest head.