diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..ad86630 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,109 @@ +# 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, + SSH certificate metadata, revocation metadata, and user service definitions + exist. +- Iroh, cr-sqlite, iroh-docs, iroh-gossip, iroh-blobs, Automerge sync, real auth + enforcement, OpenSSH KRL generation, and Keyhive/BeeKEM-style authorization are + future roadmap items unless implemented later. diff --git a/docs/roadmap.md b/docs/roadmap.md index 0b1ac60..c7570da 100644 --- a/docs/roadmap.md +++ b/docs/roadmap.md @@ -1,64 +1,299 @@ # Roadmap +This roadmap is intended to be checkable. Each item should either be completed +with tests/docs or split into smaller items before implementation. + +Status markers: + +- `[ ]` Not started +- `[~]` In progress +- `[x]` Done + ## Phase 0: Bootstrap -- single CLI -- local daemon -- local store -- local identity -- local CAS -- user service installer for systemd, launchd, and Windows scheduled tasks -- docs and ADRs +Goal: establish a compiling single-binary local runtime with local state, local +control, local CAS, service installation, and written architecture decisions. + +- `[x]` Single `geth` binary with daemon and control modes. + Acceptance criteria: + - `cargo run -p geth -- init` initializes a temp `GETH_HOME`. + - `cargo run -p geth -- daemon run` starts one local daemon. + - No `gethd` or `gethctl` binaries exist in the workspace. + +- `[x]` Local daemon control socket. + Acceptance criteria: + - Control request/response types roundtrip through JSONL serialization. + - `geth status` and `geth node id` talk to a running daemon. + - Control decoding treats input as untrusted and returns structured errors. + +- `[x]` Local metadata store and identity. + Acceptance criteria: + - SQLite migrations are idempotent. + - Agent identity persists across repeated opens of the same `GETH_HOME`. + - Store schema includes resources, auth/keychain logs, CAS, peers, modules, + SSH cert requests, certificates, and revocations. + +- `[x]` Local filesystem CAS. + Acceptance criteria: + - `geth cas add/hash/has/get/list` work through the daemon. + - Blob paths use BLAKE3 hashes under `cas/blobs///`. + - Unit or integration tests verify bytes roundtrip unchanged. + +- `[x]` User service installer. + Acceptance criteria: + - `geth daemon service print --manager systemd|launchd|windows-task` prints + the expected user-level service definition or command. + - Linux install targets a systemd user unit, not a system service. + - macOS install targets a launchd user agent. + - Windows install targets a per-user scheduled task. + - Tests verify generated definitions do not target privileged system services. + +- `[x]` Bootstrap docs and ADRs. + Acceptance criteria: + - README explains what geth is and what it is not. + - Architecture docs state Iroh-only remote communication and SSH trust role. + - ADRs cover single binary, Iroh-only transport, resources, auth, SSH, CAS, + synchronized structures, service installation, and SSH certificate flows. ## Phase 1: Iroh Foundation -- Iroh endpoint -- peer cards -- peer discovery -- peer exchange -- basic authenticated peer connection -- additional user service manager backends where useful +Goal: make the daemon own a real Iroh endpoint and establish authenticated +geth-to-geth connections without granting trust from discovery alone. + +- `[ ]` Pin and compile Iroh dependencies. + Acceptance criteria: + - `iroh` is added only after APIs are pinned and `cargo check --workspace` + passes. + - `geth-iroh` exposes endpoint startup/shutdown wrappers. + - Docs note exact crate versions and any API assumptions. + +- `[ ]` Daemon-owned Iroh endpoint. + Acceptance criteria: + - The daemon creates one shared Iroh endpoint on startup. + - `geth status --json` reports endpoint status and EndpointID. + - Endpoint identity is bound to agent/node identity in local metadata. + - Restarting the daemon preserves higher-level node identity. + +- `[ ]` Protocol/router scaffold. + Acceptance criteria: + - ALPN constants are registered through one module router. + - Unknown ALPNs are rejected explicitly. + - Tests cover registration collisions and unknown protocol handling. + +- `[ ]` Peer cards. + Acceptance criteria: + - A peer card contains node ID, agent ID, endpoint candidates, timestamp, and + signature metadata. + - Peer cards are stored in `peer_cards`. + - Invalid or unsigned peer cards do not update trust state. + +- `[ ]` Untrusted discovery backend trait. + Acceptance criteria: + - Discovery returns candidate peer cards only. + - No discovery result grants capabilities or trust. + - `auth explain` can distinguish "discovered" from "trusted". + +- `[ ]` Basic authenticated peer connection. + Acceptance criteria: + - A node can dial another node over Iroh using an EndpointID from a peer card. + - The remote side proves an agent/node binding before module access. + - Knowing only an EndpointID is insufficient to access a protected module. ## Phase 2: Trust And Authorization -- SSH-admin-rooted keychain -- SSH certificate request and renewal queues -- CA/YubiKey approval workflow -- certificate and key revocation-list records -- signed keychain ops -- resource auth ops -- grants and revocations -- auth explain -- resource secrets -- bearer invites +Goal: replace stubs with signed, reducible keychain/auth operation logs and +resource-scoped capability decisions. -## Phase 3: CAS/KV/Pubsub +- `[ ]` Canonical signed operation envelope. + Acceptance criteria: + - Keychain and auth ops use deterministic canonical encoding for signatures. + - JSON is not used as the signed representation. + - Tests verify equivalent operations hash/sign identically across runs. -- iroh-blobs CAS -- iroh-docs KV -- iroh-gossip pubsub -- private topics and encrypted values +- `[ ]` SSH-admin-rooted keychain initialization. + Acceptance criteria: + - `geth keychain init` records a signed `KeychainInit`. + - OpenSSH signature namespaces are explicit. + - Missing `ssh-keygen` or unavailable hardware keys produce clear errors. -## Phase 4: Pipes And SSH Proxy +- `[ ]` Keychain operation reducer. + Acceptance criteria: + - Admin keys, users, devices, nodes, agents, and endpoint bindings reduce into + a current keychain view. + - Revoked keys/devices/nodes are excluded from active views. + - Tests cover add, rename, revoke, and endpoint rotation. -- dumbpipe-style streams -- TCP and Unix socket forwarding -- SSH proxy over Iroh -- SSH certificate and revocation distribution over Iroh -- OpenSSH KRL export/import support -- restricted geth admin shell +- `[ ]` Resource auth operation reducer. + Acceptance criteria: + - Resource create, authority set, grants, revocations, and groups reduce into + a current permission view. + - Capabilities are strings, including scoped forms such as + `kv.write_prefix:apps/foo/`. + - Tests cover grant, revoke, group membership, and denied access. + +- `[ ]` `auth explain` real decision path. + Acceptance criteria: + - `geth auth explain ` reports allowed/denied. + - Output includes the operation chain or missing grant that caused the result. + - JSON output is stable enough for tests and scripts. + +- `[ ]` Resource secrets and bearer invites. + Acceptance criteria: + - Bearer secrets grant only resource-scoped capabilities. + - Bearer principals cannot mutate trust graph state by default. + - Secret epoch rotation is represented in durable metadata. + - Tests verify bearer access does not imply node identity. + +- `[~]` SSH certificate and revocation lifecycle. + Acceptance criteria: + - `geth ssh cert request/requests/approve/import/list` persist local metadata. + - Approval emits an explicit `ssh-keygen -s ...` command for CA/YubiKey use. + - `geth ssh revocation add/list/export` persists and exports revocations. + - Future completion requires auth checks for request, approve, import, publish, + and read capabilities. + +## Phase 3: CAS, KV, And Pubsub + +Goal: turn local CAS and stubs into Iroh-backed replicated modules while keeping +authorization and durable-state boundaries clear. + +- `[ ]` Iroh-blobs CAS integration. + Acceptance criteria: + - Local CAS can provide and fetch blobs over Iroh. + - Provider tracking is recorded locally. + - Local add/get/hash/has/list behavior remains backward compatible. + +- `[ ]` CAS pin and cache policy. + Acceptance criteria: + - Pinned blobs are retained across cache cleanup. + - Unpinned cached blobs can be evicted by policy. + - Tests cover pin, unpin, list, and attempted eviction of pinned data. + +- `[ ]` Encrypted private blobs. + Acceptance criteria: + - Private blob payloads are encrypted before network distribution. + - Access is gated by resource secret epoch material. + - Docs explicitly avoid claiming forward secrecy or PCS. + +- `[ ]` Iroh-docs KV integration. + Acceptance criteria: + - `geth kv create/set/get` works against a named KV resource. + - Prefix-scoped capabilities can allow or deny writes. + - KV metadata is durable and replicated through Iroh Documents. + +- `[ ]` Iroh-gossip pubsub integration. + Acceptance criteria: + - `geth pubsub pub/sub` works for local test nodes. + - Pubsub messages are lossy notifications, not durable facts. + - Docs and tests keep durable state in CAS/KV/document/db instead. + +## Phase 4: Pipes, SSH Proxy, And SSH Distribution + +Goal: add authorized stream-oriented management workflows over Iroh. + +- `[ ]` Dumbpipe-style Iroh streams. + Acceptance criteria: + - `geth pipe listen/connect` can connect two local test nodes. + - Pipe access requires `pipe.listen` or `pipe.connect`. + - Streams close cleanly and propagate errors. + +- `[ ]` TCP forwarding. + Acceptance criteria: + - A local TCP listener can forward over an authorized Iroh pipe. + - Tests cover basic request/response forwarding. + - Forwarding is resource-scoped and can be disabled by auth. + +- `[ ]` Unix socket forwarding where supported. + Acceptance criteria: + - Unix socket forwarding is available on Unix platforms. + - Unsupported platforms return clear errors. + - Tests skip or use cfg guards where sockets are unavailable. + +- `[ ]` SSH proxy over Iroh. + Acceptance criteria: + - `geth ssh proxy ` opens an authorized Iroh stream. + - Remote daemon checks `ssh_proxy.connect` before connecting to local sshd or + admin shell. + - Knowing an EndpointID alone cannot reach sshd. + +- `[ ]` SSH certificate and revocation distribution. + Acceptance criteria: + - Issued cert records and revocation records replicate over Iroh. + - Consumers can list current certs/revocations from local state while offline. + - Conflicting or unsigned records are rejected or quarantined. + +- `[ ]` OpenSSH KRL import/export. + Acceptance criteria: + - Revocation records can produce an OpenSSH KRL file. + - Existing KRL files can be imported into revocation metadata where possible. + - Tests cover serial, key ID, public key, and certificate revocations. ## Phase 5: DB And Documents -- cr-sqlite sync -- Automerge sync -- resource-attached authorization -- secret-derived encryption +Goal: add durable synchronized data structures for SQLite/cr-sqlite and +Automerge documents. + +- `[ ]` DB resource registration. + Acceptance criteria: + - `geth db add ` records DB metadata. + - `geth db status ` reports local path, schema metadata, and sync state. + - Nonexistent paths and invalid names produce clear errors. + +- `[ ]` cr-sqlite change extraction. + Acceptance criteria: + - The module can read changes from `crsql_changes`. + - Schema hash/version metadata is included in sync batches. + - Tests use a temp SQLite DB and deterministic fixture changes. + +- `[ ]` DB sync over Iroh. + Acceptance criteria: + - Two local test nodes can exchange and apply DB changes. + - Schema mismatch is detected before applying changes. + - Optional CAS-backed snapshots or batches are documented if used. + +- `[ ]` Automerge document resource. + Acceptance criteria: + - `geth document create/status` works for local documents. + - Document state is stored durably. + - Tests cover create, update, save, and reload. + +- `[ ]` Automerge sync over Iroh. + Acceptance criteria: + - Two local test nodes can synchronize document changes. + - Resource authorization gates read/write sync. + - Conflicts converge according to Automerge semantics. ## Phase 6: File Sync And Advanced Local-First Auth -- CAS tree objects -- file roots -- conflict handling -- Keyhive-like convergent capabilities -- BeeKEM/CGKA-inspired group key evolution +Goal: build higher-level local-first collaboration on CAS trees, resource auth, +and future group key evolution. + +- `[ ]` CAS tree objects. + Acceptance criteria: + - Tree objects describe directories, files, executable bits, and blob hashes. + - Tree objects are content-addressed and stored in CAS. + - Tests cover deterministic tree hashing. + +- `[ ]` File roots. + Acceptance criteria: + - A file root maps a local path to a CAS tree resource. + - Scan detects create/update/delete/rename changes. + - Sync never silently overwrites local changes without a recorded decision. + +- `[ ]` Conflict handling. + Acceptance criteria: + - Conflicts are represented as durable metadata. + - CLI can list conflicts and choose a resolution. + - Tests cover concurrent edit, delete/edit, and rename conflicts. + +- `[ ]` Keyhive-like convergent capabilities. + Acceptance criteria: + - Capability state is represented as local-first replicated auth data. + - Convergent grant/revoke semantics are documented and tested. + - Migration from current auth ops is documented. + +- `[ ]` BeeKEM/CGKA-inspired group key evolution. + Acceptance criteria: + - Design doc states exact security properties and non-properties. + - Prototype is behind explicit experimental module boundaries. + - Current resource secret epoch model remains compatible or has a migration.