geth/docs/architecture.md

214 lines
11 KiB
Markdown
Raw Normal View History

2026-05-15 15:08:20 +02:00
# Architecture
`geth` is a single-binary local-first mesh runtime. One executable provides both
daemon mode and control mode. The daemon owns local identity, metadata storage,
2026-05-16 03:17:45 +02:00
the shared Iroh endpoint, resource registry, module routing, and local control
socket. Control commands connect to the Unix socket and send typed JSONL
2026-05-15 15:08:20 +02:00
requests.
Service management is also exposed through the single binary. `geth daemon
service ...` installs and controls a user-level service definition for the local
daemon. The initial backends are systemd user units on Linux, launchd user agents
on macOS, and per-user scheduled tasks on Windows. Geth does not install itself
as a privileged system service.
2026-05-15 15:08:20 +02:00
## Iroh-Only Remote Communication
Remote geth node-to-node communication is Iroh-only. The daemon will own one
shared Iroh endpoint and register module protocols on ALPNs such as
`/geth/cas/1`, `/geth/kv/1`, `/geth/pipe/1`, and `/geth/ssh-proxy/1`.
2026-05-16 01:54:00 +02:00
The first pinned Iroh integration uses `iroh = 0.90.0`, because newer
Rust-1.85-compatible candidates in the 0.93-0.95 range failed to compile through
a transitive `ed25519-dalek` prerelease dependency. `geth-iroh` wraps
`iroh::Endpoint::builder()`, configures geth ALPNs with `Builder::alpns`, uses
`Builder::relay_mode`, persists an `iroh::SecretKey` as hex-encoded 32-byte key
2026-05-16 03:17:45 +02:00
material, and shuts down through `Endpoint::close().await`. The default config
uses Iroh's default relay policy; local-only/offline development can set
2026-05-16 14:28:38 +02:00
`[iroh].relay_mode = "disabled"`. Named custom relay maps are configured under
`[iroh.relay_maps.<name>]`, selected with `relay_mode = "custom"` plus
`relay_map = "<name>"`, validated at config load, and reported in status as
`custom:<name>` without exposing relay URLs.
2026-05-16 01:54:00 +02:00
2026-05-16 03:37:51 +02:00
Module ALPNs are registered through `geth-iroh`'s protocol router scaffold. The
router owns the default protocol descriptors, rejects duplicate ALPN
registrations, and returns explicit unknown-ALPN errors. It does not yet accept
or dispatch remote streams; peer authentication and module handlers are later
Phase 1 work.
2026-05-16 02:06:28 +02:00
The target product should use Iroh relay support for practical internet
connectivity and mDNS/LAN discovery for local networks. These are connectivity
and candidate-discovery mechanisms only. They do not grant trust, mutate
authorization state, or make EndpointID knowledge sufficient for access.
2026-05-16 14:33:45 +02:00
The current daemon can enable Iroh's local-network discovery service through
`[iroh].local_discovery = true`, which is the default. This publishes and
2026-05-18 04:03:52 +02:00
discovers Iroh node addressing. `geth peer export/import/list` supports manual
exchange of signed peer cards as untrusted candidates. Automatic signed
peer-card advertisement over LAN discovery remains separate future work.
2026-05-16 02:06:28 +02:00
2026-05-16 14:24:21 +02:00
Peer cards are the discovery payload. A peer card carries node ID, agent ID,
2026-05-18 04:03:52 +02:00
endpoint candidates, timestamp, signing public key, and an Ed25519 signature
over a canonical payload. Imported peer cards are stored as untrusted metadata
in `peer_cards`; trust reduction is future work. `auth explain` reports when a
subject is only a discovered peer candidate and denies access.
2026-05-16 14:24:21 +02:00
2026-05-16 01:54:00 +02:00
The daemon starts this endpoint during `geth daemon run` and keeps it alive for
the daemon lifetime. When endpoint startup succeeds, the Iroh EndpointID is
recorded as a transport binding for the stable geth node identity. If local UDP
binding is unavailable, the daemon keeps local control running and reports the
Iroh startup error through status output.
2026-05-15 15:08:20 +02:00
SSH keys are not transport keys. They are admin trust anchors and signing
identities for keychain and authorization operations. SSH proxying, when added,
will carry SSH bytes over an authorized Iroh stream and will not make SSH a geth
transport backend.
SSH certificate flows use the same split. Nodes can request new OpenSSH
certificates or renewals through geth metadata. A machine with the CA key or
YubiKey can approve the request and run an explicit `ssh-keygen -s ...` command,
then import the resulting certificate for distribution. Certificate and key
revocations are stored as signed-list-ready records and will be replicated over
Iroh in later phases.
2026-05-15 15:08:20 +02:00
## Resource Model
Everything meaningful is modeled as a resource. Resources have a kind, name,
authority reference, local role, replication policy, retention policy, and
status. Authorization is resource-scoped and capability-based.
Resource kinds:
- `db`: cr-sqlite-backed SQLite synchronization
- `kv`: Iroh Documents backed key-value data
- `pipe`: authorized byte streams and forwarding
- `document`: Automerge CRDT documents
- `pubsub`: lossy notifications and presence
- `cas`: content-addressed blobs
- `ssh-proxy`: SSH/admin proxying over Iroh
## Module Overview
`geth-cas` is implemented locally first using BLAKE3 hashes and filesystem blob
2026-05-16 16:36:35 +02:00
storage. Local pin/unpin metadata is tracked in SQLite and surfaced in
2026-05-16 21:10:25 +02:00
`cas list`. `cas cleanup` removes unpinned local blobs while retaining pinned
2026-05-17 21:20:24 +02:00
blobs. The CAS crate can build deterministic tree objects that describe
directories, files, executable bits, and file blob hashes; those tree objects
2026-05-18 03:50:09 +02:00
are stored as CAS blobs. The daemon can register local file roots and scan them
into CAS tree objects while reporting create/update/delete/rename changes. These
2026-05-18 03:57:26 +02:00
scans are local metadata only and never overwrite the working tree. The daemon
also has durable local file-conflict records with explicit resolution choices;
future cross-node file sync will create those records automatically instead of
silently applying ambiguous remote changes. Iroh-blobs, providers, encrypted
blobs, richer cache policies, cross-node file roots, and automatic conflict
detection are future work.
2026-05-15 15:08:20 +02:00
2026-05-16 21:13:33 +02:00
`geth-db` currently registers local SQLite paths as DB resources and reports
2026-05-17 20:01:36 +02:00
local-only sync status plus a read-only SQLite schema summary/hash. It also
inspects `crsql_changes` metadata when that table or view exists, reporting
2026-05-17 20:32:36 +02:00
change count, columns, and max `db_version`. The crate and local daemon can
extract read-only typed change batches from `crsql_changes` with schema metadata
through `db changes`. Loading cr-sqlite, applying remote changes, and DB sync
are future work.
2026-05-16 21:13:33 +02:00
2026-05-16 21:52:35 +02:00
`geth-kv` currently provides a SQLite-backed local fallback for named KV stores
through `kv create/set/get`. Iroh Documents namespaces, prefix authorization
enforcement, and replication are future work.
2026-05-17 19:59:03 +02:00
`geth-document` currently registers local document resources and stores
validated JSON state in the local SQLite metadata store through
`document create/status/set/get`. This is a bootstrap editing surface, not yet
Automerge CRDT state. Automerge state encoding and sync are future work.
2026-05-16 22:15:18 +02:00
2026-05-17 18:23:51 +02:00
`geth-pubsub` currently supports local publish/subscribe snapshots through the
daemon control protocol. Messages live in a bounded in-memory ring buffer and
are lost when the daemon stops. This is deliberate: pubsub is a lossy wakeup and
presence channel, not authoritative storage. Iroh-gossip replication, private
topics, and capability enforcement are future work.
2026-05-17 20:17:26 +02:00
`geth-pipe` currently supports `pipe listen/connect` against a local
daemon-lifetime registry. This is a control-plane scaffold for names and
connection attempts only; it does not carry bytes, forward sockets, or use Iroh
streams yet.
`geth-ssh-proxy` currently defines types, command shape, and roadmap stubs.
2026-05-15 15:08:20 +02:00
`geth-ssh-identity` defines SSH trust namespaces plus certificate request,
approval, certificate import, and revocation-list data models. The bootstrap
2026-05-17 18:29:47 +02:00
persists these flows locally and exports revocations as JSONL or OpenSSH KRL
specification text. It does not yet generate OpenSSH KRL binaries or replicate
the lists over Iroh.
2026-05-15 15:08:20 +02:00
## Keychain, Auth, And Secrets
The identity plane is `geth-keychain`: admin keys, users, devices, nodes, agents,
and endpoint bindings. Endpoint rotation must not destroy higher-level node
2026-05-16 14:39:18 +02:00
identity. Keychain operations reduce into an active view containing current
admin keys, users, devices, node records, agent bindings, and endpoint-to-node
bindings. Revoked identity subtrees are excluded from that active view. The
daemon persists local keychain init/admin-key operations and `keychain status`
reports the reduced local view. OpenSSH signature capture and verification for
those operations is still future work.
2026-05-15 15:08:20 +02:00
The authorization plane is `geth-auth`: resource-local signed operation logs,
2026-05-16 14:41:23 +02:00
grants, revocations, groups, and `auth explain`. Auth operations reduce into a
current permission view for resources, grants, groups, and bearer access. The
2026-05-16 16:32:03 +02:00
library can explain direct and group grants. The daemon persists local auth
grant/revoke operations and `geth auth explain` evaluates that local operation
log. Signature validation, replication, and module enforcement are still future
work.
2026-05-15 15:08:20 +02:00
2026-05-17 18:26:30 +02:00
Capability evaluation supports exact matches plus explicit scoped forms. For KV,
`kv.write_prefix:<prefix>` grants writes requested as `kv.write_key:<key>` only
when the key is under that prefix; `kv.write` remains the broad write
capability. Command-level KV enforcement is still future work.
Both keychain and auth operations use `geth-codec` canonical envelopes for
signature payloads. The envelope includes a version, an explicit signature
namespace, and the operation payload encoded with postcard. JSON remains useful
for CLI/control output, but it is not the signed representation.
2026-05-15 15:08:20 +02:00
The payload access plane is `geth-secrets`: resource master secrets, epochs,
key envelopes, bearer secrets, and rotation. Revocation for private data is
2026-05-16 22:18:49 +02:00
modeled initially as secret epoch rotation. The daemon persists resource secret
epoch metadata through `secret create/rotate/status`. Bearer access is recorded
as resource-scoped auth operations and rejects trust-mutation capabilities such
as `auth.delegate`, `auth.revoke`, and `node.enroll`. The daemon does not yet
store payload key material, encrypt resource data, or distribute key envelopes.
2026-05-15 15:08:20 +02:00
## Multi-User Direction
The project is structured for future multi-user local-first authorization:
- authorization is replicated data, not one mutable ACL blob
- resources can carry or delegate to their own auth state
- users, devices, nodes, agents, and endpoints are separate principals
- capabilities are the underlying permission unit
- bearer access is resource-scoped and does not mutate the trust graph
- offline revocation is eventual
- encryption key distribution is part of authorization
## Keyhive/BeeKEM Roadmap
Resource secret epochs are the v0/v1 approximation for private payload access.
Later designs can add Keyhive-like convergent capabilities and BeeKEM/CGKA-style
group key evolution. The bootstrap does not implement BeeKEM and does not claim
strong forward secrecy or post-compromise security.
## Security Invariants
- All remote node-to-node communication is over Iroh.
- SSH is not a geth transport.
- SSH keys are admin trust anchors and signing identities.
- Agent/node keys handle routine local identity.
- Discovery is untrusted.
- Knowing an EndpointID does not grant access.
- Bearer secrets are resource-scoped capabilities.
- Bearer access does not imply trust graph mutation rights.
- Authorization is capability-based and resource-scoped.
- SSH certificate issuance must be explicitly approved by an authorized
principal before signing.
- SSH certificate and key revocations are durable metadata that should be
distributed over Iroh, not fetched through unauthenticated discovery.
2026-05-15 15:08:20 +02:00
- Network and control decoders treat input as untrusted.
- Service installation targets user service managers, not system service
managers.