geth/docs/adr/0018-sshsigchain.md
Eric Wendland 538b52bdb6
Some checks failed
CI / fmt, clippy, docs (push) Failing after 5s
CI / test (ubuntu-latest) (push) Failing after 5s
CI / iroh integration smoke tests (push) Failing after 4s
CodeQL / Analyze Rust (push) Failing after 5s
Security / RustSec cargo-audit (push) Failing after 4s
CI / test (macos-latest) (push) Has been cancelled
CI / test (windows-latest) (push) Has been cancelled
simplify sigchain http distribution
2026-07-19 03:43:06 +02:00

3.5 KiB

ADR 0018: Sequence-free SSHSIGCHAIN authority protocol

Status

Accepted for the generic core. The protocol is still pre-deployment and has no legacy compatibility requirement.

Context

The first linked draft improved on a timestamp-sorted static bundle, but still made application profiles responsible for all key lifecycle semantics. It also included both a sequence counter and a parent hash, fixed one application profile for the whole chain, exposed every payload, and left rollback anchors outside the protocol model.

That design would let applications fragment device/key behavior, made multi-profile least privilege awkward, and offered no standard way to disclose only selected profile data or compare independently anchored heads.

Decision

SSHSIGCHAIN v1 is redesigned before deployment:

  • the trust tuple is (chain ID, SSHSIG namespace, root public key);
  • parent hashes alone define order; there is no sequence number;
  • link identity hashes the signed outer bytes, not the signature encoding;
  • every link carries a mandatory public Authority v1 transition;
  • authority owns devices, keys, proof-of-possession, causal revocation, permission ceilings, delegation, and anchor policy;
  • applications use profile-ID-scoped, salted payload commitments and cannot mutate authority;
  • disclosures are transport additions which do not change a link or its hash;
  • authorized keys can sign head claims;
  • distinct head attesters and backend-neutral receipts are evaluated by separate weighted/required thresholds and required backend classes;
  • cached ancestors are never replaced by older heads and incomparable verified histories fail as forks; and
  • a policy-change head is witnessed under the preceding policy before the new policy governs descendants;
  • canonical .sscb bundles deterministically store records, separately discloseable payloads, claims, and receipts without embedding root trust;
  • JSONL is noncanonical human-facing interchange; and
  • distribution backends return untrusted bundle bytes through one interface, with a single-file static HTTP profile at an exact operator-configured URL that requires no server application, well-known discovery, or TOFU.

The generic core defines backend interfaces and deterministic policy behavior, not Nostr, HTTP, blockchain, or transparency-log clients. Those adapters belong outside geth-keychain. Backends provide evidence and discovery, not consensus.

The generic protocol remains independent of geth transports. All geth node-to-node communication remains Iroh-only; SSH remains a trust and signature integration.

Consequences

Device and key behavior is interoperable rather than reinvented in each profile. A verifier can validate current authority while withholding application data, but must report affected profile state as incomplete. Proofs of possession prevent an administrator from silently enrolling a key it does not control. Device ceilings and delegable permission sets constrain later amplification.

The wire format is intentionally incompatible with every pre-deployment test draft. No migration parser or version alias is retained.

Rollback protection still depends on persistent local accepted heads and the operator's anchor policy. A Nostr relay, mutable HTTP URL, blockchain, or transparency service has only the guarantees its receipt verifier and deployment actually establish. Canonical bundle conversion and verification exist, while automatic HTTP/Iroh fetching, durable accepted-head storage, and cross-implementation vectors remain follow-up work.