# Compatibility Policy `geth` has not shipped a stable release yet. Until the first deployment tag, contracts may still change, but changes must be deliberate, documented in this file, and reflected in `docs/production-readiness-roadmap.md`. After the first deployment tag, compatibility is defined by the surfaces below. ## CLI Commands Commands documented in `README.md` are the automation-facing CLI surface. Existing command names, positional argument meanings, flag names, and default behavior should remain compatible within a major release. Backward-compatible CLI changes include: - Adding optional flags with defaults that preserve previous behavior. - Adding new subcommands. - Adding fields to human-readable output when `--json` is not requested. - Improving error messages while preserving the error kind and recovery path. Breaking CLI changes include: - Renaming or removing a documented command or flag. - Changing the meaning of an existing argument or default. - Changing exit success for the same observable result. - Requiring a daemon, network path, privileged service, or host mutation where a documented local command did not previously require one. Prototype commands must be called out in `README.md` or feature docs with an explicit migration expectation before scripts depend on them. ## JSON Output `--json` output is the preferred script contract. For stable commands, the top-level response variant name and existing field names keep their meaning within a major release. Execution failures in `--json` or `--jsonl` mode return a stable JSON error object on stdout with `type: "error"`, a machine-readable `code`, a human `message`, full `detail`, and an optional `hint` derived from operator recovery output. Common codes include `daemon_unavailable`, `unauthorized`, `peer_not_found`, `resource_not_found`, `invalid_input`, and `command_failed`. Backward-compatible JSON changes include: - Adding nullable or optional fields. - Adding enum variants for new commands or new explicit states. - Adding elements to arrays where ordering was not documented as stable. Breaking JSON changes include: - Removing or renaming fields. - Changing field type, unit, or identifier format. - Reusing a field for a different semantic meaning. - Changing a documented stable ordering. Automation should ignore unknown fields. Tests that assert JSON fixtures should cover the subset intended as stable rather than every incidental field. ## Local Control JSONL The local daemon control endpoint uses newline-delimited JSON request and response messages from `geth-control`. Its carrier is a Unix socket on Linux/macOS and a per-home Windows named pipe. This protocol is local-only and not a remote trust boundary, but local automation may still rely on it. Stable local-control variants follow the same compatibility rules as `--json` output. Unknown variants, malformed JSON, and messages without a trailing newline must fail without daemon state mutation. Local control must not become a remote transport. ## Peer Wire Protocols Node-to-node geth communication is Iroh-only. Peer protocols are grouped by explicit ALPNs: - `/geth/control/1` for authenticated peer-control requests. - `/geth/pipe/1` for authorized pipe byte streams. - `/geth/overlay/1` for authorized overlay packets. Within a major release, existing peer request and response variants should keep their field names, field meanings, nonce behavior, peer-card validation, and endpoint-binding validation. New variants must use explicit capabilities and resource IDs. Discovery data remains untrusted and never grants capabilities. Breaking peer-wire changes require a version bump, migration note, and tests showing old messages fail closed rather than being interpreted as a different operation. ## SQLite Metadata The metadata database is product state. Schema changes must be represented as ordered migrations before deployment. Fresh opens and repeated opens must be idempotent, and multi-table writes that represent one logical operation should commit atomically. Stable table columns may be added through migrations. Removing or repurposing a column requires a migration note and a recovery path. SQLite state is an implementation detail for scripts unless a table is explicitly documented as stable. ## Signed Operations Signed keychain, auth, SSH certificate, and SSH revocation payloads are durable compatibility surfaces. Signed payloads must use deterministic canonical encoding with explicit namespaces and versions. A verifier must never treat arbitrary JSON serialization as signed canonical data. Changing a signed payload shape, namespace, or verification rule requires a new versioned namespace or a documented migration that preserves validation of existing signed history.