# AGENTS.md This repository is `geth`, a Rust monorepo for a personal, local-first, Iroh-based mesh runtime. It is not the Ethereum geth client. `geth` has one executable only: - daemon mode: `geth daemon run` - control mode: `geth status`, `geth node ...`, `geth cas ...`, etc. Do not add separate `gethd` or `gethctl` binaries. ## Core Invariants - All remote geth node-to-node communication must be over Iroh. - SSH is not a geth transport and must not become a fallback transport. - SSH keys are admin trust anchors and ecosystem integration points. - SSH certificate flows and SSH proxying are geth-managed workflows carried by local control now and Iroh later. - The daemon owns the Iroh endpoint, local identity, local metadata store, resource registry, module routing, and synchronized data structures. - Discovery is untrusted and never grants capabilities or trust. - Authorization is resource-scoped and capability-based. - Signed data must use deterministic canonical encoding, not arbitrary JSON. - Bearer secrets may grant resource-specific access but must not create trusted node identity or trust graph mutation rights. ## Workspace Shape - Binary crate: `crates/geth` - CLI definitions and formatting: `crates/geth-cli` - Daemon orchestration and local control: `crates/geth-node` - Local JSONL control protocol: `crates/geth-control` - Shared newtypes: `crates/geth-types` - Canonical encoding/hash helpers: `crates/geth-codec` - Config/path handling: `crates/geth-config` - Local SQLite metadata store: `crates/geth-store` - Local CAS: `crates/geth-cas` - SSH trust/cert models: `crates/geth-ssh-identity` Keep crates focused. Do not create a `geth-common` crate. ## Implementation Rules - Prefer existing crate boundaries and patterns. - Libraries should use `thiserror`; binaries may use `anyhow`. - Keep async only where it is useful. - Treat network and control inputs as untrusted. - Do not implement complex cryptographic protocols casually. Add types, roadmap notes, and explicit non-claims when a feature is only scaffolded. - Do not claim Keyhive/BeeKEM-level security properties until they are actually designed, implemented, and tested. - User service installation must target user service managers, not system service managers. ## Testing Requirements Every behavior change should include tests proportional to risk: - Add unit tests for pure data models, reducers, encoders, path generation, and command builders. - Add integration tests for CLI/daemon behavior when practical. - Use temp directories and temp `GETH_HOME` values. - Avoid tests that require privileged services, real YubiKeys, real network relays, or host service-manager mutation. - For platform-specific behavior, use generated-definition tests or cfg guards. Before finishing a code change, run at least: ```sh cargo fmt --all -- --check cargo check --workspace --all-targets cargo test --workspace ``` Also run clippy when reasonable: ```sh cargo clippy --workspace --all-targets -- -D warnings ``` If a command cannot be run, state why in the final report. ## Documentation And Roadmap Keep documentation updated with behavior changes: - Update `README.md` for user-visible commands or workflows. - Update `docs/architecture.md` for architectural boundaries or invariants. - Add or update ADRs in `docs/adr/` for durable decisions. - Update `docs/roadmap.md` whenever a feature is added, completed, split, or deferred. Roadmap items should be actionable and checkable: - Use `[ ]`, `[~]`, or `[x]`. - Include acceptance criteria. - Split vague items before implementation. - Do not mark an item done unless the acceptance criteria are met or revised honestly. ## Current Feature Boundaries - Local daemon, local control socket, local identity, local store, local CAS, daemon-owned Iroh endpoint startup, built-in relay-mode config, SSH certificate metadata, revocation metadata, user service definitions, and a pinned `geth-iroh` endpoint wrapper with protocol-router scaffold, peer-card types, manual signed peer-card export/import/list commands, `geth peer ping` and `geth peer auth-check` over Iroh, signed peer-card LAN discovery payloads, authorized `geth cas fetch`, `geth ssh cert sync`, and `geth ssh revocation sync` over the Iroh control ALPN, a background SSH metadata and KV live-sync loop with per-peer cursors in `module_state` and an authorized sync-status summary that lets peers disclose only permitted stream watermarks before module pulls, untrusted discovery-backend trait, custom relay-map config, and Iroh local-network discovery toggle exist. - Canonical signed-operation envelopes exist for keychain/auth signature payloads. The keychain reducer builds an active identity view for admin keys, users, devices, nodes, agents, and endpoint bindings. - The auth reducer builds a current permission view for resources, grants, groups, and bearer access. The daemon persists local auth grant/revoke ops and uses them for `auth explain`. `kv set --subject ` enforces local KV write grants for non-local test callers. Signature validation and broader daemon-side module enforcement are still roadmap work. - The daemon persists local keychain init/admin-key ops and reduces them for `keychain status`. `keychain init --signing-key ` signs recorded keychain ops with `ssh-keygen -Y sign` under the `geth.keychain.v1@geth.local` namespace and stores signatures locally. `keychain status` verifies stored signatures with OpenSSH when public key material is available. Verification before accepting replicated keychain ops is still roadmap work. - Local CAS supports pin/unpin metadata, surfaced through `cas list`, and `cas cleanup` evicts unpinned blobs while retaining pinned blobs. The daemon can fetch CAS blobs from an imported signed peer card over Iroh when the peer grants `cas.fetch` on `resource:cas:local`; successful fetches record local provider metadata visible through `geth cas providers `. Full `iroh-blobs` provider integration is still roadmap work. - The CAS crate can build deterministic tree objects for local file trees and store those manifests as CAS blobs. The daemon can register and scan local file roots, reporting create/update/delete/rename changes without writing back to the working tree. Durable local file-conflict records can be listed and resolved manually; automatic cross-node conflict detection and file sync are still roadmap work. - DB resources can be registered locally and report local-only status plus a read-only SQLite schema summary/hash and `crsql_changes` metadata when present. The DB crate and daemon can extract typed read-only `crsql_changes` batches through `geth db changes`. `geth db sync ` can pull authorized typed `crsql_changes` batches over the protected Iroh control ALPN with `db.sync` on the remote `resource:db:`, compare schema metadata, apply compatible batches into local `crsql_changes`, and advance per-peer/per-DB cursors during manual or background live-sync. Loading and configuring cr-sqlite for real application databases is still outside the bootstrap. - KV stores support local SQLite-backed create/set/get plus authorized `geth kv sync ` over Iroh. Background live-sync refreshes local KV stores from known peers with per-peer/per-KV cursors. Iroh Documents replication and command-level prefix-capability enforcement are still roadmap work. The auth evaluator already understands `kv.write_prefix:` grants for `kv.write_key:` requests. - Document resources can be registered locally and updated with validated local JSON state. `geth document sync ` and background live-sync can pull authorized JSON last-writer-wins state over Iroh. Automerge editing/state and true CRDT sync are still roadmap work. - Pubsub supports local daemon-lifetime publish/subscribe snapshots through a bounded in-memory ring buffer. Remote publish over the protected Iroh control ALPN requires `pubsub.publish` on `resource:pubsub:`. Remote subscribe over the same path requires `pubsub.subscribe` and returns the peer's current daemon-lifetime snapshot. Iroh-gossip replication and private topics are still roadmap work. - Pipe listen/connect supports a daemon-lifetime registry. Remote `geth pipe connect --node ` uses the protected Iroh control ALPN and requires `pipe.connect` on `resource:pipe:`. Remote `geth pipe listen --node ` requires `pipe.listen` on the same resource before creating a daemon-lifetime listener on the peer. Iroh byte streams and TCP/Unix forwarding are still roadmap work. - `geth ssh proxy ` performs an authorized control-plane handshake over the protected Iroh control ALPN and requires `ssh_proxy.connect` on `resource:ssh-proxy:local` before returning proxy metadata. It does not carry SSH bytes or connect to sshd/admin shell yet. - Resource secret epoch metadata can be created, rotated, and listed locally. Bearer access metadata can be created/listed/revoked as resource-scoped auth ops and must not allow trust graph mutation capabilities. Bearer challenge/proof/verify commands exist for resource-scoped possession checks. Remote module authorization paths can accept optional bearer proofs without enrolling the caller as a trusted node. Payload encryption, key envelopes, and separating public bearer ids from private bearer tokens are still roadmap work. - SSH revocations can be exported as JSONL, OpenSSH KRL specification text, or binary OpenSSH KRL files generated through `ssh-keygen`. JSONL and OpenSSH KRL specification imports are supported; binary KRL import is unsupported because OpenSSH KRL files are not enumerable through OpenSSH tooling. Tests cover public-key and certificate binary KRL revocations when `ssh-keygen` is available. `geth ssh cert approve` emits the OpenSSH signing command by default; `approve --sign` runs `ssh-keygen`, imports the resulting certificate, and marks the request signed when local signing succeeds. Local SSH certificate and revocation commands accept optional `--subject` principals and enforce `ssh_cert.*` capabilities on `resource:ssh:certs` plus `ssh_revocation.*` capabilities on `resource:ssh:revocations` for non-owner subjects. Authorized peers can pull SSH certificate-flow metadata with `ssh_cert.sync` on `resource:ssh:certs` and revocation metadata with `ssh_revocation.sync` on `resource:ssh:revocations`. The daemon live-syncs known peers every 30 seconds using per-peer cursors; this is pull-only metadata sync, not yet a CRDT/resource-log replication model. - cr-sqlite apply, iroh-docs, iroh-blobs provider/fetch, Automerge sync, broader auth enforcement, and Keyhive/BeeKEM-style authorization are future roadmap items unless implemented later.