geth/AGENTS.md

214 lines
11 KiB
Markdown
Raw Normal View History

# 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,
2026-05-16 03:17:45 +02:00
daemon-owned Iroh endpoint startup, built-in relay-mode config, SSH
certificate metadata, revocation metadata, user service definitions, and a
2026-05-16 14:24:21 +02:00
pinned `geth-iroh` endpoint wrapper with protocol-router scaffold, peer-card
2026-05-18 12:09:50 +02:00
types, manual signed peer-card export/import/list commands, `geth peer ping`
2026-05-18 17:05:43 +02:00
and `geth peer auth-check` over Iroh, signed peer-card LAN discovery payloads,
2026-05-18 17:24:10 +02:00
authorized `geth cas fetch`, `geth ssh cert sync`, and
2026-05-18 18:29:45 +02:00
`geth ssh revocation sync` over the Iroh control ALPN, a background SSH
2026-05-18 22:17:27 +02:00
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,
2026-05-18 18:36:03 +02:00
untrusted discovery-backend trait, custom relay-map config, and Iroh
local-network discovery toggle exist.
- Canonical signed-operation envelopes exist for keychain/auth signature
2026-05-16 14:39:18 +02:00
payloads. The keychain reducer builds an active identity view for admin keys,
users, devices, nodes, agents, and endpoint bindings.
2026-05-16 14:41:23 +02:00
- The auth reducer builds a current permission view for resources, grants,
2026-05-16 16:32:03 +02:00
groups, and bearer access. The daemon persists local auth grant/revoke ops
2026-05-18 04:06:41 +02:00
and uses them for `auth explain`. `kv set --subject <principal>` 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
2026-05-19 16:04:20 +02:00
`keychain status`. `keychain init --signing-key <path>` signs recorded
keychain ops with `ssh-keygen -Y sign` under the
`geth.keychain.v1@geth.local` namespace and stores signatures locally.
2026-05-19 18:58:07 +02:00
`keychain status` verifies stored signatures with OpenSSH when public key
material is available. Verification before accepting replicated keychain ops
is still roadmap work.
2026-05-16 21:10:25 +02:00
- Local CAS supports pin/unpin metadata, surfaced through `cas list`, and
2026-05-18 17:18:25 +02:00
`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
2026-05-19 15:37:02 +02:00
grants `cas.fetch` on `resource:cas:local`; successful fetches record local
provider metadata visible through `geth cas providers <hash>`. Full
`iroh-blobs` provider integration is still roadmap work.
2026-05-17 21:20:24 +02:00
- The CAS crate can build deterministic tree objects for local file trees and
2026-05-18 03:50:09 +02:00
store those manifests as CAS blobs. The daemon can register and scan local
file roots, reporting create/update/delete/rename changes without writing back
2026-05-20 13:22:40 +02:00
to the working tree. `geth cas root sync <node-id> <name>` can pull authorized
remote tree metadata and CAS tree bytes, recording a peer-qualified remote
root with path `remote:<node>:<name>` without applying files or overwriting
2026-05-20 13:26:50 +02:00
same-named local roots. Background live-sync refreshes authorized remote file
2026-05-20 13:30:57 +02:00
roots from sync-status `cas-tree:<name>` watermarks. `geth cas root apply`
materializes missing files/directories from a CAS tree without deleting extras
or overwriting local edits, and records conflicts for manual resolution.
Richer three-way file application remains roadmap work.
- DB resources can be registered locally and report local-only status plus a
2026-05-17 20:01:36 +02:00
read-only SQLite schema summary/hash and `crsql_changes` metadata when
2026-05-17 20:32:36 +02:00
present. The DB crate and daemon can extract typed read-only `crsql_changes`
2026-05-18 22:11:57 +02:00
batches through `geth db changes`. `geth db sync <node-id> <name>` can pull
authorized typed `crsql_changes` batches over the protected Iroh control ALPN
with `db.sync` on the remote `resource:db:<name>`, compare schema metadata,
2026-05-19 19:02:39 +02:00
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.
2026-05-18 18:36:03 +02:00
- KV stores support local SQLite-backed create/set/get plus authorized
`geth kv sync <node-id> <name>` over Iroh. Background live-sync refreshes
local KV stores from known peers with per-peer/per-KV cursors. Iroh Documents
2026-05-17 18:26:30 +02:00
replication and command-level prefix-capability enforcement are still roadmap
work. The auth evaluator already understands `kv.write_prefix:<prefix>`
grants for `kv.write_key:<key>` requests.
2026-05-17 19:59:03 +02:00
- Document resources can be registered locally and updated with validated local
2026-05-18 18:49:34 +02:00
JSON state. `geth document sync <node-id> <name>` 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.
2026-05-17 18:23:51 +02:00
- Pubsub supports local daemon-lifetime publish/subscribe snapshots through a
2026-05-18 18:41:04 +02:00
bounded in-memory ring buffer. Remote publish over the protected Iroh control
2026-05-19 15:28:48 +02:00
ALPN requires `pubsub.publish` on `resource:pubsub:<topic>`. 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.
2026-05-18 18:45:10 +02:00
- Pipe listen/connect supports a daemon-lifetime registry. Remote
`geth pipe connect <name> --node <node-id>` uses the protected Iroh control
2026-05-19 19:21:42 +02:00
ALPN and requires `pipe.connect` on `resource:pipe:<name>`. Remote
`geth pipe listen <name> --node <node-id>` 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.
2026-05-19 15:51:11 +02:00
- `geth ssh proxy <node-id>` 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.
2026-05-16 22:18:49 +02:00
- Resource secret epoch metadata can be created, rotated, and listed locally.
Bearer access metadata can be created/listed/revoked as resource-scoped auth
2026-05-19 19:08:08 +02:00
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. Bearer creation separates the public
bearer id stored in auth logs from the private bearer token returned to the
caller once. Payload encryption and key envelopes are still roadmap work.
2026-05-18 11:51:12 +02:00
- SSH revocations can be exported as JSONL, OpenSSH KRL specification text, or
2026-05-18 11:56:42 +02:00
binary OpenSSH KRL files generated through `ssh-keygen`. JSONL and OpenSSH KRL
specification imports are supported; binary KRL import is unsupported because
2026-05-18 11:58:39 +02:00
OpenSSH KRL files are not enumerable through OpenSSH tooling. Tests cover
public-key and certificate binary KRL revocations when `ssh-keygen` is
2026-05-19 15:56:47 +02:00
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
2026-05-20 13:34:16 +02:00
`resource:ssh:revocations`. The daemon live-syncs known peers using per-peer
cursors; `[sync] live_sync_enabled` and `live_sync_interval_ms` in
`config.toml` control that loop. Conflicting records with already-known ids
are rejected during sync import; this is pull-only metadata sync, not yet a
2026-05-20 13:13:44 +02:00
signed CRDT/resource-log replication model.
2026-05-18 22:11:57 +02:00
- 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.